Exemplo n.º 1
0
def data_geo(ntest):
    """Returns test data numpy array and geometry object
    """
    from time import time
    from PSCalib.NDArrIO import save_txt, load_txt
    from PSCalib.GeometryAccess import GeometryAccess

    dir = '/reg/g/psdm/detector/alignment/cspad/calib-cxi-camera2-2016-02-05'
    #fname_nda = '%s/nda-water-ring-cxij4716-r0022-e000001-CxiDs2-0-Cspad-0-ave.txt' % dir
    fname_nda = '%s/nda-water-ring-cxij4716-r0022-e014636-CxiDs2-0-Cspad-0-ave.txt' % dir
    fname_geo = '%s/calib/CsPad::CalibV1/CxiDs2.0:Cspad.0/geometry/geo-cxi01516-2016-02-18-Ag-behenate-tuned.data' % dir
    #fname_geo = '%s/geo-cxi02416-r0010-2016-03-11.txt' % dir
    fname_gain = '%s/calib/CsPad::CalibV1/CxiDs2.0:Cspad.0/pixel_gain/cxi01516-r0016-2016-02-18-FeKalpha.data' % dir

    # load n-d array with averaged water ring
    arr = load_txt(fname_nda)
    #arr *= load_txt(fname_gain)
    #print_ndarr(arr,'water ring')
    arr.shape = (arr.size, )  # (32*185*388,)

    # retrieve geometry
    t0_sec = time()
    geo = GeometryAccess(fname_geo)
    geo.move_geo('CSPAD:V1', 0, 1600, 0, 0)
    geo.move_geo('QUAD:V1', 2, -100, 0, 0)
    #geo.get_geo('QUAD:V1', 3).print_geo()
    print 'Time to load geometry %.3f sec from file\n%s' % (time() - t0_sec,
                                                            fname_geo)

    return arr, geo
Exemplo n.º 2
0
    def test_pnccd_vs_geometry_access(self):

        # ---- get the geometry Mikhail-style
        try:
            from PSCalib.GeometryAccess import GeometryAccess
            ga = GeometryAccess('ref_files/pnccd.data')
            xyz_old = ga.get_pixel_coords()

        except:
            # if that don't work, load a pre-saved answer
            print 'could not use GeometryAccess, loading saved xyz'
            xyz_old = np.load('ref_files/pnccd_saved.npy')

        xyz_old = np.rollaxis(np.array(xyz_old), 0, 6)  # send 0 --> end
        xyz_old = np.squeeze(xyz_old)

        geom = camera.CompoundAreaCamera.from_psana_file(
            'ref_files/pnccd.data')
        xyz_new = np.squeeze(geom.xyz)

        assert xyz_new.shape == xyz_old.shape, 'shape mismatch'

        err = np.sum(np.abs(xyz_new - xyz_old)) / float(
            np.product(xyz_new.shape))
        print 'Mean Absolute Error: %f um / px' % err
        num_more_than_1px_err = np.sum(np.abs(xyz_new - xyz_old) > 75.0)

        assert err < 10.0, 'error greater than 10um avg per px (%f)' % err
        assert num_more_than_1px_err < 7500, '>7500 pix w err > 1 px'
Exemplo n.º 3
0
    def test_xyz_vs_old_implementation(self):

        # ---- get the geometry Mikhail-style
        try:
            from PSCalib.GeometryAccess import GeometryAccess
            ga = GeometryAccess('ref_files/refgeom_psana.data')
            xyz_old = ga.get_pixel_coords()

        except:
            # if that don't work, load a pre-saved answer
            print 'could not use GeometryAccess, loading saved xyz'
            xyz_old = np.load('ref_files/GA_saved_1-end.npy')

        # some np-foo to move the 3-d x,y,z axis from first dim to last
        xyz_old = np.rollaxis(np.array(xyz_old), 0, 7)  # send 0 --> 7
        xyz_old = np.squeeze(xyz_old)

        geom = camera.CompoundCamera.from_psana_file(
            'ref_files/refgeom_psana.data')
        xyz_new = np.squeeze(geom.xyz)

        assert xyz_new.shape == xyz_old.shape, 'shape mismatch'

        err = np.sum(np.abs(xyz_new - xyz_old)) / float(
            np.product(xyz_new.shape))
        print 'Mean Absolute Error: %f um / px' % err
        num_more_than_1px_err = np.sum(np.abs(xyz_new - xyz_old) > 109.92)

        assert err < 10.0, 'error greater than 10um avg per px (%f)' % err
        assert num_more_than_1px_err < 7500, '>7500 pix w err > 1 px'
