Skip to content

Commit

Permalink
Add ORSO providers
Browse files Browse the repository at this point in the history
  • Loading branch information
jl-wynen committed Feb 2, 2024
1 parent 43d7e0c commit 611bf76
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 91 deletions.
27 changes: 1 addition & 26 deletions src/essreflectometry/amor/load.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,32 +153,7 @@ def extract_events(
data.coords['position'].fields.y += data.coords['position'].fields.z * sc.tan(
2.0 * data.coords['sample_rotation'] - (0.955 * sc.units.deg)
)
return RawData[Run](data)


# TODO
# def populate_orso(orso: Any, data: sc.DataGroup, filename: str) -> Any:
# """
# Populate the Orso object, by calling the :code:`base_orso` and adding data from the
# file.
#
# Parameters
# ----------
# orso:
# The orso object to be populated by additional information from the loaded file.
# data:
# Data group to source information from.
# Should mimic the structure of the NeXus file.
# filename:
# Path of the file to load.
# """
# orso.data_source.experiment.title = data['title']
# orso.data_source.experiment.instrument = data['name']
# orso.data_source.experiment.start_date = datetime.strftime(
# datetime.strptime(data['start_time'][:-3], '%Y-%m-%dT%H:%M:%S.%f'),
# '%Y-%m-%d',
# )
# orso.data_source.measurement.data_files = [filename]
return RawEvents[Run](data)


providers = (extract_events, load_raw_nexus)
133 changes: 76 additions & 57 deletions src/essreflectometry/amor/orso.py
Original file line number Diff line number Diff line change
@@ -1,60 +1,79 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
import platform
from datetime import datetime

from orsopy import fileio

from .. import __version__


def make_orso(
owner: fileio.base.Person,
sample: fileio.data_source.Sample,
creator: fileio.base.Person,
reduction_script: str,
) -> fileio.orso.Orso:
"""
Generate the base Orso object for the Amor instrument.
Populate the Orso object for metadata storage.
Parameters
----------
owner:
The owner of the data set, i.e. the main proposer of the measurement.
sample:
A description of the sample.
creator:
The creator of the reduced data, the person responsible for the
reduction process.
reduction_script:
The script or notebook used for reduction.
Returns
-------
:
Orso object with the default parameters for the Amor instrument.
"""
orso = fileio.orso.Orso.empty()
orso.data_source.experiment.probe = 'neutrons'
orso.data_source.experiment.facility = 'Paul Scherrer Institut'
orso.data_source.measurement.scheme = 'angle- and energy-dispersive'
orso.reduction.software = fileio.reduction.Software(
'scipp-ess', __version__, platform.platform()
"""ORSO utilities for Amor."""
import os
from typing import Optional

from dateutil.parser import parse as parse_datetime
from orsopy.fileio import base as orso_base
from orsopy.fileio import data_source

from ..orso import (
OrsoExperiment,
OrsoInstrument,
OrsoMeasurement,
OrsoOwner,
OrsoSample,
)
from ..types import Filename, RawData, Reference, Run, Sample


def parse_orso_experiment(raw_data: RawData[Run]) -> OrsoExperiment[Run]:
"""Parse ORSO experiment data from raw Amor NeXus data."""
return OrsoExperiment(
data_source.Experiment(
title=raw_data['title'],
instrument=raw_data['name'],
facility=raw_data['facility'],
start_date=parse_datetime(raw_data['start_time']),
probe='neutron',
)
)


def parse_orso_owner(raw_data: RawData[Run]) -> OrsoOwner[Run]:
"""Parse ORSO owner data from raw Amor NeXus data."""
return OrsoOwner(
orso_base.Person(
name=raw_data['user']['name'],
contact=raw_data['user']['email'],
affiliation=None,
)
)
orso.reduction.timestep = datetime.now()
orso.reduction.corrections = []
orso.reduction.computer = platform.node()
orso.columns = [
fileio.base.Column('Qz', '1/angstrom', 'wavevector transfer'),
fileio.base.Column('R', None, 'reflectivity'),
fileio.base.Column('sR', None, 'standard deivation of reflectivity'),
fileio.base.Column(
'sQz', '1/angstrom', 'standard deviation of wavevector transfer resolution'
),
]
orso.data_source.owner = owner
orso.data_source.sample = sample
orso.reduction.creator = creator
orso.reduction.script = reduction_script
return orso


def parse_orso_sample(raw_data: RawData[Run]) -> OrsoSample[Run]:
"""Parse ORSO sample data from raw Amor NeXus data."""
if not raw_data.get('sample'):
return OrsoSample(data_source.Sample.empty())
raise NotImplementedError('Amor NsXus sample parsing is not implemented')


def build_orso_measurement(
sample_filename: Filename[Sample],
reference_filename: Filename[Reference],
instrument: Optional[OrsoInstrument],
) -> OrsoMeasurement:
"""Assemble ORSO measurement data."""
# TODO populate timestamp
# doesn't work with a local file because we need the timestamp of the original,
# SciCat can provide that
return OrsoMeasurement(
data_source.Measurement(
instrument_settings=instrument,
data_files=[orso_base.File(file=os.path.basename(sample_filename))],
additional_files=[
orso_base.File(
file=os.path.basename(reference_filename), comment='supermirror'
)
],
)
)


providers = (
parse_orso_experiment,
build_orso_measurement,
parse_orso_owner,
parse_orso_sample,
)
102 changes: 94 additions & 8 deletions src/essreflectometry/orso.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,101 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
import warnings
"""ORSO utilities for reflectometry."""
import platform
from datetime import datetime, timezone
from typing import NewType, Optional

import sciline
from orsopy.fileio import base as orso_base
from orsopy.fileio import data_source, reduction

def not_found_warning():
from . import __version__
from .types import Reference, Run, Sample


class OrsoExperiment(
sciline.Scope[Run, data_source.Experiment], data_source.Experiment
):
"""ORSO experiment for a run."""


class OrsoInstrument(
sciline.Scope[Run, data_source.InstrumentSettings], data_source.InstrumentSettings
):
"""ORSO instrument settings for a run."""


class OrsoOwner(sciline.Scope[Run, orso_base.Person], orso_base.Person):
"""ORSO owner of a file."""


class OrsoReduction(sciline.Scope[Run, reduction.Reduction], reduction.Reduction):
"""ORSO measurement for a run."""


class OrsoSample(sciline.Scope[Run, data_source.Sample], data_source.Sample):
"""ORSO sample of a run."""


OrsoCreator = NewType('OrsoCreator', orso_base.Person)
"""ORSO creator, that is, the person who processed the data."""

OrsoDataSource = NewType('OrsoDataSource', data_source.DataSource)
"""ORSO data source."""

OrsoMeasurement = NewType('OrsoMeasurement', data_source.Measurement)
"""ORSO measurement."""


def build_orso_reduction(creator: Optional[OrsoCreator]) -> OrsoReduction:
"""Construct ORSO reduction data.
This assumes that ess.reflectometry is the primary piece of software
used to reduce the data.
"""
A function to raise a orso specific error if necessary.
return OrsoReduction(
reduction.Reduction(
software=reduction.Software(
name='ess.reflectometry',
version=str(__version__),
platform=platform.system(),
),
timestamp=datetime.now(tz=timezone.utc),
creator=creator,
corrections=[],
)
)


def build_orso_data_source(
owner: Optional[OrsoOwner[Sample]],
sample: Optional[OrsoSample[Sample]],
sample_experiment: Optional[OrsoExperiment[Sample]],
reference_experiment: Optional[OrsoExperiment[Reference]],
measurement: Optional[OrsoMeasurement],
) -> OrsoDataSource:
"""Judiciously assemble an ORSO DataSource.
Makes some assumptions about how sample and reference runs should be merged,
giving precedence to the sample run.
"""
warnings.warn(
"For metadata to be logged in the data array, "
"it is necessary to install the orsopy package.",
UserWarning,
stacklevel=2,
# We simply assume that the owner of the reference measurement
# has no claim on this data.
if (sample_experiment.facility != reference_experiment.facility) or (
sample_experiment.instrument != reference_experiment.instrument
):
raise ValueError(
'The sample and reference experiments were done at different instruments'
)

return OrsoDataSource(
data_source.DataSource(
owner=owner,
sample=sample,
experiment=sample_experiment,
measurement=measurement,
)
)


providers = (build_orso_reduction, build_orso_data_source)

0 comments on commit 611bf76

Please sign in to comment.