class ALBAPilatus(AbstractDetector, HardwareObject): """Detector class. Contains all information about detector - states are 'OK', and 'BAD' - status is busy, exposing, ready, etc. - physical property is RH for pilatus, P for rayonix """ def __init__(self, name): AbstractDetector.__init__(self) HardwareObject.__init__(self, name) self.distance_motor_hwobj = None self.default_distance = None self.default_distance_limits = None self.default_latency_time = 0.003 self.exp_time_limits = None self.headers = {} def init(self): self.distance_motor_hwobj = self.getObjectByRole("distance_motor") self.devname = self.getProperty("tangoname") try: self.latency_time = float(self.getProperty("latency_time")) except Exception: self.latency_time = None if self.latency_time is None: logging.getLogger("HWR").debug( "Cannot obtain latency time from Pilatus XML. Using %s" % self.default_latency_time) self.latency_time = self.default_latency_time self.devspecific = self.getProperty("device_specific") exp_time_limits = self.getProperty("exposure_limits") self.exp_time_limits = map(float, exp_time_limits.strip().split(",")) self.device = DeviceProxy(self.devname) self.device_specific = DeviceProxy(self.devspecific) self.device.set_timeout_millis(30000) self.beamx_chan = self.get_channel_object("beamx") self.beamy_chan = self.get_channel_object("beamy") def start_acquisition(self): self.device.startAcq() def stop_acquisition(self): self.device.abortAcq() def wait_move_distance_done(self): self.distance_motor_hwobj.wait_end_of_move() def get_threshold(self): return self.device_specific.threshold def get_threshold_gain(self): return self.device_specific.threshold_gain def has_shutterless(self): """Return True if has shutterless mode""" return True def get_beam_centre(self): """Returns beam center coordinates""" beam_x = 0 beam_y = 0 try: beam_x = self.beamx_chan.getValue() beam_y = self.beamy_chan.getValue() except Exception: pass return beam_x, beam_y def get_manufacturer(self): return self.getProperty("manufacturer") return "Dectris" def get_model(self): return self.getProperty("model") def get_detector_type(self): return self.getProperty("type") def get_default_exposure_time(self): return self.getProperty("default_exposure_time") def get_minimum_exposure_time(self): return self.getProperty("minimum_exposure_time") def get_exposure_time_limits(self): """Returns exposure time limits as list with two floats""" return self.exp_time_limits def get_file_suffix(self): return self.getProperty("file_suffix") def get_pixel_size(self): return self.getProperty("px"), self.getProperty("py") # methods for data collection def set_energy_threshold(self): eugap_ch = self.get_channel_object("eugap") try: currentenergy = eugap_ch.getValue() except Exception: currentenergy = 12.6 det_energy = self.get_threshold() # threshold = det_energy / 2. # limitenergy = threshold / 0.8 if round(currentenergy, 6) < 7.538: currentenergy = 7.538 kev_diff = abs(det_energy - currentenergy) if kev_diff > 1.2: logging.getLogger("HWR").debug( "programming energy_threshold on pilatus to: %s" % currentenergy) # if self.wait_standby(): # self.device_specific.energy_threshold = currentenergy def get_latency_time(self): return self.latency_time def wait_standby(self, timeout=300): t0 = time.time() while self.device_specific.cam_state == "STANDBY": if time.time() - t0 > timeout: print("timeout waiting for Pilatus to be on STANDBY") return False time.sleep(0.1) return True def prepare_acquisition(self, dcpars): self.set_energy_threshold() # self.wait_standby() osc_seq = dcpars["oscillation_sequence"][0] file_pars = dcpars["fileinfo"] basedir = file_pars["directory"] prefix = "%s_%s_" % (file_pars["prefix"], file_pars["run_number"]) first_img_no = osc_seq["start_image_number"] nb_frames = osc_seq["number_of_images"] exp_time = osc_seq["exposure_time"] fileformat = "CBF" trig_mode = "EXTERNAL_TRIGGER" # latency_time = 0.003 logging.getLogger("HWR").debug( " Preparing detector (dev=%s) for data collection" % self.devname) logging.getLogger("HWR").debug(" /saving directory: %s" % basedir) logging.getLogger("HWR").debug(" /prefix : %s" % prefix) logging.getLogger("HWR").debug(" /saving_format : %s" % fileformat) logging.getLogger("HWR").debug(" /trigger_mode : %s" % trig_mode) logging.getLogger("HWR").debug(" /acq_nb_frames : %s" % nb_frames) logging.getLogger("HWR").debug(" /acq_expo_time : %s" % str(exp_time - self.latency_time)) logging.getLogger("HWR").debug(" /latency_time : %s" % self.latency_time) self.device.write_attribute("saving_mode", "AUTO_FRAME") self.device.write_attribute("saving_directory", basedir) self.device.write_attribute("saving_prefix", prefix) self.device.write_attribute("saving_format", fileformat) # set ROI and header in limaserver # TODO TrigList = [ "INTERNAL_TRIGGER", "EXTERNAL_TRIGGER", "EXTERNAL_TRIGGER_MULTI", "EXTERNAL_GATE", "EXTERNAL_START_STOP", ] self.device.write_attribute("acq_trigger_mode", trig_mode) self.device.write_attribute("acq_expo_time", exp_time - self.latency_time) self.device.write_attribute("latency_time", self.latency_time) return True def prepare_collection(self, nb_frames, first_img_no): logging.getLogger("HWR").debug( "ALBAPilatus. preparing collection. nb_images: %s, first_no: %s" % (nb_frames, first_img_no)) self.device.write_attribute("acq_nb_frames", nb_frames) self.device.write_attribute("saving_next_number", first_img_no) self.device.prepareAcq() return True def start_collection(self): self.start_acquisition() def stop_collection(self): self.stop_acquisition() def set_image_headers(self, image_headers, angle_info): nb_images = image_headers["nb_images"] angle_inc = image_headers["Angle_increment"] start_angle = image_headers["Start_angle"] startangles_list = list() ang_start, ang_inc, spacing = angle_info for i in range(nb_images): startangles_list.append("%0.4f deg." % (ang_start + spacing * i)) headers = list() for i, sa in enumerate(startangles_list): header = ("_array_data.header_convention PILATUS_1.2\n" "# Detector: PILATUS 6M, S/N 60-0108, Alba\n" "# %s\n" "# Pixel_size 172e-6 m x 172e-6 m\n" "# Silicon sensor, thickness 0.000320 m\n" % time.strftime("%Y/%b/%d %T")) # Acquisition values (headers dictionary) but overwrites start angle image_headers["Start_angle"] = sa for key, value in image_headers.items(): if key == "nb_images": continue header += "# %s %s\n" % (key, value) headers.append("%d : array_data/header_contents|%s;" % (i, header)) self.device.write_attribute("saving_header_delimiter", ["|", ";", ":"]) self.device.resetCommonHeader() self.device.resetFrameHeaders() self.device.setImageHeader(headers)
class TangoChannel(ChannelObject): _tangoEventsQueue = queue.Queue() _eventReceivers = {} _tangoEventsProcessingTimer = gevent.get_hub().loop. async () # start Tango events processing timer _tangoEventsProcessingTimer.start(processTangoEvents) def __init__(self, name, attribute_name, tangoname=None, username=None, polling=None, timeout=10000, **kwargs): ChannelObject.__init__(self, name, username, **kwargs) self.attributeName = attribute_name self.deviceName = tangoname self.device = None self.value = Poller.NotInitializedValue self.polling = polling self.pollingTimer = None self.pollingEvents = False self.timeout = int(timeout) self.read_as_str = kwargs.get("read_as_str", False) self._device_initialized = gevent.event.Event() logging.getLogger("HWR").debug( "creating Tango attribute %s/%s, polling=%s, timeout=%d", self.deviceName, self.attributeName, polling, self.timeout) self.init_poller = Poller.poll( self.init_device, polling_period=3000, value_changed_callback=self.continue_init, error_callback=self.init_poll_failed, start_delay=100) def init_poll_failed(self, e, poller_id): self._device_initialized.clear() logging.warning( "%s/%s (%s): could not complete init. (hint: device server is not running, or has to be restarted)", self.deviceName, self.attributeName, self.name()) self.init_poller = self.init_poller.restart(3000) def continue_init(self, _): self.init_poller.stop() if type(self.polling) == int: Poller.poll(self.poll, polling_period=self.polling, value_changed_callback=self.update, error_callback=self.pollFailed) else: if self.polling == "events": # try to register event try: self.pollingEvents = True #logging.getLogger("HWR").debug("subscribing to CHANGE event for %s", self.attributeName) self.device.subscribe_event(self.attributeName, PyTango.EventType.CHANGE_EVENT, self, [], True) #except PyTango.EventSystemFailed: # pass except: logging.getLogger("HWR").exception( "could not subscribe event") self._device_initialized.set() def init_device(self): try: self.device = DeviceProxy(self.deviceName) except PyTango.DevFailed as traceback: self.imported = False last_error = traceback[-1] logging.getLogger('HWR').error("%s: %s", str(self.name()), last_error['desc']) else: self.imported = True try: self.device.ping() except PyTango.ConnectionFailed: self.device = None raise ConnectionError else: self.device.set_timeout_millis(self.timeout) # check that the attribute exists (to avoid Abort in PyTango grrr) if not self.attributeName.lower() in [ attr.name.lower() for attr in self.device.attribute_list_query() ]: logging.getLogger("HWR").error( "no attribute %s in Tango device %s", self.attributeName, self.deviceName) self.device = None def push_event(self, event): #logging.getLogger("HWR").debug("%s | attr_value=%s, event.errors=%s, quality=%s", self.name(), event.attr_value, event.errors,event.attr_value is None and "N/A" or event.attr_value.quality) if event.attr_value is None or event.err or event.attr_value.quality != PyTango.AttrQuality.ATTR_VALID: #logging.getLogger("HWR").debug("%s, receving BAD event... attr_value=%s, event.errors=%s, quality=%s", self.name(), event.attr_value, event.errors, event.attr_value is None and "N/A" or event.attr_value.quality) return else: pass #logging.getLogger("HWR").debug("%s, receiving good event", self.name()) ev = E(event) TangoChannel._eventReceivers[id(ev)] = saferef.safe_ref(self.update) TangoChannel._tangoEventsQueue.put(ev) TangoChannel._tangoEventsProcessingTimer.send() def poll(self): if self.read_as_str: value = self.device.read_attribute( self.attributeName, PyTango.DeviceAttribute.ExtractAs.String).value #value = self.device.read_attribute_as_str(self.attributeName).value else: value = self.device.read_attribute(self.attributeName).value return value def pollFailed(self, e, poller_id): emit_update = True if self.value is None: emit_update = False else: self.value = None try: self.init_device() except: pass poller = Poller.get_poller(poller_id) if poller is not None: poller.restart(1000) try: raise e except: logging.exception("%s: Exception happened while polling %s", self.name(), self.attributeName) if emit_update: # emit at the end => can raise exceptions in callbacks self.emit('update', None) def getInfo(self): self._device_initialized.wait(timeout=3) return self.device.get_attribute_config(self.attributeName) def update(self, value=Poller.NotInitializedValue): if value == Poller.NotInitializedValue: value = self.getValue() if type(value) == tuple: value = list(value) self.value = value self.emit('update', value) def getValue(self): self._device_initialized.wait(timeout=3) if self.read_as_str: value = self.device.read_attribute( self.attributeName, PyTango.DeviceAttribute.ExtractAs.String).value else: value = self.device.read_attribute(self.attributeName).value return value def setValue(self, newValue, wait=False): self.device.write_attribute(self.attributeName, newValue) #attr = PyTango.AttributeProxy(self.deviceName + "/" + self.attributeName) #a = attr.read() #a.value = newValue #attr.write(a) def isConnected(self): return self.device is not None
class TangoChannel(ChannelObject): _tangoEventsQueue = Queue.Queue() _eventReceivers = {} _tangoEventsProcessingTimer = gevent.get_hub().loop.async() # start Tango events processing timer _tangoEventsProcessingTimer.start(processTangoEvents) def __init__( self, name, attribute_name, tangoname=None, username=None, polling=None, timeout=10000, **kwargs ): ChannelObject.__init__(self, name, username, **kwargs) self.attributeName = attribute_name self.deviceName = tangoname self.device = None self.value = Poller.NotInitializedValue self.polling = polling self.pollingTimer = None self.pollingEvents = False self.timeout = int(timeout) self.read_as_str = kwargs.get("read_as_str", False) self._device_initialized = gevent.event.Event() logging.getLogger("HWR").debug( "creating Tango attribute %s/%s, polling=%s, timeout=%d", self.deviceName, self.attributeName, polling, self.timeout, ) self.init_device() self.continue_init(None) """ self.init_poller = Poller.poll(self.init_device, polling_period = 3000, value_changed_callback = self.continue_init, error_callback = self.init_poll_failed, start_delay=100) """ def init_poll_failed(self, e, poller_id): self._device_initialized.clear() logging.warning( "%s/%s (%s): could not complete init. (hint: device server is not running, or has to be restarted)", self.deviceName, self.attributeName, self.name(), ) self.init_poller = self.init_poller.restart(3000) def continue_init(self, _): # self.init_poller.stop() if isinstance(self.polling, types.IntType): self.raw_device = RawDeviceProxy(self.deviceName) Poller.poll( self.poll, polling_period=self.polling, value_changed_callback=self.update, error_callback=self.pollFailed, ) else: if self.polling == "events": # try to register event try: self.pollingEvents = True # logging.getLogger("HWR").debug("subscribing to CHANGE event for %s", self.attributeName) self.device.subscribe_event( self.attributeName, PyTango.EventType.CHANGE_EVENT, self, [], True, ) # except PyTango.EventSystemFailed: # pass except BaseException: logging.getLogger("HWR").exception("could not subscribe event") self._device_initialized.set() def init_device(self): try: self.device = DeviceProxy(self.deviceName) except PyTango.DevFailed as traceback: self.imported = False last_error = traceback[-1] logging.getLogger("HWR").error( "%s: %s", str(self.name()), last_error["desc"] ) else: self.imported = True try: self.device.ping() except PyTango.ConnectionFailed: self.device = None raise ConnectionError else: self.device.set_timeout_millis(self.timeout) # check that the attribute exists (to avoid Abort in PyTango grrr) if not self.attributeName.lower() in [ attr.name.lower() for attr in self.device.attribute_list_query() ]: logging.getLogger("HWR").error( "no attribute %s in Tango device %s", self.attributeName, self.deviceName, ) self.device = None def push_event(self, event): # logging.getLogger("HWR").debug("%s | attr_value=%s, event.errors=%s, quality=%s", self.name(), event.attr_value, event.errors,event.attr_value is None and "N/A" or event.attr_value.quality) if ( event.attr_value is None or event.err or event.attr_value.quality != PyTango.AttrQuality.ATTR_VALID ): # logging.getLogger("HWR").debug("%s, receving BAD event... attr_value=%s, event.errors=%s, quality=%s", self.name(), event.attr_value, event.errors, event.attr_value is None and "N/A" or event.attr_value.quality) return else: pass # logging.getLogger("HWR").debug("%s, receiving good event", self.name()) ev = E(event) TangoChannel._eventReceivers[id(ev)] = saferef.safe_ref(self.update) TangoChannel._tangoEventsQueue.put(ev) TangoChannel._tangoEventsProcessingTimer.send() def poll(self): if self.read_as_str: value = self.raw_device.read_attribute( self.attributeName, PyTango.DeviceAttribute.ExtractAs.String ).value # value = self.device.read_attribute_as_str(self.attributeName).value else: value = self.raw_device.read_attribute(self.attributeName).value return value def pollFailed(self, e, poller_id): self.emit("update", None) """ emit_update = True if self.value is None: emit_update = False else: self.value = None try: self.init_device() except: pass poller = Poller.get_poller(poller_id) if poller is not None: poller.restart(1000) try: raise e except: logging.exception("%s: Exception happened while polling %s", self.name(), self.attributeName) if emit_update: # emit at the end => can raise exceptions in callbacks self.emit('update', None) """ def getInfo(self): self._device_initialized.wait(timeout=3) return self.device.get_attribute_config(self.attributeName) def update(self, value=Poller.NotInitializedValue): if value == Poller.NotInitializedValue: value = self.getValue() if isinstance(value, types.TupleType): value = list(value) self.value = value self.emit("update", value) def getValue(self): self._device_initialized.wait(timeout=3) if self.read_as_str: value = self.device.read_attribute( self.attributeName, PyTango.DeviceAttribute.ExtractAs.String ).value else: value = self.device.read_attribute(self.attributeName).value return value def setValue(self, newValue): self.device.write_attribute(self.attributeName, newValue) # attr = PyTango.AttributeProxy(self.deviceName + "/" + self.attributeName) # a = attr.read() # a.value = newValue # attr.write(a) def isConnected(self): return self.device is not None
class TangoCommand(CommandObject): def __init__(self, name, command, tangoname=None, username=None, **kwargs): CommandObject.__init__(self, name, username, **kwargs) self.command = command self.deviceName = tangoname self.device = None def init_device(self): try: self.device = DeviceProxy(self.deviceName) except PyTango.DevFailed as traceback: last_error = traceback[-1] logging.getLogger("HWR").error( "%s: %s", str(self.name()), last_error["desc"] ) self.device = None else: try: self.device.ping() except PyTango.ConnectionFailed: self.device = None raise ConnectionError def __call__(self, *args, **kwargs): self.emit("commandBeginWaitReply", (str(self.name()),)) if self.device is None: # TODO: emit commandFailed # beware of infinite recursion with Sample Changer # (because of procedure exception cleanup...) self.init_device() try: tangoCmdObject = getattr(self.device, self.command) ret = tangoCmdObject( *args ) # eval('self.device.%s(*%s)' % (self.command, args)) except PyTango.DevFailed as error_dict: logging.getLogger("HWR").error( "%s: Tango, %s", str(self.name()), error_dict ) except BaseException: logging.getLogger("HWR").exception( "%s: an error occured when calling Tango command %s", str(self.name()), self.command, ) else: self.emit("commandReplyArrived", (ret, str(self.name()))) return ret self.emit("commandFailed", (-1, self.name())) def abort(self): pass def setDeviceTimeout(self, timeout): if self.device is None: self.init_device() self.device.set_timeout_millis(timeout) def isConnected(self): return self.device is not None
class ALBAPilatus(AbstractDetector, HardwareObject): """Detector class. Contains all information about detector - states are 'OK', and 'BAD' - status is busy, exposing, ready, etc. - physical property is RH for pilatus, P for rayonix """ def __init__(self, name): AbstractDetector.__init__(self) HardwareObject.__init__(self, name) self.distance_motor_hwobj = None self.default_distance = None self.default_distance_limits = None self.default_latency_time = 0.003 self.exp_time_limits = None self.headers = {} def init(self): self.distance_motor_hwobj = self.getObjectByRole("distance_motor") self.devname = self.getProperty("tangoname") try: self.latency_time = float(self.getProperty("latency_time")) except BaseException: self.latency_time = None if self.latency_time is None: logging.getLogger("HWR").debug( "Cannot obtain latency time from Pilatus XML. Using %s" % self.default_latency_time ) self.latency_time = self.default_latency_time self.devspecific = self.getProperty("device_specific") exp_time_limits = self.getProperty("exposure_limits") self.exp_time_limits = map(float, exp_time_limits.strip().split(",")) self.device = DeviceProxy(self.devname) self.device_specific = DeviceProxy(self.devspecific) self.device.set_timeout_millis(30000) self.beamx_chan = self.getChannelObject("beamx") self.beamy_chan = self.getChannelObject("beamy") def start_acquisition(self): self.device.startAcq() def stop_acquisition(self): self.device.abortAcq() def get_distance(self): """Returns detector distance in mm""" if self.distance_motor_hwobj is not None: return float(self.distance_motor_hwobj.getPosition()) else: return self.default_distance def move_distance(self, value): if self.distance_motor_hwobj is not None: self.distance_motor_hwobj.move(value) def wait_move_distance_done(self): self.distance_motor_hwobj.wait_end_of_move() def get_distance_limits(self): """Returns detector distance limits""" if self.distance_motor_hwobj is not None: return self.distance_motor_hwobj.getLimits() else: return self.default_distance_limits def get_threshold(self): return self.device_specific.threshold def get_threshold_gain(self): return self.device_specific.threshold_gain def has_shutterless(self): """Return True if has shutterless mode""" return True def get_beam_centre(self): """Returns beam center coordinates""" beam_x = 0 beam_y = 0 try: beam_x = self.beamx_chan.getValue() beam_y = self.beamy_chan.getValue() except BaseException: pass return beam_x, beam_y def get_manufacturer(self): return self.getProperty("manufacturer") return "Dectris" def get_model(self): return self.getProperty("model") def get_detector_type(self): return self.getProperty("type") def get_default_exposure_time(self): return self.getProperty("default_exposure_time") def get_minimum_exposure_time(self): return self.getProperty("minimum_exposure_time") def get_exposure_time_limits(self): """Returns exposure time limits as list with two floats""" return self.exp_time_limits def get_file_suffix(self): return self.getProperty("file_suffix") def get_pixel_size(self): return self.getProperty("px"), self.getProperty("py") # methods for data collection def set_energy_threshold(self): eugap_ch = self.getChannelObject("eugap") try: currentenergy = eugap_ch.getValue() except BaseException: currentenergy = 12.6 det_energy = self.get_threshold() # threshold = det_energy / 2. # limitenergy = threshold / 0.8 if round(currentenergy, 6) < 7.538: currentenergy = 7.538 kev_diff = abs(det_energy - currentenergy) if kev_diff > 1.2: logging.getLogger("HWR").debug( "programming energy_threshold on pilatus to: %s" % currentenergy ) # if self.wait_standby(): # self.device_specific.energy_threshold = currentenergy def get_latency_time(self): return self.latency_time def wait_standby(self, timeout=300): t0 = time.time() while self.device_specific.cam_state == "STANDBY": if time.time() - t0 > timeout: print("timeout waiting for Pilatus to be on STANDBY") return False time.sleep(0.1) return True def prepare_acquisition(self, dcpars): self.set_energy_threshold() # self.wait_standby() osc_seq = dcpars["oscillation_sequence"][0] file_pars = dcpars["fileinfo"] basedir = file_pars["directory"] prefix = "%s_%s_" % (file_pars["prefix"], file_pars["run_number"]) first_img_no = osc_seq["start_image_number"] nb_frames = osc_seq["number_of_images"] exp_time = osc_seq["exposure_time"] fileformat = "CBF" trig_mode = "EXTERNAL_TRIGGER" # latency_time = 0.003 logging.getLogger("HWR").debug( " Preparing detector (dev=%s) for data collection" % self.devname ) logging.getLogger("HWR").debug(" /saving directory: %s" % basedir) logging.getLogger("HWR").debug(" /prefix : %s" % prefix) logging.getLogger("HWR").debug(" /saving_format : %s" % fileformat) logging.getLogger("HWR").debug(" /trigger_mode : %s" % trig_mode) logging.getLogger("HWR").debug(" /acq_nb_frames : %s" % nb_frames) logging.getLogger("HWR").debug( " /acq_expo_time : %s" % str(exp_time - self.latency_time) ) logging.getLogger("HWR").debug(" /latency_time : %s" % self.latency_time) self.device.write_attribute("saving_mode", "AUTO_FRAME") self.device.write_attribute("saving_directory", basedir) self.device.write_attribute("saving_prefix", prefix) self.device.write_attribute("saving_format", fileformat) # set ROI and header in limaserver # TODO TrigList = [ "INTERNAL_TRIGGER", "EXTERNAL_TRIGGER", "EXTERNAL_TRIGGER_MULTI", "EXTERNAL_GATE", "EXTERNAL_START_STOP", ] self.device.write_attribute("acq_trigger_mode", trig_mode) self.device.write_attribute("acq_expo_time", exp_time - self.latency_time) self.device.write_attribute("latency_time", self.latency_time) return True def prepare_collection(self, nb_frames, first_img_no): logging.getLogger("HWR").debug( "ALBAPilatus. preparing collection. nb_images: %s, first_no: %s" % (nb_frames, first_img_no) ) self.device.write_attribute("acq_nb_frames", nb_frames) self.device.write_attribute("saving_next_number", first_img_no) self.device.prepareAcq() return True def start_collection(self): self.start_acquisition() def stop_collection(self): self.stop_acquisition() def set_image_headers(self, image_headers, angle_info): nb_images = image_headers["nb_images"] angle_inc = image_headers["Angle_increment"] start_angle = image_headers["Start_angle"] startangles_list = list() ang_start, ang_inc, spacing = angle_info for i in range(nb_images): startangles_list.append("%0.4f deg." % (ang_start + spacing * i)) headers = list() for i, sa in enumerate(startangles_list): header = ( "_array_data.header_convention PILATUS_1.2\n" "# Detector: PILATUS 6M, S/N 60-0108, Alba\n" "# %s\n" "# Pixel_size 172e-6 m x 172e-6 m\n" "# Silicon sensor, thickness 0.000320 m\n" % time.strftime("%Y/%b/%d %T") ) # Acquisition values (headers dictionary) but overwrites start angle image_headers["Start_angle"] = sa for key, value in image_headers.iteritems(): if key == "nb_images": continue header += "# %s %s\n" % (key, value) headers.append("%d : array_data/header_contents|%s;" % (i, header)) self.device.write_attribute("saving_header_delimiter", ["|", ";", ":"]) self.device.resetCommonHeader() self.device.resetFrameHeaders() self.device.setImageHeader(headers)