def test_rmsdev(): t1 = np.eye(4) t2 = affine.scaleOffsetXform([1, 1, 1], [2, 0, 0]) assert np.isclose(affine.rmsdev(t1, t2), 2) assert np.isclose(affine.rmsdev(t1, t2, R=2), 2) assert np.isclose(affine.rmsdev(t1, t2, R=2, xc=(1, 1, 1)), 2) t1 = np.eye(3) lastdist = 0 for i in range(1, 11): rot = np.pi * i / 10.0 t2 = affine.axisAnglesToRotMat(rot, 0, 0) result = affine.rmsdev(t1, t2) assert result > lastdist lastdist = result for i in range(11, 20): rot = np.pi * i / 10.0 t2 = affine.axisAnglesToRotMat(rot, 0, 0) result = affine.rmsdev(t1, t2) assert result < lastdist lastdist = result
def doMovieUpdate(self, overlay, opts): """Overrides :meth:`.CanvasPanel.doMovieUpdate`. For x/y/z axis movies, the scene is rotated. Otherwise (for time) the ``CanvasPanel`` implementation is called. """ if self.movieAxis >= 3: return canvaspanel.CanvasPanel.doMovieUpdate(self, overlay, opts) else: canvas = self.__canvas currot = canvas.opts.rotation rate = float(self.movieRate) rateMin = self.getAttribute('movieRate', 'minval') rateMax = self.getAttribute('movieRate', 'maxval') rate = 0.1 + 0.9 * (rate - rateMin) / (rateMax - rateMin) rate = rate * np.pi / 10 rots = [0, 0, 0] rots[self.movieAxis] = rate xform = affine.axisAnglesToRotMat(*rots) xform = affine.concat(xform, currot) canvas.opts.rotation = xform return np.copy(xform)
def lightPos(self): """Takes the values of :attr:`.Scene3DOpts.lightPos` and :attr:`.Scene3DOpts.lightDistance`, and converts it to a position in the display coordinate system. The ``Scene3DOpts.lightPos`` property contains rotations about the centre of the display bounding box, and the :attr:`.Scene3DOpts.lightDistance` property specifies the distance of the light from the bounding box centre. """ b = self.__displayCtx.bounds centre = np.array([ b.xlo + 0.5 * (b.xhi - b.xlo), b.ylo + 0.5 * (b.yhi - b.ylo), b.zlo + 0.5 * (b.zhi - b.zlo) ]) yaw, pitch, roll = self.opts.lightPos distance = self.opts.lightDistance yaw = yaw * np.pi / 180 pitch = pitch * np.pi / 180 roll = roll * np.pi / 180 rotmat = affine.axisAnglesToRotMat(pitch, roll, yaw) xform = affine.compose([1, 1, 1], [0, 0, 0], rotmat, origin=centre) lightPos = centre + [0, 0, distance * b.zlen] lightPos = affine.transform(lightPos, xform) return lightPos
def test_rotMatToAffine(seed): pi = np.pi pi2 = pi / 2 for i in range(100): rots = [ -pi + 2 * pi * np.random.random(), -pi2 + 2 * pi2 * np.random.random(), -pi + 2 * pi * np.random.random() ] if np.random.random() < 0.5: origin = None else: origin = np.random.random(3) rmat = affine.axisAnglesToRotMat(*rots) mataff = affine.rotMatToAffine(rmat, origin) rotaff = affine.rotMatToAffine(rots, origin) exp = np.eye(4) exp[:3, :3] = rmat exp[:3, 3] = origin assert np.all(np.isclose(mataff, rotaff))
def _rotateModeLeftMouseDrag(self, ev, canvas, mousePos, canvasPos): """Called on left mouse drag events in ``rotate`` mode. Modifies the canvas rotation matrix according to the X and Y mouse position (relative to the mouse down location). """ if self.__rotateMousePos is None: return w, h = canvas.GetSize() x0, y0 = self.__rotateMousePos x1, y1 = mousePos # Normalise x/y mouse pos to [-fac*pi, +fac*pi] fac = 1 x0 = -1 + 2 * (x0 / float(w)) * fac * np.pi y0 = -1 + 2 * (y0 / float(h)) * fac * np.pi x1 = -1 + 2 * (x1 / float(w)) * fac * np.pi y1 = -1 + 2 * (y1 / float(h)) * fac * np.pi xrot = x1 - x0 yrot = y1 - y0 rot = affine.axisAnglesToRotMat(yrot, 0, xrot) self.__lastRot = rot self.__rotateMousePos = mousePos canvas.opts.rotation = affine.concat(rot, self.__lastRot, self.__baseXform)
def swapdim(infile): basename = fslimage.removeExt(op.basename(infile)) outfile = '{}_swapdim.nii.gz'.format(basename) img = fslimage.Image(infile) data = img.data xform = img.voxToWorldMat data = data.transpose((2, 0, 1)) rot = affine.rotMatToAffine( affine.concat(affine.axisAnglesToRotMat(np.pi / 2, 0, 0), affine.axisAnglesToRotMat(0, 0, 3 * np.pi / 2))) xform = affine.concat(xform, affine.scaleOffsetXform((1, -1, -1), (0, 0, 0)), rot) fslimage.Image(data, xform=xform, header=img.header).save(outfile) return outfile
def get3DClipPlane(self, planeIdx): """A convenience method which calculates a point-vector description of the specified clipping plane. ``planeIdx`` is an index into the :attr:`clipPosition`, :attr:`clipAzimuth`, and :attr:`clipInclination`, properties. Returns the clip plane at the given ``planeIdx`` as an origin and normal vector, in the display coordinate system.. """ pos = self.clipPosition[ planeIdx] azimuth = self.clipAzimuth[ planeIdx] incline = self.clipInclination[planeIdx] b = self.bounds pos = pos / 100.0 azimuth = azimuth * np.pi / 180.0 incline = incline * np.pi / 180.0 xmid = b.xlo + 0.5 * b.xlen ymid = b.ylo + 0.5 * b.ylen zmid = b.zlo + 0.5 * b.zlen centre = [xmid, ymid, zmid] normal = [0, 0, -1] rot1 = affine.axisAnglesToRotMat(incline, 0, 0) rot2 = affine.axisAnglesToRotMat(0, 0, azimuth) rotation = affine.concat(rot2, rot1) normal = affine.transformNormal(normal, rotation) normal = affine.normalise(normal) offset = (pos - 0.5) * max((b.xlen, b.ylen, b.zlen)) origin = centre + normal * offset return origin, normal
def rotate(infile, rx, ry, rz): basename = fslimage.removeExt(op.basename(infile)) outfile = '{}_rotated_{}_{}_{}.nii.gz'.format(basename, rx, ry, rz) img = fslimage.Image(infile) rx = rx * np.pi / 180 ry = ry * np.pi / 180 rz = rz * np.pi / 180 rot = affine.axisAnglesToRotMat(rx, ry, rz) rot = affine.rotMatToAffine(rot) img.voxToWorldMat = affine.concat(rot, img.voxToWorldMat) img.save(outfile) return outfile
def test_rotMatToAxisAngles(seed): pi = np.pi pi2 = pi / 2 for i in range(100): rots = [ -pi + 2 * pi * np.random.random(), -pi2 + 2 * pi2 * np.random.random(), -pi + 2 * pi * np.random.random() ] rmat = affine.axisAnglesToRotMat(*rots) gotrots = affine.rotMatToAxisAngles(rmat) assert np.all(np.isclose(rots, gotrots))
def test_compose_and_decompose(): testfile = op.join(datadir, 'test_transform_test_compose.txt') lines = readlines(testfile) ntests = len(lines) // 4 for i in range(ntests): xform = lines[i * 4:i * 4 + 4] xform = np.genfromtxt(xform) scales, offsets, rotations, shears = affine.decompose(xform, shears=True) result = affine.compose(scales, offsets, rotations, shears=shears) assert np.all(np.isclose(xform, result, atol=1e-5)) # The decompose function does not support a # different rotation origin, but we test # explicitly passing the origin for # completeness scales, offsets, rotations, shears = affine.decompose(xform, shears=True) result = affine.compose(scales, offsets, rotations, origin=[0, 0, 0], shears=shears) assert np.all(np.isclose(xform, result, atol=1e-5)) # compose should also accept a rotation matrix rots = [np.pi / 5, np.pi / 4, np.pi / 3] rmat = affine.axisAnglesToRotMat(*rots) xform = affine.compose([1, 1, 1], [0, 0, 0], rmat) # And the angles flag should cause decompose # to return the rotation matrix, instead of # the axis angls sc, of, rot = affine.decompose(xform) scat, ofat, rotat = affine.decompose(xform, angles=True) scaf, ofaf, rotaf = affine.decompose(xform, angles=False) sc, of, rot = np.array(sc), np.array(of), np.array(rot) scat, ofat, rotat = np.array(scat), np.array(ofat), np.array(rotat) scaf, ofaf, rotaf = np.array(scaf), np.array(ofaf), np.array(rotaf) assert np.all(np.isclose(sc, [1, 1, 1])) assert np.all(np.isclose(of, [0, 0, 0])) assert np.all(np.isclose(scat, [1, 1, 1])) assert np.all(np.isclose(ofat, [0, 0, 0])) assert np.all(np.isclose(scaf, [1, 1, 1])) assert np.all(np.isclose(ofaf, [0, 0, 0])) assert np.all(np.isclose(rot, rots)) assert np.all(np.isclose(rotat, rots)) assert np.all(np.isclose(rotaf, rmat)) # decompose should accept a 3x3 # affine, and return translations of 0 affine.decompose(xform[:3, :3]) sc, of, rot = affine.decompose(xform[:3, :3]) sc, of, rot = np.array(sc), np.array(of), np.array(rot) assert np.all(np.isclose(sc, [1, 1, 1])) assert np.all(np.isclose(of, [0, 0, 0])) assert np.all(np.isclose(rot, rots))