Esempio n. 1
0
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
Esempio n. 2
0
            dt0  = 10 # here's assuming...
            dtau = 10 #  should be true for all from before dt* was saved

    if args.save:
        helpy.save_meta(absprefix, meta)

if __name__=='__main__':
    if args.plotmsd:
        if verbose: print 'plotting msd now!'
        plot_msd(msds, msdids, dtau, dt0, data['f'].max()+1, tnormalize=False,
                 prefix=absprefix, show_tracks=args.showtracks, show=args.show,
                 singletracks=args.singletracks, fps=fps, S=S, save=args.save,
                 kill_flats=args.killflat, kill_jumps=args.killjump*S*S)
    if args.plottracks:
        if verbose: print 'plotting tracks now!'
        bgimage = helpy.find_first_frame([locdir, prefix])
        if args.singletracks:
            mask = np.in1d(trackids, args.singletracks)
        else:
            mask = None
        plot_tracks(data, trackids, bgimage, mask=mask,
                    save=args.save, show=args.show)

if __name__=='__main__' and args.nn:
    # Calculate the <nn> correlation for all the tracks in a given dataset
    # TODO: fix this to combine multiple datasets (more than one prefix)

    if args.verbose:
        print 'calculating <nn> correlations for track'
        coscorrs = []
        sincorrs = []