From 22de6a74a1ac58a52b0a4ce843515abdf4bcbbf0 Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 15 Aug 2024 10:31:53 +0200 Subject: [PATCH 01/15] clean extract function --- atomrdf/graph.py | 40 +++++++++++++---- atomrdf/structure.py | 15 +++++++ examples/02_grain_boundaries.ipynb | 72 ++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 8 deletions(-) diff --git a/atomrdf/graph.py b/atomrdf/graph.py index 0a4a6d3..6be1992 100644 --- a/atomrdf/graph.py +++ b/atomrdf/graph.py @@ -1161,7 +1161,7 @@ def activity_ids(self): return [x[0] for x in self.triples((None, RDF.type, PROV.Activity))] - def iterate_graph(self, item, create_new_graph=False): + def iterate_graph(self, item, create_new_graph=False, create_new_list=False): """ Iterate through the graph starting from the given item. @@ -1177,16 +1177,40 @@ def iterate_graph(self, item, create_new_graph=False): ------- None """ - if isinstance(item, str): - item = URIRef(item) + #active = False + + if not type(item).__name__ == 'URIRef': + return + + #if create_new_graph: + # self.sgraph = KnowledgeGraph() + + if create_new_list: + self.slist = [] - if create_new_graph: - self.sgraph = KnowledgeGraph() triples = list(self.triples((item, None, None))) + #print(triples) + for triple in triples: - self.sgraph.graph.add(triple) + #active = True + #if create_new_graph: + # self.sgraph.graph.add(triple) + self.slist.append(triple) self.iterate_graph(triple[2]) - + + def iterate_and_reapply_triples(self, item): + self.iterate_graph(item, create_new_list=True) + triples = copy.deepcopy(self.slist) + #now we have to edit this triples, and reapply them + #for that we make a dict of all URIRef values in this graph + uri_dict = {} + for triple in triples: + if isinstance(triple[0], URIRef): + print(triple[0]) + if triple[0].toPython() not in uri_dict.keys(): + uri_dict[triple[0].toPython()] = None + return uri_dict + def get_sample(self, sample, no_atoms=False): """ Get the Sample as a KnowledgeGraph @@ -1210,7 +1234,7 @@ def get_sample(self, sample, no_atoms=False): if isinstance(sample, str): sample = URIRef(sample) - self.iterate_graph(sample, create_new_graph=True) + _ = self.iterate_graph(sample, create_new_graph=True) if no_atoms: na = self.sgraph.value(sample, CMSO.hasNumberOfAtoms).toPython() return self.sgraph, na diff --git a/atomrdf/structure.py b/atomrdf/structure.py index d9ae5d0..1c34c7d 100644 --- a/atomrdf/structure.py +++ b/atomrdf/structure.py @@ -2553,3 +2553,18 @@ def add_shear_triples(self, translation_vector, plane, distance, ): self.graph.add((plane_vector, CMSO.hasComponent_y, Literal(plane[1], datatype=XSD.float),)) self.graph.add((plane_vector, CMSO.hasComponent_z, Literal(plane[2], datatype=XSD.float),)) self.graph.add((activity, UNSAFECMSO.hasDistance, Literal(distance, datatype=XSD.float))) + + def copy_defects(self, parent_sample): + if self.sample is None: + return + if parent_sample is None: + return + + parent_material = list([k[2] for k in self.kg.triples((parent_sample, CMSO.hasMaterial, None))])[0] + parent_defects = list([x[2] for x in self.kg.triples((parent_material, CMSO.hasDefect, None))]) + + material = list([k[2] for k in self.kg.triples((self.sample, CMSO.hasMaterial, None))])[0] + + for defect in parent_defects: + new_defect = URIRef(defect.toPython()) + \ No newline at end of file diff --git a/examples/02_grain_boundaries.ipynb b/examples/02_grain_boundaries.ipynb index 4d110a5..86a9917 100644 --- a/examples/02_grain_boundaries.ipynb +++ b/examples/02_grain_boundaries.ipynb @@ -60,6 +60,78 @@ " graph=kg)" ] }, + { + "cell_type": "code", + "execution_count": 4, + "id": "dc65fb07", + "metadata": {}, + "outputs": [], + "source": [ + "from atomrdf.namespace import PROV, CMSO\n", + "parent_material = list(\n", + " [\n", + " k[2]\n", + " for k in kg.triples((struct_gb_1.sample, CMSO.hasMaterial, None))\n", + " ]\n", + ")[0]\n", + "parent_defects = list(\n", + " [x[2] for x in kg.triples((parent_material, CMSO.hasDefect, None))]\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "2f07ae38", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[rdflib.term.URIRef('sample:ddb98ea8-c0dd-4b86-b6a1-97bddf93b94a_SymmetricalTiltGrainBoundary')]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "parent_defects" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "6f2b8588", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "sample:ddb98ea8-c0dd-4b86-b6a1-97bddf93b94a_SymmetricalTiltGrainBoundary\n", + "sample:ddb98ea8-c0dd-4b86-b6a1-97bddf93b94a_SymmetricalTiltGrainBoundary\n", + "sample:ddb98ea8-c0dd-4b86-b6a1-97bddf93b94a_SymmetricalTiltGrainBoundary\n", + "sample:ddb98ea8-c0dd-4b86-b6a1-97bddf93b94a_SymmetricalTiltGrainBoundary\n", + "sample:ddb98ea8-c0dd-4b86-b6a1-97bddf93b94a_SymmetricalTiltGrainBoundary\n" + ] + }, + { + "data": { + "text/plain": [ + "{'sample:ddb98ea8-c0dd-4b86-b6a1-97bddf93b94a_SymmetricalTiltGrainBoundary': None}" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg.iterate_and_reapply_triples(parent_defects[0])" + ] + }, { "cell_type": "markdown", "id": "717626e5-3672-470e-a9d9-2878310268ca", From 6d7e8ecd7b5d152bd4df4b1e99a718f5c1bef269 Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 15 Aug 2024 10:56:27 +0200 Subject: [PATCH 02/15] add graph method --- atomrdf/graph.py | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/atomrdf/graph.py b/atomrdf/graph.py index 6be1992..6b5b083 100644 --- a/atomrdf/graph.py +++ b/atomrdf/graph.py @@ -1161,7 +1161,8 @@ def activity_ids(self): return [x[0] for x in self.triples((None, RDF.type, PROV.Activity))] - def iterate_graph(self, item, create_new_graph=False, create_new_list=False): + def iterate_graph(self, item, create_new_graph=False, create_new_list=False, + stop_at_sample=False): """ Iterate through the graph starting from the given item. @@ -1169,35 +1170,48 @@ def iterate_graph(self, item, create_new_graph=False, create_new_list=False): ---------- item : object The item to start the iteration from. - create_new_graph : bool, optional - If True, create a new KnowledgeGraph object to store the iteration results. - Default is False. The results are stored in `self.sgraph`. + create_new_list : bool, optional + If True, create a new list to store extracted triples, this is needed when + calling this function iteratively + stop_at_sample : bool, optional + If True, stops the iteration at the when a sample object is encountered. Default is False. + will only stop if `item` is a sample object Returns ------- None """ #active = False + #if create_new_graph: + # self.sgraph = KnowledgeGraph() + #print(triples) + #active = True + #if create_new_graph: + # self.sgraph.graph.add(triple) if not type(item).__name__ == 'URIRef': return - - #if create_new_graph: - # self.sgraph = KnowledgeGraph() if create_new_list: self.slist = [] - + rdftype = self.value(item, RDF.type) + if rdftype is not None: + rdftype = rdftype.toPython() + stop_at_sample = stop_at_sample and rdftype == CMSO.AtomicScaleSample.uri + triples = list(self.triples((item, None, None))) - #print(triples) for triple in triples: - #active = True - #if create_new_graph: - # self.sgraph.graph.add(triple) self.slist.append(triple) - self.iterate_graph(triple[2]) + self.iterate_graph(triple[2], stop_at_sample=stop_at_sample) + def iterate_and_create_graph(self, item, stop_at_sample=False): + triples = self.iterate_graph(item, create_new_list=True, stop_at_sample=stop_at_sample) + sgraph = KnowledgeGraph() + for triple in triples: + sgraph.add(triple) + return sgraph + def iterate_and_reapply_triples(self, item): self.iterate_graph(item, create_new_list=True) triples = copy.deepcopy(self.slist) From 60006f1b8624aa8792ada92fef23fae2b4c2a9aa Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 15 Aug 2024 12:37:30 +0200 Subject: [PATCH 03/15] fix graph creation routines --- atomrdf/graph.py | 56 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/atomrdf/graph.py b/atomrdf/graph.py index 6b5b083..26496cd 100644 --- a/atomrdf/graph.py +++ b/atomrdf/graph.py @@ -300,7 +300,13 @@ def _is_valid(self, input_list): def _is_ontoterm(self, term): return type(term).__name__ == "OntoTerm" - + + def _is_uriref(self, term): + return type(term).__name__ == "URIRef" + + def _is_bnode(self, term): + return not term.toPython().startswith("http") + def _modify_triple(self, triple): modified_triple = [] for term in triple: @@ -1160,7 +1166,30 @@ def activity_ids(self): """ return [x[0] for x in self.triples((None, RDF.type, PROV.Activity))] - + + def _is_of_type(self, item, target_item): + """ + Check if an item is of a specific type + + item - direct from graph, comparison only makes sense if it is URIRef + if item is node with https - direct comparison + if not - check the type of the item + + target_item - URIRef or OntoTerm + """ + if not self._is_uriref(item): + return False + + if self._is_bnode(item): + rdftype = self.value(item, RDF.type) + if rdftype is not None: + rdftype = rdftype.toPython() + else: + rdftype = item.toPython() + + target_type = target_item.toPython() + return rdftype == target_type + def iterate_graph(self, item, create_new_graph=False, create_new_list=False, stop_at_sample=False): """ @@ -1181,32 +1210,24 @@ def iterate_graph(self, item, create_new_graph=False, create_new_list=False, ------- None """ - #active = False - #if create_new_graph: - # self.sgraph = KnowledgeGraph() - #print(triples) - #active = True - #if create_new_graph: - # self.sgraph.graph.add(triple) - if not type(item).__name__ == 'URIRef': return if create_new_list: self.slist = [] - rdftype = self.value(item, RDF.type) - if rdftype is not None: - rdftype = rdftype.toPython() - stop_at_sample = stop_at_sample and rdftype == CMSO.AtomicScaleSample.uri + stop_at_sample = stop_at_sample and self._is_of_type(item, CMSO.AtomicScaleSample) triples = list(self.triples((item, None, None))) for triple in triples: - self.slist.append(triple) - self.iterate_graph(triple[2], stop_at_sample=stop_at_sample) + if not (stop_at_sample and self._is_of_type(triple[1], PROV.wasDerivedFrom)): + self.slist.append(triple) + self.iterate_graph(triple[2], stop_at_sample=stop_at_sample) def iterate_and_create_graph(self, item, stop_at_sample=False): - triples = self.iterate_graph(item, create_new_list=True, stop_at_sample=stop_at_sample) + self.iterate_graph(item, create_new_list=True, stop_at_sample=stop_at_sample) + triples = copy.deepcopy(self.slist) + self.slist = [] sgraph = KnowledgeGraph() for triple in triples: sgraph.add(triple) @@ -1220,7 +1241,6 @@ def iterate_and_reapply_triples(self, item): uri_dict = {} for triple in triples: if isinstance(triple[0], URIRef): - print(triple[0]) if triple[0].toPython() not in uri_dict.keys(): uri_dict[triple[0].toPython()] = None return uri_dict From fd4d7107e7c6e1e77f23d217d9e15893d646936b Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 15 Aug 2024 12:43:14 +0200 Subject: [PATCH 04/15] rewrite get graph method --- atomrdf/graph.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/atomrdf/graph.py b/atomrdf/graph.py index 26496cd..60205be 100644 --- a/atomrdf/graph.py +++ b/atomrdf/graph.py @@ -1245,7 +1245,7 @@ def iterate_and_reapply_triples(self, item): uri_dict[triple[0].toPython()] = None return uri_dict - def get_sample(self, sample, no_atoms=False): + def get_sample(self, sample, no_atoms=False, stop_at_sample=True): """ Get the Sample as a KnowledgeGraph @@ -1257,6 +1257,9 @@ def get_sample(self, sample, no_atoms=False): no_atoms: bool, optional if True, returns the number of atoms in the sample + stop_at_sample: bool, optional + if True, stops the iteration at the when a sample object is encountered. Default is True. + Returns ------- sgraph: :py:class:`RDFGraph` @@ -1268,11 +1271,11 @@ def get_sample(self, sample, no_atoms=False): if isinstance(sample, str): sample = URIRef(sample) - _ = self.iterate_graph(sample, create_new_graph=True) + sgraph = self.iterate_and_create_graph(sample, stop_at_sample=stop_at_sample) if no_atoms: - na = self.sgraph.value(sample, CMSO.hasNumberOfAtoms).toPython() - return self.sgraph, na - return self.sgraph + na = sgraph.value(sample, CMSO.hasNumberOfAtoms).toPython() + return sgraph, na + return sgraph def get_label(self, item): label = self.graph.value(item, RDFS.label) From a1c0c8dc966522bb2c5c1a5270ed4d5bb2ba6ddf Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 15 Aug 2024 12:58:22 +0200 Subject: [PATCH 05/15] add fn to rename objects --- atomrdf/graph.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/atomrdf/graph.py b/atomrdf/graph.py index 60205be..c7cedf5 100644 --- a/atomrdf/graph.py +++ b/atomrdf/graph.py @@ -1233,7 +1233,24 @@ def iterate_and_create_graph(self, item, stop_at_sample=False): sgraph.add(triple) return sgraph - def iterate_and_reapply_triples(self, item): + def _create_a_new_name(self, uristring): + """ + take a given uriref string name and create one in similar fashion + """ + raw = uristring.split(':') + if len(raw) > 1: + prologue = raw[0]+':' + else: + prologue = '' + + raw = uristring.split('_') + if len(raw) > 1: + epilogue = '_'+"_".join(raw[1:]) + else: + epilogue = '' + return f"{prologue}{uuid.uuid4()}{epilogue}" + + def iterate_and_rename_triples(self, item): self.iterate_graph(item, create_new_list=True) triples = copy.deepcopy(self.slist) #now we have to edit this triples, and reapply them @@ -1242,7 +1259,10 @@ def iterate_and_reapply_triples(self, item): for triple in triples: if isinstance(triple[0], URIRef): if triple[0].toPython() not in uri_dict.keys(): - uri_dict[triple[0].toPython()] = None + if self._is_bnode(triple[0]): + uri_dict[triple[0].toPython()] = self._create_a_new_name(triple[0].toPython()) + else: + uri_dict[triple[0].toPython()] = None return uri_dict def get_sample(self, sample, no_atoms=False, stop_at_sample=True): From f281b22dad7227d854ab3cb2f30bae7f47c9c984 Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 15 Aug 2024 13:05:49 +0200 Subject: [PATCH 06/15] add method to rename triples --- atomrdf/graph.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/atomrdf/graph.py b/atomrdf/graph.py index c7cedf5..28d0239 100644 --- a/atomrdf/graph.py +++ b/atomrdf/graph.py @@ -1262,8 +1262,15 @@ def iterate_and_rename_triples(self, item): if self._is_bnode(triple[0]): uri_dict[triple[0].toPython()] = self._create_a_new_name(triple[0].toPython()) else: - uri_dict[triple[0].toPython()] = None - return uri_dict + uri_dict[triple[0].toPython()] = triple[0].toPython() + + for triple in triples: + if triple[0].toPython() in uri_dict.keys(): + triples[0] = uri_dict[triple[0].toPython()] + if triple[2].toPython() in uri_dict.keys(): + triples[2] = uri_dict[triple[2].toPython()] + + return uri_dict[item.toPython()], triples def get_sample(self, sample, no_atoms=False, stop_at_sample=True): """ From 2a0031647aab3c15854f00a4e53b8b149eb03e57 Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 15 Aug 2024 13:08:13 +0200 Subject: [PATCH 07/15] add copy_defect function --- atomrdf/graph.py | 2 +- atomrdf/structure.py | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/atomrdf/graph.py b/atomrdf/graph.py index 28d0239..2871a3d 100644 --- a/atomrdf/graph.py +++ b/atomrdf/graph.py @@ -1270,7 +1270,7 @@ def iterate_and_rename_triples(self, item): if triple[2].toPython() in uri_dict.keys(): triples[2] = uri_dict[triple[2].toPython()] - return uri_dict[item.toPython()], triples + return URIRef(uri_dict[item.toPython()]), triples def get_sample(self, sample, no_atoms=False, stop_at_sample=True): """ diff --git a/atomrdf/structure.py b/atomrdf/structure.py index 1c34c7d..0be4bd0 100644 --- a/atomrdf/structure.py +++ b/atomrdf/structure.py @@ -2566,5 +2566,9 @@ def copy_defects(self, parent_sample): material = list([k[2] for k in self.kg.triples((self.sample, CMSO.hasMaterial, None))])[0] for defect in parent_defects: - new_defect = URIRef(defect.toPython()) - \ No newline at end of file + new_defect, defect_triples = self.graph.iterate_and_rename_triples(defect) + #add the new defect to the new material + self.graph.add((material, CMSO.hasDefect, new_defect)) + #add the triples to the graph + for triple in defect_triples: + self.graph.add((triple)) \ No newline at end of file From f089c8d93787a04984ec61b798045206428b566f Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 15 Aug 2024 13:22:51 +0200 Subject: [PATCH 08/15] fix GB being added twice --- atomrdf/structure.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/atomrdf/structure.py b/atomrdf/structure.py index 0be4bd0..74791ab 100644 --- a/atomrdf/structure.py +++ b/atomrdf/structure.py @@ -527,11 +527,12 @@ def _make_grain_boundary_aimsgb( to_primitive=primitive, ) asestruct = AseAtomsAdaptor().get_atoms(structure=gb_struct) - sys = System.read.ase(asestruct, graph=graph, names=names, label=label) + sys = System.read.ase(asestruct, graph=None, names=names, label=label) sys.atoms._lattice = structure sys.atoms._lattice_constant = _declass(lattice_constant) sys._structure_dict = sdict sys.label = label + sys.graph = graph sys.to_graph() sys.add_property_mappings(lattice_constant, mapping_quantity='lattice_constant') sys.add_property_mappings(ca_ratio, mapping_quantity='lattice_constant') @@ -619,13 +620,14 @@ def _make_grain_boundary_inbuilt( if 'repetitions' not in sdict.keys(): sdict['repetitions'] = repetitions - s = System(graph=graph, names=names) + s = System(graph=None, names=names) s.box = box s.atoms = atoms s.atoms._lattice = structure s.atoms._lattice_constant = _declass(lattice_constant) s._structure_dict = sdict s.label = label + s.graph = graph s.to_graph() s.add_property_mappings(lattice_constant, mapping_quantity='lattice_constant') From 3772047feb6ded8c4f866d2127082f1f827327f7 Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 15 Aug 2024 13:30:28 +0200 Subject: [PATCH 09/15] convert things to urirefs --- atomrdf/graph.py | 4 ++-- atomrdf/structure.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/atomrdf/graph.py b/atomrdf/graph.py index 2871a3d..675fb1c 100644 --- a/atomrdf/graph.py +++ b/atomrdf/graph.py @@ -1266,9 +1266,9 @@ def iterate_and_rename_triples(self, item): for triple in triples: if triple[0].toPython() in uri_dict.keys(): - triples[0] = uri_dict[triple[0].toPython()] + triples[0] = URIRef(uri_dict[triple[0].toPython()]) if triple[2].toPython() in uri_dict.keys(): - triples[2] = uri_dict[triple[2].toPython()] + triples[2] = URIRef(uri_dict[triple[2].toPython()]) return URIRef(uri_dict[item.toPython()]), triples diff --git a/atomrdf/structure.py b/atomrdf/structure.py index 74791ab..b497d8b 100644 --- a/atomrdf/structure.py +++ b/atomrdf/structure.py @@ -2562,10 +2562,10 @@ def copy_defects(self, parent_sample): if parent_sample is None: return - parent_material = list([k[2] for k in self.kg.triples((parent_sample, CMSO.hasMaterial, None))])[0] - parent_defects = list([x[2] for x in self.kg.triples((parent_material, CMSO.hasDefect, None))]) + parent_material = list([k[2] for k in self.graph.triples((parent_sample, CMSO.hasMaterial, None))])[0] + parent_defects = list([x[2] for x in self.graph.triples((parent_material, CMSO.hasDefect, None))]) - material = list([k[2] for k in self.kg.triples((self.sample, CMSO.hasMaterial, None))])[0] + material = list([k[2] for k in self.graph.triples((self.sample, CMSO.hasMaterial, None))])[0] for defect in parent_defects: new_defect, defect_triples = self.graph.iterate_and_rename_triples(defect) From c0ddf11d45f4e22c081fdac63f5bb1fb76bd9bb8 Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 15 Aug 2024 13:44:53 +0200 Subject: [PATCH 10/15] working copy_defects function --- atomrdf/graph.py | 15 ++++++++++----- atomrdf/structure.py | 3 ++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/atomrdf/graph.py b/atomrdf/graph.py index 675fb1c..893d47a 100644 --- a/atomrdf/graph.py +++ b/atomrdf/graph.py @@ -1264,13 +1264,18 @@ def iterate_and_rename_triples(self, item): else: uri_dict[triple[0].toPython()] = triple[0].toPython() + new_triples = [] for triple in triples: - if triple[0].toPython() in uri_dict.keys(): - triples[0] = URIRef(uri_dict[triple[0].toPython()]) - if triple[2].toPython() in uri_dict.keys(): - triples[2] = URIRef(uri_dict[triple[2].toPython()]) + subject = triple[0] + if subject.toPython() in uri_dict.keys(): + subject = URIRef(uri_dict[subject.toPython()]) + predicate = triple[1] + object = triple[2] + if object.toPython() in uri_dict.keys(): + object = URIRef(uri_dict[object.toPython()]) + new_triples.append((subject, predicate, object)) - return URIRef(uri_dict[item.toPython()]), triples + return URIRef(uri_dict[item.toPython()]), new_triples def get_sample(self, sample, no_atoms=False, stop_at_sample=True): """ diff --git a/atomrdf/structure.py b/atomrdf/structure.py index b497d8b..f88d18a 100644 --- a/atomrdf/structure.py +++ b/atomrdf/structure.py @@ -2573,4 +2573,5 @@ def copy_defects(self, parent_sample): self.graph.add((material, CMSO.hasDefect, new_defect)) #add the triples to the graph for triple in defect_triples: - self.graph.add((triple)) \ No newline at end of file + #print(triple) + self.graph.add(triple) \ No newline at end of file From 7706e726cd84e2d211b8edd4b6c914f13b1d0614 Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 15 Aug 2024 14:52:34 +0200 Subject: [PATCH 11/15] add copy fn --- atomrdf/structure.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/atomrdf/structure.py b/atomrdf/structure.py index f88d18a..ede152a 100644 --- a/atomrdf/structure.py +++ b/atomrdf/structure.py @@ -936,6 +936,7 @@ def repeat(self, repetitions): new_system._structure_dict = {} new_system._structure_dict["repetitions"] = repetitions new_system.to_graph() + new_system.copy_defects(self.sample) return new_system def delete(self, ids=None, indices=None, condition=None, selection=False, copy_structure=False): @@ -968,6 +969,7 @@ def delete(self, ids=None, indices=None, condition=None, selection=False, copy_s sys = self.duplicate() #and add this new structure to the graph sys.to_graph() + sys.copy_defects(self.sample) else: sys = self @@ -1184,6 +1186,7 @@ def substitute_atoms( sys = self.duplicate() #and add this new structure to the graph sys.to_graph() + sys.copy_defects(self.sample) else: sys = self @@ -1386,6 +1389,7 @@ def add_interstitial_impurities( #sys = self.duplicate() sys = System(source=sys.add_atoms({"positions": randpos, "species": element})) sys.to_graph() + sys.copy_defects(self.sample) else: #sys = self.duplicate() sys = System(source=self.add_atoms({"positions": randpos, "species": element})) @@ -2410,6 +2414,7 @@ def rotate(self, rotation_vectors, graph=None, label=None): else: output_structure.label = self.label output_structure.to_graph() + output_structure.copy_defects(self.sample) if output_structure.graph is not None: self.add_rotation_triples(rotation_vectors, output_structure.sample) return output_structure @@ -2467,6 +2472,7 @@ def translate(self, translation_vector, sys = self.duplicate() #and add this new structure to the graph sys.to_graph() + sys.copy_defects(self.sample) else: sys = self @@ -2518,6 +2524,7 @@ def shear(self, shear_vector, sys = self.duplicate() #and add this new structure to the graph sys.to_graph() + sys.copy_defects(self.sample) else: sys = self From 64cf40604e15e51466ed8d1361ade3fa96f0defd Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 15 Aug 2024 14:56:40 +0200 Subject: [PATCH 12/15] add tests --- tests/test_structure.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/test_structure.py b/tests/test_structure.py index 3453df6..6fb8f70 100644 --- a/tests/test_structure.py +++ b/tests/test_structure.py @@ -91,3 +91,22 @@ def test_interstitials(): species = s.value(sys.sample, CMSO.hasSpecies) elements = [k[2] for k in s.triples((species, CMSO.hasElement, None))] assert len(elements) == 3 + +def test_gb(): + kg = KnowledgeGraph() + struct_gb_1 = System.create.defect.grain_boundary(axis=[0,0,1], + sigma=5, + gb_plane=[3, -1, 0], + element='Fe', + graph=kg) + res = kg.query_sample(kg.ontology.terms.pldo.SymmetricalTiltGrainBoundary) + assert len(res.AtomicScaleSample.values) == 1 + + new = struct_gb_1.repeat((2,2,2)) + res = kg.query_sample(kg.ontology.terms.pldo.SymmetricalTiltGrainBoundary) + assert len(res.AtomicScaleSample.values) == 2 + + ss = kg.get_sample(new.sample) + res = ss.query_sample(ss.ontology.terms.pldo.SymmetricalTiltGrainBoundary) + assert len(res.AtomicScaleSample.values) == 1 + From 898383ae7d194c25fb55ed6c2dab3f516e52b1ac Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 15 Aug 2024 15:08:01 +0200 Subject: [PATCH 13/15] restructure copy defects function --- atomrdf/graph.py | 39 ++++++++++++++++++++++++++++++++- atomrdf/structure.py | 15 +------------ atomrdf/workflow/workflow.py | 42 ++---------------------------------- 3 files changed, 41 insertions(+), 55 deletions(-) diff --git a/atomrdf/graph.py b/atomrdf/graph.py index 893d47a..4f06071 100644 --- a/atomrdf/graph.py +++ b/atomrdf/graph.py @@ -1276,7 +1276,44 @@ def iterate_and_rename_triples(self, item): new_triples.append((subject, predicate, object)) return URIRef(uri_dict[item.toPython()]), new_triples - + + def copy_defects(self, sample, parent_sample): + """ + Copy defects from one sample to another + """ + parent_material = list([k[2] for k in self.triples((parent_sample, CMSO.hasMaterial, None))])[0] + parent_defects = list([x[2] for x in self.triples((parent_material, CMSO.hasDefect, None))]) + + material = list([k[2] for k in self.triples((sample, CMSO.hasMaterial, None))])[0] + + for defect in parent_defects: + new_defect, defect_triples = self.graph.iterate_and_rename_triples(defect) + #add the new defect to the new material + self.add((material, CMSO.hasDefect, new_defect)) + #add the triples to the graph + for triple in defect_triples: + #print(triple) + self.add(triple) + + #we need to add special items which are mapped to the sample directly + # now add the special props for vacancy, interstitial &substitional + for triple in self.triples( + (parent_sample, PODO.hasVacancyConcentration, None) + ): + self.add((sample, triple[1], triple[2])) + #for triple in self.graph.triples( + # (parent_sample, PODO.hasNumberOfVacancies, None) + #): + # self.graph.add((self.sample, triple[1], triple[2])) + for triple in self.triples( + (parent_sample, PODO.hasImpurityConcentration, None) + ): + self.add((sample, triple[1], triple[2])) + #for triple in self.graph.triples( + # (parent_sample, PODO.hasNumberOfImpurityAtoms, None) + #): + # self.graph.add((self.sample, triple[1], triple[2])) + def get_sample(self, sample, no_atoms=False, stop_at_sample=True): """ Get the Sample as a KnowledgeGraph diff --git a/atomrdf/structure.py b/atomrdf/structure.py index ede152a..840b6f2 100644 --- a/atomrdf/structure.py +++ b/atomrdf/structure.py @@ -2568,17 +2568,4 @@ def copy_defects(self, parent_sample): return if parent_sample is None: return - - parent_material = list([k[2] for k in self.graph.triples((parent_sample, CMSO.hasMaterial, None))])[0] - parent_defects = list([x[2] for x in self.graph.triples((parent_material, CMSO.hasDefect, None))]) - - material = list([k[2] for k in self.graph.triples((self.sample, CMSO.hasMaterial, None))])[0] - - for defect in parent_defects: - new_defect, defect_triples = self.graph.iterate_and_rename_triples(defect) - #add the new defect to the new material - self.graph.add((material, CMSO.hasDefect, new_defect)) - #add the triples to the graph - for triple in defect_triples: - #print(triple) - self.graph.add(triple) \ No newline at end of file + self.graph.copy_defects(self.sample, parent_sample) diff --git a/atomrdf/workflow/workflow.py b/atomrdf/workflow/workflow.py index 774537e..3ff7c92 100644 --- a/atomrdf/workflow/workflow.py +++ b/atomrdf/workflow/workflow.py @@ -207,49 +207,11 @@ def _add_inherited_properties( ): # Here we need to add inherited info: CalculatedProperties will be lost # Defects will be inherited + if sample is None: return - parent_material = list( - [ - k[2] - for k in self.kg.triples((parent_sample, CMSO.hasMaterial, None)) - ] - )[0] - parent_defects = list( - [x[2] for x in self.kg.triples((parent_material, CMSO.hasDefect, None))] - ) - # now for each defect we copy add this to the final sample - material = list( - [k[2] for k in self.kg.triples((sample, CMSO.hasMaterial, None))] - )[0] - - for defect in parent_defects: - new_defect = URIRef(defect.toPython()) - self.kg.add((material, CMSO.hasDefect, new_defect)) - # now fetch all defect based info - for triple in self.kg.triples((defect, None, None)): - self.kg.add((new_defect, triple[1], triple[2])) - - # now add the special props for vacancy, interstitial &substitional - for triple in self.kg.triples( - (parent_sample, PODO.hasVacancyConcentration, None) - ): - self.kg.add((sample, triple[1], triple[2])) - for triple in self.kg.triples( - (parent_sample, PODO.hasNumberOfVacancies, None) - ): - self.kg.add((sample, triple[1], triple[2])) - for triple in self.kg.triples( - (parent_sample, PODO.hasImpurityConcentration, None) - ): - self.kg.add((sample, triple[1], triple[2])) - for triple in self.kg.triples( - (parent_sample, PODO.hasNumberOfImpurityAtoms, None) - ): - self.kg.add((sample, triple[1], triple[2])) - - + self.kg.copy_defects(sample, parent_sample) def _add_method( self, job_dict, From 896187d5492244850819e477dffe9f12c4a1cad2 Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 15 Aug 2024 15:10:07 +0200 Subject: [PATCH 14/15] fix self call --- atomrdf/graph.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomrdf/graph.py b/atomrdf/graph.py index 4f06071..a56274b 100644 --- a/atomrdf/graph.py +++ b/atomrdf/graph.py @@ -1287,7 +1287,7 @@ def copy_defects(self, sample, parent_sample): material = list([k[2] for k in self.triples((sample, CMSO.hasMaterial, None))])[0] for defect in parent_defects: - new_defect, defect_triples = self.graph.iterate_and_rename_triples(defect) + new_defect, defect_triples = self.iterate_and_rename_triples(defect) #add the new defect to the new material self.add((material, CMSO.hasDefect, new_defect)) #add the triples to the graph From 917e96a25895d07f6844c73a6cb7b2af9a24a595 Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 15 Aug 2024 15:11:11 +0200 Subject: [PATCH 15/15] =?UTF-8?q?Bump=20version:=200.9.10=20=E2=86=92=200.?= =?UTF-8?q?9.11?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- CITATION.cff | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index b79eb0a..8d3fd5a 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.9.10 +current_version = 0.9.11 commit = True tag = False diff --git a/CITATION.cff b/CITATION.cff index a10dede..20e2c05 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.10 +version: 0.9.11 diff --git a/setup.py b/setup.py index ff182b1..e2d527e 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ setup( name='atomrdf', - version='0.9.10', + version='0.9.11', author='Abril Azocar Guzman, Sarath Menon', author_email='sarath.menon@pyscal.org', description='Ontology based structural manipulation and quering',