コード例 #1
0
 def testEulers2(self):
     for i in range(100):
         y, p, r = randnums(3, -math.pi * 2, math.pi * 2)
         r1 = rotator(y, p, r)
         self.assertEqual(
             r1,
             rotator(0, 0, r) * rotator(y, 0, 0) * rotator(0, p, 0))
コード例 #2
0
 def testFromTo2(self):
     for i in range(100):
         x, y, z = randnums(3, -5, 5)
         v = vec3(x, y, z)
         r = rotator(v, -v)
         self.assertEqual(r, rotator(
             vec3(1, 0, 0).cross(v),
             0))  # TODO: wanted to actually test 180 degree rotators
コード例 #3
0
 def testMatrix1(self):
     for i in range(100):
         a = randangle()
         m = [
             math.cos(a), 0,
             math.sin(a), 0, 1, 0, -math.sin(a), 0,
             math.cos(a)
         ]
         r = rotator(*m)
         self.assertEqual(r, rotator(vec3(0, 1, 0), a))
コード例 #4
0
 def testMatrix3(self):
     for i in range(100):
         y, p, r = randnums(3, -math.pi * 2, math.pi * 2)
         r1 = rotator(y, p, r)
         y, p, r = randnums(3, -math.pi * 2, math.pi * 2)
         r2 = rotator(y, p, r)
         m1 = r1.toMatrix()
         m2 = r2.toMatrix()
         m = np.asarray(m1).dot(np.asarray(m2)).flat
         eqas_(listSum((r1 * r2).toMatrix()), m)
コード例 #5
0
 def testXis1(self):
     '''Test the xi values of points on the plane of a SharedImage, calls SharedImage.getPlaneXi().'''
     si = SharedImage('', vec3(), rotator(), (10, 10))
     self.assertEqual(vec3(), si.getPlaneXi(vec3()))
     self.assertEqual(vec3(1, 1), si.getPlaneXi(vec3(10, -10)))
     self.assertEqual(vec3(0.5, 0.5), si.getPlaneXi(vec3(5, -5)))
     self.assertEqual(vec3(0.5, 0.5), si.getPlaneXi(vec3(5, -5)))
コード例 #6
0
ファイル: NiftiPlugin.py プロジェクト: liu3xing3long/Eidolon
        def _loadAnalyzeFile(filename, name, imgObj, task):
            with f:
                filename = Future.get(filename)
                name = name or self.mgr.getUniqueObjName(
                    splitPathExt(filename)[1])
                img = imgObj or nibabel.load(filename)

                dat = dat = np.asanyarray(img.dataobj)
                hdr = dict(img.get_header())
                hdr['filename'] = filename

                pixdim = hdr['pixdim']
                interval = float(pixdim[4])

                if interval == 0.0 and len(
                        img.shape) == 4 and img.shape[-1] > 1:
                    interval = 1.0

                spacing = vec3(pixdim[1], pixdim[2], pixdim[3])
                dat = eidolon.transposeRowsColsNP(
                    dat)  # transpose from row-column to column-row

                obj = self.createObjectFromArray(name,
                                                 dat,
                                                 interval,
                                                 0,
                                                 vec3(),
                                                 rotator(),
                                                 spacing,
                                                 task=task)
                obj.source = hdr
                f.setObject(obj)
コード例 #7
0
 def testIdent1(self):
     '''Test the default rotator which should represent the identity transformation.'''
     for i in range(100):
         x, y, z = randnums(3, -5, 5)
         v = vec3(x, y, z)
         r = rotator()
         self.assertEqual(r * v, v)
コード例 #8
0
 def testInv1(self):
     for i in range(100):
         x, y, z = randnums(3, -5, 5)
         v = vec3(x, y, z)
         y, p, r = randnums(3, -math.pi * 2, math.pi * 2)
         r1 = rotator(y, p, r)
         self.assertEqual(r1 * (r1 / v), v)
コード例 #9
0
 def testMatrix2(self):
     for i in range(100):
         a = randangle()
         r = rotator(vec3(1, 0, 0), a)
         eqas_(listSum(r.toMatrix()),
               (1, 0, 0, 0, 0, math.cos(a), -math.sin(a), 0, 0, math.sin(a),
                math.cos(a), 0, 0, 0, 0, 1))