Exemplo n.º 4
0
 def setupRadialBackground(self):
     self.findPsanaGeometry()
     if self.calibFile is not None:
         self.geo = GeometryAccess(self.calibPath+'/'+self.calibFile)
         self.xarr, self.yarr, self.zarr = self.geo.get_pixel_coords()
         self.iX, self.iY = self.geo.get_pixel_coord_indexes()
         self.mask = self.geo.get_pixel_mask(mbits=0377)  # mask for 2x1 edges, two central columns, and unbound pixels with their neighbours
         self.rb = RadialBkgd(self.xarr, self.yarr, mask=self.mask, radedges=None, nradbins=100, phiedges=(0, 360), nphibins=1)
     else:
         self.rb = None
Exemplo n.º 5
0
    def __init__(self, geom_file):
        """
        Initialize instance of Detector class.
        
        :param geom_file: path to *-end.data geometry file
        """

        from PSCalib.GeometryAccess import GeometryAccess
        self._geometry = GeometryAccess(geom_file, 0)
        self._compute_pixel_index_map()
Exemplo n.º 6
0
    def on_but_roi_convert(self):

        self.setStatus(1, 'Convert image to ndarray')

        mcbits = self.sensor_mask_cbits.value()
        gfname = self.fname_geometry.value()
        ifname = self.fname_roi_mask_img.value()
        ofname = self.fname_roi_mask_nda.value()
        tfname = self.fname_roi_mask_nda_tst.value()

        msg = '\n  Convert ROI mask image: %s\n      to ndarray: %s\n    using geometry: %s' % \
             ( ifname, ofname, gfname )
        logger.info(msg, __name__)

        geometry = GeometryAccess(gfname, 0)
        iX, iY = geometry.get_pixel_coord_indexes()
        msg = 'Pixel index array iX, iY shapes: %s,  %s' % (str(
            iX.shape), str(iY.shape))
        logger.info(msg, __name__)

        ifext = os.path.splitext(ifname)[1]
        ofext = os.path.splitext(ofname)[1]

        mask_roi = np.load(ifname) if ifext == '.npy' else np.loadtxt(
            ifname, dtype=np.uint16)

        mask_nda = np.array([mask_roi[r, c]
                             for r, c in zip(iX, iY)])  # 155 msec
        if mcbits: mask_nda *= geometry.get_pixel_mask(mbits=mcbits)

        img_mask_test = img_from_pixel_arrays(iX, iY, W=mask_nda)

        if ofext == '.npy': np.save(ofname, mask_nda)
        else:
            mask_nda.shape = [iX.size / iX.shape[-1], iX.shape[-1]]
            logger.info(
                'Mask ndarray is re-shape for saving in txt to 2-d: %s' %
                str(mask_nda.shape), __name__)
            np.savetxt(ofname, mask_nda, fmt='%d', delimiter=' ')

        logger.info('Mask ndarray is saved in the file %s' % ofname, __name__)

        self.setStatus(1, 'Test: reconstruct image from mask ndarray...')

        tfext = os.path.splitext(tfname)[1]

        if tfext == '.npy': np.save(tfname, img_mask_test)
        else: np.savetxt(tfname, img_mask_test, fmt='%d', delimiter=' ')
        logger.info(
            'Test-image generated from mask ndarray is saved in file %s' %
            tfname, __name__)

        self.setStatus(0)
