def event(self, evt, env):
    """The event() function puts a "skip_event" object with value @c
    True into the event if the shot is to be skipped.

    @param evt Event data object, a configure object
    @param env Environment object
    """

    self.nshots += 1
    if (evt.get("skip_event")):
      return

    # Get time as a (seconds, milliseconds) tuple.
    t = cspad_tbx.evt_time(evt)
    if (t is None):
      self.logger.warning("event(): no timestamp, shot skipped")
      evt.put(skip_event_flag(), "skip_event")
      return

    # Update laser status.
    self.laser_1.set_status(cspad_tbx.env_laser_status(env, laser_id=1), t)
    self.laser_4.set_status(cspad_tbx.env_laser_status(env, laser_id=4), t)

    t1 = self.laser_1.ms_since_last_status_change(t)
    t4 = self.laser_4.ms_since_last_status_change(t)
    if (self.laser_4.status or
        (t4 is not None and t4 < self._wait) or
        (t1 is not None and t1 < self._wait)):
      # If laser 4 is on or was switched off less than self._wait ms
      # ago, the shot falls in the "other" category.  If laser 1
      # changed its state less than self._wait ms ago the shot falls
      # in the "other" category.

      if (self._filter != "other"):
        evt.put(skip_event_flag(), "skip_event")
        return

    elif (self.laser_1.status):
      # If laser 1 is on the shot falls in the "light" category.
      if (self._filter != "light"):
        evt.put(skip_event_flag(), "skip_event")
        return

    elif (not self.laser_1.status):
      # If laser 1 is off the shot falls in the "dark" category.
      if (self._filter != "dark"):
        evt.put(skip_event_flag(), "skip_event")
        return

    else:
      # NOTREACHED
      self.logger.error("Could not determine shot category")
      raise RuntimeError("XXX")

    self.naccepted += 1
  def event(self, evt, env):
    """The event() function is called for every L1Accept transition.
    @param evt Event data object, a configure object
    @param env Environment object
    """

    super(mod_radial_average, self).event(evt, env)
    if (evt.get("skip_event")):
      return

    # This module only applies to detectors for which a distance is
    # available.
    distance = cspad_tbx.env_distance(self.address, env, self._detz_offset)
    if distance is None:
      self.nfail += 1
      self.logger.warning("event(): no distance, shot skipped")
      evt.put(skip_event_flag(), "skip_event")
      return

    # See r17537 of mod_average.py.
    device = cspad_tbx.address_split(self.address)[2]
    if device == 'Cspad':
      pixel_size = cspad_tbx.pixel_size
      saturated_value = cspad_tbx.cspad_saturated_value
    elif device == 'marccd':
      pixel_size = 0.079346
      saturated_value = 2**16 - 1

    d = cspad_tbx.dpack(
      active_areas=self.active_areas,
      address=self.address,
      beam_center_x=pixel_size * self.beam_center[0],
      beam_center_y=pixel_size * self.beam_center[1],
      data=self.cspad_img.iround(), # XXX ouch!
      distance=distance,
      pixel_size=pixel_size,
      saturated_value=saturated_value,
      timestamp=self.timestamp,
      wavelength=self.wavelength,
      xtal_target=self.m_xtal_target)

    from xfel.command_line.radial_average import run
    args = [
      "file_path=XTC stream",
      "xfel_target=%s"%self.m_xtal_target,
      "verbose=False"
    ]

    t = self.timestamp
    s = t[0:4] + t[5:7] + t[8:10] + t[11:13] + t[14:16] + t[17:19] + t[20:23]

    if self._dirname is not None:
      dest_path = os.path.join(self._dirname, self._basename + s + ".txt")
      args.append("output_file=%s"%dest_path)

    self.logger.info("Calculating radial average for image %s"%s)
    xvals, results = run(args, d)

    evt.put(xvals, "cctbx.xfel.radial_average.xvals")
    evt.put(results, "cctbx.xfel.radial_average.results")
Example #3
0
  def event(self, evt, env):
    """The event() function is called for every L1Accept transition.

    @param evt Event data object, a configure object
    @param env Environment object
    """

    super(mod_image_dict, self).event(evt, env)
    if (evt.get("skip_event")):
      return

    # This module only applies to detectors for which a distance is
    # available.
    distance = cspad_tbx.env_distance(self.address, env, self._detz_offset)
    if distance is None:
      self.nfail += 1
      self.logger.warning("event(): no distance, shot skipped")
      evt.put(skip_event_flag(), "skip_event")
      return

    device = cspad_tbx.address_split(self.address)[2]

    self.logger.info("Subprocess %02d: process image #%05d @ %s" %
                     (env.subprocess(), self.nshots, self.timestamp))

    # See r17537 of mod_average.py.
    if device == 'Cspad':
      pixel_size = cspad_tbx.pixel_size
      saturated_value = cspad_tbx.cspad_saturated_value
    elif device == 'Rayonix':
      pixel_size = rayonix_tbx.get_rayonix_pixel_size(self.bin_size)
      saturated_value = rayonix_tbx.rayonix_saturated_value
    elif device == 'marccd':
      pixel_size = evt.get("marccd_pixel_size")
      saturated_value = evt.get("marccd_saturated_value")
      if distance == 0:
        distance = evt.get("marccd_distance")

    d = cspad_tbx.dpack(
      active_areas=self.active_areas,
      address=self.address,
      beam_center_x=pixel_size * self.beam_center[0],
      beam_center_y=pixel_size * self.beam_center[1],
      data=self.cspad_img.iround(), # XXX ouch!
      distance=distance,
      pixel_size=pixel_size,
      saturated_value=saturated_value,
      timestamp=self.timestamp,
      wavelength=self.wavelength)

    evt.put(d, self.m_out_key)

    # Diagnostic message emitted only when all the processing is done.
    if (env.subprocess() >= 0):
      self.logger.info("Subprocess %02d: accepted #%05d @ %s" %
                       (env.subprocess(), self.nshots, self.timestamp))
    else:
      self.logger.info("Accepted #%05d @ %s" %
                       (self.nshots, self.timestamp))
Example #4
0
  def event(self, evt, env):
    """The event() function is called for every L1Accept transition.
    Once self.nshots shots are accumulated, this function turns into
    a nop.
    @param evt Event data object, a configure object
    @param env Environment object
    """
    self.nv=self.nv+1
    super(mod_spectra, self).event(evt, env)
    if (evt.get("skip_event")):
      return
#    self.nv=self.nv+1
    self.n_shots += 1
    self.logger.info("processing event Number: " + str(self.nv))
    next_update = (self.nupdate - 1) - (self.nshots - 1) % self.nupdate
    if (self.ncollate > 0 and next_update >= self.ncollate):
      return
    count=0
    file=open("spectra.txt","w+")
    if (self.nvalid == 0 or self.ncollate > 0 and self.nvalid >= self.ncollate):
      self.img_sum = self.cspad_img
      self.nvalid  = 1
    else:
      self.img_sum += self.cspad_img
      self.nvalid  += 1
    if next_update==0:
      pixels=self.img_sum/self.nvalid
      if self.angle==0:  #if the signal is not rotated sum each raw and add it to oneD array
        oneD=[]
        pixels=pixels.matrix_transpose()
        for r in flex.rows(pixels):
          oneD.append(flex.sum(r))
        if self.clean=="True":
          oneD=self.Gauss(oneD)
      else:              #if the signal is rotated do projection and sum the signal based on the projection line
       oneD=self.project(pixels)
      if self.clean=="True":
         oneD=self.Gauss(oneD)
      (filter,location)=self.Filter(oneD, self.target, self.threshold)
      if filter==2:
         flag='2C'
      elif filter==1:
        if location==self.target[0]:
           flag='E1'
        if location==self.target[1]:
           flag='E2'
      else:
        flag='bad'
      if self.filter=='False':
          evt.put(flag, "flag")
          evt.put(oneD, "cctbx_spectra")
      if self.filter=="True":
        if self.mode==flag:
          evt.put(flag, "flag")
          evt.put(oneD, "cctbx_spectra")
        else:
          self.logger.warning("event(): Event Skipped")
          evt.put(skip_event_flag(), "skip_event")
  def event(self,evt,evn):
    """The event() function puts a "skip_event" object with value @c
    True into the event if the shot is to be skipped.

    @param evt Event data object, a configure object
    @param env Environment object
    """
    if (evt.get("skip_event")):
      return
    self.n_total += 1
    ts = cspad_tbx.evt_timestamp(cspad_tbx.evt_time(evt))

    accept = self.filter.filter_event(evt, self.selected_filter)[0]
    if not accept:
      print "Skipping event", ts, ": didn't pass filter", self.selected_filter
      evt.put(skip_event_flag(), "skip_event")
      return

    print "Accepting event", ts, ": passed filter", self.selected_filter
    self.n_accepted += 1
Example #6
0
    def event(self, evt, evn):
        """The event() function puts a "skip_event" object with value @c
    True into the event if the shot is to be skipped.

    @param evt Event data object, a configure object
    @param env Environment object
    """
        if (evt.get("skip_event")):
            return
        self.n_total += 1
        ts = cspad_tbx.evt_timestamp(cspad_tbx.evt_time(evt))

        accept = self.filter.filter_event(evt, self.selected_filter)[0]
        if not accept:
            print "Skipping event", ts, ": didn't pass filter", self.selected_filter
            evt.put(skip_event_flag(), "skip_event")
            return

        print "Accepting event", ts, ": passed filter", self.selected_filter
        self.n_accepted += 1
Example #7
0
    def event(self, evt, env):
        """The event() function puts a "skip_event" object with value @c
    True into the event if the shot is to be skipped.

    @param evt Event data object, a configure object
    @param env Environment object
    """

        self.nshots += 1
        if (evt.get("skip_event")):
            return

        if (self.timestamps_list is not None):
            t = cspad_tbx.evt_time(evt)
            if (t is None):
                self.logger.warning(
                    "event(): no timestamp, shot skipped. Shot: %s" %
                    self.nshots)
                evt.put(skip_event_flag(), "skip_event")
                return
            elif (self.negate and t in self.timestamps_list):
                evt.put(skip_event_flag(), "skip_event")
                return
            elif (not self.negate and t not in self.timestamps_list):
                evt.put(skip_event_flag(), "skip_event")
                return

        else:
            t = cspad_tbx.evt_time(evt)
            if (t is None):
                self.logger.warning(
                    "event(): no timestamp, shot skipped. Shot: %s" %
                    self.nshots)
                evt.put(skip_event_flag(), "skip_event")
                return
            if (self.negate and self._tir(t, self.timestamps_interval)):
                evt.put(skip_event_flag(), "skip_event")
                return
            elif (not self.negate
                  and not self._tir(t, self.timestamps_interval)):
                evt.put(skip_event_flag(), "skip_event")
                return

        self.logger.info("event(): event accepted. Shot: %s, TS: %s" %
                         (self.nshots, cspad_tbx.evt_timestamp(t)))
        self.naccepted += 1
Example #8
0
  def event(self, evt, env):
    """The event() function puts a "skip_event" object with value @c
    True into the event if the shot is to be skipped.

    @param evt Event data object, a configure object
    @param env Environment object
    """

    self.nshots += 1
    if (evt.get("skip_event")):
      return

    if (self.timestamps_list is not None):
      t = cspad_tbx.evt_time(evt)
      if (t is None):
        self.logger.warning("event(): no timestamp, shot skipped. Shot: %s"%self.nshots)
        evt.put(skip_event_flag(), "skip_event")
        return
      elif (self.negate and t in self.timestamps_list):
        evt.put(skip_event_flag(), "skip_event")
        return
      elif (not self.negate and t not in self.timestamps_list):
        evt.put(skip_event_flag(), "skip_event")
        return

    else:
      t = cspad_tbx.evt_time(evt)
      if (t is None):
        self.logger.warning("event(): no timestamp, shot skipped. Shot: %s"%self.nshots)
        evt.put(skip_event_flag(), "skip_event")
        return
      if (self.negate and self._tir(t, self.timestamps_interval)):
        evt.put(skip_event_flag(), "skip_event")
        return
      elif (not self.negate and not self._tir(t, self.timestamps_interval)):
        evt.put(skip_event_flag(), "skip_event")
        return

    self.logger.info("event(): event accepted. Shot: %s, TS: %s"%(self.nshots,cspad_tbx.evt_timestamp(t)))
    self.naccepted += 1
Example #9
0
  def event(self, evt, env):
    """The event() function is called for every L1Accept transition.
    XXX more?

    Previously, common-mode correction was applied only after initial
    threshold filtering.  Since the common_mode class applies the
    (lengthy) common-mode correction immediately after reading the
    image from the stream, this optimisation is currently not
    (elegantly) doable.

    @param evt Event data object, a configure object
    @param env Environment object
    """

    super(mod_hitfind, self).event(evt, env)
    if (evt.get("skip_event")):
      return

    # This module only applies to detectors for which a distance is
    # available.
    distance = cspad_tbx.env_distance(self.address, env, self._detz_offset)
    if distance is None:
      self.nfail += 1
      self.logger.warning("event(): no distance, shot skipped")
      evt.put(skip_event_flag(), "skip_event")
      return

    device = cspad_tbx.address_split(self.address)[2]

    # ***** HITFINDING ***** XXX For hitfinding it may be interesting
    # to look at the fraction of subzero pixels in the dark-corrected
    # image.
    if (self.m_threshold is not None):
      # If a threshold value is given it can be applied in one of three ways:
      #    1.  Apply it over the whole image
      if (self.m_roi is None and self.m_distl_min_peaks is None):
        vmax = flex.max(self.cspad_img)
        if (vmax < self.m_threshold):
          if not self.m_negate_hits:
            # Tell downstream modules to skip this event if the threshold was not met.
            evt.put(skip_event_flag(), "skip_event")
            return
        elif self.m_negate_hits:
          evt.put(skip_event_flag(), "skip_event")
          return

      #    2. Apply threshold over a rectangular region of interest.
      elif (self.m_roi is not None):
        vmax = flex.max(self.cspad_img[self.m_roi[2]:self.m_roi[3],
                                       self.m_roi[0]:self.m_roi[1]])
        if (vmax < self.m_threshold):
          if not self.m_negate_hits:
            evt.put(skip_event_flag(), "skip_event")
            return
        elif self.m_negate_hits:
          evt.put(skip_event_flag(), "skip_event")
          return

      #    3. Determine the spotfinder spots within the central ASICS, and accept the
      #       image as a hit if there are m_distl_min_peaks exceeding m_threshold.
      #       As a further requirement, the peaks must exceed 2.5 * the 90-percentile
      #       pixel value of the central ASICS.  This filter was added to avoid high-background
      #       false positives.
      elif (self.m_distl_min_peaks is not None):
        if device == 'marccd':
          self.hitfinder_d['BEAM_CENTER_X'] = self.beam_center[0]
          self.hitfinder_d['BEAM_CENTER_Y'] = self.beam_center[1]
        elif device == 'Rayonix':
          self.hitfinder_d['BEAM_CENTER_X'] = self.beam_center[0]
          self.hitfinder_d['BEAM_CENTER_Y'] = self.beam_center[1]

        peak_heights,outvalue = self.distl_filter(
          self.address,
          self.cspad_img.iround(), # XXX correct?
          distance,
          self.timestamp,
          self.wavelength)
        if ('permissive' in self.m_distl_flags):
          number_of_accepted_peaks = (peak_heights > self.m_threshold).count(True)
        else:
          number_of_accepted_peaks = ((peak_heights > self.m_threshold).__and__(outvalue==0)).count(True)

        sec,ms = cspad_tbx.evt_time(evt)
        evt_time = sec + ms/1000
        self.stats_logger.info("BRAGG %.3f %d" %(evt_time, number_of_accepted_peaks))

        skip_event = False
        if number_of_accepted_peaks < self.m_distl_min_peaks:
          self.logger.info("Subprocess %02d: Spotfinder NO  HIT image #%05d @ %s; %d spots > %d" %(
            env.subprocess(), self.nshots, self.timestamp, number_of_accepted_peaks, self.m_threshold))

          if not self.m_negate_hits:
            skip_event = True
        else:
          self.logger.info("Subprocess %02d: Spotfinder YES HIT image #%05d @ %s; %d spots > %d" %(
            env.subprocess(), self.nshots, self.timestamp, number_of_accepted_peaks, self.m_threshold))

          if self.m_negate_hits:
            skip_event = True

        if skip_event:
          if self.m_db_logging:
            # log misses to the database
            self.queue_entry((self.trial, evt.run(), "%.3f"%evt_time, number_of_accepted_peaks, distance,
                              self.sifoil, self.wavelength, False, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, self.m_db_tags))
          evt.put(skip_event_flag(), "skip_event")
          return
        # the indexer will log this hit when it is ran. Bug: if the spotfinder is ran by itself, this
        # hit will not be logged in the db.
        evt.put(number_of_accepted_peaks, 'sfspots')

    self.logger.info("Subprocess %02d: process image #%05d @ %s" %
                     (env.subprocess(), self.nshots, self.timestamp))

    # See r17537 of mod_average.py.
    if device == 'Cspad':
      pixel_size = cspad_tbx.pixel_size
      saturated_value = cspad_tbx.cspad_saturated_value
    elif device == 'marccd':
      pixel_size = evt.get("marccd_pixel_size")
      saturated_value = evt.get("marccd_saturated_value")
    elif device == 'Rayonix':
      pixel_size = rayonix_tbx.get_rayonix_pixel_size(self.bin_size)
      saturated_value = rayonix_tbx.rayonix_saturated_value

    d = cspad_tbx.dpack(
      active_areas=self.active_areas,
      address=self.address,
      beam_center_x=pixel_size * self.beam_center[0],
      beam_center_y=pixel_size * self.beam_center[1],
      data=self.cspad_img.iround(), # XXX ouch!
      distance=distance,
      pixel_size=pixel_size,
      saturated_value=saturated_value,
      timestamp=self.timestamp,
      wavelength=self.wavelength,
      xtal_target=self.m_xtal_target)

    if (self.m_dispatch == "index"):
      import sys
      from xfel.cxi.integrate_image_api import integrate_one_image
      info = integrate_one_image(d,
                                 integration_dirname  = self.m_integration_dirname,
                                 integration_basename = self.m_integration_basename)
      sys.stdout = sys.__stdout__
      sys.stderr = sys.__stderr__

      indexed = info is not None
      if indexed and self.m_progress_logging:
        # integration pickle dictionary is available here as info.last_saved_best
        if info.last_saved_best["identified_isoform"] is not None:
          #print info.last_saved_best.keys()
          from cxi_xdr_xes.cftbx.cspad_ana import db
          dbobj = db.dbconnect(self.m_db_host, self.m_db_name, self.m_db_user, self.m_db_password)
          cursor = dbobj.cursor()
          if info.last_saved_best["identified_isoform"] in self.isoforms:
            PM, indices, miller_id = self.isoforms[info.last_saved_best["identified_isoform"]]
          else:
            from xfel.xpp.progress_support import progress_manager
            PM = progress_manager(info.last_saved_best,self.m_db_experiment_tag, self.m_trial_id, self.m_rungroup_id, evt.run())
            indices, miller_id = PM.get_HKL(cursor)
            # cache these as they don't change for a given isoform
            self.isoforms[info.last_saved_best["identified_isoform"]] = PM, indices, miller_id
          if self.m_sql_buffer_size > 1:
            self.queue_progress_entry(PM.scale_frame_detail(self.timestamp,cursor,do_inserts=False))
          else:
            PM.scale_frame_detail(self.timestamp,cursor,do_inserts=True)
            dbobj.commit()
            cursor.close()
            dbobj.close()

      if self.m_db_logging:
        sec,ms = cspad_tbx.evt_time(evt)
        evt_time = sec + ms/1000
        sfspots = evt.get('sfspots')
        if sfspots is None:
          if indexed:
            n_spots = len(info.spotfinder_results.images[info.frames[0]]['spots_total'])
          else:
            n_spots = 0
        else:
          n_spots = sfspots

        if indexed:
          mosaic_bloc_rotation = info.last_saved_best.get('ML_half_mosaicity_deg', [0])[0]
          mosaic_block_size = info.last_saved_best.get('ML_domain_size_ang', [0])[0]
          ewald_proximal_volume = info.last_saved_best.get('ewald_proximal_volume', [0])[0]

          obs = info.last_saved_best['observations'][0]
          cell_a, cell_b, cell_c, cell_alpha, cell_beta, cell_gamma = obs.unit_cell().parameters()
          pointgroup = info.last_saved_best['pointgroup']
          resolution = obs.d_min()
        else:
          mosaic_bloc_rotation = mosaic_block_size = ewald_proximal_volume = cell_a = cell_b = cell_c = \
            cell_alpha = cell_beta = cell_gamma = spacegroup = resolution = 0

        self.queue_entry((self.trial, evt.run(), "%.3f"%evt_time, n_spots, distance,
                          self.sifoil, self.wavelength, indexed, mosaic_bloc_rotation,
                          mosaic_block_size, ewald_proximal_volume, pointgroup, cell_a,
                          cell_b, cell_c, cell_alpha, cell_beta, cell_gamma, resolution,
                          self.m_db_tags))

      if (not indexed):
        evt.put(skip_event_flag(), "skip_event")
        return

    elif (self.m_dispatch == "nop"):
      pass

    elif (self.m_dispatch == "view"): #interactive image viewer

      args = ["indexing.data=dummy"]
      detector_format_version = detector_format_function(
        self.address, evt.GetTime())
      if detector_format_version is not None:
        args += ["distl.detector_format_version=%" % detector_format_version]

      from xfel.phil_preferences import load_cxi_phil
      horizons_phil = load_cxi_phil(self.m_xtal_target, args)
      horizons_phil.indexing.data = d

      from xfel.cxi import display_spots
      display_spots.parameters.horizons_phil = horizons_phil
      display_spots.wrapper_of_callback().display(horizons_phil.indexing.data)

    elif (self.m_dispatch == "spots"): #interactive spotfinder viewer

      args = ["indexing.data=dummy"]
      detector_format_version = detector_format_function(
        self.address, evt.GetTime())
      if detector_format_version is not None:
        args += ["distl.detector_format_version=%s" % detector_format_version]

      from xfel.phil_preferences import load_cxi_phil
      horizons_phil = load_cxi_phil(self.m_xtal_target, args)
      horizons_phil.indexing.data = d

      from xfel.cxi import display_spots
      display_spots.parameters.horizons_phil = horizons_phil

      from rstbx.new_horizons.index import pre_indexing_validation,pack_names
      pre_indexing_validation(horizons_phil)
      imagefile_arguments = pack_names(horizons_phil)
      horizons_phil.persist.show()
      from spotfinder.applications import signal_strength
      info = signal_strength.run_signal_strength_core(horizons_phil,imagefile_arguments)

      work = display_spots.wrapper_of_callback(info)
      work.display_with_callback(horizons_phil.indexing.data)

    elif (self.m_dispatch == "write_dict"):
      self.logger.warning(
        "event(): deprecated dispatch 'write_dict', use mod_dump instead")
      if (self.m_out_dirname  is not None or
          self.m_out_basename is not None):
        cspad_tbx.dwritef(d, self.m_out_dirname, self.m_out_basename)

    # Diagnostic message emitted only when all the processing is done.
    if (env.subprocess() >= 0):
      self.logger.info("Subprocess %02d: accepted #%05d @ %s" %
                       (env.subprocess(), self.nshots, self.timestamp))
    else:
      self.logger.info("Accepted #%05d @ %s" %
                       (self.nshots, self.timestamp))