コード例 #10
0
 def testXis2(self):
     '''Test the xi values of corners of a SharedImage, calls getPlaneXi().'''
     si = SharedImage('', vec3(1, -2, 3), rotator(0.1, -0.2, 0.3), (10, 10),
                      (0.678, 0.789))
     corners = si.getCorners()
     self.assertEqual(vec3(), si.getPlaneXi(corners[0]))
     self.assertEqual(vec3(1, 1), si.getPlaneXi(corners[-1]))
     self.assertEqual(vec3(0.5, 0.5), si.getPlaneXi(si.center))
コード例 #11
0
 def testXis3(self):
     '''Test the xi values of points on the plane of a SharedImage, calls SharedImage.getPlaneXi().'''
     pos = vec3(5, -6, 7)
     si = SharedImage('', pos, rotator(), (10, 10))
     self.assertEqual(vec3(), si.getPlaneXi(pos))
     self.assertEqual(vec3(1, 1), si.getPlaneXi(pos + vec3(10, -10)))
     self.assertEqual(vec3(0.5, 0.5, 5),
                      si.getPlaneXi(pos + vec3(5, -5, 5)))
コード例 #12
0
 def testXis4(self):
     '''Test the xi values of points on the plane of a SharedImage, calls SharedImage.getPlaneXi().'''
     pos = vec3(5, -6, 7)
     dim = (0.678, 0.789)
     si = SharedImage('', pos, rotator(), (10, 10), dim)
     self.assertEqual(vec3(), si.getPlaneXi(pos))
     self.assertEqual(vec3(1, 1),
                      si.getPlaneXi(pos + vec3(10 * dim[0], -10 * dim[1])))
     self.assertEqual(vec3(0.5, 0.5, 5),
                      si.getPlaneXi(pos + vec3(5 * dim[0], -5 * dim[1], 5)))
コード例 #13
0
ファイル: NiftiPlugin.py プロジェクト: liu3xing3long/Eidolon
    def setUp(self):
        self.tempdir = tempfile.mkdtemp()
        self.plugin = eidolon.getSceneMgr().getPlugin('Nifti')

        self.vfunc = lambda x, y, z, t: (x + 1) * 1000 + (y + 1) * 100 + (
            z + 1) * 10 + t + 1
        self.volarr = np.fromfunction(self.vfunc, (21, 33, 46, 17))
        self.vpos = vec3(-10, 20, -15)
        self.vrot = rotator(0.1, -0.2, 0.13)

        self.vol = self.plugin.createObjectFromArray('TestVolume',
                                                     self.volarr,
                                                     pos=self.vpos,
                                                     rot=self.vrot)
コード例 #14
0
def importImages(x4, plugin):
    '''
    Import images from the X4DF object `x4', returning a list of ImageSceneObject instances. The `plugin' must be an
    ImageScenePlugin instance used to create the objects.
    '''
    arrs = {a.name: a for a in x4.arrays}
    results = []

    for im in x4.images:
        name, timescheme, trans, imagedata, _ = im
        images = []
        filenames = []
        tstart, tstep = timescheme or (0, 0)
        trans = trans or idTransform

        for i, imgdat in enumerate(imagedata):
            src, timestep, imgtrans, _ = imgdat
            arr = arrs[src].data
            imgtrans = imgtrans or trans

            filenames.append(arrs[src].filename)

            if timestep is None:
                offset, interval = tstart, tstep
            else:
                offset, interval = tstart + i * tstep, 0

            arr = reverseAxes(
                arr
            )  # array is stored in inverse index order from what is expected

            pos = vec3(*imgtrans.position)
            rot = rotator(*imgtrans.rmatrix.flatten())
            spacing = vec3(*imgtrans.scale) * vec3(
                arr.shape[1], arr.shape[0],
                arr.shape[2] if len(arr.shape) > 2 else 0).inv()

            obj = plugin.createObjectFromArray('tmp', arr, interval, offset,
                                               pos, rot, spacing)
            images += obj.images

        results.append(
            eidolon.ImageSceneObject(name,
                                     None,
                                     images,
                                     filenames=list(filter(bool, filenames))))

    return results
コード例 #15
0
    def loadImageStackObject(self,name,filenames,pos=vec3(),rot=rotator(),spacing=(1.0,1.0),imgsep=1.0,sortIndex=None,regex=None,reverse=False,task=None):
        '''
        Loads a stack of images (or a sequence of stacks), ordered bottom up, into a ImageSceneObject. If
        `sortIndex' is not None, this is the sorting index in the file names used to sort the stack. The start
        position `pos' is intepreted as the top left position of the bottom-most image. If `filenames' is a list
        of filenames only, the series is not timed, however if it's a list of lists of filenames then each sublist
        is (optionally) sorted and then loaded into a time series object.
        '''

        isTimed=eidolon.isIterable(filenames[0]) and not isinstance(filenames[0],str)

        if isTimed:
            if sortIndex!=None:
                filenames=[sortFilenameList(fn,sortIndex,regex) for fn in filenames]

            if reverse:
                for f in filenames:
                    f.reverse()

            positions=[pos+(rot*vec3(0,0,imgsep*i)) for i in range(len(filenames[0]))]

            imagesteps=[loadImageStack(fn,self.mgr.scene.loadImageFile,positions,rot,spacing,task) for fn in filenames]

            for i,imgs in enumerate(imagesteps):
                for img in imgs:
                    img.timestep=i

            images=listSum(imagesteps)
            filenames=listSum(filenames)
        else:
            if sortIndex!=None:
                filenames=sortFilenameList(filenames,sortIndex,regex)

            if reverse:
                filenames.reverse()

            positions=[pos+(rot*vec3(0,0,imgsep*i)) for i in range(len(filenames))]

            images=loadImageStack(filenames,self.mgr.scene.loadImageFile,positions,rot,spacing,task)

        return self.createSceneObject(name,images,filenames,isTimed)
コード例 #16
0
def getTransformFromInfo(offcenter, angulation, sliceorient, spacing,
                         dimensions):
    '''
    Returns a (vec3,rotator) pair for the position and orientation of an image given the ParRec parameters for
    offcenter position, angulation in degrees, slice orientation value from SliceOrientations, pixel spacing,
    and image dimensions.
    '''
    cy, cz, cx = offcenter
    theta, phi, rho = map(math.radians, angulation)
    refmat = np.array([[-1, 0, 0], [0, 0, 1], [0, -1, 0]])
    AFRtoLPS = np.array([[0, 0, 1], [1, 0, 0], [0, 1, 0]])
    torient = np.eye(3)

    # get the slice orientation transform matrix
    if sliceorient == SliceOrientations.Transverse:
        torient = np.array([[0, 1, 0], [-1, 0, 0], [0, 0, -1]])
    elif sliceorient == SliceOrientations.Sagittal:
        torient = np.array([[-1, 0, 0], [0, 0, -1], [0, 1, 0]])
    elif sliceorient == SliceOrientations.Coronal:
        torient = np.array([[0, 0, -1], [1, 0, 0], [0, 1, 0]])

    # convert angulation values to rotation matrices
    tap = np.array([[1, 0, 0], [0, math.cos(theta), -math.sin(theta)],
                    [0, math.sin(theta), math.cos(theta)]])
    tfh = np.array([[math.cos(phi), 0, math.sin(phi)], [0, 1, 0],
                    [-math.sin(phi), 0, math.cos(phi)]])
    trl = np.array([[math.cos(rho), -math.sin(rho), 0],
                    [math.sin(rho), math.cos(rho), 0], [0, 0, 1]])

    # compose transformations and convert to a rotator object
    dirmat = AFRtoLPS.dot(trl).dot(tap).dot(tfh).dot(refmat).dot(torient)
    rot = rotator(*dirmat.flat)

    # Since rotation is defined at the center of the image, need to add a rotated mid vector to the
    # position which is instead defined at the top left corner.
    midoffset = ((spacing * vec3(1, -1, 1)) *
                 (dimensions - vec3(1))) * 0.5 - spacing * vec3(0.5, -0.5, 0)
    pos = vec3(cx, cy, cz) - (rot * midoffset)

    return pos, rot
コード例 #17
0
 def testEulers5(self):
     for i in range(100):
         a = randangle()
         self.assertEqual(rotator(0, 0, a), rotator(vec3(0, 1, 0), a))
コード例 #18
0
 def testIdent2(self):
     '''Test a rotator specified as the angle around the zero vector is an identity transformation.'''
     r = rotator(vec3(), randangle())
     self.assertEqual(r, rotator())
