def run(args, imageset=None): # Parse input try: len(args) except Exception: params = args else: user_phil = [] for arg in args: if "=" in arg: try: user_phil.append(libtbx.phil.parse(arg)) except RuntimeError as e: raise Sorry("Unrecognized argument '%s' (error: %s)" % (arg, str(e))) else: try: user_phil.append( libtbx.phil.parse("""file_path=%s""" % arg)) except ValueError: raise Sorry("Unrecognized argument '%s'" % arg) params = master_phil.fetch(sources=user_phil).extract() if imageset is None: if (params.file_path is None or len(params.file_path) == 0 or not all(os.path.isfile(f) for f in params.file_path)): master_phil.show() raise Usage( "file_path must be defined (either file_path=XXX, or the path alone)." ) assert params.n_bins is not None assert params.verbose is not None assert params.output_bins is not None # Allow writing to a file instead of stdout if params.output_file is None: logger = sys.stdout else: logger = open(params.output_file, "w") logger.write("%s " % params.output_file) if params.show_plots: from matplotlib import pyplot as plt colormap = plt.cm.gist_ncar plt.gca().set_color_cycle( [colormap(i) for i in np.linspace(0, 0.9, len(params.file_path))]) if params.mask is not None: params.mask = easy_pickle.load(params.mask) if imageset is None: iterable = params.file_path def load_func(x): try: obj = dxtbx.datablock.DataBlockFactory.from_filenames( [x])[0].extract_imagesets()[0] except IndexError: try: obj = dxtbx.datablock.DataBlockFactory.from_json_file( x)[0].extract_imagesets()[0] except dxtbx.datablock.InvalidDataBlockError: obj = ExperimentListFactory.from_json_file(x)[0].imageset return obj else: iterable = [imageset] def load_func(x): return x # Iterate over each file provided for item in iterable: iset = load_func(item) n_images = len(iset) if params.image_number is None: if params.max_images is None: subiterable = range(n_images) else: subiterable = range(0, min(params.max_images, n_images)) else: subiterable = [params.image_number] for image_number in subiterable: beam = iset.get_beam(image_number) detector = iset.get_detector(image_number) s0 = col(beam.get_s0()) # Search the detector for the panel farthest from the beam. The # number of bins in the radial average will be equal to the # farthest point from the beam on the detector, in pixels, unless # overridden at the command line panel_res = [p.get_max_resolution_at_corners(s0) for p in detector] farthest_panel = detector[panel_res.index(min(panel_res))] size2, size1 = farthest_panel.get_image_size() corners = [(0, 0), (size1 - 1, 0), (0, size2 - 1), (size1 - 1, size2 - 1)] corners_lab = [ col(farthest_panel.get_pixel_lab_coord(c)) for c in corners ] corner_two_thetas = [ farthest_panel.get_two_theta_at_pixel(s0, c) for c in corners ] extent_two_theta = max(corner_two_thetas) max_corner = corners_lab[corner_two_thetas.index(extent_two_theta)] extent = int( math.ceil(max_corner.length() * math.sin(extent_two_theta) / max(farthest_panel.get_pixel_size()))) extent_two_theta *= 180 / math.pi if params.n_bins < extent: params.n_bins = extent # These arrays will store the radial average info sums = flex.double(params.n_bins) * 0 sums_sq = flex.double(params.n_bins) * 0 counts = flex.int(params.n_bins) * 0 all_data = iset[image_number] if not isinstance(all_data, tuple): all_data = (all_data, ) for tile, (panel, data) in enumerate(zip(detector, all_data)): if params.panel is not None and tile != params.panel: continue if params.mask is None: mask = flex.bool(flex.grid(data.focus()), True) else: mask = params.mask[tile] if hasattr(data, "as_double"): data = data.as_double() logger.flush() if params.verbose: logger.write("Average intensity tile %d: %9.3f\n" % (tile, flex.mean(data))) logger.write("N bins: %d\n" % params.n_bins) logger.flush() x1, y1, x2, y2 = ( 0, 0, panel.get_image_size()[1], panel.get_image_size()[0], ) bc = panel.get_beam_centre_px(beam.get_s0()) bc = int(round(bc[1])), int(round(bc[0])) # compute the average radial_average( data, mask, bc, sums, sums_sq, counts, panel.get_pixel_size()[0], panel.get_distance(), (x1, y1), (x2, y2), ) # average the results, avoiding division by zero results = sums.set_selected(counts <= 0, 0) results /= counts.set_selected(counts <= 0, 1).as_double() if params.median_filter_size is not None: logger.write( "WARNING, the median filter is not fully propagated to the variances\n" ) from scipy.ndimage.filters import median_filter results = flex.double( median_filter(results.as_numpy_array(), size=params.median_filter_size)) # calculate standard devations stddev_sel = ((sums_sq - sums * results) >= 0) & (counts > 0) std_devs = flex.double(len(sums), 0) std_devs.set_selected( stddev_sel, (sums_sq.select(stddev_sel) - sums.select(stddev_sel) * results.select(stddev_sel)) / counts.select(stddev_sel).as_double(), ) std_devs = flex.sqrt(std_devs) twotheta = (flex.double(range(len(results))) * extent_two_theta / params.n_bins) q_vals = (4 * math.pi * flex.sin(math.pi * twotheta / 360) / beam.get_wavelength()) # nlmbda = 2dsin(theta) resolution = flex.double(len(twotheta), 0) nonzero = twotheta > 0 resolution.set_selected( nonzero, beam.get_wavelength() / (2 * flex.asin( (math.pi / 180) * twotheta.select(nonzero) / 2)), ) if params.low_max_two_theta_limit is None: subset = results else: subset = results.select( twotheta >= params.low_max_two_theta_limit) max_result = flex.max(subset) if params.x_axis == "two_theta": xvals = twotheta max_x = twotheta[flex.first_index(results, max_result)] elif params.x_axis == "q": xvals = q_vals max_x = q_vals[flex.first_index(results, max_result)] elif params.x_axis == "resolution": xvals = resolution max_x = resolution[flex.first_index(results, max_result)] for i, r in enumerate(results): val = xvals[i] if params.output_bins and "%.3f" % r != "nan": # logger.write("%9.3f %9.3f\n"% (val,r)) #.xy format for Rex.cell. logger.write( "%9.3f %9.3f %9.3f\n" % (val, r, std_devs[i])) # .xye format for GSASII # logger.write("%.3f %.3f %.3f\n"%(val,r,ds[i])) # include calculated d spacings logger.write("Maximum %s: %f, value: %f\n" % (params.x_axis, max_x, max_result)) if params.show_plots: if params.plot_x_max is not None: results = results.select(xvals <= params.plot_x_max) xvals = xvals.select(xvals <= params.plot_x_max) if params.normalize: plt.plot( xvals.as_numpy_array(), (results / flex.max(results)).as_numpy_array(), "-", ) else: plt.plot(xvals.as_numpy_array(), results.as_numpy_array(), "-") if params.x_axis == "two_theta": plt.xlabel("2 theta") elif params.x_axis == "q": plt.xlabel("q") elif params.x_axis == "resolution": plt.xlabel("Resolution ($\\AA$)") plt.gca().set_xscale("log") plt.gca().invert_xaxis() plt.xlim(0, 50) plt.ylabel("Avg ADUs") if params.plot_y_max is not None: plt.ylim(0, params.plot_y_max) if params.show_plots: # plt.legend([os.path.basename(os.path.splitext(f)[0]) for f in params.file_path], ncol=2) plt.show() return xvals, results
def run (args, image = None): from xfel import radial_average from scitbx.array_family import flex import os, sys import dxtbx # Parse input try: n = len(args) except Exception: params = args else: user_phil = [] for arg in args: if (not "=" in arg): try : user_phil.append(libtbx.phil.parse("""file_path=%s""" % arg)) except ValueError: raise Sorry("Unrecognized argument '%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 image is None: if params.file_path is None or len(params.file_path) == 0 or not all([os.path.isfile(f) for f in params.file_path]): master_phil.show() raise Usage("file_path must be defined (either file_path=XXX, or the path alone).") assert params.n_bins is not None assert params.verbose is not None assert params.output_bins is not None # Allow writing to a file instead of stdout if params.output_file is None: logger = sys.stdout else: logger = open(params.output_file, 'w') logger.write("%s "%params.output_file) if params.show_plots: from matplotlib import pyplot as plt import numpy as np colormap = plt.cm.gist_ncar plt.gca().set_color_cycle([colormap(i) for i in np.linspace(0, 0.9, len(params.file_path))]) if params.mask is not None: params.mask = easy_pickle.load(params.mask) if image is None: iterable = params.file_path load_func = lambda x: dxtbx.load(x) else: iterable = [image] load_func = lambda x: x # Iterate over each file provided for item in iterable: img = load_func(item) try: n_images = img.get_num_images() subiterable = xrange(n_images) except AttributeError: n_images = None subiterable = [0] for image_number in subiterable: if n_images is None: beam = img.get_beam() detector = img.get_detector() else: beam = img.get_beam(image_number) detector = img.get_detector(image_number) s0 = col(beam.get_s0()) # Search the detector for the panel farthest from the beam. The number of bins in the radial average will be # equal to the farthest point from the beam on the detector, in pixels, unless overridden at the command line panel_res = [p.get_max_resolution_at_corners(s0) for p in detector] farthest_panel = detector[panel_res.index(min(panel_res))] size2, size1 = farthest_panel.get_image_size() corners = [(0,0), (size1-1,0), (0,size2-1), (size1-1,size2-1)] corners_lab = [col(farthest_panel.get_pixel_lab_coord(c)) for c in corners] corner_two_thetas = [farthest_panel.get_two_theta_at_pixel(s0, c) for c in corners] extent_two_theta = max(corner_two_thetas) max_corner = corners_lab[corner_two_thetas.index(extent_two_theta)] extent = int(math.ceil(max_corner.length()*math.sin(extent_two_theta)/max(farthest_panel.get_pixel_size()))) extent_two_theta *= 180/math.pi if params.n_bins < extent: params.n_bins = extent # These arrays will store the radial average info sums = flex.double(params.n_bins) * 0 sums_sq = flex.double(params.n_bins) * 0 counts = flex.int(params.n_bins) * 0 if n_images is None: all_data = img.get_raw_data() else: all_data = img.get_raw_data(image_number) if not isinstance(all_data, tuple): all_data = (all_data,) for tile, (panel, data) in enumerate(zip(detector, all_data)): if params.mask is None: mask = flex.bool(flex.grid(data.focus()), True) else: mask = params.mask[tile] if hasattr(data,"as_double"): data = data.as_double() logger.flush() if params.verbose: logger.write("Average intensity tile %d: %9.3f\n"%(tile, flex.mean(data))) logger.write("N bins: %d\n"%params.n_bins) logger.flush() x1,y1,x2,y2 = 0,0,panel.get_image_size()[1],panel.get_image_size()[0] bc = panel.get_beam_centre_px(beam.get_s0()) bc = int(round(bc[1])), int(round(bc[0])) # compute the average radial_average(data,mask,bc,sums,sums_sq,counts,panel.get_pixel_size()[0],panel.get_distance(), (x1,y1),(x2,y2)) # average the results, avoiding division by zero results = sums.set_selected(counts <= 0, 0) results /= counts.set_selected(counts <= 0, 1).as_double() if params.median_filter_size is not None: logger.write("WARNING, the median filter is not fully propogated to the variances\n") from scipy.ndimage.filters import median_filter results = flex.double(median_filter(results.as_numpy_array(), size = params.median_filter_size)) # calculate standard devations stddev_sel = ((sums_sq-sums*results) >= 0) & (counts > 0) std_devs = flex.double(len(sums), 0) std_devs.set_selected(stddev_sel, (sums_sq.select(stddev_sel)-sums.select(stddev_sel)* \ results.select(stddev_sel))/counts.select(stddev_sel).as_double()) std_devs = flex.sqrt(std_devs) twotheta = flex.double(xrange(len(results)))*extent_two_theta/params.n_bins q_vals = 4*math.pi*flex.sin(math.pi*twotheta/360)/beam.get_wavelength() if params.low_max_two_theta_limit is None: subset = results else: subset = results.select(twotheta >= params.low_max_two_theta_limit) max_result = flex.max(subset) if params.x_axis == 'two_theta': xvals = twotheta max_x = twotheta[flex.first_index(results, max_result)] elif params.x_axis == 'q': xvals = q_vals max_x = q_vals[flex.first_index(results, max_result)] for i in xrange(len(results)): val = xvals[i] if params.output_bins and "%.3f"%results[i] != "nan": #logger.write("%9.3f %9.3f\n"% (val,results[i])) #.xy format for Rex.cell. logger.write("%9.3f %9.3f %9.3f\n"%(val,results[i],std_devs[i])) #.xye format for GSASII #logger.write("%.3f %.3f %.3f\n"%(val,results[i],ds[i])) # include calculated d spacings logger.write("Maximum %s: %f, value: %f\n"%(params.x_axis, max_x, max_result)) if params.show_plots: if params.plot_x_max is not None: results = results.select(xvals <= params.plot_x_max) xvals = xvals.select(xvals <= params.plot_x_max) if params.normalize: plt.plot(xvals.as_numpy_array(),(results/flex.max(results)).as_numpy_array(),'-') else: plt.plot(xvals.as_numpy_array(),results.as_numpy_array(),'-') if params.x_axis == 'two_theta': plt.xlabel("2 theta") elif params.x_axis == 'q': plt.xlabel("q") plt.ylabel("Avg ADUs") if params.plot_y_max is not None: plt.ylim(0, params.plot_y_max) if params.show_plots: #plt.legend([os.path.basename(os.path.splitext(f)[0]) for f in params.file_path], ncol=2) plt.show() return xvals, results
logger.flush() if params.verbose: logger.write("Average intensity tile %d: %9.3f\n" % (tile, flex.mean(data))) logger.write("N bins: %d\n" % params.n_bins) logger.flush() x1, y1, x2, y2 = 0, 0, panel.get_image_size( )[1], panel.get_image_size()[0] bc = panel.get_beam_centre_px(beam.get_s0()) bc = int(round(bc[1])), int(round(bc[0])) # compute the average radial_average(data, mask, bc, sums, sums_sq, counts, panel.get_pixel_size()[0], panel.get_distance(), (x1, y1), (x2, y2)) # average the results, avoiding division by zero results = sums.set_selected(counts <= 0, 0) results /= counts.set_selected(counts <= 0, 1).as_double() # calculate standard devations std_devs = [ math.sqrt((sums_sq[i] - sums[i] * results[i]) / counts[i]) if counts[i] > 0 else 0 for i in xrange(len(sums)) ] xvals = flex.double(len(results)) max_twotheta = float('-inf')
if hasattr(data,"as_double"): data = data.as_double() logger.write("Average intensity: %9.3f\n"%flex.mean(data)) if params.verbose: logger.write("Generating average...tile:") logger.flush() for tile in xrange(len(the_tiles)//4): if params.verbose: logger.write(" %d"%tile) logger.flush() x1,y1,x2,y2 = get_tile_coords(the_tiles,tile) radial_average(data,bc,sums,sums_sq,counts,img.pixel_size,img.distance, (x1,y1),(x2,y2)) if params.verbose: logger.write(" Finishing...\n") # average, avoiding division by zero results = sums.set_selected(counts <= 0, 0) results /= counts.set_selected(counts <= 0, 1).as_double() # calculte standard devations std_devs = [math.sqrt((sums_sq[i]-sums[i]*results[i])/counts[i]) if counts[i] > 0 else 0 for i in xrange(len(sums))] xvals = flex.double(len(results)) max_twotheta = float('-inf') max_result = float('-inf')
def run(args, source_data=None): from xfel import radial_average from scitbx.array_family import flex from iotbx.detectors.cspad_detector_formats import reverse_timestamp from iotbx.detectors.cspad_detector_formats import detector_format_version as detector_format_function from spotfinder.applications.xfel import cxi_phil from iotbx.detectors.npy import NpyImage import os, sys from iotbx.detectors.npy import NpyImage user_phil = [] # TODO: replace this stuff with iotbx.phil.process_command_line_with_files # as soon as I can safely modify it for arg in args: if (not "=" in arg): try: user_phil.append(libtbx.phil.parse("""file_path=%s""" % arg)) except ValueError as e: raise Sorry("Unrecognized argument '%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.file_path is None or not os.path.isfile( params.file_path) and source_data is None: master_phil.show() raise Usage( "file_path must be defined (either file_path=XXX, or the path alone)." ) assert params.handedness is not None assert params.n_bins is not None assert params.verbose is not None assert params.output_bins is not None if source_data is None: from libtbx import easy_pickle source_data = easy_pickle.load(params.file_path) if params.output_file is None: logger = sys.stdout else: logger = open(params.output_file, 'w') logger.write("%s " % params.output_file) if not "DETECTOR_ADDRESS" in source_data: # legacy format; try to guess the address LCLS_detector_address = 'CxiDs1-0|Cspad-0' if "DISTANCE" in source_data and source_data["DISTANCE"] > 1000: # downstream CS-PAD detector station of CXI instrument LCLS_detector_address = 'CxiDsd-0|Cspad-0' else: LCLS_detector_address = source_data["DETECTOR_ADDRESS"] timesec = reverse_timestamp(source_data["TIMESTAMP"])[0] version_lookup = detector_format_function(LCLS_detector_address, timesec) args = [ "distl.detector_format_version=%s" % version_lookup, "viewer.powder_arcs.show=False", "viewer.powder_arcs.code=3n9c", ] horizons_phil = cxi_phil.cxi_versioned_extract(args).persist.commands img = NpyImage(params.file_path, source_data) img.readHeader(horizons_phil) img.translate_tiles(horizons_phil) if params.verbose: img.show_header() the_tiles = img.get_tile_manager( horizons_phil).effective_tiling_as_flex_int( reapply_peripheral_margin=False, encode_inactive_as_zeroes=True) if params.beam_x is None: params.beam_x = img.beamx / img.pixel_size if params.beam_y is None: params.beam_y = img.beamy / img.pixel_size if params.verbose: logger.write("I think the beam center is (%s,%s)\n" % (params.beam_x, params.beam_y)) bc = (int(params.beam_x), int(params.beam_y)) extent = int( math.ceil( max(distance((0, 0), bc), distance((img.size1, 0), bc), distance((0, img.size2), bc), distance((img.size1, img.size2), bc)))) if params.n_bins < extent: params.n_bins = extent extent_in_mm = extent * img.pixel_size extent_two_theta = math.atan(extent_in_mm / img.distance) * 180 / math.pi sums = flex.double(params.n_bins) * 0 sums_sq = flex.double(params.n_bins) * 0 counts = flex.int(params.n_bins) * 0 data = img.get_raw_data() if hasattr(data, "as_double"): data = data.as_double() logger.write("Average intensity: %9.3f\n" % flex.mean(data)) if params.verbose: logger.write("Generating average...tile:") logger.flush() for tile in xrange(len(the_tiles) // 4): if params.verbose: logger.write(" %d" % tile) logger.flush() x1, y1, x2, y2 = get_tile_coords(the_tiles, tile) radial_average(data, bc, sums, sums_sq, counts, img.pixel_size, img.distance, (x1, y1), (x2, y2)) if params.verbose: logger.write(" Finishing...\n") # average, avoiding division by zero results = sums.set_selected(counts <= 0, 0) results /= counts.set_selected(counts <= 0, 1).as_double() # calculte standard devations std_devs = [ math.sqrt((sums_sq[i] - sums[i] * results[i]) / counts[i]) if counts[i] > 0 else 0 for i in xrange(len(sums)) ] xvals = flex.double(len(results)) max_twotheta = float('-inf') max_result = float('-inf') for i in xrange(len(results)): twotheta = i * extent_two_theta / params.n_bins xvals[i] = twotheta if params.output_bins and "%.3f" % results[i] != "nan": #logger.write("%9.3f %9.3f\n"% (twotheta,results[i])) #.xy format for Rex.cell. logger.write( "%9.3f %9.3f %9.3f\n" % (twotheta, results[i], std_devs[i])) #.xye format for GSASII #logger.write("%.3f %.3f %.3f\n"%(twotheta,results[i],ds[i])) # include calculated d spacings if results[i] > max_result: max_twotheta = twotheta max_result = results[i] logger.write( "Maximum 2theta for %s, TS %s: %f, value: %f\n" % (params.file_path, source_data['TIMESTAMP'], max_twotheta, max_result)) if params.verbose: from pylab import scatter, show, xlabel, ylabel, ylim scatter(xvals, results) xlabel("2 theta") ylabel("Avg ADUs") if params.plot_y_max is not None: ylim(0, params.plot_y_max) show() return xvals, results
if hasattr(data, "as_double"): data = data.as_double() logger.write("Average intensity: %9.3f\n" % flex.mean(data)) if params.verbose: logger.write("Generating average...tile:") logger.flush() for tile in xrange(len(the_tiles) // 4): if params.verbose: logger.write(" %d" % tile) logger.flush() x1, y1, x2, y2 = get_tile_coords(the_tiles, tile) radial_average(data, bc, sums, sums_sq, counts, img.pixel_size, img.distance, (x1, y1), (x2, y2)) if params.verbose: logger.write(" Finishing...\n") # average, avoiding division by zero results = sums.set_selected(counts <= 0, 0) results /= counts.set_selected(counts <= 0, 1).as_double() # calculte standard devations std_devs = [ math.sqrt((sums_sq[i] - sums[i] * results[i]) / counts[i]) if counts[i] > 0 else 0 for i in xrange(len(sums)) ] xvals = flex.double(len(results))
for tile, (panel, data) in enumerate(zip(detector, all_data)): if hasattr(data,"as_double"): data = data.as_double() logger.flush() if params.verbose: logger.write("Average intensity tile %d: %9.3f\n"%(tile, flex.mean(data))) logger.flush() x1,y1,x2,y2 = 0,0,panel.get_image_size()[1],panel.get_image_size()[0] bc = panel.get_beam_centre_px(beam.get_s0()) bc = int(round(bc[1])), int(round(bc[0])) # compute the average radial_average(data,bc,sums,sums_sq,counts,panel.get_pixel_size()[0],panel.get_distance(), (x1,y1),(x2,y2)) # average the results, avoiding division by zero results = sums.set_selected(counts <= 0, 0) results /= counts.set_selected(counts <= 0, 1).as_double() # calculate standard devations std_devs = [math.sqrt((sums_sq[i]-sums[i]*results[i])/counts[i]) if counts[i] > 0 else 0 for i in xrange(len(sums))] xvals = flex.double(len(results)) max_twotheta = float('-inf') max_result = float('-inf') for i in xrange(len(results)): twotheta = i * extent_two_theta/params.n_bins