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

Overload structure #31

Merged
merged 13 commits into from
Jun 26, 2023
9 changes: 7 additions & 2 deletions pyscal_rdf/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@

from pyscal_rdf.visualize import visualize_graph
from pyscal_rdf.network import OntologyNetwork
from pyscal_rdf.rdfsystem import System
import pyscal_rdf.properties as prp
from pyscal3.core import System
#from pyscal3.core import System
from pyscal3.atoms import Atoms
from pyscal3.core import System

CMSO = Namespace("https://purls.helmholtz-metadaten.de/cmso/")
PLDO = Namespace("https://purls.helmholtz-metadaten.de/pldo/")
Expand Down Expand Up @@ -73,6 +73,7 @@ def __init__(self, graph_file=None,
self.sysdict = None
self.sgraph = None
self._query_graph = OntologyNetwork()
self._atom_ids = None

def process_structure(self, structure, format=None):
"""
Expand Down Expand Up @@ -509,13 +510,15 @@ def add_atoms(self, name=None):
Returns
-------
"""
self._atom_ids = []

for x in range(len(self.data("Positions"))):
uname = None
if name is not None:
uname = f'{name}_{x}'
#create atom
atom = BNode(uname)
self._atom_ids.append(atom)
self.add((self.sample, CMSO.hasAtom, atom))
self.add((atom, RDF.type, CMSO.Atom))

Expand Down Expand Up @@ -631,6 +634,8 @@ def add_vacancy(self, concentration, number=None, name=None):
self.add((self.simulation_cell, PODO.hasVacancyConcentration, Literal(concentration, datatype=XSD.float)))
if number is not None:
self.add((self.simulation_cell, PODO.hasNumberOfVacancies, Literal(number, datatype=XSD.integer)))
#if vacancy is added, atoms have to be deleted from the existing record!
#this is indeed a tricky item

def visualize(self, *args, **kwargs):
"""
Expand Down
67 changes: 67 additions & 0 deletions pyscal_rdf/rdfsystem.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import numpy as np
import pyscal3.core as pc
from rdflib import Graph, Literal, Namespace, XSD, RDF, RDFS, BNode, URIRef, FOAF, SKOS, DCTERMS

CMSO = Namespace("https://purls.helmholtz-metadaten.de/cmso/")
PLDO = Namespace("https://purls.helmholtz-metadaten.de/pldo/")
PODO = Namespace("https://purls.helmholtz-metadaten.de/podo/")

class System(pc.System):
def __init__(self, filename = None,
format = "lammps-dump",
compressed = False,
customkeys = None,
source=None):
super().__init__(filename = filename,
format = format,
compressed = compressed,
customkeys = customkeys)
#this is the sample which will be stored
self.sample = None
#the graph object should also be attached
#for post-processing of structures
self.graph = None
self._atom_ids = None
if source is not None:
self.__dict__.update(source.__dict__)

def __delitem__(self, val):
if isinstance(val, int):
val = [val]
self.delete(indices=list(val))
#now the graph has to be updated accordingly
if self.graph is not None:
#first annotate graph
c = (len(val)/self.natoms)
self.graph.add_vacancy(c, number=len(val))
#now we need to re-add atoms, so at to remove
#deleted ones from the vacancy
atoms = [self._atom_ids[v] for v in val]
#this is the list of atoms in this sample
for atom in atoms:
#identify the position
position = list([s[2] for s in self.graph.graph.triples((atom, CMSO.hasPositionVector, None))])[0]
self.graph.graph.remove((position, None, None))
#identify element
element = list([s[2] for s in self.graph.graph.triples((atom, CMSO.hasElement, None))])[0]
self.graph.graph.remove((element, None, None))
#now remove the atom from the list completely
self.graph.graph.remove((atom, None, None))
self.graph.graph.remove((None, None, atom))
#now fully remove atoms
for atom in atoms:
self._atom_ids.remove(atom)
#now fix the number of atoms
self.graph.graph.remove((self.sample, CMSO.hasNumberOfAtoms, None))
self.graph.graph.add((self.sample, CMSO.hasNumberOfAtoms, Literal(self.natoms, datatype=XSD.integer)))
#revamp composition
#for that first get element
material = list([s[2] for s in self.graph.graph.triples((self.sample, CMSO.hasMaterial, None))])[0]
#remove existing chem composution
self.graph.graph.remove((material, CMSO.hasElementRatio, None))
#now recalculate and add it again
chem_comp_element = list(self.composition.keys())
chem_comp_ratio = [val for key, val in self.composition.items()]
chem_comp = ["=".join([str(x), str(y)]) for x,y in zip(chem_comp_element, chem_comp_ratio)]
for x in range(len(chem_comp)):
self.graph.graph.add((material, CMSO.hasElementRatio, Literal(chem_comp[x], datatype=XSD.string)))
35 changes: 25 additions & 10 deletions pyscal_rdf/structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
of :py:class:`pyscal_rdf.graph.RDFGraph` along with easy structural creation routines.
"""
import numpy as np
from pyscal3.core import System
import copy

from pyscal_rdf.rdfsystem import System
from pyscal3.crystal_structures import structure_creator, elements, structures
from pyscal_rdf.graph import RDFGraph
from pyscal3.grain_boundary import GrainBoundary
Expand All @@ -13,10 +15,11 @@ def __init__(self, graph_file=None,
store="Memory",
store_file=None,
identifier="default_graph"):

super().__init__(graph_file=graph_file, store=store, store_file=store_file, identifier=identifier)
self._element_dict = elements
self._structure_dict = structures

def create_element(self, element, repetitions=(1,1,1),
noise=0, add_to_graph=True, names=False):
"""
Expand Down Expand Up @@ -52,13 +55,16 @@ def create_element(self, element, repetitions=(1,1,1),
"""
if element in self._element_dict.keys():
structure = self._element_dict[element]['structure']
sys = structure_creator(structure,
sys = System(source=structure_creator(structure,
repetitions=repetitions,
noise=noise,
lattice_constant=self._element_dict[element]['lattice_constant'],
element = element)
element = element))
if add_to_graph:
self.add_structure_to_graph(sys, names=names)
sys.sample = self.sample
sys._atom_ids = copy.copy(self._atom_ids)
sys.graph = self
return sys

def create_structure(self, structure,
Expand Down Expand Up @@ -102,14 +108,17 @@ def create_structure(self, structure,

"""
if structure in self._structure_dict.keys():
sys = structure_creator(structure,
sys = System(source=structure_creator(structure,
repetitions=repetitions,
noise=noise,
lattice_constant=lattice_constant,
element = element,
)
))
if add_to_graph:
self.add_structure_to_graph(sys, names = names)
sys.sample = self.sample
sys._atom_ids = copy.copy(self._atom_ids)
sys.graph = self
return sys

def read_structure(self, filename, format="lammps-dump",
Expand Down Expand Up @@ -140,6 +149,9 @@ def read_structure(self, filename, format="lammps-dump",
sys = System(filename, format=format)
if add_to_graph:
self.add_structure_to_graph(sys, names=names)
sys.sample = self.sample
sys._atom_ids = copy.copy(self._atom_ids)
sys.graph = self
return sys

def create_grain_boundary(self, axis,
Expand Down Expand Up @@ -198,19 +210,22 @@ def create_grain_boundary(self, axis,

#use standard creation routine
if structure is not None:
sys = gb.populate_grain_boundary(structure,
sys = System(source=gb.populate_grain_boundary(structure,
repetitions = repetitions,
lattice_parameter = lattice_constant,
overlap=overlap)
overlap=overlap))
elif element is not None:
sys = gb.populate_grain_boundary(element,
sys = System(source=gb.populate_grain_boundary(element,
repetitions=repetitions,
overlap=overlap)
overlap=overlap))
else:
raise ValueError("Either structure or element should be provided")

#mapping of the system can be done
self.add_structure_to_graph(sys, names=names)
sys.sample = self.sample
sys._atom_ids = copy.copy(self._atom_ids)
sys.graph = self
gb_dict = {"GBPlane": " ".join(np.array(gb_plane).astype(str)),
"RotationAxis": axis,
"MisorientationAngle": gb.theta,
Expand Down