forked from EmpaEconversion/aiida-aurora
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3790f4c
commit 624ebea
Showing
5 changed files
with
100 additions
and
103 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,107 +1,101 @@ | ||
from datetime import datetime | ||
from enum import Flag | ||
from typing import Literal, Optional | ||
from typing import Literal, Optional, Set | ||
|
||
from pydantic import BaseModel, NonNegativeFloat, PositiveFloat, root_validator | ||
from pydantic import BaseModel, NonNegativeFloat, PositiveInt | ||
|
||
from .utils import extract_schema_types | ||
|
||
|
||
class BatteryComposition(BaseModel): # TypedDict? | ||
description: Optional[str] = None | ||
cathode: Optional[str] = None | ||
anode: Optional[str] = None | ||
electrolyte: Optional[str] = None | ||
|
||
class Config: | ||
# exclude fields from export, to avoid validation errors when reloaded | ||
fields = { | ||
'cathode': { | ||
'exclude': True | ||
}, | ||
'anode': { | ||
'exclude': True | ||
}, | ||
'electrolyte': { | ||
'exclude': True | ||
}, | ||
} | ||
|
||
@root_validator | ||
def validate_composition(cls, values): | ||
""" | ||
Check that components are not specified if 'description' is specified | ||
then build components from a 'description' string, or vice versa. | ||
# TODO: what to do if 'description' is not in the C|E|A format? | ||
""" | ||
if values['description']: | ||
if any(values[key] for key in ('cathode', 'anode', 'electrolyte')): | ||
raise ValueError("You cannot specify a 'description' and any component at the same time.") | ||
values['description'] = values['description'].strip() | ||
components = list(map(str.strip, values['description'].split('|'))) | ||
if len(components) == 3: | ||
values['cathode'], values['electrolyte'], values['anode'] = components | ||
else: | ||
values['cathode'], values['electrolyte'], values['anode'] = (None, None, None) | ||
# raise ValueError( | ||
# "Composition 'description' does not have 3 components (i.e. {cathode}|{electrolyte}|{anode}).") | ||
elif any(values[key] for key in ('cathode', 'anode', 'electrolyte')): | ||
for key in ('cathode', 'anode', 'electrolyte'): | ||
values[key] = values[key].strip() | ||
values['description'] = f"{values['cathode']}|{values['electrolyte']}|{values['anode']}" | ||
else: | ||
raise ValueError("You must specify either a string 'description' or the components.") | ||
return values | ||
|
||
|
||
class BatteryCapacity(BaseModel): # TypedDict? | ||
nominal: PositiveFloat | ||
class Component(BaseModel): | ||
description: Optional[str] | ||
|
||
|
||
class Diameter(BaseModel): | ||
nominal: NonNegativeFloat | ||
actual: Optional[NonNegativeFloat] | ||
units: Literal["mAh", "Ah"] | ||
units: Literal["mm"] = "mm" | ||
|
||
|
||
class BatteryMetadata(BaseModel): | ||
name: str | ||
creation_datetime: datetime | ||
creation_process: str | ||
class Capacity(BaseModel): | ||
nominal: NonNegativeFloat | ||
actual: Optional[NonNegativeFloat] | ||
units: Literal["mAh", "Ah"] = "mAh" | ||
|
||
|
||
class BatterySpecs(BaseModel): | ||
""" | ||
Battery specification schema. | ||
""" | ||
manufacturer: str | ||
composition: BatteryComposition | ||
form_factor: str | ||
capacity: BatteryCapacity | ||
class Electrolyte(Component): | ||
formula: str | ||
position: PositiveInt | ||
amount: NonNegativeFloat | ||
|
||
# manufacturer, form_factor: | ||
# should we use a Literal or a validator to check that they are one of the available ones? | ||
|
||
# add pre-validator to specify capacity as str (e.g. '4.8 mAh')? | ||
class ElectrodeWeight(BaseModel): | ||
total: NonNegativeFloat | ||
collector: NonNegativeFloat | ||
net: Optional[NonNegativeFloat] | ||
units: Literal["mg", "g"] = "mg" | ||
|
||
|
||
class BatterySample(BatterySpecs): | ||
""" | ||
Battery sample schema. | ||
""" | ||
battery_id: int | ||
metadata: BatteryMetadata | ||
class Electrode(Component): | ||
formula: str | ||
position: PositiveInt | ||
diameter: Diameter | ||
weight: ElectrodeWeight | ||
capacity: Capacity | ||
|
||
|
||
class Separator(Component): | ||
name: str # ? use `Literal` of available? | ||
diameter: Diameter | ||
|
||
|
||
class Spacer(Component): | ||
value: NonNegativeFloat | ||
units: Literal["mm"] = "mm" | ||
|
||
|
||
class Composition(BaseModel): | ||
description: Optional[str] | ||
anode: Electrode | ||
cathode: Electrode | ||
electrolyte: Electrolyte | ||
separator: Separator | ||
spacer: Spacer | ||
|
||
|
||
class BatterySpecs(BaseModel): | ||
case: str # ? use `Literal` of available? | ||
manufacturer: str # ? use `Literal` of available? | ||
composition: Composition | ||
capacity: Capacity | ||
np_ratio: Optional[str] | ||
|
||
|
||
class BatteryMetadata(BaseModel): | ||
name: str | ||
groups: Set[str] = {"all-samples"} | ||
batch: str = "" | ||
subbatch: str = "0" | ||
creation_datetime: datetime | ||
creation_process: str | ||
|
||
|
||
class ChargeState(Flag): | ||
"""Defines the charge state of a battery.""" | ||
CHARGED = True | ||
DISCHARGED = False | ||
|
||
|
||
class BatteryState(BatterySample): | ||
""" | ||
Battery state schema. | ||
""" | ||
state_id: int | ||
class BatteryState(BaseModel): | ||
used = False | ||
charged: ChargeState = ChargeState.CHARGED | ||
|
||
|
||
class BatterySample(BaseModel): | ||
id: int | ||
# state: BatteryState # TODO move to metadata? | ||
specs: BatterySpecs | ||
metadata: BatteryMetadata | ||
|
||
|
||
BatterySpecsJsonTypes = extract_schema_types(BatterySpecs) | ||
BatterySampleJsonTypes = extract_schema_types(BatterySample) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters