Beispiel #1
0
    def OnRestoreMetrology(self, event):
        print("Not implemented")
        return

        dialog = wx.FileDialog(
            self,
            defaultDir="",
            message="Restore metrology file",
            style=wx.FD_OPEN,
            wildcard="Phil files (*.eff; *.def)|*.eff;*.def")
        if dialog.ShowModal() == wx.ID_OK:
            path = dialog.GetPath()
            if (path != ""):
                from xfel.cftbx.detector.metrology import \
                  master_phil, metrology_as_transformation_matrices
                from libtbx import phil

                frame = self.GetParent().GetParent()
                stream = open(path)
                metrology_phil = master_phil.fetch(
                    sources=[phil.parse(stream.read())])
                stream.close()

                # Merge restored metrology into the raw image
                from libtbx.phil import experimental
                experimental.merge_params_by_key(
                    frame.pyslip.tiles.raw_image._metrology_params,
                    metrology_phil.extract(), 'serial')

                img = frame.pyslip.tiles.raw_image
                img.apply_metrology_from_matrices(
                    metrology_as_transformation_matrices(
                        metrology_phil.extract()))

                # Update the view, trigger redraw.  XXX Duplication
                # w.r.t. OnUpdateQuad().
                tiles = frame.pyslip.tiles
                tiles.flex_image = frame.pyslip.tiles.raw_image.get_flex_image(
                    brightness=tiles.current_brightness / 100)
                tiles.flex_image.adjust(
                    color_scheme=tiles.current_color_scheme)

                tiles.reset_the_cache()
                tiles.tile_cache = tiles.cache[tiles.zoom_level]
                tiles.tile_list = tiles.lru[tiles.zoom_level]
                frame.pyslip.Update()

                # Update the controls, remember to reset the default values
                # for the spinners.
                for serial in range(4):
                    fast, slow = img.get_panel_fast_slow(serial)
                    name_quadrant = ["Q0", "Q1", "Q2", "Q3"][serial]

                    spinner = getattr(self, "_" + name_quadrant + "_fast_ctrl")
                    spinner.SetDefaultValue(fast)
                    spinner.SetValue(fast)

                    spinner = getattr(self, "_" + name_quadrant + "_slow_ctrl")
                    spinner.SetDefaultValue(slow)
                    spinner.SetValue(slow)
  def OnRestoreMetrology(self, event):
    print "Not implemented"
    return

    dialog = wx.FileDialog(
      self,
      defaultDir="",
      message="Restore metrology file",
      style=wx.FD_OPEN,
      wildcard="Phil files (*.eff; *.def)|*.eff;*.def")
    if dialog.ShowModal() == wx.ID_OK:
      path = dialog.GetPath()
      if (path != "") :
        from xfel.cftbx.detector.metrology import \
          master_phil, metrology_as_transformation_matrices
        from libtbx import phil

        frame = self.GetParent().GetParent()
        stream = open(path)
        metrology_phil = master_phil.fetch(sources=[phil.parse(stream.read())])
        stream.close()

        # Merge restored metrology into the raw image
        from libtbx.phil import experimental
        experimental.merge_params_by_key(
          frame.pyslip.tiles.raw_image._metrology_params,
          metrology_phil.extract(),
          'serial')

        img = frame.pyslip.tiles.raw_image
        img.apply_metrology_from_matrices(metrology_as_transformation_matrices(
          metrology_phil.extract()))

        # Update the view, trigger redraw.  XXX Duplication
        # w.r.t. OnUpdateQuad().
        tiles = frame.pyslip.tiles
        tiles.flex_image = frame.pyslip.tiles.raw_image.get_flex_image(
          brightness=tiles.current_brightness / 100)
        tiles.flex_image.adjust(color_scheme=tiles.current_color_scheme)

        tiles.reset_the_cache()
        tiles.tile_cache = tiles.cache[tiles.zoom_level]
        tiles.tile_list = tiles.lru[tiles.zoom_level]
        frame.pyslip.Update()

        # Update the controls, remember to reset the default values
        # for the spinners.
        for serial in xrange(4):
          fast, slow = img.get_panel_fast_slow(serial)
          name_quadrant = ["Q0", "Q1", "Q2", "Q3"][serial]

          spinner = getattr(self, "_" + name_quadrant + "_fast_ctrl")
          spinner.SetDefaultValue(fast)
          spinner.SetValue(fast)

          spinner = getattr(self, "_" + name_quadrant + "_slow_ctrl")
          spinner.SetDefaultValue(slow)
          spinner.SetValue(slow)
    def transformation_matrices_as_metrology(self):
        """The transformation_matrices_as_metrology() function regularizes
    the the transformation matrices and converts them to a phil
    object.
    """

        from libtbx import phil
        from xfel.cftbx.detector.metrology import \
          master_phil, regularize_transformation_matrices

        # XXX Experimental!
        regularize_transformation_matrices(self._matrices)

        (Tf_d, Tb_d) = self._matrices[(0, )]
        metrology_str = "detector {\n"
        metrology_str += "serial = %d\n" % 0
        metrology_str += self._matrix_as_string(Tb_d)

        for p in [
                k[1] for k in self._matrices.keys()
                if (len(k) == 2 and k[0:1] == (0, ))
        ]:
            (Tf_p, Tb_p) = self._matrices[(0, p)]
            metrology_str += "panel {\n"
            metrology_str += "serial = %d\n" % p
            metrology_str += self._matrix_as_string(Tf_d * Tb_p)

            for s in [
                    k[2] for k in self._matrices.keys()
                    if (len(k) == 3 and k[0:2] == (0, p))
            ]:
                (Tf_s, Tb_s) = self._matrices[(0, p, s)]
                metrology_str += "sensor {\n"
                metrology_str += "serial = %d\n" % s
                metrology_str += self._matrix_as_string(Tf_p * Tb_s)

                for a in [
                        k[3] for k in self._matrices.keys()
                        if (len(k) == 4 and k[0:3] == (0, p, s))
                ]:
                    (Tf_a, Tb_a) = self._matrices[(0, p, s, a)]
                    metrology_str += "asic {\n"
                    metrology_str += "serial = %d\n" % a
                    metrology_str += self._matrix_as_string(Tf_s * Tb_a)

                    metrology_str += "}\n"
                metrology_str += "}\n"
            metrology_str += "}\n"
        metrology_str += "}\n"

        return master_phil.fetch(sources=[phil.parse(metrology_str)])
  def transformation_matrices_as_metrology(self):
    """The transformation_matrices_as_metrology() function regularizes
    the the transformation matrices and converts them to a phil
    object.
    """

    from libtbx import phil
    from xfel.cftbx.detector.metrology import \
      master_phil, regularize_transformation_matrices

    # XXX Experimental!
    regularize_transformation_matrices(self._matrices)

    (Tf_d, Tb_d) = self._matrices[(0,)]
    metrology_str = "detector {\n"
    metrology_str += "serial = %d\n" % 0
    metrology_str += self._matrix_as_string(Tb_d)

    for p in [k[1] for k in self._matrices.keys()
              if (len(k) == 2 and k[0:1] == (0,))]:
      (Tf_p, Tb_p) = self._matrices[(0, p)]
      metrology_str += "panel {\n"
      metrology_str += "serial = %d\n" % p
      metrology_str += self._matrix_as_string(Tf_d * Tb_p)

      for s in[k[2] for k in self._matrices.keys()
               if (len(k) == 3 and k[0:2] == (0, p))]:
        (Tf_s, Tb_s) = self._matrices[(0, p, s)]
        metrology_str += "sensor {\n"
        metrology_str += "serial = %d\n" % s
        metrology_str += self._matrix_as_string(Tf_p * Tb_s)

        for a in [k[3] for k in self._matrices.keys()
                  if (len(k) == 4 and k[0:3] == (0, p, s))]:
          (Tf_a, Tb_a) = self._matrices[(0, p, s, a)]
          metrology_str += "asic {\n"
          metrology_str += "serial = %d\n" % a
          metrology_str += self._matrix_as_string(Tf_s * Tb_a)

          metrology_str += "}\n"
        metrology_str += "}\n"
      metrology_str += "}\n"
    metrology_str += "}\n"

    return master_phil.fetch(sources=[phil.parse(metrology_str)])
