Example #1
0
    def from_basisgrid(cls, bg, element_type=sensors.Mtrx):
        """
        Convert a BasisGrid object to a CompoundCamera.
    
        Parameters
        ----------
        bg : basisgrid.BasisGrid
            The basisgrid object to convert.
        
        element_type : sensors.PixelArraySensor
            The SensorElement type to populate the camera with.
        
        Returns
        -------
        cd : CompoundCamera
            The compound camera instance.
        """
    
        if not isinstance(bg, basisgrid.BasisGrid):
            raise TypeError('`bg` argument must be instance of BasisGrid,'
                            ' got: %s' % type(bg))
    
        cd = cls(type_name='root_frame', id_num=0, parent=None)
    
    
        for g in range(bg.num_grids):
        
            p, s, f, shape = bg.get_grid(g)
        
            pixel_shape = (np.linalg.norm(s),
                           np.linalg.norm(f))
        
            # to compute the rotation, find the 
            us = s / pixel_shape[0] # unit vector
            uf = f / pixel_shape[1] # unit vector
            n  = np.cross(us, uf)   # tested for orthog. in next fxn
        
            # remember: in the matrix convention (Mikhail uses), +x is slow
            # and +y is fast
            ra = moveable._angles_from_rotated_frame(us, uf, n)

            # translation is just p
            tr = p
        
            pas = element_type(shape, 
                               pixel_shape, 
                               id_num=g, 
                               parent=cd,
                               rotation_angles=ra, 
                               translation=tr)

    
        return cd
Example #2
0
    def from_basisgrid(cls, bg, element_type=sensors.Mtrx):
        """
        Convert a BasisGrid object to a CompoundCamera.
    
        Parameters
        ----------
        bg : basisgrid.BasisGrid
            The basisgrid object to convert.
        
        element_type : sensors.PixelArraySensor
            The SensorElement type to populate the camera with.
        
        Returns
        -------
        cd : CompoundCamera
            The compound camera instance.
        """

        if not isinstance(bg, basisgrid.BasisGrid):
            raise TypeError('`bg` argument must be instance of BasisGrid,'
                            ' got: %s' % type(bg))

        cd = cls(type_name='root_frame', id_num=0, parent=None)

        for g in range(bg.num_grids):

            p, s, f, shape = bg.get_grid(g)

            pixel_shape = (np.linalg.norm(s), np.linalg.norm(f))

            # to compute the rotation, find the
            us = s / pixel_shape[0]  # unit vector
            uf = f / pixel_shape[1]  # unit vector
            n = np.cross(us, uf)  # tested for orthog. in next fxn

            # remember: in the matrix convention (Mikhail uses), +x is slow
            # and +y is fast
            ra = moveable._angles_from_rotated_frame(us, uf, n)

            # translation is just p
            tr = p

            pas = element_type(shape,
                               pixel_shape,
                               id_num=g,
                               parent=cd,
                               rotation_angles=ra,
                               translation=tr)

        return cd
Example #3
0
def test_angle_retrieval():

    for i in range(100):

        alpha = np.random.rand() * 180.0
        beta  = np.random.rand() * 180.0
        gamma = np.random.rand() * 180.0

        R = moveable._rotation_matrix_from_angles(gamma, beta, alpha)

        I = np.eye(3)
        Ip = np.dot(R, I)

        gp, bp, ap = moveable._angles_from_rotated_frame(Ip[:,0], Ip[:,1], Ip[:,2])

        #print np.array([gamma, beta, alpha]), np.array([gp, bp, ap])

        # test to make sure they rotate to the same thing
        R2 = moveable._rotation_matrix_from_angles(gp, bp, ap)

        assert np.sum( np.abs( R - R2 ) ) < 1e-12
Example #4
0
def test_angle_retrieval():

    for i in range(100):

        alpha = np.random.rand() * 180.0
        beta = np.random.rand() * 180.0
        gamma = np.random.rand() * 180.0

        R = moveable._rotation_matrix_from_angles(gamma, beta, alpha)

        I = np.eye(3)
        Ip = np.dot(R, I)

        gp, bp, ap = moveable._angles_from_rotated_frame(
            Ip[:, 0], Ip[:, 1], Ip[:, 2])

        #print np.array([gamma, beta, alpha]), np.array([gp, bp, ap])

        # test to make sure they rotate to the same thing
        R2 = moveable._rotation_matrix_from_angles(gp, bp, ap)

        assert np.sum(np.abs(R - R2)) < 1e-12
