Commit d92cf181 authored by Félix Hartmann's avatar Félix Hartmann
Browse files

New interactive window for discarding points from the end of the

skeleton of an organ. These points are neither plotted nor included in
computations. This is useful when the end of the skeleton is crooked.
parent 71cc3bdc
......@@ -142,9 +142,10 @@ interekt = None # contains the main window
hdf5file = None # path to hdf5 data file
tk_list_images = None # Tk listbox object which contain the list of images
tk_toplevel_listimages = None # Tk window which displays the list of images
# contains the number of points which have to be removed from the end of organ skeleton
tk_nb_points_to_remove_from_end = None
tk_tige_offset = None # contains the offset for tige skeleton detection
tk_tige_percent_diam = None # contains the diameter multplier for the transverse range of tige skeleton detection
tk_detection_step = None # contains the space step for the skeleton detection process
PERCENT_DIAM_DEFAULT = 1.4 # default value chosen by Hugo
DETECTION_STEP_DEFAULT = 0.3 # default value chosen by Hugo
CURVATURE_AVERAGING_LENGTH = 2 # Length (in cm) of the zone over which the curvature is averaged
......@@ -179,7 +180,7 @@ def reset_globals_data():
global dtphoto, local_photo_path, thread_process, infos_traitement
global old_step, add_dist_draw, dist_measure_pts, pixel_distance, cm_distance
global tk_list_images, tk_toplevel_listimages
global tk_tige_offset, tk_tige_percent_diam, tk_detection_step
global tk_tige_offset, tk_tige_percent_diam
global hdf5file, tiges_data, tiges_names
# Reset all gl;obalvariables
......@@ -216,7 +217,6 @@ def reset_globals_data():
tk_list_images = None
tk_tige_offset = None
tk_tige_percent_diam = None
tk_detection_step = None
hdf5file = None
tiges_data = None
tiges_names = []
......@@ -490,6 +490,13 @@ def load_hdf5_file(hdf5file):
if dtphoto == []:
interekt.get_photo_datetime.set(False)
# Retrieve the space step for organ skeleton detection
detection_step = h5store.get_detection_step(hdf5file)
if detection_step is not None:
interekt.detection_step.set(detection_step)
else:
interekt.detection_step.set(DETECTION_STEP_DEFAULT)
# Retrieve the data on the steady state from the h5 file
steady_state, exclude_steady_state = h5store.get_steady_state(hdf5file)
interekt.steady_state_image = steady_state
......@@ -1019,9 +1026,8 @@ def launch_process():
Nimgs = h5store.get_number_of_images(hdf5file)
# Retrieve the detection step from the Tkinter DoubleVar
if tk_detection_step is not None:
detection_step = tk_detection_step.get()
else:
detection_step = interekt.detection_step.get()
if detection_step is None:
detection_step = DETECTION_STEP_DEFAULT
# Save the value of detection step into the hdf5 file
......@@ -1150,9 +1156,12 @@ def Traite_data(save_to_hdf5=False):
if detection_step is None:
detection_step = DETECTION_STEP_DEFAULT
cutoffs = h5store.get_number_of_points_to_remove_from_organ_end(hdf5file)
tiges_x, tiges_y, tiges_s, tiges_tailles, tiges_angles, tiges_tip_angles, \
tiges_lines, tiges_measure_zone = traite_tiges2(
tiges_data, pas=detection_step, return_estimation_zone=True)
tiges_data, pas=detection_step, return_estimation_zone=True,
cutoffs=cutoffs)
if save_to_hdf5:
for id_tige in range(len(tiges_x)):
......@@ -3488,34 +3497,84 @@ def pixel_calibration():
def detection_step_setting():
global tk_detection_step
# Ajout d'une boite tk pour l'export
top_step = Tk.Toplevel(master=root)
top_step.title(_("Skeleton detection step"))
"""
Interactive top level window for setting the space step for organ
skeleton detection.
"""
window_detection_step = Tk.Toplevel(master=root)
window_detection_step.title(_("Skeleton detection step"))
step_frame = Frame(top_step)
step_frame = Frame(window_detection_step)
w1 = Label(step_frame, text=_("Size of the detection step (in pixels):"))
w1.pack(fill='x', expand=True)
tk_detection_step = Tk.DoubleVar()
# Retrieve the detection step from the h5 file
detection_step = h5store.get_detection_step(hdf5file)
if detection_step is not None:
tk_detection_step.set(detection_step)
else:
tk_detection_step.set(DETECTION_STEP_DEFAULT)
detection_step = interekt.detection_step.get()
if detection_step is None:
interekt.detection_step.set(DETECTION_STEP_DEFAULT)
w2 = Tk.Scale(step_frame, from_=0.1, to=5, resolution=0.01, variable=tk_detection_step,
orient=Tk.HORIZONTAL)
w2 = Tk.Scale(step_frame, from_=0.1, to=5, resolution=0.01,
variable=interekt.detection_step, orient=Tk.HORIZONTAL)
w2.pack(fill='x', expand=True)
step_frame.pack()
def remove_points():
"""
Called by 'choose_points_to_remove' when the number of points to
remove from the end of an organ skeleton has been chosen.
Then the plot is updated with the newly trimmed skeleton, and
organ data are recomputed.
"""
tige_name = tiges_names[cur_tige]
hdf5_tigeid = get_hdf5_tigeid(hdf5file, cur_tige)
nb_points = tk_nb_points_to_remove_from_end.get()
h5store.save_number_of_points_to_remove_from_organ_end(
hdf5file, hdf5_tigeid, nb_points)
# Replot the main image
interekt.plot_image(cur_image, keep_zoom=True)
# Recompute data
Traite_data(save_to_hdf5=True)
def choose_points_to_remove():
"""
Interactive top level window for setting the number of points to
remove from the end of an organ skeleton.
"""
global tk_nb_points_to_remove_from_end
# Force la fermeture du menu popup dans tk
interekt.floatmenuisopen = False
# Retrieving from hdf5 file the organ name and the number of points to remove
tige_name = tiges_names[cur_tige]
hdf5_tigeid = get_hdf5_tigeid(hdf5file, cur_tige)
nb_points = \
h5store.get_number_of_points_to_remove_from_organ_end(hdf5file, hdf5_tigeid)
tk_nb_points_to_remove_from_end = Tk.IntVar()
tk_nb_points_to_remove_from_end.set(nb_points)
window_points_to_remove = Tk.Toplevel(master=root)
window_points_to_remove.title(_("Points to remove from organ") + " %s"%tige_name)
points_frame = Frame(window_points_to_remove)
w1 = Label(
points_frame,
text=_("Number of points to remove from the end of the organ:"))
w1.pack(side=Tk.LEFT)
w2 = Entry(points_frame, width=5, textvariable=tk_nb_points_to_remove_from_end)
w2.pack(side=Tk.LEFT, fill=Tk.X, expand=True)
Tk.Button(points_frame, text=_("Apply"),
command=remove_points).pack(fill=Tk.X, expand=True)
points_frame.pack()
def select_steady_state_image():
"""Top window for selecting the steady-state image.
......@@ -3859,6 +3918,8 @@ class Interekt:
options_menu.add_command(label=_("Scale"), command=pixel_calibration)
# Set the space step for skeleton detection process
self.detection_step = Tk.DoubleVar()
self.detection_step.set(DETECTION_STEP_DEFAULT)
options_menu.add_command(label=_("Step for skeleton detection"), command=detection_step_setting)
#TODO: Pour trier ou non les photos
......@@ -4043,6 +4104,10 @@ class Interekt:
command=show_B)
self.floatmenu.add_separator()
# Add the command for removing points from the end of the skeleton
self.floatmenu.add_command(label=_("Remove end points"),
command=choose_points_to_remove)
# In all cases, add the base commands
self.floatmenu.add_command(label=_("Settings"),
command=show_tige_options)
......@@ -4451,15 +4516,22 @@ class Interekt:
tige_plot_decimation = 100
else:
# Quand on est en fullresolution on decime moins les tiges
tige_plot_decimation = 10
tige_plot_decimation = 1 # 10
if tiges_data is not None:
# Plot des tiges traitée
for ti, tige_xyplot in enumerate(tiges_plot_object):
hdf5_tigeid = get_hdf5_tigeid(hdf5file, ti)
# On teste d'abord si il y a des données
tigeh5id = get_hdf5_tigeid(hdf5file, ti)
if h5store.is_data(hdf5file, 'xc', hdf5_tigeid):
if h5store.is_data(hdf5file, 'xc', tigeh5id):
# if points have to be removed from the skeleton end
nb_points = \
h5store.get_number_of_points_to_remove_from_organ_end(
hdf5file, hdf5_tigeid)
space_slice = slice(0, -nb_points or None, tige_plot_decimation)
# 'or None' replaces -0 with None
# Creation des graphiques
if tige_xyplot is None:
......@@ -4467,8 +4539,10 @@ class Interekt:
# avec le scalefactor
try:
tmp, = self.ax.plot(
tiges_data.xc[ti,int(img_num),::tige_plot_decimation].T * image_scale,
tiges_data.yc[ti,int(img_num),::tige_plot_decimation].T * image_scale,
tiges_data.xc[ti, int(img_num),
space_slice].T * image_scale,
tiges_data.yc[ti, int(img_num),
space_slice].T * image_scale,
lw=3, picker=5, label="%i"%(ti), color=tiges_colors[ti])
tiges_plot_object[ti] = tmp
except Exception as e:
......@@ -4479,8 +4553,10 @@ class Interekt:
else:
try:
tiges_plot_object[ti].set_data(
tiges_data.xc[ti,int(img_num),::tige_plot_decimation].T * image_scale,
tiges_data.yc[ti,int(img_num),::tige_plot_decimation].T * image_scale)
tiges_data.xc[ti, int(img_num),
space_slice].T * image_scale,
tiges_data.yc[ti, int(img_num),
space_slice].T * image_scale)
except Exception as e:
print(u'Erreur de mise à jour des données pour la tige %s en position %i du gui'%(tiges_names[ti], ti))
print(e)
......
......@@ -767,6 +767,72 @@ def get_tiges_bases(hdf5file, tige_num=None):
return output
def get_number_of_points_to_remove_from_organ_end(hdf5file, tige_id=None):
"""
Return the number of points to remove from the end of the
skeleton of the organ.
Parameters:
-----------
hdf5file, str:
HDF5 file containing the data.
tige_id, int:
Organ index. If None, return a list with the numbers of
points for all organs.
"""
if tige_id is None:
tiges_ids = get_tiges_indices(hdf5file)
else:
tiges_ids = [tige_id]
nb_points = []
if tiges_ids != []:
with h5py.File(hdf5file, 'r') as f:
for idx in tiges_ids:
if 'data/tige%i/nb_points_to_remove_from_end'%idx in f:
nb = h5todict(
hdf5file,
path='data/tige%i/nb_points_to_remove_from_end'%idx)
nb_points.append(nb)
else:
# by default, return 0
nb_points.append(0)
# If an organ index has been given, do not return a list
if tige_id is not None:
nb_points = nb_points[-1]
return nb_points
def save_number_of_points_to_remove_from_organ_end(hdf5file, tige_id, nb_points):
"""
Save the number of points to remove from the end of the
skeleton of the organ.
Parameters:
-----------
hdf5file, str:
HDF5 file containing the data.
tige_id, int:
Organ index.
nb_points, int:
Number of points to remove.
"""
tige_points_dict = {'nb_points_to_remove_from_end': int(nb_points)}
dicttoh5(treedict=tige_points_dict, hdf5file=hdf5file,
h5path='/data/tige%i'%tige_id,
mode="a")
def get_tiges_names(hdf5file, tige_num=None):
"""
Fonction pour récupérer le nom d'une tige si tige_num est un
......
......@@ -1159,9 +1159,9 @@ def traite_tige2(xc, yc, R, pas, cutoff=5):
# Filtre les tiges trop petites
if L > 1.5 * R.mean() and len(x) > cutoff * 2:
# Retire coupe point au bout
x = x[:-cutoff]
y = y[:-cutoff]
R = R[:-cutoff]
x = x[:-cutoff or None] # -0 is replaced with None
y = y[:-cutoff or None]
R = R[:-cutoff or None]
# Retourne y car photo axes dans autre sens
y = -y
......@@ -1193,7 +1193,8 @@ def traite_tige2(xc, yc, R, pas, cutoff=5):
return smoothed_x, smoothed_y, angle, s, W
def traite_tiges2(tiges, itige=None, pas=0.3, causette=True, return_estimation_zone=False):
def traite_tiges2(tiges, itige=None, pas=0.3, causette=True,
return_estimation_zone=False, cutoffs=None):
"""
Fonction pour traiter les tiges detectées pour l'expérience du gravitron
**return x, y, dx, dy, s, L, angle, tip_angle, lines**
......@@ -1208,6 +1209,10 @@ def traite_tiges2(tiges, itige=None, pas=0.3, causette=True, return_estimation_z
return_estimation_zone : Bool
If True, the averaging zone for the tip angle computation is returned.
cutoff : list of int
Number of points which will be removed from the end of the
each organ skeleton. If None, no points are removed.
Returns
-------
x : 3-D ndarray
......@@ -1234,6 +1239,9 @@ def traite_tiges2(tiges, itige=None, pas=0.3, causette=True, return_estimation_z
else:
Ntige = len(itige)
if cutoffs is None:
cutoffs = zeros(Ntige)
lines = [None] * Ntige
bad_value = -30000
......@@ -1259,7 +1267,8 @@ def traite_tiges2(tiges, itige=None, pas=0.3, causette=True, return_estimation_z
xt, yt, anglet, st, W = \
traite_tige2(tiges.xc[itige[i], t, :],
tiges.yc[itige[i], t, :],
tiges.diam[itige[i], t, :] / 2., pas)
tiges.diam[itige[i], t, :] / 2.,
pas, cutoff=cutoffs[i])
if xt is None and yt is None:
if causette:
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment