def run(args): if ("--help" in args or "-h" in args) : print "Write a CBF header from a SLAC metrology file. Parameters:" master_phil.show(attributes_level=2) return user_phil = [] for arg in args: if (os.path.isfile(arg)) : user_phil.append(libtbx.phil.parse("""metrology_file=\"%s\"""" % arg)) else : try : user_phil.append(libtbx.phil.parse(arg)) except RuntimeError as e : raise Sorry("Unrecognized argument '%s' (error: %s)" % (arg, str(e))) params = master_phil.fetch(sources=user_phil).extract() if (params.metrology_file is None) : master_phil.show() raise Usage("metrology_file must be defined (either metrology_file=XXX, or the file path alone).") assert params.plot is not None assert params.out is not None print params.metrology_file metro = read_slac_metrology(params.metrology_file, plot=params.plot) write_cspad_cbf(None, metro, 'cbf', None, params.out, None, 0, header_only=True)
def run(self): params, options = self.parser.parse_args(show_diff_phil=True) experiments = flatten_experiments(params.input.experiments) detector = experiments[0].detector metro = map_detector_to_basis_dict(detector) write_cspad_cbf(None, metro, 'cbf', None, params.output_def_file, None, detector.hierarchy().get_distance(), header_only=True) print "Done"
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(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(self): params, options = self.parser.parse_args(show_diff_phil=True) experiments = flatten_experiments(params.input.experiments) detector = experiments[0].detector metro = map_detector_to_basis_dict(detector) write_cspad_cbf(None, metro, 'cbf', None, params.output_def_file, None, detector.hierarchy().get_distance(), header_only=True) print("Done")
def run(self): params, options = self.parser.parse_args(show_diff_phil=True) datablocks = flatten_datablocks(params.input.datablock) experiments = flatten_experiments(params.input.experiments) if len(datablocks) > 0: detector = datablocks[0].unique_detectors()[0] else: detector = experiments[0].detector metro = map_detector_to_basis_dict(detector) write_cspad_cbf(None, metro, 'cbf', None, params.output_def_file, None, detector.hierarchy().get_distance(), header_only=True) print "Done"
.help = Directory with optical metrology information posistioning quadrants and sensors, corrected for .help = rectangularity .optional = False out = None .type = str .help = Output file name .optional = False """) if (__name__ == "__main__") : user_phil = [] for arg in sys.argv[1:]: if (os.path.isdir(arg)) : user_phil.append(libtbx.phil.parse("""metrology_dir=\"%s\"""" % arg)) else : try : user_phil.append(libtbx.phil.parse(arg)) except RuntimeError, e : raise Sorry("Unrecognized argument '%s' (error: %s)" % (arg, str(e))) params = master_phil.fetch(sources=user_phil).extract() if (params.metrology_dir is None) : master_phil.show() raise Usage("metrology_dir must be defined (either metrology_dir=XXX, or the directory path alone).") assert params.out is not None metro_phil = metrology2phil(params.metrology_dir, verbose=True) write_cspad_cbf(None, metro_phil, 'calibdir', None, params.out, None, 0, header_only=True)
for p in xrange(num_sections): for s in xrange(section_len): for a in xrange(2): x1,y1,x2,y2 = active_areas[tile_id] block = data[x1:x2,y1:y2] asics[(0, p, s, a)] = block.matrix_rot90(-rotations[tile_id]) tile_id += 1 if not 'asic_focus' in locals(): asic_focus = asics[(0, p, s, a)].focus() else: assert asic_focus == asics[(0, p, s, a)].focus() # make the tiles dictionary for p in xrange(num_sections): tiles[(0,p)] = type(data)(flex.grid(asic_focus[0]*section_len,asic_focus[1]*2)) for s in xrange(section_len): tiles[(0,p)].matrix_paste_block_in_place(asics[(0,p,s,0)], i_row = s*asic_focus[0], i_column = 0) tiles[(0,p)].matrix_paste_block_in_place(asics[(0,p,s,1)], i_row = s*asic_focus[0], i_column = asic_focus[1]) tiles[(0,p)].reshape(flex.grid((section_len,asic_focus[0],asic_focus[1]*2))) # Write the cbf file destpath = os.path.splitext(filename)[0] + ".cbf" write_cspad_cbf(tiles, metro, metro_style, img['TIMESTAMP'], destpath, img['WAVELENGTH'], img['DISTANCE'])
from __future__ import division from __future__ import print_function # script to convert the output of refined_quadrants to a cbf header that # can be applied to a cspad cbf with cxi.apply_metrology # Note the hardcoded wavelength and distance. For development only. from dials.util.command_line import Importer importer = Importer(["refined_experiments.json"], check_format=False) experiment = importer.experiments[0] detector = experiment.detector from xfel.cftbx.detector.cspad_cbf_tbx import ( write_cspad_cbf, map_detector_to_basis_dict, ) metro = map_detector_to_basis_dict(detector) write_cspad_cbf(None, metro, "cbf", None, "quad_refined.def", 1.81587, 105, header_only=True) print("Done")
print "Write a CBF header from a SLAC metrology file. Parameters:" master_phil.show(attributes_level=2) return user_phil = [] for arg in args: if (os.path.isfile(arg)) : user_phil.append(libtbx.phil.parse("""metrology_file=\"%s\"""" % arg)) else : try : user_phil.append(libtbx.phil.parse(arg)) except RuntimeError, e : raise Sorry("Unrecognized argument '%s' (error: %s)" % (arg, str(e))) params = master_phil.fetch(sources=user_phil).extract() if (params.metrology_file is None) : master_phil.show() raise Usage("metrology_file must be defined (either metrology_file=XXX, or the file path alone).") assert params.plot is not None assert params.out is not None print params.metrology_file metro = read_slac_metrology(params.metrology_file, plot=params.plot) write_cspad_cbf(None, metro, 'cbf', None, params.out, None, 0, header_only=True) if (__name__ == "__main__") : args = sys.argv[1:] run(args)
asics[(0, p, s, a)] = block.matrix_rot90(-rotations[tile_id]) tile_id += 1 if not 'asic_focus' in locals(): asic_focus = asics[(0, p, s, a)].focus() else: assert asic_focus == asics[(0, p, s, a)].focus() # make the tiles dictionary for p in range(num_sections): tiles[(0, p)] = type(data)(flex.grid(asic_focus[0] * section_len, asic_focus[1] * 2)) for s in range(section_len): tiles[(0, p)].matrix_paste_block_in_place(asics[(0, p, s, 0)], i_row=s * asic_focus[0], i_column=0) tiles[(0, p)].matrix_paste_block_in_place(asics[(0, p, s, 1)], i_row=s * asic_focus[0], i_column=asic_focus[1]) tiles[(0, p)].reshape( flex.grid((section_len, asic_focus[0], asic_focus[1] * 2))) # Write the cbf file destpath = os.path.splitext(filename)[0] + ".cbf" write_cspad_cbf(tiles, metro, metro_style, img['TIMESTAMP'], destpath, img['WAVELENGTH'], img['DISTANCE'])
except RuntimeError, e: raise Sorry("Unrecognized argument '%s' (error: %s)" % (arg, str(e))) params = master_phil.fetch(sources=user_phil).extract() if (params.metrology_file is None): master_phil.show() raise Usage( "metrology_file must be defined (either metrology_file=XXX, or the file path alone)." ) assert params.plot is not None assert params.out is not None print params.metrology_file metro = read_slac_metrology(params.metrology_file, plot=params.plot) write_cspad_cbf(None, metro, 'cbf', None, params.out, None, 0, header_only=True) if (__name__ == "__main__"): args = sys.argv[1:] run(args)
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
from __future__ import division # script to convert the output of refined_quadrants to a cbf header that # can be applied to a cspad cbf with cxi.apply_metrology # Note the hardcoded wavelength and distance. For development only. from dials.util.command_line import Importer importer = Importer(['refined_experiments.json'], check_format=False) experiment = importer.experiments[0] detector = experiment.detector from xfel.cftbx.detector.cspad_cbf_tbx import write_cspad_cbf, map_detector_to_basis_dict metro = map_detector_to_basis_dict(detector) write_cspad_cbf(None, metro, 'cbf', None, 'quad_refined.def', 1.81587, 105, header_only=True) print "Done"
user_phil = [] for arg in sys.argv[1:]: if (os.path.isdir(arg)): user_phil.append( libtbx.phil.parse("""metrology_dir=\"%s\"""" % arg)) else: try: user_phil.append(libtbx.phil.parse(arg)) except RuntimeError, e: raise Sorry("Unrecognized argument '%s' (error: %s)" % (arg, str(e))) params = master_phil.fetch(sources=user_phil).extract() if (params.metrology_dir is None): master_phil.show() raise Usage( "metrology_dir must be defined (either metrology_dir=XXX, or the directory path alone)." ) assert params.out is not None metro_phil = metrology2phil(params.metrology_dir, verbose=True) write_cspad_cbf(None, metro_phil, 'calibdir', None, params.out, None, 0, header_only=True)
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