def sections2phil(sections, verbose):
  from xfel.cftbx.detector.metrology import master_phil

  # Properties of CSPad pixels (Philipp et al., 2007).  The counters
  # are 14 bits wide, and the pixels are square with a side length of
  # 110 um.  Because cspad_tbx depends on pyana, it may fail to import
  # in which case a hardcoded fallback is provided.
  try:
    from xfel.cxi.cspad_ana.cspad_tbx import cspad_saturated_value as sv
    from xfel.cxi.cspad_ana.cspad_tbx import pixel_size as ps
    saturated_value = sv
    pixel_size = ps * 1e-3
  except ImportError:
    saturated_value = 90000
    pixel_size = 110e-6

  # Build the Phil object.  XXX Should have det-z?  Probably not,
  # because then it aint't just metrology anymore.  In fact, under
  # orthographic projection the whole translation/orientation thing
  # can be scrapped for the detector.  XXX look up include,
  # include_scope for phil XXX Hardcoded address for now.
  address = "CxiDs1-0|Cspad-0"
  metrology_str = "detector { serial = %d\n" % 0
  metrology_str += "label = %s\n" % address

  # The center of the detector is defined as the average of all the
  # sections it contains.  The first coordinate of the matrix-oriented
  # coordinate system of the Section class maps to -y, the second to
  # x, and the third to z.  While the detector still sits on the
  # origin (zero translation), the mapping from the origin in Section
  # coordinates is still needed.
  t_d = [0, 0, 0]
  nmemb = 0
  for p in range(len(sections)):
    for s in range(len(sections[p])):
      t_d[0] += +sections[p][s].center[1]
      t_d[1] += -sections[p][s].center[0]
      t_d[2] += 0
      nmemb += 1
  if (nmemb > 0):
    for i in range(3):
      t_d[i] /= nmemb
  metrology_str += "translation = 0, 0, 0\n"

  o_d = matrix.col([0, 0, 1]).axis_and_angle_as_unit_quaternion(
    angle=0, deg=True)
  metrology_str += "orientation = %s, %s, %s, %s\n" % \
      tuple(repr(c) for c in o_d)

  for p in range(len(sections)):
    # Loop over quadrants (panels).  XXX Translation of panels is
    # wrongly set to to centre of sections in the quadrant
    # w.r.t. center of the detector.
    metrology_str += "panel { serial = %d\n" % p
    metrology_str += "translation = "
    t_p = [0, 0, 0]
    for s in range(len(sections[p])):
      t_p[0] += +sections[p][s].center[1] - t_d[0]
      t_p[1] += -sections[p][s].center[0] - t_d[1]
      t_p[2] +=  0                        - t_d[2]
    for i in range(3):
      t_p[i] /= len(sections[p])
      metrology_str += "%s" % repr(t_p[i] * pixel_size)
      if (i < 2):
        metrology_str += ", "
      else:
        metrology_str += "\n"

    # XXX Orientation wrongly set to zero.
    o_p = matrix.col([0, 0, 1]).axis_and_angle_as_unit_quaternion(
      angle=0, deg=True)
    metrology_str += "orientation = %s, %s, %s, %s\n" % \
        tuple(repr(c) for c in o_p)

    for s in range(len(sections[p])):
      # Loop over sensors (sections or two-by-one:s).  Note that
      # sensors are rotated by -90 degrees in the SLAC metrology
      # convention w.r.t. their appearance in the XTC stream.
      s_t = [0, 0, 0]
      s_t[0] = +sections[p][s].center[1] - t_p[0] - t_d[0]
      s_t[1] = -sections[p][s].center[0] - t_p[1] - t_d[1]
      s_t[2] =  0                        - t_p[2] - t_d[2]

      metrology_str += "sensor { serial = %d\n" % s
      metrology_str += "translation = "
      for i in range(3):
        metrology_str += "%s" % repr(s_t[i] * pixel_size)
        if (i < 2):
          metrology_str += ", "
        else:
          metrology_str += "\n"

      s_o = matrix.col([0, 0, 1]).axis_and_angle_as_unit_quaternion(
        angle=sections[p][s].angle - 90, deg=True)
      metrology_str += "orientation = %s, %s, %s, %s\n" % \
          tuple(repr(c) for c in s_o)

      for a in range(2):
        # The ASIC:s of the CSPad are 185 rows by 194 columns.  The
        # ASIC:s are horizontally aligned within a section, with a
        # three-column gap between them.
        metrology_str += "asic { serial = %d\n" % a

        if (a == 0):
          metrology_str += "translation = %s, %s, %s\n" % (
            repr(-(194 + 3) / 2 * pixel_size), "0", "0") # XXX hardcoded!
        else:
          metrology_str += "translation = %s, %s, %s\n" % (
            repr(+(194 + 3) / 2 * pixel_size), "0", "0") # XXX hardcoded!
        metrology_str += "orientation = 1, 0, 0, 0\n"
        metrology_str += "pixel_size = %s, %s\n" % (
          repr(pixel_size), repr(pixel_size))
        metrology_str += "dimension = %d, %d\n" % (194, 185) # XXX hardcoded!
        metrology_str += "saturation = %s\n" % repr(float(saturated_value))
        metrology_str += "}\n"
      metrology_str += "}\n"
    metrology_str += "}\n"
  metrology_str += "}\n"

  metrology_phil = master_phil.fetch(
    sources=[phil.parse(metrology_str)])
  return (metrology_phil)
