Exemple #1
0
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
Exemple #2
0
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
Exemple #3
0
            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
Exemple #6
0
    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