Skip to content

Commit

Permalink
added multiframe tracker to workflow, params_file and user manual. ve…
Browse files Browse the repository at this point in the history
…rsion up to 1.1.0
  • Loading branch information
ronshnapp committed Oct 27, 2024
1 parent 94a7dd5 commit 703046b
Show file tree
Hide file tree
Showing 10 changed files with 290 additions and 239 deletions.
4 changes: 2 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
October 04, 2024
October 27, 2024

Version: 1.0.3
Version: 1.1.0


<img src="./user_manual/figs/logo.png" style="zoom:20%;" />
Expand Down
4 changes: 4 additions & 0 deletions example/params_file.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,14 @@

- tracking:
particles_file_name: particles
method: multiframe
frame_start: 0
N_frames: None
d_max: 1.0
dv_max: 1.0
max_dt: 3
Ns: 5
NSR_threshold: 0.25
mean_flow: [0.0, 0.0, 0.0]
plot_candidate_graph: False
save_name: trajectories
Expand Down
160 changes: 114 additions & 46 deletions example/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,8 @@ def do_tracking(self):
'''
Will perform the tracking using the file given parameters.
'''
from myptv.tracking_mod import tracker_four_frames
from myptv.tracking_mod import tracker_four_frames, tracker_multiframe
from myptv.tracking_mod import traj_NSR, fill_in_trajectory
from numpy import array
from os import getcwd, listdir
from os.path import exists as pathExists
Expand All @@ -1017,63 +1018,124 @@ def do_tracking(self):
candidate_graph = self.get_param('tracking', 'plot_candidate_graph')
save_name = self.get_param('tracking', 'save_name')

method = self.get_param('tracking', 'method')
max_dt = self.get_param('tracking', 'max_dt')
Ns = self.get_param('tracking', 'Ns')
NSR_th = self.get_param('tracking', 'NSR_threshold')

# initiate the tracker
t4f = tracker_four_frames(particles_fm,
d_max=d_max,
dv_max=dv_max,
mean_flow=array(mean_flow),
store_candidates = candidate_graph)

#setting up the frame range
ts = int(t4f.times[0])
te = int(t4f.times[-1])
if method not in ['multiframe', 'fourframe']:
raise ValueError("method can only be 'multiframe' or 'four_frame'.")



print('available particles time range: %d -> %d'%(ts,te),'\n')

if candidate_graph and (te-ts)>100:
print('Warning: you are about to plot a candidate graph with')
print('more than 100 frames.')
ans = input('Do you wish to proceed (1 = Yes , else = No)? ')
if method=='fourframe':

# initiate the tracker
t4f = tracker_four_frames(particles_fm,
d_max=d_max,
dv_max=dv_max,
mean_flow=array(mean_flow),
store_candidates = candidate_graph)

#setting up the frame range
ts = int(t4f.times[0])
te = int(t4f.times[-1])

print('available particles time range: %d -> %d'%(ts,te),'\n')

if ans=='1':
pass
if candidate_graph and (te-ts)>100:
print('Warning: you are about to plot a candidate graph with')
print('more than 100 frames.')
ans = input('Do you wish to proceed (1 = Yes , else = No)? ')

if ans=='1':
pass

else:
print('quitting ')
return None


if frame_start is not None:
if frame_start>=ts and frame_start <=te:
ts = frame_start
else:
print('Warning: frame_start outside the available frame range')
#raise ValueError('frame_start outside the available frame range')

if N_frames is None:
frames = range(ts, te)
else:
print('quitting ')
return None
try:
frames = range(ts, ts+N_frames)
except:
tp = type(frames)
msg = 'N_frames must be an integer or None (given %s).'%tp
raise TypeError(msg)

# do the tracking
t4f.track_all_frames(frames=frames)

# print some statistics
tr = array(t4f.return_connected_particles())
untracked = len(tr[tr[:,0]==-1])
tot = len(tr)
print('untracked fraction:', untracked/tot)
print('tracked per frame:', (tot-untracked)/len(set(tr[:,-1])))