Example #5
0
    def from_basisgrid(cls, bg):
        """
        Convert a BasisGrid object to a Cspad. The BasisGrid must have 64 grids/
        panels, one for each CSPAD ASIC.
        
        Parameters
        ----------
        bg : basisgrid.BasisGrid
            The basisgrid object to convert.
            
        Returns
        -------
        cspad : Cspad
            The Cspad instance.
        """
        
        cspad = cls(type_name='CSPAD:V1')
        
        if not isinstance(bg, basisgrid.BasisGrid):
            raise TypeError('`bg` argument must be instance of BasisGrid,'
                            ' got: %s' % type(bg))
        
        
        # if the grids are asics, we can strip out every other one and then
        # treat them like 2x1s        
        if bg.num_pixels / bg.num_grids == 185 * 388: # two-by-one grids
            stride = 1
            
        elif bg.num_pixels / bg.num_grids == 185 * 194: # asic grids
            stride = 2
            
        else:
            raise RuntimeError('Could not tell if BasisGrid grid elements are '
                               'CSPAD 2x1s or ASICs. Pixels per element:'
                               '%d' % (bg.num_pixels / bg.num_grids,))
        
        for g in range(0, bg.num_grids, stride):
            
            asic_id = (g/stride) # index from 0 to 7
            
            # find the quad geometry
            quad_index = asic_id / 8
            
            # we just put the quads in a zero'd frame, no knowledge of absolute
            # orientations
            quad_rot = np.array([0.0, 0.0, 0.0])
            quad_trs = np.array([0.0, 0.0, 0.0])
                                 
                                 
            # add a new quad if necessary
            if asic_id % 8 == 0:
                quad = CompoundCamera(type_name='QUAD:V1',
                                        id_num=quad_index,
                                        parent=cspad,
                                        rotation_angles=quad_rot, 
                                        translation=quad_trs)
                                 
            p, s, f, shape = bg.get_grid(g)
            
            pixel_shape = (np.linalg.norm(s),
                           np.linalg.norm(f))
            
            
            # compute the rotation based on s/f vectors
            us = s / pixel_shape[0] # unit vector
            uf = f / pixel_shape[1] # unit vector
            
            # BIG WARNING: There is a minus sign on `us` below, which is needed
            # to account for the fact that the slow scan is swapped in the
            # sensors.Cspad2x1 class
            
            n  = np.cross(uf, -us)   # tested for orthog. in next fxn
            ra = moveable._angles_from_rotated_frame(uf, -us, n)
            
            
            # translation is center of 2x1, less the quad center
            # dont forget the big pixels!
            # dont forget p/s/f here is only an ASIC!
            # dont forget p points to the middle of a pixel!

            tr = p + 184.0/2.0 * 109.92 * us + (192.5 * 109.92 + 274.8) * uf

            
            # construct the 2x1
            pas = sensors.Cspad2x1(type_name='SENS2X1:V1', 
                                   id_num=int(asic_id % 8), 
                                   parent=quad,
                                   rotation_angles=ra, 
                                   translation=tr)
                        
                                   
            # if we skipped a grid (ASIC), we'll check to make sure that
            # the p-vector from that grid points to the correct pixel on
            # our newly oriented 2x1 -- allow 10 um error in x/y, 200 um in z
            
            if stride == 2:
                
                p_skipped, _, _, _ = bg.get_grid(g + 1)
                
                # be more lenient in z, since some programs are not general
                # enough to handle it
                
                if (np.linalg.norm(p_skipped[:2] - pas.xyz[0,194,:2]) > 10.0) or \
                   (np.abs(p_skipped[2] - pas.xyz[0,194,2]) > 200.0):
                    
                    print('quad %d / 2x1 %d' % (quad_index, asic_id % 8))
                    print('grid p-vector:   ', p_skipped)
                    print('pixel (0, 194):  ', pas.xyz[0,194,:])
                    print('')
                    
                    warnings.warn('The two ASICs making up the %d-th 2x1 on '
                                  'the %d-th quad (grids %d, %d) do not conform'
                                  ' to the geometric requirements of a 2x1 '
                                  'unit. Check your geometry! Do not ignore this'
                                  ' warning unless you were expecting it!!'
                                  '' % (asic_id % 8, quad_index, g, g+1))
                                  
                    if _STRICT:
                        raise RuntimeError('_STRICT set, no warnings allowed')
                               
                               
        return cspad
