Skip to content

Commit

Permalink
Better reference methods
Browse files Browse the repository at this point in the history
  • Loading branch information
lucas-wilkins committed Oct 7, 2024
1 parent fb10792 commit df6d045
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 97 deletions.
3 changes: 2 additions & 1 deletion sasdata/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ def summary(self, indent = " ", include_raw=False):
for data in self._data_contents:
s += f"{indent}{data}\n"

s += f"{indent}Metadata:\n"
s += f"Metadata:\n"
s += "\n"
s += self.metadata.summary()

if include_raw:
Expand Down
188 changes: 105 additions & 83 deletions sasdata/metadata.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from tokenize import String

import numpy as np
from numpy.typing import ArrayLike

Expand All @@ -15,41 +17,41 @@ class Detector:
def __init__(self, target_object: AccessorTarget):

# Name of the instrument [string]
self.name = StringAccessor(target_object, "detector.name")
self.name = StringAccessor(target_object, "name")

# Sample to detector distance [float] [mm]
self.distance = LengthAccessor[float](target_object,
"detector.distance",
"detector.distance.units",
"distance",
"distance.units",
default_unit=units.millimeters)

# Offset of this detector position in X, Y,
# (and Z if necessary) [Vector] [mm]
self.offset = LengthAccessor[ArrayLike](target_object,
"detector.offset",
"detector.offset.units",
"offset",
"offset.units",
default_unit=units.millimeters)

self.orientation = AngleAccessor[ArrayLike](target_object,
"detector.orientation",
"detector.orientation.units",
"orientation",
"orientation.units",
default_unit=units.degrees)

self.beam_center = LengthAccessor[ArrayLike](target_object,
"detector.beam_center",
"detector.beam_center.units",
"beam_center",
"beam_center.units",
default_unit=units.millimeters)

# Pixel size in X, Y, (and Z if necessary) [Vector] [mm]
self.pixel_size = LengthAccessor[ArrayLike](target_object,
"detector.pixel_size",
"detector.pixel_size.units",
"pixel_size",
"pixel_size.units",
default_unit=units.millimeters)

# Slit length of the instrument for this detector.[float] [mm]
self.slit_length = LengthAccessor[float](target_object,
"detector.slit_length",
"detector.slit_length.units",
"slit_length",
"slit_length.units",
default_unit=units.millimeters)

def summary(self):
Expand All @@ -68,24 +70,24 @@ class Aperture:
def __init__(self, target_object: AccessorTarget):

# Name
self.name = StringAccessor(target_object, "aperture.name")
self.name = StringAccessor(target_object, "name")

# Type
self.type = StringAccessor(target_object, "aperture.type")
self.type = StringAccessor(target_object, "type")

# Size name - TODO: What is the name of a size
self.size_name = StringAccessor(target_object, "aperture.size_name")
self.size_name = StringAccessor(target_object, "size_name")

# Aperture size [Vector] # TODO: Wat!?!
self.size = QuantityAccessor[ArrayLike](target_object,
"aperture.size",
"aperture.size.units",
"size",
"size.units",
default_unit=units.millimeters)

# Aperture distance [float]
self.distance = LengthAccessor[float](target_object,
"apature.distance",
"apature.distance.units",
"distance",
"distance.units",
default_unit=units.millimeters)


Expand All @@ -103,11 +105,11 @@ class Collimation:
def __init__(self, target_object: AccessorTarget):

# Name
self.name = StringAccessor(target_object, "collimation.name")
self.name = StringAccessor(target_object, "name")
# Length [float] [mm]
self.length = LengthAccessor[float](target_object,
"collimation.length",
"collimation.length.units",
"length",
"length.units",
default_unit=units.millimeters)


Expand All @@ -130,53 +132,53 @@ class Source:

def __init__(self, target_object: AccessorTarget):
# Name
self.name = StringAccessor(target_object, "sassource.name")
self.name = StringAccessor(target_object, "name")

# Generic radiation type (Type and probe give more specific info) [string]
self.radiation = StringAccessor(target_object, "sassource.radiation")
self.radiation = StringAccessor(target_object, "radiation")