コード例 #19
0
ファイル: NiftiPlugin.py プロジェクト: liu3xing3long/Eidolon
        def _saveFile(path, obj, kwargs, task):
            with f:
                assert isinstance(obj, ImageSceneObject)

                if os.path.isdir(path):
                    path = os.path.join(path, obj.getName())

                if not overwrite and os.path.exists(path):
                    raise IOError('File already exists: %r' % path)

                if not eidolon.hasExtension(path, 'nii', 'nii.gz'):
                    path += '.nii'

                if 'datatype' in kwargs:
                    datatype = kwargs.pop('datatype')
                elif isinstance(obj.source, dict) and 'datatype' in obj.source:
                    datatype = data_type_codes.dtype[int(
                        obj.source['datatype'])]
                else:
                    datatype = np.float32

                mat = self.getImageObjectArray(obj, datatype)
                dat = mat['array']
                pos = mat['pos']
                spacex, spacey, spacez = mat['spacing']
                rot = rotator(vec3(0, 0, 1), math.pi) * mat['rot'] * rotator(
                    vec3(0, 0, 1), -halfpi)
                toffset = mat['toffset']
                interval = mat['interval']

                affine = np.array(rot.toMatrix())
                affine[:, 3] = -pos.x(), -pos.y(), pos.z(), 1.0

                dat = eidolon.transposeRowsColsNP(
                    dat)  # transpose from row-column to column-row

                imgobj = nibabel.nifti1.Nifti1Image(dat, affine)

                # header info: http://nifti.nimh.nih.gov/pub/dist/src/niftilib/nifti1.h
                hdr = {
                    'pixdim':
                    np.array([
                        1.0, spacex, spacey, spacez if spacez != 0.0 else 1.0,
                        interval, 1.0, 1.0, 1.0
                    ], np.float32),
                    'toffset':
                    toffset,
                    'slice_duration':
                    interval,
                    'xyzt_units':
                    unit_codes['mm'] | unit_codes['msec'],
                    'qform_code':
                    xform_codes['aligned'],
                    'sform_code':
                    xform_codes['scanner'],
                    'datatype':
                    data_type_codes.code[datatype]
                }

                hdr.update(kwargs)

                for k, v in hdr.items():
                    if k in imgobj.header:
                        imgobj.header[k] = v

                nibabel.save(imgobj, path)

                if setFilenames:
                    obj.plugin.removeObject(obj)
                    obj.plugin = self
                    obj.source = dict(nibabel.load(path).get_header())
                    obj.source['filename'] = path
                elif isinstance(obj.source, dict) and 'filename' in obj.source:
                    obj.source['filename'] = path

                f.setObject(imgobj)
コード例 #20
0
 def testPlaneXiFunc(self):
     '''Tests the getPlaneXi function directly.'''
     v = vec3(*randnums(3, -5, 5))
     r = rotator(*randnums(4, -1, 1))
     self.assertEqual(vec3(0), getPlaneXi(v, v, r, vec3(1)))
コード例 #21
0
ファイル: NiftiPlugin.py プロジェクト: liu3xing3long/Eidolon
        def _loadNiftiFile(filename, name, imgObj, task):
            with f:
                filename = Future.get(filename)
                name = name or self.mgr.getUniqueObjName(
                    splitPathExt(filename)[1])
                img = imgObj or nibabel.load(filename)

                hdr = dict(img.header)
                hdr['filename'] = filename

                pixdim = hdr['pixdim']
                xyzt_units = hdr['xyzt_units']
                x = float(hdr['qoffset_x'])
                y = float(hdr['qoffset_y'])
                z = float(hdr['qoffset_z'])
                b = float(hdr['quatern_b'])
                c = float(hdr['quatern_c'])
                d = float(hdr['quatern_d'])
                toffset = float(hdr['toffset'])
                interval = float(pixdim[4])

                if interval == 0.0 and len(
                        img.shape) == 4 and img.shape[-1] > 1:
                    interval = 1.0

                qfac = float(pixdim[0]) or 1.0
                spacing = vec3(pixdim[1], pixdim[2], qfac * pixdim[3])

                if int(hdr['qform_code']) > 0:
                    position = vec3(-x, -y, z)
                    rot = rotator(
                        -c, b, math.sqrt(max(0, 1.0 -
                                             (b * b + c * c + d * d))),
                        -d) * rotator(vec3.Z(), halfpi)
                else:
                    affine = img.get_affine()
                    position = vec3(-affine[0, 3], -affine[1, 3], affine[2, 3])
                    rmat = np.asarray([
                        affine[0, :3] / -spacing.x(),
                        affine[1, :3] / -spacing.y(),
                        affine[2, :3] / spacing.z()
                    ])
                    rot = rotator(*rmat.flatten().tolist()) * rotator(
                        vec3.Z(), halfpi)

                xyzunit = xyzt_units & 0x07  # isolate space units with a bitmask of 7
                tunit = xyzt_units & 0x38  # isolate time units with a bitmask of 56

                if tunit == 0:  # if no tunit provided, try to guess
                    if interval < 1.0:
                        tunit = unit_codes['sec']
                    elif interval > 1000.0:
                        tunit = unit_codes['usec']

                # convert to millimeters
                if xyzunit == unit_codes['meter']:
                    position *= 1000.0
                    spacing *= 1000.0
                elif xyzunit == unit_codes['micron']:
                    position /= 1000.0
                    spacing /= 1000.0

                # convert to milliseconds
                if tunit == unit_codes['sec']:
                    toffset *= 1000.0
                    interval *= 1000.0
                elif tunit == unit_codes['usec']:
                    toffset /= 1000.0
                    interval /= 1000.0

                dobj = img.dataobj
                datshape = tuple(
                    d or 1 for d in dobj.shape
                )  # dimensions are sometimes given as 0 for some reason?

                # reading file data directly is expected to be faster than using nibabel, specifically by using memmap
                if filename.endswith('.gz'):
                    dat = img.get_data()
                    #dat=np.asanyarray(dobj) # same as the above

