Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 2 additions & 10 deletions qcelemental/models/v2/atomic.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from ...util import provenance_stamp
from .basemodels import ExtendedConfigDict, ProtoModel, check_convertible_version, qcschema_draft
from .basis_set import BasisSet
from .common_models import DriverEnum, Model, Provenance
from .common_models import DriverEnum, Model, Provenance, NativeFilesProtocolEnum
from .molecule import Molecule
from .types import Array

Expand Down Expand Up @@ -640,14 +640,6 @@ def allows(self, policy: str):
return self.policies.get(policy, self.default_policy)


class NativeFilesProtocolEnum(str, Enum):
r"""CMS program files to keep from a computation."""

all = "all"
input = "input"
none = "none"


class AtomicProtocols(ProtoModel):
r"""Protocols regarding the manipulation of computational result data."""

Expand Down Expand Up @@ -822,7 +814,7 @@ class AtomicResult(ProtoModel):
description="The primary logging output of the program, whether natively standard output or a file. Presence vs. absence (or null-ness?) configurable by protocol.",
)
stderr: Optional[str] = Field(None, description="The standard error of the program execution.")
native_files: Dict[str, Any] = Field({}, description="DSL files.")
native_files: Dict[str, Any] = Field({}, description="Other program-specific files returned from the computation.")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I remember why native_files wasn't fully implemented (result field but not protocol) now: the target programs (geometric, optking, torsiondrive, qcmanybody) don't really have a history of random text or binary file in/outputs. Anything extra they did comm. could probably be absorbed into schema another way.


