コード例 #1
0
ファイル: image.py プロジェクト: neuropoly/spinalcordtoolbox
    def get_inverse_transform(self, im_ref, mode='affine'):
        aff_im_self = self.im_file.affine
        aff_im_ref = im_ref.im_file.affine
        if mode == 'affine':
            transform = np.matmul(np.linalg.inv(aff_im_ref), aff_im_self)
        else:
            T_self, R_self, Sc_self, Sh_self = affines.decompose44(aff_im_self)
            T_ref, R_ref, Sc_ref, Sh_ref = affines.decompose44(aff_im_ref)
            if mode == 'translation':
                T_transform = T_self - T_ref
                R_transform = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
                Sc_transform = np.array([1.0, 1.0, 1.0])
                transform = affines.compose(T_transform, R_transform, Sc_transform)
            elif mode == 'rigid':
                T_transform = T_self - T_ref
                R_transform = np.matmul(np.linalg.inv(R_ref), R_self)
                Sc_transform = np.array([1.0, 1.0, 1.0])
                transform = affines.compose(T_transform, R_transform, Sc_transform)
            elif mode == 'rigid_scaling':
                T_transform = T_self - T_ref
                R_transform = np.matmul(np.linalg.inv(R_ref), R_self)
                Sc_transform = Sc_self / Sc_ref
                transform = affines.compose(T_transform, R_transform, Sc_transform)
            else:
                transform = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])

        return transform
コード例 #2
0
    def get_inverse_transform(self, im_ref, mode='affine'):
        aff_im_self = self.im_file.affine
        aff_im_ref = im_ref.im_file.affine
        if mode == 'affine':
            transform = np.matmul(np.linalg.inv(aff_im_ref), aff_im_self)
        else:
            T_self, R_self, Sc_self, Sh_self = affines.decompose44(aff_im_self)
            T_ref, R_ref, Sc_ref, Sh_ref = affines.decompose44(aff_im_ref)
            if mode == 'translation':
                T_transform = T_self - T_ref
                R_transform = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
                Sc_transform = np.array([1.0, 1.0, 1.0])
                transform = affines.compose(T_transform, R_transform,
                                            Sc_transform)
            elif mode == 'rigid':
                T_transform = T_self - T_ref
                R_transform = np.matmul(np.linalg.inv(R_ref), R_self)
                Sc_transform = np.array([1.0, 1.0, 1.0])
                transform = affines.compose(T_transform, R_transform,
                                            Sc_transform)
            elif mode == 'rigid_scaling':
                T_transform = T_self - T_ref
                R_transform = np.matmul(np.linalg.inv(R_ref), R_self)
                Sc_transform = Sc_self / Sc_ref
                transform = affines.compose(T_transform, R_transform,
                                            Sc_transform)
            else:
                transform = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0],
                                      [0, 0, 0, 1]])

        return transform
コード例 #3
0
ファイル: simulator.py プロジェクト: hamogu/marxs
    def generate_elements(self):
        '''Initialize all optical elements.

        After any of the ``elem_pos``, ``elem_uncertainty`` or
        ``uncertainty`` attributes has changed, `generate_elements` needs to be
        called to regenerate the positions of the individual elements using

        - the global position of ``Parallel.pos4d``
        - the position of each element ``Parallel.elem_pos`` relativ to the global position
        - the global uncertainty `uncertainty`.
        - the uncertainty for individual facets.
        '''

        self.elements = []

        for i in range(len(self.elem_pos)):
            # _parse_position_keywords pops off keywords, thus operate on a copy here
            elem_args = self.elem_args.copy()
            # check if elem_args is the same for every element
            specific_elem_args = {}
            for k, v in elem_args.items():
                if isinstance(v, list) and (len(v) == len(self.elem_pos)):
                    specific_elem_args[k] = v[i]
                else:
                    specific_elem_args[k] = v
            if 'name' not in specific_elem_args:
                specific_elem_args['name'] = 'Elem {0} in {1}'.format(i, self.name)

            elem_pos4d = _parse_position_keywords(specific_elem_args)
            telem, relem, zelem, Selem = decompose44(elem_pos4d)
            if not np.allclose(Selem, 0.):
                raise ValueError('pos4 for elem includes shear, which is not supported here.')

            e_center, e_rot, e_zoom, stemp = decompose44(self.elem_pos[i])
            tsigelem, rsigelem, zsigelem, stemp = decompose44(self.elem_uncertainty[i])
            if not np.allclose(stemp, 0.):
                raise SimulationSetupError('Shear is not supported in the elem uncertainty.')
            # Will be able to write this so much better in python 3.5,
            # but for now I don't want to nest np.dot too much so here it goes
            f_pos4d = np.eye(4)
            for m in reversed([self.pos4d,                 # global position of ParallelElement
                               self.uncertainty,           # uncertainty in global positioning
                               translation2aff(tsigelem),  # uncertaintig in translation for elem
                               translation2aff(e_center),  # translate elem center to global center
                               translation2aff(telem),     # offset for all elem. Usually 0.
                               mat2aff(rsigelem),          # uncertainty in rotation for elem
                               mat2aff(e_rot),             # Rotation of individual elem
                               mat2aff(relem),             # Rotation for all  elem, e.g. CAT gratings
                               zoom2aff(zsigelem),         # uncertainty in the zoom
                               zoom2aff(e_zoom),           # zoom of individual elem
                               zoom2aff(zelem),            # sets size for all elem
                              ]):
                assert m.shape == (4, 4)
                f_pos4d = np.dot(m, f_pos4d)
            self.elements.append(self.elem_class(pos4d = f_pos4d,
                                                 id_num=self.id_num_offset + i,
                                                 **specific_elem_args))
コード例 #4
0
ファイル: geometry.py プロジェクト: Chandra-MARX/marxs
    def parametric_surface(self, phi=None, z=None, display={}):
        '''Parametric description of the tube.

        This is just another way to obtain the shape of the tube, e.g.
        for visualization.

        Parameters
        ----------
        phi : np.array
            ``phi`` is the angle around the tube profile. Set to ``None`` to use the
            extend of the element itself.
        z : np.array
            The coordiantes along the radius coordinate. Set to ``None`` to use the
            extend of the element itself.

        Returns
        -------
        xyzw : np.array
            Ring coordinates in global homogeneous coordinate system.
        '''
        phi = np.linspace(self.coos_limits[0][0], self.coos_limits[0][1], self.n_points) \
              if phi is None else np.asanyarray(phi)
        trans, rot, zoom, shear = decompose44(self.pos4d)
        z = self.coos_limits[1] if z is None else np.asanyarray(z) / zoom[2]
        if (phi.ndim != 1) or (z.ndim != 1):
            raise ValueError('input parameters have 1-dim shape.')
        phi, z = np.meshgrid(phi, z)
        x = np.cos(phi)
        y = np.sin(phi)
        w = np.ones_like(z)
        coos = np.array([x, y, z, w]).T
        return np.einsum('...ij,...j', self.pos4d, coos)
コード例 #5
0
    def parametric_surface(self, phi=None, z=None, display={}):
        '''Parametric description of the tube.

        This is just another way to obtain the shape of the tube, e.g.
        for visualization.

        Parameters
        ----------
        phi : np.array
            ``phi`` is the angle around the tube profile. Set to ``None`` to
            use the extend of the element itself.
        z : np.array
            The coordiantes along the radius coordinate. Set to ``None`` to use
            the extend of the element itself.

        Returns
        -------
        xyzw : np.array
            Ring coordinates in global homogeneous coordinate system.
        '''
        phi = np.linspace(self.coos_limits[0][0], self.coos_limits[0][1], self.n_points) \
              if phi is None else np.asanyarray(phi)
        trans, rot, zoom, shear = decompose44(self.pos4d)
        z = self.coos_limits[1] if z is None else np.asanyarray(z) / zoom[2]
        if (phi.ndim != 1) or (z.ndim != 1):
            raise ValueError('input parameters have 1-dim shape.')
        phi, z = np.meshgrid(phi, z)
        x = np.cos(phi)
        y = np.sin(phi)
        w = np.ones_like(z)
        coos = np.array([x, y, z, w]).T
        return np.einsum('...ij,...j', self.pos4d, coos)
コード例 #6
0
    def process_photons(self, photons):
        intersect, interpos, inter_local = self.intersect(
            photons['dir'], photons['pos'])

        photons['pos'][intersect, :] = interpos[intersect, :]
        self.add_output_cols(photons, self.loc_coos_name + self.detpix_name)
        # Add ID number to ID col, if requested
        if self.id_col is not None:
            photons[self.id_col][intersect] = self.id_num
        # Set position in different coordinate systems
        photons['pos'][intersect] = interpos[intersect]
        photons[self.loc_coos_name[0]][intersect] = inter_local[intersect, 0]
        photons[self.loc_coos_name[1]][intersect] = inter_local[intersect, 1]
        trans, rot, zoom, shear = decompose44(self.pos4d)
        if np.isclose(zoom[0], zoom[1]):
            photons[self.detpix_name[0]][intersect] = inter_local[
                intersect, 0] * zoom[0] / self.pixsize
        else:
            warnings.warn(
                'Pixel coordinate for elliptical mirrors not implemented.',
                PixelSizeWarning)
        photons[self.detpix_name[1]][intersect] = inter_local[intersect,
                                                              1] / self.pixsize

        return photons
コード例 #7
0
ファイル: rowland.py プロジェクト: jhfrost314/marxs
    def generate_facets(self, facet_class, facet_args={}):
        '''
        Example
        -------
        from marxs.optics.grating import FlatGrating
        gsa = GSA( ... args ...)
        gsa.generate_facets(FlatGrating, {'d': 0.002})
        '''
        self.facets = []

        facet_pos4d = _parse_position_keywords(facet_args)
        tfacet, rfacet, zfacet, Sfacet = decompose44(facet_pos4d)
        if not np.allclose(Sfacet, 0.):
            raise ValueError('pos4 for facet includes shear, which is not supported for gratings.')
        name = facet_args.pop('name', '')

        gas_center = self.calc_ideal_center()
        Tgas = translation2aff(gas_center)

        for i in range(len(self.facet_pos)):
            f_center, rrown, ztemp, stemp = decompose44(self.facet_pos[i])
            Tfacetgas = translation2aff(-np.array(gas_center) + f_center)
            tsigfacet, rsigfacet, ztemp, stemp = decompose44(self.facet_uncertainty[i])
            if not np.allclose(ztemp, 1.):
                raise FacetPlacementError('Zoom is not supported in the facet uncertainty.')
            if not np.allclose(stemp, 0.):
                raise FacetPlacementError('Shear is not supported in the facet uncertainty.')
            # Will be able to write this so much better in python 3.5,
            # but for now I don't want to nest np.dot too much so here it goes
            f_pos4d = np.eye(4)
            for m in reversed([self.pos4d,  # any change between GAS system and global
                      # coordiantes, e.g. if x is not optical axis
                      Tgas,  # move to center of GAS
                      self.uncertainty,  # uncertainty in GAS positioning
                      Tfacetgas,  # translate facet center to GAS center
                      translation2aff(tsigfacet),  # uncertaintig in translation for facet
                      translation2aff(tfacet),  # any additional offset of facet. Probably 0
                      mat2aff(rsigfacet),  # uncertainty in rotation for facet
                      mat2aff(rfacet),  # Any rotation of facet, e.g. for CAT gratings
                      mat2aff(rrown),   # rotate grating normal to be normal to Rowland torus
                      zoom2aff(zfacet),  # sets size of grating
                     ]):
                assert m.shape == (4, 4)
                f_pos4d = np.dot(m, f_pos4d)
            self.facets.append(facet_class(pos4d = f_pos4d, name='{0}  Facet {1} in GAS {2}'.format(name, i, self.name), **facet_args))
コード例 #8
0
ファイル: image.py プロジェクト: neuropoly/spinalcordtoolbox
 def get_directions(self):
     """
     This function return the X, Y, and Z axes of the image
     Returns:
         X, Y and Z axes of the image
     """
     direction_matrix = self.header.get_best_affine()
     T_self, R_self, Sc_self, Sh_self = affines.decompose44(direction_matrix)
     return R_self[0:3, 0], R_self[0:3, 1], R_self[0:3, 2]
コード例 #9
0
 def get_directions(self):
     """
     This function return the X, Y, and Z axes of the image
     Returns:
         X, Y and Z axes of the image
     """
     direction_matrix = self.header.get_best_affine()
     T_self, R_self, Sc_self, Sh_self = affines.decompose44(direction_matrix)
     return R_self[0:3, 0], R_self[0:3, 1], R_self[0:3, 2]
コード例 #10
0
ファイル: detector.py プロジェクト: bsipocz/marxs
 def __init__(self, pixsize=1, **kwargs):
     self.pixsize = pixsize
     super(FlatDetector, self).__init__(**kwargs)
     t, r, zoom, s = decompose44(self.pos4d)
     self.npix = [0, 0]
     self.centerpix = [0, 0]
     for i in (0, 1):
         z  = zoom[i + 1]
         self.npix[i] = int(np.round(2. * z / self.pixsize))
         if (2. * z / self.pixsize - self.npix[i]) > 1e-3:
             warnings.warn('Detector size is not an integer multiple of pixel size in direction {0}. It will be rounded.'.format('xy'[i]), PixelSizeWarning)
         self.centerpix[i] = (self.npix[i] - 1) / 2
コード例 #11
0
ファイル: detector.py プロジェクト: jhfrost314/marxs
 def __init__(self, pixsize, **kwargs):
     self.pixsize = pixsize
     super(FlatDetector, self).__init__(**kwargs)
     t, r, zoom, s = decompose44(self.pos4d)
     self.npix = [0, 0]
     self.centerpix = [0, 0]
     for i in (0, 1):
         z  = zoom[i + 1]
         self.npix[i] = 2 * z // self.pixsize
         if (2. * z / self.pixsize - self.npix[i]) > 1e-3:
             warn('Detector size is not an integer multiple of pixel size. It will be rounded.')
         self.centerpix[i] = (self.npix[i] - 1) / 2
コード例 #12
0
def xyz_rpy(transformation):
    """Decompose a transformation matrix into translation and euler angles

    :param transformation: A 4x4 transformation matrix

    :return: A tuple of (x, y, z, r, p, y) where (x, y, z) are coordinates of a
        cartesian translation and (r, p, y) are roll, pitch, yaw applied in
        that order around fixed axis
    """

    T, R, _, _ = decompose44(transformation)
    return (T[0], T[1], T[2]), mat2euler(R)
コード例 #13
0
ファイル: detector.py プロジェクト: Chandra-MARX/marxs
 def __init__(self, pixsize=1, ignore_pixel_warning=False, **kwargs):
     self.pixsize = pixsize
     super().__init__(**kwargs)
     t, r, zoom, s = decompose44(self.pos4d)
     self.npix = [0, 0]
     self.centerpix = [0, 0]
     for i in (0, 1):
         z  = zoom[i + 1]
         self.npix[i] = int(np.round(2. * z / self.pixsize))
         if (np.abs(2. * z / self.pixsize - self.npix[i]) > 1e-2) and not ignore_pixel_warning:
             warnings.warn('Detector size is not an integer multiple of pixel size in direction {0}. It will be rounded.'.format('xy'[i]), SimulationSetupWarning)
         self.centerpix[i] = (self.npix[i] - 1) / 2
コード例 #14
0
 def __init__(self, pixsize=1, **kwargs):
     self.pixsize = pixsize
     super(FlatDetector, self).__init__(**kwargs)
     t, r, zoom, s = decompose44(self.pos4d)
     self.npix = [0, 0]
     self.centerpix = [0, 0]
     for i in (0, 1):
         z = zoom[i + 1]
         self.npix[i] = int(np.round(2. * z / self.pixsize))
         if np.abs(2. * z / self.pixsize - self.npix[i]) > 1e-2:
             warnings.warn(
                 'Detector size is not an integer multiple of pixel size in direction {0}. It will be rounded.'
                 .format('xy'[i]), PixelSizeWarning)
         self.centerpix[i] = (self.npix[i] - 1) / 2
コード例 #15
0
ファイル: base.py プロジェクト: astrofrog/marxs
 def _plot_mayavi(self, viewer=None):
     from tvtk.tools import visual
     visual.set_viewer(viewer)
     trans, rot, zoom, shear = decompose44(self.pos4d)
     # turn into valid color tuple
     self.display['color'] = get_color(self.display)
     # setting color here is more global than in the next line
     # because this automatically changes the diffuse, ambient, etc. color, too.
     b = visual.box(pos=trans, size=tuple(np.abs(zoom) * 2), axis=np.dot([1.,0.,0.], rot),
                    color=self.display['color'], viewer=viewer)
     # No safety net here like for color converting to a tuple.
     # If the advnaced properties are set you are on your own.
     for n in b.property.trait_names():
         if n in self.display:
             setattr(b.property, n, self.display[n])
コード例 #16
0
    def xml(self, doc, link):
        """Represent this visual element as xml"""

        # Extract scale and shear from transformation
        _, _, Z, S = decompose44(self.trans)
        z = np.mean(Z)

        meta = _URDFVisual.meta[self.node.name]
        if not meta.non_uniform_scale and not np.allclose(Z, z):
            raise ValueError('Non uniform scale not supported for node '
                             f'{self.node.name}')
        if not meta.shear and not np.allclose(S, 0):
            raise ValueError('Scaling which induces shear is not supported '
                             f'for node {self.node.name}')

        fields = self.node.fields

        visual = doc.createElement('visual')

        xyz, rpy = xyz_rpy(self.trans)
        origin = doc.createElement('origin')
        origin.setAttribute('xyz', ' '.join(str(a) for a in xyz))
        origin.setAttribute('rpy', ' '.join(str(a) for a in rpy))
        visual.appendChild(origin)

        geometry = doc.createElement('geometry')
        if self.node.name == 'Box':
            size = [float(a) for a in fields['size'].split()]
            box = doc.createElement('box')
            box.setAttribute('size', ' '.join(str(a) for a in Z * size))
            geometry.appendChild(box)
        elif self.node.name == 'Cylinder':
            cylinder = doc.createElement('cylinder')
            cylinder.setAttribute('radius', str(float(fields['radius']) * z))
            cylinder.setAttribute('length', str(float(fields['height']) * z))
            geometry.appendChild(cylinder)
        elif self.node.name == 'Sphere':
            sphere = doc.createElement('sphere')
            sphere.setAttribute('radius', str(float(fields['radius']) * z))
            geometry.appendChild(sphere)
        elif self.node.name == 'Mesh':
            mesh = doc.createElement('mesh')
            mesh.setAttribute('filename', str(fields['url']))
            mesh.setAttribute('scale', ' '.join(str(a) for a in Z))
            geometry.appendChild(mesh)
        visual.appendChild(geometry)

        link.appendChild(visual)
コード例 #17
0
 def _plot_mayavi(self, viewer=None):
     from tvtk.tools import visual
     visual.set_viewer(viewer)
     trans, rot, zoom, shear = decompose44(self.pos4d)
     # turn into valid color tuple
     self.display['color'] = get_color(self.display)
     # setting color here is more global than in the next line
     # because this automatically changes the diffuse, ambient, etc. color, too.
     b = visual.box(pos=trans,
                    size=tuple(np.abs(zoom) * 2),
                    axis=np.dot([1., 0., 0.], rot),
                    color=self.display['color'],
                    viewer=viewer)
     # No safety net here like for color converting to a tuple.
     # If the advnaced properties are set you are on your own.
     for n in b.property.trait_names():
         if n in self.display:
             setattr(b.property, n, self.display[n])
コード例 #18
0
ファイル: detector.py プロジェクト: hamogu/marxs
    def process_photons(self, photons, intersect, interpos, inter_local):
        photons['pos'][intersect, :] = interpos[intersect, :]
        self.add_output_cols(photons, self.loc_coos_name + self.detpix_name)
        # Add ID number to ID col, if requested
        if self.id_col is not None:
            photons[self.id_col][intersect] = self.id_num
        # Set position in different coordinate systems
        photons['pos'][intersect] = interpos[intersect]
        photons[self.loc_coos_name[0]][intersect] = inter_local[intersect, 0]
        photons[self.loc_coos_name[1]][intersect] = inter_local[intersect, 1]
        trans, rot, zoom, shear = decompose44(self.pos4d)
        if np.isclose(zoom[0], zoom[1]):
            photons[self.detpix_name[0]][intersect] = inter_local[intersect, 0] * zoom[0] / self.pixsize
        else:
            warnings.warn('Pixel coordinate for elliptical mirrors not implemented.', PixelSizeWarning)
        photons[self.detpix_name[1]][intersect] = inter_local[intersect, 1] / self.pixsize

        return photons
コード例 #19
0
 def __resample(self):
     """
     Resample image to standard shape; this occurs only at (re)-initialization time
     """
     shape = self.__img.shape
     affine = None
     hdr = self.__hdr
     try:
         affine = hdr.Affine
     except:
         print("header: {}".format(hdr))
         raise self.TransformError(
             "Image header must contain affine transformation information in `.Affine` attribute."
         )
     _, R, Z, S = affine3d.decompose44(hdr.Affine)
     # If any of the __mm_per_voxel items are negative, keep the original zoom at those locations:
     mm_per_voxel = np.atleast_1d(self.__mm_per_voxel).astype("float")
     if len(mm_per_voxel) not in [1, len(Z)]:
         raise RuntimeError(
             "`mm_per_voxel` must be a scalar value or tuple of length {}.".
             format(len(Z)))
     if any(mm_per_voxel < 0):
         if len(mm_per_voxel) == 1:
             mm_per_voxel = Z
         else:
             mm_per_voxel[mm_per_voxel < 0] = Z[mm_per_voxel < 0]
     # If there are shears, bail out (we don't support that yet):
     if S.sum() != 0:
         raise self.TransformError(
             "Image affine includes shear, which is not supported in this version."
         )
     # See if any rotations are necessary (we don't support that yet):
     if np.any(np.eye(R.shape[0]).astype(R.dtype) != R):
         raise self.TransformError(
             "Image affine includes rotation, which is not supported in this version"
         )
     # Now apply scaling
     Z = Z / np.array(mm_per_voxel)
     self.__img = interpolation.zoom(self.__img, Z)
コード例 #20
0
    def intersect(self, dir, pos, transform=True):
        '''Calculate the intersection point between a ray and the element

        Parameters
        ----------
        dir : `numpy.ndarray` of shape (N, 4)
            homogeneous coordinates of the direction of the ray
        pos : `numpy.ndarray` of shape (N, 4)
            homogeneous coordinates of a point on the ray
        transform : bool
            If ``True``, input is in global coordinates and needs to be
            transformed here for the calculations; if ``False`` input is in
            local coordinates.

        Returns
        -------
        intersect :  boolean array of length N
            ``True`` if an intersection point is found.
        interpos : `numpy.ndarray` of shape (N, 4)
            homogeneous coordinates of the intersection point. Values are set
            to ``np.nan`` is no intersecton point is found.
        interpos_local : `numpy.ndarray` of shape (N, 2)
            phi, z coordiantes (in the local frame) for one of the intersection
            points. If both intersection points are required, reset
            ``self.inner`` and call this function again.
        '''
        # This could be moved to a general function
        if not np.all(dir[:, 3] == 0):
            raise ValueError('First input must be direction vectors.')
        # Could test pos, too...
        if transform:
            invpos4d = np.linalg.inv(self.pos4d)
            dir = np.dot(invpos4d, dir.T).T
            pos = np.dot(invpos4d, pos.T).T

        xyz = h2e(pos)
        dir_e = h2e(dir)

        # Solve quadratic equation in steps.
        # a12 = (-xr +- sqrt(xr - r**2(x**2 - R**2)))
        xy = xyz[:, :2]
        r = dir[:, :2]
        c = np.sum(xy**2, axis=1) - 1.
        b = 2 * np.sum(xy * r, axis=1)
        a = np.sum(r**2, axis=1)
        underroot = b**2 - 4 * a * c
        # List of intersect in xy plane.
        intersect = (underroot >= 0)
        i = intersect  # just a shorthand because it's used so much below

        interpos_local = np.ones((pos.shape[0], 2))
        interpos_local[:] = np.nan
        interpos = np.ones_like(pos)
        interpos[:] = np.nan

        if intersect.sum() > 0:
            i_ind = intersect.nonzero()[0]
            denom = 2 * a[i]
            a1 = (-b[i] + np.sqrt(underroot[i])) / denom
            a2 = (-b[i] - np.sqrt(underroot[i])) / denom
            xy_1 = xy[i, :] + a1[:, np.newaxis] * r[i, :]
            phi_1 = np.arctan2(xy_1[:, 1], xy_1[:, 0])
            xy_2 = xy[i, :] + a2[:, np.newaxis] * r[i, :]
            phi_2 = np.arctan2(xy_2[:, 1], xy_2[:, 0])
            # 1, 2 look like hits in x,y but might still miss in z
            z_1 = xyz[i, 2] + a1 * dir[i, 2]
            z_2 = xyz[i, 2] + a2 * dir[i, 2]
            hit_1 = ((a1 >= 0) & (np.abs(z_1) <= 1.) & angle_between(
                phi_1, self.coos_limits[0][0], self.coos_limits[0][1]))
            hit_2 = ((a2 >= 0) & (np.abs(z_2) <= 1.) & angle_between(
                phi_2, self.coos_limits[0][0], self.coos_limits[0][1]))
            # If both 1 and 2 are hits, use the closer one
            hit_1[hit_2 & (a2 < a1)] = False
            hit_2[hit_1 & (a2 >= a1)] = False
            intersect[i_ind] = hit_1 | hit_2
            # Set values into array from either point 1 or 2
            interpos_local[i_ind[hit_1], 0] = phi_1[hit_1]
            interpos_local[i_ind[hit_1], 1] = z_1[hit_1]

            interpos_local[i_ind[hit_2], 0] = phi_2[hit_2]
            interpos_local[i_ind[hit_2], 1] = z_2[hit_2]
            # Calculate pos for point 1 or 2 in local xyz coord system
            interpos[i_ind[hit_1], :] = e2h(
                xyz[i_ind, :] + a1[:, None] * dir_e[i_ind, :], 1)[hit_1, :]
            interpos[i_ind[hit_2], :] = e2h(
                xyz[i_ind, :] + a2[:, None] * dir_e[i_ind, :], 1)[hit_2, :]

            trans, rot, zoom, shear = decompose44(self.pos4d)
            # interpos_local in z direction is in local coordinates, i.e.
            # the x coordiante is 0..1, but we want that in units of the
            # global coordinate system.
            interpos_local[:, 1] = interpos_local[:, 1] * zoom[2]
            interpos = np.dot(self.pos4d, interpos.T).T

        return intersect, interpos, interpos_local
コード例 #21
0
 def __getitem__(self, value):
     if value == 'R':
         trans, rot, zoom, shear = decompose44(self.pos4d)
         return zoom[0]
     else:
         return super().__getitem__(value)
コード例 #22
0
 def _reset_trans(self, trans):
     _, _, Z, S = decompose44(trans)
     return scale_matrix(Z) * shear_matrix(S)
