Skip to content

Commit

Permalink
Generate RSM figures properly.
Browse files Browse the repository at this point in the history
  • Loading branch information
RubelMozumder committed Aug 31, 2024
1 parent df8938a commit 9b22316
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 46 deletions.
8 changes: 4 additions & 4 deletions src/nomad_measurements/transmission/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class Transmission(Measurement):
section_def=Operator,
)

def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None:
def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: # noqa: PLR0912
super().normalize(archive, logger)
raw_path = archive.m_context.raw_path()
eln_filename = '_transmission_eln_temp.json'
Expand All @@ -108,9 +108,9 @@ def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None:
if self.operator.name:
eln_dict['/ENTRY[entry]/operator/name'] = self.name
if self.operator.affiliation:
eln_dict['/ENTRY[entry]/operator/affiliation'] = (
self.operator.affiliation
)
eln_dict[
'/ENTRY[entry]/operator/affiliation'
] = self.operator.affiliation
if self.operator.address:
eln_dict['/ENTRY[entry]/operator/address'] = self.operator.address
if self.operator.email:
Expand Down
5 changes: 3 additions & 2 deletions src/nomad_measurements/xrd/nx.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ def __set_data_and_units(

for key, value in concept_links_from_xrd_dict.items():
if key in ['line', 'rsm'] and isinstance(value, dict):
# run for provided scan_type
if key != scan_type:
continue
for k, v in value.items():
__set_data_and_units(k, xrd_dict, **v)
elif isinstance(value, dict):
Expand Down Expand Up @@ -174,7 +177,6 @@ def write_nx_section_and_create_file(
scan_type (str): The type of scan, either 'line' or 'rsm'
"""
app_def = 'NXxrd_pan'
entry_type = archive.metadata.entry_type
nxdl_root, _ = dataconverter.helpers.get_nxdl_root_and_path(app_def)
template = dataconverter.template.Template()
dataconverter.helpers.generate_template_from_nxdl(nxdl_root, template)
Expand All @@ -190,4 +192,3 @@ def write_nx_section_and_create_file(
output_file_path=nx_file,
on_temp_file=False,
)
archive.metadata.entry_type = entry_type
83 changes: 45 additions & 38 deletions src/nomad_measurements/xrd/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@
)

import numpy as np
import pint
import plotly.express as px
from fairmat_readers_xrd import (
read_bruker_brml,
read_panalytical_xrdml,
read_rigaku_rasx,
)
from nomad.config import config
from nomad.datamodel.data import (
ArchiveSection,
EntryData,
Expand Down Expand Up @@ -73,16 +75,14 @@
from nomad_measurements.xrd.nx import write_nx_section_and_create_file

if TYPE_CHECKING:
import pint
from nomad.datamodel.datamodel import (
EntryArchive,
)
from structlog.stdlib import (
BoundLogger,
)


from nomad.config import config
ureg = pint.UnitRegistry()

configuration = config.get_plugin_entry_point('nomad_measurements.xrd:schema')

Expand All @@ -94,8 +94,8 @@

def calculate_two_theta_or_q(
wavelength: 'pint.Quantity',
q: Optional[np.ndarray] = None,
two_theta: Optional[np.ndarray] = None,
q: Optional['pint.Quantity'] = None,
two_theta: Optional['pint.Quantity'] = None,
) -> tuple['pint.Quantity', 'pint.Quantity']:
"""
Calculate the two-theta array from the scattering vector (q) or vice-versa,
Expand All @@ -118,10 +118,10 @@ def calculate_two_theta_or_q(
return q, two_theta


def calculate_q_vectors_RSM(
def calculate_q_vectors(
wavelength: 'pint.Quantity',
two_theta: np.ndarray,
omega: np.ndarray,
two_theta: 'pint.Quantity',
omega: 'pint.Quantity',
):
"""
Calculate the q-vectors for RSM scans in coplanar configuration.
Expand All @@ -132,22 +132,27 @@ def calculate_q_vectors_RSM(
Returns:
tuple[pint.Quantity, pint.Quantity]: Tuple of q-vectors.
"""
omega = omega[:, None] * np.ones_like(two_theta)
omega = omega[:, None] * np.ones_like(two_theta.magnitude)
qx = (
2
* np.pi
/ wavelength.magnitude
* (np.cos((two_theta - omega) * np.pi / 180.0) - np.cos(omega * np.pi / 180.0))
/ wavelength
* (
np.cos(two_theta.to('radian') - omega.to('radian'))
- np.cos(omega.to('radian'))
).magnitude
)
qz = (
2
* np.pi
/ wavelength
* (np.sin((two_theta - omega) * np.pi / 180.0) + np.sin(omega * np.pi / 180.0))
* (
np.sin(two_theta.to('radian') - omega.to('radian'))
+ np.sin(omega.to('radian'))
).magnitude
)

q_parallel = qx
q_perpendicular = qz
q_parallel = qx.to('1/angstrom')
q_perpendicular = qz.to('1/angstrom')
return q_parallel, q_perpendicular


Expand Down Expand Up @@ -275,26 +280,21 @@ class XRDResult(MeasurementResult):
two_theta = Quantity(
type=HDF5Reference,
description='The 2-theta range of the diffractogram',
unit='deg',
)
q_norm = Quantity(
type=HDF5Reference,
unit='meter**(-1)',
description='The norm of scattering vector *Q* of the diffractogram',
)
omega = Quantity(
type=HDF5Reference,
unit='deg',
description='The omega range of the diffractogram',
)
phi = Quantity(
type=HDF5Reference,
unit='deg',
description='The phi range of the diffractogram',
)
chi = Quantity(
type=HDF5Reference,
unit='deg',
description='The chi range of the diffractogram',
)
source_peak_wavelength = Quantity(
Expand Down Expand Up @@ -510,19 +510,12 @@ class XRDResultRSM(XRDResult):
m_def = Section()
q_parallel = Quantity(
type=HDF5Reference,
unit='meter**(-1)',
description='The scattering vector *Q_parallel* of the diffractogram',
)
q_perpendicular = Quantity(
type=HDF5Reference,
unit='meter**(-1)',
description='The scattering vector *Q_perpendicular* of the diffractogram',
)
intensity = Quantity(
type=HDF5Reference,
unit='dimensionless',
description='The count at each position, dimensionless',
)

def generate_plots(self, archive: 'EntryArchive', logger: 'BoundLogger'):
"""
Expand Down Expand Up @@ -613,8 +606,8 @@ def generate_plots(self, archive: 'EntryArchive', logger: 'BoundLogger'):

# Plot for RSM in Q-vectors
if self.q_parallel is not None and self.q_perpendicular is not None:
x = self.q_parallel.to('1/angstrom').magnitude.flatten()
y = self.q_perpendicular.to('1/angstrom').magnitude.flatten()
x = HDF5Reference.read_dataset(archive, self.q_parallel).flatten()
y = HDF5Reference.read_dataset(archive, self.q_perpendicular).flatten()
# q_vectors lead to irregular grid
# generate a regular grid using interpolation
x_regular = np.linspace(x.min(), x.max(), z.shape[0])
Expand Down Expand Up @@ -695,27 +688,39 @@ def generate_plots(self, archive: 'EntryArchive', logger: 'BoundLogger'):

return plots

def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger'):
super().normalize(archive, logger)
if self.name is None:
self.name = 'RSM Scan Result'
def calculate_q_components_for_RSM(self):
"""
Calculate the q-vectors for RSM scans in coplanar configuration.
"""
if self.source_peak_wavelength is not None:
source_peak_wavelength = self.source_peak_wavelength
else:
source_peak_wavelength = xrd_dict.get('eln_dict').get('kalpha_one', None)
source_peak_wavelength = source_peak_wavelength * ureg(
xrd_dict.get('eln_dict').get('kalpha_one/units', None)
)
if source_peak_wavelength is not None:
for var_axis in ['Omega', 'Chi', 'Phi']:
if (
xrd_dict[var_axis] is not None
and len(np.unique(xrd_dict[var_axis])) > 1
and len(np.unique(xrd_dict[var_axis].magnitude)) > 1
):
(
xrd_dict['q_parallel'],
xrd_dict['q_perpendicular'],
) = calculate_q_vectors_RSM(
wavelength=self.source_peak_wavelength,
) = calculate_q_vectors(
wavelength=source_peak_wavelength.to('angstrom'),
two_theta=xrd_dict['2Theta']
* np.ones_like(xrd_dict['intensity']),
omega=xrd_dict[var_axis],
)
break

def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger'):
super().normalize(archive, logger)
if self.name is None:
self.name = 'RSM Scan Result'


class XRayDiffraction(Measurement):
"""
Expand Down Expand Up @@ -926,21 +931,23 @@ def write_xrd_data(
elif scan_type == 'rsm':
result = XRDResultRSM(
intensity=f'{nx_out_f}#/entry/experiment_result/intensity',
two_theta=f'{nx_out_f}#/entry/experiment_result/intensity',
two_theta=f'{nx_out_f}#/entry/experiment_result/two_theta',
omega=f'{nx_out_f}#/entry/experiment_result/omega',
chi=f'{nx_out_f}#/entry/experiment_result/chi',
phi=f'{nx_out_f}#/entry/experiment_result/phi',
q_parallel=f'{nx_out_f}#/entry/experiment_result/q_parallel',
q_perpendicular=f'{nx_out_f}#/entry/experiment_result/q_perpendicular',
scan_axis=metadata_dict.get('scan_axis', None),
integration_time=xrd_dict.get('countTime', None),
)
result.calculate_q_components_for_RSM()
else:
raise NotImplementedError(f'Scan type `{scan_type}` is not supported.')
xrd = ELNXRayDiffraction(
results=[result],
xrd_settings=xrd_settings,
samples=samples,
)

write_nx_section_and_create_file(
archive,
logger,
Expand Down
10 changes: 9 additions & 1 deletion tests/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import pytest
from nomad.client import normalize_all, parse
from nomad.datamodel.hdf5 import HDF5Reference


@pytest.fixture(
Expand Down Expand Up @@ -59,7 +60,14 @@ def test_normalize_all(parsed_archive):
assert parsed_archive.data.results[
0
].source_peak_wavelength.magnitude == pytest.approx(1.540598, 1e-2)
if len(parsed_archive.data.results[0].intensity.shape) == 1:
if (
len(
HDF5Reference.read_dataset(
parsed_archive, parsed_archive.data.results[0].intensity
).shape
)
== 1
):
assert parsed_archive.results.properties.structural.diffraction_pattern[
0
].incident_beam_wavelength.magnitude * 1e10 == pytest.approx(1.540598, 1e-2)
1 change: 0 additions & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
PureSubstanceComponent,
PureSubstanceSection,
)

from nomad_measurements.utils import (
merge_sections,
)
Expand Down

0 comments on commit 9b22316

Please sign in to comment.