success: Literal[True] = Field(
True, description="The success of program execution. If False, other fields may be blank."
Expand Down
8 changes: 8 additions & 0 deletions qcelemental/models/v2/common_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,11 @@ def derivative_int(self):
return 0
else:
return egh.index(self)


class NativeFilesProtocolEnum(str, Enum):
r"""Program-specific to keep from a computation."""
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
r"""Program-specific to keep from a computation."""
r"""Program-specific to keep from a computation.
Less likely to be used when program is API- or schema-based (e.g., geomeTRIC)
"""


all = "all"
input = "input"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And since geometric/TD/QCMB are API or schema input, they have no "input" file generated

none = "none"
39 changes: 35 additions & 4 deletions qcelemental/models/v2/optimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from ...util import provenance_stamp
from .atomic import AtomicProperties, AtomicResult, AtomicSpecification
from .basemodels import ExtendedConfigDict, ProtoModel, check_convertible_version
from .common_models import Provenance
from .common_models import Provenance, NativeFilesProtocolEnum
from .molecule import Molecule
from .types import Array

Expand All @@ -38,20 +38,24 @@ class TrajectoryProtocolEnum(str, Enum):

class OptimizationProtocols(ProtoModel):
"""
Protocols regarding the manipulation of a Optimization output data.
Protocols regarding the manipulation of Optimization output data.
"""

schema_name: Literal["qcschema_optimization_protocols"] = "qcschema_optimization_protocols"
trajectory_results: TrajectoryProtocolEnum = Field(
TrajectoryProtocolEnum.none, description=str(TrajectoryProtocolEnum.__doc__)
)
native_files: NativeFilesProtocolEnum = Field(
NativeFilesProtocolEnum.none,
description="Policies for keeping processed files from the computation",
)

model_config = ExtendedConfigDict(force_skip_defaults=True)

def convert_v(
self, target_version: int, /
) -> Union["qcelemental.models.v1.OptimizationProtocols", "qcelemental.models.v2.OptimizationProtocols"]:
"""Convert to instance of particular QCSchema version."""
"""Convert to an instance of a particular QCSchema version."""
import qcelemental as qcel

if check_convertible_version(target_version, error="OptimizationProtocols") == "self":
Expand All @@ -61,6 +65,7 @@ def convert_v(
if target_version == 1:
# serialization is compact, so use model to assure value
dself.pop("trajectory_results", None)
dself.pop("native_files", None)
dself["trajectory"] = self.trajectory_results.value

self_vN = qcel.models.v1.OptimizationProtocols(**dself)
Expand Down Expand Up @@ -277,7 +282,7 @@ class OptimizationResult(ProtoModel):
provenance: Provenance = Field(..., description=str(Provenance.__doc__))

# native_files placeholder for when any opt programs supply extra files or need an input file. no protocol at present
native_files: Dict[str, Any] = Field({}, description="DSL files.")
native_files: Dict[str, Any] = Field({}, description="Other program-specific files returned from the computation.")

properties: OptimizationProperties = Field(..., description=str(OptimizationProperties.__doc__))

Expand Down Expand Up @@ -309,6 +314,32 @@ def _trajectory_protocol(cls, v, info):

return v

@field_validator("native_files")
@classmethod
def _native_file_protocol(cls, value, info):
# Do not propagate validation errors
if "input_data" not in info.data:
raise ValueError("Input_data was not properly formed.")

ancp = info.data["input_data"].specification.protocols.native_files
if ancp == "all":
return value
elif ancp == "none":
return {}
elif ancp == "input":
return_keep = ["input"]
if value is None:
files = {}
else:
files = value.copy()
else:
raise ValueError(f"Protocol `native_files:{ancp}` is not understood")

ret = {}
for rk in return_keep:
ret[rk] = files.get(rk, None)
return ret

def convert_v(
self, target_version: int, /
) -> Union["qcelemental.models.v1.OptimizationResult", "qcelemental.models.v2.OptimizationResult"]:
Expand Down
42 changes: 35 additions & 7 deletions qcelemental/models/v2/torsion_drive.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,15 @@

from pydantic import Field, conlist, field_validator

from ...util import provenance_stamp
from .basemodels import ExtendedConfigDict, ProtoModel, check_convertible_version
from .common_models import DriverEnum, Provenance
from .common_models import DriverEnum, Provenance, NativeFilesProtocolEnum
from .molecule import Molecule
from .optimization import OptimizationProperties, OptimizationResult, OptimizationSpecification
from .types import Array
from ...util import provenance_stamp

if TYPE_CHECKING:
import qcelemental

from .common_models import ReprArgs


# ==== Protocols ==============================================================

Expand All @@ -39,6 +36,11 @@ class TorsionDriveProtocols(ProtoModel):
ScanResultsProtocolEnum.none, description=str(ScanResultsProtocolEnum.__doc__)
)

native_files: NativeFilesProtocolEnum = Field(
NativeFilesProtocolEnum.none,
description="Policies for keeping processed files from the computation",
)

model_config = ExtendedConfigDict(force_skip_defaults=True)


Expand Down Expand Up @@ -229,8 +231,8 @@ class TorsionDriveResult(ProtoModel):
stdout: Optional[str] = Field(None, description="The standard output of the program.")
stderr: Optional[str] = Field(None, description="The standard error of the program.")

# native_files placeholder for when any td programs supply extra files or need an input file. no protocol at present
native_files: Dict[str, Any] = Field({}, description="DSL files.")
# native_files placeholder for when any opt programs supply extra files or need an input file. no protocol at present
native_files: Dict[str, Any] = Field({}, description="Other program-specific files returned from the computation.")

properties: TorsionDriveProperties = Field(..., description=str(TorsionDriveProperties.__doc__))

Expand Down Expand Up @@ -269,6 +271,32 @@ def _scan_protocol(cls, v, info):

return v

@field_validator("native_files")
@classmethod
def _native_file_protocol(cls, value, info):
# Do not propagate validation errors
if "input_data" not in info.data:
raise ValueError("Input_data was not properly formed.")

ancp = info.data["input_data"].specification.protocols.native_files
if ancp == "all":
return value
elif ancp == "none":
return {}
elif ancp == "input":
return_keep = ["input"]
if value is None:
files = {}
else:
files = value.copy()
else:
raise ValueError(f"Protocol `native_files:{ancp}` is not understood")

ret = {}
for rk in return_keep:
ret[rk] = files.get(rk, None)
return ret

def convert_v(
self, target_version: int, /
) -> Union["qcelemental.models.v1.TorsionDriveResult", "qcelemental.models.v2.TorsionDriveResult"]:
Expand Down
Loading