if candidate_graph:
t4f.plot_candidate_graph()

if frame_start is not None:
if frame_start>=ts and frame_start <=te:
ts = frame_start
else:
print('Warning: frame_start outside the available frame range')
#raise ValueError('frame_start outside the available frame range')

if N_frames is None:
frames = range(ts, te)
else:
try:
frames = range(ts, ts+N_frames)
except:
tp = type(frames)
msg = 'N_frames must be an integer or None (given %s).'%tp
raise TypeError(msg)


# do the tracking
t4f.track_all_frames(frames=frames)

# print some statistics
tr = array(t4f.return_connected_particles())
untracked = len(tr[tr[:,0]==-1])
tot = len(tr)
print('untracked fraction:', untracked/tot)
print('tracked per frame:', (tot-untracked)/len(set(tr[:,-1])))

if candidate_graph:
t4f.plot_candidate_graph()
elif method=='multiframe':

tmf = tracker_multiframe(particles_fm, max_dt, Ns,
d_max=d_max, dv_max=dv_max,
NSR_th=NSR_th,
mean_flow=array(mean_flow))

#setting up the frame range
ts = int(tmf.times[0])
te = int(tmf.times[-1])
print('available particles time range: %d -> %d'%(ts,te),'\n')

if candidate_graph:
print('\nNote, candidate graph can only be plotted with')
print('fourframe tracker, so it is skipped.')


if frame_start is not None:
if frame_start>=ts and frame_start <=te:
ts = frame_start
else:
print('Warning: frame_start outside the available frame range')
#raise ValueError('frame_start outside the available frame range')

if N_frames is None:
frames = range(ts, te)
else:
try:
frames = range(ts, ts+N_frames)
except:
tp = type(frames)
msg = 'N_frames must be an integer or None (given %s).'%tp
raise TypeError(msg)


# doing the tracking
frame_skips = max([int(Ns/3), 1])
tmf.track_frames(f0=ts, fe=te, frame_skips=frame_skips)

# interpolating missing points
tmf.interpolate_trajs()



# save the results
if save_name is not None:
Expand All @@ -1084,18 +1146,24 @@ def do_tracking(self):
usr = input('(1=yes, else=no)')
if usr == '1':
print('\n','saving file.')
t4f.save_results(save_name)
if method=='fourframe': t4f.save_results(save_name)
elif method=='multiframe': tmf.save_results(save_name)

else:
print('\n', 'skipped saving.')

else:
print('\n','saving file.')
t4f.save_results(save_name)
if method=='fourframe': t4f.save_results(save_name)
elif method=='multiframe': tmf.save_results(save_name)

print('\n', 'Finished tracking.')






def do_smoothing(self):
'''
Will smooth the trajectories using the specified file given paramters.
Expand Down
85 changes: 24 additions & 61 deletions myptv/tracking_mod.py
Original file line number Diff line number Diff line change
Expand Up @@ -1099,8 +1099,8 @@ def track_frames(self, f0=None, fe=None, frame_skips=2):
msg = 'Tracking forward and backward, round 1'

for frm in tqdm.tqdm(range(f0, fe, frame_skips), desc=msg):
tmf.build_trajectories_from_frame(frm, p_bar=False)
tmf.build_trajectories_from_frame(fe+f0-frm-1,
self.build_trajectories_from_frame(frm, p_bar=False)
self.build_trajectories_from_frame(fe+f0-frm-1,
backwards=True, p_bar=False)

msg = 'Tracking forward and backward, round 2'
Expand All @@ -1109,8 +1109,8 @@ def track_frames(self, f0=None, fe=None, frame_skips=2):
fe-int(frame_skips/2),
frame_skips), desc=msg):

tmf.build_trajectories_from_frame(frm, p_bar=False)
tmf.build_trajectories_from_frame(fe+f0-frm-1,
self.build_trajectories_from_frame(frm, p_bar=False)
self.build_trajectories_from_frame(fe+f0-frm-1,
backwards=True, p_bar=False)

print('')
Expand Down Expand Up @@ -1289,7 +1289,7 @@ def tracking_movie(self, particle_identifier):
This animates the tracking of a given particle with all the candidates
'''

