diff --git a/docs/source/user_guide/structuredata/user_guide_SData.ipynb b/docs/source/user_guide/structuredata/user_guide_SData.ipynb index 77ee5c5..ae57137 100644 --- a/docs/source/user_guide/structuredata/user_guide_SData.ipynb +++ b/docs/source/user_guide/structuredata/user_guide_SData.ipynb @@ -107,7 +107,7 @@ "output_type": "stream", "text": [ "The whole list of currently supported properties is: \n", - "['cell', 'symbols', 'pbc', 'charge', 'positions', 'mass', 'custom']\n" + "['symbols', 'cell', 'mass', 'charge', 'positions', 'kinds', 'custom', 'pbc']\n" ] } ], @@ -130,7 +130,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 4, @@ -160,7 +160,7 @@ "output_type": "stream", "text": [ "The cell property class: \n", - "parent= value=[[3.5, 0.0, 0.0], [0.0, 3.5, 0.0], [0.0, 0.0, 3.5]] domain='global'\n", + "parent= value=[[3.5, 0.0, 0.0], [0.0, 3.5, 0.0], [0.0, 0.0, 3.5]] domain='global'\n", "\n", "The cell property value: \n", "[[3.5, 0.0, 0.0], [0.0, 3.5, 0.0], [0.0, 0.0, 3.5]]\n", @@ -187,7 +187,7 @@ "output_type": "stream", "text": [ "The positions property class: \n", - "parent= domain='intra-site' value=[[0.0, 0.0, 0.0], [1.5, 1.5, 1.5]]\n", + "parent= domain='intra-site' value=[[0.0, 0.0, 0.0], [1.5, 1.5, 1.5]]\n", "\n", "The positions property value: \n", "[[0.0, 0.0, 0.0], [1.5, 1.5, 1.5]]\n", @@ -214,7 +214,7 @@ "output_type": "stream", "text": [ "Stored properties are: \n", - "['cell', 'pbc', 'symbols', 'positions']\n" + "['symbols', 'cell', 'mass', 'positions', 'pbc']\n" ] } ], @@ -259,7 +259,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -270,7 +270,7 @@ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNotImplementedError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[9], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mstructure\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mproperties\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcell\u001b[49m \u001b[38;5;241m=\u001b[39m [[\u001b[38;5;241m1\u001b[39m,\u001b[38;5;241m2\u001b[39m,\u001b[38;5;241m3\u001b[39m],[\u001b[38;5;241m1\u001b[39m,\u001b[38;5;241m2\u001b[39m,\u001b[38;5;241m3\u001b[39m],[\u001b[38;5;241m1\u001b[39m,\u001b[38;5;241m2\u001b[39m,\u001b[38;5;241m3\u001b[39m]]\n", - "File \u001b[0;32m~/Envs/aiida-muonic/codes/aiida-atomistic/src/aiida_atomistic/data/structure/properties/property_utils.py:112\u001b[0m, in \u001b[0;36mPropertyMixinMetaclass.__new__..\u001b[0;34m(self, pname, pvalue)\u001b[0m\n\u001b[1;32m 106\u001b[0m func_get \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mlambda\u001b[39;00m \u001b[38;5;28mself\u001b[39m, type_hint\u001b[38;5;241m=\u001b[39mtype_hint, attr\u001b[38;5;241m=\u001b[39mattr: \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_template_property(type_hint\u001b[38;5;241m=\u001b[39mtype_hint, attr\u001b[38;5;241m=\u001b[39mattr)\n\u001b[1;32m 108\u001b[0m \u001b[38;5;66;03m# We do not allow to set any property after the creation of the instance: \u001b[39;00m\n\u001b[1;32m 109\u001b[0m \u001b[38;5;66;03m#===> WE CAN DEACTIVATE THE METHOD, using the `allow_no_calls_decorator`.\u001b[39;00m\n\u001b[1;32m 110\u001b[0m \u001b[38;5;66;03m# Here below, we leave it there for now, in case it is needed in the future.\u001b[39;00m\n\u001b[1;32m 111\u001b[0m \u001b[38;5;66;03m#func_set = lambda self, type_hint=type_hint, attr=attr: self._template_property(type_hint=type_hint, attr=attr)\u001b[39;00m\n\u001b[0;32m--> 112\u001b[0m func_set \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mlambda\u001b[39;00m \u001b[38;5;28mself\u001b[39m, pname\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, pvalue\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m: \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_set_property\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpname\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mpvalue\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 113\u001b[0m \u001b[38;5;28msetattr\u001b[39m(\u001b[38;5;28mcls\u001b[39m, attr, \u001b[38;5;28mproperty\u001b[39m(fget\u001b[38;5;241m=\u001b[39mfunc_get,fset\u001b[38;5;241m=\u001b[39mfunc_set))\n\u001b[1;32m 115\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mcls\u001b[39m\n", + "File \u001b[0;32m~/Envs/aiida-muonic/codes/aiida-atomistic/src/aiida_atomistic/data/structure/properties/property_utils.py:113\u001b[0m, in \u001b[0;36mPropertyMixinMetaclass.__new__..\u001b[0;34m(self, pname, pvalue)\u001b[0m\n\u001b[1;32m 107\u001b[0m func_get \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mlambda\u001b[39;00m \u001b[38;5;28mself\u001b[39m, type_hint\u001b[38;5;241m=\u001b[39mtype_hint, attr\u001b[38;5;241m=\u001b[39mattr: \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_template_property(type_hint\u001b[38;5;241m=\u001b[39mtype_hint, attr\u001b[38;5;241m=\u001b[39mattr)\n\u001b[1;32m 109\u001b[0m \u001b[38;5;66;03m# We do not allow to set any property after the creation of the instance: \u001b[39;00m\n\u001b[1;32m 110\u001b[0m \u001b[38;5;66;03m#===> WE CAN DEACTIVATE THE METHOD, using the `allow_no_calls_decorator`.\u001b[39;00m\n\u001b[1;32m 111\u001b[0m \u001b[38;5;66;03m# Here below, we leave it there for now, in case it is needed in the future.\u001b[39;00m\n\u001b[1;32m 112\u001b[0m \u001b[38;5;66;03m#func_set = lambda self, type_hint=type_hint, attr=attr: self._template_property(type_hint=type_hint, attr=attr)\u001b[39;00m\n\u001b[0;32m--> 113\u001b[0m func_set \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mlambda\u001b[39;00m \u001b[38;5;28mself\u001b[39m, pname\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, pvalue\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m: \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_set_property\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpname\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mpvalue\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 114\u001b[0m \u001b[38;5;28msetattr\u001b[39m(\u001b[38;5;28mcls\u001b[39m, attr, \u001b[38;5;28mproperty\u001b[39m(fget\u001b[38;5;241m=\u001b[39mfunc_get,fset\u001b[38;5;241m=\u001b[39mfunc_set))\n\u001b[1;32m 116\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mcls\u001b[39m\n", "File \u001b[0;32m~/Envs/aiida-muonic/codes/aiida-atomistic/src/aiida_atomistic/data/structure/properties/property_utils.py:38\u001b[0m, in \u001b[0;36mallow_no_calls_decorator..wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 35\u001b[0m \u001b[38;5;28mlocals\u001b[39m \u001b[38;5;241m=\u001b[39m frame\u001b[38;5;241m.\u001b[39mf_back\u001b[38;5;241m.\u001b[39mf_locals\n\u001b[1;32m 37\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlocals\u001b[39m\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mself\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m) \u001b[38;5;129;01mis\u001b[39;00m args[\u001b[38;5;241m0\u001b[39m]:\n\u001b[0;32m---> 38\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mNotImplementedError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAfter the initialization, `properties` and its attributes are read-only!\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCalled from this class!\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 40\u001b[0m func(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", "\u001b[0;31mNotImplementedError\u001b[0m: After the initialization, `properties` and its attributes are read-only!" ] @@ -304,7 +304,8 @@ "{'cell': {'value': [[3.5, 0.0, 0.0], [0.0, 3.5, 0.0], [0.0, 0.0, 3.5]]},\n", " 'pbc': {'value': [True, True, True]},\n", " 'positions': {'value': [[0.0, 0.0, 0.0], [1.5, 1.5, 1.5]]},\n", - " 'symbols': {'value': ['Li', 'Li']}}" + " 'symbols': {'value': ['Li', 'Li']},\n", + " 'mass': {'value': [6.941, 6.941]}}" ] }, "execution_count": 9, @@ -323,6 +324,20 @@ "Here below and example where we want to change the dimensionality of the structure: we elongate the cell along Z and we fix the pbc property consistently." ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## The `get_kinds()` method\n", + "\n", + "It is possible to get a list of kinds using the `get_kinds` method. \n", + "This will generate the corresponding predicted kinds for all the properties (the \"intra-site\" ones) \n", + "and then generate the list of global different kinds. \n", + "The default threshold used for each property can be found under the attribute ``\n", + "\n", + "This method should be used in the plugins which requires a kind-based definition of properties, e.g. the aiida-quantumespresso one." + ] + }, { "cell_type": "code", "execution_count": 10, @@ -348,23 +363,9 @@ "print(f\"The cell property value: \\n{new_structure.properties.cell.value}\\n\")" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## The `get_kinds()` method\n", - "\n", - "It is possible to get a list of kinds using the `get_kinds` method. \n", - "This will generate the corresponding predicted kinds for all the properties (the \"intra-site\" ones) \n", - "and then generate the list of global different kinds. \n", - "The default threshold used for each property can be found under the attribute ``\n", - "\n", - "This method should be used in the plugins which requires a kind-based definition of properties, e.g. the aiida-quantumespresso one." - ] - }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -372,7 +373,7 @@ "output_type": "stream", "text": [ "['Li0', 'Li1']\n", - "{'charge': [1.0, 0.0], 'mass': [6.941, 6.941]}\n" + "{'mass': {'value': [6.941, 6.941]}, 'charge': {'value': [1.0, 0.0]}}\n" ] } ], @@ -416,7 +417,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -425,7 +426,7 @@ "0.1" ] }, - "execution_count": 30, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -436,20 +437,20 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "['Li0', 'Li1']\n", - "{'charge': [1.0, 0.0], 'mass': [6.941, 6.941]}\n" + "['Li0', 'Li0']\n", + "{'mass': {'value': [6.941, 6.941]}, 'charge': {'value': [0.0, 0.0]}}\n" ] } ], "source": [ - "kinds, kinds_values = structure.get_kinds(custom_thr={\"charge\":0.6})\n", + "kinds, kinds_values = structure.get_kinds(custom_thr={\"charge\":2})\n", "\n", "print(kinds)\n", "print(kinds_values)" @@ -468,7 +469,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -476,7 +477,7 @@ "output_type": "stream", "text": [ "['Li1', 'Li2', 'Cu1', 'Cu1']\n", - "{'charge': [1.0, 0.0], 'mass': [6.941, 6.941]}\n" + "{'mass': {'value': [6.941, 6.941]}, 'charge': {'value': [1.0, 0.0]}}\n" ] } ], @@ -496,7 +497,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -504,7 +505,7 @@ "output_type": "stream", "text": [ "['Li0', 'Li0']\n", - "{'mass': [6.941, 6.941]}\n" + "{'mass': {'value': [6.941, 6.941]}}\n" ] } ], @@ -514,6 +515,118 @@ "print(kinds)\n", "print(kinds_values)" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is possible to combine the `to_dict` and the `get_kinds` methods, in such a way to have a ready-to-use dictionary with also the kinds, automatically generated:" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'cell': {'value': [[3.5, 0.0, 0.0], [0.0, 3.5, 0.0], [0.0, 0.0, 3.5]]},\n", + " 'pbc': {'value': [True, True, True]},\n", + " 'positions': {'value': [[0.0, 0.0, 0.0], [1.5, 1.5, 1.5]]},\n", + " 'symbols': {'value': ['Li', 'Li']},\n", + " 'mass': {'value': [6.941, 6.941]},\n", + " 'charge': {'value': [0.0, 0.0]},\n", + " 'kinds': {'value': ['Li0', 'Li0']}}" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "new_properties = structure.to_dict(generate_kinds= True, kinds_exclude=['mass'],kinds_thresholds={\"charge\":1.5})\n", + "new_properties" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "structure_with_kinds = StructureData(properties=new_properties)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Kinds(parent=, domain='intra-site', value=['Li0', 'Li0'])" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "structure_with_kinds.properties.kinds" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "structure_with_kinds.store()" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "loaded_structure_kinds = orm.load_node(structure_with_kinds.pk)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Kinds(parent=, domain='intra-site', value=['Li0', 'Li0'])" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "loaded_structure_kinds.properties.kinds" + ] } ], "metadata": { diff --git a/src/aiida_atomistic/data/structure/__init__.py b/src/aiida_atomistic/data/structure/__init__.py index 434a2de..fdc454f 100644 --- a/src/aiida_atomistic/data/structure/__init__.py +++ b/src/aiida_atomistic/data/structure/__init__.py @@ -757,10 +757,19 @@ def __init__( if pymatgen_molecule is not None: self.set_pymatgen_molecule(pymatgen_molecule) - + + # We initialize the PropertyCollector to have the validation of the properties. + elif not properties: + # dummy to have the StructureData().properties.get_supported_properties() + properties = { + 'positions':{'value':[[0,0,0]]}, + 'cell':{'value':[[0,0,0]]*3}, + 'symbols':{'value':['H']} + } + self._properties = PropertyCollector(parent=self, properties=properties) else: # Private property attribute - self._property_attribute = PropertyCollector(parent=self, properties=properties) + self._properties = PropertyCollector(parent=self, properties=properties) ## RM else: ## RM if cell is None: @@ -784,13 +793,28 @@ def properties(self): def properties(self,value): raise AttributeError("After the initialization, `properties` is a read-only attribute") - def to_dict(self): + def to_dict(self, generate_kinds: bool = False, kinds_thresholds: dict = {}, kinds_exclude: list = []): """ - Returns a dictionary with the properties defined. - Used to generate new StructureData with some changed/updated properties. + Args: + generate_kinds (bool, optional): includes also the kinds in the properties, using the automatically generated ones via the `get_kinds` method. + kinds_thresholds (dict, optional): dictionary with the custom threshold for given properties (key: property, value: thr). + if not provided, we fallback into the default threshold define in the property class. + kinds_exclude (list, optional): list of properties to be excluded in the kind determination. + + Returns: + structure_dictionary: a dictionary with the properties defined. Used to generate new StructureData with some changed/updated properties. """ - return copy.deepcopy(self.base.attributes.get('_property_attributes')) - + + structure_dictionary = copy.deepcopy(self.base.attributes.get('_property_attributes')) + + if generate_kinds: + kinds, new_properties_value = self.get_kinds(exclude=kinds_exclude, custom_thr=kinds_thresholds) + + structure_dictionary['kinds'] = {'value':kinds} + for key, new_value in new_properties_value.items(): # can also use recursive_merge here, to check if cyclic import problems + structure_dictionary[key]['value'] = new_value['value'] + + return structure_dictionary def get_kinds(self, kind_tags=[], exclude=[], custom_thr={}): """Get the list of kinds, taking into account all the properties. @@ -828,7 +852,12 @@ def get_kinds(self, kind_tags=[], exclude=[], custom_thr={}): import numpy as np import copy - symbols = self.properties.symbols.value + # cannot do properties.symbols.value due to recursion problem if called in Kinds: + # if I call properties, this will again reinitialize the properties attribute and so on. + # should be this: + # symbols = self.base.attributes.get("_property_attributes")['symbols']['value'] + # However, for now I do not let the kinds to be automatically generated when we initialise the structure: + symbols = self.properties.symbols.value if len(kind_tags) == 0: kind_tags = [None]*len(symbols) @@ -839,12 +868,14 @@ def get_kinds(self, kind_tags=[], exclude=[], custom_thr={}): prop = getattr(self.properties,single_property) if prop.domain == "intra-site" and not single_property in ["symbols","positions"]+exclude: thr = custom_thr.get(single_property, None) + kind_values[single_property] = {} # for this if, refer to the description of the `to_kinds` method of the IntraSiteProperty class. if not None in kind_tags: thr = 0 kinds_per_property = prop.to_kinds(thr=thr) kind_properties.append(kinds_per_property[0]) - kind_values[single_property] = kinds_per_property[1].tolist() + # I prefer to store again under the key 'value', may be useful in the future + kind_values[single_property]['value'] = kinds_per_property[1].tolist() k = np.array(kind_properties) k = k.T diff --git a/src/aiida_atomistic/data/structure/from_atomistic_to_orm.ipynb b/src/aiida_atomistic/data/structure/from_atomistic_to_orm.ipynb new file mode 100644 index 0000000..b852bc8 --- /dev/null +++ b/src/aiida_atomistic/data/structure/from_atomistic_to_orm.ipynb @@ -0,0 +1,498 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[93m\u001b[1mWarning\u001b[0m: \u001b[22mYou are currently using a post release development version of AiiDA: 2.4.0.post0\u001b[0m\n", + "\u001b[93m\u001b[1mWarning\u001b[0m: \u001b[22mBe aware that this is not recommended for production and is not officially supported.\u001b[0m\n", + "\u001b[93m\u001b[1mWarning\u001b[0m: \u001b[22mDatabases used with this version may not be compatible with future releases of AiiDA\u001b[0m\n", + "\u001b[93m\u001b[1mWarning\u001b[0m: \u001b[22mas you might not be able to automatically migrate your data.\n", + "\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "Profile" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from aiida import orm, load_profile\n", + "load_profile()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Performance test aorm.StructureData\n", + "\n", + "This is a playground to develop the get_kinds method... the problem here is to have the property value unified." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from aiida_atomistic.data.structure import StructureData" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "properties = {\n", + " \"cell\":{\"value\":[[1.0,0,0],[0,1,0],[0,0,1]]},\n", + " \"pbc\":{\"value\":[True,False,True]},\n", + " \"positions\":{\n", + " \"value\":[[1,1,1],[2,3,3],[3,4,5],[1,2,3]],\n", + " },\n", + " \"symbols\":{\"value\":[\"He\",\"Cu\",\"He\",\"He\"]},\n", + " #\"mass\":{\"value\":[1.551,9,1.5512,2],},\n", + " \"mass\":{\"value\":None,},\n", + " \"charge\":{\"value\":[1,0,1,0]}\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "structure = StructureData(properties = properties)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['cell', 'symbols', 'charge', 'pbc', 'positions', 'mass']" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "structure.properties.get_stored_properties()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'cell': {'value': [[1.0, 0, 0], [0, 1, 0], [0, 0, 1]]},\n", + " 'pbc': {'value': [True, False, True]},\n", + " 'positions': {'value': [[1, 1, 1], [2, 3, 3], [3, 4, 5], [1, 2, 3]]},\n", + " 'symbols': {'value': ['He', 'Cu', 'He', 'He']},\n", + " 'mass': {'value': [4.002602, 63.546, 4.002602, 4.002602]},\n", + " 'charge': {'value': [1, 0, 1, 0]}}" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "structure.to_dict()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[1.0, 1.0, 1.0], [2.0, 3.0, 3.0], [3.0, 4.0, 5.0], [1.0, 2.0, 3.0]]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "structure.properties.positions.value" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(structure.properties.positions.value)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Symbols(parent=, domain='intra-site', value=['He', 'Cu', 'He', 'He'])" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "structure.properties.symbols " + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'cell': {'value': [[1.0, 0, 0], [0, 1, 0], [0, 0, 1]]},\n", + " 'pbc': {'value': [True, False, True]},\n", + " 'positions': {'value': [[1, 1, 1], [2, 3, 3], [3, 4, 5], [1, 2, 3]]},\n", + " 'symbols': {'value': ['He', 'Cu', 'He', 'He']},\n", + " 'mass': {'value': [4.002602, 63.546, 4.002602, 4.002602]},\n", + " 'charge': {'value': [1, 0, 1, 0]}}" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "structure.base.attributes.get('_property_attributes')" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'cell': {'value': [[1.0, 0, 0], [0, 1, 0], [0, 0, 1]]},\n", + " 'pbc': {'value': [True, False, True]},\n", + " 'positions': {'value': [[1, 1, 1], [2, 3, 3], [3, 4, 5], [1, 2, 3]]},\n", + " 'symbols': {'value': ['He', 'Cu', 'He', 'He']},\n", + " 'mass': {'value': [4.002602, 63.546, 4.002602, 4.002602]},\n", + " 'charge': {'value': [1, 0, 1, 0]}}" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "structure.to_dict()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[4.002602, 63.546, 4.002602, 4.002602]" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "structure.properties.mass.value" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.001" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "structure.properties.mass.default_kind_threshold" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(array([0, 1, 0, 0]), array([ 4.002602, 63.546 , 4.002602, 4.002602]))" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# In principle this is used internally, not to be used externally... consider to make it \"private\".\n", + "structure.properties.mass.to_kinds(thr = 0.1,)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(array([1, 0, 1, 0]), array([1., 0., 1., 0.]))" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "structure.properties.charge.to_kinds(thr = 0.1,)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(['He2', 'Cu1', 'He2', 'He3'],\n", + " {'charge': [1.0, 0.0, 1.0, 0.0],\n", + " 'mass': [4.002602, 63.546, 4.002602, 4.002602]})" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# seems similar to the old `get_kind` method... consider to delete the older method.\n", + "structure.get_kinds()" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[4.002602, 63.546, 4.002602, 4.002602]" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "structure.properties.mass.value" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1.0, 0.0, 1.0, 0.0]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "structure.properties.charge.value" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "overriding tags:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "sd = orm.StructureData()" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [], + "source": [ + "sd.append_atom(position=[1,2,3],symbols=['He'])" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "ename": "LinAlgError", + "evalue": "Singular matrix", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mLinAlgError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[28], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43msd\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_pymatgen\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/Envs/aiida-muonic/codes/aiida-core/aiida/orm/nodes/data/structure.py:1267\u001b[0m, in \u001b[0;36mStructureData.get_pymatgen\u001b[0;34m(self, **kwargs)\u001b[0m\n\u001b[1;32m 1250\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mget_pymatgen\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 1251\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 1252\u001b[0m \u001b[38;5;124;03m Get pymatgen object. Returns Structure for structures with\u001b[39;00m\n\u001b[1;32m 1253\u001b[0m \u001b[38;5;124;03m periodic boundary conditions (in three dimensions) and Molecule\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 1265\u001b[0m \u001b[38;5;124;03m of earlier versions may cause errors).\u001b[39;00m\n\u001b[1;32m 1266\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m-> 1267\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get_object_pymatgen\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/Envs/aiida-muonic/codes/aiida-core/aiida/orm/nodes/data/structure.py:1805\u001b[0m, in \u001b[0;36mStructureData._get_object_pymatgen\u001b[0;34m(self, **kwargs)\u001b[0m\n\u001b[1;32m 1793\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 1794\u001b[0m \u001b[38;5;124;03mConverts\u001b[39;00m\n\u001b[1;32m 1795\u001b[0m \u001b[38;5;124;03m:py:class:`StructureData `\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 1802\u001b[0m \u001b[38;5;124;03m of earlier versions may cause errors).\u001b[39;00m\n\u001b[1;32m 1803\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 1804\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mpbc \u001b[38;5;241m==\u001b[39m (\u001b[38;5;28;01mTrue\u001b[39;00m, \u001b[38;5;28;01mTrue\u001b[39;00m, \u001b[38;5;28;01mTrue\u001b[39;00m):\n\u001b[0;32m-> 1805\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_get_object_pymatgen_structure\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1807\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_get_object_pymatgen_molecule(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", + "File \u001b[0;32m~/Envs/aiida-muonic/codes/aiida-core/aiida/orm/nodes/data/structure.py:1873\u001b[0m, in \u001b[0;36mStructureData._get_object_pymatgen_structure\u001b[0;34m(self, **kwargs)\u001b[0m\n\u001b[1;32m 1870\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mUnrecognized parameters passed to pymatgen converter: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mkwargs\u001b[38;5;241m.\u001b[39mkeys()\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 1872\u001b[0m positions \u001b[38;5;241m=\u001b[39m [\u001b[38;5;28mlist\u001b[39m(x\u001b[38;5;241m.\u001b[39mposition) \u001b[38;5;28;01mfor\u001b[39;00m x \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msites]\n\u001b[0;32m-> 1873\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mStructure\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcell\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mspecies\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mpositions\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcoords_are_cartesian\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43madditional_kwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/Envs/aiida-muonic/lib/python3.10/site-packages/pymatgen/core/structure.py:3534\u001b[0m, in \u001b[0;36mStructure.__init__\u001b[0;34m(self, lattice, species, coords, charge, validate_proximity, to_unit_cell, coords_are_cartesian, site_properties)\u001b[0m\n\u001b[1;32m 3489\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__init__\u001b[39m(\n\u001b[1;32m 3490\u001b[0m \u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m 3491\u001b[0m lattice: ArrayLike \u001b[38;5;241m|\u001b[39m Lattice,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 3498\u001b[0m site_properties: \u001b[38;5;28mdict\u001b[39m \u001b[38;5;241m|\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 3499\u001b[0m ):\n\u001b[1;32m 3500\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 3501\u001b[0m \u001b[38;5;124;03m Create a periodic structure.\u001b[39;00m\n\u001b[1;32m 3502\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 3532\u001b[0m \u001b[38;5;124;03m fractional_coords. Defaults to None for no properties.\u001b[39;00m\n\u001b[1;32m 3533\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m-> 3534\u001b[0m \u001b[38;5;28;43msuper\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[38;5;21;43m__init__\u001b[39;49m\u001b[43m(\u001b[49m\n\u001b[1;32m 3535\u001b[0m \u001b[43m \u001b[49m\u001b[43mlattice\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3536\u001b[0m \u001b[43m \u001b[49m\u001b[43mspecies\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3537\u001b[0m \u001b[43m \u001b[49m\u001b[43mcoords\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3538\u001b[0m \u001b[43m \u001b[49m\u001b[43mcharge\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcharge\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3539\u001b[0m \u001b[43m \u001b[49m\u001b[43mvalidate_proximity\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mvalidate_proximity\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3540\u001b[0m \u001b[43m \u001b[49m\u001b[43mto_unit_cell\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mto_unit_cell\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3541\u001b[0m \u001b[43m \u001b[49m\u001b[43mcoords_are_cartesian\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcoords_are_cartesian\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3542\u001b[0m \u001b[43m \u001b[49m\u001b[43msite_properties\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msite_properties\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3543\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 3545\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sites: \u001b[38;5;28mlist\u001b[39m[PeriodicSite] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlist\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sites)\n", + "File \u001b[0;32m~/Envs/aiida-muonic/lib/python3.10/site-packages/pymatgen/core/structure.py:900\u001b[0m, in \u001b[0;36mIStructure.__init__\u001b[0;34m(self, lattice, species, coords, charge, validate_proximity, to_unit_cell, coords_are_cartesian, site_properties)\u001b[0m\n\u001b[1;32m 897\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m site_properties:\n\u001b[1;32m 898\u001b[0m prop \u001b[38;5;241m=\u001b[39m {key: val[idx] \u001b[38;5;28;01mfor\u001b[39;00m key, val \u001b[38;5;129;01min\u001b[39;00m site_properties\u001b[38;5;241m.\u001b[39mitems()}\n\u001b[0;32m--> 900\u001b[0m site \u001b[38;5;241m=\u001b[39m \u001b[43mPeriodicSite\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 901\u001b[0m \u001b[43m \u001b[49m\u001b[43mspecie\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 902\u001b[0m \u001b[43m \u001b[49m\u001b[43mcoords\u001b[49m\u001b[43m[\u001b[49m\u001b[43midx\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 903\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_lattice\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 904\u001b[0m \u001b[43m \u001b[49m\u001b[43mto_unit_cell\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 905\u001b[0m \u001b[43m \u001b[49m\u001b[43mcoords_are_cartesian\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcoords_are_cartesian\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 906\u001b[0m \u001b[43m \u001b[49m\u001b[43mproperties\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mprop\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# type: ignore\u001b[39;49;00m\n\u001b[1;32m 907\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 908\u001b[0m sites\u001b[38;5;241m.\u001b[39mappend(site)\n\u001b[1;32m 909\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sites: \u001b[38;5;28mtuple\u001b[39m[PeriodicSite, \u001b[38;5;241m.\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;241m.\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mtuple\u001b[39m(sites)\n", + "File \u001b[0;32m~/Envs/aiida-muonic/lib/python3.10/site-packages/pymatgen/core/sites.py:312\u001b[0m, in \u001b[0;36mPeriodicSite.__init__\u001b[0;34m(self, species, coords, lattice, to_unit_cell, coords_are_cartesian, properties, skip_checks)\u001b[0m\n\u001b[1;32m 278\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__init__\u001b[39m(\n\u001b[1;32m 279\u001b[0m \u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m 280\u001b[0m species: SpeciesLike \u001b[38;5;241m|\u001b[39m CompositionLike,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 286\u001b[0m skip_checks: \u001b[38;5;28mbool\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m,\n\u001b[1;32m 287\u001b[0m ):\n\u001b[1;32m 288\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 289\u001b[0m \u001b[38;5;124;03m Create a periodic site.\u001b[39;00m\n\u001b[1;32m 290\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 310\u001b[0m \u001b[38;5;124;03m controlled manner and speed is desired.\u001b[39;00m\n\u001b[1;32m 311\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m--> 312\u001b[0m frac_coords \u001b[38;5;241m=\u001b[39m \u001b[43mlattice\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_fractional_coords\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcoords\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;28;01mif\u001b[39;00m coords_are_cartesian \u001b[38;5;28;01melse\u001b[39;00m coords\n\u001b[1;32m 314\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m to_unit_cell:\n\u001b[1;32m 315\u001b[0m frac_coords \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39marray([np\u001b[38;5;241m.\u001b[39mmod(f, \u001b[38;5;241m1\u001b[39m) \u001b[38;5;28;01mif\u001b[39;00m p \u001b[38;5;28;01melse\u001b[39;00m f \u001b[38;5;28;01mfor\u001b[39;00m p, f \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mzip\u001b[39m(lattice\u001b[38;5;241m.\u001b[39mpbc, frac_coords)]) \u001b[38;5;66;03m# type: ignore\u001b[39;00m\n", + "File \u001b[0;32m~/Envs/aiida-muonic/lib/python3.10/site-packages/pymatgen/core/lattice.py:181\u001b[0m, in \u001b[0;36mLattice.get_fractional_coords\u001b[0;34m(self, cart_coords)\u001b[0m\n\u001b[1;32m 171\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mget_fractional_coords\u001b[39m(\u001b[38;5;28mself\u001b[39m, cart_coords: ArrayLike) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m np\u001b[38;5;241m.\u001b[39mndarray:\n\u001b[1;32m 172\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 173\u001b[0m \u001b[38;5;124;03m Returns the fractional coordinates given Cartesian coordinates.\u001b[39;00m\n\u001b[1;32m 174\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 179\u001b[0m \u001b[38;5;124;03m Fractional coordinates.\u001b[39;00m\n\u001b[1;32m 180\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m--> 181\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m np\u001b[38;5;241m.\u001b[39mdot(cart_coords, \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minv_matrix\u001b[49m)\n", + "File \u001b[0;32m~/Envs/aiida-muonic/lib/python3.10/site-packages/pymatgen/core/lattice.py:150\u001b[0m, in \u001b[0;36mLattice.inv_matrix\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 148\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Inverse of lattice matrix.\"\"\"\u001b[39;00m\n\u001b[1;32m 149\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_inv_matrix \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m--> 150\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_inv_matrix \u001b[38;5;241m=\u001b[39m \u001b[43minv\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_matrix\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 151\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_inv_matrix\u001b[38;5;241m.\u001b[39msetflags(write\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m)\n\u001b[1;32m 152\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_inv_matrix\n", + "File \u001b[0;32m<__array_function__ internals>:180\u001b[0m, in \u001b[0;36minv\u001b[0;34m(*args, **kwargs)\u001b[0m\n", + "File \u001b[0;32m~/Envs/aiida-muonic/lib/python3.10/site-packages/numpy/linalg/linalg.py:552\u001b[0m, in \u001b[0;36minv\u001b[0;34m(a)\u001b[0m\n\u001b[1;32m 550\u001b[0m signature \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mD->D\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m isComplexType(t) \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124md->d\u001b[39m\u001b[38;5;124m'\u001b[39m\n\u001b[1;32m 551\u001b[0m extobj \u001b[38;5;241m=\u001b[39m get_linalg_error_extobj(_raise_linalgerror_singular)\n\u001b[0;32m--> 552\u001b[0m ainv \u001b[38;5;241m=\u001b[39m \u001b[43m_umath_linalg\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minv\u001b[49m\u001b[43m(\u001b[49m\u001b[43ma\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43msignature\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msignature\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mextobj\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mextobj\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 553\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m wrap(ainv\u001b[38;5;241m.\u001b[39mastype(result_t, copy\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m))\n", + "File \u001b[0;32m~/Envs/aiida-muonic/lib/python3.10/site-packages/numpy/linalg/linalg.py:89\u001b[0m, in \u001b[0;36m_raise_linalgerror_singular\u001b[0;34m(err, flag)\u001b[0m\n\u001b[1;32m 88\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_raise_linalgerror_singular\u001b[39m(err, flag):\n\u001b[0;32m---> 89\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m LinAlgError(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mSingular matrix\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", + "\u001b[0;31mLinAlgError\u001b[0m: Singular matrix" + ] + } + ], + "source": [ + "sd.get_pymatgen()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import timeit\n", + "def create_f():\n", + " structure = StructureData(properties = properties)\n", + "time = timeit.timeit(create_f)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 4 µs, sys: 2 µs, total: 6 µs\n", + "Wall time: 12.2 µs\n" + ] + } + ], + "source": [ + "time" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "orm. " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "aiida-muonic", + "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.10.11" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/src/aiida_atomistic/data/structure/get_kinds.ipynb b/src/aiida_atomistic/data/structure/get_kinds.ipynb deleted file mode 100644 index c2d85fc..0000000 --- a/src/aiida_atomistic/data/structure/get_kinds.ipynb +++ /dev/null @@ -1,590 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[93m\u001b[1mWarning\u001b[0m: \u001b[22mYou are currently using a post release development version of AiiDA: 2.4.0.post0\u001b[0m\n", - "\u001b[93m\u001b[1mWarning\u001b[0m: \u001b[22mBe aware that this is not recommended for production and is not officially supported.\u001b[0m\n", - "\u001b[93m\u001b[1mWarning\u001b[0m: \u001b[22mDatabases used with this version may not be compatible with future releases of AiiDA\u001b[0m\n", - "\u001b[93m\u001b[1mWarning\u001b[0m: \u001b[22mas you might not be able to automatically migrate your data.\n", - "\u001b[0m\n" - ] - }, - { - "data": { - "text/plain": [ - "Profile" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from aiida import orm, load_profile\n", - "load_profile()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# The get_kinds methods for intra-site properties and float values\n", - "\n", - "This is a playground to develop the get_kinds method... the problem here is to have the property value unified." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "from aiida_atomistic.data.structure import StructureData" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [], - "source": [ - "properties = {\n", - " \"cell\":{\"value\":[[1.0,0,0],[0,1,0],[0,0,1]]},\n", - " \"pbc\":{\"value\":[True,False,True]},\n", - " \"positions\":{\n", - " \"value\":[[1,1,1],[2,3,3],[3,4,5],[1,2,3]],\n", - " },\n", - " \"symbols\":{\"value\":[\"He\",\"Cu\",\"He\",\"He\"]},\n", - " #\"mass\":{\"value\":[1.551,9,1.5512,2],},\n", - " \"mass\":{\"value\":None,},\n", - " \"charge\":{\"value\":[1,0,1,0]}\n", - " }" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "ename": "ValidationError", - "evalue": "1 validation error for Pbc\nvalue\n ensure this value has at most 3 items (type=value_error.list.max_items; limit_value=3)", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mValidationError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[30], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m structure \u001b[38;5;241m=\u001b[39m \u001b[43mStructureData\u001b[49m\u001b[43m(\u001b[49m\u001b[43mproperties\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[43mproperties\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/Envs/aiida-muonic/codes/aiida-atomistic/src/aiida_atomistic/data/structure/__init__.py:763\u001b[0m, in \u001b[0;36mStructureData.__init__\u001b[0;34m(self, ase, pymatgen, pymatgen_structure, pymatgen_molecule, properties, **kwargs)\u001b[0m\n\u001b[1;32m 759\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mset_pymatgen_molecule(pymatgen_molecule)\n\u001b[1;32m 761\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 762\u001b[0m \u001b[38;5;66;03m# Private property attribute\u001b[39;00m\n\u001b[0;32m--> 763\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_property_attribute \u001b[38;5;241m=\u001b[39m \u001b[43mPropertyCollector\u001b[49m\u001b[43m(\u001b[49m\u001b[43mparent\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mproperties\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mproperties\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/Envs/aiida-muonic/codes/aiida-atomistic/src/aiida_atomistic/data/structure/properties/__init__.py:100\u001b[0m, in \u001b[0;36mPropertyCollector.__init__\u001b[0;34m(self, parent, properties)\u001b[0m\n\u001b[1;32m 97\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_parent\u001b[38;5;241m.\u001b[39mis_stored:\n\u001b[1;32m 98\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_parent\u001b[38;5;241m.\u001b[39mbase\u001b[38;5;241m.\u001b[39mattributes\u001b[38;5;241m.\u001b[39mset(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m_property_attributes\u001b[39m\u001b[38;5;124m'\u001b[39m,\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_property_attributes)\n\u001b[0;32m--> 100\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_inspect_properties\u001b[49m\u001b[43m(\u001b[49m\u001b[43mproperties\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/Envs/aiida-muonic/codes/aiida-atomistic/src/aiida_atomistic/data/structure/properties/__init__.py:142\u001b[0m, in \u001b[0;36mPropertyCollector._inspect_properties\u001b[0;34m(self, properties)\u001b[0m\n\u001b[1;32m 134\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 135\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 136\u001b[0m \u001b[38;5;124;03m Using the pydantic validation:\u001b[39;00m\n\u001b[1;32m 137\u001b[0m \u001b[38;5;124;03m the following `getattr` call is done as we want to initialise the properties, in such a way to have `pydantic` validation.\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 140\u001b[0m \u001b[38;5;124;03m The fact is that the `PropertyMixinMetaclass` only define the fget and fset methods, without using them.\u001b[39;00m\n\u001b[1;32m 141\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m--> 142\u001b[0m \u001b[38;5;28;43mgetattr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43mpname\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/Envs/aiida-muonic/codes/aiida-atomistic/src/aiida_atomistic/data/structure/properties/property_utils.py:107\u001b[0m, in \u001b[0;36mPropertyMixinMetaclass.__new__..\u001b[0;34m(self, type_hint, attr)\u001b[0m\n\u001b[1;32m 105\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28missubclass\u001b[39m(type_hint, BaseProperty)\n\u001b[1;32m 106\u001b[0m \u001b[38;5;28mcls\u001b[39m\u001b[38;5;241m.\u001b[39m_valid_properties\u001b[38;5;241m.\u001b[39madd(attr)\n\u001b[0;32m--> 107\u001b[0m func_get \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mlambda\u001b[39;00m \u001b[38;5;28mself\u001b[39m, type_hint\u001b[38;5;241m=\u001b[39mtype_hint, attr\u001b[38;5;241m=\u001b[39mattr: \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_template_property\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtype_hint\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtype_hint\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mattr\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mattr\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 109\u001b[0m \u001b[38;5;66;03m# We do not allow to set any property after the creation of the instance: \u001b[39;00m\n\u001b[1;32m 110\u001b[0m \u001b[38;5;66;03m#===> WE CAN DEACTIVATE THE METHOD, using the `allow_no_calls_decorator`.\u001b[39;00m\n\u001b[1;32m 111\u001b[0m \u001b[38;5;66;03m# Here below, we leave it there for now, in case it is needed in the future.\u001b[39;00m\n\u001b[1;32m 112\u001b[0m \u001b[38;5;66;03m#func_set = lambda self, type_hint=type_hint, attr=attr: self._template_property(type_hint=type_hint, attr=attr)\u001b[39;00m\n\u001b[1;32m 113\u001b[0m func_set \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mlambda\u001b[39;00m \u001b[38;5;28mself\u001b[39m, pname\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, pvalue\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m: \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_set_property(pname, pvalue)\n", - "File \u001b[0;32m~/Envs/aiida-muonic/codes/aiida-atomistic/src/aiida_atomistic/data/structure/properties/property_utils.py:124\u001b[0m, in \u001b[0;36mHasPropertyMixin._template_property\u001b[0;34m(self, type_hint, attr)\u001b[0m\n\u001b[1;32m 122\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_template_property\u001b[39m(\u001b[38;5;28mself\u001b[39m, type_hint, attr):\n\u001b[0;32m--> 124\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mtype_hint\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 125\u001b[0m \u001b[43m \u001b[49m\u001b[43mparent\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_parent\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 126\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_property_attribute\u001b[49m\u001b[43m(\u001b[49m\u001b[43mattr\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 127\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 128\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m'''except: \u001b[39;00m\n\u001b[1;32m 129\u001b[0m \u001b[38;5;124;03m # In case we initialise to\u001b[39;00m\n\u001b[1;32m 130\u001b[0m \u001b[38;5;124;03m return type_hint(\u001b[39;00m\n\u001b[1;32m 131\u001b[0m \u001b[38;5;124;03m parent=self._parent,\u001b[39;00m\n\u001b[1;32m 132\u001b[0m \u001b[38;5;124;03m )'''\u001b[39;00m\n", - "File \u001b[0;32m~/Envs/aiida-muonic/lib/python3.10/site-packages/pydantic/main.py:341\u001b[0m, in \u001b[0;36mpydantic.main.BaseModel.__init__\u001b[0;34m()\u001b[0m\n", - "\u001b[0;31mValidationError\u001b[0m: 1 validation error for Pbc\nvalue\n ensure this value has at most 3 items (type=value_error.list.max_items; limit_value=3)" - ] - } - ], - "source": [ - "structure = StructureData(properties = properties)" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['charge', 'positions', 'pbc', 'symbols', 'mass', 'cell']" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "structure.properties.get_stored_properties()" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'cell': {'value': [[1.0, 0, 0], [0, 1, 0], [0, 0, 1]]},\n", - " 'pbc': {'value': [True, False, True]},\n", - " 'positions': {'value': [[1, 1, 1], [2, 3, 3], [3, 4, 5], [1, 2, 3]]},\n", - " 'symbols': {'value': ['He', 'Cu', 'He', 'He']},\n", - " 'mass': {'value': [4.002602, 63.546, 4.002602, 4.002602]},\n", - " 'charge': {'value': [1, 0, 1, 0]}}" - ] - }, - "execution_count": 28, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "structure.to_dict()" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "structure.store()" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "s = orm.load_node(structure.pk)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Charge(parent=, domain='intra-site', value=[1.0, 0.0, 1.0, 0.0], default_kind_threshold=0.1)" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "s.properties.charge" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "s = orm.load_node(structure.pk)" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'pbc': {'value': [True, True, True]},\n", - " 'cell': {'value': [[1.0, 0, 0], [0, 1, 0], [0, 0, 1]]},\n", - " 'mass': {'value': [4.002602, 63.546, 4.002602, 4.002602]},\n", - " 'charge': {'value': [1, 0, 1, 0]},\n", - " 'symbols': {'value': ['He', 'Cu', 'He', 'He']},\n", - " 'positions': {'value': [[1, 1, 1], [2, 3, 3], [3, 4, 5], [1, 2, 3]]}}" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "s.to_dict()" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "#s.properties.positions" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "len(structure.properties.positions.value)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Symbols(parent=, domain='intra-site', value=['He', 'Cu', 'He', 'He'])" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "structure.properties.symbols " - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'pbc': {'value': [True, True, True]},\n", - " 'cell': {'value': [[1.0, 0, 0], [0, 1, 0], [0, 0, 1]]},\n", - " 'mass': {'value': [4.002602, 63.546, 4.002602, 4.002602]},\n", - " 'charge': {'value': [1, 0, 1, 0]},\n", - " 'symbols': {'value': ['He', 'Cu', 'He', 'He']},\n", - " 'positions': {'value': [[1, 1, 1], [2, 3, 3], [3, 4, 5], [1, 2, 3]]}}" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "structure.base.attributes.get('_property_attributes')" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'pbc': {'value': [True, True, True]},\n", - " 'cell': {'value': [[1.0, 0, 0], [0, 1, 0], [0, 0, 1]]},\n", - " 'mass': {'value': [4.002602, 63.546, 4.002602, 4.002602]},\n", - " 'charge': {'value': [1, 0, 1, 0]},\n", - " 'symbols': {'value': ['He', 'Cu', 'He', 'He']},\n", - " 'positions': {'value': [[1, 1, 1], [2, 3, 3], [3, 4, 5], [1, 2, 3]]}}" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "structure.to_dict()\n" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[4.002602, 63.546, 4.002602, 4.002602]" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "structure.properties.mass.value" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0.001" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "structure.properties.mass.default_kind_threshold" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(array([0, 1, 0, 0]), array([ 4.002602, 63.546 , 4.002602, 4.002602]))" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# In principle this is used internally, not to be used externally... consider to make it \"private\".\n", - "structure.properties.mass.to_kinds(thr = 0.1,)" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(array([1, 0, 1, 0]), array([1., 0., 1., 0.]))" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "structure.properties.charge.to_kinds(thr = 0.1,)" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(['He2', 'Cu1', 'He2', 'He3'],\n", - " {'charge': [1.0, 0.0, 1.0, 0.0],\n", - " 'mass': [4.002602, 63.546, 4.002602, 4.002602]})" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# seems similar to the old `get_kind` method... consider to delete the older method.\n", - "structure.get_kinds()" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[4.002602, 63.546, 4.002602, 4.002602]" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "structure.properties.mass.value" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[1.0, 0.0, 1.0, 0.0]" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "structure.properties.charge.value" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'get_kinds' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[24], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# PROBLEM in to_kinds... midvalue...\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m \u001b[43mget_kinds\u001b[49m(structure, custom_thr\u001b[38;5;241m=\u001b[39m{\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcharge\u001b[39m\u001b[38;5;124m\"\u001b[39m:\u001b[38;5;241m0.5\u001b[39m})\n", - "\u001b[0;31mNameError\u001b[0m: name 'get_kinds' is not defined" - ] - } - ], - "source": [ - "# PROBLEM in to_kinds... midvalue...\n", - "get_kinds(structure, custom_thr={\"charge\":0.5})" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "overriding tags:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "He\n", - "Cu\n", - "He\n", - "He\n" - ] - }, - { - "data": { - "text/plain": [ - "(['He0', 'He2', 'He6', 'He3'],\n", - " {'mass': [1.551, 9.0, 1.551, 2.0], 'charge': [0.9, 0.0, 0.9, 0.0]})" - ] - }, - "execution_count": 35, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "get_kinds(structure,kind_tags=[\"He0\",\"He2\",None,None])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "He\n", - "Cu\n", - "He\n", - "He\n" - ] - }, - { - "data": { - "text/plain": [ - "(['He2', 'Cu1', 'He2', 'He3'],\n", - " {'mass': [1.551, 9.0, 1.551, 2.0], 'charge': [0.9, 0.0, 0.9, 0.0]})" - ] - }, - "execution_count": 36, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "get_kinds(structure)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "aiida-muonic", - "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.10.11" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/src/aiida_atomistic/data/structure/performance_test.ipynb b/src/aiida_atomistic/data/structure/performance_test.ipynb new file mode 100644 index 0000000..7ee2c69 --- /dev/null +++ b/src/aiida_atomistic/data/structure/performance_test.ipynb @@ -0,0 +1,380 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[93m\u001b[1mWarning\u001b[0m: \u001b[22mYou are currently using a post release development version of AiiDA: 2.4.0.post0\u001b[0m\n", + "\u001b[93m\u001b[1mWarning\u001b[0m: \u001b[22mBe aware that this is not recommended for production and is not officially supported.\u001b[0m\n", + "\u001b[93m\u001b[1mWarning\u001b[0m: \u001b[22mDatabases used with this version may not be compatible with future releases of AiiDA\u001b[0m\n", + "\u001b[93m\u001b[1mWarning\u001b[0m: \u001b[22mas you might not be able to automatically migrate your data.\n", + "\u001b[0m\n" + ] + } + ], + "source": [ + "from aiida import orm, load_profile\n", + "load_profile()\n", + "\n", + "from aiida_atomistic.data.structure import StructureData\n", + "\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from aiida_atomistic.data.structure import StructureData" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Performance test atomistic.StructureData vs orm.StructureData\n", + "\n", + "- Increase linearly the number of atoms in both cases(2D plot), \n", + "- Then see how the scaling changes if I also defined more and more related properties (2D countour plot?)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "properties = {\n", + " \"cell\":{\"value\":[[1,0,0],[0,1,0],[0,0,1]]},\n", + " \"positions\":{\"value\":[[1,1,1]]},\n", + " \"symbols\":{\"value\":[\"He\"]},\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "structure = StructureData(properties = properties)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['pbc', 'cell', 'symbols', 'mass', 'positions']" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "structure.properties.get_stored_properties()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "legacy = orm.StructureData(cell=properties['cell']['value'])\n", + "for position,symbol in list(zip(properties['positions']['value'],properties['symbols']['value'])):\n", + " legacy.append_atom(position=position,symbols=symbol)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test 1. only increasing number of atoms." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "def generate_simple_atomistic(properties):\n", + " return StructureData(properties = properties)\n", + "\n", + "def generate_simple_orm(cell, zipped):\n", + " legacy = orm.StructureData(cell=cell)\n", + " for position,symbol in zipped:\n", + " legacy.append_atom(position=position,symbols=symbol)\n", + " \n", + " return legacy\n", + "\n", + "def timing_atomistic_and_orm(properties, factor_list=[1]):\n", + " \"\"\"\n", + " timing function for the generation of atomistic and orm StructureData\n", + " without considering additional properties apart cell, positions, symbols\n", + " \"\"\"\n", + " import time\n", + " time_list_atom = []\n", + " time_list_orm = []\n", + " cell = properties['cell']['value']\n", + " initial_pos = [[1,1,1]]\n", + " initial_symb = ['H']\n", + " \n", + " for factor in factor_list:\n", + " properties['positions']['value']=initial_pos*factor\n", + " properties['symbols']['value']=initial_symb*factor\n", + " zipped = list(zip(properties['positions']['value'],properties['symbols']['value']))\n", + "\n", + " t_i_atom=time.time()\n", + " atomistic = generate_simple_atomistic(properties)\n", + " t_f_atom=time.time()\n", + " time.sleep(0.0001)\n", + " t_i_orm=time.time()\n", + " legacy = generate_simple_orm(cell, zipped) \n", + " t_f_orm=time.time()\n", + " time_list_atom.append(t_f_atom-t_i_atom)\n", + " time_list_orm.append(t_f_orm-t_i_orm)\n", + " \n", + " properties['positions']['value']=initial_pos\n", + " properties['symbols']['value']=initial_symb\n", + " \n", + " return np.array(time_list_atom),np.array(time_list_orm),np.array(factor_list)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "properties = {\n", + " \"cell\":{\"value\":[[1,0,0],[0,1,0],[0,0,1]]},\n", + " \"positions\":{\"value\":[[1,1,1]]},\n", + " \"symbols\":{\"value\":[\"He\"]},\n", + " }\n", + "t_atom, t_orm, factors = timing_atomistic_and_orm(properties,factor_list=list(range(500)))\n", + "#print(t_atom, t_orm, factors)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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dO3aVSxdutRqELjiQyKYpKamiokTJ4rIyEih0WhEWFiY6N27t1i9erV5GYPBIN544w0RFRUltFqtaNu2rVi/fr3VZcRCGMckadeunfD09LS4xL2kAV3nzJkjoqOjhUajEZGRkaUO6FpcSZc3F+dImWzVVUm3/zBddl/8kttDhw6JBx54QAQHBwutViuioqLEww8/LLZs2VJmWUt6r0wDugYGBgovLy/RsWPHEgd0tfcS4NJua1K0nkx+/fVX0bVrV+Ht7S38/f3FkCFDHBrQ9YsvvhAzZ84UtWvXFt7e3mLQoEFW4+qYBvK0JTU1VYwdO1aEhIQIT09PERsbazWYYdHX9M4774jIyEih1WpF9+7dzePHFXXu3DkxatQoERYWJjQajahTp44YPHiw+Pbbb83LmIYb2Ldvn81yvfbaa6JOnTpCpVJZXJJta0DXW7duiZkzZ4pGjRoJT09PERISIrp06SLefvtt8xhK3377rejXr595kOV69eqJf/3rXyI5OdliXSEhIeLuu++2WabivvrqK9G2bVuh1WpFUFBQqQO6FlfS58TWsBT5+fmiZs2aIiAgwO7bh5U2oGtxto45OTk54qWXXjIfR8LCwsSDDz5oHl+prNv32LMP5OXlienTp4vw8HDh7e0tunbtKvbs2WN1DFq1apXo0aOH+bPfsGFD8fzzz4ubN2+alyltQNfibB3jDh06ZB5Lqm7dumLevHliyZIlAoDFOHm2FBYWismTJ4tatWoJSZLM76ujxwJ76swWR7fz6aefmgc4bdOmjdi0aVOpA7oWVdLx0NbnueiArq1atRJarVY0a9bM5rHUns9weW4ZZe/3oSPDVxw/flz06dNH+Pn5iZCQEDFhwgTx559/CsByINiS9gvT6502bZqIiIgQGo1GNG7cuNQBXYuy97353//+J8aNGycaNmwovLy8RFBQkLjnnnvEr7/+atfrNJFuF4SIitm+fTvuuecefPPNN+bWEle5cOECoqOj8dZbb+G5555z6baUdPz4cbRo0QLr16936unFiiosLERERASGDBli1Z+KXGfq1KlYtWoVsrKyePskqrYq7438iKjS2bZtGzp37uxWIQww9s27evWqRedgcq7c3FyLx9evX8cnn3yCbt26MYRRteZed44moipt4sSJmDhxotLFMEtKSsKRI0fw2muvoW3btlYXT5DzdO7cGb169ULz5s2RmpqKDz/8EJmZmZg1a5bSRSNSFIMYEVVbK1aswKeffoo2bdrgo48+Uro4VdrAgQPx7bffYvXq1ZAkCXfddRc+/PBD9OjRQ+miESmKfcSIiIiIFMI+YkREREQKYRAjIiIiUgj7iMF4H64rV66gRo0ast5aiIiIiMpPCIFbt24hIiJClkHCXYFBDMZbRBS/yzoRERFVDn///bfdN9l2NwxigPkWHn///Tf8/f2dtl6dTofNmzejX79+Dt/YlxzDupYH61kerGf5sK7l4ap6zszMRGRkpFNuxaUUBjHcuYO7v7+/04OYj48P/P39+QF3Mda1PFjP8mA9y4d1LQ9X13Nl7lZUOU+oEhEREVUBDGJERERECmEQIyIiIlII+4jZyWAwoKCgwKHn6HQ6eHh4IC8vD3q93kUlI6D0utZoNLypMBERuSUGMTsUFBTg/PnzMBgMDj1PCIGwsDD8/ffflbojYWVQVl0HBgYiLCyM7wMREbkVBrEyCCGQnJwMtVqNyMhIhwaMMxgMyMrKgp+fX6UdaK6yKKmuhRDIyclBWloaACA8PFypIhIREVlhECtDYWEhcnJyEBERAR8fH4eeazqd6eXlxSDmYqXVtbe3NwAgLS0NtWvX5mlKIiJyG0wHZTD1N/L09FS4JFQRphCt0+kULgkREdEdDGJ2Yt+iyo3vHxERuSOemiQiIiJrBj1wcTeQlQr4hQJRXQAVu3Y4G4MYyWLMmDHIyMjAunXryvX8CxcuIDo6GocOHUKbNm2cWjYiIirm+E9AwotA5pU70/wjgP4LgJihypWrCmIQk4neILD3fDrSbuWhdg0vdIwOglql3OkyuYPN4sWLIYSwa1lboS0yMhLJyckICQlxUQmJiAiAMYR9PQpAsWN2ZrJx+sMfM4w5EYOYDBKOpeC1X04g+WaeeVp4gBdmD4lB/5bVYziFgICACj1frVYjLCzMSaUhIiKbDHpjS1jxEAbcniYBCTOAZoN4mtJJ2Fnfxbacuo6Jnx+yCGEAkHIzD09/ehAJx5Jdtu2EhAR069YNgYGBCA4OxuDBg3Hu3DkAQHR0NACgbdu2kCQJvXr1AmAcBmLu3LmoW7cutFot2rRpg4SEBPM6L1y4AEmS8PXXX6N79+7w9vZGhw4dcPr0aezbtw/t27eHn58fBgwYgKtXr5qfN2bMGNx3333mx99++y1iY2Ph7e2N4OBg9OnTB9nZ2Xj11Vexdu1a/Pjjj5AkCZIkYfv27ebtHj582LyOv/76C4MHD4a/vz8CAgIwYMAA8+sjIqJyuLjb8nSkFQFkXjYuR07BIOYgIQRyCgrt+ncrT4cFif8r8XcFALz603HcytPZtT57T+2ZZGdnIz4+Hvv378eWLVugUqlw//33w2AwYO/evQCAX3/9FcnJyfj+++8BGE8hvvPOO3j77bdx5MgRxMXFYejQoThz5ozFumfPno2XX34ZBw8ehIeHBx577DG88MILWLx4MX777TecPXsWr7zyis1yJScn49FHH8W4ceNw4sQJbN++HQ888ACEEHjuuefw8MMPo3///khOTkZycjK6dOlitY7Lly+jR48e0Gq12Lp1K/bt24fHH38chYWFDtUREREVkZXq3OWoTDw16aBcnR4xr2xyyroEgJTMPMS+utmu5Y/PjYOPp/1v2fDhwy0e//e//0WtWrVw/Phx1KpVCwAQHBxsccrv7bffxosvvogRI0YAABYsWIBt27Zh0aJFWL58uXm55557DnFxcQCAZ599Fo8++ii2bNmCrl27AgDGjx+Pjz76yGa5kpOTUVhYiAceeABRUVEAgNjYWPN8b29v5Ofnl3oqcvny5QgICMCXX34JjUYDg8GAsLAw+Pv721s9RERUnF+oc5ejMrFFrAo7c+YMHn30UTRo0AD+/v6oX78+AODSpUs2l8/MzMSVK1fMYcqka9euOHHihMW0Vq1amf8ODTV+IIuGqdDQUPNthYpr3bo1evfujdjYWDz00EN4//33cePGDYde2+HDh9G9e3doNBqHnkdERKWI6mK8OhIlXUwmAf51jMuRUyjaIrZz50689dZbOHDgAJKTk/HDDz9Y9CMq6t///jdWrVqFd999F1OnTjVPT09Px+TJk/Hzzz9DpVJh+PDhWLx4Mfz8/FxSZm+NGsfnxtm17B/nrmHc2gNlLvfR2A7oGB1k17YdMWTIEERFReH9999HREQEDAYDWrZsiYKCAofWY0vRAGQaLLX4tJJukq5Wq5GYmIjdu3dj8+bNWLp0KV566SUkJSWZ+66VxXTbIiIiciKV2jhExdejbMy8Hc76z2dHfSdStEUsOzsbrVu3tjjlZcsPP/yAP/74AxEREVbzRo4cib/++guJiYlYv349du7ciaeeespVRYYk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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(t_atom*1000, label='atomistic', marker='o')\n", + "plt.plot(t_orm*1000, label='orm', marker='o')\n", + "plt.grid()\n", + "plt.ylabel('Time (ms)')\n", + "plt.xlabel('Number of atoms')\n", + "plt.title('Creation time for no properties, only increasing the number of atoms')\n", + "plt.legend()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'cell': {'value': [[1, 0, 0], [0, 1, 0], [0, 0, 1]]},\n", + " 'positions': {'value': [[1, 1, 1]]},\n", + " 'symbols': {'value': ['H']}}" + ] + }, + "execution_count": 83, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "properties" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test 2. Adding properties and increasing number of atoms." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "def timing_atomistic_and_orm_properties(properties, factor_list=[1], props_num=2):\n", + " \"\"\"\n", + " timing function for the generation of atomistic and orm StructureData\n", + " considering additional properties and additional atoms.\n", + " \"\"\"\n", + " import time\n", + " time_list_atom = []\n", + " time_list_orm = []\n", + " cell = properties['cell']['value']\n", + " initial_pos = [[1,1,1]]\n", + " initial_symb = ['H']\n", + " initial_charge = [1]\n", + " initial_mass = [1]\n", + " initial_kinds = ['H1']\n", + " \n", + " for factor in factor_list:\n", + " properties['positions']['value']=initial_pos*factor\n", + " properties['symbols']['value']=initial_symb*factor\n", + " properties['charge']= {'value':initial_charge*factor}\n", + " properties['mass']= {'value':initial_mass*factor}\n", + " properties['kinds']= {'value':initial_kinds*factor}\n", + " \n", + " if props_num==1: \n", + " properties.pop('kinds')\n", + " properties.pop('mass')\n", + " \n", + " elif props_num==3:\n", + " properties.pop('kinds')\n", + " properties.pop('charge')\n", + " \n", + " zipped = list(zip(properties['positions']['value'],properties['symbols']['value']))\n", + "\n", + " t_i_atom=time.time()\n", + " atomistic = generate_simple_atomistic(properties)\n", + " t_f_atom=time.time()\n", + " time.sleep(0.0001)\n", + " t_i_orm=time.time()\n", + " legacy = generate_simple_orm(cell, zipped) \n", + " t_f_orm=time.time()\n", + " time_list_atom.append(t_f_atom-t_i_atom)\n", + " time_list_orm.append(t_f_orm-t_i_orm)\n", + " \n", + " properties['positions']['value']=initial_pos\n", + " properties['symbols']['value']=initial_symb\n", + " properties['charge']= {'value':initial_charge}\n", + " properties['mass']= {'value':initial_mass}\n", + " properties['kinds']= {'value':initial_kinds}\n", + " \n", + " return np.array(time_list_atom),np.array(time_list_orm),np.array(factor_list)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "properties = {\n", + " \"cell\":{\"value\":[[1,0,0],[0,1,0],[0,0,1]]},\n", + " \"positions\":{\"value\":[[1,1,1]]},\n", + " \"symbols\":{\"value\":[\"He\"]},\n", + " }\n", + "t_atom_props, t_orm_props, factors = timing_atomistic_and_orm_properties(properties,factor_list=list(range(500)))\n", + "t_atom_props_2, t_orm_props, factors = timing_atomistic_and_orm_properties(properties,factor_list=list(range(500)),props_num=1)\n", + "t_atom_props_3, t_orm_props, factors = timing_atomistic_and_orm_properties(properties,factor_list=list(range(500)),props_num=3)\n", + "\n", + "#print(t_atom, t_orm, factors)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(t_atom_props*1000, label='atomistic with 3 properties', marker='o')\n", + "plt.plot(t_atom_props_2*1000, label='atomistic with 1 property, mass set automatically', marker='o')\n", + "plt.plot(t_atom*1000, label='atomistic', marker='o')\n", + "plt.plot(t_orm*1000, label='orm', marker='o')\n", + "plt.ylabel('Time (ms)')\n", + "plt.xlabel('Number of atoms')\n", + "plt.title('Creation time increasing the number of atoms and number of properties')\n", + "plt.grid()\n", + "plt.ylim(0,60)\n", + "plt.legend()\n", + "plt.tight_layout()\n", + "plt.savefig('scaling.png')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The main difference is that to create the orm.StructureData we need to loop and append atoms." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "aiida-muonic", + "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.10.11" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/src/aiida_atomistic/data/structure/properties/__init__.py b/src/aiida_atomistic/data/structure/properties/__init__.py index 2abe9c1..93b7584 100644 --- a/src/aiida_atomistic/data/structure/properties/__init__.py +++ b/src/aiida_atomistic/data/structure/properties/__init__.py @@ -6,7 +6,8 @@ from aiida_atomistic.data.structure.properties.globals.cell import Cell from aiida_atomistic.data.structure.properties.globals.pbc import Pbc -from aiida_atomistic.data.structure.properties.intra_site.position import Positions +from aiida_atomistic.data.structure.properties.intra_site.positions import Positions +from aiida_atomistic.data.structure.properties.intra_site.kinds import Kinds from aiida_atomistic.data.structure.properties.intra_site.symbols import Symbols from aiida_atomistic.data.structure.properties.intra_site.mass import Mass from aiida_atomistic.data.structure.properties.intra_site.charge import Charge @@ -53,6 +54,8 @@ class PropertyCollector(HasPropertyMixin): mass: Mass = Property() charge: Charge = Property() + kinds: Kinds = Property() # optional; if not there but required, use the get_kinds to generate automatically. + # Custom custom: CustomProperty = Property() @@ -62,7 +65,7 @@ class PropertyCollector(HasPropertyMixin): # Derived properties: properties which, if not set, they will be set automatically, as they are mandatory to have in the # StructureData but can also be initialised with defaults if not explicitely provided - derived_properties = ['pbc','mass'] #['kinds', 'mass'] + derived_properties = ['pbc','mass'] # for now we exclude kinds. def __init__( self, @@ -91,18 +94,14 @@ def __init__( # is an instance of the corresponding Property subclass value. super().__init__() + # inspect and then store the properties in the `_property_attributes` attribute. self._property_attributes = provided_properties + # Store the properties in the StructureData node. - #self._parent.base.attributes.set('_property_attributes',{}) if not self._parent.is_stored: self._parent.base.attributes.set('_property_attributes',self._property_attributes) - self._inspect_properties(properties) - - - """def get_supported_properties(self,): - return list(typing.get_type_hints(self.__class__).keys()) - """ + self._inspect_properties(self._property_attributes) def get_property_attribute(self, key): # In AiiDA this could be self.base.attrs['properties'][key] or similar @@ -139,4 +138,4 @@ def _inspect_properties(self,properties): `HasPropertyMixin` class. The fact is that the `PropertyMixinMetaclass` only define the fget and fset methods, without using them. """ - getattr(self,pname) + getattr(self,pname) \ No newline at end of file diff --git a/src/aiida_atomistic/data/structure/properties/intra_site/kinds.py b/src/aiida_atomistic/data/structure/properties/intra_site/kinds.py index 46848fe..957a0fc 100644 --- a/src/aiida_atomistic/data/structure/properties/intra_site/kinds.py +++ b/src/aiida_atomistic/data/structure/properties/intra_site/kinds.py @@ -1,4 +1,4 @@ -from typing import List, Literal +from typing import List from pydantic import Field, validator from aiida.common.constants import elements @@ -11,18 +11,23 @@ class Kinds(IntraSiteProperty): """ - The kinds property, intended as the chemical symbols for each atom(site). + The kinds property, for each atom(site). """ domain = "intra-site" - value: List[Literal[None]] + value: List[str] @validator("value", always=True) def validate_kinds(cls,value,values): - # I have to use the _property_attributes, as accessing directly parent.properties gives recursion error. - # Maybe it is possible to change how we get the properties? - if not "positions" in values["parent"].base.attributes.get("_property_attributes"): - raise ValueError("If you define symbols, you should define also the corresponding positions.") - elif not len(value) == len(values["parent"].base.attributes.get("_property_attributes")["positions"]["value"]): - raise ValueError("The number of provided symbols should match the number of positions.") + + properties = values["parent"].base.attributes.get("_property_attributes") + + if not "symbols" in properties.keys(): + raise ValueError("If you define kinds, you should define also the corresponding symbols.") + elif not len(value) == len(properties["symbols"]["value"]): + raise ValueError("The number of provided kinds should match the number of symbols.") + + # Check that the properties are not inconsistent with respect to the defined kinds: i.e. + # same kinds should have same properties. + return value ################################################## End: PBC property. \ No newline at end of file diff --git a/src/aiida_atomistic/data/structure/properties/intra_site/position.py b/src/aiida_atomistic/data/structure/properties/intra_site/positions.py similarity index 85% rename from src/aiida_atomistic/data/structure/properties/intra_site/position.py rename to src/aiida_atomistic/data/structure/properties/intra_site/positions.py index fd7c844..bc03eee 100644 --- a/src/aiida_atomistic/data/structure/properties/intra_site/position.py +++ b/src/aiida_atomistic/data/structure/properties/intra_site/positions.py @@ -1,5 +1,5 @@ from typing import List -from pydantic import Field +from pydantic import Field, validator from aiida_atomistic.data.structure.properties.intra_site import IntraSiteProperty @@ -22,5 +22,8 @@ def validate_positions(cls,value,values): return ValueError("Each position should be represented by an array of length three (x,y,z)") # (2) check that all positions are unique: + # However, this is not checked in the orm.StructureData, so we will implement later. + + return value ################################################## End: Positions property. \ No newline at end of file diff --git a/src/aiida_atomistic/data/structure/properties/intra_site/symbols.py b/src/aiida_atomistic/data/structure/properties/intra_site/symbols.py index 33805eb..125748d 100644 --- a/src/aiida_atomistic/data/structure/properties/intra_site/symbols.py +++ b/src/aiida_atomistic/data/structure/properties/intra_site/symbols.py @@ -21,9 +21,10 @@ class Symbols(IntraSiteProperty): def validate_symbols(cls,value,values): # I have to use the _property_attributes, as accessing directly parent.properties gives recursion error. # Maybe it is possible to change how we get the properties? - if not "positions" in values["parent"].base.attributes.get("_property_attributes"): + properties = values["parent"].base.attributes.get("_property_attributes") + if not "positions" in properties.keys(): raise ValueError("If you define symbols, you should define also the corresponding positions.") - elif not len(value) == len(values["parent"].base.attributes.get("_property_attributes")["positions"]["value"]): + elif not len(value) == len(properties["positions"]["value"]): raise ValueError("The number of provided symbols should match the number of positions.") # what if we prefer to give a guess? like the following: #return [value[0]]*len(values["parent"].base.attributes.get("_property_attributes")["positions"]["value"]) diff --git a/src/aiida_atomistic/data/structure/scaling.png b/src/aiida_atomistic/data/structure/scaling.png new file mode 100644 index 0000000..68655b9 Binary files /dev/null and b/src/aiida_atomistic/data/structure/scaling.png differ