Source code for pylablib.aux_libs.devices.AndorShamrock

from .AndorShamrock_lib import lib, ShamrockLibError

from ...core.devio import data_format
from ...core.devio.interface import IDevice
from ...core.utils import funcargparse, py3, dictionary, strpack, general
from ...core.dataproc import image as image_utils

_depends_local=[".AndorShamrock_lib","...core.devio.interface"]

import numpy as np
import collections
import contextlib
import ctypes
import threading
import time

[docs]class ShamrockError(RuntimeError): "Generic Andor Shamrock error."
[docs]class ShamrockNotSupportedError(ShamrockError): "Option not supported."
[docs]def get_spectrographs_number(): """Get number of connected Andor cameras""" with lib.using_handle(): return lib.ShamrockGetNumberDevices()
[docs]class ShamrockSpectrograph(IDevice): """ Shaprock spectrograph. Args: idx(int): spectrograph index (starting from 0; use :func:`get_spectrographs_number` to get the total number of connected spectrogaphs) """ def __init__(self, idx=0): IDevice.__init__(self) self.idx=idx self._opened=False self.open() self._add_full_info_node("model_data",self.get_model_data) self._add_full_info_node("optical_parameters",self.get_optical_parameters) self._add_full_info_node("gratings_number",self.get_gratings_number) self._add_status_node("grating_infos",lambda: [self.get_grating_info(g) for g in range(1,self.get_gratings_number()+1)]) self._add_settings_node("grating",self.get_grating,self.set_grating) self._add_settings_node("grating_offsets",self._get_all_grating_offsets,self._set_all_grating_offsets) self._add_settings_node("detector_offset",self.get_detector_offset,self.set_detector_offset) self._add_full_info_node("wavelength_present",self.is_wavelength_control_present) self._add_full_info_node("wavelength_limits",lambda: [self.get_wavelength_limits(g) for g in range(1,self.get_gratings_number()+1)],ignore_error=(ShamrockError,)) self._add_settings_node("wavelength",self.get_wavelength,self.set_wavelength,ignore_error=(ShamrockError,)) self._add_status_node("zero_order",self.is_at_zero_order,ignore_error=(ShamrockError,)) self._add_full_info_node("slits_present",lambda: [self.is_slit_present(s) for s in range(1,5)]) self._add_settings_node("slit_widths",self._get_all_slit_widths,self._set_all_slit_widths) self._add_full_info_node("shutter_present",self.is_shutter_present) self._add_settings_node("shutter_mode",self.get_shutter,self.set_shutter,ignore_error=(ShamrockError,)) self._add_full_info_node("filter_present",self.is_filter_present) self._add_settings_node("filter",self.get_filter,self.set_filter,ignore_error=(ShamrockError,)) self._add_full_info_node("flippers_present",lambda: [self.is_flipper_present(s) for s in range(1,3)]) self._add_settings_node("flipper_ports",self._get_all_flipper_ports,self._set_all_flipper_ports) self._add_full_info_node("accessory_present",self.is_accessory_present) self._add_settings_node("accessory_states",self._get_all_accessory_states,self._set_all_accessory_states) self._add_settings_node("pixel_width",self.get_pixel_width,self.set_pixel_width) self._add_settings_node("number_pixels",self.get_number_pixels,self.set_number_pixels) self._add_status_node("calibration",self.get_calibration)
[docs] def open(self): """Open connection to the camera""" if not self._opened: lib.open_handle() ncams=get_spectrographs_number() if self.idx>=ncams: lib.close_handle() raise ShamrockError("spectrograph index {} is not available ({} spectrograph exist)".format(self.idx,ncams)) self._opened=True
[docs] def close(self): """Close connection to the camera""" if self._opened: lib.close_handle() self._opened=False
[docs] def is_opened(self): """Check if the device is connected""" return self._opened
ModelData=collections.namedtuple("ModelData",["serial_number"])
[docs] def get_model_data(self): """ Get camera model data. Return tuple ``(serial_number)``. """ serial_number=lib.ShamrockGetSerialNumber(self.idx) return self.ModelData(serial_number)
OpticalParameters=collections.namedtuple("OpticalParameters",["focal_length","angular_deviation","focal_tilt"])
[docs] def get_optical_parameters(self): """ Get device optical parameters. Return tuple ``(focal_length, angular_deviation, focal_tilt)``. """ params=lib.ShamrockEepromGetOpticalParams(self.idx) return self.OpticalParameters(*params)
### Grating control ###
[docs] def get_gratings_number(self): """Get number of gratings""" return lib.ShamrockGetNumberGratings(self.idx)
def _check_grating(self, grating): if grating is None: return self.get_grating() if grating<1 or grating>self.get_gratings_number(): raise ValueError("incorrect grating index: {}; should be between 1 and {}".format(grating,self.get_gratings_number())) return grating
[docs] def get_grating(self): """Get current grating index (counting from 1)""" return lib.ShamrockGetGrating(self.idx)
[docs] def set_grating(self, grating, force=False): """ Set current grating (counting from 1) Call blocks until the grating is exchanged (up to 10-20 seconds). If ``force==False`` and the current grating index is the same as requested, skip the call; otherwise, call the grating set command regardless (takes about a second in the grating is unchaged). """ grating=self._check_grating(grating) if force or self.get_grating()!=grating: lib.ShamrockSetGrating(self.idx,grating) return self.get_grating()
GratingInfo=collections.namedtuple("GratingInfo",["lines","blaze_wavelength","home","offset"])
[docs] def get_grating_info(self, grating=None): """ Get info of a given grating (by default, current grating). Return tuple ``(lines, blaze_wavelength, home, offset)`` (blazing wavelength is in nm). """ grating=self._check_grating(grating) return self.GratingInfo(*lib.ShamrockGetGratingInfo(self.idx,grating))
[docs] def get_grating_offset(self, grating=None): """Get grating offset (in steps) for a given grating (by default, current grating)""" grating=self._check_grating(grating) return lib.ShamrockGetGratingOffset(self.idx,grating)
[docs] def set_grating_offset(self, offset, grating=None): """Set grating offset (in steps) for a given grating (by default, current grating)""" grating=self._check_grating(grating) lib.ShamrockSetGratingOffset(self.idx,grating,offset) return self.get_grating_offset(grating)
def _get_all_grating_offsets(self): return [self.get_grating_offset(g) for g in range(1,self.get_gratings_number()+1)] def _set_all_grating_offsets(self, offsets): for g,o in enumerate(offsets,start=1): if o is not None: self.set_grating_offset(g,o)
[docs] def get_detector_offset(self): """Get detector offset (in steps)""" return lib.ShamrockGetDetectorOffset(self.idx)
[docs] def set_detector_offset(self, offset): """Set detector offset (in steps)""" lib.ShamrockSetDetectorOffset(self.idx,offset) return self.get_detector_offset()
[docs] def get_turret(self): """Get turrent""" return lib.ShamrockGetTurret(self.idx)
[docs] def set_turret(self, turret): """Set turret""" lib.ShamrockSetTurret(self.idx,turret) return self.get_turret()
### Wavelength control ###
[docs] def is_wavelength_control_present(self): """Check if wavelength control is present""" return bool(lib.ShamrockWavelengthIsPresent(self.idx))
def _check_wavelength(self): if not self.is_wavelength_control_present(): raise ShamrockError("wavelength control is not preset")
[docs] def get_wavelength(self): """Get current central wavelength (in m)""" self._check_wavelength() return lib.ShamrockGetWavelength(self.idx)*1E-9
[docs] def set_wavelength(self, wavelength): """Get current central wavelength (in m)""" self._check_wavelength() lib.ShamrockSetWavelength(self.idx,wavelength/1E-9) return self.get_wavelength()
[docs] def get_wavelength_limits(self, grating=None): """Get wavelength limits (in m) for a given grating (by default, current grating)""" self._check_wavelength() grating=self._check_grating(grating) lim=lib.ShamrockGetWavelengthLimits(self.idx,grating) return lim[0]*1E-9,lim[1]*1E-9
[docs] def reset_wavelength(self): """Reset current wavelength to 0 nm""" self._check_wavelength() lib.ShamrockWavelengthReset(self.idx) return self.get_wavelength()
[docs] def is_at_zero_order(self): """Check if current grating is at zero order""" self._check_wavelength() return bool(lib.ShamrockAtZeroOrder(self.idx))
[docs] def goto_zero_order(self): """Set current grating to zero order""" self._check_wavelength() lib.ShamrockGotoZeroOrder(self.idx) return self.is_at_zero_order()
### Slit control ### _default_slits={"input_side":1,"input_direct":2,"output_side":3,"output_direct":4} def _slit_idx(self, slit): return self._default_slits.get(slit,slit)
[docs] def is_slit_present(self, slit): """ Check if the slit is present. `slit` cen be either a slit index (starting from 1), or one of the following: ``"input_side"``, ``"input_direct"``, ``"output_side"``, or ``"output_direct"``. """ slit=self._slit_idx(slit) return bool(lib.ShamrockAutoSlitIsPresent(self.idx,slit))
def _check_slit(self, slit): if not self.is_slit_present(slit): raise ShamrockError("slit {} is not preset".format(slit)) return self._slit_idx(slit)
[docs] def get_slit_width(self, slit): """ Get slit width (in m). `slit` cen be either a slit index (starting from 1), or one of the following: ``"input_side"``, ``"input_direct"``, ``"output_side"``, or ``"output_direct"``. """ slit=self._check_slit(slit) return lib.ShamrockGetAutoSlitWidth(self.idx,slit)*1E-6
[docs] def set_slit_width(self, slit, width): """ Set slit width (in m). `slit` cen be either a slit index (starting from 1), or one of the following: ``"input_side"``, ``"input_direct"``, ``"output_side"``, or ``"output_direct"``. """ slit=self._check_slit(slit) lib.ShamrockSetAutoSlitWidth(self.idx,slit,width/1E-6) return self.get_slit_width(slit)
def _get_all_slit_widths(self): return [self.get_slit_width(s) if self.is_slit_present(s) else None for s in range(1,5)] def _set_all_slit_widths(self, widths): for s,w in enumerate(widths,start=1): if w is not None: self.set_slit_width(s,w)
[docs] def reset_slit(self, slit): """ Reset slit to the default width (10 um). `slit` cen be either a slit index (starting from 1), or one of the following: ``"input_side"``, ``"input_direct"``, ``"output_side"``, or ``"output_direct"``. """ slit=self._check_slit(slit) lib.ShamrockAutoSlitReset(self.idx,slit) return self.get_slit_width(slit)
### Shutter control ###
[docs] def is_shutter_present(self): """Check if the shutter is present""" return bool(lib.ShamrockShutterIsPresent(self.idx))
def _check_shutter(self): if not self.is_shutter_present(): raise ShamrockError("shutter is not preset") _shutter_modes={0:"closed",1:"opened",-1:"not_set"}
[docs] def get_shutter(self): """ Get shutter mode. Can return ``"closed"``, ``"opened"``, or ``"not_set"``. """ self._check_shutter() mode=lib.ShamrockGetShutter(self.idx) return self._shutter_modes[mode]
[docs] def set_shutter(self, mode): """Set shutter mode""" self._check_shutter() mode=0 if mode in [False,"closed"] else 1 lib.ShamrockSetShutter(self.idx,mode) return self.get_shutter()
### Filter control ###
[docs] def is_filter_present(self): """Check if the filter is present""" return bool(lib.ShamrockFilterIsPresent(self.idx))
def _check_filter(self): if not self.is_filter_present(): raise ShamrockError("filter is not preset")
[docs] def get_filter(self): """Get current filter""" self._check_filter() return lib.ShamrockGetFilter(self.idx)
[docs] def set_filter(self, filter): """Set current flilter""" self._check_filter() lib.ShamrockSetFilter(self.idx,filter) return self.get_filter()
[docs] def get_filter_info(self, filter): """Get info of the given filter""" self._check_filter() return lib.ShamrockGetFilterInfo(self.idx,filter)
[docs] def reset_filter(self): """Reset flilter to default position""" self._check_filter() lib.ShamrockFilterReset(self.idx) return self.get_filter()
### Filpper control ### _default_filpperss={"input":1,"output":2} def _flipper_idx(self, flipper): return self._default_filpperss.get(flipper,flipper)
[docs] def is_flipper_present(self, flipper): """ Check if the flipper is present. `flipper` cen be either a flipper index (starting from 1), or one of the following: ``"input"``, or `"output"``. """ flipper=self._flipper_idx(flipper) return bool(lib.ShamrockFlipperMirrorIsPresent(self.idx,flipper))
def _check_flipper(self, flipper): if not self.is_flipper_present(flipper): raise ShamrockError("flipper {} is not preset".format(flipper)) return self._slit_idx(flipper) _flipper_ports={0:"direct",1:"size"}
[docs] def get_flipper_port(self, flipper): """ Get flipper port. `flipper` cen be either a flipper index (starting from 1), or one of the following: ``"input"``, or `"output"``. Return either ``"direct"`` or ``"side"``. """ flipper=self._check_flipper(flipper) port=lib.ShamrockGetFlipperMirror(self.idx,flipper) return self._flipper_ports[port]
[docs] def set_flipper_port(self, flipper, port): """ Set flipper port. `flipper` cen be either a flipper index (starting from 1), or one of the following: ``"input"``, or `"output"``. Port can be a numerical value (0 or 1), ``"direct"``, or ``"side"``. """ flipper=self._check_flipper(flipper) port=0 if port in [0,False,"direct"] else 1 lib.ShamrockSetFlipperMirror(self.idx,flipper,port) return self.get_flipper_port(flipper)
def _get_all_flipper_ports(self): return [self.get_flipper_port(f) if self.is_flipper_present(f) else None for f in range(1,3)] def _set_all_flipper_ports(self, ports): for f,p in enumerate(ports,start=1): if p is not None: self.set_flipper_port(f,p)
[docs] def reset_flipper(self, flipper): """ Reset flipper to the default state. `flipper` cen be either a flipper index (starting from 1), or one of the following: ``"input"``, or `"output"``. """ flipper=self._check_flipper(flipper) lib.ShamrockFlipperMirrorReset(self.idx,flipper) return self.get_flipper_port(flipper)
### Accessory control ###
[docs] def is_accessory_present(self): """Check if the accessory is present""" return bool(lib.ShamrockAccessoryIsPresent(self.idx))
def _check_accessory(self): if not self.is_accessory_present(): raise ShamrockError("accessory is not preset")
[docs] def get_accessory_state(self, line): """Get current accessory state on a given line (1 or 2)""" self._check_accessory() return lib.ShamrockGetAccessoryState(self.idx,line)
[docs] def set_accessory_state(self, line, state): """Set current accessory state (0 or 1) on a given line (1 or 2)""" self._check_accessory() lib.ShamrockSetAccessory(self.idx,line,state) return self.get_accessory_state(line)
def _get_all_accessory_states(self): return [self.get_accessory_state(l) if self.is_accessory_present() else None for l in range(1,3)] def _set_all_accessory_states(self, states): for l,s in enumerate(states,start=1): if s is not None: self.set_accessory_state(l,s) ### Calibration ###
[docs] def get_pixel_width(self): """Get current set detector pixel width (in m)""" return lib.ShamrockGetPixelWidth(self.idx)*1E-6
[docs] def set_pixel_width(self, width): """Set current detector pixel width (in m)""" lib.ShamrockSetPixelWidth(self.idx,width/1E-6) return self.get_pixel_width()
[docs] def get_number_pixels(self): """Get current set detector number of pixels""" return lib.ShamrockGetNumberPixels(self.idx)
[docs] def set_number_pixels(self, number): """Set current detector number of pixels""" lib.ShamrockSetNumberPixels(self.idx,number) return self.get_number_pixels()
[docs] def setup_from_camera(self, cam): """Setup detector parameters (number of pixels, pixel width) from the camera""" pixel_size=cam.get_pixel_size() det_size=cam.get_detector_size() self.set_pixel_width(pixel_size[0]) self.set_number_pixels(det_size[0]) return self.get_pixel_width(),self.get_number_pixels()
[docs] def get_calibration(self): """ Get wavelength calibration. Return numpy array with number equal preset number of detector pixels, which specifies wavelength (in m) corresponding to each pixel. """ return np.array(lib.ShamrockGetCalibration(self.idx,self.get_number_pixels()))*1E-9