Package: xform
xform [WIP]xformis a library to transform spatial data from one space to another and
provides a common interface to combine different types of transforms.It was originally written fornavisto transform neurons from one brain template space to another and then
split off into a separate general-purpose package.Featuresvarious supported transforms (see below)chaining of transformsa template registry that tracks available transforms and plots paths to
get from a given source to the desired target template spaceSupported transformsCMTKwarp transformsElastixwarp transformsH5 deformation fieldsLandmark-based thin-plate spline transforms (powered bymorphops)Landmark-based least-moving square transforms (powered bymolesq)Affine transformationsInstall$ pip3 install xformAdditional dependencies:To use CMTK transforms, you need to haveCMTKinstalled and its binaries (specificallystreamxform) in a path wherexformcan find them (e.g./usr/local/bin).UsageSingle transformsAt the most basic level you can use individual transform fromxform.transforms:AffineTransformfor affine transforms using aaffine matrixCMTKtransformfor CMTK transformsElastixTransformfor Elastix transformsTPStransformorMovingLeastSquaresTransformfor landmark-based transformsH5transformfor deformation-field transforms using Hdf5 files
(specs)A quick example that uses an affine transform to scale coordinates by a factor
of 2:>>>importxform>>>importnumpyasnp>>># Generate the affine matrix>>>m=np.diag([2,2,2,2])>>># Create the transform>>>tr=xform.AffineTransform(m)>>># Some 3D points to transform>>>points=np.array([[1,1,1],[2,2,2],[3,3,3]])>>># Apply>>>xf=tr.xform(points)>>>xfarray([[2.,2.,2.],[4.,4.,4.],[6.,6.,6.]])>>># Transforms are invertible!>>>(-tr).xform(xf)array([[1.,1.,1.],[2.,2.,2.],[3.,3.,3.]])Transform sequencesIf you find yourself in a situation where you need to chain some transforms,
you can usexform.transforms.TransformSequenceto combine transforms.For example, let's say we have a CMTK transform that requires spatial data to
be in microns but our data is in nanometers:>>>fromxformimportCMTKtransform,AffineTransform,TransformSequence>>>importnumpyasnp>>># Initialize CMTK transform>>>cmtk=CMTKtransform('~/transform/target_source.list')>>># Create an affine transform to go from microns to nanometers>>>aff=AffineTransform(np.diag([1e3,1e3,1e3,1e3]))>>># Create a transform sequence>>>tr=TransformSequence([-aff,cmtk])>>># Apply transform>>>points=np.array([[1,1,1],[2,2,2],[3,3,3]])>>>xf=tr.xform(points)Bridging graphsWhen working with many interconnected transforms (e.g. A->B, B->C, B->D, etc.),
you can register the individual transforms and letxformplot the shortest
path to get from a given source to a given target for you:>>>importxform>>>fromxformimportCMTKtransform,AffineTransform,TransformRegistry>>>importnumpyasnp>>># Create a transform registry>>>registry=TransformRegistry()>>># Generate a couple transforms>>># Note that we now provide source and target labels>>>tr1=AffineTransform(np.diag([1e3,1e3,1e3,1e3]),...source_space='A',target_space='B')>>>cmtk=CMTKtransform('~/transform/C_B.list',...source_space='B',target_space='C')>>># Register the transforms>>>registry.register_transform([tr1,cmtk])>>># Now you ask the registry for the required transforms to move between spaces>>>path,trans_seq=registry.shortest_bridging_seq(source='A',target='C')>>>patharray(['A','B','C'],dtype='<U1')>>>trans_seqTransformSequencewith2transform(s)Custom transformsTODO