Example #10
0
    def event(self, evt, env):
        """The event() function is called for every L1Accept transition.
    @param evt Event data object, a configure object
    @param env Environment object
    """

        super(mod_radial_average, self).event(evt, env)
        if (evt.get("skip_event")):
            return

        # This module only applies to detectors for which a distance is
        # available.
        distance = cspad_tbx.env_distance(self.address, env, self._detz_offset)
        if distance is None:
            self.nfail += 1
            self.logger.warning("event(): no distance, shot skipped")
            evt.put(skip_event_flag(), "skip_event")
            return

        # See r17537 of mod_average.py.
        device = cspad_tbx.address_split(self.address)[2]
        if device == 'Cspad':
            pixel_size = cspad_tbx.pixel_size
            saturated_value = cspad_tbx.cspad_saturated_value
        elif device == 'marccd':
            pixel_size = 0.079346
            saturated_value = 2**16 - 1
        elif device == 'Rayonix':
            pixel_size = rayonix_tbx.get_rayonix_pixel_size(self.bin_size)
            saturated_value = rayonix_tbx.rayonix_saturated_value

        d = cspad_tbx.dpack(
            active_areas=self.active_areas,
            address=self.address,
            beam_center_x=pixel_size * self.beam_center[0],
            beam_center_y=pixel_size * self.beam_center[1],
            data=self.cspad_img.iround(),  # XXX ouch!
            distance=distance,
            pixel_size=pixel_size,
            saturated_value=saturated_value,
            timestamp=self.timestamp,
            wavelength=self.wavelength,
            xtal_target=self.m_xtal_target)

        from xfel.command_line.radial_average import run
        args = [
            "file_path=XTC stream",
            "xfel_target=%s" % self.m_xtal_target, "verbose=False"
        ]

        t = self.timestamp
        s = t[0:4] + t[5:7] + t[8:10] + t[11:13] + t[14:16] + t[17:19] + t[
            20:23]

        if self._dirname is not None:
            dest_path = os.path.join(self._dirname,
                                     self._basename + s + ".txt")
            args.append("output_file=%s" % dest_path)

        self.logger.info("Calculating radial average for image %s" % s)
        xvals, results = run(args, d)

        evt.put(xvals, "cctbx.xfel.radial_average.xvals")
        evt.put(results, "cctbx.xfel.radial_average.results")

        def get_closest_idx(data, val):
            from scitbx.array_family import flex
            deltas = flex.abs(data - val)
            return flex.first_index(deltas, flex.min(deltas))

        if self._two_theta_low is not None:
            i_low = results[get_closest_idx(xvals, self._two_theta_low)]
            evt.put(i_low, "cctbx.xfel.radial_average.two_theta_low")

        if self._two_theta_high is not None:
            i_high = results[get_closest_idx(xvals, self._two_theta_high)]
            evt.put(i_high, "cctbx.xfel.radial_average.two_theta_high")