Exemplo n.º 7
0
def read_slac_metrology(path = None, geometry = None, plot=False, include_asic_offset=False):
  if path is None and geometry is None:
    raise Sorry("Need to provide a geometry object or a path to a geometry file")

  if path is not None and geometry is not None:
    raise Sorry("Cannot provide a geometry object and a geometry file. Ambiguous")

  if geometry is None:
    try:
      from PSCalib.GeometryAccess import GeometryAccess
      geometry = GeometryAccess(path)
    except Exception, e:
      raise Sorry("Can't parse this metrology file")
Exemplo n.º 8
0
    def reco_image_from_ndarray(self, gfname, afname):

        #mcbits = self.sensor_mask_cbits.value()

        msg = 'Reconstruct image from\n      geometry: %s\n     and ndarray: %s' % \
             ( gfname, afname )
        logger.info(msg, __name__)

        geometry = GeometryAccess(gfname, 0)
        iX, iY = geometry.get_pixel_coord_indexes()

        afext = '' if afname is None else os.path.splitext(afname)[1]

        nda = np.ones(iX.shape, dtype=np.uint16) if afname is None else \
              np.load(afname) if afext == '.npy' else \
              np.loadtxt(afname) #, dtype=np.uint16)
        nda.shape = iX.shape

        #if mcbits :  nda *= geometry.get_pixel_mask(mbits=mcbits)

        return img_from_pixel_arrays(iX, iY, W=nda)
Exemplo n.º 9
0
    def initialize(self, geom, run_num=0):
        """
        Initialize the detector as pnccd
        :param geom: The pnccd .data file which characterize the geometry profile.
        :param run_num: The run_num containing the background, rms and gain and the other
                        pixel pixel properties.
        :return:  None
        """

        # Redirect the output stream
        old_stdout = sys.stdout
        f = six.StringIO()
        # f = open('Detector_initialization.log', 'w')
        sys.stdout = f

        ###########################################################################################
        # Initialize the geometry configuration
        ############################################################################################
        self.geometry = GeometryAccess(geom, 0o377)
        self.run_num = run_num

        # Set coordinate in real space
        temp = self.geometry.get_pixel_coords()
        temp_index = self.geometry.get_pixel_coord_indexes()

        self.panel_num = temp[0].shape[1] * temp[0].shape[2]
        self.distance = temp[2][0, 0, 0, 0, 0] * 1e-6  # Convert to m

        self.pixel_position = np.zeros(
            (self.panel_num, temp[0].shape[3], temp[0].shape[4], 3))
        self.pixel_index_map = np.zeros(
            (self.panel_num, temp[0].shape[3], temp[0].shape[4], 2))

        for l in range(temp[0].shape[1]):
            for m in range(temp[0].shape[2]):
                for n in range(3):
                    self.pixel_position[m + l * temp[0].shape[2], :, :,
                                        n] = temp[n][0, l, m]
                for n in range(2):
                    self.pixel_index_map[m + l * temp[0].shape[2], :, :,
                                         n] = temp_index[n][0, l, m]

        self.pixel_index_map = self.pixel_index_map.astype(np.int64)

        # Get the range of the pixel index
        self.detector_pixel_num_x = np.max(self.pixel_index_map[:, :, :,
                                                                0]) + 1
        self.detector_pixel_num_y = np.max(self.pixel_index_map[:, :, :,
                                                                1]) + 1

        self.panel_pixel_num_x = np.array([
            self.pixel_index_map.shape[1],
        ] * self.panel_num)
        self.panel_pixel_num_y = np.array([
            self.pixel_index_map.shape[2],
        ] * self.panel_num)
        self.pixel_num_total = np.sum(
            np.multiply(self.panel_pixel_num_x, self.panel_pixel_num_y))

        tmp = float(self.geometry.get_pixel_scale_size() *
                    1e-6)  # Convert to m
        self.pixel_width = np.ones((self.panel_num, self.panel_pixel_num_x[0],
                                    self.panel_pixel_num_y[0])) * tmp
        self.pixel_height = np.ones((self.panel_num, self.panel_pixel_num_x[0],
                                     self.panel_pixel_num_y[0])) * tmp

        # Calculate the pixel area
        self.pixel_area = np.multiply(self.pixel_height, self.pixel_width)

        ###########################################################################################
        # Initialize the pixel effects
        ###########################################################################################
        # first we should parse the path
        parsed_path = geom.split('/')
        source = parsed_path[-3]

        if six.PY2:
            cbase = CalibParsBasePnccdV1()
            calibdir = '/'.join(parsed_path[:-4])
            group = parsed_path[-4]
            pbits = 255
            gcp = GenericCalibPars(cbase, calibdir, group, source, run_num,
                                   pbits)

            self._pedestals = gcp.pedestals()
            self._pixel_rms = gcp.pixel_rms()
            self._pixel_mask = gcp.pixel_mask()
            self._pixel_bkgd = gcp.pixel_bkgd()
            self._pixel_status = gcp.pixel_status()
            self._pixel_gain = gcp.pixel_gain()
        else:
            self.det = "pnccd_000" + source[-1]
            self.exp = parsed_path[-5]

            self._pedestals = None
            self._pixel_rms = None
            self._pixel_mask = None
            self._pixel_bkgd = None
            self._pixel_status = None
            self._pixel_gain = None

        # Redirect the output stream
        sys.stdout = old_stdout
    except IOError:
      # See if it's a json file
      from dxtbx.model.experiment_list import ExperimentListFactory
      try:
        experiments = ExperimentListFactory.from_json_file(params.metrology)
        assert len(experiments) == 1
        detector = experiments[0].detector
      except Exception as e:
        detector = None

    if detector is None:
      # see if it's a SLAC geometry file
      from scitbx import matrix
      try:
        from PSCalib.GeometryAccess import GeometryAccess
        geometry = GeometryAccess(params.metrology)
      except Exception as e:
        geometry = None

      if geometry is None:
        # see if this is a Ginn metrology file (see Helen Ginn et. al. (2015), Acta D Cryst)
        panels = []
        for line in open(params.metrology).readlines():
          if len(line) > 0 and line[0] != '#' and len(line.strip().split()) == 10:
            panels.append(line.strip())

        if len(panels) != 64:
          raise Sorry("Can't parse this metrology file")

        print "Ginn metrology file"
        for panel_id, panel in enumerate(panels):