Beispiel #6
0
def run(argv=None):
    if (argv is None):
        argv = sys.argv

    # XXX Could/should handle effective metrology the same way, except
    # it does not have a single scope.
    work_phil = phil.process_command_line(args=argv[1:],
                                          master_string=master_str + phil_str +
                                          additional_spotfinder_phil_defs)
    work_params = work_phil.work.extract()

    app = wx.App(0)
    wx.SystemOptions.SetOptionInt("osx.openfiledialog.always-show-types", 1)
    frame = XrayFrame(None, -1, "X-ray image display", size=(800, 720))
    frame.Show()

    # show settings panel
    frame.OnShowSettings(None)
    frame.settings_frame.panel.center_ctrl.SetValue(work_params.beam_center)
    frame.settings_frame.panel.integ_ctrl.SetValue(
        work_params.show_integration_results)
    frame.settings_frame.panel.spots_ctrl.SetValue(
        work_params.show_spotfinder_results)
    frame.settings.show_effective_tiling = work_params.show_effective_tiling
    frame.settings_frame.panel.collect_values()

    if (work_params.effective_metrology is not None):
        from xfel.cftbx.detector.metrology import \
          master_phil, metrology_as_transformation_matrices

        stream = open(work_params.effective_metrology)
        metrology_phil = master_phil.fetch(sources=[phil.parse(stream.read())])
        stream.close()
        frame.metrology_matrices = metrology_as_transformation_matrices(
            metrology_phil.extract())

    # Update initial settings with values from the command line.  Needs
    # to be done before image is loaded (but after the frame is
    # instantiated).
    frame.params = work_params
    frame.init_pyslip()
    frame.pyslip.tiles.user_requests_antialiasing = work_params.anti_aliasing
    frame.pyslip.tiles.show_untrusted = frame.params.show_untrusted

    paths = work_phil.remaining_args
    if (len(paths) == 1 and os.path.basename(paths[0]) == "DISTL_pickle"):
        assert os.path.isfile(paths[0])
        frame.load_distl_output(paths[0])
    elif (len(paths) > 0):
        frame.CHOOSER_SIZE = 1500

        # from dxtbx.imageset import ImageSetFactory
        # sets = ImageSetFactory.new(paths)
        from dxtbx.model.experiment_list import ExperimentListFactory
        from rstbx.slip_viewer.frame import chooser_wrapper
        experiments = ExperimentListFactory.from_filenames(paths)
        sets = experiments.imagesets()

        for imgset in sets:
            for idx in imgset.indices():
                frame.add_file_name_or_data(chooser_wrapper(imgset, idx))
        idx = sets[0].indices()[0]
        frame.load_image(chooser_wrapper(sets[0], idx))

    app.MainLoop()

    return 0