#                    with gzip.open(filename) as o: # TODO: not sure if this is any faster than the above
#                        o.seek(dobj.offset) # seek beyond the header
#                        dat=np.frombuffer(o.read(),dobj.dtype).reshape(datshape,order=dobj.order)
                else:
                    # mmap the image data below the header in the file
                    dat = np.memmap(dobj.file_like, dobj.dtype, 'r',
                                    dobj.offset, datshape, dobj.order)

                dat = eidolon.transposeRowsColsNP(
                    dat)  # transpose from row-column to column-row

                obj = self.createObjectFromArray(name,
                                                 dat,
                                                 interval,
                                                 toffset,
                                                 position,
                                                 rot,
                                                 spacing,
                                                 task=task)
                obj.source = hdr

                # apply slope since this isn't done automatically when using memmap/gzip
                if not filename.endswith('.gz'):
                    eidolon.applySlopeIntercept(obj,
                                                *img.header.get_slope_inter())

                f.setObject(obj)
コード例 #22
0
    def testRot1(self):
        '''Tests the creation of a SharedImage with the default vec3 and rotator value, calls SharedImage.getPlaneXi().'''
        si = SharedImage('', vec3(), rotator(), (1, 1))

        self.assertEqual(vec3(1), si.getPlaneXi(vec3(1, -1, 1)))
コード例 #23
0
 def testPlaneDef3(self):
     r = rotator(vec3(1, 0, 0), vec3(0, 0, 1), vec3(1, 0, 0), vec3(0, 1, 0))
     eqas_(r.getEulers(), (0, halfpi, 0))
コード例 #24
0
 def testAxis2(self):
     r = rotator(vec3(0, 0, -1), halfpi)
     eqas_(r.getEulers(), (-halfpi, 0, 0))
コード例 #25
0
 def testFromTo1(self):
     r = rotator(vec3(1, 0, 0), vec3(0, 1, 0))
     self.assertEqual(r, rotator(vec3(0, 0, 1), halfpi))
コード例 #26
0
 def testEulers1(self):
     for i in range(100):
         y, p, r = randnums(3, -math.pi * 2, math.pi * 2)
         r1 = rotator(y, p, r)
         self.assertEqual(r1, rotator(*r1.getEulers()))
コード例 #27
0
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# Eidolon is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along
# with this program (LICENSE.txt).  If not, see <http://www.gnu.org/licenses/>

from eidolon import ReprType,vec3, rotator,generateArrow,halfpi, MeshSceneObject,TriDataSet,AxesType

pos=vec3(-10,20,-15)
rot=rotator(0.1,-0.2,0.13)
w,h,d=31,42,53

nodesz,indsz=generateArrow(5)
nodesz=[(n+vec3.Z())*vec3(w,d,h)*vec3(0.1,0.1,0.5) for n in nodesz]
nodesx=[rotator(vec3(0,1,0),halfpi)*n for n in nodesz]
nodesy=[rotator(vec3(1,0,0),-halfpi)*n for n in nodesz]

nodes=[(rot*n)+pos for n in (nodesx+nodesy+nodesz)]
nlen=len(nodesz)
indices=indsz+[(i+nlen,j+nlen,k+nlen) for i,j,k in indsz]+[(i+nlen*2,j+nlen*2,k+nlen*2) for i,j,k in indsz]
field=[2.0]*nlen+[1.0]*nlen+[0.0]*nlen

axes=MeshSceneObject('Axes',TriDataSet('tris',nodes,indices,[('col',field)]))
mgr.addSceneObject(axes)
コード例 #28
0
 def testFullCircle1(self):
     r = rotator(vec3(1, 0, 0), math.pi * 2)
     self.assertEqual(r, rotator())