Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Csse layout 550 error #357

Merged
merged 11 commits into from
Nov 25, 2024
Merged
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
6 changes: 6 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ New Features

Enhancements
++++++++++++
- (:pr:`357`, :issue:`536`) ``v2.AtomicResult``, ``v2.OptimizationResult``, and ``v2.TorsionDriveResult`` have the ``success`` field enforced to ``True``. Previously it could be set T/F. Now validation errors if not T. Likewise ``v2.FailedOperation.success`` is enforced to ``False``.
- (:pr:`357`, :issue:`536`) ``v2.AtomicResult``, ``v2.OptimizationResult``, and ``v2.TorsionDriveResult`` have the ``error`` field removed. This isn't used now that ``success=True`` and failure should be routed to ``FailedOperation``.
- (:pr:`357`) ``v1.Molecule`` had its schema_version changed to a Literal[2] (remember Mol is one-ahead of general numbering scheme) so new instances will be 2 even if another value is passed in. Ditto ``v2.BasisSet.schema_version=2``. Ditto ``v1.BasisSet.schema_version=1`` Ditto ``v1.QCInputSpecification.schema_version=1`` and ``v1.OptimizationSpecification.schema_version=1``.
- (:pr:`357`) ``v2.AtomicResultProperties``, ``v2.QCInputSpecification``, ``v2.OptimizationSpecification`` lost its schema_version until we see if its really needed.
- (:pr:`357`) ``v2.OptimizationSpecification`` gained extras field
- (:pr:`357`) ``v1.FailedOperation.extras`` and ``v2.FailedOperation.extras`` default changed from None to {}
* Fix a lot of warnings originating in this project.
* `Molecule.extras` now defaults to `{}` rather than None in both v1 and v2. Input None converts to {} upon instantiation.
* ``v2.FailedOperation`` field `id` is becoming `Optional[str]` instead of plain `str` so that the default validates.
Expand Down
2 changes: 1 addition & 1 deletion qcelemental/models/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
DeprecationWarning,
)