def metrology2phil(calib_dir, verbose):
  """XXX Should really review the SLAC progress since last time
  around!  XXX Note that this is all SLAC-specific (as is the whole
  thing, I guess).
  """

  from xfel.cftbx.detector.metrology import master_phil

  # XXX Can this fail?  How?
  sections = calib2sections(calib_dir)
  if (sections is None):
    return (None)

  # Properties of CSPad pixels (Philipp et al., 2007).  The counters
  # are 14 bits wide, and the pixels are square with a side length of
  # 110 um.  Because cspad_tbx depends on pyana, it may fail to import
  # in which case a hardcoded fallback is provided.
  try:
    from xfel.cxi.cspad_ana.cspad_tbx import cspad_saturated_value as sv
    from xfel.cxi.cspad_ana.cspad_tbx import pixel_size as ps
    saturated_value = sv
    pixel_size = ps * 1e-3
  except ImportError:
    saturated_value = 90000
    pixel_size = 110e-6

  # Build the Phil object.  XXX Should have det-z?  Probably not,
  # because then it aint't just metrology anymore.  In fact, under
  # orthographic projection the whole translation/orientation thing
  # can be scrapped for the detector.  XXX look up include,
  # include_scope for phil XXX Hardcoded address for now.
  address = "CxiDs1-0|Cspad-0"
  metrology_str = "detector { serial = %d\n" % 0
  metrology_str += "label = %s\n" % address

  # The center of the detector is defined as the average of all the
  # sections it contains.  The first coordinate of the matrix-oriented
  # coordinate system of the Section class maps to -y, the second to
  # x, and the third to z.  While the detector still sits on the
  # origin (zero translation), the mapping from the origin in Section
  # coordinates is still needed.
  t_d = [0, 0, 0]
  nmemb = 0
  for p in xrange(len(sections)):
    for s in xrange(len(sections[p])):
      t_d[0] += +sections[p][s].center[1]
      t_d[1] += -sections[p][s].center[0]
      t_d[2] += 0
      nmemb += 1
  if (nmemb > 0):
    for i in xrange(3):
      t_d[i] /= nmemb
  metrology_str += "translation = 0, 0, 0\n"

  o_d = matrix.col([0, 0, 1]).axis_and_angle_as_unit_quaternion(
    angle=0, deg=True)
  metrology_str += "orientation = %s, %s, %s, %s\n" % \
      tuple(repr(c) for c in o_d)

  for p in xrange(len(sections)):
    # Loop over quadrants (panels).  XXX Translation of panels is
    # wrongly set to to centre of sections in the quadrant
    # w.r.t. center of the detector.
    metrology_str += "panel { serial = %d\n" % p
    metrology_str += "translation = "
    t_p = [0, 0, 0]
    for s in xrange(len(sections[p])):
      t_p[0] += +sections[p][s].center[1] - t_d[0]
      t_p[1] += -sections[p][s].center[0] - t_d[1]
      t_p[2] +=  0                        - t_d[2]
    for i in xrange(3):
      t_p[i] /= len(sections[p])
      metrology_str += "%s" % repr(t_p[i] * pixel_size)
      if (i < 2):
        metrology_str += ", "
      else:
        metrology_str += "\n"

    # XXX Orientation wrongly set to zero.
    o_p = matrix.col([0, 0, 1]).axis_and_angle_as_unit_quaternion(
      angle=0, deg=True)
    metrology_str += "orientation = %s, %s, %s, %s\n" % \
        tuple(repr(c) for c in o_p)

    for s in xrange(len(sections[p])):
      # Loop over sensors (sections or two-by-one:s).  Note that
      # sensors are rotated by -90 degrees in the SLAC metrology
      # convention w.r.t. their appearance in the XTC stream.
      s_t = [0, 0, 0]
      s_t[0] = +sections[p][s].center[1] - t_p[0] - t_d[0]
      s_t[1] = -sections[p][s].center[0] - t_p[1] - t_d[1]
      s_t[2] =  0                        - t_p[2] - t_d[2]

      metrology_str += "sensor { serial = %d\n" % s
      metrology_str += "translation = "
      for i in xrange(3):
        metrology_str += "%s" % repr(s_t[i] * pixel_size)
        if (i < 2):
          metrology_str += ", "
        else:
          metrology_str += "\n"

      s_o = matrix.col([0, 0, 1]).axis_and_angle_as_unit_quaternion(
        angle=sections[p][s].angle - 90, deg=True)
      metrology_str += "orientation = %s, %s, %s, %s\n" % \
          tuple(repr(c) for c in s_o)

      for a in xrange(2):
        # The ASIC:s of the CSPad are 185 rows by 194 columns.  The
        # ASIC:s are horizontally aligned within a section, with a
        # three-column gap between them.
        metrology_str += "asic { serial = %d\n" % a

        if (a == 0):
          metrology_str += "translation = %s, %s, %s\n" % (
            repr(-(194 + 3) / 2 * pixel_size), "0", "0") # XXX hardcoded!
        else:
          metrology_str += "translation = %s, %s, %s\n" % (
            repr(+(194 + 3) / 2 * pixel_size), "0", "0") # XXX hardcoded!
        metrology_str += "orientation = 1, 0, 0, 0\n"
        metrology_str += "pixel_size = %s, %s\n" % (
          repr(pixel_size), repr(pixel_size))
        metrology_str += "dimension = %d, %d\n" % (194, 185) # XXX hardcoded!
        metrology_str += "saturation = %s\n" % repr(float(saturated_value))
        metrology_str += "}\n"
      metrology_str += "}\n"
    metrology_str += "}\n"
  metrology_str += "}\n"

  metrology_phil = master_phil.fetch(
    sources=[phil.parse(metrology_str)])
  return (metrology_phil)
