Skip to content

Commit 694de56

Browse files
committed
Merge branch 'clean_structure' of github.com:pyscal/atomRDF into clean_structure
2 parents 7c617cb + 4d97508 commit 694de56

File tree

17 files changed

+1248
-243
lines changed

17 files changed

+1248
-243
lines changed

atomrdf/datamodels/activity.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
from typing import List, Optional, Union
2+
from atomrdf import graph
3+
from pydantic import BaseModel, Field, field_validator
4+
import uuid
5+
from atomrdf.datamodels.basemodels import TemplateMixin, DataProperty
6+
from atomrdf.datamodels.structure import AtomicScaleSample
7+
from rdflib import Graph, Namespace, XSD, RDF, RDFS, BNode, URIRef
8+
from atomrdf.utils import get_sample_object
9+
from ase import Atoms
10+
from atomrdf.build.bulk import _generate_atomic_sample_data
11+
from atomrdf.namespace import (
12+
CMSO,
13+
LDO,
14+
PLDO,
15+
PODO,
16+
CDCO,
17+
PROV,
18+
Literal,
19+
ASMO,
20+
)
21+
22+
23+
class Activity(BaseModel, TemplateMixin):
24+
pid: Optional[str] = Field(default=None, description="PID of the activity")
25+
26+
initial_sample: Optional[Union[str, AtomicScaleSample]] = Field(
27+
default=None, description="ID of the initial sample in the graph"
28+
)
29+
final_sample: Optional[Union[str, AtomicScaleSample]] = Field(
30+
default=None, description="ID of the final sample in the graph"
31+
)
32+
33+
@field_validator("initial_sample", mode="before")
34+
@classmethod
35+
def _validate_initial_sample(cls, sample):
36+
if isinstance(sample, Atoms):
37+
if "id" in sample.info:
38+
return sample.info["id"]
39+
else:
40+
#we have serialise the structure and then return the id
41+
data = _generate_atomic_sample_data(sample)
42+
sample_obj = AtomicScaleSample(**data)
43+
return sample_obj
44+
elif isinstance(sample, AtomicScaleSample):
45+
return sample
46+
elif isinstance(sample, str):
47+
return sample
48+
49+
@field_validator("final_sample", mode="before")
50+
@classmethod
51+
def _validate_final_sample(cls, sample):
52+
if isinstance(sample, Atoms):
53+
if "id" in sample.info:
54+
return sample.info["id"]
55+
else:
56+
#we have serialise the structure and then return the id
57+
data = _generate_atomic_sample_data(sample)
58+
sample_obj = AtomicScaleSample(**data)
59+
return sample_obj
60+
elif isinstance(sample, AtomicScaleSample):
61+
return sample
62+
elif isinstance(sample, str):
63+
return sample

atomrdf/datamodels/basemodels.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,17 +78,6 @@ class DataProperty(BaseModel, Generic[T], TemplateMixin):
7878
)
7979

8080

81-
class Activity(BaseModel, TemplateMixin):
82-
pid: Optional[str] = Field(default=None, description="PID of the activity")
83-
84-
initial_sample: Optional[str] = Field(
85-
default=None, description="ID of the initial sample in the graph"
86-
)
87-
final_sample: Optional[str] = Field(
88-
default=None, description="ID of the final sample in the graph"
89-
)
90-
91-
9281
class RDFMixin:
9382
def to_graph(self, graph, sample):
9483
raise NotImplementedError

atomrdf/datamodels/structure.py

