def __init__(self, address, pickle_dirname=".", pickle_basename="hist", roi=None, hist_min=None, hist_max=None, n_slots=None, **kwds): """ @param address Address string XXX Que?! @param pickle_dirname Directory portion of output pickle file XXX mean, mu? @param pickle_basename Filename prefix of output pickle file image XXX mean, mu? @param calib_dir Directory with calibration information @param dark_path Path to input dark image @param dark_stddev Path to input dark standard deviation """ super(pixel_histograms, self).__init__(address=address, **kwds) self.pickle_dirname = cspad_tbx.getOptString(pickle_dirname) self.pickle_basename = cspad_tbx.getOptString(pickle_basename) self.hist_min = cspad_tbx.getOptFloat(hist_min) self.hist_max = cspad_tbx.getOptFloat(hist_max) self.n_slots = cspad_tbx.getOptInteger(n_slots) self.histograms = {} self.dimensions = None self.roi = cspad_tbx.getOptROI(roi) self.values = flex.long() self.sigma_scaling = False if self.hist_min is None: self.hist_min = -50 if self.hist_max is None: self.hist_max = 150 if self.n_slots is None: self.n_slots = 200
def __init__(self, address, out_dirname=None, out_basename=None, xtal_target=None, two_theta_low=None, two_theta_high=None, **kwds): """The mod_radial_average class constructor stores the parameters passed from the pyana configuration file in instance variables. All parameters, except @p address are optional, and hence need not be defined in pyana.cfg. @param address Address string XXX Que?! @param out_dirname Optional directory portion of output average pathname @param out_basename Optional filename prefix of output average pathname @param xtal_target Phil file with target paramters, including metrology corrections @param two_theta_low Optional two theta value of interest @param two_theta_high Optional two theta value of interest """ super(mod_radial_average, self).__init__(address=address, **kwds) self.m_xtal_target = cspad_tbx.getOptString(xtal_target) self._basename = cspad_tbx.getOptString(out_basename) self._dirname = cspad_tbx.getOptString(out_dirname) self._two_theta_low = cspad_tbx.getOptFloat(two_theta_low) self._two_theta_high = cspad_tbx.getOptFloat(two_theta_high) if self._dirname is not None or self._basename is not None: assert self._dirname is not None and self._basename is not None
def __init__(self, address, out_dirname = None, out_basename = None, xtal_target = None, two_theta_low = None, two_theta_high = None, **kwds): """The mod_radial_average class constructor stores the parameters passed from the pyana configuration file in instance variables. All parameters, except @p address are optional, and hence need not be defined in pyana.cfg. @param address Address string XXX Que?! @param out_dirname Optional directory portion of output average pathname @param out_basename Optional filename prefix of output average pathname @param xtal_target Phil file with target paramters, including metrology corrections @param two_theta_low Optional two theta value of interest @param two_theta_high Optional two theta value of interest """ super(mod_radial_average, self).__init__(address=address, **kwds) self.m_xtal_target = cspad_tbx.getOptString(xtal_target) self._basename = cspad_tbx.getOptString(out_basename) self._dirname = cspad_tbx.getOptString(out_dirname) self._two_theta_low = cspad_tbx.getOptFloat(two_theta_low) self._two_theta_high = cspad_tbx.getOptFloat(two_theta_high) if self._dirname is not None or self._basename is not None: assert self._dirname is not None and self._basename is not None
def __init__(self, address, detz_offset=575, check_beam_status=True, verbose=False, delta_k=0.0, override_energy=None, **kwds): """The mod_event_info class constructor stores the parameters passed from the pyana configuration file in instance variables. @param address Full data source address of the DAQ device @param detz_offset The distance from the interaction region to the back of the detector stage, in mm @param check_beam_status Flag used to skip checking the beam parameters @param delta_k Correction to the K value used when calculating wavelength @param override_energy Use this energy instead of what is in the XTC stream """ logging.basicConfig() self.logger = logging.getLogger(self.__class__.__name__) self.logger.setLevel(logging.INFO) # The subclasses accept keyword arguments; warn about any # unhandled arguments at the end of the inheritance chain. if len(kwds) > 0: self.logger.warning("Ignored unknown arguments: " + ", ".join(kwds)) # This is for messages that are picked up by Nat's monitoring program self.stats_logger = logging.getLogger("stats logger") handler = logging.StreamHandler() formatter = logging.Formatter('%(message)s') handler.setFormatter(formatter) self.stats_logger.addHandler(handler) self.stats_logger.removeHandler(self.stats_logger.handlers[0]) self.stats_logger.setLevel(logging.INFO) self._detz_offset = cspad_tbx.getOptFloat(detz_offset) self.delta_k = cspad_tbx.getOptFloat(delta_k) self.override_energy = cspad_tbx.getOptFloat(override_energy) self.address = cspad_tbx.getOptString(address) self.verbose = cspad_tbx.getOptBool(verbose) self.check_beam_status = cspad_tbx.getOptBool(check_beam_status) self.distance = None self.sifoil = None self.wavelength = None # The current wavelength - set by self.event() self.laser_1_status = laser_status(laser_id=1) self.laser_4_status = laser_status(laser_id=4)
def __init__(self, illumination, laser_wait_time="2000"): """Initialise laser status, and validate input. The @p illumination parameter is mandatory. @param illumination If @c dark or @c light, only pass dark or light shots, respectively. If @c other, pass events that are neither light or dark, due to recent state changes to the lasers. @param laser_wait_time Number of ms the lasers have to be stable before classifying events as light or dark. Jan F. Kern recommends a value between 1000 and 2000 ms. """ self.logger = logging.getLogger(self.__class__.__name__) self.logger.setLevel(logging.INFO) self._filter = cspad_tbx.getOptString(illumination) if (self._filter != "dark" and self._filter != "light" and self._filter != "other"): raise RuntimeError( "Parameter illumination must be either " "\"light\", \"dark\", or \"other\"") self._wait = cspad_tbx.getOptFloat(laser_wait_time) if (self._wait is None or self._wait < 0): raise RuntimeError( "Parameter laser_wait_time must be number >= 0") self.laser_1 = laser_status(laser_id=1) self.laser_4 = laser_status(laser_id=4) self.naccepted = 0 self.nshots = 0
def __init__(self, address, out_dirname, out_basename, binning=1, brightness=1.0, color_scheme=0, format='png', **kwds): """The mod_dump_bitmap class constructor stores the parameters passed from the pyana configuration file in instance variables. @param address Full data source address of the DAQ device @param out_dirname Directory portion of output image pathname @param out_basename Filename prefix of output image pathname """ #define COLOR_GRAY 0 #define COLOR_RAINBOW 1 #define COLOR_HEAT 2 #define COLOR_INVERT 3 super(mod_dump_bitmap, self).__init__(address=address, **kwds) self._basename = cspad_tbx.getOptString(out_basename) self._dirname = cspad_tbx.getOptString(out_dirname) self._binning = cspad_tbx.getOptInteger(binning) self._brightness = cspad_tbx.getOptFloat(brightness) self._color_scheme = cspad_tbx.getOptInteger(color_scheme) self._format = cspad_tbx.getOptString(format) self._ext = self._format.lower() self._logger = logging.getLogger(self.__class__.__name__) if (not os.path.isdir(self._dirname)): os.makedirs(self._dirname)
def __init__(self, address, detz_offset=575, check_beam_status=True, verbose=False, delta_k=0.0, override_energy=None, **kwds): """The mod_event_info class constructor stores the parameters passed from the pyana configuration file in instance variables. @param address Full data source address of the DAQ device @param detz_offset The distance from the interaction region to the back of the detector stage, in mm @param check_beam_status Flag used to skip checking the beam parameters @param delta_k Correction to the K value used when calculating wavelength @param override_energy Use this energy instead of what is in the XTC stream """ logging.basicConfig() self.logger = logging.getLogger(self.__class__.__name__) self.logger.setLevel(logging.INFO) # The subclasses accept keyword arguments; warn about any # unhandled arguments at the end of the inheritance chain. if len(kwds) > 0: self.logger.warning("Ignored unknown arguments: " + ", ".join(kwds.keys())) # This is for messages that are picked up by Nat's monitoring program self.stats_logger = logging.getLogger("stats logger") handler = logging.StreamHandler() formatter = logging.Formatter('%(message)s') handler.setFormatter(formatter) self.stats_logger.addHandler(handler) self.stats_logger.removeHandler(self.stats_logger.handlers[0]) self.stats_logger.setLevel(logging.INFO) self._detz_offset = cspad_tbx.getOptFloat(detz_offset) self.delta_k = cspad_tbx.getOptFloat(delta_k) self.override_energy = cspad_tbx.getOptFloat(override_energy) self.address = cspad_tbx.getOptString(address) self.verbose = cspad_tbx.getOptBool(verbose) self.check_beam_status = cspad_tbx.getOptBool(check_beam_status) self.distance = None self.sifoil = None self.wavelength = None # The current wavelength - set by self.event() self.laser_1_status = laser_status(laser_id=1) self.laser_4_status = laser_status(laser_id=4)
def __init__(self, address, target_energy, angle=0, n_collate = None, n_update = 1, threshold= 0.4, filter="False", clean="False", mode="E1", peak_ratio=0.17, common_mode_correction = "none", **kwds): """ @param address Address string XXX Que?! @param dirname Directory portion of output pickle file @param basename Filename prefix of output pickle file @param dark_path Path to input dark image @param dark_stddev Path to input dark standard deviation """ super(mod_spectra, self).__init__( address=address, common_mode_correction=common_mode_correction, **kwds ) self.threshold=cspad_tbx.getOptFloat(threshold) self.peak_ratio=cspad_tbx.getOptFloat(peak_ratio) self.angle=cspad_tbx.getOptFloat(angle) self.nv = 0 self.collate=None self.data=None self.ncollate = cspad_tbx.getOptInteger(n_collate) self.nvalid = 0 self.n_shots = 0 self.nupdate = cspad_tbx.getOptInteger(n_update) self.filter=filter self.clean=clean self.target=map(float,target_energy.split(",")) self.mode=mode self.all=[] if (self.ncollate is None): self.ncollate = self.nupdate if (self.ncollate > self.nupdate): self.ncollate = self.nupdate self.logger.warning("n_collate capped to %d" % self.nupdate)
def __init__(self, address, n_collate=None, n_update=120, common_mode_correction="none", wait=None, photon_counting=False, sigma_scaling=False, **kwds): """The mod_view class constructor XXX. @param address Full data source address of the DAQ device @param calib_dir Directory with calibration information @param common_mode_correction The type of common mode correction to apply @param dark_path Path to input average dark image @param dark_stddev Path to input standard deviation dark image, required if @p dark_path is given @param wait Minimum time (in seconds) to wait on the current image before moving on to the next @param n_collate Number of shots to average, or <= 0 to average all shots @param n_update Number of shots between updates """ super(mod_view, self).__init__(address=address, common_mode_correction=common_mode_correction, **kwds) self.detector = cspad_tbx.address_split(address)[0] self.nvalid = 0 self.ncollate = cspad_tbx.getOptInteger(n_collate) self.nupdate = cspad_tbx.getOptInteger(n_update) self.photon_counting = cspad_tbx.getOptBool(photon_counting) self.sigma_scaling = cspad_tbx.getOptBool(sigma_scaling) if (self.ncollate is None): self.ncollate = self.nupdate if (self.ncollate > self.nupdate): self.ncollate = self.nupdate self.logger.warning("n_collate capped to %d" % self.nupdate) linger = True # XXX Make configurable wait = cspad_tbx.getOptFloat(wait) # Create a managed FIFO queue shared between the viewer and the # current process. The current process will produce images, while # the viewer process will consume them. manager = multiprocessing.Manager() self._queue = manager.Queue() self._proc = multiprocessing.Process(target=_xray_frame_process, args=(self._queue, linger, wait)) self._proc.start() self.n_shots = 0
def __init__(self, address, n_collate = None, n_update = 120, common_mode_correction = "none", wait=None, photon_counting=False, sigma_scaling=False, **kwds): """The mod_view class constructor XXX. @param address Full data source address of the DAQ device @param calib_dir Directory with calibration information @param common_mode_correction The type of common mode correction to apply @param dark_path Path to input average dark image @param dark_stddev Path to input standard deviation dark image, required if @p dark_path is given @param wait Minimum time (in seconds) to wait on the current image before moving on to the next @param n_collate Number of shots to average, or <= 0 to average all shots @param n_update Number of shots between updates """ super(mod_view, self).__init__( address=address, common_mode_correction=common_mode_correction, **kwds) self.detector = cspad_tbx.address_split(address)[0] self.nvalid = 0 self.ncollate = cspad_tbx.getOptInteger(n_collate) self.nupdate = cspad_tbx.getOptInteger(n_update) self.photon_counting = cspad_tbx.getOptBool(photon_counting) self.sigma_scaling = cspad_tbx.getOptBool(sigma_scaling) if (self.ncollate is None): self.ncollate = self.nupdate if (self.ncollate > self.nupdate): self.ncollate = self.nupdate self.logger.warning("n_collate capped to %d" % self.nupdate) linger = True # XXX Make configurable wait = cspad_tbx.getOptFloat(wait) # Create a managed FIFO queue shared between the viewer and the # current process. The current process will produce images, while # the viewer process will consume them. manager = multiprocessing.Manager() self._queue = manager.Queue() self._proc = multiprocessing.Process( target=_xray_frame_process, args=(self._queue, linger, wait)) self._proc.start() self.n_shots = 0
def __init__(self, address, pickle_dirname=".", pickle_basename="hist", roi=None, hist_min=None, hist_max=None, n_slots=None, **kwds): """ @param address Address string XXX Que?! @param pickle_dirname Directory portion of output pickle file XXX mean, mu? @param pickle_basename Filename prefix of output pickle file image XXX mean, mu? @param calib_dir Directory with calibration information @param dark_path Path to input dark image @param dark_stddev Path to input dark standard deviation """ super(pixel_histograms, self).__init__( address=address, **kwds ) self.pickle_dirname = cspad_tbx.getOptString(pickle_dirname) self.pickle_basename = cspad_tbx.getOptString(pickle_basename) self.hist_min = cspad_tbx.getOptFloat(hist_min) self.hist_max = cspad_tbx.getOptFloat(hist_max) self.n_slots = cspad_tbx.getOptInteger(n_slots) self.histograms = {} self.dimensions = None self.roi = cspad_tbx.getOptROI(roi) self.values = flex.long() self.sigma_scaling = False if self.hist_min is None: self.hist_min = -50 if self.hist_max is None: self.hist_max = 150 if self.n_slots is None: self.n_slots = 200
def __init__(self, address, calib_dir=None, common_mode_correction="none", photon_threshold=None, two_photon_threshold=None, dark_path=None, dark_stddev=None, mask_path=None, gain_map_path=None, gain_map_level=None, cache_image=True, roi=None, laser_1_status=None, laser_4_status=None, laser_wait_time=None, override_beam_x=None, override_beam_y=None, bin_size=None, crop_rayonix=False, **kwds): """The common_mode_correction class constructor stores the parameters passed from the pyana configuration file in instance variables. @param address Full data source address of the DAQ device @param calib_dir Directory with calibration information @param common_mode_correction The type of common mode correction to apply @param dark_path Path to input average dark image @param dark_stddev Path to input standard deviation dark image, required if @p dark_path is given @param mask_path Path to input mask. Pixels to mask out should be set to -2 @param gain_map_path Path to input gain map. Multiplied times the image. @param gain_map_level If set, all the '1' pixels in the gain_map are set to this multiplier and all the '0' pixels in the gain_map are set to '1'. If not set, use the values in the gain_map directly @param laser_1_status 0 or 1 to indicate that the laser should be off or on respectively @param laser_4_status 0 or 1 to indicate that the laser should be off or on respectively @param laser_wait_time Length of time in milliseconds to wait after a laser change of status to begin accepting images again. (rejection of images occurs immediately after status change). @param override_beam_x override value for x coordinate of beam center in pixels @param override_beam_y override value for y coordinate of beam center in pixels @param bin_size bin size for rayonix detector used to determin pixel size @param crop_rayonix whether to crop rayonix images such that image center is the beam center """ # Cannot use the super().__init__() construct here, because # common_mode_correction refers to the argument, and not the # class. mod_event_info.__init__(self, address=address, **kwds) # The paths will be substituted in beginjob(), where evt and env # are available. self._dark_path = cspad_tbx.getOptString(dark_path) self._dark_stddev_path = cspad_tbx.getOptString(dark_stddev) self._gain_map_path = cspad_tbx.getOptString(gain_map_path) self._mask_path = cspad_tbx.getOptString(mask_path) self.gain_map_level = cspad_tbx.getOptFloat(gain_map_level) self.common_mode_correction = cspad_tbx.getOptString(common_mode_correction) self.photon_threshold = cspad_tbx.getOptFloat(photon_threshold) self.two_photon_threshold = cspad_tbx.getOptFloat(two_photon_threshold) self.cache_image = cspad_tbx.getOptBool(cache_image) self.filter_laser_1_status = cspad_tbx.getOptInteger(laser_1_status) self.filter_laser_4_status = cspad_tbx.getOptInteger(laser_4_status) if self.filter_laser_1_status is not None: self.filter_laser_1_status = bool(self.filter_laser_1_status) if self.filter_laser_4_status is not None: self.filter_laser_4_status = bool(self.filter_laser_4_status) self.filter_laser_wait_time = cspad_tbx.getOptInteger(laser_wait_time) self.override_beam_x = cspad_tbx.getOptFloat(override_beam_x) self.override_beam_y = cspad_tbx.getOptFloat(override_beam_y) self.bin_size = cspad_tbx.getOptInteger(bin_size) self.crop_rayonix = cspad_tbx.getOptBool(crop_rayonix) self.cspad_img = None # The current image - set by self.event() self.sum_common_mode = 0 self.sumsq_common_mode = 0 self.roi = cspad_tbx.getOptROI(roi) # used to ignore the signal region in chebyshev fit assert self.common_mode_correction in \ ("gaussian", "mean", "median", "mode", "none", "chebyshev") # Get and parse metrology. self.sections = None device = cspad_tbx.address_split(self.address)[2] if device == 'Andor': self.sections = [] # XXX FICTION elif device == 'Cspad': if self.address == 'XppGon-0|Cspad-0': self.sections = [] # Not used for XPP else: self.sections = calib2sections(cspad_tbx.getOptString(calib_dir)) elif device == 'Cspad2x2': # There is no metrology information for the Sc1 detector, so # make it up. The sections are rotated by 90 degrees with # respect to the "standing up" convention. self.sections = [[Section(90, (185 / 2 + 0, (2 * 194 + 3) / 2)), Section(90, (185 / 2 + 185, (2 * 194 + 3) / 2))]] elif device == 'marccd': self.sections = [] # XXX FICTION elif device == 'pnCCD': self.sections = [] # XXX FICTION elif device == 'Rayonix': self.sections = [] # XXX FICTION elif device == 'Opal1000': self.sections = [] # XXX FICTION if self.sections is None: raise RuntimeError("Failed to load metrology")
def __init__(self, address, avg_dirname=None, avg_basename=None, stddev_dirname=None, stddev_basename=None, max_dirname=None, max_basename=None, background_path=None, flags=None, hot_threshold=None, gain_threshold=None, noise_threshold=7, elastic_threshold=9, symnoise_threshold=4, **kwds): """ @param address Full data source address of the DAQ device @param avg_dirname Directory portion of output average image XXX mean @param avg_basename Filename prefix of output average image XXX mean @param flags inactive: Eliminate the inactive pixels noelastic: Eliminate elastic scattering nohot: Eliminate the hot pixels nonoise: Eliminate noisy pixels symnoise: Symmetrically eliminate noisy pixels @param stddev_dirname Directory portion of output standard deviation image XXX std @param stddev_basename Filename prefix of output standard deviation image XXX std @param max_dirname Directory portion of output maximum projection image @param max_basename Filename prefix of output maximum projection image """ super(average_mixin, self).__init__( address=address, **kwds ) self.roi = None self.avg_basename = cspad_tbx.getOptString(avg_basename) self.avg_dirname = cspad_tbx.getOptString(avg_dirname) self.detector = cspad_tbx.address_split(address)[0] self.flags = cspad_tbx.getOptStrings(flags, default = []) self.stddev_basename = cspad_tbx.getOptString(stddev_basename) self.stddev_dirname = cspad_tbx.getOptString(stddev_dirname) self.max_basename = cspad_tbx.getOptString(max_basename) self.max_dirname = cspad_tbx.getOptString(max_dirname) self.background_path = cspad_tbx.getOptString(background_path) self.hot_threshold = cspad_tbx.getOptFloat(hot_threshold) self.gain_threshold = cspad_tbx.getOptFloat(gain_threshold) self.noise_threshold = cspad_tbx.getOptFloat(noise_threshold) self.elastic_threshold = cspad_tbx.getOptFloat(elastic_threshold) self.symnoise_threshold = cspad_tbx.getOptFloat(symnoise_threshold) if background_path is not None: background_dict = easy_pickle.load(background_path) self.background_img = background_dict['DATA'] self._have_max = self.max_basename is not None or \ self.max_dirname is not None self._have_mean = self.avg_basename is not None or \ self.avg_dirname is not None self._have_std = self.stddev_basename is not None or \ self.stddev_dirname is not None # Start a server process which holds a set of Python objects that # other processes can manipulate using proxies. The queues will # be used in endjob() to pass images between the worker processes, # and the lock will ensure the transfer is treated as a critical # section. There is therefore the risk of a hang if the queues # cannot hold all the data one process will supply before another # empties it. # # In an attempt to alleviate this issue, separate queues are used # for the potentially big images. The hope is to prevent # producers from blocking while consumers are locked out by using # more buffers. mgr = multiprocessing.Manager() self._lock = mgr.Lock() self._metadata = mgr.dict() self._queue_max = mgr.Queue() self._queue_sum = mgr.Queue() self._queue_ssq = mgr.Queue()