Exemplo n.º 11
0
    def initialize(self, geom, run_num=0, cframe=0):
        """
        Initialize the detector
        :param geom: The *-end.data file which characterizes the geometry profile.
        :param run_num: The run_num containing the background, rms and gain and the other
                        pixel pixel properties.
        :param cframe: The desired coordinate frame, 0 for psana and 1 for lab conventions.
        :return:  None
        """
        # Redirect the output stream
        old_stdout = sys.stdout
        f = six.StringIO()
        # f = open('Detector_initialization.log', 'w')
        sys.stdout = f

        ###########################################################################################
        # Initialize the geometry configuration
        ############################################################################################
        self.geometry = GeometryAccess(geom, cframe=cframe)
        self.run_num = run_num

        # Set coordinate in real space (convert to m)
        temp = [
            xp.asarray(t) * 1e-6
            for t in self.geometry.get_pixel_coords(cframe=cframe)
        ]
        temp_index = [
            xp.asarray(t)
            for t in self.geometry.get_pixel_coord_indexes(cframe=cframe)
        ]

        self.panel_num = np.prod(temp[0].shape[:-2])
        self._distance = float(temp[2].mean())

        self._shape = (self.panel_num, temp[0].shape[-2], temp[0].shape[-1])
        self.pixel_position = xp.zeros(self._shape + (3, ))
        self.pixel_index_map = xp.zeros(self._shape + (2, ))

        for n in range(3):
            self.pixel_position[..., n] = temp[n].reshape(self._shape)
        for n in range(2):
            self.pixel_index_map[..., n] = temp_index[n].reshape(self._shape)

        self.pixel_index_map = self.pixel_index_map.astype(xp.int64)

        # Get the range of the pixel index
        self.detector_pixel_num_x = asnumpy(
            xp.max(self.pixel_index_map[..., 0]) + 1)
        self.detector_pixel_num_y = asnumpy(
            xp.max(self.pixel_index_map[..., 1]) + 1)

        self.panel_pixel_num_x = np.array([
            self.pixel_index_map.shape[1],
        ] * self.panel_num)
        self.panel_pixel_num_y = np.array([
            self.pixel_index_map.shape[2],
        ] * self.panel_num)
        self.pixel_num_total = np.sum(
            np.multiply(self.panel_pixel_num_x, self.panel_pixel_num_y))

        tmp = float(self.geometry.get_pixel_scale_size() *
                    1e-6)  # Convert to m
        self.pixel_width = xp.ones((self.panel_num, self.panel_pixel_num_x[0],
                                    self.panel_pixel_num_y[0])) * tmp
        self.pixel_height = xp.ones((self.panel_num, self.panel_pixel_num_x[0],
                                     self.panel_pixel_num_y[0])) * tmp

        # Calculate the pixel area
        self.pixel_area = xp.multiply(self.pixel_height, self.pixel_width)

        ###########################################################################################
        # Initialize the pixel effects
        ###########################################################################################
        # first we should parse the path
        parsed_path = geom.split('/')
        self.exp = parsed_path[-5]
        if self.exp == 'calib':
            self.exp = parsed_path[-6]
        self.group = parsed_path[-4]
        self.source = parsed_path[-3]

        self._pedestals = None
        self._pixel_rms = None
        self._pixel_mask = None
        self._pixel_bkgd = None
        self._pixel_status = None
        self._pixel_gain = None

        if six.PY2:
            try:
                cbase = self._get_cbase()
                self.calibdir = '/'.join(parsed_path[:-4])
                pbits = 255
                gcp = GenericCalibPars(cbase, self.calibdir, self.group,
                                       self.source, run_num, pbits)

                self._pedestals = gcp.pedestals()
                self._pixel_rms = gcp.pixel_rms()
                self._pixel_mask = gcp.pixel_mask()
                self._pixel_bkgd = gcp.pixel_bkgd()
                self._pixel_status = gcp.pixel_status()
                self._pixel_gain = gcp.pixel_gain()
            except NotImplementedError:
                # No GenericCalibPars information.
                pass
        else:
            try:
                self.det = self._get_det_id(self.group)
            except NotImplementedError:
                # No GenericCalibPars information.
                self.det = None

        # Redirect the output stream
        sys.stdout = old_stdout
