def run(args): command_line = (option_parser().option( "-o", "--output_filename", action="store", type="string", help="Filename for the output cbf file", default="gain_map.cbf" ).option( "-m", "--metrology", action="store", type="string", help="CBF or DEF file", default=None ).option( "-d", "--distance", action="store", type="int", help= "Detector distance put into the gain cbf file. Not needed for processing.", default="0" ).option( "-w", "--wavelength", action="store", type="float", help= "Incident beam wavelength put into the gain cbf file. Not needed for processing.", default="0")).process(args=args) output_filename = command_line.options.output_filename metrology = command_line.options.metrology assert metrology is not None and os.path.isfile(metrology) args = command_line.args assert len(args) == 1 if args[0].endswith('.txt') or args[0].endswith('.gain'): raw_data = numpy.loadtxt(args[0]) assert raw_data.shape in [(5920, 388), (11840, 194)] tiles = convert_detector(raw_data) else: raise Usage( "Gain input file should be a text file with extension .txt or .gain" ) metro = cbf_file_to_basis_dict(metrology) write_cspad_cbf(tiles, metro, 'cbf', None, output_filename, command_line.options.wavelength, command_line.options.distance)
def run(argv=None): if argv is None: argv = sys.argv[1:] command_line = libtbx.option_parser.option_parser( usage="%s files" % libtbx.env.dispatcher_name).process(args=argv) paths = command_line.args if len(paths) <= 0: raise Usage("No files specified") for path in paths: # Load the metrology dictionary, containting basis shifts for each item in the hierarchy metro = cbf_file_to_basis_dict(path) # Remove from the hiearchy all but the central sensors (sensor 1 of each quadrant). # Need to remove the sesnor basis shifts and the corresponding asic shifts for quad in range(4): for sensor in [0, 2, 3, 4, 5, 6, 7]: metro.pop((0, quad, sensor)) for asic in range(2): metro.pop((0, quad, sensor, asic)) # Renumber the sensors to 0 instead of 1 for key in metro: if len(key) == 3: detector, quad, sensor = key metro[(detector, quad, 0)] = metro.pop(key) elif len(key) == 4: detector, quad, sensor, asic = key metro[(detector, quad, 0, asic)] = metro.pop(key) # Build the tiles dictionary for only sensor 1 of each quadrant. Rename that sensor to zero. img = dxtbx.load(path) tiles = {} for quad in range(4): src_sensor = 1 dest_sensor = 0 for asic in range(2): tiles[(0, quad, dest_sensor, asic)] = img.get_raw_data()[ (quad * 16) + (src_sensor * 2) + asic] # FIXME get the panel ID from dxtbx destpath = os.path.splitext(path)[0] + "_pinwheel.cbf" hierarchy = img.get_detector().hierarchy() beam = img.get_beam() # write the result. Have to call abs on the root distance because of a bug with the hierarchy matrix. write_cspad_cbf(tiles, metro, 'cbf', None, destpath, beam.get_wavelength(), hierarchy.get_distance())
def run(args): command_line = ( option_parser() .option( "-o", "--output_filename", action="store", type="string", help="Filename for the output cbf file", default="gain_map.cbf", ) .option("-m", "--metrology", action="store", type="string", help="CBF or DEF file", default=None) .option( "-d", "--distance", action="store", type="int", help="Detector distance put into the gain cbf file. Not needed for processing.", default="0", ) .option( "-w", "--wavelength", action="store", type="float", help="Incident beam wavelength put into the gain cbf file. Not needed for processing.", default="0", ) ).process(args=args) output_filename = command_line.options.output_filename metrology = command_line.options.metrology assert metrology is not None and os.path.isfile(metrology) args = command_line.args assert len(args) == 1 if args[0].endswith(".txt") or args[0].endswith(".gain"): raw_data = numpy.loadtxt(args[0]) assert raw_data.shape in [(5920, 388), (11840, 194)] tiles = convert_detector(raw_data) else: raise Usage("Gain input file should be a text file with extension .txt or .gain") metro = cbf_file_to_basis_dict(metrology) write_cspad_cbf( tiles, metro, "cbf", None, output_filename, command_line.options.wavelength, command_line.options.distance )
def run(argv=None): if argv is None: argv = sys.argv[1:] command_line = libtbx.option_parser.option_parser( usage="%s files" % libtbx.env.dispatcher_name).process(args=argv) paths = command_line.args if len(paths) <= 0: raise Usage("No files specified") for path in paths: # Load the metrology dictionary, containting basis shifts for each item in the hierarchy metro = cbf_file_to_basis_dict(path) # Remove from the hiearchy all but the central sensors (sensor 1 of each quadrant). # Need to remove the sesnor basis shifts and the corresponding asic shifts for quad in range(4): for sensor in [0,2,3,4,5,6,7]: metro.pop((0,quad,sensor)) for asic in range(2): metro.pop((0,quad,sensor,asic)) # Renumber the sensors to 0 instead of 1 for key in metro: if len(key) == 3: detector, quad, sensor = key metro[(detector,quad,0)] = metro.pop(key) elif len(key) == 4: detector, quad, sensor, asic = key metro[(detector,quad,0,asic)] = metro.pop(key) # Build the tiles dictionary for only sensor 1 of each quadrant. Rename that sensor to zero. img = dxtbx.load(path) tiles = {} for quad in range(4): src_sensor = 1 dest_sensor = 0 for asic in range(2): tiles[(0,quad,dest_sensor,asic)] = img.get_raw_data()[(quad*16)+(src_sensor*2)+asic] # FIXME get the panel ID from dxtbx destpath = os.path.splitext(path)[0] + "_pinwheel.cbf" hierarchy = img.get_detector().hierarchy() beam = img.get_beam() # write the result. Have to call abs on the root distance because of a bug with the hierarchy matrix. write_cspad_cbf(tiles, metro, 'cbf', None, destpath, beam.get_wavelength(), hierarchy.get_distance())
from xfel.cftbx.detector.metrology2phil import metrology2phil metro = metrology2phil(params.new_metrology, False) args = [] import iotbx.phil for arg in args: metro = metro.fetch(sources=[iotbx.phil.parse(arg)]) else: assert os.path.isfile(params.new_metrology) ext = os.path.splitext(params.new_metrology)[1].lower() if ext in ['.def', '.cbf']: metro_style = "cbf" from xfel.cftbx.detector.cspad_cbf_tbx import cbf_file_to_basis_dict metro = cbf_file_to_basis_dict(params.new_metrology) else: metro_style = "flatfile" from xfel.cftbx.detector.cspad_cbf_tbx import read_optical_metrology_from_flat_file, asic_dimension, asic_gap metro = read_optical_metrology_from_flat_file(params.new_metrology, params.detector, img['PIXEL_SIZE'], asic_dimension, asic_gap, plot=params.plot) for filename in params.pickle_file: # Read the pickle file and pull the tiles out of it
def run(argv=None): """Compute mean, standard deviation, and maximum projection images from a set of CSPAD cbf images given on the command line. @param argv Command line argument list @return @c 0 on successful termination, @c 1 on error, and @c 2 for command line syntax errors """ import libtbx.load_env from libtbx import option_parser from scitbx.array_family import flex from dxtbx.format.Registry import Registry from xfel.cftbx.detector.cspad_cbf_tbx import cbf_file_to_basis_dict, write_cspad_cbf # from xfel.cxi.cspad_ana import cspad_tbx # from iotbx.detectors.cspad_detector_formats import reverse_timestamp if argv is None: argv = sys.argv command_line = (option_parser.option_parser( usage="%s [-v] [-a PATH] [-m PATH] [-s PATH] " \ "image1 image2 [image3 ...]" % libtbx.env.dispatcher_name) .option(None, "--average-path", "-a", type="string", default=None, dest="avg_path", metavar="PATH", help="Write average image to PATH") .option(None, "--maximum-path", "-m", type="string", default=None, dest="max_path", metavar="PATH", help="Write maximum projection image to PATH") .option(None, "--stddev-path", "-s", type="string", default=None, dest="stddev_path", metavar="PATH", help="Write standard deviation image to PATH") .option(None, "--verbose", "-v", action="store_true", default=False, dest="verbose", help="Print more information about progress") ).process(args=argv[1:]) # Note that it is not an error to omit the output paths, because # certain statistics could still be printed, e.g. with the verbose # option. paths = command_line.args if len(paths) == 0: command_line.parser.print_usage(file=sys.stderr) return 2 # Loop over all images and accumulate statistics. nfail = 0 nmemb = 0 for path in paths: if command_line.options.verbose: sys.stdout.write("Processing %s...\n" % path) try: # Promote the image to double-precision floating point type. # All real-valued flex arrays have the as_double() function. # Warn if the header items across the set of images do not match # up. Note that discrepancies regarding the image size are # fatal. if not 'reader' in locals(): reader = Registry.find(path) img = reader(path) if 'detector' in locals(): test_detector = img.get_detector() if len(test_detector) != len(detector): sys.stderr.write("Detectors do not have the same number of panels\n") return 1 for t, d in zip(test_detector, detector): if t.get_image_size() != d.get_image_size(): sys.stderr.write("Panel sizes do not match\n") return 1 if t.get_pixel_size() != d.get_pixel_size(): sys.stderr.write("Pixel sizes do not match\n") return 1 if t.get_d_matrix() != d.get_d_matrix(): sys.stderr.write("Detector panels are not all in the same location. The average will use the positions of the first image.\n") detector = test_detector else: detector = img.get_detector() data = [img.get_raw_data()[i].as_1d().as_double() for i in xrange(len(detector))] wavelength = img.get_beam().get_wavelength() distance = flex.mean(flex.double([d.get_directed_distance() for d in detector])) except Exception: nfail += 1 continue # The sum-of-squares image is accumulated using long integers, as # this delays the point where overflow occurs. But really, this # is just a band-aid... if nmemb == 0: max_img = copy.deepcopy(data) sum_distance = distance sum_img = copy.deepcopy(data) ssq_img = [flex.pow2(d) for d in data] sum_wavelength = wavelength metro = cbf_file_to_basis_dict(path) else: sel = [(d > max_d).as_1d() for d, max_d in zip(data, max_img)] for d, max_d, s in zip(data, max_img, sel): max_d.set_selected(s, d.select(s)) sum_distance += distance for d, sum_d in zip(data, sum_img): sum_d += d for d, ssq_d in zip(data, ssq_img): ssq_d += flex.pow2(d) sum_wavelength += wavelength nmemb += 1 # Early exit if no statistics were accumulated. if command_line.options.verbose: sys.stderr.write("Processed %d images (%d failed)\n" % (nmemb, nfail)) if nmemb == 0: return 0 # Calculate averages for measures where other statistics do not make # sense. Note that avg_img is required for stddev_img. avg_img = [sum_d.as_double() / nmemb for sum_d in sum_img] avg_distance = sum_distance / nmemb avg_wavelength = sum_wavelength / nmemb def make_tiles(data, detector): """ Assemble a tiles dictionary as required by write_cspad_cbf, consisting of 4 arrays of shape 8x185x388. Assumes the order in the data array matches the order of the enumerated detector panels. """ assert len(data) == 64 tiles = {} s, f = 185, 194 for q_id in xrange(4): tiles[0,q_id] = flex.double((flex.grid(s*8, f*2))) for s_id in xrange(8): for a_id in xrange(2): asic_idx = (q_id*16) + (s_id*2) + a_id asic = data[asic_idx] asic.reshape(flex.grid((s, f))) tiles[0, q_id].matrix_paste_block_in_place(asic, s_id*s, a_id*f) tiles[0, q_id].reshape(flex.grid((8, s, f*2))) return tiles # Output the average image, maximum projection image, and standard # deviation image, if requested. if command_line.options.avg_path is not None: tiles = make_tiles(avg_img, detector) write_cspad_cbf(tiles, metro, 'cbf', None, command_line.options.avg_path, avg_wavelength, avg_distance) if command_line.options.max_path is not None: tiles = make_tiles(max_img, detector) write_cspad_cbf(tiles, metro, 'cbf', None, command_line.options.max_path, avg_wavelength, avg_distance) if command_line.options.stddev_path is not None: stddev_img = [ssq_d.as_double() - sum_d.as_double() * avg_d for ssq_d, sum_d, avg_d in zip(ssq_img, sum_img, avg_img)] # Accumulating floating-point numbers introduces errors, which may # cause negative variances. Since a two-pass approach is # unacceptable, the standard deviation is clamped at zero. for stddev_d in stddev_img: stddev_d.set_selected(stddev_d < 0, 0) if nmemb == 1: stddev_img = [flex.sqrt(stddev_d) for stddev_d in stddev_img] else: stddev_img = [flex.sqrt(stddev_d / (nmemb - 1)) for stddev_d in stddev_img] tiles = make_tiles(stddev_img, detector) write_cspad_cbf(tiles, metro, 'cbf', None, command_line.options.stddev_path, avg_wavelength, avg_distance) return 0
def run(argv=None): """Compute mean, standard deviation, and maximum projection images from a set of CSPAD cbf images given on the command line. @param argv Command line argument list @return @c 0 on successful termination, @c 1 on error, and @c 2 for command line syntax errors """ import libtbx.load_env from libtbx import option_parser from scitbx.array_family import flex from dxtbx.format.Registry import Registry from xfel.cftbx.detector.cspad_cbf_tbx import cbf_file_to_basis_dict, write_cspad_cbf # from xfel.cxi.cspad_ana import cspad_tbx # from iotbx.detectors.cspad_detector_formats import reverse_timestamp if argv is None: argv = sys.argv command_line = (option_parser.option_parser( usage="%s [-v] [-a PATH] [-m PATH] [-s PATH] " \ "image1 image2 [image3 ...]" % libtbx.env.dispatcher_name) .option(None, "--average-path", "-a", type="string", default=None, dest="avg_path", metavar="PATH", help="Write average image to PATH") .option(None, "--maximum-path", "-m", type="string", default=None, dest="max_path", metavar="PATH", help="Write maximum projection image to PATH") .option(None, "--stddev-path", "-s", type="string", default=None, dest="stddev_path", metavar="PATH", help="Write standard deviation image to PATH") .option(None, "--verbose", "-v", action="store_true", default=False, dest="verbose", help="Print more information about progress") ).process(args=argv[1:]) # Note that it is not an error to omit the output paths, because # certain statistics could still be printed, e.g. with the verbose # option. paths = command_line.args if len(paths) == 0: command_line.parser.print_usage(file=sys.stderr) return 2 # Loop over all images and accumulate statistics. nfail = 0 nmemb = 0 for path in paths: if command_line.options.verbose: sys.stdout.write("Processing %s...\n" % path) try: # Promote the image to double-precision floating point type. # All real-valued flex arrays have the as_double() function. # Warn if the header items across the set of images do not match # up. Note that discrepancies regarding the image size are # fatal. if not 'reader' in locals(): reader = Registry.find(path) img = reader(path) if 'detector' in locals(): test_detector = img.get_detector() if len(test_detector) != len(detector): sys.stderr.write( "Detectors do not have the same number of panels\n") return 1 for t, d in zip(test_detector, detector): if t.get_image_size() != d.get_image_size(): sys.stderr.write("Panel sizes do not match\n") return 1 if t.get_pixel_size() != d.get_pixel_size(): sys.stderr.write("Pixel sizes do not match\n") return 1 if t.get_d_matrix() != d.get_d_matrix(): sys.stderr.write( "Detector panels are not all in the same location. The average will use the positions of the first image.\n" ) detector = test_detector else: detector = img.get_detector() data = [ img.get_raw_data()[i].as_1d().as_double() for i in range(len(detector)) ] wavelength = img.get_beam().get_wavelength() distance = flex.mean( flex.double([d.get_directed_distance() for d in detector])) except Exception: nfail += 1 continue # The sum-of-squares image is accumulated using long integers, as # this delays the point where overflow occurs. But really, this # is just a band-aid... if nmemb == 0: max_img = copy.deepcopy(data) sum_distance = distance sum_img = copy.deepcopy(data) ssq_img = [flex.pow2(d) for d in data] sum_wavelength = wavelength metro = cbf_file_to_basis_dict(path) else: sel = [(d > max_d).as_1d() for d, max_d in zip(data, max_img)] for d, max_d, s in zip(data, max_img, sel): max_d.set_selected(s, d.select(s)) sum_distance += distance for d, sum_d in zip(data, sum_img): sum_d += d for d, ssq_d in zip(data, ssq_img): ssq_d += flex.pow2(d) sum_wavelength += wavelength nmemb += 1 # Early exit if no statistics were accumulated. if command_line.options.verbose: sys.stderr.write("Processed %d images (%d failed)\n" % (nmemb, nfail)) if nmemb == 0: return 0 # Calculate averages for measures where other statistics do not make # sense. Note that avg_img is required for stddev_img. avg_img = [sum_d.as_double() / nmemb for sum_d in sum_img] avg_distance = sum_distance / nmemb avg_wavelength = sum_wavelength / nmemb def make_tiles(data, detector): """ Assemble a tiles dictionary as required by write_cspad_cbf, consisting of 4 arrays of shape 8x185x388. Assumes the order in the data array matches the order of the enumerated detector panels. """ assert len(data) == 64 tiles = {} s, f = 185, 194 for q_id in range(4): tiles[0, q_id] = flex.double((flex.grid(s * 8, f * 2))) for s_id in range(8): for a_id in range(2): asic_idx = (q_id * 16) + (s_id * 2) + a_id asic = data[asic_idx] asic.reshape(flex.grid((s, f))) tiles[0, q_id].matrix_paste_block_in_place( asic, s_id * s, a_id * f) tiles[0, q_id].reshape(flex.grid((8, s, f * 2))) return tiles # Output the average image, maximum projection image, and standard # deviation image, if requested. if command_line.options.avg_path is not None: tiles = make_tiles(avg_img, detector) write_cspad_cbf(tiles, metro, 'cbf', None, command_line.options.avg_path, avg_wavelength, avg_distance) if command_line.options.max_path is not None: tiles = make_tiles(max_img, detector) write_cspad_cbf(tiles, metro, 'cbf', None, command_line.options.max_path, avg_wavelength, avg_distance) if command_line.options.stddev_path is not None: stddev_img = [ ssq_d.as_double() - sum_d.as_double() * avg_d for ssq_d, sum_d, avg_d in zip(ssq_img, sum_img, avg_img) ] # Accumulating floating-point numbers introduces errors, which may # cause negative variances. Since a two-pass approach is # unacceptable, the standard deviation is clamped at zero. for stddev_d in stddev_img: stddev_d.set_selected(stddev_d < 0, 0) if nmemb == 1: stddev_img = [flex.sqrt(stddev_d) for stddev_d in stddev_img] else: stddev_img = [ flex.sqrt(stddev_d / (nmemb - 1)) for stddev_d in stddev_img ] tiles = make_tiles(stddev_img, detector) write_cspad_cbf(tiles, metro, 'cbf', None, command_line.options.stddev_path, avg_wavelength, avg_distance) return 0
from xfel.cftbx.detector.metrology2phil import metrology2phil metro = metrology2phil(params.new_metrology,False) args = [] import iotbx.phil for arg in args: metro = metro.fetch(sources=[iotbx.phil.parse(arg)]) else: assert os.path.isfile(params.new_metrology) ext = os.path.splitext(params.new_metrology)[1].lower() if ext in ['.def','.cbf']: metro_style = "cbf" from xfel.cftbx.detector.cspad_cbf_tbx import cbf_file_to_basis_dict metro = cbf_file_to_basis_dict(params.new_metrology) else: metro_style = "flatfile" from xfel.cftbx.detector.cspad_cbf_tbx import read_optical_metrology_from_flat_file, asic_dimension, asic_gap metro = read_optical_metrology_from_flat_file(params.new_metrology, params.detector, img['PIXEL_SIZE'], asic_dimension, asic_gap, plot=params.plot) for filename in params.pickle_file: # Read the pickle file and pull the tiles out of it img = easy_pickle.load(filename) tiles = {} asics = {}