Beispiel #8
0
def run(argv=None):
  if (argv is None):
    argv = sys.argv

  # XXX Could/should handle effective metrology the same way, except
  # it does not have a single scope.
  work_phil = phil.process_command_line(
    args=argv[1:],
    master_string=master_str + phil_str + additional_spotfinder_phil_defs)
  work_params = work_phil.work.extract()

  app = wx.App(0)
  wx.SystemOptions.SetOptionInt("osx.openfiledialog.always-show-types", 1)
  frame = XrayFrame(None, -1, "X-ray image display", size=(800,720))
  frame.Show()

  # show settings panel
  frame.OnShowSettings(None)
  frame.settings_frame.panel.center_ctrl.SetValue(
    work_params.beam_center)
  frame.settings_frame.panel.integ_ctrl.SetValue(
    work_params.show_integration_results)
  frame.settings_frame.panel.spots_ctrl.SetValue(
    work_params.show_spotfinder_results)
  frame.settings.show_effective_tiling = work_params.show_effective_tiling
  frame.settings_frame.panel.collect_values()

  if (work_params.effective_metrology is not None):
    from xfel.cftbx.detector.metrology import \
      master_phil, metrology_as_transformation_matrices

    stream = open(work_params.effective_metrology)
    metrology_phil = master_phil.fetch(sources=[phil.parse(stream.read())])
    stream.close()
    frame.metrology_matrices = metrology_as_transformation_matrices(
      metrology_phil.extract())

  # Update initial settings with values from the command line.  Needs
  # to be done before image is loaded (but after the frame is
  # instantiated).
  frame.params = work_params
  frame.init_pyslip()
  frame.pyslip.tiles.user_requests_antialiasing = work_params.anti_aliasing
  frame.pyslip.tiles.show_untrusted = frame.params.show_untrusted

  paths = work_phil.remaining_args
  if (len(paths) == 1 and os.path.basename(paths[0]) == "DISTL_pickle"):
    assert os.path.isfile(paths[0])
    frame.load_distl_output(paths[0])
  elif (len(paths) > 0):
    frame.CHOOSER_SIZE = 1500

    from dxtbx.imageset import ImageSetFactory
    from rstbx.slip_viewer.frame import chooser_wrapper
    sets = ImageSetFactory.new(paths)

    for imgset in sets:
      for idx in imgset.indices():
        frame.add_file_name_or_data(chooser_wrapper(imgset, idx))
    idx = sets[0].indices()[0]
    frame.load_image(chooser_wrapper(sets[0],idx))

  app.MainLoop()

  return 0