Source code for pylablib.core.dataproc.ctransform_fallback
import numpy as np
_meye=np.eye(2,dtype="float")
_mt=np.array([[0,1],[1,0]])
_szero=np.zeros(2,dtype="float")
[docs]
class CLinear2DTransform:
"""Pure Python implementation of Cython-based linear 2D transform"""
def __init__(self, m=None, s=None):
self.m=_meye.copy() if m is None else m
self.s=_szero.copy() if s is None else s
self._set_inv()
def _set_inv(self):
d=self.m[0,0]*self.m[1,1]-self.m[0,1]*self.m[1,0]
self.mi=np.array([[self.m[1,1],-self.m[0,1]],[-self.m[1,0],self.m[0,0]]])/d
self.si=np.array([-(self.mi[0,0]*self.s[0]+self.mi[0,1]*self.s[1]),-(self.mi[1,0]*self.s[0]+self.mi[1,1]*self.s[1])])
def _multiply(self, m, preceded):
if preceded:
self.m=np.dot(self.m,m)
else:
self.m=np.dot(m,self.m)
self.s=np.dot(m,self.s)
self._set_inv()
def _shift(self, s, preceded):
if preceded:
self.s+=np.dot(self.m,s)
else:
self.s+=s
self._set_inv()
@property
def tmatr(self, copy=False):
"""Transform matrix as a 2x2 numpy array"""
return self.m.copy() if copy else self.m
@property
def svec(self, copy=False):
"""Transform vector as a numpy array"""
return self.s.copy() if copy else self.s
[docs]
def invert(self):
"""Invert the transform"""
self.m=self.mi
self.s=self.si
self._set_inv()
return self
[docs]
def precede(self, trans):
"""Precede the transform with a different transform"""
self.s+=np.dot(self.m,trans.s)
self.m=np.dot(self.m,trans.m)
self._set_inv()
return self
[docs]
def follow(self, trans):
"""Follow the transform with a different transform"""
self.s=np.dot(trans.m,self.s)+self.s
self.m=np.dot(trans.m,self.m)
self._set_inv()
return self
def __call__(self, x, y):
"""Apply the transform to the given point"""
return list(np.dot(self.m,np.array([x,y]))+self.s)
[docs]
def i(self, x,y):
"""Apply the inverse transform to the given point"""
return list(np.dot(self.mi,np.array([x,y]))+self.si)
[docs]
def shift(self, s1, s2, preceded=False):
"""Apply a shift transform before or after (default) the given transform"""
self._shift(np.array([s1,s2]),preceded)
return self
[docs]
def multiply(self, m11, m12, m21, m22, preceded=False):
"""Apply a matrix multiplication transform before or after (default) the given transform"""
self._multiply(np.array([[m11,m12],[m21,m22]]),preceded)
return self
[docs]
def scale(self, s1, s2, preceded=False):
"""Apply a scale transform before or after (default) the given transform"""
self._multiply(np.array([[s1,0],[0,s2]]),preceded)
return self
[docs]
def transpose(self, preceded=False):
"""Apply a transpose transform before or after (default) the given transform"""
self._multiply(_mt,preceded)
return self
[docs]
@classmethod
def from_matr_shift(cls, matr, shift):
"""Build a transform from a 2x2 transform matrix and a shift vector"""
return cls(matr,shift)