def saveInstrumentRegFile(self, filename): ''' Similar to saveInstrumentFile, but saves the positions of the pixelPoints used for registration ''' regBlobs = [blob.blob(p[0], p[1]) for p in self.pixelPoints] self.saveInstrumentFile(filename, regBlobs)
def loadInstrumentFile(self, filename): ''' Loads all the targets associated with a given instrument file. filename: the ptn file to load. Actually gets information from a partner text file. returns a list of blobs of the target locations ''' result = [] if os.path.exists(filename[0:-4] + '.txt'): reader = open(filename[0:-4] + '.txt', 'r') for l in reader.readlines(): toks = l.split('\t') if len(toks) == 3: result.append(blob.blob(float(toks[0]), float(toks[1]), group = int(toks[2]))) else: result.append(blob.blob(float(toks[0]), float(toks[1]))) else: print('{} containing pixel positions not found!'.format(filename[0:-4] + '.txt')) return result
def loadInstrumentFile(self, filename): ''' Loads target locations from a target file filename: the file to read returns a list of blobs ''' input = open(filename, 'r') result = [] for l in input.readlines()[1:]: toks = l.split(' ') toks = toks[2].split('_') if len(toks) == 3: result.append( blob(int(toks[1][1:]), int(toks[2][1:]), group=int(toks[0][1:]))) elif len(toks) == 2: result.append(blob(int(toks[0][1:]), int(toks[1][1:]))) return result
def loadInstrumentFile(self, filename): ''' Loads a zaberMapper instrument file and returns a list of blobs with the target locations. filename: the file to load returns a list of blob objects ''' result = [] reader = open(filename, 'r') for l in reader.readlines(): toks = l.split('\t') if len(toks) == 3: #group is encoded result.append(blob.blob(float(toks[0]), float(toks[1]), group = int(toks[2]))) else: #no group result.append(blob.blob(float(toks[0]), float(toks[1]))) return result
def loadInstrumentFile(self, filename): ''' Loads a srsMapper instrument file and returns a list of blobs with the target locations. filename: the file to load returns a list of blob objects ''' result = [] reader = open(filename, 'r') for l in reader.readlines()[2:]:#toss focus plane toks = l.split('\t') pos = toks[0].split('_') #parse pixel position and group x = int(pos[1][:-1]) y = int(pos[2]) if len(toks) == 4: s = int(toks[3]) result.append(blob.blob(x = x, y = y, group = s)) else: result.append(blob.blob(x = x, y = y)) return result
def _blbHelp(img, sizes, channel=2, threshold=200, circs=(0.7, None), xShift=0, yShift=0): ''' helper function to perform blob finding on the image returns a list of blobs img: the image to blob find sizes: (min, max) size to consider max == None means not max size channel: r,g,b channel to threshold threshold: minimum pixel intensity to count as blob circs: (min, max) circularity to consider max == None means no max xShift: amount to add to x coordinate to shift into global coordinate yShift: amount to add to x coordinate to shift into global coordinate ''' #blob find lbl, num = blobFinder._blbThresh(img, channel, threshold) slices = scipy.ndimage.find_objects(lbl) result = [] #for each blob for i in range(num): #convert to boolean image s = slices[i] dx, dy = s[:2] region = lbl[dx.start - 1:dx.stop + 1, dy.start - 1:dy.stop + 1] region = region == i + 1 #area is total number of true pixels area = np.sum(region) #if passes size threshold if area > sizes[0] and (sizes[1] is None or area < sizes[1]): #calculate circularity = 4 pi area / perimeter^2 perim = skimage.measure.perimeter(region) circ = 4 * np.pi * area / perim**2 #if passes circularity threshold if circ > circs[0] and (circs[1] is None or circ < circs[1]): #determine center of mass, ignoring intensity (x, y) = scipy.ndimage.measurements.center_of_mass(region) #calculate radius assuming circle r = np.sqrt(area / np.pi) #add to result, note x,y transpose! result.append( blob(y=x + dx.start - 1 + yShift, x=y + dy.start - 1 + xShift, radius=r, circularity=circ)) return result
def blobRequest(self, globalPoint, radius): ''' Tries to add the blob to the current blob list. If overlap with current blob, remove that point globalPoint: (x,y) tuple in the image coordinate space radius: the radius of the new blob to be added returns true if a blob was added, false if one was removed ''' for i, b in enumerate(self.blobs): if (globalPoint[0]-b.X)**2 + (globalPoint[1]-b.Y)**2 <= \ b.radius**2: self.blobs.pop(i) return False, i self.blobs.append(blob.blob(globalPoint[0], globalPoint[1], radius)) return True, -1
def hexagonallyClosePackPoints(self, spacing, numLayers, r=GUIConstants.DEFAULT_PATTERN_RADIUS, c=1, dynamicLayering=False): ''' Expands each blob into a grid of points, with hexagonal close packed spacing blobs: list of blob objects to expand spacing: spacing between new blobs numLayers: number of layers around each blob. 1 generates a grid of 7 with the initial blob in the center. This can be adjusted for radius r: radius to set new blobs to c: circularity of new blobs dynamicLayering: set to True to account for blob size in making pattern positions ''' #this may save some computation time to precompute sqrt3ov2 = np.sqrt(3) / 2 #list of directions to march along to generate a layer marcher = np.array([[-0.5, sqrt3ov2], [-1., 0.], [-0.5, -sqrt3ov2], [0.5, -sqrt3ov2], [1., 0.], [0.5, sqrt3ov2]]) #use one mask each time if dynamicLayering == False: #start at center mask = np.array([[0, 0]]) for n in range(numLayers): current = np.array([[n + 1., 0]]) for i in range(6): direction = marcher[i, :] for j in range(n + 1): current += direction mask = np.append(mask, current, axis=0) mask *= spacing #strip off radius result = [] ind = 0 for blb in self.blobs: #use new mask each blob, with number of layers being size dependent if dynamicLayering == True: mask = np.array([[0, 0]]) #change number of layers by blb radius for n in range(numLayers + int(np.ceil(blb.radius / spacing))): current = np.array([[n + 1., 0]]) for i in range(6): direction = marcher[i, :] for j in range(n + 1): current += direction mask = np.append(mask, current, axis=0) mask *= spacing #expand blb into points based on mask for b in map( lambda x: blob.blob( x=x[0], y=x[1], radius=r, circularity=c, group=ind), list(mask + (blb.X, blb.Y))): result.append(b) ind += 1 result = self.partialDeepCopy(result) result.generateGroupLabels() return result
def rectangularlyPackPoints(self, spacing, numLayers, r=GUIConstants.DEFAULT_PATTERN_RADIUS, c=1, dynamicLayering=False): ''' Expands each blob into a grid of points, with regular rectangular spacing blobs: list of blob objects to expand spacing: spacing between new blobs numLayers: number of layers around each blob. 1 generates a grid of 3x3 with the initial blob in the center. This can be adjusted for radius r: radius to set new blobs to c: circularity of new blobs dynamicLayering: set to True to account for blob size in making pattern positions ''' #marcher is a list of directions to move to for generating the spacing #this starts at the right, moves down, left, up, right, down, to spiral around the blob #additional layers are generated by applying the marcher multiple times marcher = np.array([[0, 1], [-1., 0.], [-1., 0.], [0., -1.], [0., -1.], [1., 0.], [1., 0.], [0, 1]]) #use one mask each time if dynamicLayering == False: #start at center mask = np.array([[0, 0]]) for n in range(numLayers): #move to the right by n spaces current = np.array([[n + 1., 0]]) for i in range(8): #add the marcher n times direction = marcher[i, :] for j in range(n + 1): current += direction mask = np.append(mask, current, axis=0) #scale unit mask by spacing mask *= spacing result = [] ind = 0 for blb in self.blobs: #use new mask each blob, with number of layers being size dependent if dynamicLayering == True: mask = np.array([[0, 0]]) #only change from above is the blb.radius/spacing for n in range(numLayers + int(np.ceil(blb.radius / spacing))): current = np.array([[n + 1., 0]]) for i in range(8): direction = marcher[i, :] for j in range(n + 1): current += direction mask = np.append(mask, current, axis=0) mask *= spacing #expand blb by mask for b in map( lambda x: blob.blob( x=x[0], y=x[1], radius=r, circularity=c, group=ind), list(mask + (blb.X, blb.Y))): #add each point to result result.append(b) ind += 1 result = self.partialDeepCopy(result) result.generateGroupLabels() return result
def circularPackPoints(self, spacing, maxSpots, offset, minSpots=4, r=GUIConstants.DEFAULT_PATTERN_RADIUS, c=1): ''' Expands each blob into several points surrounding the blob. blobs: list of blobs to expand spacing: minimum spacing between points maxSpots: max number of spots to expand for each blob offset: offset of circumference to space blobs minSpots: minimum number of spots for each blob. Ignores spacing with min spots r: radius of new blobs c: circumference of new blobs returns a list of blobs of the expanded positions ''' #check maxspots to ensure less than min maxSpots = minSpots if maxSpots < minSpots else maxSpots #calculate min and max r: maxR = maxSpots * spacing / (2 * np.pi) - offset #angles and unit vectors of max spots thetas = np.linspace(0, 2 * np.pi, maxSpots, False) maxUnits = np.vstack((np.cos(thetas), np.sin(thetas))) minR = minSpots * spacing / (2 * np.pi) - offset #angles and unit vectors at min number of spots thetas = np.linspace(0, 2 * np.pi, minSpots, False) minUnits = np.vstack((np.cos(thetas), np.sin(thetas))) result = [] ind = 0 for blb in self.blobs: #check radius for min, max or between if (blb.radius > maxR): unitvec = maxUnits elif (blb.radius < minR): unitvec = minUnits #between min and max, use most spots as possible while retaining the spacing else: spots = np.floor(2 * np.pi * (blb.radius + offset) / spacing) thetas = np.linspace(0, 2 * np.pi, spots, False) unitvec = np.vstack((np.cos(thetas), np.sin(thetas))) #expand each blob into a new x,y positions targetSpots = unitvec*(blb.radius + offset) + \ np.matlib.repmat(np.array((blb.X, blb.Y)) ,unitvec.shape[1],1).T #add targets to result for e in targetSpots.T: result.append( blob.blob(x=e[0], y=e[1], radius=r, circularity=c, group=ind)) #increment group number for next blob ind += 1 result = self.partialDeepCopy(result) result.generateGroupLabels() return result