def find_tracks(n=-1, maxdist=20, giveup=10, cut=False): sys.setrecursionlimit(max(sys.getrecursionlimit(), 2*giveup)) trackids = -np.ones(data.shape, dtype=int) if n==-1: n = np.count_nonzero(data['f']==0) print "number of particles:", n if cut: bgimage = locdir + prefix + '_0001.tif' from os.path import isfile if not isfile(bgimage): bgimage = raw_input('Please give the path to an image ' 'from this dataset to identify boundary\n') C, R = helpy.circle_click(bgimage) margin = S if S>1 else R/16.9 # assume 6mm particles if S not specified rs = np.hypot(data['x'] - C[0], data['y'] - C[1]) cut = rs > R - margin print "seeking tracks" for i in range(len(data)): trackids[i] = find_closest(data[i], trackids, maxdist=maxdist, giveup=giveup, cut=cut) # save the data record array and the trackids array print "saving track data" # Michael used the data['lab'] field (as line[3] for line in data) to store # trackids. I'll keep doing that: assert len(data) == len(trackids), "too few/many trackids" assert np.allclose(data['id'], np.arange(len(data))), "gap in particle id" data['lab'] = trackids #data = data[trackids < n] # michael did this to "crop out extra tracks" stubs = np.where(np.bincount(trackids+1)[1:] < args.stub)[0] if verbose: print "removing {} stubs".format(len(stubs)) stubs = np.in1d(trackids, stubs) trackids[stubs] = -1 return trackids
def find_tracks(pdata, maxdist=20, giveup=10, n=0, cut=False, stub=0): """ Track dots from frame-to-frame, giving each particle a unique and persistent id, called the trackid. parameters ---------- pdata : the main positions data array maxdist : maximal separation in pixels between a particles current and previous position. i.e., the maximum distance a particle is allowed to travel to be considered part of the same track A good choice for this value is the size of one particle. giveup : maximal number of frames to recurse over seeking the parent n : the number of particles to track, useful if you wish to have one track per physical particle. Not useful if you want tracks to be cut when the particle hits the boundary cut : whether or not to cut tracks (assign a new trackid to the same physical particle) when the particle nears or hits the boundary if True, it requires either args.boundary or for user to click on an image to mark the center and boundary. Particle at the boundary (between two tracks) will have track id of -1 stub : minimal length of a track for it to be kept. trackids of any track with length less than `stub` will be set to -1 returns ------- trackids : an array of length `len(pdata)`, giving the track id number for each point in data. Any point not belonging to any track has a track id of -1 """ from sys import setrecursionlimit, getrecursionlimit setrecursionlimit(max(getrecursionlimit(), 2*giveup)) trackids = -np.ones(pdata.shape, dtype=int) if n is True: # use the mode of number of particles per frame # np.argmax(np.bincount(x)) == mode(x) n = np.argmax(np.bincount(np.bincount(pdata['f']))) print "Found {n} particles, will use {n} longest tracks".format(n=n) if cut: if args.boundary: print "cutting at supplied boundary" x0, y0, R = args.boundary elif 'track_cut_boundary' in meta: print "cutting at previously saved boundary" x0, y0, R = meta['track_cut_boundary'] else: not_found = ('Please give the path to a tiff image ' 'from this dataset to identify boundary\n') bgimage = helpy.find_first_frame([locdir, prefix], err=not_found) x0, y0, R = helpy.circle_click(bgimage) print "cutting at selected boundary (x0, y0, r):", x0, y0, R # assume 6mm particles if S not specified mm = R/101.6 # R = 4 in = 101.6 mm margin = S if S>1 else 6*mm meta['track_cut_boundary'] = (x0, y0, R) meta['track_cut_margin'] = margin print 'Cutting with margin {:.1f} pix = {:.1f} mm'.format(margin, margin/mm) rs = np.hypot(pdata['x'] - x0, pdata['y'] - y0) cut = rs > R - margin print "seeking tracks" for i in xrange(len(pdata)): # This must remain a simple loop because trackids gets modified and # passed into the function with each iteration trackids[i] = find_closest(pdata.item(i), trackids, maxdist=maxdist, giveup=giveup, cut=cut) if verbose: assert len(pdata) == len(trackids), "too few/many trackids" assert np.allclose(pdata['id'], np.arange(len(pdata))), "gap in particle id" if n or stub > 0: track_lens = np.bincount(trackids+1)[1:] if n: stubs = np.argsort(track_lens)[:-n] # all but the longest n elif stub > 0: stubs = np.where(track_lens < stub)[0] if verbose: print "removing {} stubs".format(len(stubs)) if n or stub > 0: stubs = np.in1d(trackids, stubs) trackids[stubs] = -1 return trackids
sizes.update({ 'corner': { 'max_ecc': args.cecc, 'min_area': args.cmin or int(ckern_area // 2), 'max_area': args.cmax or int(ckern_area * 2 + 1), 'kern': args.ckern, 'thresh': args.cthresh } }) dots = sorted(sizes) meta.update( {dot + '_' + k: v for dot in dots for k, v in sizes[dot].iteritems()}) if args.boundary is not None: args.boundary = args.boundary or helpy.circle_click(first) meta.update(boundary=args.boundary) def snapshot(desc, im, **kwargs): global snapshot_num, imprefix if args.save: fname = '{}_{:02d}_{}.png'.format(imprefix, snapshot_num, desc) plt.imsave(fname, im, **kwargs) else: fig, ax = plt.subplots() ax.imshow(im, title=os.path.basename(imprefix) + '_' + desc, **kwargs) snapshot_num += 1 def plot_points(pts,
'thresh': args.thresh}} if args.ckern: args.both = True if args.both: ckern_area = np.pi*args.ckern**2 sizes.update({'corner': {'max_ecc': args.cecc, 'min_area': args.cmin or int(ckern_area//2), 'max_area': args.cmax or int(ckern_area*2 + 1), 'kern': args.ckern, 'thresh': args.cthresh}}) dots = sorted(sizes) meta.update({dot + '_' + k: v for dot in dots for k, v in sizes[dot].iteritems()}) if args.boundary is not None: args.boundary = args.boundary or helpy.circle_click(first) meta.update(boundary=args.boundary) def snapshot(desc, im, **kwargs): global snapshot_num, imprefix if args.save: fname = '{}_{:02d}_{}.png'.format(imprefix, snapshot_num, desc) plt.imsave(fname, im, **kwargs) else: fig, ax = plt.subplots() ax.imshow(im, title=os.path.basename(imprefix)+'_'+desc, **kwargs) snapshot_num += 1 def plot_points(pts, img, name='', s=10, c='r', cmap=None, vmin=None, vmax=None, cbar=False): global snapshot_num, imprefix
if args.ckern: args.both = True if args.both: ckern_area = np.pi*args.ckern**2 if args.cmin == -1: args.cmin = ckern_area/2 if args.cmax == -1: args.cmax = 2*ckern_area thresh.update({'corner': {'max_ecc' : args.cecc, 'min_area': args.cmin, 'max_area': args.cmax, 'kern' : args.ckern}}) dots = sorted(thresh) if args.select: co, ro = helpy.circle_click(filenames[0]) def plot_positions(savebase, level, pts, labels, convolved=None,): cm = pl.cm.prism_r pl.clf() labels_mask = labels.astype(float) labels_mask[labels_mask==0] = np.nan pl.imshow(labels_mask, cmap=cm, interpolation='nearest') ax = pl.gca() xl, yl = ax.get_xlim(), ax.get_ylim() if level > 1: ptsarr = np.asarray(pts) pl.scatter(ptsarr[:,1], ptsarr[:,0], s=10, c='r')#ptsarr[:,2], cmap=cm) pl.xlim(xl); pl.ylim(yl) savename = savebase + '_POSITIONS.png' if args.verbose: print 'saving positions image to', savename
kern_area = np.pi * args.kern**2 size = { 'center': { 'max_ecc': args.ecc, 'min_area': args.min or int(kern_area // 2), 'max_area': args.max or int(kern_area * 2 + 1), 'kern': float(args.kern), 'thresh': args.thresh, 'convex': args.convex } } meta.update({k: v for k, v in size['center'].iteritems()}) #initialize boundary boundary = meta.get('boundary') if boundary is None or boundary == [0.0] * 3: boundary = helpy.circle_click(first) meta.update(boundary=boundary) helpy.save_meta(prefix, meta) x0, y0, R0 = boundary #initialize model for machine leanring device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') # load category network net_cat = ClassNet() net_cat.load_state_dict(torch.load(args.cpath)) net_cat.eval() net_cat.to(device) # load orientation network net = ConvNet() net.load_state_dict(torch.load(args.opath)) net.eval() net.to(device)
def find_tracks(maxdist=20, giveup=10, n=0, cut=False, stub=0): """ Track dots from frame-to-frame, giving each particle a unique and persistent id, called the trackid. parameters ---------- maxdist : maximal separation in pixels between a particles current and previous position. i.e., the maximum distance a particle is allowed to travel to be considered part of the same track A good choice for this value is the size of one particle. giveup : maximal number of frames to recurse over seeking the parent n : the number of particles to track, useful if you wish to have one track per physical particle. Not useful if you want tracks to be cut when the particle hits the boundary cut : whether or not to cut tracks (assign a new trackid to the same physical particle) when the particle nears or hits the boundary if True, it requires either args.center or for user to click on an image to mark the center and boundary. Particle at the boundary (between two tracks) will have track id of -1 stub : minimal length of a track for it to be kept. trackids of any track with length less than `stub` will be set to -1 accesses -------- data : the main data array modifies -------- data : replaces the `data['lab']` field with the values from `trackids` returns ------- trackids : an array of length `len(data)`, giving the track id number for each point in data. Any point not belonging to any track has a track id of -1 """ from sys import setrecursionlimit, getrecursionlimit setrecursionlimit(max(getrecursionlimit(), 2*giveup)) trackids = -np.ones(data.shape, dtype=int) if n is True: # use the mode of number of particles per frame # np.argmax(np.bincount(x)) == mode(x) n = np.argmax(np.bincount(np.bincount(data['f']))) print "Found {n} particles, will use {n} longest tracks".format(n=n) if cut: if args.center: C = args.center[:2] R = args.center[2] else: from glob import glob bgimage = glob(locdir + prefix + "*.tif") if not bgimage: bgimage = glob(locdir + prefix + "/*.tif") if not bgimage: bgimage = glob(locdir + '../' + prefix + "/*.tif") if not bgimage: bgimage = raw_input('Please give the path to a tiff image ' 'from this dataset to identify boundary\n') else: bgimage = bgimage[0] print 'Opening', bgimage C, R = helpy.circle_click(bgimage) print "Boundary:", C, R margin = S if S>1 else R/16.9 # assume 6mm particles if S not specified rs = np.hypot(data['x'] - C[0], data['y'] - C[1]) cut = rs > R - margin print "seeking tracks" for i in range(len(data)): trackids[i] = find_closest(data[i], trackids, maxdist=maxdist, giveup=giveup, cut=cut) if verbose: assert len(data) == len(trackids), "too few/many trackids" assert np.allclose(data['id'], np.arange(len(data))), "gap in particle id" if n or stub > 0: track_lens = np.bincount(trackids+1)[1:] if n: stubs = np.argsort(track_lens)[:-n] # all but the longest n elif stub > 0: stubs = np.where(track_lens < stub)[0] if verbose: print "removing {} stubs".format(len(stubs)) if n or stub > 0: stubs = np.in1d(trackids, stubs) trackids[stubs] = -1 # Michael used the data['lab'] field (as line[3] for line in data) to store # trackids. I'll keep doing that: data['lab'] = trackids return trackids