Esempio n. 1
0
    def __init__(self, experiment, diffraction_rings=None, log_scale=False):
        self.experiment = experiment
        self.center = self.experiment.det.geometry.point_coord_indexes((0, 0))
        # ! Wavenumber definition != beam's.
        self.wavenumber = np.linalg.norm(self.experiment.beam.get_wavevector())
        self.distance = self.experiment.det.distance

        pixel_width = asnumpy(self.experiment.det.pixel_width)
        # Cupy doesn't have median yet.
        self.pix_width = np.median(pixel_width)

        recidet = ReciprocalDetector(self.experiment.det, self.experiment.beam)
        self.q_max = asnumpy(
            np.min((  # Max inscribed radius
                xp.max(recidet.pixel_position_reciprocal[..., 1]),
                -xp.min(recidet.pixel_position_reciprocal[..., 1]),
                xp.max(recidet.pixel_position_reciprocal[..., 0]),
                -xp.min(recidet.pixel_position_reciprocal[..., 0]))))

        self._auto_rings = False
        if diffraction_rings is not None:
            if diffraction_rings.lower() == "auto":
                self._auto_rings = True
            else:
                raise ValueError(
                    "Unrecognized value '{}' for argument diffraction_rings"
                    "".format(diffraction_rings))

        if log_scale:
            self._norm = LogNorm()
        else:
            self._norm = None
    def get_reciprocal_mesh(self, voxel_number_1d):
        """
        Get the proper reciprocal mesh.

        :param voxel_number_1d: The voxel number along 1 dimension.
        :return: The reciprocal mesh, voxel length.
        """
        dist_max = xp.max(self.pixel_distance_reciprocal)
        return pg.get_reciprocal_mesh(voxel_number_1d, dist_max)
    def preferred_reciprocal_mesh_number(self, wave_vector):
        """
        If one want to put the diffraction pattern into 3D reciprocal space, then one needs to
        select a proper voxel number for a proper voxel length for the reciprocal space.
        This function gives a reasonable estimation of this length and voxel number

        :param wave_vector: The wavevector of in this experiment.
        :return: The reciprocal mesh number along 1 dimension
        """
        """ Return the prefered the reciprocal voxel grid number along 1 dimension. """
        voxel_length = self.preferred_voxel_length(wave_vector)
        reciprocal_space_range = xp.max(self.pixel_distance_reciprocal)
        # The voxel number along 1 dimension is 2*voxel_half_num_1d+1
        voxel_half_num_1d = int(
            xp.floor_divide(reciprocal_space_range, voxel_length) + 1)

        voxel_num_1d = int(2 * voxel_half_num_1d + 1)
        return voxel_num_1d