ret = tmf.build_candidate_trajectories(particle_identifier)[0]
ret = self.build_candidate_trajectories(particle_identifier)[0]

for tr in ret:
xmin = min(min(tr, key=lambda x: min(x[:,1]))[:,1]) - 2*self.d_max
Expand All @@ -1312,7 +1312,7 @@ def tracking_movie(self, particle_identifier):
ax.plot(tr[whr,1], tr[whr,2], 'o-', alpha=0.3)

for frm in range(f0, fe+1):
for p in tmf.particles[frm]:
for p in self.particles[frm]:
if xmin<p[1]<xmax and ymin<p[2]<ymax:
ax.plot(p[1], p[2], 'ko', ms=2)

Expand Down Expand Up @@ -1371,49 +1371,8 @@ def traj_NSR(traj, Ns):
NSR.append(0)

return NSR






def smooth_trajectory(traj, Ns):
'''
Returns a trajectory smoothed over windows with size Ns via a
polynomial with degree 2.
'''
from numpy import polyfit, poly1d

if Ns%2 != 1:
raise ValueError('Ns must be an odd interger')

w = int(Ns/2)

if len(traj)<=Ns:
signal = traj
return signal

signal = []

for i in range(w):
signal.append([traj[i,1], traj[i,2], traj[i,3]])

for i in range(w, len(traj)-w):
x_ = traj[i-w:i+w+1, -1] - traj[i-w, -1]
signal.append([])
for j in range(3):
y_ = traj[i-w:i+w+1, j+1]
p = poly1d(polyfit(x_, y_, 2))
signal[-1].append(p(w))

for i in range(-w,0):
signal.append([traj[i,1], traj[i,2], traj[i,3]])

return array(signal)






def fill_in_trajectory(tr):
Expand Down Expand Up @@ -1477,22 +1436,26 @@ def fill_in_trajectory(tr):







# Tests:
if __name__ == "__main__":
fname = '/home/ron/Desktop/Research/jetArrayTank/20241020_puffs/Rec18/particles'
max_dt = 3
Ns = 11
NSR_th = 0.25
tmf = tracker_multiframe(fname, max_dt, Ns, d_max=0.5, dv_max=0.5, NSR_th=NSR_th)

f0 = 134
fe = None
frame_skips = 5
tmf.track_frames(f0=f0, fe=fe, frame_skips=frame_skips)
tmf.interpolate_trajs()
# =============================================================================
# # Tests:
# if __name__ == "__main__":
# fname = '/home/ron/Desktop/Research/jetArrayTank/20241020_puffs/Rec18/particles'
# max_dt = 3
# Ns = 11
# NSR_th = 0.25
# tmf = tracker_multiframe(fname, max_dt, Ns, d_max=0.5, dv_max=0.5, NSR_th=NSR_th)
#
# f0 = None
# fe = None
# frame_skips = 3
# tmf.track_frames(f0=f0, fe=fe, frame_skips=frame_skips)
# tmf.interpolate_trajs()
#
# tmf.save_results('trajectories_multiframe')
# =============================================================================



Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
setup(
name='myptv',
packages=find_packages(include=['myptv', 'myptv.fibers', 'myptv.TsaiModel', 'myptv.extendedZolof', 'myptv.makePlots', 'myptv.sheets']),
version='1.0.4',
version='1.1.0',
description='A 3D Particle Tracking Velocimetry library',
install_requires=['numpy', 'scipy', 'scikit-image','pandas','matplotlib','pyyaml', 'tk', 'Pillow>=9.5.0'],
author='Ron Shnapp',
Expand Down
Binary file modified user_manual/figs/traj_image.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 703046b

Please sign in to comment.