Example #6
0
    def from_basisgrid(cls, bg):
        """
        Convert a BasisGrid object to a Cspad. The BasisGrid must have 64 grids/
        panels, one for each CSPAD ASIC.
        
        Parameters
        ----------
        bg : basisgrid.BasisGrid
            The basisgrid object to convert.
            
        Returns
        -------
        cspad : Cspad
            The Cspad instance.
        """

        cspad = cls(type_name='CSPAD:V1')

        if not isinstance(bg, basisgrid.BasisGrid):
            raise TypeError('`bg` argument must be instance of BasisGrid,'
                            ' got: %s' % type(bg))

        # if the grids are asics, we can strip out every other one and then
        # treat them like 2x1s
        if bg.num_pixels / bg.num_grids == 185 * 388:  # two-by-one grids
            stride = 1

        elif bg.num_pixels / bg.num_grids == 185 * 194:  # asic grids
            stride = 2

        else:
            raise RuntimeError('Could not tell if BasisGrid grid elements are '
                               'CSPAD 2x1s or ASICs. Pixels per element:'
                               '%d' % (bg.num_pixels / bg.num_grids, ))

        for g in range(0, bg.num_grids, stride):

            asic_id = (g / stride)  # index from 0 to 7

            # find the quad geometry
            quad_index = asic_id / 8

            # we just put the quads in a zero'd frame, no knowledge of absolute
            # orientations
            quad_rot = np.array([0.0, 0.0, 0.0])
            quad_trs = np.array([0.0, 0.0, 0.0])

            # add a new quad if necessary
            if asic_id % 8 == 0:
                quad = CompoundCamera(type_name='QUAD:V1',
                                      id_num=quad_index,
                                      parent=cspad,
                                      rotation_angles=quad_rot,
                                      translation=quad_trs)

            p, s, f, shape = bg.get_grid(g)

            pixel_shape = (np.linalg.norm(s), np.linalg.norm(f))

            # compute the rotation based on s/f vectors
            us = s / pixel_shape[0]  # unit vector
            uf = f / pixel_shape[1]  # unit vector

            # BIG WARNING: There is a minus sign on `us` below, which is needed
            # to account for the fact that the slow scan is swapped in the
            # sensors.Cspad2x1 class

            n = np.cross(uf, -us)  # tested for orthog. in next fxn
            ra = moveable._angles_from_rotated_frame(uf, -us, n)

            # translation is center of 2x1, less the quad center
            # dont forget the big pixels!
            # dont forget p/s/f here is only an ASIC!
            # dont forget p points to the middle of a pixel!

            tr = p + 184.0 / 2.0 * 109.92 * us + (192.5 * 109.92 + 274.8) * uf

            # construct the 2x1
            pas = sensors.Cspad2x1(type_name='SENS2X1:V1',
                                   id_num=int(asic_id % 8),
                                   parent=quad,
                                   rotation_angles=ra,
                                   translation=tr)

            # if we skipped a grid (ASIC), we'll check to make sure that
            # the p-vector from that grid points to the correct pixel on
            # our newly oriented 2x1 -- allow 10 um error in x/y, 200 um in z

            if stride == 2:

                p_skipped, _, _, _ = bg.get_grid(g + 1)

                # be more lenient in z, since some programs are not general
                # enough to handle it

                if (np.linalg.norm(p_skipped[:2] - pas.xyz[0,194,:2]) > 10.0) or \
                   (np.abs(p_skipped[2] - pas.xyz[0,194,2]) > 200.0):

                    print('quad %d / 2x1 %d' % (quad_index, asic_id % 8))
                    print('grid p-vector:   ', p_skipped)
                    print('pixel (0, 194):  ', pas.xyz[0, 194, :])
                    print('')

                    warnings.warn(
                        'The two ASICs making up the %d-th 2x1 on '
                        'the %d-th quad (grids %d, %d) do not conform'
                        ' to the geometric requirements of a 2x1 '
                        'unit. Check your geometry! Do not ignore this'
                        ' warning unless you were expecting it!!'
                        '' % (asic_id % 8, quad_index, g, g + 1))

                    if _STRICT:
                        raise RuntimeError('_STRICT set, no warnings allowed')

        return cspad