# Type and probe are only written to by the NXcanSAS reader
# Specific radiation type (Synchotron X-ray, Reactor neutron, etc) [string]
self.type = StringAccessor(target_object, "sassource.type")
self.type = StringAccessor(target_object, "type")

# Radiation probe (generic probe such as neutron, x-ray, muon, etc) [string]
self.probe_particle = StringAccessor(target_object, "sassource.probe")
self.probe_particle = StringAccessor(target_object, "probe")

# Beam size name
self.beam_size_name = StringAccessor(target_object, "sassource.beam_size_name")
self.beam_size_name = StringAccessor(target_object, "beam_size_name")

# Beam size [Vector] [mm]
self.beam_size = LengthAccessor[ArrayLike](target_object,
"sassource.beam_size",
"sassource.beam_size.units",
"beam_size",
"beam_size.units",
default_unit=units.millimeters)

# Beam shape [string]
self.beam_shape = StringAccessor(target_object, "sassource.beam_shape")
self.beam_shape = StringAccessor(target_object, "beam_shape")

# Wavelength [float] [Angstrom]
self.wavelength = LengthAccessor[float](target_object,
"sassource.wavelength",
"sassource.wavelength.units",
"wavelength",
"wavelength.units",
default_unit=units.angstroms)

# Minimum wavelength [float] [Angstrom]
self.wavelength_min = LengthAccessor[float](target_object,
"source.wavelength_min",
"source.wavelength_min.units",
"wavelength_min",
"wavelength_min.units",
default_unit=units.angstroms)

# Maximum wavelength [float] [Angstrom]
self.wavelength_max = LengthAccessor[float](target_object,
"source.wavelength_min",
"source.wavelength_max.units",
"wavelength_min",
"wavelength_max.units",
default_unit=units.angstroms)

# Wavelength spread [float] [Angstrom]
# Quantity because it might have other units, such as percent
self.wavelength_spread = QuantityAccessor[float](target_object,
"source.wavelength_spread",
"source.wavelength_spread.units",
"wavelength_spread",
"wavelength_spread.units",
default_unit=units.angstroms)

def summary(self) -> str:
Expand All @@ -187,13 +189,13 @@ def summary(self) -> str:
radiation = f"{self.radiation.value}"

return (f"Source:\n"
f" Radiation: {radiation}\n"
f" Shape: {self.beam_shape.value}\n"
f" Wavelength: {self.wavelength.value}\n"
f" Min. Wavelength: {self.wavelength_min.value}\n"
f" Max. Wavelength: {self.wavelength_max.value}\n"
f" Radiation: {radiation}\n"
f" Shape: {self.beam_shape.value}\n"
f" Wavelength: {self.wavelength.value}\n"
f" Min. Wavelength: {self.wavelength_min.value}\n"
f" Max. Wavelength: {self.wavelength_max.value}\n"
f" Wavelength Spread: {self.wavelength_spread.value}\n"
f" Beam Size: {self.beam_size.value}\n")
f" Beam Size: {self.beam_size.value}\n")



Expand All @@ -213,39 +215,39 @@ class Sample:
def __init__(self, target_object: AccessorTarget):

# Short name for sample
self.name = StringAccessor(target_object, "sample.name")
self.name = StringAccessor(target_object, "name")
# ID

self.sample_id = StringAccessor(target_object, "sample.id")
self.sample_id = StringAccessor(target_object, "id")

# Thickness [float] [mm]
self.thickness = LengthAccessor(target_object,
"sample.thickness",
"sample.thickness.units",
"thickness",
"thickness.units",
default_unit=units.millimeters)

# Transmission [float] [fraction]
self.transmission = FloatAccessor(target_object,"sample.transmission")
self.transmission = FloatAccessor(target_object,"transmission")

# Temperature [float] [No Default]
self.temperature = AbsoluteTemperatureAccessor(target_object,
"sample.temperature",
"sample.temperature.unit",
"temperature",
"temperature.unit",
default_unit=units.kelvin)
# Position [Vector] [mm]
self.position = LengthAccessor[ArrayLike](target_object,
"sample.position",
"sample.position.unit",
"position",
"position.unit",
default_unit=units.millimeters)