Esempio n. 4
0
    def initialize(self, geom, beam):
        """
        Initialize the detector with user defined parameters
        :param geom: The dictionary containing all the necessary information to initialized the
                    detector.
        :param beam: The beam object
        :return: None
        """
        """
        Doc:
            To use this class, the user has to provide the necessary information to initialize
             the detector.
            All the necessary entries are listed in the example notebook.
        """

        # 'detector distance': detector distance in (m)

        ##########################################################################################
        # Extract necessary information
        ##########################################################################################

        # Define the hierarchy system. For simplicity, we only use two-layer structure.
        for key in {'panel number', 'panel pixel num x', 'panel pixel num y'}:
            if key not in geom:
                raise KeyError("Missing required '{}' key.".format(key))
        self.panel_num = int(geom['panel number'])
        self.panel_pixel_num_x = int(geom['panel pixel num x'])
        self.panel_pixel_num_y = int(geom['panel pixel num y'])
        self._shape = (self.panel_num, self.panel_pixel_num_x,
                       self.panel_pixel_num_y)

        # Define all properties the detector should have
        self._distance = None
        if 'pixel center z' in geom:
            if 'detector distance' in geom:
                raise ValueError("Please provide one of "
                                 "'pixel center z' or 'detector distance'.")
            self.center_z = xp.asarray(geom['pixel center z'],
                                       dtype=xp.float64)
            self._distance = float(self.center_z.mean())
        else:
            if 'detector distance' not in geom:
                KeyError("Missing required 'detector distance' key.")
            self._distance = float(geom['detector distance'])
            self.center_z = self._distance * xp.ones(self._shape,
                                                     dtype=xp.float64)

        # Below: [panel number, pixel num x, pixel num y]  in (m)
        # Change dtype and make numpy/cupy array
        self.pixel_width = xp.asarray(geom['pixel width'], dtype=xp.float64)
        self.pixel_height = xp.asarray(geom['pixel height'], dtype=xp.float64)
        self.center_x = xp.asarray(geom['pixel center x'], dtype=xp.float64)
        self.center_y = xp.asarray(geom['pixel center y'], dtype=xp.float64)
        self.orientation = np.array([0, 0, 1])

        # construct the the pixel position array
        self.pixel_position = xp.zeros(self._shape + (3, ))
        self.pixel_position[..., 0] = self.center_x
        self.pixel_position[..., 1] = self.center_y
        self.pixel_position[..., 2] = self.center_z

        # Pixel map
        if 'pixel map' in geom:
            # [panel number, pixel num x, pixel num y]
            self.pixel_index_map = xp.asarray(geom['pixel map'],
                                              dtype=xp.int64)
            # Detector pixel number info
            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)

            # Panel pixel number info
            # number of pixels in each panel in x/y direction
            self.panel_pixel_num_x = self.pixel_index_map.shape[1]
            self.panel_pixel_num_y = self.pixel_index_map.shape[2]

        # total number of pixels (px*py)
        self.pixel_num_total = np.prod(self._shape)

        ###########################################################################################
        # Do necessary calculation to finishes the initialization
        ###########################################################################################
        # self.geometry currently only work for the pre-defined detectors
        self.geometry = geom

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

        # Get reciprocal space configurations and corrections.
        self.initialize_pixels_with_beam(beam=beam)

        ##########################################################################################
        # Do necessary calculation to finishes the initialization
        ##########################################################################################
        # Detector effects
        if 'pedestal' in geom:
            self._pedestal = xp.asarray(geom['pedestal'], dtype=xp.float64)
        else:
            self._pedestal = xp.zeros((self.panel_num, self.panel_pixel_num_x,
                                       self.panel_pixel_num_y))

        if 'pixel rms' in geom:
            self._pixel_rms = xp.asarray(geom['pixel rms'], dtype=xp.float64)
        else:
            self._pixel_rms = xp.zeros((self.panel_num, self.panel_pixel_num_x,
                                        self.panel_pixel_num_y))

        if 'pixel bkgd' in geom:
            self._pixel_bkgd = xp.asarray(geom['pixel bkgd'], dtype=xp.float64)
        else:
            self._pixel_bkgd = xp.zeros(
                (self.panel_num, self.panel_pixel_num_x,
                 self.panel_pixel_num_y))

        if 'pixel status' in geom:
            self._pixel_status = xp.asarray(geom['pixel status'],
                                            dtype=xp.float64)
        else:
            self._pixel_status = xp.zeros(
                (self.panel_num, self.panel_pixel_num_x,
                 self.panel_pixel_num_y))

        if 'pixel mask' in geom:
            self._pixel_mask = xp.asarray(geom['pixel mask'], dtype=xp.float64)
        else:
            self._pixel_mask = xp.zeros(
                (self.panel_num, self.panel_pixel_num_x,
                 self.panel_pixel_num_y))

        if 'pixel gain' in geom:
            self._pixel_gain = xp.asarray(geom['pixel gain'], dtype=xp.float64)
        else:
            self._pixel_gain = xp.ones((self.panel_num, self.panel_pixel_num_x,
                                        self.panel_pixel_num_y))
Esempio n. 5
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
Esempio n. 6
0
    def __init__(self, N_pixel, det_size, det_distance, beam=None):
        """
        Initialize the detector
        :param N_pixel: Number of pixels per dimension.
        :param det_size: Length of detector sides (m).
        :param det_distance: Sample-Detector distance (m).
        """
        super(SimpleSquareDetector, self).__init__()

        ar = xp.arange(N_pixel)
        sep = float(det_size) / N_pixel
        x = -det_size / 2 + sep / 2 + ar * sep
        y = -det_size / 2 + sep / 2 + ar * sep
        X, Y = xp.meshgrid(x, y, indexing='xy')
        Xar, Yar = xp.meshgrid(ar, ar, indexing='xy')

        self.panel_num = 1
        self.panel_pixel_num_x = N_pixel
        self.panel_pixel_num_y = N_pixel
        self._shape = (1, N_pixel, N_pixel)

        # Define all properties the detector should have
        self._distance = det_distance
        self.center_z = self._distance * xp.ones(self._shape, dtype=xp.float64)

        p_center_x = xp.stack((X, ))
        p_center_y = xp.stack((Y, ))
        self.pixel_width = sep * xp.ones(self._shape, dtype=xp.float64)
        self.pixel_height = sep * xp.ones(self._shape, dtype=xp.float64)
        self.center_x = p_center_x
        self.center_y = p_center_y

        # construct the the pixel position array
        self.pixel_position = xp.zeros(self._shape + (3, ))
        self.pixel_position[..., 0] = self.center_x
        self.pixel_position[..., 1] = self.center_y
        self.pixel_position[..., 2] = self.center_z

        # Pixel map
        p_map_x = xp.stack((Xar, ))
        p_map_y = xp.stack((Yar, ))
        # [panel number, pixel num x, pixel num y]
        self.pixel_index_map = xp.stack((p_map_x, p_map_y), axis=-1)
        # Detector pixel number info
        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)

        # Panel pixel number info
        # number of pixels in each panel in x/y direction
        self.panel_pixel_num_x = self.pixel_index_map.shape[1]
        self.panel_pixel_num_y = self.pixel_index_map.shape[2]

        # total number of pixels (px*py)
        self.pixel_num_total = np.prod(self._shape)

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

        # Get reciprocal space configurations and corrections.
        self.initialize_pixels_with_beam(beam=beam)