コード例 #23
0
ファイル: geometry.py プロジェクト: Chandra-MARX/marxs
    def intersect(self, dir, pos, transform=True):
        '''Calculate the intersection point between a ray and the element

        Parameters
        ----------
        dir : `numpy.ndarray` of shape (N, 4)
            homogeneous coordinates of the direction of the ray
        pos : `numpy.ndarray` of shape (N, 4)
            homogeneous coordinates of a point on the ray
        transform : bool
            If ``True``, input is in global coordinates and needs to be transformed
            here for the calculations; if ``False`` input is in local coordinates.

        Returns
        -------
        intersect :  boolean array of length N
            ``True`` if an intersection point is found.
        interpos : `numpy.ndarray` of shape (N, 4)
            homogeneous coordinates of the intersection point. Values are set
            to ``np.nan`` is no intersecton point is found.
        interpos_local : `numpy.ndarray` of shape (N, 2)
            phi, z coordiantes (in the local frame) for one of the intersection points.
            If both intersection points are required, reset ``self.inner`` and call this
            function again.
        '''
        # This could be moved to a general function
        if not np.all(dir[:, 3] == 0):
            raise ValueError('First input must be direction vectors.')
        # Could test pos, too...
        if transform:
            invpos4d = np.linalg.inv(self.pos4d)
            dir = np.dot(invpos4d, dir.T).T
            pos = np.dot(invpos4d, pos.T).T

        xyz = h2e(pos)
        dir_e = h2e(dir)

        # Solve quadratic equation in steps. a12 = (-xr +- sqrt(xr - r**2(x**2 - R**2)))
        xy = xyz[:, :2]
        r = dir[:, :2]
        c = np.sum(xy**2, axis=1) - 1.
        b = 2 * np.sum(xy * r, axis=1)
        a = np.sum(r**2, axis=1)
        underroot = b**2 - 4 * a * c
        # List of intersect in xy plane.
        intersect = (underroot >= 0)
        i = intersect  # just a shorthand because it's used so much below

        interpos_local = np.ones((pos.shape[0], 2))
        interpos_local[:] = np.nan
        interpos = np.ones_like(pos)
        interpos[:] = np.nan

        if intersect.sum() > 0:
            i_ind = intersect.nonzero()[0]
            denom = 2 * a[i]
            a1 = (- b[i] + np.sqrt(underroot[i])) / denom
            a2 = (- b[i] - np.sqrt(underroot[i])) / denom
            xy_1 = xy[i, :] + a1[:, np.newaxis] * r[i, :]
            phi_1 = np.arctan2(xy_1[:, 1], xy_1[:, 0])
            xy_2 = xy[i, :] + a2[:, np.newaxis] * r[i, :]
            phi_2 = np.arctan2(xy_2[:, 1], xy_2[:, 0])
            # 1, 2 look like hits in x,y but might still miss in z
            z_1 = xyz[i, 2] + a1 * dir[i, 2]
            z_2 = xyz[i, 2] + a2 * dir[i, 2]
            hit_1 = ((a1 >= 0) & (np.abs(z_1) <= 1.) &
                     angle_between(phi_1, self.coos_limits[0][0], self.coos_limits[0][1]))
            hit_2 = ((a2 >= 0) & (np.abs(z_2) <= 1.) &
                     angle_between(phi_2, self.coos_limits[0][0], self.coos_limits[0][1]))
            # If both 1 and 2 are hits, use the closer one
            hit_1[hit_2 & (a2 < a1)] = False
            hit_2[hit_1 & (a2 >= a1)] = False
            intersect[i_ind] = hit_1 | hit_2
            # Set values into array from either point 1 or 2
            interpos_local[i_ind[hit_1], 0] = phi_1[hit_1]
            interpos_local[i_ind[hit_1], 1] = z_1[hit_1]

            interpos_local[i_ind[hit_2], 0] = phi_2[hit_2]
            interpos_local[i_ind[hit_2], 1] = z_2[hit_2]
            # Calculate pos for point 1 or 2 in local xyz coord system
            interpos[i_ind[hit_1], :] = e2h(xyz[i_ind, :] + a1[:, None] * dir_e[i_ind, :], 1)[hit_1, :]
            interpos[i_ind[hit_2], :] = e2h(xyz[i_ind, :] + a2[:, None] * dir_e[i_ind, :], 1)[hit_2, :]


            trans, rot, zoom, shear = decompose44(self.pos4d)
            # interpos_local in z direction is in local coordinates, i.e.
            # the x coordiante is 0..1, but we want that in units of the
            # global coordinate system.
            interpos_local[:, 1] = interpos_local[:, 1] * zoom[2]
            interpos = np.dot(self.pos4d, interpos.T).T

        return intersect, interpos, interpos_local
コード例 #24
0
ファイル: geometry.py プロジェクト: Chandra-MARX/marxs
 def __getitem__(self, value):
     if value == 'R':
         trans, rot, zoom, shear = decompose44(self.pos4d)
         return zoom[0]
     else:
         return super(Cylinder, self).__getitem__(value)
コード例 #25
0
ファイル: detector.py プロジェクト: hamogu/marxs
    def intersect(self, dir, pos, transform=True):
        '''Calculate the intersection point between a ray and the element

        Parameters
        ----------
        dir : `numpy.ndarray` of shape (N, 4)
            homogeneous coordinates of the direction of the ray
        pos : `numpy.ndarray` of shape (N, 4)
            homogeneous coordinates of a point on the ray
        transform : bool
            If ``True``, input is in global coordinates and needs to be transformed
            here for the calculations; if ``False`` input is in local coordinates.

        Returns
        -------
        intersect :  boolean array of length N
            ``True`` if an intersection point is found.
        interpos : `numpy.ndarray` of shape (N, 4)
            homogeneous coordinates of the intersection point. Values are set
            to ``np.nan`` is no intersecton point is found.
        interpos_local : `numpy.ndarray` of shape (N, 2)
            phi, z coordiantes (in the local frame) for one of the intersection points.
            If both intersection points are required, reset ``self.inner`` and call this
            function again.
        '''
        # This could be moved to a general function
        if not np.all(dir[:, 3] == 0):
            raise ValueError('First input must be direction vectors.')
        # Could test pos, too...
        if transform:
            invpos4d = np.linalg.inv(self.pos4d)
            dir = np.dot(invpos4d, dir.T).T
            pos = np.dot(invpos4d, pos.T).T

        xyz = h2e(pos)

        # Solve quadratic equation in steps. a12 = (-xr +- sqrt(xr - r**2(x**2 - R**2)))
        xy = xyz[:, :2]
        r = dir[:, :2]
        underroot = (np.einsum('ij,ij->i', xy, r))**2 - np.sum(r**2, axis=1) * (np.sum(xy**2, axis=1) - 1.)
        intersect = (underroot >= 0)
        i = intersect  # just a shorthand because it's used so much below

        interpos_local = np.ones((pos.shape[0], 2))
        interpos_local[:] = np.nan
        interpos = np.ones_like(pos)
        interpos[:] = np.nan

        if intersect.sum() > 0:
            b = np.sum(xy[i] * r[i], axis=1)
            denom = np.sum(r[i]**2, axis=1)
            a1 = (- b + np.sqrt(underroot[i])) / denom
            a2 = (- b - np.sqrt(underroot[i])) / denom
            x1 = xy[i, :] + a1[:, np.newaxis] * r[i, :]
            apick = np.where(self._inwardsoutwards * np.sum(x1 * r[i, :], axis=1) >=0, a1, a2)
            xy_p = xy[i, :] + apick[:, np.newaxis] * r[i, :]
            phi = np.arctan2(xy_p[:, 1], xy_p[:, 0])
            # Shift phi by offset, then wrap to that it is in range [-pi, pi]
            interpos_local[i, 0] = (phi - self.phi_offset + np.pi) % (2 * np.pi) - np.pi
            # Those look like they hit in the xy plane.
            # Still possible to miss if z axis is too large.
            # Calculate z-coordiante at intersection
            interpos_local[intersect, 1] = xyz[i, 2] + apick * dir[i, 2]
            interpos[i, :2] = xy_p
            interpos[i, 2] = interpos_local[i, 1]
            interpos[i, 3] = 1
            # set those elements on intersect that miss in z to False
            trans, rot, zoom, shear = decompose44(self.pos4d)
            z_p = interpos[i, 2]
            intersect[i.nonzero()[0][np.abs(z_p) > 1]] = False
            # Now reset everything to nan that does not intersect
            interpos_local[~i, :] = np.nan
            # interpos_local in z direction is in local coordinates, i.e.
            # the x coordiante is 0..1, but we want that in units of the
            # global coordinate system.
            interpos_local[:, 1] = interpos_local[:, 1] * zoom[2]
            interpos[~i, :] = np.nan

            interpos = np.dot(self.pos4d, interpos.T).T

        return intersect, interpos, interpos_local