Example #11
0
    def event(self, evt, evn):
        """The event() function puts a "skip_event" object with value @c
    True into the event if the shot is to be skipped.

    @param evt Event data object, a configure object
    @param env Environment object
    """
        #import pdb; pdb.set_trace()
        if (evt.get("skip_event")):
            return
        # check if FEE data is one or two dimensional
        data = evt.get(Camera.FrameV1, self.src)
        if data is None:
            one_D = True
            data = evt.get(Bld.BldDataSpectrometerV1, self.src)
        else:
            one_D = False
        # get event timestamp
        timestamp = cspad_tbx.evt_timestamp(
            cspad_tbx.evt_time(evt))  # human readable format

        if data is None:
            self.nnodata += 1
            #self.logger.warning("event(): No spectrum data")
            evt.put(skip_event_flag(), "skip_event")

        if timestamp is None:
            evt.put(skip_event_flag(), "skip_event")
            self.logger.warning("event(): No TIMESTAMP, skipping shot")

        elif data is not None:
            self.nshots += 1
            # get data as array and split into two half to find each peak
            if one_D:
                data = np.array(data.hproj().astype(np.float64))
                if 'dark' in locals():
                    data = data - self.dark
                spectrum = data
                spectrum1 = data[:data.shape[0] // 2]
                spectrum2 = data[data.shape[0] // 2:]
            else:
                data = np.array(data.data16().astype(np.float64))
                if 'dark' in locals():
                    data = data - self.dark
                data_split1 = data[:, :data.shape[1] // 2]
                data_split2 = data[:, data.shape[1] // 2:]
                # make a 1D trace of entire spectrum and each half to find peaks
                spectrum = np.sum(data, 0) / data.shape[0]
                spectrum1 = np.sum(data_split1, 0) / data_split1.shape[0]
                spectrum2 = np.sum(data_split2, 0) / data_split2.shape[0]

            peak_one = np.max(spectrum1)
            peak_two = np.max(spectrum2)
            peak_one_position = np.argmax(spectrum1)
            peak_two_position = np.argmax(spectrum2) + len(spectrum2)
            # define the limits of the regions between the two peaks
            peak_one_lower_limit = self.peak_one_position_min - self.peak_one_width
            peak_one_upper_limit = self.peak_one_position_max + self.peak_one_width
            peak_two_lower_limit = self.peak_two_position_min - self.peak_two_width
            peak_two_upper_limit = self.peak_two_position_max + self.peak_two_width

            # the x-coordinate of the weighted center of peak region
            weighted_peak_one_positions = []
            for i in range(peak_one_lower_limit, peak_one_upper_limit):
                weighted_peak_one_positions.append(spectrum[i] * i)

            weighted_sum_peak_one = sum(weighted_peak_one_positions)
            weighted_peak_one_center_position = weighted_sum_peak_one // sum(
                spectrum[peak_one_lower_limit:peak_one_upper_limit])

            weighted_peak_two_positions = []
            for i in range(peak_two_lower_limit, peak_two_upper_limit):
                weighted_peak_two_positions.append(spectrum[i] * i)

            weighted_sum_peak_two = sum(weighted_peak_two_positions)
            weighted_peak_two_center_position = weighted_sum_peak_two // sum(
                spectrum[peak_two_lower_limit:peak_two_upper_limit])
            # normalized integrated peaks
            int_peak_one = np.sum(
                spectrum[peak_one_lower_limit:self.peak_one_position_max]
            ) / len(spectrum[peak_one_lower_limit:self.peak_one_position_max])
            int_peak_two = np.sum(
                spectrum[peak_two_lower_limit:self.peak_two_position_max]
            ) / len(spectrum[peak_two_lower_limit:self.peak_two_position_max])
            # normalized integrated regions between the peaks
            int_left_region = np.sum(spectrum[0:peak_one_lower_limit]) / len(
                spectrum[0:peak_one_lower_limit])
            int_middle_region = np.sum(
                spectrum[peak_one_upper_limit:peak_two_lower_limit]) / len(
                    spectrum[peak_one_upper_limit:peak_two_lower_limit])
            int_right_region = np.sum(spectrum[peak_two_upper_limit:]) / len(
                spectrum[:peak_two_upper_limit])
            # now to do the filtering
            if peak_one / peak_two < self.peak_ratio or peak_one / peak_two > 1 / self.peak_ratio:
                print "event(): too low"
                evt.put(skip_event_flag(), "skip_event")
                return
            if weighted_peak_two_center_position < self.peak_two_position_min or weighted_peak_two_center_position > self.peak_two_position_max:
                print "event(): out of range high energy peak"
                evt.put(skip_event_flag(), "skip_event")
                return
            if weighted_peak_one_center_position < self.peak_one_position_min or weighted_peak_one_center_position > self.peak_one_position_max:
                print "event(): out of range low energy peak"
                evt.put(skip_event_flag(), "skip_event")
                return
            if not one_D and (int_left_region / int_peak_one >
                              self.normalized_peak_to_noise_ratio):
                print "event(): noisy left of low energy peak"
                evt.put(skip_event_flag(), "skip_event")
                return
            if not one_D and (int_middle_region / int_peak_one >
                              self.normalized_peak_to_noise_ratio):
                print "event(): noisy middle"
                evt.put(skip_event_flag(), "skip_event")
                return
            if not one_D and (int_middle_region / int_peak_two >
                              self.normalized_peak_to_noise_ratio):
                print "event(): noisy middle"
                evt.put(skip_event_flag(), "skip_event")
                return
            if not one_D and (int_right_region / int_peak_two >
                              self.normalized_peak_to_noise_ratio):
                print "event(): noisy right of high energy peak"
                evt.put(skip_event_flag(), "skip_event")
                return
            #iron edge at 738 pixels on FFE detetor
            if one_D and (spectrum[self.iron_edge_position] >=
                          spectrum[weighted_peak_one_center_position]):
                print "event(): peak at iron edge"
                evt.put(skip_event_flag(), "skip_event")
                return

            if one_D and (spectrum[self.iron_edge_position] >=
                          spectrum[weighted_peak_two_center_position]):
                print "event(): peak at iron edge"
                evt.put(skip_event_flag(), "skip_event")
                return

            #self.logger.info("TIMESTAMP %s accepted" %timestamp)
            self.naccepted += 1
            self.ntwo_color += 1
            print "%d Two Color shots" % self.ntwo_color
  def event(self,evt,evn):
    """The event() function puts a "skip_event" object with value @c
    True into the event if the shot is to be skipped.

    @param evt Event data object, a configure object
    @param env Environment object
    """
    #import pdb; pdb.set_trace()
    if (evt.get("skip_event")):
      return
    # check if FEE data is one or two dimensional
    data = evt.get(Camera.FrameV1, self.src)
    if data is None:
      one_D = True
      data = evt.get(Bld.BldDataSpectrometerV1, self.src)
    else:
      one_D = False
    # get event timestamp
    timestamp = cspad_tbx.evt_timestamp(cspad_tbx.evt_time(evt)) # human readable format

    if data is None:
      self.nnodata +=1
      #self.logger.warning("event(): No spectrum data")
      evt.put(skip_event_flag(),"skip_event")

    if timestamp is None:
      evt.put(skip_event_flag(),"skip_event")
      #self.logger.warning("event(): No TIMESTAMP, skipping shot")

    elif data is not None:
      self.nshots +=1
      # get data as array and split into two half to find each peak
      if one_D:
        # filtering out outlier spikes in FEE data
        data = np.array(data.hproj().astype(np.float64))
        for i in xrange(len(data)):
          if data[i]>1000000000:
            data[i]=data[i]-(2**32)
        if self.dark is not None:
          data = data - self.dark
        spectrum = data
        spectrum1 = data[:data.shape[0]//2]
        spectrum2 = data[data.shape[0]//2:]
      else:
        data = np.array(data.data16().astype(np.int32))
        if self.dark is not None:
          data = data - self.dark
        data = np.double(data)
        data_split1 = data[:,:data.shape[1]//2]
        data_split2 = data[:,data.shape[1]//2:]
        # make a 1D trace of entire spectrum and each half to find peaks
        spectrum  = np.sum(data,0)/data.shape[0]
        spectrum1 = np.sum(data_split1,0)/data_split1.shape[0]
        spectrum2 = np.sum(data_split2,0)/data_split2.shape[0]
      if not one_D:
        # the x-coordinate of the weighted center of peak region
        weighted_peak_one_positions = []
        for i in xrange(self.peak_one_range_min,self.peak_one_range_max):
          weighted_peak_one_positions.append(spectrum[i]*i)
        weighted_sum_peak_one = np.sum(weighted_peak_one_positions)
        weighted_peak_one_center_position = weighted_sum_peak_one/np.sum(spectrum[self.peak_one_range_min:self.peak_one_range_max])

        weighted_peak_two_positions = []
        for i in xrange(self.peak_two_range_min,self.peak_two_range_max):
          weighted_peak_two_positions.append(spectrum[i]*i)
        weighted_sum_peak_two = np.sum(weighted_peak_two_positions)
        weighted_peak_two_center_position = weighted_sum_peak_two/np.sum(spectrum[self.peak_two_range_min:self.peak_two_range_max])

        # normalized integrated regions between the peaks
        #int_left_region = np.sum(spectrum[weighted_peak_one_center_position+len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2:(weighted_peak_two_center_position-len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2)])
        int_left_region = np.sum(spectrum[:weighted_peak_two_center_position/2])

        #int_left_region_norm = np.sum(spectrum[weighted_peak_one_center_position+len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2:(weighted_peak_two_center_position-len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2)])/len(spectrum[weighted_peak_one_center_position+len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2:(weighted_peak_two_center_position-len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2)])
        int_left_region_norm = np.sum(spectrum[:weighted_peak_two_center_position/2])/len(spectrum[:weighted_peak_two_center_position/2])

        int_right_region = np.sum(spectrum[self.peak_two_range_max:])

        int_right_region_norm = np.sum(spectrum[self.peak_two_range_max:])/len(spectrum[self.peak_two_range_max:])

        # normalized integrated peaks
        int_peak_one = np.sum(spectrum[(weighted_peak_one_center_position-len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2):(weighted_peak_one_center_position+len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2)])

        int_peak_one_norm = np.sum(spectrum[(weighted_peak_one_center_position-len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2):(weighted_peak_one_center_position+len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2)])/len(spectrum[(weighted_peak_one_center_position-len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2):(weighted_peak_one_center_position+len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2)])

        int_peak_two = np.sum(spectrum[(weighted_peak_two_center_position-len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2):(weighted_peak_two_center_position+len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2)])

        int_peak_two_norm = np.sum(spectrum[(weighted_peak_two_center_position-len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2):(weighted_peak_two_center_position+len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2)])/len(spectrum[(weighted_peak_two_center_position-len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2):(weighted_peak_two_center_position+len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2)])

      if not one_D:
        if int_peak_one_norm/int_peak_two_norm > self.peak_ratio:
          print "event(): inflection peak too high"
          evt.put(skip_event_flag(), "skip_event")
          return
        if int_left_region_norm > self.normalized_peak_to_noise_ratio*int_peak_two_norm:
          print "event(): noisy left of low energy peak"
          evt.put(skip_event_flag(), "skip_event")
          return
        if int_right_region_norm > self.normalized_peak_to_noise_ratio*int_peak_two_norm:
          print "event(): noisy right of high energy peak"
          evt.put(skip_event_flag(), "skip_event")
          return
      #self.logger.info("TIMESTAMP %s accepted" %timestamp)
      self.naccepted += 1
      self.ntwo_color += 1
      print "%d Remote shot"  %self.ntwo_color
      print "%s Remote timestamp" %timestamp
  def event(self,evt,evn):
    """The event() function puts a "skip_event" object with value @c
    True into the event if the shot is to be skipped.

    @param evt Event data object, a configure object
    @param env Environment object
    """
    #import pdb; pdb.set_trace()
    if (evt.get("skip_event")):
      return
    # check if FEE data is one or two dimensional
    data = evt.get(Camera.FrameV1, self.src)
    if data is None:
      one_D = True
      data = evt.get(Bld.BldDataSpectrometerV1, self.src)
    else:
      one_D = False
    # get event timestamp
    timestamp = cspad_tbx.evt_timestamp(cspad_tbx.evt_time(evt)) # human readable format

    if data is None:
      self.nnodata +=1
      #self.logger.warning("event(): No spectrum data")
      evt.put(skip_event_flag(),"skip_event")

    if timestamp is None:
      evt.put(skip_event_flag(),"skip_event")
      #self.logger.warning("event(): No TIMESTAMP, skipping shot")

    elif data is not None:
      self.nshots +=1
      # get data as array and split into two half to find each peak
      if one_D:
        # filtering out outlier spikes in FEE data
        data = np.array(data.hproj().astype(np.float64))
        for i in range(len(data)):
          if data[i]>1000000000:
            data[i]=data[i]-(2**32)
        if self.dark is not None:
          data = data - self.dark
        spectrum = data
        spectrum1 = data[:data.shape[0]//2]
        spectrum2 = data[data.shape[0]//2:]
      else:
        data = np.array(data.data16().astype(np.int32))
        if self.dark is not None:
          data = data - self.dark
        data = np.double(data)
        data_split1 = data[:,:data.shape[1]//2]
        data_split2 = data[:,data.shape[1]//2:]
        # make a 1D trace of entire spectrum and each half to find peaks
        spectrum  = np.sum(data,0)/data.shape[0]
        spectrum1 = np.sum(data_split1,0)/data_split1.shape[0]
        spectrum2 = np.sum(data_split2,0)/data_split2.shape[0]
      if not one_D:
        # the x-coordinate of the weighted center of peak region
        weighted_peak_one_positions = []
        for i in range(self.peak_one_range_min,self.peak_one_range_max):
          weighted_peak_one_positions.append(spectrum[i]*i)
        weighted_sum_peak_one = np.sum(weighted_peak_one_positions)
        weighted_peak_one_center_position = weighted_sum_peak_one/np.sum(spectrum[self.peak_one_range_min:self.peak_one_range_max])

        weighted_peak_two_positions = []
        for i in range(self.peak_two_range_min,self.peak_two_range_max):
          weighted_peak_two_positions.append(spectrum[i]*i)
        weighted_sum_peak_two = np.sum(weighted_peak_two_positions)
        weighted_peak_two_center_position = weighted_sum_peak_two/np.sum(spectrum[self.peak_two_range_min:self.peak_two_range_max])

        # normalized integrated regions between the peaks
        #int_left_region = np.sum(spectrum[weighted_peak_one_center_position+len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2:(weighted_peak_two_center_position-len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2)])
        int_left_region = np.sum(spectrum[:weighted_peak_two_center_position/2])

        #int_left_region_norm = np.sum(spectrum[weighted_peak_one_center_position+len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2:(weighted_peak_two_center_position-len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2)])/len(spectrum[weighted_peak_one_center_position+len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2:(weighted_peak_two_center_position-len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2)])
        int_left_region_norm = np.sum(spectrum[:weighted_peak_two_center_position/2])/len(spectrum[:weighted_peak_two_center_position/2])

        int_right_region = np.sum(spectrum[self.peak_two_range_max:])

        int_right_region_norm = np.sum(spectrum[self.peak_two_range_max:])/len(spectrum[self.peak_two_range_max:])

        # normalized integrated peaks
        int_peak_one = np.sum(spectrum[(weighted_peak_one_center_position-len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2):(weighted_peak_one_center_position+len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2)])

        int_peak_one_norm = np.sum(spectrum[(weighted_peak_one_center_position-len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2):(weighted_peak_one_center_position+len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2)])/len(spectrum[(weighted_peak_one_center_position-len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2):(weighted_peak_one_center_position+len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2)])

        int_peak_two = np.sum(spectrum[(weighted_peak_two_center_position-len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2):(weighted_peak_two_center_position+len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2)])

        int_peak_two_norm = np.sum(spectrum[(weighted_peak_two_center_position-len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2):(weighted_peak_two_center_position+len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2)])/len(spectrum[(weighted_peak_two_center_position-len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2):(weighted_peak_two_center_position+len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2)])

      if not one_D:
        if int_peak_one_norm/int_peak_two_norm > self.peak_ratio:
          print("event(): inflection peak too high")
          evt.put(skip_event_flag(), "skip_event")
          return
        if int_left_region_norm > self.normalized_peak_to_noise_ratio*int_peak_two_norm:
          print("event(): noisy left of low energy peak")
          evt.put(skip_event_flag(), "skip_event")
          return
        if int_right_region_norm > self.normalized_peak_to_noise_ratio*int_peak_two_norm:
          print("event(): noisy right of high energy peak")
          evt.put(skip_event_flag(), "skip_event")
          return
      #self.logger.info("TIMESTAMP %s accepted" %timestamp)
      self.naccepted += 1
      self.ntwo_color += 1
      print("%d Remote shot"  %self.ntwo_color)
      print("%s Remote timestamp" %timestamp)
Example #14
0
    def event(self, evt, env):
        """The event() function is called for every L1Accept transition.
    XXX more?

    Previously, common-mode correction was applied only after initial
    threshold filtering.  Since the common_mode class applies the
    (lengthy) common-mode correction immediately after reading the
    image from the stream, this optimisation is currently not
    (elegantly) doable.

    @param evt Event data object, a configure object
    @param env Environment object
    """

        super(mod_hitfind, self).event(evt, env)
        if (evt.get("skip_event")):
            return

        # This module only applies to detectors for which a distance is
        # available.
        distance = cspad_tbx.env_distance(self.address, env, self._detz_offset)
        if distance is None:
            self.nfail += 1
            self.logger.warning("event(): no distance, shot skipped")
            evt.put(skip_event_flag(), "skip_event")
            return

        device = cspad_tbx.address_split(self.address)[2]

        # ***** HITFINDING ***** XXX For hitfinding it may be interesting
        # to look at the fraction of subzero pixels in the dark-corrected
        # image.
        if (self.m_threshold is not None):
            # If a threshold value is given it can be applied in one of three ways:
            #    1.  Apply it over the whole image
            if (self.m_roi is None and self.m_distl_min_peaks is None):
                vmax = flex.max(self.cspad_img)
                if (vmax < self.m_threshold):
                    if not self.m_negate_hits:
                        # Tell downstream modules to skip this event if the threshold was not met.
                        evt.put(skip_event_flag(), "skip_event")
                        return
                elif self.m_negate_hits:
                    evt.put(skip_event_flag(), "skip_event")
                    return

            #    2. Apply threshold over a rectangular region of interest.
            elif (self.m_roi is not None):
                vmax = flex.max(self.cspad_img[self.m_roi[2]:self.m_roi[3],
                                               self.m_roi[0]:self.m_roi[1]])
                if (vmax < self.m_threshold):
                    if not self.m_negate_hits:
                        evt.put(skip_event_flag(), "skip_event")
                        return
                elif self.m_negate_hits:
                    evt.put(skip_event_flag(), "skip_event")
                    return

            #    3. Determine the spotfinder spots within the central ASICS, and accept the
            #       image as a hit if there are m_distl_min_peaks exceeding m_threshold.
            #       As a further requirement, the peaks must exceed 2.5 * the 90-percentile
            #       pixel value of the central ASICS.  This filter was added to avoid high-background
            #       false positives.
            elif (self.m_distl_min_peaks is not None):
                if device == 'marccd':
                    self.hitfinder_d['BEAM_CENTER_X'] = self.beam_center[0]
                    self.hitfinder_d['BEAM_CENTER_Y'] = self.beam_center[1]
                elif device == 'Rayonix':
                    self.hitfinder_d['BEAM_CENTER_X'] = self.beam_center[0]
                    self.hitfinder_d['BEAM_CENTER_Y'] = self.beam_center[1]

                peak_heights, outvalue = self.distl_filter(
                    self.address,
                    self.cspad_img.iround(),  # XXX correct?
                    distance,
                    self.timestamp,
                    self.wavelength)
                if ('permissive' in self.m_distl_flags):
                    number_of_accepted_peaks = (peak_heights >
                                                self.m_threshold).count(True)
                else:
                    number_of_accepted_peaks = ((
                        peak_heights > self.m_threshold).__and__(
                            outvalue == 0)).count(True)

                sec, ms = cspad_tbx.evt_time(evt)
                evt_time = sec + ms / 1000
                self.stats_logger.info("BRAGG %.3f %d" %
                                       (evt_time, number_of_accepted_peaks))

                skip_event = False
                if number_of_accepted_peaks < self.m_distl_min_peaks:
                    self.logger.info(
                        "Subprocess %02d: Spotfinder NO  HIT image #%05d @ %s; %d spots > %d"
                        % (env.subprocess(), self.nshots, self.timestamp,
                           number_of_accepted_peaks, self.m_threshold))

                    if not self.m_negate_hits:
                        skip_event = True
                else:
                    self.logger.info(
                        "Subprocess %02d: Spotfinder YES HIT image #%05d @ %s; %d spots > %d"
                        % (env.subprocess(), self.nshots, self.timestamp,
                           number_of_accepted_peaks, self.m_threshold))

                    if self.m_negate_hits:
                        skip_event = True

                if skip_event:
                    if self.m_db_logging:
                        # log misses to the database
                        self.queue_entry(
                            (self.trial, evt.run(), "%.3f" % evt_time,
                             number_of_accepted_peaks, distance, self.sifoil,
                             self.wavelength, False, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                             0, 0, self.m_db_tags))
                    evt.put(skip_event_flag(), "skip_event")
                    return
                # the indexer will log this hit when it is ran. Bug: if the spotfinder is ran by itself, this
                # hit will not be logged in the db.
                evt.put(number_of_accepted_peaks, 'sfspots')

        self.logger.info("Subprocess %02d: process image #%05d @ %s" %
                         (env.subprocess(), self.nshots, self.timestamp))

        # See r17537 of mod_average.py.
        if device == 'Cspad':
            pixel_size = cspad_tbx.pixel_size
            saturated_value = cspad_tbx.cspad_saturated_value
        elif device == 'marccd':
            pixel_size = evt.get("marccd_pixel_size")
            saturated_value = evt.get("marccd_saturated_value")
        elif device == 'Rayonix':
            pixel_size = rayonix_tbx.get_rayonix_pixel_size(self.bin_size)
            saturated_value = rayonix_tbx.rayonix_saturated_value

        d = cspad_tbx.dpack(
            active_areas=self.active_areas,
            address=self.address,
            beam_center_x=pixel_size * self.beam_center[0],
            beam_center_y=pixel_size * self.beam_center[1],
            data=self.cspad_img.iround(),  # XXX ouch!
            distance=distance,
            pixel_size=pixel_size,
            saturated_value=saturated_value,
            timestamp=self.timestamp,
            wavelength=self.wavelength,
            xtal_target=self.m_xtal_target)

        if (self.m_dispatch == "index"):
            import sys
            from xfel.cxi.integrate_image_api import integrate_one_image
            info = integrate_one_image(
                d,
                integration_dirname=self.m_integration_dirname,
                integration_basename=self.m_integration_basename)
            sys.stdout = sys.__stdout__
            sys.stderr = sys.__stderr__

            indexed = info is not None and hasattr(info, 'spotfinder_results')
            if self.m_progress_logging:
                if self.m_db_version == 'v1':
                    if indexed:
                        # integration pickle dictionary is available here as info.last_saved_best
                        if info.last_saved_best[
                                "identified_isoform"] is not None:
                            #print info.last_saved_best.keys()
                            from cxi_xdr_xes.cftbx.cspad_ana import db
                            dbobj = db.dbconnect(self.m_db_host,
                                                 self.m_db_name,
                                                 self.m_db_user,
                                                 self.m_db_password)
                            cursor = dbobj.cursor()
                            if info.last_saved_best[
                                    "identified_isoform"] in self.isoforms:
                                PM, indices, miller_id = self.isoforms[
                                    info.last_saved_best["identified_isoform"]]
                            else:
                                from xfel.xpp.progress_support import progress_manager
                                PM = progress_manager(info.last_saved_best,
                                                      self.m_db_experiment_tag,
                                                      self.m_trial_id,
                                                      self.m_rungroup_id,
                                                      evt.run())
                                indices, miller_id = PM.get_HKL(cursor)
                                # cache these as they don't change for a given isoform
                                self.isoforms[info.last_saved_best[
                                    "identified_isoform"]] = PM, indices, miller_id
                            if self.m_sql_buffer_size > 1:
                                self.queue_progress_entry(
                                    PM.scale_frame_detail(self.timestamp,
                                                          cursor,
                                                          do_inserts=False))
                            else:
                                PM.scale_frame_detail(self.timestamp,
                                                      cursor,
                                                      do_inserts=True)
                                dbobj.commit()
                                cursor.close()
                                dbobj.close()
                elif self.m_db_version == 'v2':
                    key_low = 'cctbx.xfel.radial_average.two_theta_low'
                    key_high = 'cctbx.xfel.radial_average.two_theta_high'
                    tt_low = evt.get(key_low)
                    tt_high = evt.get(key_high)

                    from xfel.ui.db.dxtbx_db import log_frame
                    if indexed:
                        n_spots = len(info.spotfinder_results.images[
                            info.frames[0]]['spots_total'])
                    else:
                        sfspots = evt.get('sfspots')
                        if sfspots is None:
                            if info is None or not isinstance(info, int):
                                n_spots = 0
                            else:
                                n_spots = info
                        else:
                            n_spots = sfspots

                    if indexed:
                        known_setting = info.horizons_phil.known_setting
                        indexed_setting = info.organizer.info[
                            'best_integration']['counter']
                        if known_setting is None or known_setting == indexed_setting:
                            from xfel.command_line.frame_unpickler import construct_reflection_table_and_experiment_list
                            c = construct_reflection_table_and_experiment_list(
                                info.last_saved_best,
                                None,
                                pixel_size,
                                proceed_without_image=True)
                            c.assemble_experiments()
                            c.assemble_reflections()
                            log_frame(c.experiment_list, c.reflections,
                                      self.db_params, evt.run(), n_spots,
                                      self.timestamp, tt_low, tt_high)
                        else:
                            print(
                                "Not logging %s, wrong bravais setting (expecting %d, got %d)"
                                % (self.timestamp, known_setting,
                                   indexed_setting))
                    else:
                        log_frame(None, None, self.db_params, evt.run(),
                                  n_spots, self.timestamp, tt_low, tt_high)

            if self.m_db_logging:
                sec, ms = cspad_tbx.evt_time(evt)
                evt_time = sec + ms / 1000
                sfspots = evt.get('sfspots')
                if sfspots is None:
                    if indexed:
                        n_spots = len(info.spotfinder_results.images[
                            info.frames[0]]['spots_total'])
                    else:
                        n_spots = 0
                else:
                    n_spots = sfspots

                if indexed:
                    mosaic_bloc_rotation = info.last_saved_best.get(
                        'ML_half_mosaicity_deg', [0])[0]
                    mosaic_block_size = info.last_saved_best.get(
                        'ML_domain_size_ang', [0])[0]
                    ewald_proximal_volume = info.last_saved_best.get(
                        'ewald_proximal_volume', [0])[0]

                    obs = info.last_saved_best['observations'][0]
                    cell_a, cell_b, cell_c, cell_alpha, cell_beta, cell_gamma = obs.unit_cell(
                    ).parameters()
                    pointgroup = info.last_saved_best['pointgroup']
                    resolution = obs.d_min()
                else:
                    mosaic_bloc_rotation = mosaic_block_size = ewald_proximal_volume = cell_a = cell_b = cell_c = \
                      cell_alpha = cell_beta = cell_gamma = spacegroup = resolution = 0

                self.queue_entry(
                    (self.trial, evt.run(), "%.3f" % evt_time, n_spots,
                     distance, self.sifoil, self.wavelength, indexed,
                     mosaic_bloc_rotation, mosaic_block_size,
                     ewald_proximal_volume, pointgroup, cell_a, cell_b, cell_c,
                     cell_alpha, cell_beta, cell_gamma, resolution,
                     self.m_db_tags))

            if (not indexed):
                evt.put(skip_event_flag(), "skip_event")
                return

        elif (self.m_dispatch == "nop"):
            pass

        elif (self.m_dispatch == "view"):  #interactive image viewer

            args = ["indexing.data=dummy"]
            detector_format_version = detector_format_function(
                self.address, evt.GetTime())
            if detector_format_version is not None:
                args += [
                    "distl.detector_format_version=%" % detector_format_version
                ]

            from xfel.phil_preferences import load_cxi_phil
            horizons_phil = load_cxi_phil(self.m_xtal_target, args)
            horizons_phil.indexing.data = d

            from xfel.cxi import display_spots
            display_spots.parameters.horizons_phil = horizons_phil
            display_spots.wrapper_of_callback().display(
                horizons_phil.indexing.data)

        elif (self.m_dispatch == "spots"):  #interactive spotfinder viewer

            args = ["indexing.data=dummy"]
            detector_format_version = detector_format_function(
                self.address, evt.GetTime())
            if detector_format_version is not None:
                args += [
                    "distl.detector_format_version=%s" %
                    detector_format_version
                ]

            from xfel.phil_preferences import load_cxi_phil
            horizons_phil = load_cxi_phil(self.m_xtal_target, args)
            horizons_phil.indexing.data = d

            from xfel.cxi import display_spots
            display_spots.parameters.horizons_phil = horizons_phil

            from rstbx.new_horizons.index import pre_indexing_validation, pack_names
            pre_indexing_validation(horizons_phil)
            imagefile_arguments = pack_names(horizons_phil)
            horizons_phil.persist.show()
            from spotfinder.applications import signal_strength
            info = signal_strength.run_signal_strength_core(
                horizons_phil, imagefile_arguments)

            work = display_spots.wrapper_of_callback(info)
            work.display_with_callback(horizons_phil.indexing.data)

        elif (self.m_dispatch == "write_dict"):
            self.logger.warning(
                "event(): deprecated dispatch 'write_dict', use mod_dump instead"
            )
            if (self.m_out_dirname is not None
                    or self.m_out_basename is not None):
                cspad_tbx.dwritef(d, self.m_out_dirname, self.m_out_basename)

        # Diagnostic message emitted only when all the processing is done.
        if (env.subprocess() >= 0):
            self.logger.info("Subprocess %02d: accepted #%05d @ %s" %
                             (env.subprocess(), self.nshots, self.timestamp))
        else:
            self.logger.info("Accepted #%05d @ %s" %
                             (self.nshots, self.timestamp))
Example #15
0
  def event(self, evt, env):
    """The event() function is called for every L1Accept transition.

    @param evt Event data object, a configure object
    @param env Environment object
    """

    super(average_mixin, self).event(evt, env)
    if evt.get('skip_event'):
      return

    # Get the distance for the detectors that should have it, and set
    # it to NaN for those that should not.
    if self.detector == 'CxiDs1' or \
       self.detector == 'CxiDs2' or \
       self.detector == 'CxiDsd' or \
       self.detector == 'XppGon':
      distance = cspad_tbx.env_distance(self.address, env, self._detz_offset)
      if distance is None:
        self._nfail += 1
        self.logger.warning("event(): no distance, shot skipped")
        evt.put(skip_event_flag(), 'skip_event')
        return
    else:
      distance = float('nan')

    if ("skew" in self.flags):
      # Take out inactive pixels
      if self.roi is not None:
        pixels = self.cspad_img[self.roi[2]:self.roi[3], self.roi[0]:self.roi[1]]
        dark_mask = self.dark_mask[self.roi[2]:self.roi[3], self.roi[0]:self.roi[1]]
        pixels = pixels.as_1d().select(dark_mask.as_1d())
      else:
        pixels = self.cspad_img.as_1d().select(self.dark_mask.as_1d()).as_double()
      stats = scitbx.math.basic_statistics(pixels.as_double())
      #stats.show()
      self.logger.info("skew: %.3f" %stats.skew)
      self.logger.info("kurtosis: %.3f" %stats.kurtosis)
      if 0:
        from matplotlib import pyplot
        hist_min, hist_max = flex.min(flex_cspad_img.as_double()), flex.max(flex_cspad_img.as_double())
        print hist_min, hist_max
        n_slots = 100
        n, bins, patches = pyplot.hist(flex_cspad_img.as_1d().as_numpy_array(), bins=n_slots, range=(hist_min, hist_max))
        pyplot.show()

      # XXX This skew threshold probably needs fine-tuning
      skew_threshold = 0.35
      if stats.skew < skew_threshold:
        self._nfail += 1
        self.logger.warning("event(): skew < %f, shot skipped" % skew_threshold)
        evt.put(skip_event_flag(), 'skip_event')
        return
      #self.cspad_img *= stats.skew

    if ("inactive" in self.flags):
      self.cspad_img.set_selected(self.dark_stddev <= 0, 0)

    if ("noelastic" in self.flags):
      ELASTIC_THRESHOLD = self.elastic_threshold
      self.cspad_img.set_selected(self.cspad_img > ELASTIC_THRESHOLD, 0)

    if self.hot_threshold is not None:
      HOT_THRESHOLD = self.hot_threshold
      self.cspad_img.set_selected(self.dark_img > HOT_THRESHOLD, 0)

    if self.gain_map is not None and self.gain_threshold is not None:
      # XXX comparing each pixel to a moving average would probably be better
      # since the gain should vary approximately smoothly over different areas
      # of the detector
      GAIN_THRESHOLD = self.gain_threshold
      #self.logger.debug(
        #"rejecting: %i" %(self.gain_map > GAIN_THRESHOLD).count(True))
      self.cspad_img.set_selected(self.gain_map > GAIN_THRESHOLD, 0)

    if ("nonoise" in self.flags):
      NOISE_THRESHOLD = self.noise_threshold
      self.cspad_img.set_selected(self.cspad_img < NOISE_THRESHOLD, 0)

    if ("sigma_scaling" in self.flags):
      self.do_sigma_scaling()

    if ("symnoise" in self.flags):
      SYMNOISE_THRESHOLD = self.symnoise_threshold
      self.cspad_img.set_selected((-SYMNOISE_THRESHOLD < self.cspad_img) &
                                  ( self.cspad_img  < SYMNOISE_THRESHOLD), 0)

    if ("output" in self.flags):
      try:
        import cPickle as pickle
      except ImportError:
        import pickle
      import os
      if (not os.path.isdir(self.pickle_dirname)):
        os.makedirs(self.pickle_dirname)
      flexdata = flex.int(self.cspad_img.astype(numpy.int32))
      d = cspad_tbx.dpack(
        address=self.address,
        data=flexdata,
        timestamp=cspad_tbx.evt_timestamp(cspad_tbx.evt_time(evt))
      )
      G = open(os.path.join(".",self.pickle_dirname)+"/"+self.pickle_basename,
               "ab")
      pickle.dump(d,G,pickle.HIGHEST_PROTOCOL)
      G.close()

    if self.photon_threshold is not None and self.two_photon_threshold is not None:
      self.do_photon_counting()

    if self.background_path is not None:
      self.cspad_img -= self.background_img


    # t and self._sum_time are a two-long arrays of seconds and
    # milliseconds which hold time with respect to the base time.
    t = [t1 - t2 for (t1, t2) in zip(cspad_tbx.evt_time(evt),
                                     self._metadata['time_base'])]
    if self._nmemb == 0:
      # The peers metadata item is a bit field where a bit is set if
      # the partial sum from the corresponding worker process is
      # pending.  If this is the first frame a worker process sees,
      # set its corresponding bit in the bit field since it will
      # contribute a partial sum.
      if env.subprocess() >= 0:
        self._lock.acquire()
        if 'peers' in self._metadata.keys():
          self._metadata['peers'] |= (1 << env.subprocess())
        else:
          self._metadata['peers'] = (1 << env.subprocess())
        self._lock.release()

      self._sum_distance = distance
      self._sum_time = (t[0], t[1])
      self._sum_wavelength = self.wavelength

      if self._have_max:
        self._max_img = self.cspad_img.deep_copy()
      if self._have_mean:
        self._sum_img = self.cspad_img.deep_copy()
      if self._have_std:
        self._ssq_img = flex.pow2(self.cspad_img)

    else:
      self._sum_distance += distance
      self._sum_time = (self._sum_time[0] + t[0], self._sum_time[1] + t[1])
      self._sum_wavelength += self.wavelength

      if self._have_max:
        sel = (self.cspad_img > self._max_img).as_1d()
        self._max_img.as_1d().set_selected(
          sel, self.cspad_img.as_1d().select(sel))
      if self._have_mean:
        self._sum_img += self.cspad_img
      if self._have_std:
        self._ssq_img += flex.pow2(self.cspad_img)

    self._nmemb += 1
Example #16
0
  def event(self, evt, env):
    """The event() function is called for every L1Accept transition.

    @param evt Event data object, a configure object
    @param env Environment object
    """
    super(common_mode_correction, self).event(evt, env)
    if (evt.get("skip_event")):
      return

    if not hasattr(self, 'active_areas') or self.active_areas is None or \
       not hasattr(self, 'beam_center')  or self.beam_center  is None:
      if self.address == 'XppGon-0|marccd-0':
        # The mod_mar module needs to have been called before this one
        # to set this up.  The MAR does not have a configure object.
        self.beam_center = evt.get("marccd_beam_center")
        self.active_areas = evt.get("marccd_active_areas")
      elif self.address == 'XppEndstation-0|Rayonix-0' or \
           self.address == 'MfxEndstation-0|Rayonix-0':
        pass # bc and aa set in the beginjob function
      elif self.address == 'XppGon-0|Cspad-0':
        # Load the active areas as determined from the optical metrology
        from iotbx.detectors.cspad_detector_formats import detector_format_version, reverse_timestamp
        from xfel.cxi.cspad_ana.cspad_tbx import xpp_active_areas
        version_lookup = detector_format_version(self.address, reverse_timestamp(self.timestamp)[0])
        assert version_lookup is not None
        self.active_areas = xpp_active_areas[version_lookup]['active_areas']
        self.beam_center = [1765 // 2, 1765 // 2]
      else:
        (self.beam_center, self.active_areas) = \
          cspad_tbx.cbcaa(cspad_tbx.getConfig(self.address, env), self.sections)

    if self.filter_laser_1_status is not None:
      if (self.laser_1_status.status != self.filter_laser_1_status or
          (self.laser_1_ms_since_change is not None and
           self.laser_1_ms_since_change < self.filter_laser_wait_time)):
        evt.put(skip_event_flag(), "skip_event")
        return
    if self.filter_laser_4_status is not None:
      if (self.laser_4_status.status != self.filter_laser_4_status or
          (self.laser_4_ms_since_change is not None and
           self.laser_4_ms_since_change < self.filter_laser_wait_time)):
        evt.put(skip_event_flag(), "skip_event")
        return

    # Early return if the full detector image is already stored in the
    # event.  Otherwise, get it from the stream as a double-precision
    # floating-point flex array.  XXX It is probably not safe to key
    # the image on self.address, so we should come up with our own
    # namespace.  XXX Misnomer--could be CAMP, too

    self.cspad_img = evt.get(self.address)
    if self.cspad_img is not None:
      return
    if self.address == 'XppGon-0|Cspad-0':
      # Kludge until cspad_tbx.image() can be rewritten to handle the
      # XPP metrology.
      self.cspad_img = cspad_tbx.image_xpp(
        self.address, evt, env, self.active_areas)
    elif self.address == 'XppEndstation-0|Rayonix-0' or \
         self.address == 'MfxEndstation-0|Rayonix-0':
      from psana import Source, Camera
      import numpy as np
      address = cspad_tbx.old_address_to_new_address(self.address)
      src=Source('DetInfo(%s)'%address)
      self.cspad_img = evt.get(Camera.FrameV1,src)
      if self.cspad_img is not None:
        self.cspad_img = self.cspad_img.data16().astype(np.float64)
    elif self.address=='CxiDg3-0|Opal1000-0':
      if evt.getFrameValue(self.address) is not None:
        self.cspad_img = evt.getFrameValue(self.address).data()
    elif self.address=='CxiEndstation-0|Opal1000-2':
      if evt.getFrameValue(self.address) is not None:
        self.cspad_img = evt.getFrameValue(self.address).data()
    elif self.address=='FeeHxSpectrometer-0|Opal1000-1':
      if evt.getFrameValue(self.address) is not None:
        self.cspad_img = evt.getFrameValue(self.address).data()
    elif self.address=='NoDetector-0|Cspad2x2-0':
        import numpy as np
        from pypdsdata import xtc
        test=[]
        self.cspad_img = evt.get(xtc.TypeId.Type.Id_Cspad2x2Element,self.address).data()
        self.cspad_img=np.reshape(self.cspad_img,(370, 388))
    else:
      try:
        self.cspad_img = cspad_tbx.image(
          self.address, cspad_tbx.getConfig(self.address, env),
          evt, env, self.sections)
      except Exception, e:
        self.logger.error("Error reading image data: " + str(e))
        evt.put(skip_event_flag(), "skip_event")
        return
Example #17
0
    def event(self, evt, env):
        """The event() function is called for every L1Accept transition.

    @param evt Event data object, a configure object
    @param env Environment object
    """
        super(common_mode_correction, self).event(evt, env)
        if (evt.get("skip_event")):
            return

        if not hasattr(self, 'active_areas') or self.active_areas is None or \
           not hasattr(self, 'beam_center')  or self.beam_center  is None:
            if self.address == 'XppGon-0|marccd-0':
                # The mod_mar module needs to have been called before this one
                # to set this up.  The MAR does not have a configure object.
                self.beam_center = evt.get("marccd_beam_center")
                self.active_areas = evt.get("marccd_active_areas")
            elif self.address == 'XppEndstation-0|Rayonix-0' or \
                 self.address == 'MfxEndstation-0|Rayonix-0':
                pass  # bc and aa set in the beginjob function
            elif self.address == 'XppGon-0|Cspad-0':
                # Load the active areas as determined from the optical metrology
                from iotbx.detectors.cspad_detector_formats import detector_format_version, reverse_timestamp
                from xfel.cxi.cspad_ana.cspad_tbx import xpp_active_areas
                version_lookup = detector_format_version(
                    self.address,
                    reverse_timestamp(self.timestamp)[0])
                assert version_lookup is not None
                self.active_areas = xpp_active_areas[version_lookup][
                    'active_areas']
                self.beam_center = [1765 // 2, 1765 // 2]
            else:
                (self.beam_center, self.active_areas) = \
                  cspad_tbx.cbcaa(cspad_tbx.getConfig(self.address, env), self.sections)

        if self.filter_laser_1_status is not None:
            if (self.laser_1_status.status != self.filter_laser_1_status or
                (self.laser_1_ms_since_change is not None and
                 self.laser_1_ms_since_change < self.filter_laser_wait_time)):
                evt.put(skip_event_flag(), "skip_event")
                return
        if self.filter_laser_4_status is not None:
            if (self.laser_4_status.status != self.filter_laser_4_status or
                (self.laser_4_ms_since_change is not None and
                 self.laser_4_ms_since_change < self.filter_laser_wait_time)):
                evt.put(skip_event_flag(), "skip_event")
                return

        # Early return if the full detector image is already stored in the
        # event.  Otherwise, get it from the stream as a double-precision
        # floating-point flex array.  XXX It is probably not safe to key
        # the image on self.address, so we should come up with our own
        # namespace.  XXX Misnomer--could be CAMP, too

        self.cspad_img = evt.get(self.address)
        if self.cspad_img is not None:
            return
        if self.address == 'XppGon-0|Cspad-0':
            # Kludge until cspad_tbx.image() can be rewritten to handle the
            # XPP metrology.
            self.cspad_img = cspad_tbx.image_xpp(self.address, evt, env,
                                                 self.active_areas)
        elif self.address == 'XppEndstation-0|Rayonix-0' or \
             self.address == 'MfxEndstation-0|Rayonix-0':
            from psana import Source, Camera
            import numpy as np
            address = cspad_tbx.old_address_to_new_address(self.address)
            src = Source('DetInfo(%s)' % address)
            self.cspad_img = evt.get(Camera.FrameV1, src)
            if self.cspad_img is not None:
                self.cspad_img = self.cspad_img.data16().astype(np.float64)
        elif self.address == 'CxiDg3-0|Opal1000-0':
            if evt.getFrameValue(self.address) is not None:
                self.cspad_img = evt.getFrameValue(self.address).data()
        elif self.address == 'CxiEndstation-0|Opal1000-2':
            if evt.getFrameValue(self.address) is not None:
                self.cspad_img = evt.getFrameValue(self.address).data()
        elif self.address == 'FeeHxSpectrometer-0|Opal1000-1':
            if evt.getFrameValue(self.address) is not None:
                self.cspad_img = evt.getFrameValue(self.address).data()
        elif self.address == 'NoDetector-0|Cspad2x2-0':
            import numpy as np
            from pypdsdata import xtc
            test = []
            self.cspad_img = evt.get(xtc.TypeId.Type.Id_Cspad2x2Element,
                                     self.address).data()
            self.cspad_img = np.reshape(self.cspad_img, (370, 388))
        else:
            try:
                self.cspad_img = cspad_tbx.image(
                    self.address, cspad_tbx.getConfig(self.address, env), evt,
                    env, self.sections)
            except Exception as e:
                self.logger.error("Error reading image data: " + str(e))
                evt.put(skip_event_flag(), "skip_event")
                return

        if self.cspad_img is None:
            if cspad_tbx.address_split(self.address)[2] != 'Andor':
                self.nfail += 1
                self.logger.warning("event(): no image, shot skipped")
                evt.put(skip_event_flag(), "skip_event")
            return
        self.cspad_img = flex.double(self.cspad_img.astype(numpy.float64))
        # If a dark image was provided, subtract it from the image.  There
        # is no point in doing common-mode correction unless the dark
        # image was subtracted.
        if (self.dark_img is not None):
            self.cspad_img -= self.dark_img

            if (self.common_mode_correction != "none"):
                # Mask out inactive pixels prior to common mode correction.
                # Pixels are marked as inactive either due to low ADU values
                # or non-positive standard deviations in dark image.  XXX Make
                # the threshold tunable?
                cspad_mask = self.dark_mask.deep_copy()

                if self.roi is not None and self.common_mode_correction == "chebyshev":
                    roi_mask = cspad_mask[self.roi[2]:self.roi[3], :]
                    roi_mask = flex.bool(roi_mask.accessor(), False)
                    cspad_mask.matrix_paste_block_in_place(block=roi_mask,
                                                           i_row=self.roi[2],
                                                           i_column=0)

                # Extract each active section from the assembled detector
                # image and apply the common mode correction.  XXX Make up a
                # quadrant mask for the emission detector.  Needs to be
                # checked!
                config = cspad_tbx.getConfig(self.address, env)
                if len(self.sections) == 1:
                    q_mask = 1
                else:
                    q_mask = config.quadMask()
                for q in range(len(self.sections)):
                    if (not ((1 << q) & q_mask)):
                        continue

                    # XXX Make up section mask for the emission detector.  Needs
                    # to be checked!
                    import _pdsdata
                    if len(self.sections) == 1 and type(config) in (
                            _pdsdata.cspad2x2.ConfigV1,
                            _pdsdata.cspad2x2.ConfigV2):
                        s_mask = config.roiMask()
                    else:
                        s_mask = config.roiMask(q)
                    for s in range(len(self.sections[q])):
                        # XXX DAQ misconfiguration?  This mask appears not to work
                        # reliably for the Sc1 detector.
                        #            if (not((1 << s) & s_mask)):
                        #              continue
                        corners = self.sections[q][s].corners()
                        i_row = int(round(min(c[0] for c in corners)))
                        i_column = int(round(min(c[1] for c in corners)))
                        n_rows = int(round(max(c[0] for c in corners))) - i_row
                        n_columns = int(round(max(
                            c[1] for c in corners))) - i_column

                        section_img = self.cspad_img.matrix_copy_block(
                            i_row=i_row,
                            i_column=i_column,
                            n_rows=n_rows,
                            n_columns=n_columns)
                        section_mask = cspad_mask.matrix_copy_block(
                            i_row=i_row,
                            i_column=i_column,
                            n_rows=n_rows,
                            n_columns=n_columns)
                        section_stddev = self.dark_stddev.matrix_copy_block(
                            i_row=i_row,
                            i_column=i_column,
                            n_rows=n_rows,
                            n_columns=n_columns)

                        if section_mask.count(True) == 0: continue

                        if self.common_mode_correction == "chebyshev":
                            assert len(self.sections[q]) == 2
                            if s == 0:
                                section_imgs = [section_img]
                                section_masks = [section_mask]
                                i_rows = [i_row]
                                i_columns = [i_column]
                                continue
                            else:
                                section_imgs.append(section_img)
                                section_masks.append(section_mask)
                                i_rows.append(i_row)
                                i_columns.append(i_column)

                                chebyshev_corrected_imgs = self.chebyshev_common_mode(
                                    section_imgs, section_masks)
                                for i in range(2):
                                    section_imgs[i].as_1d().copy_selected(
                                        section_masks[i].as_1d().iselection(),
                                        chebyshev_corrected_imgs[i].as_1d())
                                    self.cspad_img.matrix_paste_block_in_place(
                                        block=section_imgs[i],
                                        i_row=i_rows[i],
                                        i_column=i_columns[i])

                        else:
                            common_mode = self.common_mode(
                                section_img, section_stddev, section_mask)
                            self.sum_common_mode += common_mode
                            self.sumsq_common_mode += common_mode**2

                            # Apply the common mode correction to the
                            # section, and paste it back into the image.
                            self.cspad_img.matrix_paste_block_in_place(
                                block=section_img - common_mode,
                                i_row=i_row,
                                i_column=i_column)

        if self.gain_map is not None:
            self.cspad_img *= self.gain_map

        if (self.mask_img is not None):
            sel = (self.mask_img == -2) | (self.mask_img
                                           == cspad_tbx.cspad_mask_value)
            self.cspad_img.set_selected(sel, cspad_tbx.cspad_mask_value)

        if (self.address == 'XppEndstation-0|Rayonix-0' or \
            self.address == 'MfxEndstation-0|Rayonix-0') and \
            self.crop_rayonix:
            # Crop the masked data so that the beam center is in the center of the image
            self.cspad_img = self.cspad_img[self.rayonix_crop_slice[0],
                                            self.rayonix_crop_slice[1]]

        if self.cache_image:
            # Store the image in the event.
            evt.put(self.cspad_img, self.address)
Example #18
0
  def event(self, evt, env):
    """The event() function is called for every L1Accept transition.
    XXX Since the viewer is now running in a parallel process, the
    averaging here is now the bottleneck.

    @param evt Event data object, a configure object
    @param env Environment object
    """
    from pyana.event import Event

    self.n_shots += 1

    super(mod_view, self).event(evt, env)
    if evt.status() != Event.Normal or evt.get('skip_event'): # XXX transition
      return

    # Get the distance for the detectors that should have it, and set
    # it to NaN for those that should not.
    if self.detector == 'CxiDs1' or \
       self.detector == 'CxiDsd' or \
       self.detector == 'XppGon':
      distance = cspad_tbx.env_distance(self.address, env, self._detz_offset)
      if distance is None:
        self.nfail += 1
        self.logger.warning("event(): no distance, shot skipped")
        evt.put(skip_event_flag(), "skip_event")
        return
    else:
      distance = float('nan')

    if not self._proc.is_alive():
      evt.setStatus(Event.Stop)

    # Early return if the next update to the viewer is more than
    # self.ncollate shots away.  XXX Since the common_mode.event()
    # function does quite a bit of processing, the savings are
    # probably not so big.
    next_update = (self.nupdate - 1) - (self.nshots - 1) % self.nupdate
    if (self.ncollate > 0 and next_update >= self.ncollate):
      return

    if self.sigma_scaling:
      self.do_sigma_scaling()

    if self.photon_counting:
      self.do_photon_counting()

    # Trim the disabled section from the Sc1 detector image.  XXX This
    # is a bit of a kludge, really.
#    if (self.address == "CxiSc1-0|Cspad2x2-0"):
#      self.cspad_img = self.cspad_img[185:2 * 185, :]

    # Update the sum of the valid images, starting a new collation if
    # appropriate.  This guarantees self.nvalid > 0.
    if (self.nvalid == 0 or self.ncollate > 0 and self.nvalid >= self.ncollate):
      self.img_sum = self.cspad_img
      self.nvalid  = 1
    else:
      self.img_sum += self.cspad_img
      self.nvalid  += 1

    # Update the viewer to display the current average image, and
    # start a new collation, if appropriate.
    if (next_update == 0):
      from time import localtime, strftime

      time_str = strftime("%H:%M:%S", localtime(evt.getTime().seconds()))
      title = "r%04d@%s: average of %d last images on %s" \
          % (evt.run(), time_str, self.nvalid, self.address)

      # See also mod_average.py.
      device = cspad_tbx.address_split(self.address)[2]
      if device == 'Cspad':
        beam_center = self.beam_center
        pixel_size = cspad_tbx.pixel_size
        saturated_value = cspad_tbx.cspad_saturated_value

      elif device == 'marccd':
        beam_center = tuple(t // 2 for t in self.img_sum.focus())
        pixel_size = 0.079346
        saturated_value = 2**16 - 1

      # Wait for the viewer process to empty the queue before feeding
      # it a new image, and ensure not to hang if the viewer process
      # exits.  Because of multithreading/multiprocessing semantics,
      # self._queue.empty() is unreliable.
      fmt = _Format(BEAM_CENTER=beam_center,
                      DATA=self.img_sum / self.nvalid,
                      DETECTOR_ADDRESS=self.address,
                      DISTANCE=distance,
                      PIXEL_SIZE=pixel_size,
                      SATURATED_VALUE=saturated_value,
                      TIME_TUPLE=cspad_tbx.evt_time(evt),
                      WAVELENGTH=self.wavelength)

      while not self._queue.empty():
        if not self._proc.is_alive():
          evt.setStatus(Event.Stop)
          return
      while True:
        try:
          self._queue.put((fmt, title), timeout=1)
          break
        except Exception:
          pass

      if (self.ncollate > 0):
        self.nvalid = 0
Example #19
0
    def event(self, evt, evn):
        """The event() function puts a "skip_event" object with value @c
    True into the event if the shot is to be skipped.

    @param evt Event data object, a configure object
    @param env Environment object
    """
        #import pdb; pdb.set_trace()
        if (evt.get("skip_event")):
            return
        # check if FEE data is one or two dimensional
        data = evt.get(Camera.FrameV1, self.src)
        if data is None:
            one_D = True
            data = evt.get(Bld.BldDataSpectrometerV1, self.src)
        else:
            one_D = False
        # get event timestamp
        timestamp = cspad_tbx.evt_timestamp(
            cspad_tbx.evt_time(evt))  # human readable format

        if data is None:
            self.nnodata += 1
            #self.logger.warning("event(): No spectrum data")
            evt.put(skip_event_flag(), "skip_event")

        if timestamp is None:
            evt.put(skip_event_flag(), "skip_event")
            #self.logger.warning("event(): No TIMESTAMP, skipping shot")

        elif data is not None:
            self.nshots += 1
            # get data as array and split into two half to find each peak
            if one_D:
                # filtering out outlier spikes in FEE data
                data = np.array(data.hproj().astype(np.float64))
                for i in range(len(data)):
                    if data[i] > 1000000000:
                        data[i] = data[i] - (2**32)
                if self.dark is not None:
                    data = data - self.dark
                spectrum = data
                spectrum1 = data[:data.shape[0] // 2]
                spectrum2 = data[data.shape[0] // 2:]
            else:
                data = np.array(data.data16().astype(np.int32))
                if self.dark is not None:
                    data = data - self.dark
                data_split1 = data[:, :data.shape[1] // 2]
                data_split2 = data[:, data.shape[1] // 2:]
                # make a 1D trace of entire spectrum and each half to find peaks
                spectrum = np.sum(data, 0) / data.shape[0]
                spectrum1 = np.sum(data_split1, 0) / data_split1.shape[0]
                spectrum2 = np.sum(data_split2, 0) / data_split2.shape[0]
            if not one_D:
                # the x-coordinate of the weighted center of peak region
                weighted_peak_one_positions = []
                for i in range(self.peak_one_range_min,
                               self.peak_one_range_max):
                    weighted_peak_one_positions.append(spectrum[i] * i)
                weighted_sum_peak_one = sum(weighted_peak_one_positions)
                weighted_peak_one_center_position = weighted_sum_peak_one // sum(
                    spectrum[self.peak_one_range_min:self.peak_one_range_max])
                weighted_peak_two_positions = []
                for i in range(self.peak_two_range_min,
                               self.peak_two_range_max):
                    weighted_peak_two_positions.append(spectrum[i] * i)
                weighted_sum_peak_two = sum(weighted_peak_two_positions)
                weighted_peak_two_center_position = weighted_sum_peak_two // sum(
                    spectrum[self.peak_two_range_min:self.peak_two_range_max])
                # normalized integrated regions between the peaks
                int_left_region_norm = np.sum(spectrum[0:(
                    weighted_peak_one_center_position -
                    len(spectrum[self.peak_one_range_min:self.
                                 peak_one_range_max]) / 2)]) / len(spectrum[0:(
                                     weighted_peak_one_center_position -
                                     len(spectrum[self.peak_one_range_min:self.
                                                  peak_one_range_max]) / 2)])

                int_middle_region_norm = np.sum(
                    spectrum[(weighted_peak_one_center_position +
                              len(spectrum[self.peak_one_range_min:self.
                                           peak_one_range_max]) / 2):
                             (weighted_peak_two_center_position -
                              len(spectrum[self.peak_two_range_min:self.
                                           peak_two_range_max]) / 2)]
                ) / len(spectrum[(weighted_peak_one_center_position +
                                  len(spectrum[self.peak_one_range_min:self.
                                               peak_one_range_max]) / 2):
                                 (weighted_peak_two_center_position -
                                  len(spectrum[self.peak_two_range_min:self.
                                               peak_two_range_max]) / 2)])

                int_right_region_norm = np.sum(spectrum[(
                    weighted_peak_two_center_position +
                    len(spectrum[self.peak_two_range_min:self.
                                 peak_two_range_max]) / 2):]) / len(spectrum[(
                                     weighted_peak_two_center_position +
                                     len(spectrum[self.peak_two_range_min:self.
                                                  peak_two_range_max]) / 2):])

                # normalized integrated peaks
                int_peak_one_norm = np.sum(
                    spectrum[(weighted_peak_one_center_position -
                              len(spectrum[self.peak_one_range_min:self.
                                           peak_one_range_max]) / 2):
                             (weighted_peak_one_center_position +
                              len(spectrum[self.peak_one_range_min:self.
                                           peak_one_range_max]) / 2)]
                ) / len(spectrum[(weighted_peak_one_center_position -
                                  len(spectrum[self.peak_one_range_min:self.
                                               peak_one_range_max]) / 2):
                                 (weighted_peak_one_center_position +
                                  len(spectrum[self.peak_one_range_min:self.
                                               peak_one_range_max]) / 2)])

                int_peak_two_norm = np.sum(
                    spectrum[(weighted_peak_two_center_position -
                              len(spectrum[self.peak_two_range_min:self.
                                           peak_two_range_max]) / 2):
                             (weighted_peak_two_center_position +
                              len(spectrum[self.peak_two_range_min:self.
                                           peak_two_range_max]) / 2)]
                ) / len(spectrum[(weighted_peak_two_center_position -
                                  len(spectrum[self.peak_two_range_min:self.
                                               peak_two_range_max]) / 2):
                                 (weighted_peak_two_center_position +
                                  len(spectrum[self.peak_two_range_min:self.
                                               peak_two_range_max]) / 2)])

            else:
                # convert eV range of iron edge (7112 eV) to pixels:
                metal_edge_max = (self.forbidden_range_eV / 2.) / 0.059 + 738
                metal_edge_min = (-self.forbidden_range_eV / 2.) / 0.059 + 738
                int_metal_region = np.sum(
                    spectrum[metal_edge_min:metal_edge_max])
                #peak one region integrate:
                int_peak_one = np.sum(spectrum[0:metal_edge_min])
                int_peak_two = np.sum(spectrum[metal_edge_max:])
            # now to do the filtering
            if not one_D:
                if min(int_peak_one_norm, int_peak_two_norm) / max(
                        int_peak_one_norm,
                        int_peak_two_norm) < self.peak_ratio:
                    print("event(): too low")
                    evt.put(skip_event_flag(), "skip_event")
                    return
                if (np.argmax(spectrum2) + len(spectrum2)) > (
                        weighted_peak_two_center_position +
                    (len(spectrum[self.peak_two_range_min:self.
                                  peak_two_range_max]) /
                     2)) or (np.argmax(spectrum2) + len(spectrum2)) < (
                         weighted_peak_two_center_position -
                         (len(spectrum[self.peak_two_range_min:self.
                                       peak_two_range_max]) / 2)):
                    print("event(): out of range high energy peak")
                    evt.put(skip_event_flag(), "skip_event")
                    return
                if np.argmax(spectrum1) > (
                        weighted_peak_one_center_position +
                    (len(spectrum[self.peak_one_range_min:self.
                                  peak_one_range_max]) /
                     2)) or np.argmax(spectrum1) < (
                         weighted_peak_one_center_position -
                         (len(spectrum[self.peak_one_range_min:self.
                                       peak_one_range_max]) / 2)):
                    print("event(): out of range low energy peak")
                    evt.put(skip_event_flag(), "skip_event")
                    return
                if int_left_region_norm / int_peak_one_norm > self.normalized_peak_to_noise_ratio:
                    print("event(): noisy left of low energy peak")
                    evt.put(skip_event_flag(), "skip_event")
                    return
                if int_middle_region_norm / int_peak_one_norm > self.normalized_peak_to_noise_ratio:
                    print("event(): noisy middle")
                    evt.put(skip_event_flag(), "skip_event")
                    return
                if int_middle_region_norm / int_peak_one_norm > self.normalized_peak_to_noise_ratio:
                    print("event(): noisy middle")
                    evt.put(skip_event_flag(), "skip_event")
                    return
                if int_right_region_norm / int_peak_two_norm > self.normalized_peak_to_noise_ratio:
                    print("event(): noisy right of high energy peak")
                    evt.put(skip_event_flag(), "skip_event")
                    return
            else:
                # filter for cxih8015
                #iron edge at 738 pixels on FFE detetor
                if int_metal_region >= 0.10 * int_peak_two:
                    print("event(): high intensity at metal edge")
                    evt.put(skip_event_flag(), "skip_event")
                    return
                if int_metal_region >= 0.10 * int_peak_one:
                    print("event(): high intensity at metal edge")
                    evt.put(skip_event_flag(), "skip_event")
                    return
                if min(int_peak_one, int_peak_two) / max(
                        int_peak_one, int_peak_two) < self.peak_ratio:
                    print("event(): peak ratio too low")
                    evt.put(skip_event_flag(), "skip_event")
                    return
            #self.logger.info("TIMESTAMP %s accepted" %timestamp)
            self.naccepted += 1
            self.ntwo_color += 1
            print("%d Two Color shots" % self.ntwo_color)
Example #20
0
    def event(self, evt, env):
        if (evt.get("skip_event")):
            return
        self.nshots += 1

        s = None
        t = evt.getTime()
        if (t is not None):
            s = t.seconds() + (t.nanoseconds() / 1000000000)
        else:
            self.nfail += 1
            self.logger.warning("event(): no timestamp, shot skipped")
            evt.put(skip_event_flag(), "skip_event")
            return
        if (not isinstance(s, float)):
            raise RuntimeError("Wrong type for 's': %s" % type(s).__name__)

        # XXX This hardcodes the address for the front detector!
        det_z = cspad_tbx.env_detz('CxiDs1-0|Cspad-0', env)
        if (det_z is None):
            self.nfail += 1
            self.logger.warning("event(): no distance, shot skipped")
            evt.put(skip_event_flag(), "skip_event")
            return

        laser01 = cspad_tbx.env_laser_status(env, 1)
        if laser01 is None:
            self.nfail += 1
            self.logger.warning("event(): no status for laser 1, shot skipped")
            evt.put(skip_event_flag(), 'skip_event')
            return

        laser04 = cspad_tbx.env_laser_status(env, 4)
        if laser04 is None:
            self.nfail += 1
            self.logger.warning("event(): no status for laser 4, shot skipped")
            evt.put(skip_event_flag(), 'skip_event')
            return

        # Laser power for fourth laser.  The control name was provided by
        # Jan Kern.  XXX Move to its own function in cspad_tbx?
        laser04_power = None
        if env is not None:
            pv = env.epicsStore().value('CXI:LAS:MMN:02:ROT.RBV')
            if pv is not None and len(pv.values) == 1:
                laser04_power = pv.values[0]
        if laser04_power is None:
            self.nfail += 1
            self.logger.warning("event(): no power for laser 4, shot skipped")
            evt.put(skip_event_flag(), 'skip_event')
            return

        si_foil = cspad_tbx.env_sifoil(env)
        if (si_foil is None):
            self.nfail += 1
            self.logger.warning("event(): no Si-foil thickness, shot skipped")
            evt.put(skip_event_flag(), "skip_event")
            return
        if (not (isinstance(si_foil, float) or isinstance(si_foil, int))):
            raise RuntimeError("Wrong type for 'si_foil': %s" %
                               type(si_foil).__name__)

        wavelength = cspad_tbx.evt_wavelength(evt)
        if (wavelength is None):
            self.nfail += 1
            self.logger.warning("event(): no wavelength, shot skipped")
            evt.put(skip_event_flag(), "skip_event")
            return

        # In order to keep all arrays the same length, only append once
        # all values have been successfully obtained.  XXX Still bugs: see
        # June run 119.
        self._t.append(s)
        self._si_foil.append(si_foil)
        self._wavelength.append(wavelength)
        self._det_z.append(det_z)
        self._laser01.append(laser01)
        self._laser04.append(laser04)
        self._laser04_power.append(laser04_power)
        if (self.nshots % 120 == 0):
            self.update_plot()
Example #21
0
  def event (self, evt, env) :
    if (evt.get("skip_event")) :
      return
    self.nshots += 1

    s = None
    t = evt.getTime()
    if (t is not None):
      s = t.seconds() + (t.nanoseconds() / 1000000000)
    else :
      self.nfail += 1
      self.logger.warning("event(): no timestamp, shot skipped")
      evt.put(skip_event_flag(), "skip_event")
      return
    if (not isinstance(s, float)) :
      raise RuntimeError("Wrong type for 's': %s" % type(s).__name__)

    # XXX This hardcodes the address for the front detector!
    det_z = cspad_tbx.env_detz('CxiDs1-0|Cspad-0', env)
    if (det_z is None):
      self.nfail += 1
      self.logger.warning("event(): no distance, shot skipped")
      evt.put(skip_event_flag(), "skip_event")
      return

    laser01 = cspad_tbx.env_laser_status(env, 1)
    if laser01 is None:
      self.nfail += 1
      self.logger.warning("event(): no status for laser 1, shot skipped")
      evt.put(skip_event_flag(), 'skip_event')
      return

    laser04 = cspad_tbx.env_laser_status(env, 4)
    if laser04 is None:
      self.nfail += 1
      self.logger.warning("event(): no status for laser 4, shot skipped")
      evt.put(skip_event_flag(), 'skip_event')
      return

    # Laser power for fourth laser.  The control name was provided by
    # Jan Kern.  XXX Move to its own function in cspad_tbx?
    laser04_power = None
    if env is not None:
      pv = env.epicsStore().value('CXI:LAS:MMN:02:ROT.RBV')
      if pv is not None and len(pv.values) == 1:
        laser04_power = pv.values[0]
    if laser04_power is None:
      self.nfail += 1
      self.logger.warning("event(): no power for laser 4, shot skipped")
      evt.put(skip_event_flag(), 'skip_event')
      return

    si_foil = cspad_tbx.env_sifoil(env)
    if (si_foil is None):
      self.nfail += 1
      self.logger.warning("event(): no Si-foil thickness, shot skipped")
      evt.put(skip_event_flag(), "skip_event")
      return
    if (not (isinstance(si_foil, float) or isinstance(si_foil, int))) :
      raise RuntimeError("Wrong type for 'si_foil': %s"% type(si_foil).__name__)

    wavelength = cspad_tbx.evt_wavelength(evt)
    if (wavelength is None):
      self.nfail += 1
      self.logger.warning("event(): no wavelength, shot skipped")
      evt.put(skip_event_flag(), "skip_event")
      return

    # In order to keep all arrays the same length, only append once
    # all values have been successfully obtained.  XXX Still bugs: see
    # June run 119.
    self._t.append(s)
    self._si_foil.append(si_foil)
    self._wavelength.append(wavelength)
    self._det_z.append(det_z)
    self._laser01.append(laser01)
    self._laser04.append(laser04)
    self._laser04_power.append(laser04_power)
    if (self.nshots % 120 == 0) :
      self.update_plot()
  def event(self,evt,evn):
    """The event() function puts a "skip_event" object with value @c
    True into the event if the shot is to be skipped.

    @param evt Event data object, a configure object
    @param env Environment object
    """
    #import pdb; pdb.set_trace()
    if (evt.get("skip_event")):
      return
    # check if FEE data is one or two dimensional
    data = evt.get(Camera.FrameV1, self.src)
    if data is None:
      one_D = True
      data = evt.get(Bld.BldDataSpectrometerV1, self.src)
    else:
      one_D = False
    # get event timestamp
    timestamp = cspad_tbx.evt_timestamp(cspad_tbx.evt_time(evt)) # human readable format

    if data is None:
      self.nnodata +=1
      #self.logger.warning("event(): No spectrum data")
      evt.put(skip_event_flag(),"skip_event")

    if timestamp is None:
      evt.put(skip_event_flag(),"skip_event")
      #self.logger.warning("event(): No TIMESTAMP, skipping shot")

    elif data is not None:
      self.nshots +=1
      # get data as array and split into two half to find each peak
      if one_D:
        # filtering out outlier spikes in FEE data
        data = np.array(data.hproj().astype(np.float64))
        for i in xrange(len(data)):
          if data[i]>1000000000:
            data[i]=data[i]-(2**32)
        if self.dark is not None:
          data = data - self.dark
        spectrum = data
        spectrum1 = data[:data.shape[0]//2]
        spectrum2 = data[data.shape[0]//2:]
      else:
        data = np.array(data.data16().astype(np.int32))
        if self.dark is not None:
          data = data - self.dark
        data_split1 = data[:,:data.shape[1]//2]
        data_split2 = data[:,data.shape[1]//2:]
        # make a 1D trace of entire spectrum and each half to find peaks
        spectrum  = np.sum(data,0)/data.shape[0]
        spectrum1 = np.sum(data_split1,0)/data_split1.shape[0]
        spectrum2 = np.sum(data_split2,0)/data_split2.shape[0]
      if not one_D:
        # the x-coordinate of the weighted center of peak region
        weighted_peak_one_positions = []
        for i in xrange(self.peak_one_range_min,self.peak_one_range_max):
          weighted_peak_one_positions.append(spectrum[i]*i)
        weighted_sum_peak_one = sum(weighted_peak_one_positions)
        weighted_peak_one_center_position = weighted_sum_peak_one//sum(spectrum[self.peak_one_range_min:self.peak_one_range_max])
        weighted_peak_two_positions = []
        for i in xrange(self.peak_two_range_min,self.peak_two_range_max):
          weighted_peak_two_positions.append(spectrum[i]*i)
        weighted_sum_peak_two = sum(weighted_peak_two_positions)
        weighted_peak_two_center_position = weighted_sum_peak_two//sum(spectrum[self.peak_two_range_min:self.peak_two_range_max])
        # normalized integrated regions between the peaks
        int_left_region_norm = np.sum(spectrum[0:(weighted_peak_one_center_position-len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2)])/len(spectrum[0:(weighted_peak_one_center_position-len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2)])

        int_middle_region_norm = np.sum(spectrum[(weighted_peak_one_center_position+len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2):(weighted_peak_two_center_position-len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2)])/len(spectrum[(weighted_peak_one_center_position+len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2):(weighted_peak_two_center_position-len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2)])

        int_right_region_norm = np.sum(spectrum[(weighted_peak_two_center_position+len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2):])/len(spectrum[(weighted_peak_two_center_position+len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2):])

        # normalized integrated peaks
        int_peak_one_norm = np.sum(spectrum[(weighted_peak_one_center_position-len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2):(weighted_peak_one_center_position+len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2)])/len(spectrum[(weighted_peak_one_center_position-len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2):(weighted_peak_one_center_position+len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2)])

        int_peak_two_norm = np.sum(spectrum[(weighted_peak_two_center_position-len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2):(weighted_peak_two_center_position+len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2)])/len(spectrum[(weighted_peak_two_center_position-len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2):(weighted_peak_two_center_position+len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2)])

      else:
        # convert eV range of iron edge (7112 eV) to pixels:
        metal_edge_max=(self.forbidden_range_eV/2.)/0.059+738
        metal_edge_min=(-self.forbidden_range_eV/2.)/0.059+738
        int_metal_region = np.sum(spectrum[metal_edge_min:metal_edge_max])
        #peak one region integrate:
        int_peak_one=np.sum(spectrum[0:metal_edge_min])
        int_peak_two=np.sum(spectrum[metal_edge_max:])
      # now to do the filtering
      if not one_D:
        if min(int_peak_one_norm,int_peak_two_norm)/max(int_peak_one_norm,int_peak_two_norm) < self.peak_ratio:
          print "event(): too low"
          evt.put(skip_event_flag(), "skip_event")
          return
        if (np.argmax(spectrum2)+len(spectrum2)) > (weighted_peak_two_center_position+(len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2)) or (np.argmax(spectrum2)+len(spectrum2)) < (weighted_peak_two_center_position-(len(spectrum[self.peak_two_range_min:self.peak_two_range_max])/2)):
          print "event(): out of range high energy peak"
          evt.put(skip_event_flag(), "skip_event")
          return
        if np.argmax(spectrum1) > (weighted_peak_one_center_position+(len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2)) or np.argmax(spectrum1) < (weighted_peak_one_center_position-(len(spectrum[self.peak_one_range_min:self.peak_one_range_max])/2)):
          print "event(): out of range low energy peak"
          evt.put(skip_event_flag(), "skip_event")
          return
        if int_left_region_norm/int_peak_one_norm > self.normalized_peak_to_noise_ratio:
          print "event(): noisy left of low energy peak"
          evt.put(skip_event_flag(), "skip_event")
          return
        if int_middle_region_norm/int_peak_one_norm > self.normalized_peak_to_noise_ratio:
          print "event(): noisy middle"
          evt.put(skip_event_flag(), "skip_event")
          return
        if int_middle_region_norm/int_peak_one_norm > self.normalized_peak_to_noise_ratio:
          print "event(): noisy middle"
          evt.put(skip_event_flag(), "skip_event")
          return
        if int_right_region_norm/int_peak_two_norm > self.normalized_peak_to_noise_ratio:
          print "event(): noisy right of high energy peak"
          evt.put(skip_event_flag(), "skip_event")
          return
      else:
      # filter for cxih8015
      #iron edge at 738 pixels on FFE detetor
        if int_metal_region>=0.10*int_peak_two:
          print "event(): high intensity at metal edge"
          evt.put(skip_event_flag(), "skip_event")
          return
        if int_metal_region>=0.10*int_peak_one:
          print "event(): high intensity at metal edge"
          evt.put(skip_event_flag(), "skip_event")
          return
        if min(int_peak_one,int_peak_two)/max(int_peak_one,int_peak_two) < self.peak_ratio:
          print "event(): peak ratio too low"
          evt.put(skip_event_flag(), "skip_event")
          return
      #self.logger.info("TIMESTAMP %s accepted" %timestamp)
      self.naccepted += 1
      self.ntwo_color += 1
      print "%d Two Color shots"  %self.ntwo_color
Example #23
0
  def event(self, evt, env):
    from dxtbx.format.Registry import Registry
    from os.path import exists
    from time import sleep

    # Nop if there is no image.  For experiments configured to have
    # exactly one event per calibration cycle, this should never
    # happen.
    if self._path is None:
      evt.put(skip_event_flag(), "skip_event")
      return

    # Skip this event if the template isn't in the path
    if self._template is not None and not True in [t in self._path for t in self._template.split(',')]:
      evt.put(skip_event_flag(), "skip_event")
      return

    if "phi" in self._path:
      evt.put(skip_event_flag(), "skip_event")
      return

    # Wait for the image to appear in the file system, probing for it
    # at exponentially increasing delays.
    t = 1
    t_tot = 0

    if not exists(self._path):
      self._logger.info("Waiting for path %s"%self._path)

    while not exists(self._path):
      if t_tot > 1:
        self._logger.info("Timeout waiting for path %s"%self._path)
        evt.put(skip_event_flag(), "skip_event")
        self._logger.info("Image not found:  %s"%self._path)
        return
      sleep(t)
      t_tot += t
      t *= 2

    # Find a matching Format object and instantiate it using the
    # given path.  If the Format object does not understand the image,
    # try determining a new format.  XXX Emits "Couldn't create a
    # detector model for this image".
    if self._fmt is None:
      self._fmt = Registry.find(self._path)
      if self._fmt is None:
        evt.put(skip_event_flag(), "skip_event")
        return

    img = self._fmt(self._path)
    if img is None:
      self._fmt = Registry.find(self._path)
      if self._fmt is None:
        evt.put(skip_event_flag(), "skip_event")
        return
      img = self._fmt(self._path)
      if img is None:
        evt.put(skip_event_flag(), "skip_event")
        return

    self._logger.info(
      "Reading %s using %s" % (self._path, self._fmt.__name__))

    # Get the raw image data and convert to double precision floating
    # point array.  XXX Why will img.get_raw_data() not work, like it
    # does in print_header?
    db = img.get_detectorbase()
    db.readHeader()
    db.read()
    data = db.get_raw_data().as_double()

    # Get the pixel size and store it for common_mode.py
    detector = img.get_detector()[0]
    ps = detector.get_pixel_size()
    assert ps[0] == ps[1]
    pixel_size = ps[0]
    evt.put(ps[0],"marccd_pixel_size")
    evt.put(detector.get_trusted_range()[1],"marccd_saturated_value")
    evt.put(detector.get_distance(),"marccd_distance")

    # If the beam center isn't provided in the config file, get it from the
    # image.  It will probably be wrong.
    if self._beam_x is None or self._beam_y is None:
      self._beam_x, self._beam_y = detector.get_beam_centre_px(img.get_beam().get_s0())
      self._beam_x = int(round(self._beam_x))
      self._beam_y = int(round(self._beam_y))

    # Crop the data so that the beam center is in the center of the image
    maxy, maxx = data.focus()

    minsize = min([self._beam_x,self._beam_y,maxx-self._beam_x,maxy-self._beam_y])

    data = data[self._beam_y-minsize:self._beam_y+minsize,self._beam_x-minsize:self._beam_x+minsize]
    evt.put((minsize,minsize),"marccd_beam_center")

    evt.put(flex.int([0,0,minsize*2,minsize*2]),"marccd_active_areas")

    # Store the image in the event.
    evt.put(data, self._address)
    # Store the .mmcd file name in the event
    evt.put(self._mccd_name, "mccd_name")

    evt_time = cspad_tbx.evt_time(evt) # tuple of seconds, milliseconds
    timestamp = cspad_tbx.evt_timestamp(evt_time) # human readable format
    self._logger.info("converted  %s to pickle with timestamp %s" %(self._path, timestamp))

    # This should not be necessary as the machine is configured with
    # one event per calibration cycle.
    self._path = None
Example #24
0
  def event(self, evt, env):
    """The event() function is called for every L1Accept transition.

    @param evt Event data object, a configure object
    @param env Environment object
    """

    super(average_mixin, self).event(evt, env)
    if evt.get('skip_event'):
      return

    # Get the distance for the detectors that should have it, and set
    # it to NaN for those that should not.
    if self.detector == 'CxiDs1' or \
       self.detector == 'CxiDs2' or \
       self.detector == 'CxiDsd' or \
       self.detector == 'XppGon':
      distance = cspad_tbx.env_distance(self.address, env, self._detz_offset)
      if distance is None:
        self._nfail += 1
        self.logger.warning("event(): no distance, shot skipped")
        evt.put(skip_event_flag(), 'skip_event')
        return
    else:
      distance = float('nan')

    if ("skew" in self.flags):
      # Take out inactive pixels
      if self.roi is not None:
        pixels = self.cspad_img[self.roi[2]:self.roi[3], self.roi[0]:self.roi[1]]
        dark_mask = self.dark_mask[self.roi[2]:self.roi[3], self.roi[0]:self.roi[1]]
        pixels = pixels.as_1d().select(dark_mask.as_1d())
      else:
        pixels = self.cspad_img.as_1d().select(self.dark_mask.as_1d()).as_double()
      stats = scitbx.math.basic_statistics(pixels.as_double())
      #stats.show()
      self.logger.info("skew: %.3f" %stats.skew)
      self.logger.info("kurtosis: %.3f" %stats.kurtosis)
      if 0:
        from matplotlib import pyplot
        hist_min, hist_max = flex.min(flex_cspad_img.as_double()), flex.max(flex_cspad_img.as_double())
        print hist_min, hist_max
        n_slots = 100
        n, bins, patches = pyplot.hist(flex_cspad_img.as_1d().as_numpy_array(), bins=n_slots, range=(hist_min, hist_max))
        pyplot.show()

      # XXX This skew threshold probably needs fine-tuning
      skew_threshold = 0.35
      if stats.skew < skew_threshold:
        self._nfail += 1
        self.logger.warning("event(): skew < %f, shot skipped" % skew_threshold)
        evt.put(skip_event_flag(), 'skip_event')
        return
      #self.cspad_img *= stats.skew

    if ("inactive" in self.flags):
      self.cspad_img.set_selected(self.dark_stddev <= 0, 0)

    if ("noelastic" in self.flags):
      ELASTIC_THRESHOLD = self.elastic_threshold
      self.cspad_img.set_selected(self.cspad_img > ELASTIC_THRESHOLD, 0)

    if self.hot_threshold is not None:
      HOT_THRESHOLD = self.hot_threshold
      self.cspad_img.set_selected(self.dark_img > HOT_THRESHOLD, 0)

    if self.gain_map is not None and self.gain_threshold is not None:
      # XXX comparing each pixel to a moving average would probably be better
      # since the gain should vary approximately smoothly over different areas
      # of the detector
      GAIN_THRESHOLD = self.gain_threshold
      #self.logger.debug(
        #"rejecting: %i" %(self.gain_map > GAIN_THRESHOLD).count(True))
      self.cspad_img.set_selected(self.gain_map > GAIN_THRESHOLD, 0)

    if ("nonoise" in self.flags):
      NOISE_THRESHOLD = self.noise_threshold
      self.cspad_img.set_selected(self.cspad_img < NOISE_THRESHOLD, 0)

    if ("sigma_scaling" in self.flags):
      self.do_sigma_scaling()

    if ("symnoise" in self.flags):
      SYMNOISE_THRESHOLD = self.symnoise_threshold
      self.cspad_img.set_selected((-SYMNOISE_THRESHOLD < self.cspad_img) &
                                  ( self.cspad_img  < SYMNOISE_THRESHOLD), 0)

    if ("output" in self.flags):
      import pickle,os
      if (not os.path.isdir(self.pickle_dirname)):
        os.makedirs(self.pickle_dirname)
      flexdata = flex.int(self.cspad_img.astype(numpy.int32))
      d = cspad_tbx.dpack(
        address=self.address,
        data=flexdata,
        timestamp=cspad_tbx.evt_timestamp(cspad_tbx.evt_time(evt))
      )
      G = open(os.path.join(".",self.pickle_dirname)+"/"+self.pickle_basename,
               "ab")
      pickle.dump(d,G,pickle.HIGHEST_PROTOCOL)
      G.close()

    if self.photon_threshold is not None and self.two_photon_threshold is not None:
      self.do_photon_counting()

    if self.background_path is not None:
      self.cspad_img -= self.background_img


    # t and self._sum_time are a two-long arrays of seconds and
    # milliseconds which hold time with respect to the base time.
    t = [t1 - t2 for (t1, t2) in zip(cspad_tbx.evt_time(evt),
                                     self._metadata['time_base'])]
    if self._nmemb == 0:
      # The peers metadata item is a bit field where a bit is set if
      # the partial sum from the corresponding worker process is
      # pending.  If this is the first frame a worker process sees,
      # set its corresponding bit in the bit field since it will
      # contribute a partial sum.
      if env.subprocess() >= 0:
        self._lock.acquire()
        if 'peers' in self._metadata.keys():
          self._metadata['peers'] |= (1 << env.subprocess())
        else:
          self._metadata['peers'] = (1 << env.subprocess())
        self._lock.release()

      self._sum_distance = distance
      self._sum_time = (t[0], t[1])
      self._sum_wavelength = self.wavelength

      if self._have_max:
        self._max_img = self.cspad_img.deep_copy()
      if self._have_mean:
        self._sum_img = self.cspad_img.deep_copy()
      if self._have_std:
        self._ssq_img = flex.pow2(self.cspad_img)

    else:
      self._sum_distance += distance
      self._sum_time = (self._sum_time[0] + t[0], self._sum_time[1] + t[1])
      self._sum_wavelength += self.wavelength

      if self._have_max:
        sel = (self.cspad_img > self._max_img).as_1d()
        self._max_img.as_1d().set_selected(
          sel, self.cspad_img.as_1d().select(sel))
      if self._have_mean:
        self._sum_img += self.cspad_img
      if self._have_std:
        self._ssq_img += flex.pow2(self.cspad_img)

    self._nmemb += 1
Example #25
0
    def event(self, evt, env):
        """The event() function is called for every L1Accept transition.
    XXX Since the viewer is now running in a parallel process, the
    averaging here is now the bottleneck.

    @param evt Event data object, a configure object
    @param env Environment object
    """
        from pyana.event import Event

        self.n_shots += 1

        super(mod_view, self).event(evt, env)
        if evt.status() != Event.Normal or evt.get(
                'skip_event'):  # XXX transition
            return

        # Get the distance for the detectors that should have it, and set
        # it to NaN for those that should not.
        if self.detector == 'CxiDs1' or \
           self.detector == 'CxiDsd' or \
           self.detector == 'XppGon':
            distance = cspad_tbx.env_distance(self.address, env,
                                              self._detz_offset)
            if distance is None:
                self.nfail += 1
                self.logger.warning("event(): no distance, shot skipped")
                evt.put(skip_event_flag(), "skip_event")
                return
        else:
            distance = float('nan')

        if not self._proc.is_alive():
            evt.setStatus(Event.Stop)

        # Early return if the next update to the viewer is more than
        # self.ncollate shots away.  XXX Since the common_mode.event()
        # function does quite a bit of processing, the savings are
        # probably not so big.
        next_update = (self.nupdate - 1) - (self.nshots - 1) % self.nupdate
        if (self.ncollate > 0 and next_update >= self.ncollate):
            return

        if self.sigma_scaling:
            self.do_sigma_scaling()

        if self.photon_counting:
            self.do_photon_counting()

        # Trim the disabled section from the Sc1 detector image.  XXX This
        # is a bit of a kludge, really.


#    if (self.address == "CxiSc1-0|Cspad2x2-0"):
#      self.cspad_img = self.cspad_img[185:2 * 185, :]

# Update the sum of the valid images, starting a new collation if
# appropriate.  This guarantees self.nvalid > 0.
        if (self.nvalid == 0
                or self.ncollate > 0 and self.nvalid >= self.ncollate):
            self.img_sum = self.cspad_img
            self.nvalid = 1
        else:
            self.img_sum += self.cspad_img
            self.nvalid += 1

        # Update the viewer to display the current average image, and
        # start a new collation, if appropriate.
        if (next_update == 0):
            from time import localtime, strftime

            time_str = strftime("%H:%M:%S", localtime(evt.getTime().seconds()))
            title = "r%04d@%s: average of %d last images on %s" \
                % (evt.run(), time_str, self.nvalid, self.address)

            # See also mod_average.py.
            device = cspad_tbx.address_split(self.address)[2]
            if device == 'Cspad':
                beam_center = self.beam_center
                pixel_size = cspad_tbx.pixel_size
                saturated_value = cspad_tbx.cspad_saturated_value

            elif device == 'marccd':
                beam_center = tuple(t // 2 for t in self.img_sum.focus())
                pixel_size = 0.079346
                saturated_value = 2**16 - 1

            # Wait for the viewer process to empty the queue before feeding
            # it a new image, and ensure not to hang if the viewer process
            # exits.  Because of multithreading/multiprocessing semantics,
            # self._queue.empty() is unreliable.
            fmt = _Format(BEAM_CENTER=beam_center,
                          DATA=self.img_sum / self.nvalid,
                          DETECTOR_ADDRESS=self.address,
                          DISTANCE=distance,
                          PIXEL_SIZE=pixel_size,
                          SATURATED_VALUE=saturated_value,
                          TIME_TUPLE=cspad_tbx.evt_time(evt),
                          WAVELENGTH=self.wavelength)

            while not self._queue.empty():
                if not self._proc.is_alive():
                    evt.setStatus(Event.Stop)
                    return
            while True:
                try:
                    self._queue.put((fmt, title), timeout=1)
                    break
                except Exception:
                    pass

            if (self.ncollate > 0):
                self.nvalid = 0
  def event(self,evt,evn):
    """The event() function puts a "skip_event" object with value @c
    True into the event if the shot is to be skipped.

    @param evt Event data object, a configure object
    @param env Environment object
    """
    #import pdb; pdb.set_trace()
    if (evt.get("skip_event")):
      return
    # check if FEE data is one or two dimensional
    data = evt.get(Camera.FrameV1, self.src)
    if data is None:
      one_D = True
      data = evt.get(Bld.BldDataSpectrometerV1, self.src)
    else:
      one_D = False
    # get event timestamp
    timestamp = cspad_tbx.evt_timestamp(cspad_tbx.evt_time(evt)) # human readable format

    if data is None:
      self.nnodata +=1
      #self.logger.warning("event(): No spectrum data")
      evt.put(skip_event_flag(),"skip_event")


    if timestamp is None:
      evt.put(skip_event_flag(),"skip_event")
      self.logger.warning("event(): No TIMESTAMP, skipping shot")

    elif data is not None:
      self.nshots +=1
      # get data as array and split into two half to find each peak
      if one_D:
        data = np.array(data.hproj().astype(np.float64))
        if 'dark' in locals():
          data = data - self.dark
        spectrum = data
        spectrum1 = data[:data.shape[0]//2]
        spectrum2 = data[data.shape[0]//2:]
      else:
        data = np.array(data.data16().astype(np.float64))
        if 'dark' in locals():
          data = data - self.dark
        data_split1 = data[:,:data.shape[1]//2]
        data_split2 = data[:,data.shape[1]//2:]
        # make a 1D trace of entire spectrum and each half to find peaks
        spectrum  = np.sum(data,0)/data.shape[0]
        spectrum1 = np.sum(data_split1,0)/data_split1.shape[0]
        spectrum2 = np.sum(data_split2,0)/data_split2.shape[0]

      peak_one = np.max(spectrum1)
      peak_two = np.max(spectrum2)
      peak_one_position = np.argmax(spectrum1)
      peak_two_position = np.argmax(spectrum2) + len(spectrum2)
    # define the limits of the regions between the two peaks
      peak_one_lower_limit = self.peak_one_position_min - self.peak_one_width
      peak_one_upper_limit = self.peak_one_position_max + self.peak_one_width
      peak_two_lower_limit = self.peak_two_position_min - self.peak_two_width
      peak_two_upper_limit = self.peak_two_position_max + self.peak_two_width

      # the x-coordinate of the weighted center of peak region
      weighted_peak_one_positions = []
      for i in xrange(peak_one_lower_limit,peak_one_upper_limit):
        weighted_peak_one_positions.append(spectrum[i]*i)

      weighted_sum_peak_one = sum(weighted_peak_one_positions)
      weighted_peak_one_center_position = weighted_sum_peak_one//sum(spectrum[peak_one_lower_limit:peak_one_upper_limit])

      weighted_peak_two_positions = []
      for i in xrange(peak_two_lower_limit,peak_two_upper_limit):
        weighted_peak_two_positions.append(spectrum[i]*i)

      weighted_sum_peak_two = sum(weighted_peak_two_positions)
      weighted_peak_two_center_position = weighted_sum_peak_two//sum(spectrum[peak_two_lower_limit:peak_two_upper_limit])
    # normalized integrated peaks
      int_peak_one = np.sum(spectrum[peak_one_lower_limit:self.peak_one_position_max])/len(spectrum[peak_one_lower_limit:self.peak_one_position_max])
      int_peak_two = np.sum(spectrum[peak_two_lower_limit:self.peak_two_position_max])/len(spectrum[peak_two_lower_limit:self.peak_two_position_max])
    # normalized integrated regions between the peaks
      int_left_region = np.sum(spectrum[0:peak_one_lower_limit])/len(spectrum[0:peak_one_lower_limit])
      int_middle_region = np.sum(spectrum[peak_one_upper_limit:peak_two_lower_limit])/len(spectrum[peak_one_upper_limit:peak_two_lower_limit])
      int_right_region = np.sum(spectrum[peak_two_upper_limit:])/len(spectrum[:peak_two_upper_limit])
      # now to do the filtering
      if peak_one/peak_two < self.peak_ratio or peak_one/peak_two > 1/self.peak_ratio:
        print "event(): too low"
        evt.put(skip_event_flag(), "skip_event")
        return
      if weighted_peak_two_center_position < self.peak_two_position_min or weighted_peak_two_center_position > self.peak_two_position_max:
        print "event(): out of range high energy peak"
        evt.put(skip_event_flag(), "skip_event")
        return
      if weighted_peak_one_center_position < self.peak_one_position_min or weighted_peak_one_center_position > self.peak_one_position_max:
        print "event(): out of range low energy peak"
        evt.put(skip_event_flag(), "skip_event")
        return
      if not one_D and (int_left_region/int_peak_one > self.normalized_peak_to_noise_ratio):
        print "event(): noisy left of low energy peak"
        evt.put(skip_event_flag(), "skip_event")
        return
      if not one_D and (int_middle_region/int_peak_one > self.normalized_peak_to_noise_ratio):
        print "event(): noisy middle"
        evt.put(skip_event_flag(), "skip_event")
        return
      if not one_D and (int_middle_region/int_peak_two > self.normalized_peak_to_noise_ratio):
        print "event(): noisy middle"
        evt.put(skip_event_flag(), "skip_event")
        return
      if not one_D and (int_right_region/int_peak_two > self.normalized_peak_to_noise_ratio):
        print "event(): noisy right of high energy peak"
        evt.put(skip_event_flag(), "skip_event")
        return
      #iron edge at 738 pixels on FFE detetor
      if one_D and (spectrum[self.iron_edge_position]>=spectrum[weighted_peak_one_center_position]):
        print "event(): peak at iron edge"
        evt.put(skip_event_flag(), "skip_event")
        return

      if one_D and (spectrum[self.iron_edge_position]>=spectrum[weighted_peak_two_center_position]):
        print "event(): peak at iron edge"
        evt.put(skip_event_flag(), "skip_event")
        return

      #self.logger.info("TIMESTAMP %s accepted" %timestamp)
      self.naccepted += 1
      self.ntwo_color += 1
      print "%d Two Color shots"  %self.ntwo_color
Example #27
0
class common_mode_correction(mod_event_info):
  """Dark subtraction and alternate implementation of common mode
  substituting for cspad_tbx.

  Known problems: the algorithm relies on a substantial part of the
  sensor having no signal, which is not the case if a water ring
  crosses the sensor.
  """


  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 beginjob(self, evt, env):
    """The beginjob() function does one-time initialisation from
    event- or environment data.  It is called at an XTC configure
    transition.

    @param evt Event data object, a configure object
    @param env Environment object
    """

    super(common_mode_correction, self).beginjob(evt, env)
    # Load the dark image and ensure it is signed and at least 32 bits
    # wide, since it will be used for differencing.  If a dark image
    # is provided, a standard deviation image is required, and all the
    # ADU scales must match up.
    #
    # XXX Can we zap all the ADU_SCALE stuff?
    #
    # XXX Do we really need to store the substituted values in the
    # instance here?  At least self._dark_path is referenced later on.
    #
    # Note that this will load the dark, standard deviation and gain
    # once (SEVERAL TIMES) for each process, but the gain is that we
    # can do substitutions.  But it is only done at the beginning of
    # the job.
    self.dark_img = None
    if self._dark_path is not None:
      self._dark_path = cspad_tbx.getOptEvalOrString(
        cspad_tbx.pathsubst(self._dark_path, evt, env))

      assert self._dark_stddev_path is not None
      dark_dict = easy_pickle.load(self._dark_path)
      #assert "ADU_SCALE" not in dark_dict # force use of recalculated dark
      self.dark_img = dark_dict['DATA']
      assert isinstance(self.dark_img, flex.double)

      self._dark_stddev_path = cspad_tbx.getOptEvalOrString(
        cspad_tbx.pathsubst(self._dark_stddev_path, evt, env))

      self.dark_stddev = easy_pickle.load(self._dark_stddev_path)['DATA']
      assert isinstance(self.dark_stddev, flex.double)
      self.dark_mask = (self.dark_stddev > 0)

    # Load the mask image and ensure it is signed and at least 32 bits
    # wide, since it will be used for differencing.
    self.gain_map = None
    if self._gain_map_path is not None:
      self._gain_map_path = cspad_tbx.getOptEvalOrString(
        cspad_tbx.pathsubst(self._gain_map_path, evt, env))
      self.gain_map = easy_pickle.load(self._gain_map_path)['DATA']
      if self.gain_map_level is not None:
        sel = flex.bool([bool(f) for f in self.gain_map])
        sel.reshape(flex.grid(self.gain_map.focus()))
        self.gain_map = self.gain_map.set_selected(~sel, self.gain_map_level)
        self.gain_map = self.gain_map.set_selected(sel, 1)
      assert isinstance(self.gain_map, flex.double)

    self.mask_img = None
    if self._mask_path is not None:
      self._mask_path = cspad_tbx.getOptEvalOrString(
        cspad_tbx.pathsubst(self._mask_path, evt, env))

      self.mask_img = easy_pickle.load(self._mask_path)['DATA']
      assert isinstance(self.mask_img, flex.double) \
        or   isinstance(self.mask_img, flex.int)

    if self.address == 'XppGon-0|marccd-0':
      #mod_mar.py will set these during its event function
      self.active_areas = None
      self.beam_center = None
    elif self.address == 'XppEndstation-0|Rayonix-0' or \
         self.address == 'MfxEndstation-0|Rayonix-0':
      assert self.override_beam_x is not None
      assert self.override_beam_y is not None
      from xfel.cxi.cspad_ana import rayonix_tbx
      maxx, maxy = rayonix_tbx.get_rayonix_detector_dimensions(self.bin_size)
      if self.crop_rayonix:
        bx = int(round(self.override_beam_x))
        by = int(round(self.override_beam_y))
        minsize = min([bx,by,maxx-bx,maxy-by])
        self.beam_center = minsize,minsize
        self.active_areas = flex.int([0,0,2*minsize,2*minsize])
        self.rayonix_crop_slice = slice(by-minsize,by+minsize), slice(bx-minsize,bx+minsize)
      else:
        self.beam_center = self.override_beam_x,self.override_beam_y
        self.active_areas = flex.int([0,0,maxx,maxy])
    elif self.address == 'XppGon-0|Cspad-0':
      evt_time = cspad_tbx.evt_time(evt) # tuple of seconds, milliseconds
      timestamp = cspad_tbx.evt_timestamp(evt_time) # human readable format
      from iotbx.detectors.cspad_detector_formats import detector_format_version, reverse_timestamp
      from xfel.cxi.cspad_ana.cspad_tbx import xpp_active_areas
      version_lookup = detector_format_version(self.address, reverse_timestamp(timestamp)[0])
      assert version_lookup is not None
      self.active_areas = xpp_active_areas[version_lookup]['active_areas']
      self.beam_center = [1765 // 2, 1765 // 2]
    else:
      (self.beam_center, self.active_areas) = cspad_tbx.cbcaa(
        cspad_tbx.getConfig(self.address, env), self.sections)

  def common_mode(self, img, stddev, mask):
    """The common_mode() function returns the mode of image stored in
    the array pointed to by @p img.  @p mask must be such that the @p
    stddev at the selected pixels is greater than zero.

    @param img    2D integer array of the image
    @param stddev 2D integer array of the standard deviation of each
                  pixel in @p img
    @param mask   2D Boolean array, @c True if the pixel is to be
                  included, @c False otherwise
    @return       Mode of the image, as a real number
    """

    # Flatten the image and take out inactive pixels XXX because we
    # cannot take means and medians of 2D arrays?
    img_1d = img.as_1d().select(mask.as_1d()).as_double()
    assert img_1d.size() > 0

    if (self.common_mode_correction == "mean"):
      # The common mode is approximated by the mean of the pixels with
      # signal-to-noise ratio less than a given threshold.  XXX Breaks
      # if the selection is empty!
      THRESHOLD_SNR = 2
      img_snr = img_1d / stddev.as_double().as_1d().select(mask.as_1d())
      return (flex.mean(img_1d.select(img_snr < THRESHOLD_SNR)))

    elif (self.common_mode_correction == "median"):
      return (flex.median(img_1d))

    # Identify the common-mode correction as the peak histogram of the
    # histogram of pixel values (the "standard" common-mode correction, as
    # previously implemented in this class).
    hist_min = -40
    hist_max = 40
    n_slots = 100

    hist = flex.histogram(img_1d, hist_min, hist_max, n_slots=n_slots)
    slots = hist.slots()
    i = flex.max_index(slots)
    common_mode = list(hist.slot_infos())[i].center()

    if (self.common_mode_correction == "mode"):
      return (common_mode)

    # Determine the common-mode correction from the peak of a single
    # Gaussian function fitted to the histogram.
    from scitbx.math.curve_fitting import single_gaussian_fit
    x = hist.slot_centers()
    y = slots.as_double()
    fit = single_gaussian_fit(x, y)
    scale, mu, sigma = fit.a, fit.b, fit.c
    self.logger.debug("fitted gaussian: mu=%.3f, sigma=%.3f" %(mu, sigma))
    mode = common_mode
    common_mode = mu
    if abs(mode-common_mode) > 1000: common_mode = mode # XXX
    self.logger.debug("delta common mode corrections: %.3f" %(mode-common_mode))

    if 0 and abs(mode-common_mode) > 0:
      #if 0 and skew > 0.5:
      # view histogram and fitted gaussian
      from numpy import exp
      from matplotlib import pyplot
      x_all = x
      n, bins, patches = pyplot.hist(section_img.as_1d().as_numpy_array(), bins=n_slots, range=(hist_min, hist_max))
      y_all = scale * flex.exp(-flex.pow2(x_all-mu) / (2 * sigma**2))
      scale = slots[flex.max_index(slots)]
      y_all *= scale/flex.max(y_all)
      pyplot.plot(x_all, y_all)
      pyplot.show()

    return (common_mode)


  def event(self, evt, env):
    """The event() function is called for every L1Accept transition.

    @param evt Event data object, a configure object
    @param env Environment object
    """
    super(common_mode_correction, self).event(evt, env)
    if (evt.get("skip_event")):
      return

    if not hasattr(self, 'active_areas') or self.active_areas is None or \
       not hasattr(self, 'beam_center')  or self.beam_center  is None:
      if self.address == 'XppGon-0|marccd-0':
        # The mod_mar module needs to have been called before this one
        # to set this up.  The MAR does not have a configure object.
        self.beam_center = evt.get("marccd_beam_center")
        self.active_areas = evt.get("marccd_active_areas")
      elif self.address == 'XppEndstation-0|Rayonix-0' or \
           self.address == 'MfxEndstation-0|Rayonix-0':
        pass # bc and aa set in the beginjob function
      elif self.address == 'XppGon-0|Cspad-0':
        # Load the active areas as determined from the optical metrology
        from iotbx.detectors.cspad_detector_formats import detector_format_version, reverse_timestamp
        from xfel.cxi.cspad_ana.cspad_tbx import xpp_active_areas
        version_lookup = detector_format_version(self.address, reverse_timestamp(self.timestamp)[0])
        assert version_lookup is not None
        self.active_areas = xpp_active_areas[version_lookup]['active_areas']
        self.beam_center = [1765 // 2, 1765 // 2]
      else:
        (self.beam_center, self.active_areas) = \
          cspad_tbx.cbcaa(cspad_tbx.getConfig(self.address, env), self.sections)

    if self.filter_laser_1_status is not None:
      if (self.laser_1_status.status != self.filter_laser_1_status or
          (self.laser_1_ms_since_change is not None and
           self.laser_1_ms_since_change < self.filter_laser_wait_time)):
        evt.put(skip_event_flag(), "skip_event")
        return
    if self.filter_laser_4_status is not None:
      if (self.laser_4_status.status != self.filter_laser_4_status or
          (self.laser_4_ms_since_change is not None and
           self.laser_4_ms_since_change < self.filter_laser_wait_time)):
        evt.put(skip_event_flag(), "skip_event")
        return

    # Early return if the full detector image is already stored in the
    # event.  Otherwise, get it from the stream as a double-precision
    # floating-point flex array.  XXX It is probably not safe to key
    # the image on self.address, so we should come up with our own
    # namespace.  XXX Misnomer--could be CAMP, too

    self.cspad_img = evt.get(self.address)
    if self.cspad_img is not None:
      return
    if self.address == 'XppGon-0|Cspad-0':
      # Kludge until cspad_tbx.image() can be rewritten to handle the
      # XPP metrology.
      self.cspad_img = cspad_tbx.image_xpp(
        self.address, evt, env, self.active_areas)
    elif self.address == 'XppEndstation-0|Rayonix-0' or \
         self.address == 'MfxEndstation-0|Rayonix-0':
      from psana import Source, Camera
      import numpy as np
      address = cspad_tbx.old_address_to_new_address(self.address)
      src=Source('DetInfo(%s)'%address)
      self.cspad_img = evt.get(Camera.FrameV1,src)
      if self.cspad_img is not None:
        self.cspad_img = self.cspad_img.data16().astype(np.float64)
    elif self.address=='CxiDg3-0|Opal1000-0':
      if evt.getFrameValue(self.address) is not None:
        self.cspad_img = evt.getFrameValue(self.address).data()
    elif self.address=='CxiEndstation-0|Opal1000-2':
      if evt.getFrameValue(self.address) is not None:
        self.cspad_img = evt.getFrameValue(self.address).data()
    elif self.address=='FeeHxSpectrometer-0|Opal1000-1':
      if evt.getFrameValue(self.address) is not None:
        self.cspad_img = evt.getFrameValue(self.address).data()
    elif self.address=='NoDetector-0|Cspad2x2-0':
        import numpy as np
        from pypdsdata import xtc
        test=[]
        self.cspad_img = evt.get(xtc.TypeId.Type.Id_Cspad2x2Element,self.address).data()
        self.cspad_img=np.reshape(self.cspad_img,(370, 388))
    else:
      try:
        self.cspad_img = cspad_tbx.image(
          self.address, cspad_tbx.getConfig(self.address, env),
          evt, env, self.sections)
      except Exception, e:
        self.logger.error("Error reading image data: " + str(e))
        evt.put(skip_event_flag(), "skip_event")
        return

    if self.cspad_img is None:
      if cspad_tbx.address_split(self.address)[2] != 'Andor':
        self.nfail += 1
        self.logger.warning("event(): no image, shot skipped")
        evt.put(skip_event_flag(), "skip_event")
      return
    self.cspad_img = flex.double(self.cspad_img.astype(numpy.float64))
    # If a dark image was provided, subtract it from the image.  There
    # is no point in doing common-mode correction unless the dark
    # image was subtracted.
    if (self.dark_img is not None):
      self.cspad_img -= self.dark_img

      if (self.common_mode_correction != "none"):
        # Mask out inactive pixels prior to common mode correction.
        # Pixels are marked as inactive either due to low ADU values
        # or non-positive standard deviations in dark image.  XXX Make
        # the threshold tunable?
        cspad_mask = self.dark_mask.deep_copy()

        if self.roi is not None and self.common_mode_correction == "chebyshev":
          roi_mask = cspad_mask[self.roi[2]:self.roi[3], :]
          roi_mask = flex.bool(roi_mask.accessor(), False)
          cspad_mask.matrix_paste_block_in_place(
            block=roi_mask,
            i_row=self.roi[2],
            i_column=0)

        # Extract each active section from the assembled detector
        # image and apply the common mode correction.  XXX Make up a
        # quadrant mask for the emission detector.  Needs to be
        # checked!
        config = cspad_tbx.getConfig(self.address, env)
        if len(self.sections) == 1:
          q_mask = 1
        else:
          q_mask = config.quadMask()
        for q in xrange(len(self.sections)):
          if (not((1 << q) & q_mask)):
            continue

          # XXX Make up section mask for the emission detector.  Needs
          # to be checked!
          import _pdsdata
          if len(self.sections) == 1 and type(config) in (
            _pdsdata.cspad2x2.ConfigV1, _pdsdata.cspad2x2.ConfigV2):
            s_mask = config.roiMask()
          else:
            s_mask = config.roiMask(q)
          for s in xrange(len(self.sections[q])):
            # XXX DAQ misconfiguration?  This mask appears not to work
            # reliably for the Sc1 detector.
#            if (not((1 << s) & s_mask)):
#              continue
            corners   = self.sections[q][s].corners()
            i_row     = int(round(min(c[0] for c in corners)))
            i_column  = int(round(min(c[1] for c in corners)))
            n_rows    = int(round(max(c[0] for c in corners))) - i_row
            n_columns = int(round(max(c[1] for c in corners))) - i_column

            section_img    = self.cspad_img.matrix_copy_block(
              i_row  = i_row,  i_column  = i_column,
              n_rows = n_rows, n_columns = n_columns)
            section_mask   = cspad_mask.matrix_copy_block(
              i_row  = i_row,  i_column  = i_column,
              n_rows = n_rows, n_columns = n_columns)
            section_stddev = self.dark_stddev.matrix_copy_block(
              i_row  = i_row,  i_column  = i_column,
              n_rows = n_rows, n_columns = n_columns)

            if section_mask.count(True) == 0: continue

            if self.common_mode_correction == "chebyshev":
              assert len(self.sections[q]) == 2
              if s == 0:
                section_imgs = [section_img]
                section_masks = [section_mask]
                i_rows = [i_row]
                i_columns = [i_column]
                continue
              else:
                section_imgs.append(section_img)
                section_masks.append(section_mask)
                i_rows.append(i_row)
                i_columns.append(i_column)

                chebyshev_corrected_imgs = self.chebyshev_common_mode(
                  section_imgs, section_masks)
                for i in range(2):
                  section_imgs[i].as_1d().copy_selected(
                    section_masks[i].as_1d().iselection(),
                    chebyshev_corrected_imgs[i].as_1d())
                  self.cspad_img.matrix_paste_block_in_place(
                    block=section_imgs[i],
                    i_row=i_rows[i],
                    i_column=i_columns[i])

            else:
              common_mode = self.common_mode(
                section_img, section_stddev, section_mask)
              self.sum_common_mode += common_mode
              self.sumsq_common_mode += common_mode**2

              # Apply the common mode correction to the
              # section, and paste it back into the image.
              self.cspad_img.matrix_paste_block_in_place(
                block    = section_img - common_mode,
                i_row    = i_row,
                i_column = i_column)

    if self.gain_map is not None:
      self.cspad_img *= self.gain_map

    if (self.mask_img is not None):
      sel = (self.mask_img == -2 )|(self.mask_img == cspad_tbx.cspad_mask_value)
      self.cspad_img.set_selected(sel, cspad_tbx.cspad_mask_value)

    if (self.address == 'XppEndstation-0|Rayonix-0' or \
        self.address == 'MfxEndstation-0|Rayonix-0') and \
        self.crop_rayonix:
      # Crop the masked data so that the beam center is in the center of the image
      self.cspad_img = self.cspad_img[self.rayonix_crop_slice[0], self.rayonix_crop_slice[1]]

    if self.cache_image:
      # Store the image in the event.
      evt.put(self.cspad_img, self.address)
Example #28
0
    def event(self, evt, env):
        """The event() function is called for every L1Accept transition.

    @param evt Event data object, a configure object
    @param env Environment object
    """

        # Increase the event counter, even if this event is to be skipped.
        self.nshots += 1
        if (evt.get("skip_event")):
            return

        sifoil = cspad_tbx.env_sifoil(env)
        if self.check_beam_status and sifoil is None:
            self.nfail += 1
            self.logger.warning("event(): no Si-foil thickness, shot skipped")
            evt.put(skip_event_flag(), "skip_event")
            return
        if (self.sifoil is not None and self.sifoil != sifoil):
            self.logger.warning(
                "event(): Si-foil changed mid-run: % 8i -> % 8d" %
                (self.sifoil, sifoil))
        self.sifoil = sifoil
        if self.verbose: self.logger.info("Si-foil thickness: %i" % sifoil)

        self.evt_time = cspad_tbx.evt_time(
            evt)  # tuple of seconds, milliseconds
        self.timestamp = cspad_tbx.evt_timestamp(
            self.evt_time)  # human readable format
        if (self.timestamp is None):
            self.nfail += 1
            self.logger.warning("event(): no timestamp, shot skipped")
            evt.put(skip_event_flag(), "skip_event")
            return
        if self.verbose: self.logger.info(self.timestamp)

        if self.override_energy is None:
            self.wavelength = cspad_tbx.evt_wavelength(evt, self.delta_k)
            if self.wavelength is None:
                if self.check_beam_status:
                    self.nfail += 1
                    self.logger.warning("event(): no wavelength, shot skipped")
                    evt.put(skip_event_flag(), "skip_event")
                    return
                else:
                    self.wavelength = 0
        else:
            self.wavelength = 12398.4187 / self.override_energy
        if self.verbose: self.logger.info("Wavelength: %.4f" % self.wavelength)

        self.pulse_length = cspad_tbx.evt_pulse_length(evt)
        if self.pulse_length is None:
            if self.check_beam_status:
                self.nfail += 1
                self.logger.warning("event(): no pulse length, shot skipped")
                evt.put(skip_event_flag(), "skip_event")
                return
            else:
                self.pulse_length = 0
        if self.verbose:
            self.logger.info("Pulse length: %s" % self.pulse_length)

        self.beam_charge = cspad_tbx.evt_beam_charge(evt)
        if self.beam_charge is None:
            if self.check_beam_status:
                self.nfail += 1
                self.logger.warning("event(): no beam charge, shot skipped")
                evt.put(skip_event_flag(), "skip_event")
                return
            else:
                self.beam_charge = 0
        if self.verbose: self.logger.info("Beam charge: %s" % self.beam_charge)

        self.injector_xyz = cspad_tbx.env_injector_xyz(env)
        #if self.injector_xyz is not None:
        #self.logger.info("injector_z: %i" %self.injector_xyz[2].value)

        self.laser_1_status.set_status(
            cspad_tbx.env_laser_status(env, laser_id=1), self.evt_time)
        self.laser_4_status.set_status(
            cspad_tbx.env_laser_status(env, laser_id=4), self.evt_time)
        self.laser_1_ms_since_change = self.laser_1_status.ms_since_last_status_change(
            self.evt_time)
        self.laser_4_ms_since_change = self.laser_4_status.ms_since_last_status_change(
            self.evt_time)
        if self.verbose:
            if self.laser_1_ms_since_change is not None:
                self.logger.info("ms since laser 1 status change: %i" %
                                 self.laser_1_ms_since_change)
            if self.laser_4_ms_since_change is not None:
                self.logger.info("ms since laser 4 status change: %i" %
                                 self.laser_4_ms_since_change)
            if self.laser_1_status is not None and self.laser_1_status.status is not None:
                self.logger.info("Laser 1 status: %i" %
                                 int(self.laser_1_status.status))
            if self.laser_4_status is not None and self.laser_4_status.status is not None:
                self.logger.info("Laser 4 status: %i" %
                                 int(self.laser_4_status.status))
Example #29
0
  def event(self, evt, env):
    """The event() function is called for every L1Accept transition.

    @param evt Event data object, a configure object
    @param env Environment object
    """

    # Increase the event counter, even if this event is to be skipped.
    self.nshots += 1
    if (evt.get("skip_event")):
      return

    sifoil = cspad_tbx.env_sifoil(env)
    if self.check_beam_status and sifoil is None:
      self.nfail += 1
      self.logger.warning("event(): no Si-foil thickness, shot skipped")
      evt.put(skip_event_flag(), "skip_event")
      return
    if (self.sifoil is not None and self.sifoil != sifoil):
      self.logger.warning("event(): Si-foil changed mid-run: % 8i -> % 8d" %
        (self.sifoil, sifoil))
    self.sifoil = sifoil
    if self.verbose: self.logger.info("Si-foil thickness: %i" %sifoil)

    self.evt_time = cspad_tbx.evt_time(evt) # tuple of seconds, milliseconds
    self.timestamp = cspad_tbx.evt_timestamp(self.evt_time) # human readable format
    if (self.timestamp is None):
      self.nfail += 1
      self.logger.warning("event(): no timestamp, shot skipped")
      evt.put(skip_event_flag(), "skip_event")
      return
    if self.verbose: self.logger.info(self.timestamp)

    if self.override_energy is None:
      self.wavelength = cspad_tbx.evt_wavelength(evt, self.delta_k)
      if self.wavelength is None:
        if self.check_beam_status:
          self.nfail += 1
          self.logger.warning("event(): no wavelength, shot skipped")
          evt.put(skip_event_flag(), "skip_event")
          return
        else:
          self.wavelength = 0
    else:
      self.wavelength = 12398.4187/self.override_energy
    if self.verbose: self.logger.info("Wavelength: %.4f" %self.wavelength)

    self.pulse_length = cspad_tbx.evt_pulse_length(evt)
    if self.pulse_length is None:
      if self.check_beam_status:
        self.nfail += 1
        self.logger.warning("event(): no pulse length, shot skipped")
        evt.put(skip_event_flag(), "skip_event")
        return
      else:
        self.pulse_length = 0
    if self.verbose: self.logger.info("Pulse length: %s" %self.pulse_length)

    self.beam_charge = cspad_tbx.evt_beam_charge(evt)
    if self.beam_charge is None:
      if self.check_beam_status:
        self.nfail += 1
        self.logger.warning("event(): no beam charge, shot skipped")
        evt.put(skip_event_flag(), "skip_event")
        return
      else:
        self.beam_charge = 0
    if self.verbose: self.logger.info("Beam charge: %s" %self.beam_charge)

    self.injector_xyz = cspad_tbx.env_injector_xyz(env)
    #if self.injector_xyz is not None:
      #self.logger.info("injector_z: %i" %self.injector_xyz[2].value)

    self.laser_1_status.set_status(cspad_tbx.env_laser_status(env, laser_id=1), self.evt_time)
    self.laser_4_status.set_status(cspad_tbx.env_laser_status(env, laser_id=4), self.evt_time)
    self.laser_1_ms_since_change = self.laser_1_status.ms_since_last_status_change(self.evt_time)
    self.laser_4_ms_since_change = self.laser_4_status.ms_since_last_status_change(self.evt_time)
    if self.verbose:
      if self.laser_1_ms_since_change is not None:
        self.logger.info("ms since laser 1 status change: %i" %self.laser_1_ms_since_change)
      if self.laser_4_ms_since_change is not None:
        self.logger.info("ms since laser 4 status change: %i" %self.laser_4_ms_since_change)
      if self.laser_1_status is not None and self.laser_1_status.status is not None:
        self.logger.info("Laser 1 status: %i" %int(self.laser_1_status.status))
      if self.laser_4_status is not None and self.laser_4_status.status is not None:
        self.logger.info("Laser 4 status: %i" %int(self.laser_4_status.status))
Example #30
0
  def event(self, evt, env):
    """The event() function is called for every L1Accept transition.

    @param evt Event data object, a configure object
    @param env Environment object
    """

    super(mod_image_dict, self).event(evt, env)
    if (evt.get("skip_event")):
      return

    if self.cspad_img is None:
      return

    # This module only applies to detectors for which a distance is
    # available.
    distance = cspad_tbx.env_distance(self.address, env, self._detz_offset)
    if distance is None:
      self.nfail += 1
      self.logger.warning("event(): no distance, shot skipped")
      evt.put(skip_event_flag(), "skip_event")
      return

    device = cspad_tbx.address_split(self.address)[2]

    self.logger.info("Subprocess %02d: process image #%05d @ %s" %
                     (env.subprocess(), self.nshots, self.timestamp))

    # See r17537 of mod_average.py.
    if device == 'Cspad':
      pixel_size = cspad_tbx.pixel_size
      saturated_value = cspad_tbx.cspad_saturated_value
    elif device == 'Rayonix':
      pixel_size = rayonix_tbx.get_rayonix_pixel_size(self.bin_size)
      saturated_value = rayonix_tbx.rayonix_saturated_value
    elif device == 'marccd':
      pixel_size = evt.get("marccd_pixel_size")
      saturated_value = evt.get("marccd_saturated_value")
      if distance == 0:
        distance = evt.get("marccd_distance")

    d = cspad_tbx.dpack(
      active_areas=self.active_areas,
      address=self.address,
      beam_center_x=pixel_size * self.beam_center[0],
      beam_center_y=pixel_size * self.beam_center[1],
      data=self.cspad_img.iround(), # XXX ouch!
      distance=distance,
      pixel_size=pixel_size,
      saturated_value=saturated_value,
      timestamp=self.timestamp,
      wavelength=self.wavelength)

    evt.put(d, self.m_out_key)

    # Diagnostic message emitted only when all the processing is done.
    if (env.subprocess() >= 0):
      self.logger.info("Subprocess %02d: accepted #%05d @ %s" %
                       (env.subprocess(), self.nshots, self.timestamp))
    else:
      self.logger.info("Accepted #%05d @ %s" %
                       (self.nshots, self.timestamp))