Lines changed: 119 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
from pydantic import Field
1313
from atomrdf.datamodels.basemodels import (
1414
TemplateMixin,
15-
DataProperty,
1615
RDFMixin,
1716
BaseModel,
1817
)
18+
from atomrdf.datamodels.workflow.property import Property as DataProperty
1919
from rdflib import Graph, Namespace, XSD, RDF, RDFS, BNode, URIRef
2020
from atomrdf.namespace import (
2121
CMSO,
@@ -52,66 +52,70 @@ def to_graph(self, graph, sample_id, crystal_structure):
5252
unit_cell = graph.create_node(f"{sample_id}_UnitCell", CMSO.UnitCell)
5353
graph.add((crystal_structure, CMSO.hasUnitCell, unit_cell))
5454

55-
bv = graph.create_node(
56-
f"{sample_id}_BravaisLattice", URIRef(self.bravais_lattice.value)
57-
)
58-
graph.add(
59-
(
60-
unit_cell,
61-
CMSO.hasBravaisLattice,
62-
bv,
55+
if self.bravais_lattice.value is not None:
56+
bv = graph.create_node(
57+
f"{sample_id}_BravaisLattice", URIRef(self.bravais_lattice.value)
6358
)
64-
)
65-
lattice_parameter = graph.create_node(
66-
f"{sample_id}_LatticeParameter", CMSO.LatticeParameter
67-
)
68-
graph.add(
69-
(
70-
unit_cell,
71-
CMSO.hasLength_x,
72-
Literal(self.lattice_parameter.value[0], datatype=XSD.float),
59+
graph.add(
60+
(
61+
unit_cell,
62+
CMSO.hasBravaisLattice,
63+
bv,
64+
)
7365
)
74-
)
75-
graph.add(
76-
(
77-
unit_cell,
78-
CMSO.hasLength_y,
79-
Literal(self.lattice_parameter.value[1], datatype=XSD.float),
66+
67+
if self.lattice_parameter.value is not None:
68+
lattice_parameter = graph.create_node(
69+
f"{sample_id}_LatticeParameter", CMSO.LatticeParameter
8070
)
81-
)
82-
graph.add(
83-
(
84-
unit_cell,
85-
CMSO.hasLength_z,
86-
Literal(self.lattice_parameter.value[2], datatype=XSD.float),
71+
graph.add(
72+
(
73+
unit_cell,
74+
CMSO.hasLength_x,
75+
Literal(self.lattice_parameter.value[0], datatype=XSD.float),
76+
)
77+
)
78+
graph.add(
79+
(
80+
unit_cell,
81+
CMSO.hasLength_y,
82+
Literal(self.lattice_parameter.value[1], datatype=XSD.float),
83+
)
84+
)
85+
graph.add(
86+
(
87+
unit_cell,
88+
CMSO.hasLength_z,
89+
Literal(self.lattice_parameter.value[2], datatype=XSD.float),
90+
)
8791
)
88-
)
8992

90-
lattice_angle = graph.create_node(
91-
f"{sample_id}_LatticeAngle", CMSO.LatticeAngle
92-
)
93-
graph.add((unit_cell, CMSO.hasAngle, lattice_angle))
94-
graph.add(
95-
(
96-
lattice_angle,
97-
CMSO.hasAngle_alpha,
98-
Literal(self.angle.value[0], datatype=XSD.float),
93+
if self.angle.value is not None:
94+
lattice_angle = graph.create_node(
95+
f"{sample_id}_LatticeAngle", CMSO.LatticeAngle
9996
)
100-
)
101-
graph.add(
102-
(
103-
lattice_angle,
104-
CMSO.hasAngle_beta,
105-
Literal(self.angle.value[1], datatype=XSD.float),
97+
graph.add((unit_cell, CMSO.hasAngle, lattice_angle))
98+
graph.add(
99+
(
100+
lattice_angle,
101+
CMSO.hasAngle_alpha,
102+
Literal(self.angle.value[0], datatype=XSD.float),
103+
)
106104
)
107-
)
108-
graph.add(
109-
(
110-
lattice_angle,
111-
CMSO.hasAngle_gamma,
112-
Literal(self.angle.value[2], datatype=XSD.float),
105+
graph.add(
106+
(
107+
lattice_angle,
108+
CMSO.hasAngle_beta,
109+
Literal(self.angle.value[1], datatype=XSD.float),
110+
)
111+
)
112+
graph.add(
113+
(
114+
lattice_angle,
115+
CMSO.hasAngle_gamma,
116+
Literal(self.angle.value[2], datatype=XSD.float),
117+
)
113118
)
114-
)
115119

116120
@classmethod
117121
def from_graph(cls, graph, crystal_structure):
@@ -125,17 +129,17 @@ def from_graph(cls, graph, crystal_structure):
125129
alpha = graph.value(angle, CMSO.hasAngle_alpha)
126130
beta = graph.value(angle, CMSO.hasAngle_beta)
127131
gamma = graph.value(angle, CMSO.hasAngle_gamma)
128-
datadict = {
129-
"bravais_lattice": {
130-
"value": str(bv),
131-
},
132-
"lattice_parameter": {
133-
"value": [x, y, z],
134-
},
135-
"angle": {
136-
"value": [alpha, beta, gamma],
137-
},
138-
}
132+
datadict = {}
133+
if bv is not None:
134+
datadict["bravais_lattice"] = {"value": str(bv)}
135+
if x is not None and y is not None and z is not None:
136+
datadict["lattice_parameter"] = {"value": [x.toPython(),
137+
y.toPython(),
138+
z.toPython()]}
139+
if alpha is not None and beta is not None and gamma is not None:
140+
datadict["angle"] = {"value": [alpha.toPython(),
141+
beta.toPython(),
142+
gamma.toPython()]}
139143
return cls(**datadict)
140144

141145

@@ -259,7 +263,7 @@ class SimulationCell(BaseModel, TemplateMixin):
259263
length: Optional[DataProperty[List[float]]] = None
260264
vector: Optional[DataProperty[List[List[float]]]] = None
261265
angle: Optional[DataProperty[List[float]]] = None
262-
repetitions: Optional[DataProperty[List[int]]] = None
266+
repetitions: Optional[DataProperty[List[int]]]
263267

264268
def to_graph(self, graph, sample):
265269
sample_id = get_sample_id(sample)
@@ -297,27 +301,28 @@ def to_graph(self, graph, sample):
297301
)
298302

299303
repetitions = self.repetitions.value
300-
graph.add(
301-
(
302-
simulation_cell,
303-
CMSO.hasRepetition_x,
304-
Literal(repetitions[0], datatype=XSD.integer),
304+
if repetitions is not None:
305+
graph.add(
306+
(
307+
simulation_cell,
308+
CMSO.hasRepetition_x,
309+
Literal(repetitions[0], datatype=XSD.integer),
310+
)
305311
)
306-
)
307-
graph.add(
308-
(
309-
simulation_cell,
310-
CMSO.hasRepetition_y,
311-
Literal(repetitions[1], datatype=XSD.integer),
312+
graph.add(
313+
(
314+
simulation_cell,
315+
CMSO.hasRepetition_y,
316+
Literal(repetitions[1], datatype=XSD.integer),
317+
)
312318
)
313-
)
314-
graph.add(
315-
(
316-
simulation_cell,
317-
CMSO.hasRepetition_z,
318-
Literal(repetitions[2], datatype=XSD.integer),
319+
graph.add(
320+
(
321+
simulation_cell,
322+
CMSO.hasRepetition_z,
323+
Literal(repetitions[2], datatype=XSD.integer),
324+
)
319325
)
320-
)
321326
simulation_cell_length = graph.create_node(
322327
f"{sample_id}_SimulationCellLength", CMSO.SimulationCellLength
323328
)
@@ -458,20 +463,26 @@ def from_graph(cls, graph, sample):
458463
volume = graph.value(volume_item, ASMO.hasValue)
459464
number_of_atoms = graph.value(sample, CMSO.hasNumberOfAtoms)
460465

466+
rx = graph.value(simulation_cell, CMSO.hasRepetition_x) or 1
467+
ry = graph.value(simulation_cell, CMSO.hasRepetition_y) or 1
468+
rz = graph.value(simulation_cell, CMSO.hasRepetition_z) or 1
469+
461470
repetitions = [
462-
toPython(graph.value(simulation_cell, CMSO.hasRepetition_x)),
463-
toPython(graph.value(simulation_cell, CMSO.hasRepetition_y)),
464-
toPython(graph.value(simulation_cell, CMSO.hasRepetition_z)),
471+
int(rx),
472+
int(ry),
473+
int(rz),
465474
]
466475
simulation_cell_length = graph.value(
467476
simulation_cell,
468477
CMSO.hasLength,
469478
)
470-
length = [
471-
toPython(graph.value(simulation_cell_length, CMSO.hasLength_x)),
472-
toPython(graph.value(simulation_cell_length, CMSO.hasLength_y)),
473-
toPython(graph.value(simulation_cell_length, CMSO.hasLength_z)),
474-
]
479+
if simulation_cell_length is not None:
480+
lx = graph.value(simulation_cell_length, CMSO.hasLength_x)
481+
ly = graph.value(simulation_cell_length, CMSO.hasLength_y)
482+
lz = graph.value(simulation_cell_length, CMSO.hasLength_z)
483+
if lx is not None and ly is not None and lz is not None:
484+
length = [lx.toPython(), ly.toPython(), lz.toPython()]
485+
475486
vector = []
476487
for v in graph.objects(simulation_cell, CMSO.hasVector):
477488
vector.append(
@@ -489,7 +500,7 @@ def from_graph(cls, graph, sample):
489500
]
490501

491502
datadict = {
492-
"volume": {"value": volume},
503+
"volume": {"value": volume,},
493504
"number_of_atoms": {"value": int(number_of_atoms)},
494505
"repetitions": {"value": repetitions},
495506
"length": {"value": length},
@@ -589,10 +600,13 @@ def from_graph(cls, graph, sample):
589600
data = json.load(fin)
590601
positions = data[position_identifier]["value"]
591602
species = data[species_identifier]["value"]
592-
603+
604+
position=DataProperty(value=positions)
605+
species=DataProperty(value=species)
606+
593607
return cls(
594-
position=DataProperty(value=positions),
595-
species=DataProperty(value=species),
608+
position=position,
609+
species=species,
596610
)
597611

598612

@@ -625,6 +639,9 @@ class AtomicScaleSample(BaseModel, TemplateMixin):
625639
symmetric_tilt_grain_boundary: Optional[defects.SymmetricalTiltGrainBoundary] = None
626640
mixed_grain_boundary: Optional[defects.MixedGrainBoundary] = None
627641

642+
#properties
643+
644+
628645
def to_graph(self, graph, force=False):
629646
# if force - creates a new ID and saves the structure again
630647
if not force and self.id is not None:
@@ -670,6 +687,13 @@ def to_graph(self, graph, force=False):
670687
def from_graph(cls, graph, sample_id):
671688
kwargs = {}
672689
sample = get_sample_object(sample_id)
690+
691+
#try a type query first
692+
sample_type = graph.value(sample, RDF.type)
693+
if sample_type is None:
694+
raise ValueError(f"Sample {sample_id} not found in graph.")
695+
696+
673697
# material, simulation_cell, atom_attribute handled separately (if needed)
674698
kwargs["material"] = Material.from_graph(graph, sample)
675699
kwargs["simulation_cell"] = SimulationCell.from_graph(graph, sample)

atomrdf/datamodels/workflow/dof.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
DataProperty,
1111
RDFMixin,
1212
BaseModel,
13-
Activity,
1413
)
1514
from rdflib import Graph, Namespace, XSD, RDF, RDFS, BNode, URIRef
1615
from atomrdf.namespace import (

0 commit comments

Comments
 (0)