# Orientation [Vector] [degrees]
self.orientation = AngleAccessor[ArrayLike](target_object,
"sample.orientation",
"sample.orientation.unit",
"orientation",
"orientation.unit",
default_unit=units.degrees)

# Details
self.details = StringAccessor(target_object, "sample.details")
self.details = StringAccessor(target_object, "details")


# SESANS zacceptance
Expand Down Expand Up @@ -274,14 +276,14 @@ class Process:
performed on the data.
"""
def __init__(self, target_object: AccessorTarget):
self.name = StringAccessor(target_object, "sasprocess.name")
self.date = StringAccessor(target_object, "sasprocess.date")
self.description = StringAccessor(target_object, "sasprocess.description")
self.name = StringAccessor(target_object, "name")
self.date = StringAccessor(target_object, "date")
self.description = StringAccessor(target_object, "description")

#TODO: It seems like these might be lists of strings, this should be checked

self.term = StringAccessor(target_object, "sasprocess.term")
self.notes = StringAccessor(target_object, "sasprocess.notes")
self.term = StringAccessor(target_object, "term")
self.notes = StringAccessor(target_object, "notes")

def single_line_desc(self):
"""
Expand All @@ -305,24 +307,24 @@ class TransmissionSpectrum:
"""
def __init__(self, target_object: AccessorTarget):
# TODO: Needs to be multiple instances
self.name = StringAccessor(target_object, "transmission.")
self.timestamp = StringAccessor(target_object, "transmission.timestamp")
self.name = StringAccessor(target_object, "name")
self.timestamp = StringAccessor(target_object, "timestamp")

# Wavelength (float) [A]
self.wavelength = LengthAccessor[ArrayLike](target_object,
"transmission.wavelength",
"transmission.wavelength.units")
"wavelength",
"wavelength.units")

# Transmission (float) [unit less]
self.transmission = DimensionlessAccessor[ArrayLike](target_object,
"transmission.transmission",
"transmission.units",
"transmission",
"units",
default_unit=units.none)

# Transmission Deviation (float) [unit less]
self.transmission_deviation = DimensionlessAccessor[ArrayLike](target_object,
"transmission.transmission_deviation",
"transmission.transmission_deviation.units",
"transmission_deviation",
"transmission_deviation.units",
default_unit=units.none)


Expand All @@ -334,25 +336,45 @@ def summary(self) -> str:
f" Transmission: {self.transmission.value}\n")


class Metadata:
class Instrument:
def __init__(self, target: AccessorTarget):
self._target = target

self.aperture = Aperture(target)
self.collimation = Collimation(target)
self.detector = Detector(target)
self.process = Process(target)
self.sample = Sample(target)
self.source = Source(target)
self.transmission_spectrum = TransmissionSpectrum(target)
self.aperture = Aperture(target.with_path_prefix("sasaperture"))
self.collimation = Collimation(target.with_path_prefix("sascollimation"))
self.detector = Detector(target.with_path_prefix("sasdetector"))
self.source = Source(target.with_path_prefix("sassource"))

def summary(self):
return (
self.aperture.summary() +
self.collimation.summary() +
self.detector.summary() +
self.source.summary())


class Metadata:
def __init__(self, target: AccessorTarget):
self._target = target

self.instrument = Instrument(target.with_path_prefix("sasinstrument"))
self.process = Process(target.with_path_prefix("sasprocess"))
self.sample = Sample(target.with_path_prefix("sassample"))
self.transmission_spectrum = TransmissionSpectrum(target.with_path_prefix("sastransmission_spectrum"))

self._title = StringAccessor(target, "title")
self._run = StringAccessor(target, "run")
self._definitiion = StringAccessor(target, "definition")

self.title: str = self._title.value
self.run: str = self._run.value
self.definitiion: str = self._definitiion.value

def summary(self):
return (
f" {self.title}, Run: {self.run}\n" + " " + "="*len(self.title) +
"=======" +
"="*len(self.run) + "\n\n" +
f"Definition: {self.title}\n" +
self.process.summary() +
self.sample.summary() +
self.source.summary() +
self.transmission_spectrum.summary()
)
self.instrument.summary() +
self.transmission_spectrum.summary())
Loading

0 comments on commit df6d045

Please sign in to comment.