def test_coordinate_position(self): """ these tests duplicate some of the earlier ones, except these use a matrix with non-integer (right-left) and (top-bottom). This is an important test case for the definition of density; without it, the tests above could be passed by a variety of sheet2matrix, bounds2shape functions, etc. CEBALERT: transfer the box to TestBox3Coordinates and have these tests run in the framework. """ l, b, r, t = (-0.8, -0.8, 0.8, 0.8) # mimics that a sheet recalculates its density) density = int(16 * (r - l)) / float(r - l) bounds = BoundingBox(points=((l, b), (r, t))) ct = SheetCoordinateSystem(bounds, density, density) self.assertEqual(ct.sheet2matrixidx(0.8, 0.8), (0, 24 + 1)) self.assertEqual(ct.sheet2matrixidx(0.0, 0.0), (12, 12)) self.assertEqual(ct.sheet2matrixidx(-0.8, -0.8), (24 + 1, 0)) self.assertEqual(ct.matrixidx2sheet(24, 0), (((r - l) / int(density * (r - l)) / 2.0) + l, (t - b) / int(density * (t - b)) / 2.0 + b)) self.assertEqual(ct.matrixidx2sheet(0, 0), (((r - l) / int(density * (r - l)) / 2.0) + l, (t - b) / int(density * (t - b)) * (int(density * (t - b)) - 0.5) + b)) x, y = ct.matrixidx2sheet(0, 0) self.assertTrue(bounds.contains(x, y)) self.assertEqual((0, 0), ct.sheet2matrixidx(x, y)) x, y = ct.matrixidx2sheet(25, 25) self.assertFalse(bounds.contains(x, y)) self.assertNotEqual((24, 24), ct.sheet2matrixidx(x, y)) x, y = ct.matrixidx2sheet(0, 24) self.assertTrue(bounds.contains(x, y)) self.assertEqual((0, 24), ct.sheet2matrixidx(x, y)) x, y = ct.matrixidx2sheet(24, 0) self.assertTrue(bounds.contains(x, y)) self.assertEqual((24, 0), ct.sheet2matrixidx(x, y))
def test_coordinate_position(self): """ these tests duplicate some of the earlier ones, except these use a matrix with non-integer (right-left) and (top-bottom). This is an important test case for the definition of density; without it, the tests above could be passed by a variety of sheet2matrix, bounds2shape functions, etc. CEBALERT: transfer the box to TestBox3Coordinates and have these tests run in the framework. """ l,b,r,t = (-0.8,-0.8,0.8,0.8) # mimics that a sheet recalculates its density) density = int(16*(r-l)) / float(r-l) bounds = BoundingBox(points=((l,b),(r,t))) ct = SheetCoordinateSystem(bounds,density,density) self.assertEqual(ct.sheet2matrixidx(0.8,0.8),(0,24+1)) self.assertEqual(ct.sheet2matrixidx(0.0,0.0),(12,12)) self.assertEqual(ct.sheet2matrixidx(-0.8,-0.8),(24+1,0)) self.assertEqual(ct.matrixidx2sheet(24,0), (((r-l) / int(density*(r-l)) / 2.0) + l, (t-b) / int(density*(t-b)) / 2.0 + b)) self.assertEqual(ct.matrixidx2sheet(0,0), (((r-l) / int(density*(r-l)) / 2.0) + l , (t-b) / int(density*(t-b)) * (int(density*(t-b)) - 0.5) + b)) x,y = ct.matrixidx2sheet(0,0) self.assertTrue(bounds.contains(x,y)) self.assertEqual((0,0),ct.sheet2matrixidx(x,y)) x,y = ct.matrixidx2sheet(25,25) self.assertFalse(bounds.contains(x,y)) self.assertNotEqual((24,24),ct.sheet2matrixidx(x,y)) x,y = ct.matrixidx2sheet(0,24) self.assertTrue(bounds.contains(x,y)) self.assertEqual((0,24),ct.sheet2matrixidx(x,y)) x,y = ct.matrixidx2sheet(24,0) self.assertTrue(bounds.contains(x,y)) self.assertEqual((24,0),ct.sheet2matrixidx(x,y))
class TestCoordinateTransforms(unittest.TestCase): """ Tests for sheet. Subclassed for use; the subclasses have a setUp method to create the particular coordinates to use each time. """ def makeBox(self): self.box = BoundingBox(points=((self.left,self.bottom), (self.right,self.top))) self.ct = SheetCoordinateSystem(self.box,self.density,self.density) # float bounds for matrix coordinates: these # values are actually outside the matrix self.rbound = self.density*(self.top-self.bottom) self.cbound = self.density*(self.right-self.left) #self.cbound = int(self.density*(self.right-self.left)) / float((self.right-self.left)) #self.rbound = int(self.density*(self.top-self.bottom)) / float((self.top-self.bottom)) # CEBALERT: this is supposed to be a small distance D = 0.00001 # Sheet values around the edge of the BoundingBox self.just_in_right_x = self.right - D self.just_in_bottom_y = self.bottom + D self.just_out_top_y = self.top + D self.just_out_left_x = self.left - D # Matrix values around the edge of the matrix self.just_out_right_idx = self.rbound + D self.just_out_bottom_idx = self.cbound + D self.just_out_top_idx = 0.0 - D self.just_out_left_idx = 0.0 - D ### sheet2matrix() tests # def test_sheet2matrix_center(self): """ Check that the center of the Sheet corresponds to the center of the matrix. """ x_center = self.left+(self.right-self.left)/2.0 y_center = self.bottom+(self.top-self.bottom)/2.0 row, col = self.ct.sheet2matrix(x_center,y_center) self.assertEqual((row,col),(self.rbound/2.0,self.cbound/2.0)) def test_sheet2matrix_left_top(self): """ Check that the top-left of the Sheet is [0,0] in matrix coordinates. """ row, col = self.ct.sheet2matrix(self.left,self.top) self.assertEqual((row,col),(0,0)) def test_sheet2matrix_right_bottom(self): """ Check that the bottom-right of the Sheet is [rbound,cbound] in matrix coordinates. """ row, col = self.ct.sheet2matrix(self.right,self.bottom) self.assertEqual((row,col),(self.rbound,self.cbound)) def test_sheet2matrix_matrix2sheet(self): """ Check that matrix2sheet() is the inverse of sheet2matrix(). """ # top-right corner row, col = self.ct.sheet2matrix(self.right,self.top) x_right, y_top = self.ct.matrix2sheet(row,col) self.assertEqual((x_right,y_top),(self.right,self.top)) # bottom-left corner row, col = self.ct.sheet2matrix(self.left,self.bottom) x_left, y_bottom = self.ct.matrix2sheet(row,col) self.assertEqual((x_left,y_bottom),(self.left,self.bottom)) def test_matrix2sheet_sheet2matrix(self): """ Check that sheet2matrix() is the inverse of matrix2sheet(). """ # top-right corner x,y = self.ct.matrix2sheet(float(0),float(self.last_col)) top_row,right_col = self.ct.sheet2matrix(x,y) self.assertEqual((top_row,right_col),(float(0),float(self.last_col))) # bottom-left corner x,y = self.ct.matrix2sheet(float(self.last_row),float(0)) bottom_row,left_col = self.ct.sheet2matrix(x,y) self.assertEqual((bottom_row,left_col),(float(self.last_row),float(0))) ### sheet2matrixidx() tests # def test_sheet2matrixidx_left_top(self): """ Test a point just inside the top-left corner of the BoundingBox, and one just outside. """ # inside r,c = 0,0 x,y = self.left,self.top self.assertEqual(self.ct.sheet2matrixidx(x,y), (r,c)) # outside r,c = -1,-1 x,y = self.just_out_left_x,self.just_out_top_y self.assertEqual(self.ct.sheet2matrixidx(x,y), (r,c)) def test_sheet2matrixidx_left_bottom(self): """ Test a point just inside the left-bottom corner of the BoundingBox, and one just outside. """ # inside r,c = self.last_row, 0 x,y = self.left, self.just_in_bottom_y self.assertEqual(self.ct.sheet2matrixidx(x,y),(r,c)) # outside r,c = self.last_row+1, -1 x,y = self.just_out_left_x, self.bottom self.assertEqual(self.ct.sheet2matrixidx(x,y),(r,c)) def test_sheet2matrixidx_right_top(self): """ Test a point just inside the top-right corner of the BoundingBox, and one just outside. """ # inside r,c = 0,self.last_col x,y = self.just_in_right_x,self.top self.assertEqual(self.ct.sheet2matrixidx(x,y),(r,c)) # outside r,c = -1,self.last_col+1 x,y = self.right,self.just_out_top_y self.assertEqual(self.ct.sheet2matrixidx(x,y),(r,c)) def test_sheet2matrixidx_right_bottom(self): """ Test a point just inside the bottom-right corner of the BoundingBox, and the corner itself - which should not be inside. """ # inside r,c = self.last_row,self.last_col x,y = self.just_in_right_x,self.just_in_bottom_y self.assertEqual(self.ct.sheet2matrixidx(x,y),(r,c)) # not inside r,c = self.last_row+1,self.last_col+1 x,y = self.right,self.bottom self.assertEqual(self.ct.sheet2matrixidx(x,y),(r,c)) ### matrix2sheet() tests # def test_matrix2sheet_left_top(self): """ Check that Sheet's (0,0) is the top-left of the matrix. Check that just outside the top-left in matrix coordinates comes back to Sheet coordinates that are outside the BoundingBox. """ x,y = self.ct.matrix2sheet(0,0) self.assertEqual((x,y), (self.left,self.top)) x,y = self.ct.matrix2sheet(self.just_out_left_idx,self.just_out_top_idx) self.assertFalse(self.box.contains(x,y)) def test_matrix2sheet_right_bottom(self): """ Check that Sheet's (right,bottom) is the bottom-right in matrix coordinates i.e. [rbound,cbound] Check that just outside the bottom-right in matrix coordinates comes back to Sheet coordinates that are outside the BoundingBox. """ x,y = self.ct.matrix2sheet(self.rbound,self.cbound) self.assertEqual((x,y), (self.right,self.bottom)) x,y = self.ct.matrix2sheet(self.just_out_right_idx,self.just_out_bottom_idx) self.assertFalse(self.box.contains(x,y)) def test_matrix2sheet_center(self): """ Check that the center in Sheet coordinates corresponds to the center in continuous matrix coordinates. """ x_center = self.left+(self.right-self.left)/2.0 y_center = self.bottom+(self.top-self.bottom)/2.0 center_float_row = self.rbound/2.0 center_float_col = self.cbound/2.0 x,y = self.ct.matrix2sheet(center_float_row,center_float_col) self.assertEqual((x,y),(x_center,y_center)) ### matrixidx2sheet() tests # def test_matrixidx2sheet_left_top(self): """ The top-left matrix cell [0,0] should be given back in Sheet coordinates at the center of that cell. The cell [-1,-1] outside this corner should come back out of the BoundingBox """ # inside r,c = 0,0 x,y = self.left+self.half_unit,self.top-self.half_unit test_x, test_y = self.ct.matrixidx2sheet(r,c) self.assertEqual((test_x,test_y), (x,y)) self.assertTrue(self.box.contains(test_x,test_y)) # outside r,c = -1,-1 test_x, test_y = self.ct.matrixidx2sheet(r,c) self.assertFalse(self.box.contains(test_x,test_y)) def test_matrixidx2sheet_left_bottom(self): """ The bottom-left matrix cell [0,rbound] should be given back in Sheet coordinates at the center of that cell. The cell [last_row+1,-1] outside this corner should come back out of the BoundingBox. """ # inside r,c = self.last_row,0 x,y = self.left+self.half_unit,self.bottom+self.half_unit self.assertEqual(self.ct.matrixidx2sheet(r,c), (x,y)) # outside r,c = self.last_row+1,-1 test_x, test_y = self.ct.matrixidx2sheet(r,c) self.assertFalse(self.box.contains(test_x,test_y)) def test_matrixidx2sheet_right_top(self): """ The top-right matrix cell [cbound,0] should be given back in Sheet coordinates at the center of that cell. The cell [-1,last_col+1] outside this corner should come back out of the BoundingBox. """ # inside r,c = 0,self.last_col x,y = self.right-self.half_unit,self.top-self.half_unit self.assertEqual(self.ct.matrixidx2sheet(r,c), (x,y)) # outside r,c = -1,self.last_col+1 test_x, test_y = self.ct.matrixidx2sheet(r,c) self.assertFalse(self.box.contains(test_x,test_y)) def test_matrixidx2sheet_right_bottom(self): """ The bottom-right matrix cell [cbound,rbound] should be given back in Sheet coordinates at the center of that cell. The cell [last_row+1,last_col+1] outside this corner should come back out of the BoundingBox. """ r,c = self.last_row,self.last_col x,y = self.right-self.half_unit,self.bottom+self.half_unit self.assertEqual(self.ct.matrixidx2sheet(r,c), (x,y)) # outside r,c = self.last_row+1,self.last_col+1 test_x, test_y = self.ct.matrixidx2sheet(r,c) self.assertFalse(self.box.contains(test_x,test_y)) def test_matrixidx2sheet_center(self): """ The row and col *index* of the center unit in the matrix should come back as the Sheet coordinates of the center of that center unit. """ r,c = self.center_unit_idx x_center = self.left+(self.right-self.left)/2.0 y_center = self.bottom+(self.top-self.bottom)/2.0 x,y = x_center+self.half_unit, y_center-self.half_unit self.assertEqual(self.ct.matrixidx2sheet(r,c), (x,y)) def test_matrixidx2sheet_sheet2matrixidx(self): """ Check that sheet2matrixidx() is the inverse of matrix2sheetidx(). """ # top-right corner x,y = self.ct.matrixidx2sheet(float(0),float(self.last_col)) top_row,right_col = self.ct.sheet2matrixidx(x,y) self.assertEqual((top_row,right_col),(float(0),float(self.last_col))) # bottom-left corner x,y = self.ct.matrixidx2sheet(float(self.last_row),float(0)) bottom_row,left_col = self.ct.sheet2matrixidx(x,y) self.assertEqual((bottom_row,left_col),(float(self.last_row),float(0)))
class PatternSampler(ImageSampler): """ When called, resamples - according to the size_normalization parameter - an image at the supplied (x,y) sheet coordinates. (x,y) coordinates outside the image are returned as the background value. """ whole_pattern_output_fns = param.HookList(class_=TransferFn,default=[],doc=""" Functions to apply to the whole image before any sampling is done.""") background_value_fn = param.Callable(default=None,doc=""" Function to compute an appropriate background value. Must accept an array and return a scalar.""") size_normalization = param.ObjectSelector(default='original', objects=['original','stretch_to_fit','fit_shortest','fit_longest'], doc=""" Determines how the pattern is scaled initially, relative to the default retinal dimension of 1.0 in sheet coordinates: 'stretch_to_fit': scale both dimensions of the pattern so they would fill a Sheet with bounds=BoundingBox(radius=0.5) (disregards the original's aspect ratio). 'fit_shortest': scale the pattern so that its shortest dimension is made to fill the corresponding dimension on a Sheet with bounds=BoundingBox(radius=0.5) (maintains the original's aspect ratio, filling the entire bounding box). 'fit_longest': scale the pattern so that its longest dimension is made to fill the corresponding dimension on a Sheet with bounds=BoundingBox(radius=0.5) (maintains the original's aspect ratio, fitting the image into the bounding box but not necessarily filling it). 'original': no scaling is applied; each pixel of the pattern corresponds to one matrix unit of the Sheet on which the pattern being displayed.""") def _get_image(self): return self.scs.activity def _set_image(self,image): # Stores a SheetCoordinateSystem with an activity matrix # representing the image if not isinstance(image,numpy.ndarray): image = array(image,Float) rows,cols = image.shape self.scs = SheetCoordinateSystem(xdensity=1.0,ydensity=1.0, bounds=BoundingBox(points=((-cols/2.0,-rows/2.0), ( cols/2.0, rows/2.0)))) self.scs.activity=image def _del_image(self): self.scs = None def __call__(self, image, x, y, sheet_xdensity, sheet_ydensity, width=1.0, height=1.0): """ Return pixels from the supplied image at the given Sheet (x,y) coordinates. The image is assumed to be a NumPy array or other object that exports the NumPy buffer interface (i.e. can be converted to a NumPy array by passing it to numpy.array(), e.g. Image.Image). The whole_pattern_output_fns are applied to the image before any sampling is done. To calculate the sample, the image is scaled according to the size_normalization parameter, and any supplied width and height. sheet_xdensity and sheet_ydensity are the xdensity and ydensity of the sheet on which the pattern is to be drawn. """ # CEB: could allow image=None in args and have 'if image is # not None: self.image=image' here to avoid re-initializing the # image. self.image=image for wpof in self.whole_pattern_output_fns: wpof(self.image) if not self.background_value_fn: self.background_value = 0.0 else: self.background_value = self.background_value_fn(self.image) pattern_rows,pattern_cols = self.image.shape if width==0 or height==0 or pattern_cols==0 or pattern_rows==0: return ones(x.shape, Float)*self.background_value # scale the supplied coordinates to match the pattern being at density=1 x=x*sheet_xdensity # deliberately don't operate in place (so as not to change supplied x & y) y=y*sheet_ydensity # scale according to initial pattern size_normalization selected (size_normalization) self.__apply_size_normalization(x,y,sheet_xdensity,sheet_ydensity,self.size_normalization) # scale according to user-specified width and height x/=width y/=height # now sample pattern at the (r,c) corresponding to the supplied (x,y) r,c = self.scs.sheet2matrixidx(x,y) # (where(cond,x,y) evaluates x whether cond is True or False) r.clip(0,pattern_rows-1,out=r) c.clip(0,pattern_cols-1,out=c) left,bottom,right,top = self.scs.bounds.lbrt() return numpy.where((x>=left) & (x<right) & (y>bottom) & (y<=top), self.image[r,c], self.background_value) def __apply_size_normalization(self,x,y,sheet_xdensity,sheet_ydensity,size_normalization): pattern_rows,pattern_cols = self.image.shape # Instead of an if-test, could have a class of this type of # function (c.f. OutputFunctions, etc)... if size_normalization=='original': return elif size_normalization=='stretch_to_fit': x_sf,y_sf = pattern_cols/sheet_xdensity, pattern_rows/sheet_ydensity x*=x_sf; y*=y_sf elif size_normalization=='fit_shortest': if pattern_rows<pattern_cols: sf = pattern_rows/sheet_ydensity else: sf = pattern_cols/sheet_xdensity x*=sf;y*=sf elif size_normalization=='fit_longest': if pattern_rows<pattern_cols: sf = pattern_cols/sheet_xdensity else: sf = pattern_rows/sheet_ydensity x*=sf;y*=sf