From 76b6a5d75326a5e8cf10f566dffcf8e60639ead9 Mon Sep 17 00:00:00 2001 From: ndaelman Date: Wed, 6 Nov 2024 16:22:42 +0000 Subject: [PATCH 01/11] - Introduce `_base_value` as a pre-normalization of `value` - Remove `__setattr__` - simplify `__init__` --- .../schema_packages/physical_property.py | 115 ++++++------------ 1 file changed, 40 insertions(+), 75 deletions(-) diff --git a/src/nomad_simulations/schema_packages/physical_property.py b/src/nomad_simulations/schema_packages/physical_property.py index 5bb728bc..139ee815 100644 --- a/src/nomad_simulations/schema_packages/physical_property.py +++ b/src/nomad_simulations/schema_packages/physical_property.py @@ -109,7 +109,7 @@ class PhysicalProperty(ArchiveSection): or `'indirect'`. """, # ! add more examples in the description to improve the understanding of this quantity - ) + ) # ? label = Quantity( type=str, @@ -118,26 +118,14 @@ class PhysicalProperty(ArchiveSection): can be labeled as `'DFT'` or `'GW'` depending on the methodology used to calculate it. """, # ! add more examples in the description to improve the understanding of this quantity - ) - - rank = DirectQuantity( - type=Dimension, - shape=['0..*'], - default=[], - name='rank', - description=""" - Rank of the tensor describing the physical property. This quantity is stored as a Dimension: - - scalars (tensor rank 0) have `rank=[]` (`len(rank) = 0`), - - vectors (tensor rank 1) have `rank=[a]` (`len(rank) = 1`), - - matrices (tensor rank 2), have `rank=[a, b]` (`len(rank) = 2`), - - etc. - """, - ) + ) # ? variables = SubSection(sub_section=Variables.m_def, repeats=True) + value: Any = None + # * `value` must be overwritten in the derived classes defining its type, unit, and description - value: Quantity = _placeholder_quantity + _base_value: Quantity = _placeholder_quantity entity_ref = Quantity( type=Entity, @@ -175,7 +163,7 @@ class PhysicalProperty(ArchiveSection): Flag indicating whether the physical property is converged or not after a SCF process. This quantity is connected with `SelfConsistency` defined in the `numerical_settings.py` module. """, - ) + ) # TODO: move to numerical settings self_consistency_ref = Quantity( type=SelfConsistency, @@ -186,7 +174,7 @@ class PhysicalProperty(ArchiveSection): ) @property - def variables_shape(self) -> Optional[list]: + def variables_shape(self) -> list[int]: """ Shape of the variables over which the physical property varies. This is extracted from `Variables.n_points` and appended in a list. @@ -197,9 +185,26 @@ def variables_shape(self) -> Optional[list]: Returns: (list): The shape of the variables over which the physical property varies. """ - if self.variables is not None: - return [v.get_n_points(logger) for v in self.variables] + if self.variables: + return [v.get_n_points(logger) for v in self.variables] # ! TODO: support any variable shape, not just vectors return [] + + @property + def rank(self) -> list[int]: + """ + Rank of the physical property. This quantity is related with the order of the tensor of `value`. + + Example: a physical property which is a 3D vector will have `rank=[3]`. + + Returns: + (list): The rank of the physical property. + """ + if self._base_value: + if isinstance(shape := self._base_value.shape, list): + return shape + else: + return [] + raise ValueError('The `_base_value` quantity is not defined.') @property def full_shape(self) -> list: @@ -223,21 +228,16 @@ def full_shape(self) -> list: return self.variables_shape + self.rank @property - def _new_value(self) -> Quantity: + def _new_value(self) -> Optional[Quantity]: """ - Initialize a new `Quantity` object for the `value` quantity with the correct `shape` extracted from - the `full_shape` attribute. This copies the main attributes from `value` (`type`, `description`, `unit`). - It is used in the `__setattr__` method. - - Returns: - (Quantity): The new `Quantity` object for setting the `value` quantity. + Generate a new `Quantity` object for the `value` quantity based on `base_value` and with `shape=full_shape`. """ - value_quantity = self.m_def.all_quantities.get('value') + value_quantity = self.m_def.all_quantities.get('_base_value') if value_quantity is None: return None return Quantity( type=value_quantity.type, - unit=value_quantity.unit, # ? this can be moved to __setattr__ + unit=value_quantity.unit, description=value_quantity.description, ) @@ -247,53 +247,14 @@ def __init__( super().__init__(m_def, m_context, **kwargs) # Checking if IRI is defined - if self.iri is None: + if not self.iri: logger.warning( - 'The used property is not defined in the FAIRmat taxonomy (https://fairmat-nfdi.github.io/fairmat-taxonomy/). You can contribute there if you want to extend the list of available materials properties.' - ) - - # Checking if the quantities `n_` are defined, as this are used to calculate `rank` - for quantity, _ in self.m_def.all_quantities.items(): - if quantity.startswith('n_') and getattr(self, quantity) is None: - raise ValueError( - f'`{quantity}` is not defined during initialization of the class.' - ) - - def __setattr__(self, name: str, val: Any) -> None: - # For the special case of `value`, its `shape` needs to be defined from `_full_shape` - if name == 'value': - if val is None: - raise ValueError( - f'The value of the physical property {self.name} is None. Please provide a finite valid value.' - ) - _new_value = self._new_value - - # patch for when `val` does not have units and it is passed as a list (instead of np.array) - if isinstance(val, list): - val = np.array(val) - - # non-scalar or scalar `val` - try: - value_shape = list(val.shape) - except AttributeError: - value_shape = [] - - if value_shape != self.full_shape: - raise ValueError( - f'The shape of the stored `value` {value_shape} does not match the full shape {self.full_shape} ' - f'extracted from the variables `n_points` and the `shape` defined in `PhysicalProperty`.' - ) - _new_value.shape = self.full_shape - if hasattr(val, 'magnitude'): - _new_value = val.magnitude * val.u - else: - _new_value = val - return super().__setattr__(name, _new_value) - return super().__setattr__(name, val) + 'The used property is not defined in the FAIRmat taxonomy (https://fairmat-nfdi.github.io/fairmat-taxonomy/).' + ) # ? - def _is_derived(self) -> bool: + def _is_derived(self) -> bool: # ? """ - Resolves if the physical property is derived or not. + Resolves whether the physical property is derived or not. Returns: (bool): The flag indicating whether the physical property is derived or not. @@ -305,8 +266,12 @@ def _is_derived(self) -> bool: def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) - # Resolve if the physical property `is_derived` or not from another physical property. self.is_derived = self._is_derived() + if (new_value := self._new_value): + value_data = self.get('value') + # ? is it necessary to store the value data or can I set it right away? + self.m_def.value = new_value + self.value = value_data class PropertyContribution(PhysicalProperty): From 340e0ed25147c550c9b43e26aec1d477169d81b7 Mon Sep 17 00:00:00 2001 From: ndaelman Date: Fri, 8 Nov 2024 16:32:49 +0100 Subject: [PATCH 02/11] Apply changes to downstream sections --- .../properties/band_structure.py | 7 ++-- .../schema_packages/properties/energies.py | 5 +-- .../properties/fermi_surface.py | 3 +- .../schema_packages/properties/forces.py | 2 +- .../properties/hopping_matrix.py | 14 ++++---- .../properties/permittivity.py | 4 +-- .../properties/spectral_profile.py | 9 ++---- .../properties/thermodynamics.py | 32 +++++++++++-------- 8 files changed, 35 insertions(+), 41 deletions(-) diff --git a/src/nomad_simulations/schema_packages/properties/band_structure.py b/src/nomad_simulations/schema_packages/properties/band_structure.py index c5e169b0..1c1d71a7 100644 --- a/src/nomad_simulations/schema_packages/properties/band_structure.py +++ b/src/nomad_simulations/schema_packages/properties/band_structure.py @@ -39,8 +39,9 @@ class BaseElectronicEigenvalues(PhysicalProperty): """, ) - value = Quantity( + _base_value = Quantity( type=np.float64, + shape=['n_bands'], unit='joule', description=""" Value of the electronic eigenvalues. @@ -51,8 +52,6 @@ def __init__( self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) - # ! `n_bands` need to be set up during initialization of the class - self.rank = [int(kwargs.get('n_bands'))] def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -356,7 +355,7 @@ class Occupancy(PhysicalProperty): """, ) - value = Quantity( + _base_value = Quantity( type=np.float64, description=""" Value of the electronic occupancy in the atom defined by `atoms_state_ref` and the orbital diff --git a/src/nomad_simulations/schema_packages/properties/energies.py b/src/nomad_simulations/schema_packages/properties/energies.py index c726c4da..c3f67501 100644 --- a/src/nomad_simulations/schema_packages/properties/energies.py +++ b/src/nomad_simulations/schema_packages/properties/energies.py @@ -25,7 +25,7 @@ class BaseEnergy(PhysicalProperty): energy class. """ - value = Quantity( + _base_value = Quantity( type=np.float64, unit='joule', description=""" @@ -67,15 +67,12 @@ class FermiLevel(BaseEnergy): Energy required to add or extract a charge from a material at zero temperature. It can be also defined as the chemical potential at zero temperature. """ - # ! implement `iri` and `rank` as part of `m_def = Section()` - iri = 'http://fairmat-nfdi.eu/taxonomy/FermiLevel' def __init__( self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) - self.rank = [] self.name = self.m_def.name def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: diff --git a/src/nomad_simulations/schema_packages/properties/fermi_surface.py b/src/nomad_simulations/schema_packages/properties/fermi_surface.py index 231e15ed..5ec32782 100644 --- a/src/nomad_simulations/schema_packages/properties/fermi_surface.py +++ b/src/nomad_simulations/schema_packages/properties/fermi_surface.py @@ -28,12 +28,13 @@ class FermiSurface(PhysicalProperty): """, ) + # ! TODO _base_value + def __init__( self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) # ! `n_bands` need to be set up during initialization of the class - self.rank = [int(kwargs.get('n_bands'))] self.name = self.m_def.name def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: diff --git a/src/nomad_simulations/schema_packages/properties/forces.py b/src/nomad_simulations/schema_packages/properties/forces.py index cedf72f1..a2742c93 100644 --- a/src/nomad_simulations/schema_packages/properties/forces.py +++ b/src/nomad_simulations/schema_packages/properties/forces.py @@ -25,7 +25,7 @@ class BaseForce(PhysicalProperty): force class. """ - value = Quantity( + _base_value = Quantity( type=np.dtype(np.float64), unit='newton', description=""" diff --git a/src/nomad_simulations/schema_packages/properties/hopping_matrix.py b/src/nomad_simulations/schema_packages/properties/hopping_matrix.py index 094c901d..6446fa60 100644 --- a/src/nomad_simulations/schema_packages/properties/hopping_matrix.py +++ b/src/nomad_simulations/schema_packages/properties/hopping_matrix.py @@ -34,13 +34,14 @@ class HoppingMatrix(PhysicalProperty): """, ) - value = Quantity( + _base_value = Quantity( type=np.complex128, + shape=['n_orbitals', 'n_orbitals'], unit='joule', description=""" Value of the hopping matrix in joules. The elements are complex numbers defined for each Wigner-Seitz point and - each pair of orbitals; thus, `rank = [n_orbitals, n_orbitals]`. Note this contains also the onsite values, i.e., - it includes the Wigner-Seitz point (0, 0, 0), hence the `CrystalFieldSplitting` values. + each pair of orbitals. + Note: this contains also the onsite values (Wigner-Seitz origin), hence describing also the `CrystalFieldSplitting` values. """, ) @@ -48,8 +49,6 @@ def __init__( self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) - # ! n_orbitals need to be set up during initialization of the class - self.rank = [int(kwargs.get('n_orbitals')), int(kwargs.get('n_orbitals'))] self.name = self.m_def.name # TODO add normalization to extract DOS, band structure, etc, properties from `HoppingMatrix` @@ -73,8 +72,9 @@ class CrystalFieldSplitting(PhysicalProperty): """, ) - value = Quantity( + _base_value = Quantity( type=np.float64, + shape=['n_orbitals'], unit='joule', description=""" Value of the crystal field splittings in joules. This is the intra-orbital local contribution, i.e., the same orbital @@ -86,8 +86,6 @@ def __init__( self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) - # ! `n_orbitals` need to be set up during initialization of the class - self.rank = [int(kwargs.get('n_orbitals'))] self.name = self.m_def.name def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: diff --git a/src/nomad_simulations/schema_packages/properties/permittivity.py b/src/nomad_simulations/schema_packages/properties/permittivity.py index aeede940..ba5e23ed 100644 --- a/src/nomad_simulations/schema_packages/properties/permittivity.py +++ b/src/nomad_simulations/schema_packages/properties/permittivity.py @@ -34,8 +34,9 @@ class Permittivity(PhysicalProperty): """, ) - value = Quantity( + _base_value = Quantity( type=np.complex128, + shape=[3, 3], # unit='joule', # TODO check units (they have to match `SpectralProfile.value`) description=""" Value of the permittivity tensor. If the value does not depend on the scattering vector `q`, then we @@ -51,7 +52,6 @@ def __init__( self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) - self.rank = [3, 3] self.name = self.m_def.name self._axes_map = ['xx', 'yy', 'zz'] diff --git a/src/nomad_simulations/schema_packages/properties/spectral_profile.py b/src/nomad_simulations/schema_packages/properties/spectral_profile.py index 8078ff3d..86ea8f5c 100644 --- a/src/nomad_simulations/schema_packages/properties/spectral_profile.py +++ b/src/nomad_simulations/schema_packages/properties/spectral_profile.py @@ -26,7 +26,7 @@ class SpectralProfile(PhysicalProperty): A base section used to define the spectral profile. """ - value = Quantity( + _base_value = Quantity( type=np.float64, description=""" The value of the intensities of a spectral profile in arbitrary units. @@ -37,7 +37,6 @@ def __init__( self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) - self.rank = [] def is_valid_spectral_profile(self) -> bool: """ @@ -66,7 +65,7 @@ class DOSProfile(SpectralProfile): contributions for `projected_dos` with the correct unit. """ - value = Quantity( + _base_value = Quantity( type=np.float64, unit='1/joule', description=""" @@ -505,8 +504,6 @@ def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: class AbsorptionSpectrum(SpectralProfile): """ """ - # ! implement `iri` and `rank` as part of `m_def = Section()` - axis = Quantity( type=MEnum('xx', 'yy', 'zz'), description=""" @@ -531,8 +528,6 @@ class XASSpectrum(AbsorptionSpectrum): X-ray Absorption Spectrum (XAS). """ - # ! implement `iri` and `rank` as part of `m_def = Section()` - xanes_spectrum = SubSection( sub_section=AbsorptionSpectrum.m_def, description=""" diff --git a/src/nomad_simulations/schema_packages/properties/thermodynamics.py b/src/nomad_simulations/schema_packages/properties/thermodynamics.py index d6135943..769f4828 100644 --- a/src/nomad_simulations/schema_packages/properties/thermodynamics.py +++ b/src/nomad_simulations/schema_packages/properties/thermodynamics.py @@ -24,7 +24,7 @@ class Pressure(PhysicalProperty): # iri = 'http://fairmat-nfdi.eu/taxonomy/Pressure' # ! Does not yet exist in taxonomy - value = Quantity( + _base_value = Quantity( type=np.float64, unit='pascal', description=""" @@ -45,7 +45,7 @@ class Volume(PhysicalProperty): iri = 'http://fairmat-nfdi.eu/taxonomy/Volume' - value = Quantity( + _base_value = Quantity( type=np.float64, unit='m ** 3', description=""" @@ -61,7 +61,7 @@ class Temperature(PhysicalProperty): a measure of the average kinetic energy of the particles in a system. """ - value = Quantity( + _base_value = Quantity( type=np.float64, unit='kelvin', description=""" @@ -126,7 +126,7 @@ class Entropy(PhysicalProperty): state, as given by the Boltzmann equation for entropy. """ - value = Quantity( + _base_value = Quantity( type=np.float64, unit='joule / kelvin', description=""" @@ -162,15 +162,12 @@ class ChemicalPotential(BaseEnergy): Free energy cost of adding or extracting a particle from a thermodynamic system. """ - # ! implement `iri` and `rank` as part of `m_def = Section()` - iri = 'http://fairmat-nfdi.eu/taxonomy/ChemicalPotential' def __init__( self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) - self.rank = [] self.name = self.m_def.name def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: @@ -182,7 +179,7 @@ class HeatCapacity(PhysicalProperty): Amount of heat to be supplied to a material to produce a unit change in its temperature. """ - value = Quantity( + _base_value = Quantity( type=np.float64, unit='joule / kelvin', description=""" @@ -198,20 +195,27 @@ def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: ################################ -class VirialTensor(BaseEnergy): +class VirialTensor(BaseEnergy): # ? retain `BaseEnergy` for a semantic reasons """ A measure of the distribution of internal forces and the overall stress within a system of particles. Mathematically, the virial tensor is defined as minus the sum of the dot product between the position and force vectors for each particle. The `VirialTensor` can be related to the non-ideal pressure of the system through the virial theorem. - """ + """ # ! TODO use math notation + + _base_value = Quantity( + type=np.float64, + shape=[3, 3], # ! TODO set shape to dim + unit='joule', + description=""" + """, + ) def __init__( self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) - self.rank = [3, 3] self.name = self.m_def.name def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: @@ -223,7 +227,7 @@ class MassDensity(PhysicalProperty): Mass per unit volume of a material. """ - value = Quantity( + _base_value = Quantity( type=np.float64, unit='kg / m ** 3', description=""" @@ -241,8 +245,9 @@ class Hessian(PhysicalProperty): describing the local curvature of the energy surface. """ - value = Quantity( + _base_value = Quantity( type=np.float64, + shape=[3, 3], # ! TODO set shape to dim unit='joule / m ** 2', description=""" """, @@ -252,7 +257,6 @@ def __init__( self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) - self.rank = [3, 3] self.name = self.m_def.name def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: From 527a41af49e7a52ecd52ac5ba2e4cf2e9d791c47 Mon Sep 17 00:00:00 2001 From: ndaelman Date: Mon, 11 Nov 2024 15:57:02 +0100 Subject: [PATCH 03/11] Dynamically add `value` as a subsection based on `_base_value` --- .../schema_packages/physical_property.py | 52 +++++++++++-------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/src/nomad_simulations/schema_packages/physical_property.py b/src/nomad_simulations/schema_packages/physical_property.py index 139ee815..d51e520f 100644 --- a/src/nomad_simulations/schema_packages/physical_property.py +++ b/src/nomad_simulations/schema_packages/physical_property.py @@ -199,9 +199,9 @@ def rank(self) -> list[int]: Returns: (list): The rank of the physical property. """ - if self._base_value: - if isinstance(shape := self._base_value.shape, list): - return shape + if (base_value := self.m_def.all_quantities.get('_base_value')): + if isinstance(base_value.shape, list): + return base_value.shape else: return [] raise ValueError('The `_base_value` quantity is not defined.') @@ -227,20 +227,6 @@ def full_shape(self) -> list: """ return self.variables_shape + self.rank - @property - def _new_value(self) -> Optional[Quantity]: - """ - Generate a new `Quantity` object for the `value` quantity based on `base_value` and with `shape=full_shape`. - """ - value_quantity = self.m_def.all_quantities.get('_base_value') - if value_quantity is None: - return None - return Quantity( - type=value_quantity.type, - unit=value_quantity.unit, - description=value_quantity.description, - ) - def __init__( self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: @@ -252,6 +238,16 @@ def __init__( 'The used property is not defined in the FAIRmat taxonomy (https://fairmat-nfdi.github.io/fairmat-taxonomy/).' ) # ? + def __setattr__(self, name: str, value: Any) -> None: + # redirect from `_base_value` to `value` + if name == '_base_value': + if not isinstance(value, str): + self.value = value + elif not value.startswith('m_'): + self.value = value + else: + super().__setattr__(name, value) + def _is_derived(self) -> bool: # ? """ Resolves whether the physical property is derived or not. @@ -266,12 +262,22 @@ def _is_derived(self) -> bool: # ? def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) - self.is_derived = self._is_derived() - if (new_value := self._new_value): - value_data = self.get('value') - # ? is it necessary to store the value data or can I set it right away? - self.m_def.value = new_value - self.value = value_data + self.is_derived = self._is_derived() # ? + + try: + if self.value is not None: + value = self.value + elif self._base_value is not None: + value = self._base_value + else: + value = None + except AttributeError: + raise AttributeError('The `value` or `_base_value` is not defined at the _quantity_ level.') + + value_def = self.m_def.all_quantities.get('_base_value') + value_def.label = 'value' + value_def.shape = self.full_shape + self.m_add_sub_section(value_def, value) class PropertyContribution(PhysicalProperty): From d8239e62d45dfb74c2d76bc7684e08c0545023e2 Mon Sep 17 00:00:00 2001 From: ndaelman Date: Mon, 11 Nov 2024 17:19:49 +0100 Subject: [PATCH 04/11] Try different interface --- src/nomad_simulations/schema_packages/physical_property.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/nomad_simulations/schema_packages/physical_property.py b/src/nomad_simulations/schema_packages/physical_property.py index d51e520f..0a53cca9 100644 --- a/src/nomad_simulations/schema_packages/physical_property.py +++ b/src/nomad_simulations/schema_packages/physical_property.py @@ -277,7 +277,8 @@ def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: value_def = self.m_def.all_quantities.get('_base_value') value_def.label = 'value' value_def.shape = self.full_shape - self.m_add_sub_section(value_def, value) + self.m_add_sub_section(Quantity(name=value_def.label, type=value_def.type, unit=value_def.unit, shape=value_def.shape, description=value_def.description), value_def) + self.value = value #.to(value_def.unit).magnitude if value is not None else None class PropertyContribution(PhysicalProperty): From 512dee60fd8013e91ef027d96fe6f37cd45aab9c Mon Sep 17 00:00:00 2001 From: ndaelman Date: Tue, 12 Nov 2024 11:50:49 +0100 Subject: [PATCH 05/11] Fix writing of `value` --- .../schema_packages/physical_property.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/nomad_simulations/schema_packages/physical_property.py b/src/nomad_simulations/schema_packages/physical_property.py index 0a53cca9..029467dd 100644 --- a/src/nomad_simulations/schema_packages/physical_property.py +++ b/src/nomad_simulations/schema_packages/physical_property.py @@ -262,7 +262,7 @@ def _is_derived(self) -> bool: # ? def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) - self.is_derived = self._is_derived() # ? + # self.is_derived = self._is_derived() # ? try: if self.value is not None: @@ -274,11 +274,17 @@ def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: except AttributeError: raise AttributeError('The `value` or `_base_value` is not defined at the _quantity_ level.') - value_def = self.m_def.all_quantities.get('_base_value') - value_def.label = 'value' - value_def.shape = self.full_shape - self.m_add_sub_section(Quantity(name=value_def.label, type=value_def.type, unit=value_def.unit, shape=value_def.shape, description=value_def.description), value_def) - self.value = value #.to(value_def.unit).magnitude if value is not None else None + self.m_def.quantities.append( + Quantity( + name='value', + shape=self.full_shape, + type=self.m_def.all_quantities['_base_value'].type, + unit=self.m_def.all_quantities['_base_value'].unit, + description=self.m_def.all_quantities['_base_value'].description, + ) + ) + if value is not None: # ! pin down type + self.value = value.to(self.m_def.all_quantities['value'].unit).magnitude class PropertyContribution(PhysicalProperty): From 8e80cf427e77a6bf5e2e7c1025ffabe9635573b5 Mon Sep 17 00:00:00 2001 From: ndaelman Date: Tue, 12 Nov 2024 12:47:58 +0100 Subject: [PATCH 06/11] Remove remaining ranks --- .../schema_packages/properties/band_gap.py | 1 - .../properties/greens_function.py | 45 +++++++++---------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/nomad_simulations/schema_packages/properties/band_gap.py b/src/nomad_simulations/schema_packages/properties/band_gap.py index 05c1ba57..7348f599 100644 --- a/src/nomad_simulations/schema_packages/properties/band_gap.py +++ b/src/nomad_simulations/schema_packages/properties/band_gap.py @@ -67,7 +67,6 @@ def __init__( ) -> None: super().__init__(m_def, m_context, **kwargs) self.name = self.m_def.name - self.rank = [] def validate_values(self, logger: 'BoundLogger') -> Optional[pint.Quantity]: """ diff --git a/src/nomad_simulations/schema_packages/properties/greens_function.py b/src/nomad_simulations/schema_packages/properties/greens_function.py index 3da09e53..d5355919 100644 --- a/src/nomad_simulations/schema_packages/properties/greens_function.py +++ b/src/nomad_simulations/schema_packages/properties/greens_function.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional import numpy as np from nomad.metainfo import MEnum, Quantity @@ -129,16 +129,6 @@ class BaseGreensFunction(PhysicalProperty): """, ) - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - # ! n_orbitals need to be set up during initialization of the class - self.rank = [ - int(kwargs.get('n_atoms')), - int(kwargs.get('n_correlated_orbitals')), - ] - def resolve_space_id(self) -> str: """ Resolves the `space_id` based on the stored `variables` in the class. @@ -196,9 +186,10 @@ class ElectronicGreensFunction(BaseGreensFunction): iri = 'http://fairmat-nfdi.eu/taxonomy/ElectronicGreensFunction' - value = Quantity( + _base_value = Quantity( type=np.complex128, unit='1/joule', + shape=['n_atoms', 'n_correlated_orbitals'], description=""" Value of the electronic Green's function matrix. """, @@ -221,9 +212,10 @@ class ElectronicSelfEnergy(BaseGreensFunction): iri = 'http://fairmat-nfdi.eu/taxonomy/ElectronicSelfEnergy' - value = Quantity( + _base_value = Quantity( type=np.complex128, unit='joule', + shape=['n_atoms', 'n_correlated_orbitals'], description=""" Value of the electronic self-energy matrix. """, @@ -246,9 +238,10 @@ class HybridizationFunction(BaseGreensFunction): iri = 'http://fairmat-nfdi.eu/taxonomy/HybridizationFunction' - value = Quantity( + _base_value = Quantity( type=np.complex128, unit='joule', + shape=['n_atoms', 'n_correlated_orbitals'], description=""" Value of the electronic hybridization function. """, @@ -336,8 +329,9 @@ class QuasiparticleWeight(PhysicalProperty): """, ) - value = Quantity( + _base_value = Quantity( type=np.float64, + shape=['n_atoms', 'n_correlated_orbitals'], description=""" Value of the quasiparticle weight matrices. """, @@ -347,11 +341,6 @@ def __init__( self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) - # ! n_orbitals need to be set up during initialization of the class - self.rank = [ - int(kwargs.get('n_atoms')), - int(kwargs.get('n_correlated_orbitals')), - ] self.name = self.m_def.name def is_valid_quasiparticle_weight(self) -> bool: @@ -362,18 +351,23 @@ def is_valid_quasiparticle_weight(self) -> bool: Returns: (bool): True if the quasiparticle weight is valid, False otherwise. """ - if (self.value < 0.0).any() or (self.value > 1.0).any(): + if self.value is None: + return False + elif (self.value < 0.0).any() or (self.value > 1.0).any(): return False - return True + else: + return True - def resolve_system_correlation_strengths(self) -> str: + def resolve_system_correlation_strengths(self) -> Optional[str]: """ Resolves the `system_correlation_strengths` of the quasiparticle weight based on the stored `value` values. Returns: str: The resolved `system_correlation_strengths` of the quasiparticle weight. """ - if np.all(self.value > 0.7): + if self.value is None: + return None + elif np.all(self.value > 0.7): return 'non-correlated metal' elif np.all((self.value < 0.4) & (self.value > 0)): return 'strongly-correlated metal' @@ -381,7 +375,8 @@ def resolve_system_correlation_strengths(self) -> str: return 'OSMI' elif np.all(self.value < 1e-2): return 'Mott insulator' - return None + else: + return None def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) From de12d9ff032672e1ed14084f349ed84a712644d5 Mon Sep 17 00:00:00 2001 From: ndaelman Date: Tue, 12 Nov 2024 12:49:49 +0100 Subject: [PATCH 07/11] Apply ruff --- .../schema_packages/physical_property.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/nomad_simulations/schema_packages/physical_property.py b/src/nomad_simulations/schema_packages/physical_property.py index 029467dd..c1f8968a 100644 --- a/src/nomad_simulations/schema_packages/physical_property.py +++ b/src/nomad_simulations/schema_packages/physical_property.py @@ -186,9 +186,11 @@ def variables_shape(self) -> list[int]: (list): The shape of the variables over which the physical property varies. """ if self.variables: - return [v.get_n_points(logger) for v in self.variables] # ! TODO: support any variable shape, not just vectors + return [ + v.get_n_points(logger) for v in self.variables + ] # ! TODO: support any variable shape, not just vectors return [] - + @property def rank(self) -> list[int]: """ @@ -199,7 +201,7 @@ def rank(self) -> list[int]: Returns: (list): The rank of the physical property. """ - if (base_value := self.m_def.all_quantities.get('_base_value')): + if base_value := self.m_def.all_quantities.get('_base_value'): if isinstance(base_value.shape, list): return base_value.shape else: @@ -272,7 +274,9 @@ def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: else: value = None except AttributeError: - raise AttributeError('The `value` or `_base_value` is not defined at the _quantity_ level.') + raise AttributeError( + 'The `value` or `_base_value` is not defined at the _quantity_ level.' + ) self.m_def.quantities.append( Quantity( From 7d7ed9a6c6dcf5cac92ee0cc4bd5f082978171c4 Mon Sep 17 00:00:00 2001 From: ndaelman Date: Tue, 12 Nov 2024 20:15:42 +0100 Subject: [PATCH 08/11] - Handle different types of `value` - Default to 1D list for `value` --- .../schema_packages/physical_property.py | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/nomad_simulations/schema_packages/physical_property.py b/src/nomad_simulations/schema_packages/physical_property.py index c1f8968a..80315973 100644 --- a/src/nomad_simulations/schema_packages/physical_property.py +++ b/src/nomad_simulations/schema_packages/physical_property.py @@ -1,8 +1,10 @@ from functools import wraps -from typing import TYPE_CHECKING, Any, Optional +from typing import TYPE_CHECKING, Any +from types import NoneType import numpy as np from nomad import utils +from nomad.units import ureg from nomad.datamodel.data import ArchiveSection from nomad.datamodel.metainfo.annotations import ELNAnnotation from nomad.datamodel.metainfo.basesections import Entity @@ -227,7 +229,10 @@ def full_shape(self) -> list: Returns: (list): The full shape of the physical property. """ - return self.variables_shape + self.rank + if (full_rank := self.variables_shape + self.rank): + return full_rank + else: + return ['*'] def __init__( self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs @@ -287,8 +292,15 @@ def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: description=self.m_def.all_quantities['_base_value'].description, ) ) - if value is not None: # ! pin down type - self.value = value.to(self.m_def.all_quantities['value'].unit).magnitude + + if isinstance(value, NoneType): + self.value = None + elif isinstance(value, ureg.Quantity): + self.value = np.asarray(value.to(self.m_def.all_quantities['value'].unit).magnitude) + elif isinstance(value, np.ndarray) or isinstance(value, list): + self.value = value + else: + self.value = [value] class PropertyContribution(PhysicalProperty): From d9d6495172959eda0ffa22735ec108fcc86463c9 Mon Sep 17 00:00:00 2001 From: ndaelman Date: Tue, 12 Nov 2024 20:17:03 +0100 Subject: [PATCH 09/11] Fix `BaseForce._base_value` --- .../schema_packages/properties/forces.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/nomad_simulations/schema_packages/properties/forces.py b/src/nomad_simulations/schema_packages/properties/forces.py index a2742c93..f621dbfa 100644 --- a/src/nomad_simulations/schema_packages/properties/forces.py +++ b/src/nomad_simulations/schema_packages/properties/forces.py @@ -26,15 +26,13 @@ class BaseForce(PhysicalProperty): """ _base_value = Quantity( - type=np.dtype(np.float64), + type=np.float64, unit='newton', + shape=['*', 3], description=""" """, ) - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class ForceContribution(BaseForce, PropertyContribution): """ @@ -74,6 +72,3 @@ def __init__( ) -> None: super().__init__(m_def, m_context, **kwargs) self.name = self.m_def.name - - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) From 9e6f9a57c54d34fe334c362b94e548c91e7bf36b Mon Sep 17 00:00:00 2001 From: ndaelman Date: Tue, 12 Nov 2024 20:21:33 +0100 Subject: [PATCH 10/11] Prune unused imports --- src/nomad_simulations/schema_packages/physical_property.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nomad_simulations/schema_packages/physical_property.py b/src/nomad_simulations/schema_packages/physical_property.py index 80315973..b073bdb2 100644 --- a/src/nomad_simulations/schema_packages/physical_property.py +++ b/src/nomad_simulations/schema_packages/physical_property.py @@ -16,7 +16,7 @@ SectionProxy, SubSection, ) -from nomad.metainfo.metainfo import Dimension, DirectQuantity, _placeholder_quantity +from nomad.metainfo.metainfo import _placeholder_quantity if TYPE_CHECKING: from nomad.datamodel.datamodel import EntryArchive From 1e671c8ca45a78633ccc8c3331feda6574b2b8ee Mon Sep 17 00:00:00 2001 From: ndaelman Date: Tue, 12 Nov 2024 20:54:46 +0100 Subject: [PATCH 11/11] - Make `PhysicalProperty` initialize `self.name` - Remove wasteful `__init__` and `normalize` --- .../schema_packages/physical_property.py | 3 +- .../schema_packages/properties/band_gap.py | 75 +++---------------- .../properties/band_structure.py | 32 -------- .../schema_packages/properties/energies.py | 43 ----------- .../properties/fermi_surface.py | 12 +-- .../schema_packages/properties/forces.py | 9 --- .../properties/greens_function.py | 33 -------- .../properties/hopping_matrix.py | 18 ----- .../properties/permittivity.py | 1 - .../properties/spectral_profile.py | 35 --------- .../properties/thermodynamics.py | 63 ---------------- tests/properties/test_band_gap.py | 5 -- 12 files changed, 14 insertions(+), 315 deletions(-) diff --git a/src/nomad_simulations/schema_packages/physical_property.py b/src/nomad_simulations/schema_packages/physical_property.py index b073bdb2..15d15b43 100644 --- a/src/nomad_simulations/schema_packages/physical_property.py +++ b/src/nomad_simulations/schema_packages/physical_property.py @@ -31,7 +31,7 @@ logger = utils.get_logger(__name__) -def validate_quantity_wrt_value(name: str = ''): +def validate_quantity_wrt_value(name: str = ''): # ! tone down to `quantity_present` """ Decorator to validate the existence of a quantity and its shape with respect to the `PhysicalProperty.value` before calling a method. An example can be found in the module `properties/band_structure.py` for the method @@ -238,6 +238,7 @@ def __init__( self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) + self.name = self.m_def.name # Checking if IRI is defined if not self.iri: diff --git a/src/nomad_simulations/schema_packages/properties/band_gap.py b/src/nomad_simulations/schema_packages/properties/band_gap.py index 7348f599..f60d63c5 100644 --- a/src/nomad_simulations/schema_packages/properties/band_gap.py +++ b/src/nomad_simulations/schema_packages/properties/band_gap.py @@ -23,6 +23,7 @@ class ElectronicBandGap(PhysicalProperty): type = Quantity( type=MEnum('direct', 'indirect'), + shape=['*'], description=""" Type categorization of the electronic band gap. This quantity is directly related with `momentum_transfer` as by definition, the electronic band gap is `'direct'` for zero momentum transfer (or if `momentum_transfer` is `None`) and `'indirect'` @@ -34,15 +35,13 @@ class ElectronicBandGap(PhysicalProperty): momentum_transfer = Quantity( type=np.float64, - shape=[2, 3], + shape=['*', 2, 3], description=""" If the electronic band gap is `'indirect'`, the reciprocal momentum transfer for which the band gap is defined in units of the `reciprocal_lattice_vectors`. The initial and final momentum 3D vectors are given in the first and second element. Example, the momentum transfer in bulk Si2 happens between the Γ and the (approximately) X points in the Brillouin zone; thus: - `momentum_transfer = [[0, 0, 0], [0.5, 0.5, 0]]`. - - Note: this quantity only refers to scalar `value`, not to arrays of `value`. + `momentum_transfer = [[[0, 0, 0], [0.5, 0.5, 0]]]`. """, ) @@ -53,7 +52,7 @@ class ElectronicBandGap(PhysicalProperty): """, ) - value = Quantity( + _base_value = Quantity( type=np.float64, unit='joule', description=""" @@ -62,35 +61,7 @@ class ElectronicBandGap(PhysicalProperty): """, ) - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name - - def validate_values(self, logger: 'BoundLogger') -> Optional[pint.Quantity]: - """ - Validate the electronic band gap `value` by checking if they are negative and sets them to None if they are. - - Args: - logger (BoundLogger): The logger to log messages. - """ - value = self.value.magnitude - if not isinstance(self.value.magnitude, np.ndarray): # for scalars - value = np.array( - [value] - ) # ! check this when talking with Lauri and Theodore - - # Set the value to 0 when it is negative - if (value < 0).any(): - logger.error('The electronic band gap cannot be defined negative.') - return None - - if not isinstance(self.value.magnitude, np.ndarray): # for scalars - value = value[0] - return value * self.value.u - - def resolve_type(self, logger: 'BoundLogger') -> Optional[str]: + def momentum_to_type(self, mtr, logger: 'BoundLogger') -> Optional[str]: """ Resolves the `type` of the electronic band gap based on the stored `momentum_transfer` values. @@ -100,23 +71,7 @@ def resolve_type(self, logger: 'BoundLogger') -> Optional[str]: Returns: (Optional[str]): The resolved `type` of the electronic band gap. """ - mtr = self.momentum_transfer if self.momentum_transfer is not None else [] - - # Check if the `momentum_transfer` is [], and return the type and a warning in the log for `indirect` band gaps - if len(mtr) == 0: - if self.type == 'indirect': - logger.warning( - 'The `momentum_transfer` is not stored for an `indirect` band gap.' - ) - return self.type - - # Check if the `momentum_transfer` has at least two elements, and return None if it does not - if len(mtr) == 1: - logger.warning( - 'The `momentum_transfer` should have at least two elements so that the difference can be calculated and the type of electronic band gap can be resolved.' - ) - return None - + # Resolve `type` from the difference between the initial and final momentum transfer momentum_difference = np.diff(mtr, axis=0) if (np.isclose(momentum_difference, np.zeros(3))).all(): @@ -127,17 +82,9 @@ def resolve_type(self, logger: 'BoundLogger') -> Optional[str]: def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) - # Checks if the `value` is negative and sets it to None if it is. - self.value = self.validate_values(logger) - if self.value is None: + if self.value is not None and np.any(self.value < 0.): + logger.warning('The electronic band gap cannot be defined negative.') # ? What about deleting the class if `value` is None? - logger.error('The `value` of the electronic band gap is not stored.') - return - - # Resolve the `type` of the electronic band gap from `momentum_transfer`, ONLY for scalar `value` - if isinstance(self.value.magnitude, np.ndarray): - logger.info( - 'We do not support `type` which describe individual elements in an array `value`.' - ) - else: - self.type = self.resolve_type(logger) + + if self.momentum_transfer: + self.type = self.momentum_to_type(self.momentum_transfer, logger) diff --git a/src/nomad_simulations/schema_packages/properties/band_structure.py b/src/nomad_simulations/schema_packages/properties/band_structure.py index 1c1d71a7..9d8a20ad 100644 --- a/src/nomad_simulations/schema_packages/properties/band_structure.py +++ b/src/nomad_simulations/schema_packages/properties/band_structure.py @@ -48,14 +48,6 @@ class BaseElectronicEigenvalues(PhysicalProperty): """, ) - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class ElectronicEigenvalues(BaseElectronicEigenvalues): """ """ @@ -124,12 +116,6 @@ class ElectronicEigenvalues(BaseElectronicEigenvalues): """, ) - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name - @validate_quantity_wrt_value(name='occupation') def order_eigenvalues(self) -> Union[bool, tuple[pint.Quantity, np.ndarray]]: """ @@ -314,15 +300,6 @@ class ElectronicBandStructure(ElectronicEigenvalues): iri = 'http://fairmat-nfdi.eu/taxonomy/ElectronicBandStructure' - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name - - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class Occupancy(PhysicalProperty): """ @@ -365,13 +342,4 @@ class Occupancy(PhysicalProperty): """, ) - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name - # TODO add extraction from `ElectronicEigenvalues.occupation` - - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) diff --git a/src/nomad_simulations/schema_packages/properties/energies.py b/src/nomad_simulations/schema_packages/properties/energies.py index c3f67501..6a846ae4 100644 --- a/src/nomad_simulations/schema_packages/properties/energies.py +++ b/src/nomad_simulations/schema_packages/properties/energies.py @@ -32,9 +32,6 @@ class BaseEnergy(PhysicalProperty): """, ) - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class EnergyContribution(BaseEnergy, PropertyContribution): """ @@ -52,10 +49,6 @@ class EnergyContribution(BaseEnergy, PropertyContribution): relevant atoms or electrons or as a function of them. """ - # TODO address the dual parent normalization explicity - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - #################################### # List of specific energy properties @@ -69,15 +62,6 @@ class FermiLevel(BaseEnergy): iri = 'http://fairmat-nfdi.eu/taxonomy/FermiLevel' - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name - - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - #! The only issue with this structure is that total energy will never be a sum of its contributions, #! since kinetic energy lives separately, but I think maybe this is ok? @@ -90,15 +74,6 @@ class TotalEnergy(BaseEnergy): # ? add a generic contributions quantity to PhysicalProperty contributions = SubSection(sub_section=EnergyContribution.m_def, repeats=True) - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name - - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - # ? Separate quantities for nuclear and electronic KEs? class KineticEnergy(BaseEnergy): @@ -106,26 +81,8 @@ class KineticEnergy(BaseEnergy): Physical property section describing the kinetic energy of a (sub)system. """ - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name - - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class PotentialEnergy(BaseEnergy): """ Physical property section describing the potential energy of a (sub)system. """ - - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name - - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) diff --git a/src/nomad_simulations/schema_packages/properties/fermi_surface.py b/src/nomad_simulations/schema_packages/properties/fermi_surface.py index 5ec32782..83117713 100644 --- a/src/nomad_simulations/schema_packages/properties/fermi_surface.py +++ b/src/nomad_simulations/schema_packages/properties/fermi_surface.py @@ -28,14 +28,4 @@ class FermiSurface(PhysicalProperty): """, ) - # ! TODO _base_value - - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - # ! `n_bands` need to be set up during initialization of the class - self.name = self.m_def.name - - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) + # ! TODO add `_base_value` diff --git a/src/nomad_simulations/schema_packages/properties/forces.py b/src/nomad_simulations/schema_packages/properties/forces.py index f621dbfa..92c915b8 100644 --- a/src/nomad_simulations/schema_packages/properties/forces.py +++ b/src/nomad_simulations/schema_packages/properties/forces.py @@ -50,9 +50,6 @@ class ForceContribution(BaseForce, PropertyContribution): relevant atoms or electrons or as a function of them. """ - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - ################################### # List of specific force properties @@ -66,9 +63,3 @@ class TotalForce(BaseForce): """ contributions = SubSection(sub_section=ForceContribution.m_def, repeats=True) - - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name diff --git a/src/nomad_simulations/schema_packages/properties/greens_function.py b/src/nomad_simulations/schema_packages/properties/greens_function.py index d5355919..f1e694f0 100644 --- a/src/nomad_simulations/schema_packages/properties/greens_function.py +++ b/src/nomad_simulations/schema_packages/properties/greens_function.py @@ -195,15 +195,6 @@ class ElectronicGreensFunction(BaseGreensFunction): """, ) - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name - - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class ElectronicSelfEnergy(BaseGreensFunction): """ @@ -221,15 +212,6 @@ class ElectronicSelfEnergy(BaseGreensFunction): """, ) - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name - - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class HybridizationFunction(BaseGreensFunction): """ @@ -247,15 +229,6 @@ class HybridizationFunction(BaseGreensFunction): """, ) - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name - - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class QuasiparticleWeight(PhysicalProperty): """ @@ -337,12 +310,6 @@ class QuasiparticleWeight(PhysicalProperty): """, ) - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name - def is_valid_quasiparticle_weight(self) -> bool: """ Check if the quasiparticle weight values are valid, i.e., if all `value` are defined between diff --git a/src/nomad_simulations/schema_packages/properties/hopping_matrix.py b/src/nomad_simulations/schema_packages/properties/hopping_matrix.py index 6446fa60..31a8664b 100644 --- a/src/nomad_simulations/schema_packages/properties/hopping_matrix.py +++ b/src/nomad_simulations/schema_packages/properties/hopping_matrix.py @@ -45,17 +45,8 @@ class HoppingMatrix(PhysicalProperty): """, ) - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name - # TODO add normalization to extract DOS, band structure, etc, properties from `HoppingMatrix` - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class CrystalFieldSplitting(PhysicalProperty): """ @@ -81,12 +72,3 @@ class CrystalFieldSplitting(PhysicalProperty): at the same Wigner-Seitz point (0, 0, 0). """, ) - - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name - - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) diff --git a/src/nomad_simulations/schema_packages/properties/permittivity.py b/src/nomad_simulations/schema_packages/properties/permittivity.py index ba5e23ed..41176441 100644 --- a/src/nomad_simulations/schema_packages/properties/permittivity.py +++ b/src/nomad_simulations/schema_packages/properties/permittivity.py @@ -52,7 +52,6 @@ def __init__( self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name self._axes_map = ['xx', 'yy', 'zz'] def resolve_type(self) -> str: diff --git a/src/nomad_simulations/schema_packages/properties/spectral_profile.py b/src/nomad_simulations/schema_packages/properties/spectral_profile.py index 86ea8f5c..0a18b2f8 100644 --- a/src/nomad_simulations/schema_packages/properties/spectral_profile.py +++ b/src/nomad_simulations/schema_packages/properties/spectral_profile.py @@ -33,11 +33,6 @@ class SpectralProfile(PhysicalProperty): """, ) # TODO check units and normalization_factor of DOS and Spectras and see whether they can be merged - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - def is_valid_spectral_profile(self) -> bool: """ Check if the spectral profile is valid, i.e., if all `value` are defined positive. @@ -73,11 +68,6 @@ class DOSProfile(SpectralProfile): """, ) - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - def resolve_pdos_name(self, logger: 'BoundLogger') -> Optional[str]: """ Resolve the `name` of the projected `DOSProfile` from the `entity_ref` section. This is resolved as: @@ -106,8 +96,6 @@ def resolve_pdos_name(self, logger: 'BoundLogger') -> Optional[str]: def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) - - # We resolve self.name = self.resolve_pdos_name(logger) @@ -169,12 +157,6 @@ class ElectronicDensityOfStates(DOSProfile): """, ) - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name - def resolve_energies_origin( self, energies: pint.Quantity, @@ -512,16 +494,6 @@ class AbsorptionSpectrum(SpectralProfile): """, ) - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - # Set the name of the section - self.name = self.m_def.name - - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class XASSpectrum(AbsorptionSpectrum): """ @@ -544,13 +516,6 @@ class XASSpectrum(AbsorptionSpectrum): repeats=False, ) - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - # Set the name of the section - self.name = self.m_def.name - def generate_from_contributions(self, logger: 'BoundLogger') -> None: """ Generate the `value` of the XAS spectrum by concatenating the XANES and EXAFS contributions. It also concatenates diff --git a/src/nomad_simulations/schema_packages/properties/thermodynamics.py b/src/nomad_simulations/schema_packages/properties/thermodynamics.py index 769f4828..50db0798 100644 --- a/src/nomad_simulations/schema_packages/properties/thermodynamics.py +++ b/src/nomad_simulations/schema_packages/properties/thermodynamics.py @@ -31,9 +31,6 @@ class Pressure(PhysicalProperty): """, ) - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class Volume(PhysicalProperty): """ @@ -52,9 +49,6 @@ class Volume(PhysicalProperty): """, ) - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class Temperature(PhysicalProperty): """ @@ -68,27 +62,18 @@ class Temperature(PhysicalProperty): """, ) - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class Heat(BaseEnergy): """ The transfer of thermal energy **into** a system. """ - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class Work(BaseEnergy): """ The energy transferred to a system by means of force applied over a distance. """ - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class InternalEnergy(BaseEnergy): """ @@ -97,18 +82,12 @@ class InternalEnergy(BaseEnergy): process may be expressed as the `Heat` minus the `Work`. """ - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class Enthalpy(BaseEnergy): """ The total heat content of a system, defined as 'InternalEnergy' + 'Pressure' * 'Volume'. """ - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class Entropy(PhysicalProperty): """ @@ -133,9 +112,6 @@ class Entropy(PhysicalProperty): """, ) - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class GibbsFreeEnergy(BaseEnergy): """ @@ -143,9 +119,6 @@ class GibbsFreeEnergy(BaseEnergy): given by `Enthalpy` - `Temperature` * `Entropy`. """ - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class HelmholtzFreeEnergy(BaseEnergy): """ @@ -153,9 +126,6 @@ class HelmholtzFreeEnergy(BaseEnergy): given by `InternalEnergy` - `Temperature` * `Entropy`. """ - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class ChemicalPotential(BaseEnergy): """ @@ -164,15 +134,6 @@ class ChemicalPotential(BaseEnergy): iri = 'http://fairmat-nfdi.eu/taxonomy/ChemicalPotential' - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name - - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class HeatCapacity(PhysicalProperty): """ @@ -186,9 +147,6 @@ class HeatCapacity(PhysicalProperty): """, ) - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - ################################ # other thermodynamic properties @@ -212,15 +170,6 @@ class VirialTensor(BaseEnergy): # ? retain `BaseEnergy` for a semantic reasons """, ) - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name - - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - class MassDensity(PhysicalProperty): """ @@ -234,9 +183,6 @@ class MassDensity(PhysicalProperty): """, ) - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) - # ? fit better elsewhere class Hessian(PhysicalProperty): @@ -252,12 +198,3 @@ class Hessian(PhysicalProperty): description=""" """, ) - - def __init__( - self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs - ) -> None: - super().__init__(m_def, m_context, **kwargs) - self.name = self.m_def.name - - def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: - super().normalize(archive, logger) diff --git a/tests/properties/test_band_gap.py b/tests/properties/test_band_gap.py index 48939ea8..0f928a89 100644 --- a/tests/properties/test_band_gap.py +++ b/tests/properties/test_band_gap.py @@ -22,12 +22,7 @@ def test_default_quantities(self): Test the default quantities assigned when creating an instance of the `ElectronicBandGap` class. """ electronic_band_gap = ElectronicBandGap() - assert ( - electronic_band_gap.iri - == 'http://fairmat-nfdi.eu/taxonomy/ElectronicBandGap' - ) assert electronic_band_gap.name == 'ElectronicBandGap' - assert electronic_band_gap.rank == [] @pytest.mark.parametrize( 'value, result',