Source code for ess.polarization.supermirror
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Generic
import sciline
import scipp as sc
from .types import PlusMinus, PolarizingElement, TransmissionFunction
[docs]
class SupermirrorEfficiencyFunction(Generic[PolarizingElement], ABC):
"""Base class for supermirror efficiency functions"""
@abstractmethod
def __call__(self, *, wavelength: sc.Variable) -> sc.DataArray:
"""Return the efficiency of a supermirror for a given wavelength"""
[docs]
@dataclass
class SecondDegreePolynomialEfficiency(
SupermirrorEfficiencyFunction[PolarizingElement]
):
"""
Efficiency of a supermirror as a second-degree polynomial
The efficiency is given by a * wavelength^2 + b * wavelength + c
Parameters
----------
a:
Coefficient of the quadratic term, with unit of 1/angstrom^2
b:
Coefficient of the linear term, with unit of 1/angstrom
c:
Constant term, dimensionless
"""
a: sc.Variable
b: sc.Variable
c: sc.Variable
def __call__(self, *, wavelength: sc.Variable) -> sc.DataArray:
"""Return the efficiency of a supermirror for a given wavelength"""
return (
(self.a * wavelength**2).to(unit='', copy=False)
+ (self.b * wavelength).to(unit='', copy=False)
+ self.c.to(unit='', copy=False)
)
@dataclass
class SupermirrorTransmissionFunction(TransmissionFunction[PolarizingElement]):
"""Wavelength-dependent transmission of a supermirror"""
efficiency_function: SupermirrorEfficiencyFunction
def __call__(
self, *, wavelength: sc.Variable, plus_minus: PlusMinus
) -> sc.DataArray:
"""Return the transmission fraction for a given wavelength"""
efficiency = self.efficiency_function(wavelength=wavelength)
if plus_minus == 'plus':
return 0.5 * (1 + efficiency)
else:
return 0.5 * (1 - efficiency)
def apply(self, data: sc.DataArray, plus_minus: PlusMinus) -> sc.DataArray:
"""Apply the transmission function to a data array"""
return self(wavelength=data.coords['wavelength'], plus_minus=plus_minus)
def get_supermirror_transmission_function(
efficiency_function: SupermirrorEfficiencyFunction[PolarizingElement],
) -> TransmissionFunction[PolarizingElement]:
return SupermirrorTransmissionFunction[PolarizingElement](
efficiency_function=efficiency_function
)
[docs]
def SupermirrorWorkflow() -> sciline.Pipeline:
"""
Workflow for computing transmission functions for supermirror polarizing elements.
"""
return sciline.Pipeline((get_supermirror_transmission_function,))