Exemplo n.º 12
0
def read_slac_metrology(path = None, geometry = None, plot=False, include_asic_offset=False):
  if path is None and geometry is None:
    raise Sorry("Need to provide a geometry object or a path to a geometry file")

  if path is not None and geometry is not None:
    raise Sorry("Cannot provide a geometry object and a geometry file. Ambiguous")

  if geometry is None:
    try:
      from PSCalib.GeometryAccess import GeometryAccess
      geometry = GeometryAccess(path)
    except Exception as e:
      raise Sorry("Can't parse this metrology file")

  metro = {}
  pixel_size = geometry.get_pixel_scale_size()/1000
  null_ori = matrix.col((0,0,1)).axis_and_angle_as_unit_quaternion(0, deg=True)

  # collapse any transformations above those of the quadrants into one X/Y offset,
  # but don't keep Z transformations, as those come from the XTC stream
  root = geometry.get_top_geo()
  root_basis = basis_from_geo(root, use_z=False)
  while len(root.get_list_of_children()) != 4 and len(root.get_list_of_children()) != 32:
    assert len(root.get_list_of_children()) == 1
    root = root.get_list_of_children()[0]
    root_basis *= basis_from_geo(root, use_z=False)

  metro[(0,)] = root_basis

  def add_sensor(quad_id, sensor_id, sensor):
    metro[(0,quad_id,sensor_id)] = basis_from_geo(sensor)

    x, y, z = sensor.get_pixel_coords()
    x/=1000; y/=1000; z/=1000
    assert x.shape == y.shape == z.shape
    sensor_px_slow = x.shape[0]
    sensor_px_fast = x.shape[1]
    assert sensor_px_fast % 2 == 0

    a0ul = sul = matrix.col((x[0,0],y[0,0],z[0,0]))
    a1ur = sur = matrix.col((x[0,sensor_px_fast-1],y[0,sensor_px_fast-1],z[0,sensor_px_fast-1]))
    a1lr = slr = matrix.col((x[sensor_px_slow-1,sensor_px_fast-1],y[sensor_px_slow-1,sensor_px_fast-1],z[sensor_px_slow-1,sensor_px_fast-1]))
    a0ll = sll = matrix.col((x[sensor_px_slow-1,0],y[sensor_px_slow-1,0],z[sensor_px_slow-1,0]))

    a0ur = matrix.col((x[0,sensor_px_fast//2-1],y[0,sensor_px_fast//2-1],z[0,sensor_px_fast//2-1]))
    a0lr = matrix.col((x[sensor_px_slow-1,sensor_px_fast//2-1],y[sensor_px_slow-1,sensor_px_fast//2-1],z[sensor_px_slow-1,sensor_px_fast//2-1]))

    a1ul = matrix.col((x[0,sensor_px_fast//2],y[0,sensor_px_fast//2],z[0,sensor_px_fast//2]))
    a1ll = matrix.col((x[sensor_px_slow-1,sensor_px_fast//2],y[sensor_px_slow-1,sensor_px_fast//2],z[sensor_px_slow-1,sensor_px_fast//2]))

    sensor_center = center([sul,sur,slr,sll])
    asic0_center = center([a0ul,a0ur,a0lr,a0ll])
    asic1_center = center([a1ul,a1ur,a1lr,a1ll])

    asic_trans0 = (asic0_center-sensor_center).length()
    asic_trans1 = (asic1_center-sensor_center).length()

    if include_asic_offset:
      rotated_ori = matrix.col((1,0,0)).axis_and_angle_as_unit_quaternion(180.0, deg=True)
      offset_fast = -pixel_size*((sensor_px_fast) / 4) # 4 because sensor_px_fast is for sensor
      offset_slow = +pixel_size*((sensor_px_slow) / 2) # Sensor is divided into 2 only in fast direction
      metro[(0,quad_id,sensor_id,0)] = basis(orientation=rotated_ori,translation=matrix.col((-asic_trans0,0,0)))
      metro[(0,quad_id,sensor_id,1)] = basis(orientation=rotated_ori,translation=matrix.col((+asic_trans1,0,0)))
      metro[(0,quad_id,sensor_id,0)].translation += matrix.col((offset_fast, offset_slow, 0))
      metro[(0,quad_id,sensor_id,1)].translation += matrix.col((offset_fast, offset_slow, 0))
    else:
      metro[(0,quad_id,sensor_id,0)] = basis(orientation=null_ori,translation=matrix.col((-asic_trans0,0,0)))
      metro[(0,quad_id,sensor_id,1)] = basis(orientation=null_ori,translation=matrix.col((+asic_trans1,0,0)))

  if len(root.get_list_of_children()) == 4:
    for quad_id, quad in enumerate(root.get_list_of_children()):
      metro[(0,quad_id)] = basis_from_geo(quad)
      for sensor_id, sensor in enumerate(quad.get_list_of_children()):
        add_sensor(quad_id, sensor_id, sensor)
  elif len(root.get_list_of_children()) == 32:
    for quad_id in range(4):
      metro[(0,quad_id)] = basis(orientation = null_ori, translation = matrix.col((0,0,0)))
      sensors = root.get_list_of_children()
      for sensor_id in range(8):
        add_sensor(quad_id, sensor_id, sensors[quad_id*4+sensor_id])
  else:
    assert False

  return metro