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
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))
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)