From 62227a6de36d1bf4bc93718cf8c4e405b1520214 Mon Sep 17 00:00:00 2001 From: JosePizarro3 Date: Mon, 29 Apr 2024 12:17:36 +0200 Subject: [PATCH] Added m_def to the PhysicalProperties and fix testing --- src/nomad_simulations/physical_property.py | 33 +++-------- src/nomad_simulations/properties/band_gap.py | 6 +- src/nomad_simulations/properties/energies.py | 12 +--- .../properties/spectral_profile.py | 10 ++-- tests/test_band_gap.py | 5 +- tests/test_energies.py | 10 ++-- tests/test_outputs.py | 3 +- tests/test_physical_properties.py | 55 ++++++++++++++----- tests/test_spectral_profile.py | 10 ++-- 9 files changed, 68 insertions(+), 76 deletions(-) diff --git a/src/nomad_simulations/physical_property.py b/src/nomad_simulations/physical_property.py index afb0fab8..0f35cf58 100644 --- a/src/nomad_simulations/physical_property.py +++ b/src/nomad_simulations/physical_property.py @@ -54,18 +54,12 @@ class PhysicalProperty(ArchiveSection): # TODO add `errors` # TODO add `smearing` + m_def = Section() # modify `m_def` adding `iri` and `rank` + name = Quantity( type=str, description=""" - Name of the physical property. Example: `'ElectronicBandGap'`. - """, - ) - - iri = Quantity( - type=URL, - description=""" - Internationalized Resource Identifier (IRI) of the physical property defined in the FAIRmat - taxonomy, https://fairmat-nfdi.github.io/fairmat-taxonomy/. + Name of the physical property. """, ) @@ -96,20 +90,6 @@ class PhysicalProperty(ArchiveSection): # ! 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` must be overwritten in the derived classes defining its type, unit, and description @@ -196,7 +176,7 @@ def full_shape(self) -> list: Returns: (list): The full shape of the physical property. """ - return self.variables_shape + self.rank + return self.variables_shape + self.m_def.rank @property def _new_value(self) -> Quantity: @@ -221,9 +201,10 @@ def __init__( self, m_def: Section = None, m_context: Context = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) - if self.iri is None: + if self.m_def.iri is None: 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.' + 'The used property is not defined in the FAIRmat taxonomy (http://fairmat-nfdi.eu/taxonomy/). ' + 'You can contribute there if you want to extend the list of available materials properties.' ) def __setattr__(self, name: str, val: Any) -> None: diff --git a/src/nomad_simulations/properties/band_gap.py b/src/nomad_simulations/properties/band_gap.py index 2949a7e6..7f0b3283 100644 --- a/src/nomad_simulations/properties/band_gap.py +++ b/src/nomad_simulations/properties/band_gap.py @@ -31,9 +31,7 @@ class ElectronicBandGap(PhysicalProperty): Energy difference between the highest occupied electronic state and the lowest unoccupied electronic state. """ - # ! implement `iri` and `rank` as part of `m_def = Section()` - - iri = 'http://fairmat-nfdi.eu/taxonomy/ElectronicBandGap' + m_def = Section(iri='http://fairmat-nfdi.eu/taxonomy/ElectronicBandGap', rank=[]) type = Quantity( type=MEnum('direct', 'indirect'), @@ -80,8 +78,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.rank = [] def _check_negative_values(self, logger: BoundLogger) -> Optional[pint.Quantity]: """ diff --git a/src/nomad_simulations/properties/energies.py b/src/nomad_simulations/properties/energies.py index 8d8209a3..e4ed5acb 100644 --- a/src/nomad_simulations/properties/energies.py +++ b/src/nomad_simulations/properties/energies.py @@ -28,9 +28,7 @@ class FermiLevel(PhysicalProperty): 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' + m_def = Section(iri='http://fairmat-nfdi.eu/taxonomy/FermiLevel', rank=[]) value = Quantity( type=np.float64, @@ -44,8 +42,6 @@ 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, logger) -> None: super().normalize(archive, logger) @@ -56,9 +52,7 @@ class ChemicalPotential(PhysicalProperty): 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' + m_def = Section(iri='http://fairmat-nfdi.eu/taxonomy/ChemicalPotential', rank=[]) value = Quantity( type=np.float64, @@ -72,8 +66,6 @@ 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, logger) -> None: super().normalize(archive, logger) diff --git a/src/nomad_simulations/properties/spectral_profile.py b/src/nomad_simulations/properties/spectral_profile.py index 943c3c6a..a44722e0 100644 --- a/src/nomad_simulations/properties/spectral_profile.py +++ b/src/nomad_simulations/properties/spectral_profile.py @@ -36,6 +36,8 @@ class SpectralProfile(PhysicalProperty): A base section used to define the spectral profile. """ + m_def = Section(rank=[]) + value = Quantity( type=np.float64, description=""" @@ -47,7 +49,6 @@ def __init__( self, m_def: Section = None, m_context: Context = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) - self.rank = [] def _get_energy_points(self, logger: BoundLogger) -> Optional[pint.Quantity]: """ @@ -145,8 +146,9 @@ class ElectronicDensityOfStates(DOSProfile): Number of electronic states accessible for the charges per energy and per volume. """ - # ! implement `iri` and `rank` as part of `m_def = Section()` - iri = 'http://fairmat-nfdi.eu/taxonomy/ElectronicDensityOfStates' + m_def = Section( + iri='http://fairmat-nfdi.eu/taxonomy/ElectronicDensityOfStates', rank=[] + ) spin_channel = Quantity( type=np.int32, @@ -533,7 +535,7 @@ class XASSpectra(SpectralProfile): X-ray Absorption Spectra (XAS). """ - # ! implement `iri` and `rank` as part of `m_def = Section()` + m_def = Section(rank=[]) # TODO add XASSpectra to taxonomy xanes_spectra = SubSection( sub_section=SpectralProfile.m_def, diff --git a/tests/test_band_gap.py b/tests/test_band_gap.py index bfc45dc7..91d47eb2 100644 --- a/tests/test_band_gap.py +++ b/tests/test_band_gap.py @@ -41,11 +41,10 @@ def test_default_quantities(self): """ electronic_band_gap = ElectronicBandGap() assert ( - electronic_band_gap.iri + electronic_band_gap.m_def.iri == 'http://fairmat-nfdi.eu/taxonomy/ElectronicBandGap' ) - assert electronic_band_gap.name == 'ElectronicBandGap' - assert electronic_band_gap.rank == [] + assert electronic_band_gap.m_def.rank == [] @pytest.mark.parametrize( 'value, result', diff --git a/tests/test_energies.py b/tests/test_energies.py index f0f52e77..06e81e51 100644 --- a/tests/test_energies.py +++ b/tests/test_energies.py @@ -30,9 +30,8 @@ def test_default_quantities(self): Test the default quantities assigned when creating an instance of the `FermiLevel` class. """ fermi_level = FermiLevel() - assert fermi_level.iri == 'http://fairmat-nfdi.eu/taxonomy/FermiLevel' - assert fermi_level.name == 'FermiLevel' - assert fermi_level.rank == [] + assert fermi_level.m_def.iri == 'http://fairmat-nfdi.eu/taxonomy/FermiLevel' + assert fermi_level.m_def.rank == [] class TestChemicalPotential: @@ -47,8 +46,7 @@ def test_default_quantities(self): """ chemical_potential = ChemicalPotential() assert ( - chemical_potential.iri + chemical_potential.m_def.iri == 'http://fairmat-nfdi.eu/taxonomy/ChemicalPotential' ) - assert chemical_potential.name == 'ChemicalPotential' - assert chemical_potential.rank == [] + assert chemical_potential.m_def.rank == [] diff --git a/tests/test_outputs.py b/tests/test_outputs.py index aac05ced..d1aabfa6 100644 --- a/tests/test_outputs.py +++ b/tests/test_outputs.py @@ -24,7 +24,8 @@ from . import logger from .conftest import generate_scf_electronic_band_gap_template -from nomad_simulations.outputs import Outputs, ElectronicBandGap +from nomad_simulations.outputs import Outputs +from nomad_simulations.properties import ElectronicBandGap class TestOutputs: diff --git a/tests/test_physical_properties.py b/tests/test_physical_properties.py index 4bed0cc4..84cdf811 100644 --- a/tests/test_physical_properties.py +++ b/tests/test_physical_properties.py @@ -21,7 +21,7 @@ from nomad.units import ureg from nomad.datamodel import EntryArchive -from nomad.metainfo import Quantity +from nomad.metainfo import Quantity, Section, Context from . import logger @@ -30,6 +30,10 @@ class DummyPhysicalProperty(PhysicalProperty): + m_def = Section( + iri='http://fairmat-nfdi.eu/taxonomy/DummyPhysicalProperty', rank=[3, 3] + ) + value = Quantity( type=np.float64, unit='eV', @@ -38,6 +42,11 @@ class DummyPhysicalProperty(PhysicalProperty): """, ) + def __init__( + self, m_def: Section = None, m_context: Context = None, **kwargs + ) -> None: + super().__init__(m_def, m_context, **kwargs) + class TestPhysicalProperty: """ @@ -84,10 +93,12 @@ def test_static_properties( Test the static properties of the `PhysicalProperty` class, `variables_shape` and `full_shape`. """ physical_property = PhysicalProperty( - source='simulation', - rank=rank, - variables=variables, + m_def=Section( + iri='http://fairmat-nfdi.eu/taxonomy/PhysicalProperty', rank=rank + ) ) + physical_property.source = 'simulation' + physical_property.variables = variables assert physical_property.variables_shape == result_variables_shape assert physical_property.full_shape == result_full_shape @@ -97,8 +108,10 @@ def test_setattr_value(self): """ physical_property = DummyPhysicalProperty( source='simulation', - rank=[3, 3], - variables=[Variables(n_grid_points=4), Variables(n_grid_points=10)], + variables=[ + Variables(n_grid_points=4), + Variables(n_grid_points=10), + ], ) # `physical_property.value` must have full_shape=[4, 10, 3, 3] value = np.ones((4, 10, 3, 3)) * ureg.eV @@ -111,10 +124,12 @@ def test_setattr_value_wrong_shape(self): Test the `__setattr__` method when the `value` has a wrong shape. """ physical_property = PhysicalProperty( - source='simulation', - rank=[], - variables=[], + m_def=Section( + iri='http://fairmat-nfdi.eu/taxonomy/PhysicalProperty', rank=[] + ) ) + physical_property.source = 'simulation' + physical_property.variables = [] # `physical_property.value` must have shape=[] value = np.ones((3, 3)) wrong_shape = list(value.shape) @@ -130,10 +145,12 @@ def test_setattr_none(self): Test the `__setattr__` method when setting the `value` to `None`. """ physical_property = PhysicalProperty( - source='simulation', - rank=[], - variables=[], + m_def=Section( + iri='http://fairmat-nfdi.eu/taxonomy/PhysicalProperty', rank=[] + ) ) + physical_property.source = 'simulation' + physical_property.variables = [] with pytest.raises(ValueError) as exc_info: physical_property.value = None assert ( @@ -146,15 +163,23 @@ def test_is_derived(self): Test the `normalize` and `_is_derived` methods. """ # Testing a directly parsed physical property - not_derived_physical_property = PhysicalProperty(source='simulation') + not_derived_physical_property = PhysicalProperty( + m_def=Section( + iri='http://fairmat-nfdi.eu/taxonomy/PhysicalProperty', rank=[] + ) + ) + not_derived_physical_property.source = 'simulation' assert not_derived_physical_property._is_derived() is False not_derived_physical_property.normalize(EntryArchive(), logger) assert not_derived_physical_property.is_derived is False # Testing a derived physical property derived_physical_property = PhysicalProperty( - source='analysis', - physical_property_ref=not_derived_physical_property, + m_def=Section( + iri='http://fairmat-nfdi.eu/taxonomy/PhysicalProperty', rank=[] + ) ) + derived_physical_property.source = 'analysis' + derived_physical_property.physical_property_ref = not_derived_physical_property assert derived_physical_property._is_derived() is True derived_physical_property.normalize(EntryArchive(), logger) assert derived_physical_property.is_derived is True diff --git a/tests/test_spectral_profile.py b/tests/test_spectral_profile.py index 83eafd04..2e03cac8 100644 --- a/tests/test_spectral_profile.py +++ b/tests/test_spectral_profile.py @@ -67,11 +67,10 @@ def test_default_quantities(self): """ electronic_dos = ElectronicDensityOfStates() assert ( - electronic_dos.iri + electronic_dos.m_def.iri == 'http://fairmat-nfdi.eu/taxonomy/ElectronicDensityOfStates' ) - assert electronic_dos.name == 'ElectronicDensityOfStates' - assert electronic_dos.rank == [] + assert electronic_dos.m_def.rank == [] def test_get_energy_points(self): """ @@ -262,9 +261,8 @@ def test_default_quantities(self): Test the default quantities assigned when creating an instance of the `XASSpectra` class. """ xas_spectra = XASSpectra() - assert xas_spectra.iri is None # Add iri when available - assert xas_spectra.name == 'XASSpectra' - assert xas_spectra.rank == [] + assert xas_spectra.m_def.iri is None # TODO add iri when available + assert xas_spectra.m_def.rank == [] @pytest.mark.parametrize( 'xanes_energies, exafs_energies, xas_values',