diff --git a/.bumpversion.cfg b/.bumpversion.cfg index cd03bf6..b5f1cbb 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.9.4 +current_version = 0.9.5 commit = True tag = False diff --git a/CITATION.cff b/CITATION.cff index 3c3d542..987bab5 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -19,4 +19,4 @@ url: 'https://atomrdf.pyscal.org' license: "MIT" repository-code: https://github.com/pyscal/atomRDF type: software -version: 0.9.4 +version: 0.9.5 diff --git a/atomrdf/network/ontology.py b/atomrdf/network/ontology.py index 30bd71c..30df473 100644 --- a/atomrdf/network/ontology.py +++ b/atomrdf/network/ontology.py @@ -82,6 +82,7 @@ def read_ontology(): # General fixes combo.add_path(("cmso:CrystalStructure", "cmso:hasAltName", "string")) + combo.add_path(("cmso:LatticeParameter", "asmo:wasCalculatedBy", "prov:Activity")) # interontology paths #CMSO -> PODO VACANCY diff --git a/atomrdf/sample.py b/atomrdf/sample.py index 9e1abf3..893dd0e 100644 --- a/atomrdf/sample.py +++ b/atomrdf/sample.py @@ -69,7 +69,7 @@ def _volume(self): self._graph.add((parent, ASMO.hasUnit, URIRef(f"http://qudt.org/vocab/unit/ANGSTROM3"))) else: parent = inps[labels.index("Volume")] - return Property(volume.toPython(), graph=self._graph, parent=parent, unit='ANGSTROM3') + return Property(volume.toPython(), graph=self._graph, parent=parent, unit='ANGSTROM3', sample_parent=self._sample_id) @property def _no_of_atoms(self): @@ -83,7 +83,7 @@ def _no_of_atoms(self): self._graph.add((self._sample_id, CMSO.hasCalculatedProperty, parent)) else: parent = inps[labels.index("NumberOfAtoms")] - return Property(no_atoms.toPython(), graph=self._graph, parent=parent) + return Property(no_atoms.toPython(), graph=self._graph, parent=parent, sample_parent=self._sample_id) @property @@ -98,7 +98,7 @@ def _input_properties(self): units = [unit if unit is None else unit.toPython().split('/')[-1] for unit in units] props = [] for count, value in enumerate(values): - props.append(Property(value.toPython(), unit=units[count], graph=self._graph, parent=inps[count])) + props.append(Property(value.toPython(), unit=units[count], graph=self._graph, parent=inps[count], sample_parent=self._sample_id)) return labels, props return [], [] @@ -112,16 +112,17 @@ def _output_properties(self): units = [unit if unit is None else unit.toPython().split('/')[-1] for unit in units] props = [] for count, value in enumerate(values): - props.append(Property(value.toPython(), unit=units[count], graph=self._graph, parent=inps[count])) + props.append(Property(value.toPython(), unit=units[count], graph=self._graph, parent=inps[count], sample_parent=self._sample_id)) return labels, props class Property: - def __init__(self, value, unit=None, graph=None, parent=None): + def __init__(self, value, unit=None, graph=None, parent=None, sample_parent=None): self._value = self._clean_value(value) self._unit = unit self._graph = graph self._parent = parent self._label = None + self._sample_parent = sample_parent def _clean_value(self, value): if isinstance(value, str): @@ -191,12 +192,15 @@ def __add__(self, value): parent = self._create_node(res) res_prop = Property(res, unit=self._unit, graph=self._graph, parent=parent) res_prop.label = self._create_label(self, value, '+') + res_prop._sample_parent = self._sample_parent if self._graph is not None: operation = URIRef(f'operation:{uuid.uuid4()}') self._graph.add((operation, RDF.type, MATH.Addition)) + self._graph.add((operation, RDF.type, PROV.Activity)) self._graph.add((operation, MATH.hasAddend, self._wrap(value))) self._graph.add((operation, MATH.hasAddend, self._wrap(self))) self._graph.add((operation, MATH.hasSum, self._wrap(res_prop))) + self._graph.add((parent, MATH.wasCalculatedBy, operation)) return res_prop def __sub__(self, value): @@ -204,12 +208,15 @@ def __sub__(self, value): parent = self._create_node(res) res_prop = Property(res, unit=self._unit, graph=self._graph, parent=parent) res_prop.label = self._create_label(self, value, '-') + res_prop._sample_parent = self._sample_parent if self._graph is not None: operation = URIRef(f'operation:{uuid.uuid4()}') self._graph.add((operation, RDF.type, MATH.Subtraction)) + self._graph.add((operation, RDF.type, PROV.Activity)) self._graph.add((operation, MATH.hasMinuend, self._wrap(self))) self._graph.add((operation, MATH.hasSubtrahend, self._wrap(value))) self._graph.add((operation, MATH.hasDifference, self._wrap(res_prop))) + self._graph.add((parent, MATH.wasCalculatedBy, operation)) return res_prop def __mul__(self, value): @@ -217,12 +224,15 @@ def __mul__(self, value): parent = self._create_node(res) res_prop = Property(res, unit=self._unit, graph=self._graph, parent=parent) res_prop.label = self._create_label(self, value, '*') + res_prop._sample_parent = self._sample_parent if self._graph is not None: operation = URIRef(f'operation:{uuid.uuid4()}') self._graph.add((operation, RDF.type, MATH.Multiplication)) + self._graph.add((operation, RDF.type, PROV.Activity)) self._graph.add((operation, MATH.hasFactor, self._wrap(self))) self._graph.add((operation, MATH.hasFactor, self._wrap(value))) self._graph.add((operation, MATH.hasProduct, self._wrap(res_prop))) + self._graph.add((parent, MATH.wasCalculatedBy, operation)) return res_prop def __truediv__(self, value): @@ -230,12 +240,15 @@ def __truediv__(self, value): parent = self._create_node(res) res_prop = Property(res, unit=self._unit, graph=self._graph, parent=parent) res_prop.label = self._create_label(self, value, '/') + res_prop._sample_parent = self._sample_parent if self._graph is not None: operation = URIRef(f'operation:{uuid.uuid4()}') self._graph.add((operation, RDF.type, MATH.Division)) + self._graph.add((operation, RDF.type, PROV.Activity)) self._graph.add((operation, MATH.hasDivisor, self._wrap(self))) self._graph.add((operation, MATH.hasDividend, self._wrap(value))) self._graph.add((operation, MATH.hasQuotient, self._wrap(res_prop))) + self._graph.add((parent, MATH.wasCalculatedBy, operation)) return res_prop diff --git a/atomrdf/structure.py b/atomrdf/structure.py index 16535dd..2fa0a86 100644 --- a/atomrdf/structure.py +++ b/atomrdf/structure.py @@ -30,9 +30,10 @@ import atomrdf.json_io as json_io import atomrdf.properties as prp +from atomrdf.sample import Property from rdflib import Graph, Namespace, XSD, RDF, RDFS, BNode, URIRef -from atomrdf.namespace import CMSO, LDO, PLDO, PODO, UNSAFEASMO, UNSAFECMSO, PROV, Literal +from atomrdf.namespace import CMSO, LDO, PLDO, PODO, UNSAFEASMO, UNSAFECMSO, PROV, Literal, ASMO # read element data file file_location = os.path.dirname(__file__).split("/") @@ -41,6 +42,13 @@ with open(file_location, "r") as fin: element_indetifiers = yaml.safe_load(fin) +#declassing special variables +def _declass(item): + if isinstance(item, Property): + return item.value + else: + return item + def _make_crystal( structure, lattice_constant=1.00, @@ -85,9 +93,9 @@ def _make_crystal( """ atoms, box, sdict = pcs.make_crystal( structure, - lattice_constant=lattice_constant, + lattice_constant = _declass(lattice_constant), repetitions=repetitions, - ca_ratio=ca_ratio, + ca_ratio = _declass(ca_ratio), noise=noise, element=element, return_structure_dict=True, @@ -98,10 +106,12 @@ def _make_crystal( s.box = box s.atoms = atoms s.atoms._lattice = structure - s.atoms._lattice_constant = lattice_constant + s.atoms._lattice_constant = _declass(lattice_constant) s._structure_dict = sdict s.label = label s.to_graph() + s.add_property_mappings(lattice_constant, mapping_quantity='lattice_constant') + s.add_property_mappings(ca_ratio, mapping_quantity='lattice_constant') return s @@ -152,7 +162,7 @@ def _make_general_lattice( positions, types, box, - lattice_constant=lattice_constant, + lattice_constant=_declass(lattice_constant), repetitions=repetitions, noise=noise, element=element, @@ -162,11 +172,12 @@ def _make_general_lattice( s.box = box s.atoms = atoms s.atoms._lattice = "custom" - s.atoms._lattice_constant = lattice_constant + s.atoms._lattice_constant = _declass(lattice_constant) s._structure_dict = sdict s.label = label s.to_graph() - + s.add_property_mappings(lattice_constant, mapping_quantity='lattice_constant') + return s @@ -273,9 +284,9 @@ def _make_dislocation( # create a structure with the info input_structure = _make_crystal( structure, - lattice_constant=lattice_constant, + lattice_constant=_declass(lattice_constant), repetitions=repetitions, - ca_ratio=ca_ratio, + ca_ratio=_declass(ca_ratio), noise=noise, element=element, primitive=primitive, @@ -288,9 +299,9 @@ def _make_dislocation( raise ValueError("Please provide structure") input_structure = _make_crystal( structure, - lattice_constant=lattice_constant, + lattice_constant=_declass(lattice_constant), repetitions=repetitions, - ca_ratio=ca_ratio, + ca_ratio=_declass(ca_ratio), noise=noise, element=element, primitive=primitive, @@ -364,6 +375,8 @@ def _make_dislocation( output_structure.graph = graph output_structure.to_graph() output_structure.add_dislocation(disl_dict) + output_structure.add_property_mappings(lattice_constant, mapping_quantity='lattice_constant') + output_structure.add_property_mappings(ca_ratio, mapping_quantity='lattice_constant') if return_atomman_dislocation: return output_structure, disc @@ -423,7 +436,7 @@ def _make_grain_boundary( atoms, box, sdict = gb.populate_grain_boundary( structure, repetitions=repetitions, - lattice_parameter=lattice_constant, + lattice_parameter=_declass(lattice_constant), overlap=overlap, ) elif element is not None: @@ -434,10 +447,12 @@ def _make_grain_boundary( s.box = box s.atoms = atoms s.atoms._lattice = structure - s.atoms._lattice_constant = lattice_constant + s.atoms._lattice_constant = _declass(lattice_constant) s._structure_dict = sdict s.label = label s.to_graph() + s.add_property_mappings(lattice_constant, mapping_quantity='lattice_constant') + gb_dict = { "GBPlane": " ".join(np.array(gb_plane).astype(str)), "RotationAxis": axis, @@ -506,7 +521,7 @@ def _read_structure( datadict = structure_dict[lattice]["conventional"] datadict["lattice"] = lattice if lattice_constant is not None: - datadict["lattice_constant"] = lattice_constant + datadict["lattice_constant"] = _declass(lattice_constant) if basis_box is not None: datadict["box"] = basis_box if basis_positions is not None: @@ -523,6 +538,7 @@ def _read_structure( s.lattice_properties = datadict s.label = label s.to_graph() + s.add_property_mappings(lattice_constant, mapping_quantity='lattice_constant') return s @@ -840,6 +856,35 @@ def delete(self, ids=None, indices=None, condition=None, selection=False, copy_s return sys + + def add_property_mappings(self, output_property, mapping_quantity=None): + if self.graph is None: + return + if not isinstance(output_property, Property): + return + + #if the property is a directly calculated value + parent_samples = list([x[0] for x in self.graph.triples((None, CMSO.hasCalculatedProperty, output_property._parent))]) + if len(parent_samples)>0: + for parent_sample in parent_samples: + self.graph.add((self.sample, PROV.wasDerivedFrom, parent_sample)) + else: + #this is quantity that is derived -> for example volume/3 -> it has only sample parent, but no direct connection + if output_property._sample_parent is not None: + self.graph.add((self.sample, PROV.wasDerivedFrom, output_property._sample_parent)) + + if mapping_quantity=='lattice_constant': + #add lattice constant mapping + material = self.graph.value(self.sample, CMSO.hasMaterial) + crystal_structure = self.graph.value(material, CMSO.hasStructure) + unit_cell = self.graph.value(crystal_structure, CMSO.hasUnitCell) + lattice_parameter = self.graph.value(unit_cell, CMSO.hasLatticeParameter) + + #also get activity + activity = self.graph.value(output_property._parent, ASMO.wasCalculatedBy) + self.graph.add((lattice_parameter, UNSAFEASMO.wasCalculatedBy, activity)) + + def add_vacancy(self, concentration, number=None): """ Add Vacancy details which will be annotated by PODO diff --git a/atomrdf/workflow/pyiron/lammps.py b/atomrdf/workflow/pyiron/lammps.py index 19bd507..2008b2a 100644 --- a/atomrdf/workflow/pyiron/lammps.py +++ b/atomrdf/workflow/pyiron/lammps.py @@ -162,4 +162,34 @@ def extract_calculated_quantities(job, method_dict): "associate_to_sample": True, } ) + + structure = job.get_structure(frame=-1) + lx = np.linalg.norm(structure.cell[0]) + ly = np.linalg.norm(structure.cell[1]) + lz = np.linalg.norm(structure.cell[2]) + + outputs.append( + { + "label": "SimulationCellLength_x", + "value": np.round(lx, decimals=4), + "unit": "ANGSTROM", + "associate_to_sample": True, + } + ) + outputs.append( + { + "label": "SimulationCellLength_y", + "value": np.round(ly, decimals=4), + "unit": "ANGSTROM", + "associate_to_sample": True, + } + ) + outputs.append( + { + "label": "SimulationCellLength_z", + "value": np.round(lz, decimals=4), + "unit": "ANGSTROM", + "associate_to_sample": True, + } + ) method_dict['outputs'] = outputs \ No newline at end of file diff --git a/atomrdf/workflow/pyiron/murnaghan.py b/atomrdf/workflow/pyiron/murnaghan.py index 2c43bad..0bd8a26 100644 --- a/atomrdf/workflow/pyiron/murnaghan.py +++ b/atomrdf/workflow/pyiron/murnaghan.py @@ -48,6 +48,37 @@ def process_job(job): "associate_to_sample": True, } ) + + structure = job.get_structure(frame=-1) + lx = np.linalg.norm(structure.cell[0]) + ly = np.linalg.norm(structure.cell[1]) + lz = np.linalg.norm(structure.cell[2]) + + outputs.append( + { + "label": "SimulationCellLength_x", + "value": np.round(lx, decimals=4), + "unit": "ANGSTROM", + "associate_to_sample": True, + } + ) + outputs.append( + { + "label": "SimulationCellLength_y", + "value": np.round(ly, decimals=4), + "unit": "ANGSTROM", + "associate_to_sample": True, + } + ) + outputs.append( + { + "label": "SimulationCellLength_z", + "value": np.round(lz, decimals=4), + "unit": "ANGSTROM", + "associate_to_sample": True, + } + ) + murnaghan_dict['outputs'] = outputs lammps.add_software(murnaghan_dict) job_dicts.append(murnaghan_dict) diff --git a/atomrdf/workflow/pyiron/vasp.py b/atomrdf/workflow/pyiron/vasp.py index 298bfd2..4b795ff 100644 --- a/atomrdf/workflow/pyiron/vasp.py +++ b/atomrdf/workflow/pyiron/vasp.py @@ -159,4 +159,33 @@ def extract_calculated_quantities(job, method_dict): "associate_to_sample": True, } ) + structure = job.get_structure(frame=-1) + lx = np.linalg.norm(structure.cell[0]) + ly = np.linalg.norm(structure.cell[1]) + lz = np.linalg.norm(structure.cell[2]) + + outputs.append( + { + "label": "SimulationCellLength_x", + "value": np.round(lx, decimals=4), + "unit": "ANGSTROM", + "associate_to_sample": True, + } + ) + outputs.append( + { + "label": "SimulationCellLength_y", + "value": np.round(ly, decimals=4), + "unit": "ANGSTROM", + "associate_to_sample": True, + } + ) + outputs.append( + { + "label": "SimulationCellLength_z", + "value": np.round(lz, decimals=4), + "unit": "ANGSTROM", + "associate_to_sample": True, + } + ) method_dict['outputs'] = outputs \ No newline at end of file diff --git a/examples/workflow_examples/06_linking_calculations.ipynb b/examples/workflow_examples/06_linking_calculations.ipynb new file mode 100644 index 0000000..c7120a0 --- /dev/null +++ b/examples/workflow_examples/06_linking_calculations.ipynb @@ -0,0 +1,407 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Linking calculations" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%config IPCompleter.evaluation='unsafe'" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "10ca3afd28c24e45935e4673526b8e2c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from pyiron_atomistics import Project\n", + "from atomrdf import KnowledgeGraph\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "project = 'wf9d52b'\n", + "pr = Project(project)\n", + "kg = KnowledgeGraph(store='db', store_file=f'{project}.db')\n", + "kg.enable_workflow(pr, workflow_environment='pyiron')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Run a MD simulation; and get the relaxed structure" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The job j1 was saved and received the ID: 1148\n" + ] + } + ], + "source": [ + "structure = pr.create.structure.annotated_structure.bulk('Cu', cubic=True, label='cu_min', repetitions=(3,3,3))\n", + "job = pr.create.job.Lammps('j1', delete_existing_job=True, delete_aborted_job=True)\n", + "job.structure = structure\n", + "job.potential = '2001--Mishin-Y--Cu-1--LAMMPS--ipr1'\n", + "job.calc_minimize(pressure=0)\n", + "job.run()\n", + "kg.add_workflow(job, workflow_environment='pyiron')" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[cu_min, sample:a7f6ce8a-ce7d-4609-9aa3-56d7ddf21947_from_cu_min]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg.samples" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "sample = kg.samples[-1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The relaxed structure values are also calculation outputs" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "TotalEnergy, TotalVolume, SimulationCellLength_x, SimulationCellLength_y, SimulationCellLength_z, Volume, NumberOfAtoms" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sample.outputs" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "a = sample.outputs.SimulationCellLength_x/3" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3.615 ANGSTROM" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now create a new structure with this and run a MD simulation" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "rel_struct = pr.create.structure.annotated_structure.bulk('Cu', cubic=True, label='cu_new',\n", + " a=a, repetitions=(3,3,3))" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The job j1 was saved and received the ID: 1148\n" + ] + } + ], + "source": [ + "job = pr.create.job.Lammps('j1', delete_existing_job=True, delete_aborted_job=True)\n", + "job.structure = rel_struct\n", + "job.potential = '2001--Mishin-Y--Cu-1--LAMMPS--ipr1'\n", + "job.calc_md(pressure=0, temperature=300)\n", + "job.run()\n", + "kg.add_workflow(job, workflow_environment='pyiron')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check the KG" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "sample_a7f6ce8a-ce7d-4609-9aa3-56d7ddf21947\n", + "\n", + "sample_a7f6ce8a-ce7d-4609-9aa3-56d7ddf21947\n", + "\n", + "\n", + "\n", + "sample_ef711752-603e-4b84-8f77-7b9e03132d48\n", + "\n", + "sample_ef711752-603e-4b84-8f77-7b9e03132d48\n", + "\n", + "\n", + "\n", + "sample_a7f6ce8a-ce7d-4609-9aa3-56d7ddf21947->sample_ef711752-603e-4b84-8f77-7b9e03132d48\n", + "\n", + "\n", + "wasDerivedFrom\n", + "\n", + "\n", + "\n", + "activity_4f1b4767-6502-4f00-b35b-c6bb613d26de\n", + "\n", + "activity_4f1b4767-6502-4f00-b35b-c6bb613d26de\n", + "\n", + "\n", + "\n", + "sample_a7f6ce8a-ce7d-4609-9aa3-56d7ddf21947->activity_4f1b4767-6502-4f00-b35b-c6bb613d26de\n", + "\n", + "\n", + "wasGeneratedBy\n", + "\n", + "\n", + "\n", + "sample_60996d0a-82b3-4812-a61f-9029e9e57ca8\n", + "\n", + "sample_60996d0a-82b3-4812-a61f-9029e9e57ca8\n", + "\n", + "\n", + "\n", + "sample_60996d0a-82b3-4812-a61f-9029e9e57ca8->sample_a7f6ce8a-ce7d-4609-9aa3-56d7ddf21947\n", + "\n", + "\n", + "wasDerivedFrom\n", + "\n", + "\n", + "\n", + "sample_536d4ce9-8b97-4f0e-a7d0-4d82beee4fe9\n", + "\n", + "sample_536d4ce9-8b97-4f0e-a7d0-4d82beee4fe9\n", + "\n", + "\n", + "\n", + "sample_536d4ce9-8b97-4f0e-a7d0-4d82beee4fe9->sample_60996d0a-82b3-4812-a61f-9029e9e57ca8\n", + "\n", + "\n", + "wasDerivedFrom\n", + "\n", + "\n", + "\n", + "activity_c2b6577c-a338-4276-90ca-f372f3085c00\n", + "\n", + "activity_c2b6577c-a338-4276-90ca-f372f3085c00\n", + "\n", + "\n", + "\n", + "sample_536d4ce9-8b97-4f0e-a7d0-4d82beee4fe9->activity_c2b6577c-a338-4276-90ca-f372f3085c00\n", + "\n", + "\n", + "wasGeneratedBy\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg.visualise(sample_view=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also query and see the lattice parameter was calculated by an activity" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " LatticeParameter\n", + " wasCalculatedBy\n", + " \n", + " \n", + " \n", + " \n", + " 0\n", + " sample:60996d0a-82b3-4812-a61f-9029e9e57ca8_La...\n", + " operation:04fc5b80-11c0-4b7f-9125-0e04516807c6\n", + " \n", + " \n", + "\n", + "" + ], + "text/plain": [ + " LatticeParameter \\\n", + "0 sample:60996d0a-82b3-4812-a61f-9029e9e57ca8_La... \n", + "\n", + " wasCalculatedBy \n", + "0 operation:04fc5b80-11c0-4b7f-9125-0e04516807c6 " + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg.auto_query(kg.terms.cmso.LatticeParameter, [kg.terms.asmo.wasCalculatedBy])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "workflow-rdf", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/setup.py b/setup.py index f7246b1..ddf1700 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ setup( name='atomrdf', - version='0.9.4', + version='0.9.5', author='Abril Azocar Guzman, Sarath Menon', author_email='sarath.menon@pyscal.org', description='Ontology based structural manipulation and quering',