Source code for mxcubecore.HardwareObjects.MicrodiffAperture

# encoding: utf-8
#
#  Project name: MXCuBE
#  https://github.com/mxcube
#
#  This file is part of MXCuBE software.
#
#  MXCuBE is free software: you can redistribute it and/or modify
#  it under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  MXCuBE is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU Lesser General Public License for more details.
#
#  You should have received a copy of the GNU General Lesser Public License
#  along with MXCuBE. If not, see <http://www.gnu.org/licenses/>.
"""
MicrodiffAperture. Move the aperture in the beam to a specified value or
out of the beam.
The factor, which serves to calculate the flux, can be a single value or a
tuple of values per aperture size.

Example xml file:
<object class="MicrodiffAperture">
  <username>aperture</username>
  <exporter_address>wid30bmd2s:9001</exporter_address>
  <value_channel_name>CurrentApertureDiameterIndex</value_channel_name>
  <state_channel_name>State</state_channel_name>
  <-- either only factor -->
  <factor>(0.15, 0.3, 0.63, 0.9, 0.96)</factor>
  <!-- or complete, corresponding to label: (index, size[um], factor) -->
  <values>{"A10": (0, 10, 0.15), "A20": (1, 20, 0.3), "A30": (2, 30, 0.63), "A50": (3, 50, 0.9), "A75": (4, 75, 0.96)}</values>
  <object role="inout" href="/udiff_apertureinout"/>
</object>
"""

from ast import literal_eval
from enum import Enum

from mxcubecore.HardwareObjects.abstract.AbstractNState import BaseValueEnum
from mxcubecore.HardwareObjects.ExporterNState import ExporterNState

__copyright__ = """ Copyright © 2022 by the MXCuBE collaboration """
__license__ = "LGPLv3+"


[docs]class MicrodiffAperture(ExporterNState): """MicrodiffAperture class""" unit = "um" def __init__(self, name): super().__init__(name) self.inout_obj = None
[docs] def init(self): """Initialize the aperture""" super().init() # check if we have values other that UNKNOWN (no values in config) if len(self.VALUES) == 1: self._initialise_values() # now get the IN/OUT object self.inout_obj = self.get_object_by_role("inout") if self.inout_obj: self._initialise_inout()
def _set_value(self, value): """Set device to value Args: value (str, int, float or enum): Value to be set. """ if value.name in ("IN", "OUT"): _eval = self.inout_obj.value_to_enum(value.value) self.inout_obj.set_value(_eval, timeout=60) else: super()._set_value(value) # put the aperture in if self.inout_obj: self.inout_obj.set_value(self.inout_obj.VALUES.IN, timeout=60) def _initialise_inout(self): """Add IN and OUT to the values Enum""" values_dict = {item.name: item.value for item in self.inout_obj.VALUES} values_dict.update({item.name: item.value for item in self.VALUES}) self.VALUES = Enum("ValueEnum", values_dict) def _initialise_values(self): """Initialise the ValueEnum from the hardware Raises: RuntimeError: No aperture diameters defined. Factor and aperture diameter not the same number. Invalid factor values. """ predefined_postions = self._exporter.read_property("ApertureDiameters") if not predefined_postions: raise RuntimeError("No aperture diameters defined") values = {} try: # get the factors factor = literal_eval(self.get_property("factor")) if len(predefined_postions) == len(factor): for _pos, _fac in zip(predefined_postions, factor): values["A{0}".format(_pos)] = ( predefined_postions.index(_pos), _pos, _fac, ) else: raise RuntimeError("Factor and aperture diameter not the same number") except (ValueError, TypeError): raise RuntimeError("Invalid factor values") self.VALUES = Enum( "ValueEnum", dict(values, **{item.name: item.value for item in BaseValueEnum}), )
[docs] def get_factor(self, label): """Get the factor associated to a label. Args: (enum, str): label enum or name Returns: (float) or (tuple): Factor value """ if isinstance(label, str): try: return self.VALUES[label].value[2] except (KeyError, ValueError, IndexError): return 1.0 try: return label.value[2] except (ValueError, IndexError): return 1.0
[docs] def get_size(self, label): """Get the aperture size associated to a label. Args: (enum, str): label enum or name Returns: (float): Factor value Raises: RuntimeError: Unknown aperture size. """ if isinstance(label, str): try: return float(self.VALUES[label].value[1]) except (KeyError, ValueError, IndexError): raise RuntimeError("Unknown aperture size") try: return float(label.value[1]) except (ValueError, IndexError): if self.inout_obj: return None raise RuntimeError("Unknown aperture size")
[docs] def get_diameter_size_list(self): """Get the list of values to be visible. Hide IN, OUT and UNKNOWN. Returns: (list): List of available aperture values (string). """ values = [] for value in self.VALUES: _nam = value.name if _nam not in ["IN", "OUT", "UNKNOWN"]: values.append(_nam) return values