コード例 #26
0
def register3D_SIFT_wrapper(dataset_files, in_folder, out_folder, reg_config):
    """
    Registers the similarity transformation exploiting the sift3D library.
    https://github.com/bbrister/SIFT3D
    
    returns transforms for each time point which subsequently applied to each image?  
    """
    import matlab.engine
    import scipy.io as spio
    import os
    import shutil
    import pylab as plt
    from tqdm import tqdm
    import time
    import pylab as plt
    import Visualisation.imshowpair as imshowpair
    from skimage.exposure import rescale_intensity

    #     start the python matlab engine.
    eng = matlab.engine.start_matlab()

    fio.mkdir(
        out_folder
    )  # check that the output folder exists, create if does not exist.

    print 'registration'

    if reg_config['mode'] == 1:
        tforms = []
        translate_matrixs = []

        datasetsave_files = np.hstack([
            dataset_files[2 * i + 1].replace(in_folder, out_folder)
            for i in range(len(dataset_files) // 2)
        ])

        for i in tqdm(range(len(dataset_files) // 2)):

            t1 = time.time()
            im1file = dataset_files[2 * i]
            im2file = dataset_files[2 * i + 1]

            print 'registering SIFT'
            tmatrix = eng.register3D_SIFT_wrapper(im1file, im2file,
                                                  datasetsave_files[i],
                                                  reg_config['downsample'],
                                                  reg_config['lib_path'],
                                                  reg_config['return_img'])
            tmatrix = np.asarray(tmatrix)
            tforms.append(tmatrix)
            print tmatrix
            """
            if matlab doesn't save matrix then we use python to do so.
            """
            if reg_config['return_img'] != 1:

                print 'reading image'
                im1 = fio.read_multiimg_PIL(im1file)
                im2 = fio.read_multiimg_PIL(im2file)

                print 'finished reading image'
                # restrict the tranformation to affine.
                affine = np.zeros((4, 4))
                affine[:-1, :] = tmatrix.copy()
                affine[-1] = np.array([0, 0, 0, 1])

                # decomposition to zero out scaling and shear (rigid transformation)
                T, R, Z, S = decompose44(affine)
                affine = compose(T, R, np.ones(3),
                                 np.zeros(3))  # no scaling, no shears.

                print 'affine matrix'
                print affine

                im2 = np.uint8(
                    tf.apply_affine_tform(im2.transpose(1, 2, 0), affine,
                                          np.array(im1.shape)[[1, 2, 0]]))
                im2 = im2.transpose(2, 0, 1)

                # realign and correct the translation artifact.
                im2, translate_matrix = align_centers(im1, im2)
                translate_matrixs.append(translate_matrix)

                print 'saving'
                fio.save_multipage_tiff(im2, datasetsave_files[i])

            t2 = time.time()

            print 'elapsed time: ', t2 - t1

    if reg_config['mode'] == 2:
        print 'running sequential registration'
        datasetsave_files = np.hstack(
            [f.replace(in_folder, out_folder) for f in dataset_files])
        translate_matrixs = []

        if reg_config['return_img'] == 1:
            tforms = eng.register3D_SIFT_wrapper_batch(
                dataset_files, datasetsave_files, reg_config['downsample'],
                reg_config['lib_path'], reg_config['mode'])
        else:
            print 'running python mode'
            tforms = []
            # set the fixed image.
            fixed = fio.read_multiimg_PIL(dataset_files[0])
            fio.save_multipage_tiff(fixed, datasetsave_files[0])

            fixed_file = datasetsave_files[0]
            for i in tqdm(range(len(dataset_files) - 1)):
                moving_file = dataset_files[i + 1]

                print 'registering SIFT'
                tmatrix = eng.register3D_SIFT_wrapper(fixed_file, moving_file,
                                                      datasetsave_files[i + 1],
                                                      reg_config['downsample'],
                                                      reg_config['lib_path'],
                                                      reg_config['return_img'])
                tmatrix = np.asarray(tmatrix)
                tforms.append(tmatrix)
                """
                Apply the transforms.
                """
                im1 = fio.read_multiimg_PIL(fixed_file)
                im2 = fio.read_multiimg_PIL(moving_file)

                affine = np.zeros((4, 4))
                affine[:-1, :] = tmatrix.copy()
                affine[-1] = np.array([0, 0, 0, 1])

                # decomposition
                T, R, Z, S = decompose44(affine)  # S is shear!
                affine = compose(T, R, np.ones(3), np.zeros(
                    3))  # constant scale, allow shear.(since there is wiggle?)

                print 'compose affine'
                print affine
                print 'applying transform'
                im2 = np.uint8(
                    tf.apply_affine_tform(im2.transpose(1, 2, 0), affine,
                                          np.array(im1.shape)[[1, 2, 0]]))
                im2 = im2.transpose(2, 0, 1)

                # realign and correct the translation artifact.
                print 'realigning centers'
                im2, translate_matrix = align_centers(im1, im2)
                translate_matrixs.append(translate_matrix)
                #                translate_matrixs.append(affine)

                fio.save_multipage_tiff(im2, datasetsave_files[i + 1])

                comb = imshowpair.checkerboard_imgs(im1[:, 1000],
                                                    im2[:, 1000],
                                                    grid=(10, 10))

                plt.figure()
                plt.imshow(rescale_intensity(comb / 255.))
                plt.show()

                # update the savefile.
                fixed_file = datasetsave_files[i + 1]

    tforms = np.array(tforms)
    translate_matrixs = np.array(translate_matrixs)

    spio.savemat(
        os.path.join(out_folder, 'tforms_view_align.mat'), {
            'files': dataset_files,
            'config': reg_config,
            'view_tforms': tforms,
            'translate_tforms': translate_matrixs
        })
    """
    Stop the matlab engine? to prevent hangups. 
    """
    #    eng.quit()

    return (tforms, translate_matrixs)
コード例 #27
0
    def generate_elements(self):
        '''Initialize all optical elements.

        After any of the ``elem_pos``, ``elem_uncertainty`` or
        ``uncertainty`` attributes has changed, `generate_elements` needs to be
        called to regenerate the positions of the individual elements using

        - the global position of ``Parallel.pos4d``
        - the position of each element ``Parallel.elem_pos`` relativ to the global position
        - the global uncertainty `uncertainty`.
        - the uncertainty for individual facets.
        '''

        self.elements = []

        for i in range(len(self.elem_pos)):
            # _parse_position_keywords pops off keywords, thus operate on a copy here
            elem_args = self.elem_args.copy()
            # check if elem_args is the same for every element
            specific_elem_args = {}
            for k, v in elem_args.items():
                if isinstance(v, list) and (len(v) == len(self.elem_pos)):
                    specific_elem_args[k] = v[i]
                else:
                    specific_elem_args[k] = v
            if 'name' not in specific_elem_args:
                specific_elem_args['name'] = 'Elem {0} in {1}'.format(
                    i, self.name)

            elem_pos4d = _parse_position_keywords(specific_elem_args)
            telem, relem, zelem, Selem = decompose44(elem_pos4d)
            if not np.allclose(Selem, 0.):
                raise ValueError(
                    'pos4 for elem includes shear, which is not supported here.'
                )

            e_center, e_rot, e_zoom, stemp = decompose44(self.elem_pos[i])
            tsigelem, rsigelem, zsigelem, stemp = decompose44(
                self.elem_uncertainty[i])
            if not np.allclose(stemp, 0.):
                raise SimulationSetupError(
                    'Shear is not supported in the elem uncertainty.')
            # Will be able to write this so much better in python 3.5,
            # but for now I don't want to nest np.dot too much so here it goes
            f_pos4d = np.eye(4)
            for m in reversed([
                    self.pos4d,  # global position of ParallelElement
                    self.uncertainty,  # uncertainty in global positioning
                    translation2aff(
                        tsigelem),  # uncertaintig in translation for elem
                    translation2aff(
                        e_center),  # translate elem center to global center
                    translation2aff(telem),  # offset for all elem. Usually 0.
                    mat2aff(rsigelem),  # uncertainty in rotation for elem
                    mat2aff(e_rot),  # Rotation of individual elem
                    mat2aff(
                        relem),  # Rotation for all  elem, e.g. CAT gratings
                    zoom2aff(zsigelem),  # uncertainty in the zoom
                    zoom2aff(e_zoom),  # zoom of individual elem
                    zoom2aff(zelem),  # sets size for all elem
            ]):
                assert m.shape == (4, 4)
                f_pos4d = np.dot(m, f_pos4d)
            self.elements.append(
                self.elem_class(pos4d=f_pos4d, id_num=i, **specific_elem_args))
コード例 #28
0
def jip_align(source_file, target_file, outdir, jipdir, prefix="w",
              auto=False, non_linear=False, fslconfig=DEFAULT_FSL_PATH):
    """ Register a source image to a taget image using the 'jip_align'
    command.

    Parameters
    ----------
    source_file: str (mandatory)
        the source Nifti image.
    target_file: str (mandatory)
        the target Nifti masked image.
    outdir: str (mandatory)
        the destination folder.
    jipdir: str (mandatory)
        the jip binary path.
    prefix: str (optional, default 'w')
        prefix the generated file with this character.
    auto: bool (optional, default False)
        if set control the JIP window with the script.
    non_linear: bool (optional, default False)
        in the automatic mode, decide or not to compute the non-linear
        deformation field.
    fslconfig: str (optional)
        the FSL .sh configuration file.

    Returns
    -------
    register_file: str
        the registered image.
    register_mask_file: str
        the registered and masked image.
    native_masked_file: str
        the masked image in the native space.
    """
    # Check input image orientation: must be the same
    same_orient, orients = check_orientation([source_file, target_file])
    if not same_orient:
        print(
            "[WARNING] Source file '{0}' ({2}) and taget file '{1}' ({3}) "
            "must have the same orientation for JIP to work properly.".format(
                source_file, target_file, orients[0], orients[1]))

    # Try to init the affine deformation
    # ToDo: find a way to init the JIP deformation
    if False:
        nb_cpus = multiprocessing.cpu_count()
        init_file = os.path.join(outdir, "init_affine.mat")
        init = AffineInitializer()
        init.inputs.fixed_image = target_file
        init.inputs.moving_image = source_file
        init.inputs.num_threads = nb_cpus
        init.inputs.out_file = init_file
        init.run()
        init_source_file = os.path.join(outdir, "init_source.nii.gz")
        at = ApplyTransforms()
        at.inputs.dimension = 3
        at.inputs.input_image = source_file
        at.inputs.reference_image = target_file
        at.inputs.output_image = init_source_file
        at.inputs.transforms = init_file
        at.inputs.interpolation = "BSpline"
        at.inputs.num_threads = nb_cpus
        at.run()
        # From https://github.com/ANTsX/ANTs/wiki/ITK-affine-transform-conversion
        # From https://github.com/netstim/leaddbs/blob/master/helpers/ea_antsmat2mat.m
        init_mat = loadmat(init_file)
        afftransform = init_mat["AffineTransform_double_3_3"]
        m_center = init_mat["fixed"]
        mat = numpy.eye(4)
        mat[:3, :3] = afftransform[:9].reshape(3, 3).T
        m_translation = afftransform[9:]
        m_offset = m_translation + m_center - numpy.dot(mat[:3, :3], m_center)
        mat[:3, 3] = m_offset.squeeze()
        mat = numpy.linalg.inv(mat)
        #rotation = swap_affine(axes="LPS")
        #mat = numpy.dot(rotation, mat)
        ras_to_lps = numpy.ones((4, 4))
        ras_to_lps[2, :2] = -1
        ras_to_lps[:2, 2:] = -1
        mat = mat * ras_to_lps
        print(mat)
        trans, rot, zoom, shear = decompose44(mat)
        euler = numpy.asarray(mat2euler(rot, axes='sxyz')) * 180. / numpy.pi
        print(trans, euler, zoom, shear)
        align_file = os.path.join(outdir, "align.com")
        im = nibabel.load(source_file)
        orig = im.affine[:3, 3]
        print(orig)
        shift = orig - trans
        with open(align_file, "wt") as of:
            of.write("set registration-translations {0} \n".format(
                " ".join([str(elem) for elem in shift])))

    # Change current working directory
    cwd = os.getcwd()
    os.chdir(outdir)

    # Only support uncompressed Nifti
    source_file = ungzip_file(source_file, prefix="", outdir=outdir)
    target_file = ungzip_file(target_file, prefix="", outdir=outdir)

    # Create jip environment
    jip_envriron = os.environ
    jip_envriron["JIP_HOME"] = os.path.dirname(jipdir)
    if "PATH" in jip_envriron:
        jip_envriron["PATH"] = jip_envriron["PATH"] + ":" + jipdir
    else:
        jip_envriron["PATH"] = jipdir

    # Copy source file
    align_file = os.path.join(outdir, "align.com")
    cmd = ["align", source_file, "-t", target_file]
    if auto:
        if non_linear:
            auto_cmd = cmd + ["-L", "111111111111", "-W", "111", "-a"]
        else:
            auto_cmd = cmd + ["-L", "111111000000", "-W", "000", "-A"]
        if os.path.isfile(align_file):
            auto_cmd += ["-I"]
        subprocess.call(auto_cmd, env=jip_envriron)  
    else:
        print(" ".join(cmd))
        subprocess.call(cmd, env=jip_envriron)
    if not os.path.isfile(align_file):
        raise ValueError(
            "No 'align.com' file in '{0}' folder. JIP has probably failed: "
            "'{1}'".format(outdir, " ".join(cmd)))

    # Get the apply nonlinear deformation jip batches
    aplly_nonlin_batch = os.path.join(
        os.path.dirname(preproc.__file__), "resources", "apply_nonlin.com")
    aplly_inv_nonlin_batch = os.path.join(
        os.path.dirname(preproc.__file__), "resources", "apply_inv_nonlin.com")

    # Resample the source image
    register_file = os.path.join(outdir, prefix + os.path.basename(source_file))
    cmd = ["jip", aplly_nonlin_batch, source_file, register_file]
    subprocess.call(cmd, env=jip_envriron)

    # Apply mask
    if os.path.isfile(register_file + ".gz"):
        os.remove(register_file + ".gz")
    register_mask_fileroot = os.path.join(
        outdir, "m" + prefix + os.path.basename(source_file).split(".")[0])
    register_mask_file = apply_mask(
        input_file=register_file,
        output_fileroot=register_mask_fileroot,
        mask_file=target_file,
        fslconfig=fslconfig)

    # Send back masked image to original space
    register_mask_file = ungzip_file(register_mask_file, prefix="",
                                     outdir=outdir)
    native_masked_file = os.path.join(
        outdir, "n" + prefix + os.path.basename(register_mask_file))
    cmd = ["jip", aplly_inv_nonlin_batch, register_mask_file,
           native_masked_file]
    subprocess.call(cmd, env=jip_envriron)              

    # Restore current working directory and gzip output
    os.chdir(cwd)
    register_file = gzip_file(
        register_file, prefix="", outdir=outdir,
        remove_original_file=True)
    register_mask_file = gzip_file(
        register_mask_file, prefix="", outdir=outdir,
        remove_original_file=True)
    native_masked_file = gzip_file(
        native_masked_file, prefix="", outdir=outdir,
        remove_original_file=True)

    return register_file, register_mask_file, native_masked_file, align_file
コード例 #29
0
    def intersect(self, dir, pos, transform=True):
        '''Calculate the intersection point between a ray and the element

        Parameters
        ----------
        dir : `numpy.ndarray` of shape (N, 4)
            homogeneous coordinates of the direction of the ray
        pos : `numpy.ndarray` of shape (N, 4)
            homogeneous coordinates of a point on the ray
        transform : bool
            If ``True``, input is in global coordinates and needs to be transformed
            here for the calculations; if ``False`` input is in local coordinates.

        Returns
        -------
        intersect :  boolean array of length N
            ``True`` if an intersection point is found.
        interpos : `numpy.ndarray` of shape (N, 4)
            homogeneous coordinates of the intersection point. Values are set
            to ``np.nan`` is no intersecton point is found.
        interpos_local : `numpy.ndarray` of shape (N, 2)
            phi, z coordiantes (in the local frame) for one of the intersection points.
            If both intersection points are required, reset ``self.inner`` and call this
            function again.
        '''
        # This could be moved to a general function
        if not np.all(dir[:, 3] == 0):
            raise ValueError('First input must be direction vectors.')
        # Could test pos, too...
        if transform:
            invpos4d = np.linalg.inv(self.pos4d)
            dir = np.dot(invpos4d, dir.T).T
            pos = np.dot(invpos4d, pos.T).T

        xyz = h2e(pos)

        # Solve quadratic equation in steps. a12 = (-xr +- sqrt(xr - r**2(x**2 - R**2)))
        xy = xyz[:, :2]
        r = dir[:, :2]
        underroot = (np.einsum(
            'ij,ij->i', xy,
            r))**2 - np.sum(r**2, axis=1) * (np.sum(xy**2, axis=1) - 1.)
        intersect = (underroot >= 0)
        i = intersect  # just a shorthand because it's used so much below

        interpos_local = np.ones((pos.shape[0], 2))
        interpos_local[:] = np.nan
        interpos = np.ones_like(pos)
        interpos[:] = np.nan

        if intersect.sum() > 0:
            b = np.sum(xy[i] * r[i], axis=1)
            denom = np.sum(r[i]**2, axis=1)
            a1 = (-b + np.sqrt(underroot[i])) / denom
            a2 = (-b - np.sqrt(underroot[i])) / denom
            x1 = xy[i, :] + a1[:, np.newaxis] * r[i, :]
            apick = np.where(
                self._inwardsoutwards * np.sum(x1 * r[i, :], axis=1) >= 0, a1,
                a2)
            xy_p = xy[i, :] + apick[:, np.newaxis] * r[i, :]
            phi = np.arctan2(xy_p[:, 1], xy_p[:, 0])
            # Shift phi by offset, then wrap to that it is in range [-pi, pi]
            interpos_local[
                i, 0] = (phi - self.phi_offset + np.pi) % (2 * np.pi) - np.pi
            # Those look like they hit in the xy plane.
            # Still possible to miss if z axis is too large.
            # Calculate z-coordiante at intersection
            interpos_local[intersect, 1] = xyz[i, 2] + apick * dir[i, 2]
            interpos[i, :2] = xy_p
            interpos[i, 2] = interpos_local[i, 1]
            interpos[i, 3] = 1
            # set those elements on intersect that miss in z to False
            trans, rot, zoom, shear = decompose44(self.pos4d)
            z_p = interpos[i, 2]
            intersect[i.nonzero()[0][np.abs(z_p) > 1]] = False
            # Now reset everything to nan that does not intersect
            interpos_local[~i, :] = np.nan
            # interpos_local in z direction is in local coordinates, i.e.
            # the x coordiante is 0..1, but we want that in units of the
            # global coordinate system.
            interpos_local[:, 1] = interpos_local[:, 1] * zoom[2]
            interpos[~i, :] = np.nan

            interpos = np.dot(self.pos4d, interpos.T).T

        return intersect, interpos, interpos_local