if annulus:
    if params.resolution is None:
      print "Generating annular gain mask using %s metrology between %f and %f angstroms, assuming a distance %s mm and wavelength %s angstroms" % \
        (str(params.detector_format_version), params.annulus_inner, params.annulus_outer, params.distance, params.wavelength)
    else:
      print "Generating annular gain mask using %s metrology between %f and %f angstroms, assuming a distance %s mm and wavelength %s angstroms. Also, pixels higher than %f angstroms will be set to low gain." % \
        (str(params.detector_format_version), params.annulus_inner, params.annulus_outer, params.distance, params.wavelength, params.resolution)
  elif params.resolution is not None:
    print "Generating circular gain mask using %s metrology at %s angstroms, assuming a distance %s mm and wavelength %s angstroms" % \
      (str(params.detector_format_version), params.resolution, params.distance, params.wavelength)

  from xfel.cxi.cspad_ana.cspad_tbx import dpack, evt_timestamp, cbcaa, pixel_size, CsPadDetector
  from xfel.detector_formats import address_and_timestamp_from_detector_format_version
  from convert_gain_map import fake_env, fake_config, fake_evt, fake_cspad_ElementV2
  address, timestamp = address_and_timestamp_from_detector_format_version(params.detector_format_version)
  timestamp = evt_timestamp((timestamp,0))

  raw_data = numpy.zeros((11840,194))
  if params.detector_format_version is not None and "XPP" in params.detector_format_version:
    from xfel.cxi.cspad_ana.cspad_tbx import xpp_active_areas
    active_areas = xpp_active_areas[params.detector_format_version]['active_areas']
    data = flex.int(flex.grid((1765,1765)))
    beam_center = (1765 // 2, 1765 // 2)
  else:
    if params.optical_metrology_path is None:
      calib_dir = libtbx.env.find_in_repositories("xfel/metrology/CSPad/run4/CxiDs1.0_Cspad.0")
      sections = calib2sections(calib_dir)
    else:
      sections = calib2sections(params.optical_metrology_path)
    asic_start = 0
Exemplo n.º 2
0
def run(argv=None):
  import libtbx.option_parser

  if (argv is None):
    argv = sys.argv

  command_line = (libtbx.option_parser.option_parser(
    usage="%s [-v] [-p poly_mask] [-c circle_mask] [-a avg_max] [-s stddev_max] [-m maxproj_min] [-x mask_pix_val] [-o output] avg_path stddev_path max_path" % libtbx.env.dispatcher_name)
                  .option(None, "--verbose", "-v",
                          action="store_true",
                          default=False,
                          dest="verbose",
                          help="Print more information about progress")
                  .option(None, "--poly_mask", "-p",
                          type="string",
                          default=None,
                          dest="poly_mask",
                          help="Polygon to mask out.  Comma-seperated string of xy pairs.")
                  .option(None, "--circle_mask", "-c",
                          type="string",
                          default=None,
                          dest="circle_mask",
                          help="Circle to mask out.  Comma-seperated string of x, y, and radius.")
                  .option(None, "--avg_max", "-a",
                          type="float",
                          default=2000.0,
                          dest="avg_max",
                          help="Maximum ADU that pixels in the average image are allowed to have before masked out")
                  .option(None, "--stddev_max", "-s",
                          type="float",
                          default=10.0,
                          dest="stddev_max",
                          help="Maximum ADU that pixels in the standard deviation image are allowed to have before masked out")
                  .option(None, "--maxproj_min", "-m",
                          type="float",
                          default=300.0,
                          dest="maxproj_min",
                          help="Minimum ADU that pixels in the maximum projection image are allowed to have before masked out")
                  .option(None, "--mask_pix_val", "-x",
                          type="int",
                          default=-2,
                          dest="mask_pix_val",
                          help="Value for masked out pixels")
                  .option(None, "--detector_format_version", "-d",
                          type="string",
                          default=None,
                          dest="detector_format_version",
                          help="detector format version string")
                  .option(None, "--output", "-o",
                          type="string",
                          default="mask_.pickle",
                          dest="destpath",
                          help="output file path, should be *.pickle")
                  ).process(args=argv[1:])

  # Must have exactly three remaining arguments.
  paths = command_line.args
  if (len(paths) != 3):
    command_line.parser.print_usage(file=sys.stderr)
    return

  if command_line.options.detector_format_version is None:
    address = timestamp = None
  else:
    from xfel.cxi.cspad_ana.cspad_tbx import evt_timestamp
    from xfel.detector_formats import address_and_timestamp_from_detector_format_version
    address, timestamp = address_and_timestamp_from_detector_format_version(command_line.options.detector_format_version)
    timestamp = evt_timestamp((timestamp,0))

  poly_mask = None
  if not command_line.options.poly_mask == None:
    poly_mask = []
    poly_mask_tmp = command_line.options.poly_mask.split(",")
    if len(poly_mask_tmp) % 2 != 0:
      command_line.parser.print_usage(file=sys.stderr)
      return
    odd = True
    for item in poly_mask_tmp:
      try:
        if odd:
          poly_mask.append(int(item))
        else:
          poly_mask[-1] = (poly_mask[-1],int(item))
      except ValueError:
        command_line.parser.print_usage(file=sys.stderr)
        return
      odd = not odd

  circle_mask = None
  if command_line.options.circle_mask is not None:
    circle_mask_tmp = command_line.options.circle_mask.split(",")
    if len(circle_mask_tmp) != 3:
      command_line.parser.print_usage(file=sys.stderr)
      return
    try:
      circle_mask = (int(circle_mask_tmp[0]),int(circle_mask_tmp[1]),int(circle_mask_tmp[2]))
    except ValueError:
      command_line.parser.print_usage(file=sys.stderr)
      return

  avg_path    = paths[0]
  stddev_path = paths[1]
  max_path    = paths[2]

  # load the three images
  format_class = Registry.find(avg_path)
  avg_f = format_class(avg_path)
  avg_i = avg_f.get_detectorbase()
  avg_d = avg_i.get_raw_data()

  stddev_f = format_class(stddev_path)
  stddev_i = stddev_f.get_detectorbase()
  stddev_d = stddev_i.get_raw_data()

  max_f = format_class(max_path)
  max_i = max_f.get_detectorbase()
  max_d = max_i.get_raw_data()

  # first find all the pixels in the average that are less than zero or greater
  # than a cutoff and set them to the masking value
  avg_d.set_selected((avg_d <= 0) | (avg_d > command_line.options.avg_max), command_line.options.mask_pix_val)

  # set all the rest of the pixels to zero.  They will be accepted
  avg_d.set_selected(avg_d != command_line.options.mask_pix_val, 0)

  # mask out the overly noisy or flat pixels
  avg_d.set_selected(stddev_d <= 0, command_line.options.mask_pix_val)
  avg_d.set_selected(stddev_d >= command_line.options.stddev_max, command_line.options.mask_pix_val)

  # these are the non-bonded pixels
  avg_d.set_selected(max_d < command_line.options.maxproj_min, command_line.options.mask_pix_val)

  # calculate the beam center
  panel = avg_f.get_detector()[0]
  bcx, bcy = panel.get_beam_centre(avg_f.get_beam().get_s0())

  if poly_mask is not None or circle_mask is not None:
    minx = miny = 0
    maxx = avg_d.focus()[0]
    maxy = avg_d.focus()[1]
    if poly_mask is not None:
      minx = min([x[0] for x in poly_mask])
      miny = min([y[1] for y in poly_mask])
      maxx = max([x[0] for x in poly_mask])
      maxy = max([y[1] for y in poly_mask])
    if circle_mask is not None:
      circle_x, circle_y, radius = circle_mask

      if circle_x - radius < minx: minx = circle_x - radius
      if circle_y - radius < miny: miny = circle_y - radius
      if circle_x + radius > maxx: maxx = circle_x + radius
      if circle_y + radius > maxy: maxy = circle_y + radius

    sel = avg_d == command_line.options.mask_pix_val
    for j in xrange(miny, maxy):
      for i in xrange(minx, maxx):
        idx = j * avg_d.focus()[0] + i
        if not sel[idx]:
          if poly_mask is not None and point_in_polygon((i,j),poly_mask):
            sel[idx] = True
          elif circle_mask is not None and point_inside_circle(i,j,circle_x,circle_y,radius):
            sel[idx] = True
    avg_d.set_selected(sel,command_line.options.mask_pix_val)

  # have to re-layout the data to match how it was stored originally
  shifted_int_data_old = avg_d
  shifted_int_data_new = shifted_int_data_old.__class__(
    flex.grid(shifted_int_data_old.focus()))
  shifted_int_data_new += command_line.options.mask_pix_val

  phil = avg_i.horizons_phil_cache
  manager = avg_i.get_tile_manager(phil)

  for i,shift in enumerate(manager.effective_translations()):
    shift_slow = shift[0]
    shift_fast = shift[1]

    ur_slow = phil.distl.detector_tiling[4 * i + 0] + shift_slow
    ur_fast = phil.distl.detector_tiling[4 * i + 1] + shift_fast
    ll_slow = phil.distl.detector_tiling[4 * i + 2] + shift_slow
    ll_fast = phil.distl.detector_tiling[4 * i + 3] + shift_fast

    #print "Shifting tile at (%d, %d) by (%d, %d)" % (ur_slow-shift_slow, ur_fast-shift_fast, -shift_slow, -shift_fast)

    shifted_int_data_new.matrix_paste_block_in_place(
      block = shifted_int_data_old.matrix_copy_block(
        i_row=ur_slow,i_column=ur_fast,
        n_rows=ll_slow-ur_slow, n_columns=ll_fast-ur_fast),
      i_row = ur_slow - shift_slow,
      i_column = ur_fast - shift_fast
    )

  d = dpack(
    active_areas=avg_i.parameters['ACTIVE_AREAS'],
    address=address,
    beam_center_x=bcx,
    beam_center_y=bcy,
    data=shifted_int_data_new,
    distance=avg_i.distance,
    timestamp=timestamp,
    wavelength=avg_i.wavelength,
    xtal_target=None,
    pixel_size=avg_i.pixel_size,
    saturated_value=avg_i.saturation)

  dwritef2(d, command_line.options.destpath)

  #the minimum number of pixels to mask out cooresponding to the interstitial regions for the CS-PAD
  min_count  = 818265 # (1765 * 1765) - (194 * 185 * 64)
  masked_out = len(avg_d.as_1d().select((avg_d == command_line.options.mask_pix_val).as_1d()))
  assert masked_out >= min_count

  print "Masked out %d pixels out of %d (%.2f%%)"% \
    (masked_out-min_count,len(avg_d)-min_count,(masked_out-min_count)*100/(len(avg_d)-min_count))
Exemplo n.º 3
0
def run(args):
  command_line = (option_parser()
                  .option("-o", "--output_filename",
                          action="store",
                          type="string",
                          help="Filename for the output pickle file",
                          default="gain_map.pickle")
                  .option("-f", "--detector_format_version",
                          action="store",
                          type="string",
                          help="Detector format version to use for generating active areas and laying out tiles",
                          default=None)
                  .option("-m", "--optical_metrology_path",
                          action="store",
                          type="string",
                          help="Path to slac optical metrology file. If not set, use Run 4 metrology",
                          default=None)
                  .option("-d", "--distance",
                          action="store",
                          type="int",
                          help="Detector distance put into the gain pickle file. Not needed for processing.",
                          default="0")
                  .option("-w", "--wavelength",
                          action="store",
                          type="float",
                          help="Incident beam wavelength put into the gain pickle file. Not needed for processing.",
                          default="0")
                     ).process(args=args)
  output_filename = command_line.options.output_filename
  detector_format_version = command_line.options.detector_format_version
  if detector_format_version is None or 'XPP' not in detector_format_version:
    beam_center_x = None
    beam_center_y = None
  else:
    beam_center_x = 1765 // 2 * 0.11
    beam_center_y = 1765 // 2 * 0.11
  address, timestamp = address_and_timestamp_from_detector_format_version(detector_format_version)

  # if no detector format version is provided, make sure to write no address to the image pickle
  # but CsPadDetector (called later), needs an address, so give it a fake one
  save_address = address is not None
  if not save_address:
    address = "CxiDs1-0|Cspad-0" # time stamp will still be None
  timestamp = evt_timestamp((timestamp,0))
  args = command_line.args
  assert len(args) == 1
  if args[0].endswith('.npy'):
    data = numpy.load(args[0])
    det, active_areas = convert_2x2(data, detector_format_version, address)
  elif args[0].endswith('.txt') or args[0].endswith('.gain'):
    raw_data = numpy.loadtxt(args[0])
    assert raw_data.shape in [(5920, 388), (11840, 194)]
    det, active_areas = convert_detector(raw_data, detector_format_version, address, command_line.options.optical_metrology_path)
  img_diff = det
  img_sel = (img_diff > 0).as_1d()
  gain_map = flex.double(img_diff.accessor(), 0)
  gain_map.as_1d().set_selected(img_sel.iselection(), 1/img_diff.as_1d().select(img_sel))
  gain_map /= flex.mean(gain_map.as_1d().select(img_sel))

  if not save_address:
    address = None
  d = cspad_tbx.dpack(data=gain_map, address=address, active_areas=active_areas, timestamp=timestamp,
    distance=command_line.options.distance,wavelength=command_line.options.wavelength,
    beam_center_x = beam_center_x, beam_center_y = beam_center_y)
  easy_pickle.dump(output_filename, d)