def _re_bound(self,plot_bounding_box,mat,box,density): # CEBHACKALERT: for Julien... # If plot_bounding_box is that of a Sheet, it will already have been # setup so that the density in the x direction and the density in the # y direction are equal. # If plot_bounding_box comes from elsewhere (i.e. you create it from # arbitrary bounds), it might need to be adjusted to ensure the density # in both directions is the same (see Sheet.__init__()). I don't know where # you want to do that; presumably the code should be common to Sheet and # where it's used in the plotting? # # It's possible we can move some of the functionality # into SheetCoordinateSystem. if plot_bounding_box.containsbb_exclusive(box): ct = SheetCoordinateSystem(plot_bounding_box,density,density) new_mat = np.zeros(ct.shape,dtype=np.float) r1,r2,c1,c2 = Slice(box,ct) new_mat[r1:r2,c1:c2] = mat else: scs = SheetCoordinateSystem(box,density,density) s=Slice(plot_bounding_box,scs) s.crop_to_sheet(scs) new_mat = s.submatrix(mat) return new_mat
def __init__(self, **params): """ Initialize this object as an EventProcessor, then also as a SheetCoordinateSystem with equal xdensity and ydensity. views is a Layout, which stores associated measurements, i.e. representations of the sheet for use by analysis or plotting code. """ EventProcessor.__init__(self, **params) # Initialize this object as a SheetCoordinateSystem, with # the same density along y as along x. SheetCoordinateSystem.__init__(self, self.nominal_bounds, self.nominal_density) n_units = round((self.lbrt[2] - self.lbrt[0]) * self.xdensity, 0) if n_units < 1: raise ValueError( "Sheet bounds and density must be specified such that the "+ \ "sheet has at least one unit in each direction; " \ +self.name+ " does not.") # setup the activity matrix self.activity = zeros(self.shape, activity_type) # For non-plastic inputs self.__saved_activity = [] self._plasticity_setting_stack = [] self.views = Layout() self.views.Maps = Layout() self.views.Curves = Layout()
def __init__(self,**params): """ Initialize this object as an EventProcessor, then also as a SheetCoordinateSystem with equal xdensity and ydensity. views is a Layout, which stores associated measurements, i.e. representations of the sheet for use by analysis or plotting code. """ EventProcessor.__init__(self,**params) # Initialize this object as a SheetCoordinateSystem, with # the same density along y as along x. SheetCoordinateSystem.__init__(self,self.nominal_bounds,self.nominal_density) n_units = round((self.lbrt[2]-self.lbrt[0])*self.xdensity,0) if n_units<1: raise ValueError( "Sheet bounds and density must be specified such that the "+ \ "sheet has at least one unit in each direction; " \ +self.name+ " does not.") # setup the activity matrix self.activity = zeros(self.shape,activity_type) # For non-plastic inputs self.__saved_activity = [] self._plasticity_setting_stack = [] self.views = Layout() self.views.Maps = Layout() self.views.Curves = Layout()
def _set_image(self, image): # Stores a SheetCoordinateSystem with an activity matrix # representing the image if not isinstance(image, np.ndarray): image = np.array(image, np.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 __call__(self, **params_to_override): p = ParamOverrides(self, params_to_override) shape = SheetCoordinateSystem(p.bounds, p.xdensity, p.ydensity).shape result = p.scale * np.ones(shape, np.float) + p.offset self._apply_mask(p, result) for of in p.output_fns: of(result) return result
def _set_image(self, image): # Stores a SheetCoordinateSystem with an activity matrix # representing the image if not isinstance(image, np.ndarray): image = np.array(image, np.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 __call__(self,**params_to_override): p = ParamOverrides(self,params_to_override) if self.time_dependent: if 'name' in p: self._initialize_random_state(seed=self.seed, shared=True, name=p.name) self._hash_and_seed() shape = SheetCoordinateSystem(p.bounds,p.xdensity,p.ydensity).shape result = self._distrib(shape,p) self._apply_mask(p,result) for of in p.output_fns: of(result) return result
def set_matrix_dimensions(self, bounds, xdensity, ydensity): """ Change the dimensions of the matrix into which the pattern will be drawn. Users of this class should call this method rather than changing the bounds, xdensity, and ydensity parameters directly. Subclasses can override this method to update any internal data structures that may depend on the matrix dimensions. """ self.bounds = bounds self.xdensity = xdensity self.ydensity = ydensity scs = SheetCoordinateSystem(bounds, xdensity, ydensity) for of in self.output_fns: if isinstance(of, TransferFn): of.initialize(SCS=scs, shape=scs.shape)
def _setup_xy(self,bounds,xdensity,ydensity,x,y,orientation): """ Produce pattern coordinate matrices from the bounds and density (or rows and cols), and transforms them according to x, y, and orientation. """ self.param.debug("bounds=%s, xdensity=%s, ydensity=%s, x=%s, y=%s, orientation=%s",bounds,xdensity,ydensity,x,y,orientation) # Generate vectors representing coordinates at which the pattern # will be sampled. # CB: note to myself - use slice_._scs if supplied? x_points,y_points = SheetCoordinateSystem(bounds,xdensity,ydensity).sheetcoordinates_of_matrixidx() # Generate matrices of x and y sheet coordinates at which to # sample pattern, at the correct orientation self.pattern_x, self.pattern_y = self._create_and_rotate_coordinate_arrays(x_points-x,y_points-y,orientation)
def __call__(self,**params_to_override): p = ParamOverrides(self,params_to_override) xsize,ysize = SheetCoordinateSystem(p.bounds,p.xdensity,p.ydensity).shape xsize,ysize = int(round(xsize)),int(round(ysize)) xdisparity = int(round(xsize*p.xdisparity)) ydisparity = int(round(xsize*p.ydisparity)) dotsize = int(round(xsize*p.dotsize)) bigxsize = 2*xsize bigysize = 2*ysize ndots=int(round(p.dotdensity * (bigxsize+2*dotsize) * (bigysize+2*dotsize) / min(dotsize,xsize) / min(dotsize,ysize))) halfdot = np.floor(dotsize/2) # Choose random colors and locations of square dots random_seed = p.random_seed np.random.seed(random_seed*12+random_seed*99) col=np.where(np.random.random((ndots))>=0.5, 1.0, -1.0) np.random.seed(random_seed*122+random_seed*799) xpos=np.floor(np.random.random((ndots))*(bigxsize+2*dotsize)) - halfdot np.random.seed(random_seed*1243+random_seed*9349) ypos=np.floor(np.random.random((ndots))*(bigysize+2*dotsize)) - halfdot # Construct arrays of points specifying the boundaries of each # dot, cropping them by the big image size (0,0) to (bigxsize,bigysize) x1=xpos.astype('l') ; x1=np.choose(np.less(x1,0),(x1,0)) y1=ypos.astype('l') ; y1=np.choose(np.less(y1,0),(y1,0)) x2=(xpos+(dotsize-1)).astype('l') ; x2=np.choose(np.greater(x2,bigxsize),(x2,bigxsize)) y2=(ypos+(dotsize-1)).astype('l') ; y2=np.choose(np.greater(y2,bigysize),(y2,bigysize)) # Draw each dot in the big image, on a blank background bigimage = np.zeros((bigysize,bigxsize)) for i in range(ndots): bigimage[y1[i]:y2[i]+1,x1[i]:x2[i]+1] = col[i] result = p.offset + p.scale*bigimage[ (ysize/2)+ydisparity:(3*ysize/2)+ydisparity , (xsize/2)+xdisparity:(3*xsize/2)+xdisparity ] for of in p.output_fns: of(result) return result
def situated(self): if self.bounds.lbrt() == self.situated_bounds.lbrt(): self.warning("CFView is already situated.") return self l, b, r, t = self.bounds.lbrt() xd = int(np.round(self.data.shape[1] / (r-l))) yd = int(np.round(self.data.shape[0] / (t-b))) scs = SheetCoordinateSystem(self.situated_bounds, xd, yd) data = np.zeros(scs.shape, dtype=np.float64) r1, r2, c1, c2 = self.input_sheet_slice data[r1:r2, c1:c2] = self.data return CFView(data, self.situated_bounds, roi_bounds=self.bounds, situated_bounds=self.situated_bounds, label=self.label, value=self.value)
def _distrib(self, shape, p): max_density = min(p.xdensity,p.ydensity) if (p.grid_density > max_density and not hasattr(self,"warned_about_density")): self.warning("Requested grid_density %s larger than xdensity %s or ydensity %s; capped at %s" % (p.grid_density,p.xdensity,p.ydensity,max_density)) p.grid_density = max_density self.warned_about_density=True Nx = shape[1] Ny = shape[0] # Size of the pixel matrix assert (Nx>0 and Ny>0), 'Pixel matrix cannot be zero' SC = SheetCoordinateSystem(p.bounds, p.xdensity, p.ydensity) unitary_distance_x = SC._SheetCoordinateSystem__xstep unitary_distance_y = SC._SheetCoordinateSystem__ystep sheet_x_size = unitary_distance_x * Nx sheet_y_size = unitary_distance_y * Ny # Sizes of the structure matrix nx = int(round(sheet_x_size * p.grid_density)) # Number of points in the x's ny = int(round(sheet_y_size * p.grid_density)) # Number of points in the y's assert ( nx > 0 ), 'Grid density or bound box in the x dimension too small' assert ( ny > 0 ), 'Grid density or bound box in the y dimension too smal' ps_x = int(round(Nx / nx)) #Closest integer ps_y = int(round(Ny / ny)) # This is the actual matrix of the pixels A = np.ones(shape) * 0.5 if p.grid == False: #The centers of the spots are randomly distributed in space x = p.random_generator.randint(0, Nx - ps_x + 1) y = p.random_generator.randint(0, Ny - ps_y + 1) z = p.random_generator.randint(0,2) # Noise matrix is mapped to the pixel matrix A[x: (x + ps_y), y: (y + ps_x)] = z return A * p.scale + p.offset else: #In case you want the grid if ( Nx % nx == 0) and (Ny % ny == 0): #When the noise grid falls neatly into the the pixel grid x = p.random_generator.randint(0, nx) y = p.random_generator.randint(0, ny) z = p.random_generator.randint(0,2) # Noise matrix is mapped to the pixel matrix (faster method) A[x*ps_y: (x*ps_y + ps_y), y*ps_x: (y*ps_x + ps_x)] = z return A * p.scale + p.offset else: # If noise grid does not fit neatly in the pixel grid (slow method) x_points,y_points = SC.sheetcoordinates_of_matrixidx() # Obtain length of the side and length of the # division line between the grid size_of_block_x = Nx * 1.0 / nx size_of_block_y = Ny * 1.0 / ny # Construct the noise matrix Z = np.ones((nx,ny)) * 0.5 x = p.random_generator.randint(0, nx) y = p.random_generator.randint(0, ny) z = p.random_generator.randint(0,2) Z[x,y] = z # Noise matrix is mapped to the pixel matrix for i in range(Nx): for j in range(Ny): # Map along the x coordinates x_entry = int( i / size_of_block_x) y_entry = int( j / size_of_block_y) A[j][i] = Z[x_entry][y_entry] return A * p.scale + p.offset
def _distrib(self, shape, p): max_density = min(p.xdensity,p.ydensity) if (p.grid_density > max_density and not hasattr(self,"warned_about_density")): self.warning("Requested grid_density %s larger than xdensity %s or ydensity %s; capped at %s" % (p.grid_density,p.xdensity,p.ydensity,max_density)) p.grid_density = max_density self.warned_about_density=True Nx = shape[1] Ny = shape[0] # Size of the pixel matrix assert (Nx>0 and Ny>0), 'Pixel matrix cannot be zero' SC = SheetCoordinateSystem(p.bounds, p.xdensity, p.ydensity) unitary_distance_x = SC._SheetCoordinateSystem__xstep unitary_distance_y = SC._SheetCoordinateSystem__ystep sheet_x_size = unitary_distance_x * Nx sheet_y_size = unitary_distance_y * Ny # Sizes of the structure matrix nx = int(round(sheet_x_size * p.grid_density)) # Number of points in the x's ny = int(round(sheet_y_size * p.grid_density)) # Number of points in the y's assert ( nx > 0 ), 'Grid density or bound box in the x dimension too small' assert ( ny > 0 ), 'Grid density or bound box in the y dimension too small' # If the noise grid is proportional to the pixel grid and fits # neatly into it then this method is ~100 times faster if ( Nx % nx == 0) and (Ny % ny == 0): if (Nx == nx) and (Ny == ny): #This is faster to call the whole procedure result = 0.5 * (p.random_generator.randint(-1, 2, shape) + 1) return result * p.scale + p.offset else: # This is the actual matrix of the pixels A = np.zeros(shape) # Noise matrix that contains the structure of 0, 0.5, and 1's Z = 0.5 * (p.random_generator.randint(-1, 2, (nx, ny)) + 1 ) ps_x = int(round(Nx * 1.0/ nx)) #Closest integer ps_y = int(round(Ny * 1.0/ ny)) # Noise matrix is mapped to the pixel matrix for i in range(nx): for j in range(ny): A[i * ps_y: (i + 1) * ps_y, j * ps_x: (j + 1) * ps_x] = Z[i,j] return A * p.scale + p.offset # General method in case the noise grid does not # fall neatly in the pixel grid else: # Obtain length of the side and length of the # division line between the grid x_points,y_points = SC.sheetcoordinates_of_matrixidx() # This is the actual matrix of the pixels A = np.zeros(shape) # Noise matrix that contains the structure of 0, 0.5, and 1's Z = 0.5 * (p.random_generator.randint(-1, 2, (nx, ny)) + 1 ) size_of_block_x = Nx * 1.0 / nx size_of_block_y = Ny * 1.0 / ny # Noise matrix is mapped to the pixel matrix for i in range(Nx): for j in range(Ny): # Map along the x coordinates x_entry = int( i / size_of_block_x) y_entry = int( j / size_of_block_y) A[j][i] = Z[x_entry][y_entry] return A * p.scale + p.offset
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, np.ndarray): image = np.array(image, np.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 np.ones(x.shape) * 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 np.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
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, np.ndarray): image = np.array(image, np.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 np.ones(x.shape) * 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 np.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
def __init__(self, **params): EventProcessor.__init__(**params) SheetCoordinateSystem.__init__()