# Array = qcelemental.models.v1.Array
Array = qcelemental.models.v1.Array
# ArrayMeta = qcelemental.models.v1.ArrayMeta
# TypedArray = qcelemental.models.v1.TypedArray
6 changes: 4 additions & 2 deletions qcelemental/models/v1/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from . import types
from . import types # ever used?
from .align import AlignmentMill
from .basemodels import AutodocBaseSettings # remove when QCFractal merges `next`
from .basemodels import ProtoModel
Expand All @@ -8,6 +8,7 @@
from .procedures import Optimization # scheduled for removal
from .procedures import (
OptimizationInput,
OptimizationProtocols,
OptimizationResult,
OptimizationSpecification,
QCInputSpecification,
Expand All @@ -18,7 +19,8 @@
from .results import Result # scheduled for removal
from .results import ResultInput # scheduled for removal
from .results import ResultProperties # scheduled for removal
from .results import AtomicInput, AtomicResult, AtomicResultProperties, AtomicResultProtocols
from .results import AtomicInput, AtomicResult, AtomicResultProperties, AtomicResultProtocols, WavefunctionProperties
from .types import Array


def qcschema_models():
Expand Down
12 changes: 11 additions & 1 deletion qcelemental/models/v1/basis.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
from enum import Enum
from typing import Dict, List, Optional

try:
from typing import Literal
except ImportError:
# remove when minimum py38
from typing_extensions import Literal

from pydantic.v1 import ConstrainedInt, Field, constr, validator

from ...exceptions import ValidationError
Expand Down Expand Up @@ -155,7 +161,7 @@ class BasisSet(ProtoModel):
"qcschema_basis",
description=(f"The QCSchema specification to which this model conforms. Explicitly fixed as qcschema_basis."),
)
schema_version: int = Field( # type: ignore
schema_version: Literal[1] = Field( # type: ignore
1,
description="The version number of :attr:`~qcelemental.models.BasisSet.schema_name` to which this model conforms.",
)
Expand All @@ -175,6 +181,10 @@ class Config(ProtoModel.Config):
def schema_extra(schema, model):
schema["$schema"] = qcschema_draft

@validator("schema_version", pre=True)
def _version_stamp(cls, v):
return 1

@validator("atom_map")
def _check_atom_map(cls, v, values):
sv = set(v)
Expand Down
3 changes: 2 additions & 1 deletion qcelemental/models/v1/common_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ class FailedOperation(ProtoModel):
":class:`ComputeError` for more details.",
)
extras: Optional[Dict[str, Any]] = Field( # type: ignore
None,
{},
description="Additional information to bundle with the failed operation. Details which pertain specifically "
"to a thrown error should be contained in the `error` field. See :class:`ComputeError` for details.",
)
Expand All @@ -139,6 +139,7 @@ def convert_v(

dself = self.dict()
if version == 2:
# TODO if FailedOp gets a schema_version, add a validator
self_vN = qcel.models.v2.FailedOperation(**dself)

return self_vN
Expand Down
14 changes: 13 additions & 1 deletion qcelemental/models/v1/molecule.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
from pathlib import Path
from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Tuple, Union, cast

try:
from typing import Literal
except ImportError:
# remove when minimum py38
from typing_extensions import Literal

import numpy as np
from pydantic.v1 import ConstrainedFloat, ConstrainedInt, Field, constr, validator

Expand Down Expand Up @@ -119,7 +125,7 @@ class Molecule(ProtoModel):
f"The QCSchema specification to which this model conforms. Explicitly fixed as {qcschema_molecule_default}."
),
)
schema_version: int = Field( # type: ignore
schema_version: Literal[2] = Field( # type: ignore
2,
description="The version number of :attr:`~qcelemental.models.Molecule.schema_name` to which this model conforms.",
)
Expand Down Expand Up @@ -370,6 +376,12 @@ def __init__(self, orient: bool = False, validate: Optional[bool] = None, **kwar
elif validate or geometry_prep:
values["geometry"] = float_prep(values["geometry"], geometry_noise)

@validator("schema_version", pre=True)
def _version_stamp(cls, v):
# seemingly unneeded, this lets conver_v re-label the model w/o discarding model and
# submodel version fields first.
return 2

@validator("geometry")
def _must_be_3n(cls, v, values, **kwargs):
n = len(values["symbols"])
Expand Down
34 changes: 32 additions & 2 deletions qcelemental/models/v1/procedures.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class QCInputSpecification(ProtoModel):
"""

schema_name: constr(strip_whitespace=True, regex=qcschema_input_default) = qcschema_input_default # type: ignore
schema_version: int = 1 # TODO
schema_version: Literal[1] = 1

driver: DriverEnum = Field(DriverEnum.gradient, description=str(DriverEnum.__doc__))
model: Model = Field(..., description=str(Model.__doc__))
Expand All @@ -71,6 +71,10 @@ class QCInputSpecification(ProtoModel):
description="Additional information to bundle with the computation. Use for schema development and scratch space.",
)

@validator("schema_version", pre=True)
def _version_stamp(cls, v):
return 1


class OptimizationInput(ProtoModel):
id: Optional[str] = None
Expand Down Expand Up @@ -110,6 +114,7 @@ def convert_v(

dself = self.dict()
if version == 2:
dself["input_specification"].pop("schema_version", None)
self_vN = qcel.models.v2.OptimizationInput(**dself)

return self_vN
Expand Down Expand Up @@ -171,8 +176,16 @@ def convert_v(
if check_convertible_version(version, error="OptimizationResult") == "self":
return self

trajectory_class = self.trajectory[0].__class__
dself = self.dict()
if version == 2:
# remove harmless empty error field that v2 won't accept. if populated, pydantic will catch it.
if dself.pop("error", None):
pass

dself["trajectory"] = [trajectory_class(**atres).convert_v(version) for atres in dself["trajectory"]]
dself["input_specification"].pop("schema_version", None)

self_vN = qcel.models.v2.OptimizationResult(**dself)

return self_vN
Expand All @@ -189,12 +202,16 @@ class OptimizationSpecification(ProtoModel):
"""

schema_name: constr(strip_whitespace=True, regex="qcschema_optimization_specification") = "qcschema_optimization_specification" # type: ignore
schema_version: int = 1 # TODO
schema_version: Literal[1] = 1

procedure: str = Field(..., description="Optimization procedure to run the optimization with.")
keywords: Dict[str, Any] = Field({}, description="The optimization specific keywords to be used.")
protocols: OptimizationProtocols = Field(OptimizationProtocols(), description=str(OptimizationProtocols.__doc__))

@validator("schema_version", pre=True)
def _version_stamp(cls, v):
return 1

@validator("procedure")
def _check_procedure(cls, v):
return v.lower()
Expand Down Expand Up @@ -282,6 +299,9 @@ def convert_v(

dself = self.dict()
if version == 2:
dself["input_specification"].pop("schema_version", None)
dself["optimization_spec"].pop("schema_version", None)

self_vN = qcel.models.v2.TorsionDriveInput(**dself)

return self_vN
Expand Down Expand Up @@ -332,8 +352,18 @@ def convert_v(
if check_convertible_version(version, error="TorsionDriveResult") == "self":
return self

opthist_class = next(iter(self.optimization_history.values()))[0].__class__
dself = self.dict()
if version == 2:
# remove harmless empty error field that v2 won't accept. if populated, pydantic will catch it.
if dself.pop("error", None):

Choose a reason for hiding this comment

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

Consider removing the if statement (since it doesn't do anything) and change to dself.pop("error", None).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

fixed here and two other spots in next PR

pass

dself["optimization_history"] = {
(k, [opthist_class(**res).convert_v(version) for res in lst])
for k, lst in dself["optimization_history"].items()
}

self_vN = qcel.models.v2.TorsionDriveResult(**dself)

return self_vN
Expand Down
4 changes: 4 additions & 0 deletions qcelemental/models/v1/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,10 @@ def convert_v(

dself = self.dict()
if version == 2:
# remove harmless empty error field that v2 won't accept. if populated, pydantic will catch it.
if dself.pop("error", None):
pass

self_vN = qcel.models.v2.AtomicResult(**dself)

return self_vN
Expand Down
13 changes: 11 additions & 2 deletions qcelemental/models/v2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,17 @@
from .basis import BasisSet
from .common_models import ComputeError, DriverEnum, FailedOperation, Model, Provenance
from .molecule import Molecule
from .procedures import OptimizationInput, OptimizationResult, TorsionDriveInput, TorsionDriveResult
from .results import AtomicInput, AtomicResult, AtomicResultProperties, AtomicResultProtocols
from .procedures import (
OptimizationInput,
OptimizationProtocols,
OptimizationResult,
OptimizationSpecification,
QCInputSpecification,
TDKeywords,
TorsionDriveInput,
TorsionDriveResult,
)
from .results import AtomicInput, AtomicResult, AtomicResultProperties, AtomicResultProtocols, WavefunctionProperties


def qcschema_models():
Expand Down
12 changes: 11 additions & 1 deletion qcelemental/models/v2/basis.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
from enum import Enum
from typing import Dict, List, Optional

try:
from typing import Literal
except ImportError:
# remove when minimum py38
from typing_extensions import Literal

from pydantic import Field, constr, field_validator
from typing_extensions import Annotated

Expand Down Expand Up @@ -171,7 +177,7 @@ class BasisSet(ProtoModel):
"qcschema_basis",
description=f"The QCSchema specification to which this model conforms. Explicitly fixed as qcschema_basis.",
)
schema_version: int = Field( # type: ignore
schema_version: Literal[2] = Field( # type: ignore
2,
description="The version number of :attr:`~qcelemental.models.BasisSet.schema_name` "
"to which this model conforms.",
Expand Down Expand Up @@ -245,3 +251,7 @@ def _calculate_nbf(cls, atom_map, center_data) -> int:
ret += center_count[center]

return ret

@field_validator("schema_version", mode="before")
def _version_stamp(cls, v):
return 2
12 changes: 9 additions & 3 deletions qcelemental/models/v2/common_models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
from enum import Enum
from typing import TYPE_CHECKING, Any, Dict, Optional, Sequence, Tuple, Union

try:
from typing import Literal
except ImportError:
# remove when minimum py38
from typing_extensions import Literal

import numpy as np
from pydantic import Field
from pydantic import Field, field_validator

from .basemodels import ProtoModel, qcschema_draft
from .basis import BasisSet
Expand Down Expand Up @@ -106,7 +112,7 @@ class FailedOperation(ProtoModel):
description="The input data which was passed in that generated this failure. This should be the complete "
"input which when attempted to be run, caused the operation to fail.",
)
success: bool = Field( # type: ignore
success: Literal[False] = Field( # type: ignore
False,
description="A boolean indicator that the operation failed consistent with the model of successful operations. "
"Should always be False. Allows programmatic assessment of all operations regardless of if they failed or "
Expand All @@ -118,7 +124,7 @@ class FailedOperation(ProtoModel):
":class:`ComputeError` for more details.",
)
extras: Optional[Dict[str, Any]] = Field( # type: ignore
None,
{},
description="Additional information to bundle with the failed operation. Details which pertain specifically "
"to a thrown error should be contained in the `error` field. See :class:`ComputeError` for details.",
)
Expand Down
8 changes: 7 additions & 1 deletion qcelemental/models/v2/molecule.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class Molecule(ProtoModel):
),
)
schema_version: int = Field( # type: ignore
2,
2, # TODO Turn to Literal[3] = Field(3)
description="The version number of :attr:`~qcelemental.models.Molecule.schema_name` to which this model conforms.",
)
validated: bool = Field( # type: ignore
Expand Down Expand Up @@ -402,6 +402,12 @@ def __init__(self, orient: bool = False, validate: Optional[bool] = None, **kwar
elif validate or geometry_prep:
values["geometry"] = float_prep(values["geometry"], geometry_noise)

@field_validator("schema_version", mode="before")
def _version_stamp(cls, v):
# seemingly unneeded, this lets conver_v re-label the model w/o discarding model and
# submodel version fields first.
return 2 # TODO 3

@field_validator("geometry")
@classmethod
def _must_be_3n(cls, v, info):
Expand Down
Loading
Loading