interekt.py 196 KB
Newer Older
hchauvet's avatar
hchauvet committed
1
2
3
4
5
6
7
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Created on Mon May 18 14:14:54 2015

Petite interface graphique pour traiter les tiges ou les racines

8
@authors: Hugo Chauvet and Félix Hartmann
hchauvet's avatar
hchauvet committed
9

10
Changes:
Félix Hartmann's avatar
Félix Hartmann committed
11
09/04/2021: [Félix] Multilingual support for English, Esperanto and French + bufixes.
Félix Hartmann's avatar
Félix Hartmann committed
12
13
14
15
16
05/10/2020: [Félix] A lot of changes: bugfixes for Py2/3 compatibility
                    + multilingual support with gettext (English-only for now)
                    + partial refactoring, for the multilingual support
                    + new ways of estimating the growth length
                    + new estimation of B, with the selection of a steady-state image
17
04/06/2020: [Félix] Transition to Python3, while maintaining compatibility with Python2.
18
19
29/05/2020: [Félix] Adding growth rate estimation for computing beta_tilde and beta_tilde
                    + improved export of phenotyping data to CSV file.
Félix Hartmann's avatar
Félix Hartmann committed
20
21
20/01/2020: [Félix] Adding Lagrangian marks
                    + popup window for manualy estimating the growth length using curvature heatmap
22
06/09/2019: [Hugo] Fin de la première version compatible HDF5
Félix Hartmann's avatar
Félix Hartmann committed
23
19/07/2019: [Félix] Ajout du calcul de gamma pour expérience sous clinostat, Hugo ajout de la fonction reset_globals_data
24
04/05/2019: [Hugo] Correct bugs on export when tige_id_mapper was defined with string names for bases. Allow float in the slide to select sensitivity.
25
24/09/2018: [Hugo] Remove test dectection (ne marche pas en Thread avec matplotlib!) + Correction bug pour traiter une seule image.
26
08/06/2018: [Hugo] Correct queue.qsize() bug in osX (car marche pas sur cette plateforme
27
18/04/2018: [Hugo] correct datetime bug. Set percent_diam to 1.4 in MethodOlivier (previous 0.9). Windows system can now use thread
28
22/10/2017: [Hugo] Optimisation du positionnement du GUI, utilisation de Tk.grid a la place de Tk.pack
29
16/10/2015: [Hugo] Ajout de divers options pour la tige (suppression etc..) avec menu click droit
hchauvet's avatar
hchauvet committed
30
31
32
33
34
35
                   +Refactorisation de plot_image et de la gestion du global_tige_id_mapper (pour gerer les suppressions)

30/07/2015: [Hugo] Correction bugs pour les racines dans libgravimacro + Ajout visu position de la moyenne de l'ange + Ajout d'options pour le temps des photos
25/05/2015: [Hugo] Ajout des menus pour l'export des moyennes par tiges et pour toutes les tiges + figures
20/05/2015: [Hugo] Première version
"""
36

Félix Hartmann's avatar
Félix Hartmann committed
37
38
from __future__ import (unicode_literals, absolute_import, division, print_function)

39
40
import sys, os
if sys.version_info[0] < 3:
41
42
43
44
45
    python2 = True
else:
    python2 = False

if python2:
46
    import Tkinter as Tk, tkFileDialog as filedialog, tkMessageBox as messagebox
47
    from ttk import Style, Button, Frame, Progressbar, Label, Entry, Scale, Checkbutton
48
49
50
51
    import Queue as queue
else:
    import tkinter as Tk
    from tkinter import filedialog, messagebox
52
53
    from tkinter.ttk import (Style, Button, Frame, Progressbar, Label, Entry, Scale,
                             Checkbutton)
54
55
    import queue

56
if python2:
57
58
    import cPickle as pkl

hchauvet's avatar
hchauvet committed
59
60
61
62
63
64
65
66
67
import matplotlib
matplotlib.use('TkAgg')

#Remove zoom key shorcuts
matplotlib.rcParams['keymap.back'] = 'c'
matplotlib.rcParams['keymap.forward'] = 'v'

import matplotlib.pylab as mpl
from matplotlib.collections import LineCollection
68
from matplotlib.ticker import MultipleLocator
Félix Hartmann's avatar
Félix Hartmann committed
69
70
71
from matplotlib.colors import SymLogNorm
from matplotlib.widgets import RectangleSelector
from matplotlib.backend_bases import key_press_handler
72
if python2:
73
74
75
76
    from matplotlib.backends.backend_tkagg import (
        FigureCanvasTkAgg, NavigationToolbar2TkAgg as NavigationToolbar2Tk)
else:
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
hchauvet's avatar
hchauvet committed
77

78
79
80
from numpy import (array, arange, zeros_like, zeros, ones, linspace, newaxis, NaN, isnan,
                   hstack, ma, exp, log, arctan2, sqrt, sin, cos, pi, mean,
                   timedelta64, argmin, argsort, nonzero, flatnonzero, diff, gradient,
81
                   rad2deg, deg2rad, quantile,
82
                   )
83
from numpy.linalg import norm
hchauvet's avatar
hchauvet committed
84
85
86
87

from scipy.optimize import fmin
import pandas as pd

88
89
90
91
import re
finddigits = re.compile(r'\d+?')
from threading import Thread
from collections import OrderedDict
92

Félix Hartmann's avatar
Félix Hartmann committed
93
94
import gettext  # internationalization

95
from new_libgravimacro import (ProcessImages, traite_tiges2, traite_tige2,
96
                               get_differential_arc_length,
Félix Hartmann's avatar
Félix Hartmann committed
97
                               integrate_diff_arc_length,
98
                               get_tige_curvature,
Félix Hartmann's avatar
Félix Hartmann committed
99
                               convert_angle,
100
                               plot_sequence,
101
102
                               do_intersect,
                               load_results) # 'load_results' is old method for pkl files
hchauvet's avatar
hchauvet committed
103

104
import interekt_hdf5_store as h5store
105

106
from Extrawidgets import DraggableLines, DraggablePoints
hchauvet's avatar
hchauvet committed
107

Félix Hartmann's avatar
Félix Hartmann committed
108
__version__ = '2020-10-05'
109

hchauvet's avatar
hchauvet committed
110
########################## GLOBAL DATA ########################################
Félix Hartmann's avatar
Félix Hartmann committed
111
strings = dict()  # strings for the user interface, with gettext
112
tiges_data = None
113
tiges_names = []
hchauvet's avatar
hchauvet committed
114
115
img_object = None
text_object = None
116
tiges_plot_object = []
hchauvet's avatar
hchauvet committed
117
118
base_pts_out = None
base_dir_path = None
119
cur_image = None
hchauvet's avatar
hchauvet committed
120
121
122
123
124
125
126
cur_tige = None
toptige = None
add_tige = False
nbclick = 0
base_tiges = []
btige_plt = []
btige_text = []
127
btige_arrow = []
hchauvet's avatar
hchauvet committed
128
tiges_colors = None
Félix Hartmann's avatar
Félix Hartmann committed
129
130
131
132
add_mark = False
marks = []
mark_plt = []
mark_text = []
hchauvet's avatar
hchauvet committed
133
dtphoto = []
134
thread_process = None  # To store the thread that run image processing
hchauvet's avatar
hchauvet committed
135
136
infos_traitement = None
old_step = 0
137
add_dist_draw = False
hchauvet's avatar
hchauvet committed
138
139
140
dist_measure_pts = []
pixel_distance = None
cm_distance = None
141
142
143
144
145
146
147
148
149
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
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
150
CURVATURE_AVERAGING_LENGTH = 2  # Length (in cm) of the zone over which the curvature is averaged
151

hchauvet's avatar
hchauvet committed
152
def reset_graph_data():
Félix Hartmann's avatar
Félix Hartmann committed
153
154
155
    global img_object, text_object, tiges_plot_object
    global btige_plt, btige_text, btige_arrow
    global mark_plt, mark_text
hchauvet's avatar
hchauvet committed
156
157
158

    img_object = None
    text_object = None
159
    tiges_plot_object = []
hchauvet's avatar
hchauvet committed
160
161
    btige_plt = []
    btige_text = []
162
    btige_arrow = []
Félix Hartmann's avatar
Félix Hartmann committed
163
164
    mark_plt = []
    mark_text = []
hchauvet's avatar
hchauvet committed
165

Félix Hartmann's avatar
Félix Hartmann committed
166

167
168
def reset_globals_data():
    """
169
    Reset all global variables, ala Fortran.
170

171
    Useful when loading a new file.
172
    """
173
    print("Reset all variables and data.")
Félix Hartmann's avatar
Félix Hartmann committed
174

175
    global data_out, text_object, tige_plot_object, base_pts_out, base_dir_path
176
    global cur_image, cur_tige, toptige, add_tige, btige_arrow
177
    global nbclick, base_tiges, btige_plt, btige_text, tiges_colors
Félix Hartmann's avatar
Félix Hartmann committed
178
    global marks, mark_plt, mark_text
179
    global dtphoto, local_photo_path, thread_process, infos_traitement
180
181
182
    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
183
    global hdf5file, tiges_data, tiges_names
Félix Hartmann's avatar
Félix Hartmann committed
184

185
    # Reset all gl;obalvariables
186
187
188
189
190
191
192
    # RAZ des autres valeurs
    data_out = None
    img_object = None
    text_object = None
    tige_plot_object = None
    base_pts_out = None
    base_dir_path = None
193
    cur_image = None
194
195
196
197
198
199
200
    cur_tige = None
    toptige = None
    add_tige = False
    nbclick = 0
    base_tiges = []
    btige_plt = []
    btige_text = []
201
    btige_arrow = []
202
    tiges_colors = None
Félix Hartmann's avatar
Félix Hartmann committed
203
204
205
206
    add_mark = False
    marks = []
    mark_plt = []
    mark_text = []
207
208
209
210
211
212
213
214
215
216
    dtphoto = []
    local_photo_path = False  # If true the photo path is removed
    thread_process = None  # To store the thread that run image processing
    infos_traitement = None
    old_step = 0
    add_dist_draw = False
    dist_measure_pts = []
    pixel_distance = None
    cm_distance = None
    tk_list_images = None
217
218
219
    tk_tige_offset = None
    tk_tige_percent_diam = None
    tk_detection_step = None
220
    hdf5file = None
221
    tiges_data = None
222
    tiges_names = []
Félix Hartmann's avatar
Félix Hartmann committed
223
224

    # On ferme la liste des images si elle est ouverte
225
226
227
    if tk_toplevel_listimages:
        tk_toplevel_listimages.destroy()
        tk_toplevel_listimages = None
Félix Hartmann's avatar
Félix Hartmann committed
228

hchauvet's avatar
hchauvet committed
229
230
###############################################################################

Félix Hartmann's avatar
Félix Hartmann committed
231
232
233
234
235
########################## CONVERT OLD PKL TO HDF5 ############################

def convert_pkl_to_hdf(pklfile, hdf5file, display_message=False, display_progress=False):
    """Converts the olf format .pkl into hdf5."""
    #TODO localize strings
236
    global tiges_data
Félix Hartmann's avatar
Félix Hartmann committed
237
238
239

    base_dir_path = os.path.dirname(pklfile) + '/'

240
241
242
    # On charge le fichier pkl
    data_out = load_results(pklfile)

Félix Hartmann's avatar
Félix Hartmann committed
243
244
245
246
247
248
    # On convertit les images (avec deux images réduites)

    if display_message:
        interekt.display_message(
                """Ancien format de données: CONVERSION (rootstem_data.pkl -> """
                """interekt_data.h5)\nConversion des images...""")
249
250
251
252
253
254
255
256
257

    Nimgs = len(data_out['tiges_info'])
    for tps_step in data_out['tiges_info']:
        # Test si les images sont disponibles à partir du chemin
        # d'origine ou dans le même dossier que le fichier
        # RootStemData.pkl
        if os.path.exists(tps_step['imgname']):
            img_path = tps_step['imgname']
        else:
Félix Hartmann's avatar
Félix Hartmann committed
258
            img_path = base_dir_path + os.path.basename(tps_step['imgname'])
259
260

        # On affiche l'état d'avancement
Félix Hartmann's avatar
Félix Hartmann committed
261
262
263
264
265
266
267
268
269
270
271
272
273
        if display_message:
            interekt.display_message(
                    """Ancien format de données: CONVERSION (rootstem_data.pkl -> """
                    """interekt_data.h5)\nConversion des images..."""
                    """(%i/%i)"""%(tps_step['iimg'], Nimgs))

        if display_progress:
            # On augmente la barre de progression du GUI
            dstep = 1/float(Nimgs) * 100.
            #print(dstep)
            interekt.prog_bar.step(dstep)
            interekt.prog_bar.update_idletasks()
            interekt.master.update()
274

275
276
        # On sauvagarde la photo dans le fichier hdf5, on fait garde
        # que le niveau 0 et 2
277

278
279
        # On sauvegarde les valeurs des résolutions de la pyramide
        # juste pour le dernier pas de temps
280
281
282
        store_resolutions = False
        if tps_step['iimg'] == Nimgs-1:
            store_resolutions = True
Félix Hartmann's avatar
Félix Hartmann committed
283

284
285
        h5store.image_to_hdf(hdf5file, img_path,
                             tps_step['iimg'],
286
                             max_pyramid_layers=2,
287
288
                             save_resolutions=store_resolutions,
                             selected_resolutions=[0,2])
289

Félix Hartmann's avatar
Félix Hartmann committed
290
291
292
293
294
    if display_progress:
        # Remise a zero de la progress bar
        interekt.prog_bar.step(0.0)
        interekt.prog_bar.update_idletasks()
        interekt.master.update()
295
296
297
298
299
300
301
302
303
304
305
306
307
308

    # Chargement des points de base
    tiges_data = data_out['tiges_data']
    if 'pts_base' in data_out:
        base_tiges = data_out['pts_base']
    else:
        base_tiges = [[(tiges_data.xc[ti,0,0], tiges_data.yc[ti,0,0])]*2 for ti in range(len(tiges_data.yc[:,0,0]))]

    #chargement des numeros des tiges
    if os.path.isfile(base_dir_path+'tige_id_map.pkl'):
        with open(base_dir_path+'tige_id_map.pkl', 'rb') as f:
            datapkl = pkl.load(f)
            tige_id_mapper = datapkl['tige_id_mapper']

309
310
311
312
            # Cherche si il y a d'autre données du post-processing a
            # charger Leur nom de variable est le même que la clef du
            # dico, on utilise la fonction eval pour créer la variable
            # Expl: scale_cmpix = datapkl['scale_cmpix']
Félix Hartmann's avatar
Félix Hartmann committed
313
            for dname in ('scale_cmpix', 'growth_data', 'B_data', 'beta_data',
314
                          'gamma_data', 'End_point_data', 'Tiges_seuil_offset'):
Félix Hartmann's avatar
Félix Hartmann committed
315

316
317
318
319
320
321
                if dname in datapkl:
                    exec("%s = datapkl['%s']" % (dname, dname))
                else:
                    #Creation d'un dico vide
                    exec("%s = {}" % (dname))
    else:
Félix Hartmann's avatar
Félix Hartmann committed
322
        tige_id_mapper = {}
323

324
325
    # Création des dossiers des tiges et du tige_id_mapper si il n'a
    # pas été defini dans le fichier tige_id_map.pkl
326
    for it in range(len(base_tiges)):
327
        h5store.create_tige_in_hdf(hdf5file, it)
328
        if it not in tige_id_mapper:
329
330
            tige_id_mapper[it] = it + 1

331
332
333
    # On lance le postrocessing des données des squelette des tiges
    # pour les enregistrer ensuite dans le fichier hdf5
    Traite_data(save_to_hdf5=True)
334

335
    # Pour l'échelle de l'image
336
    scale_cmpix = None
Félix Hartmann's avatar
Félix Hartmann committed
337

338
339
340
341
342
343
344
345
    # Chargement des données du traitement dans le fichier hdf5
    for id_tige in range(len(base_tiges)):
        # Est ce qu'il y a un nom pour cette tige
        if id_tige in tige_id_mapper:
            tige_nom = tige_id_mapper[id_tige]
        else:
            tige_nom = ""

Félix Hartmann's avatar
Félix Hartmann committed
346
347
348
349
350
351
        if display_message:
            interekt.display_message(
                    """Ancien format de données: CONVERSION (rootstem_data.pkl -> """
                    """interekt_data.h5)\nConversion des squelettes..."""
                    """(tige %i/%i)"""%(id_tige+1, len(base_tiges)))

352
353
354
355
356
357
        h5store.tige_to_hdf5(hdf5file, id_tige, tige_nom, base_tiges[id_tige],
                             tiges_data.xc[id_tige], tiges_data.yc[id_tige],
                             tiges_data.theta[id_tige], tiges_data.diam[id_tige],
                             tiges_data.xb1[id_tige], tiges_data.yb1[id_tige],
                             tiges_data.xb2[id_tige], tiges_data.yb2[id_tige])

358
        # Enregistrement des données comme dans fonction l'ancienne
359
360
361
        # fonction save_tige_idmapper() On sauve aussi cet ancien
        # tige_id_mapper dans le champ 'name' de la tige qui est plus
        # logique et qui serra dorénavant utilisé
362
        postprocess_data = {'OLD_tige_id_mapper': tige_id_mapper[id_tige]}
363

364
365
        h5store.save_tige_name(hdf5file, id_tige, str(tige_id_mapper[id_tige]))

366
367
        # On boucle sur les autres données du post-processing leur nom
        # est le même que le nom de la variable
Félix Hartmann's avatar
Félix Hartmann committed
368
369
        for dname in ('growth_data', 'B_data', 'beta_data', 'gamma_data',
                      'End_point_data', 'Tiges_seuil_offset'):
370
371
372
373
374
375
            try:
                postprocess_data[dname] = eval('%s[%i]' % (dname, id_tige))
            except Exception as e:
                print('No postprocessing data %s for tige %i' % (dname, id_tige))
                print(e)

376
377
            # On enregistre la valeur de l'échelle pour la sauvegarder
            # dans la H5 une seule fois à la fin
378
379
            if 'scale_cmpix' in postprocess_data:
                scale_cmpix = postprocess_data['scale_cmpix']
380

381
        # Cas un peu particulier de B_data qui contient des clefs
382
        # avec des '/' ce qui fait des sous-dossiers dans le
383
        # fichier h5, il faut donc les changer
384
        if 'B_data' in postprocess_data:
385
386
387
388
389
            if 'Lc (fit Log(A/A0))' in postprocess_data['B_data']:
                try:
                    postprocess_data['B_data']['Lc (fit Log(A over A0))'] = postprocess_data['B_data'].pop('Lc (fit Log(A/A0))')
                except:
                    print('Pas capable de convertir la clef "Lc (fit Log(A/A0))"')
390

391
392
393
394
395
            if 'Lc (fit exp(A/A0))' in postprocess_data['B_data']:
                try:
                    postprocess_data['B_data']['Lc (fit exp(A over A0))'] = postprocess_data['B_data'].pop('Lc (fit exp(A/A0))')
                except:
                    print('Pas capable de convertir la clef "Lc (fit exp(A/A0))"')
Félix Hartmann's avatar
Félix Hartmann committed
396

397
        h5store.save_tige_dict_to_hdf(hdf5file, id_tige, postprocess_data)
398

399
    # Sauvegarde de l'échelle
400
    h5store.save_pixelscale(hdf5file, scale_cmpix)
Félix Hartmann's avatar
Félix Hartmann committed
401

Félix Hartmann's avatar
Félix Hartmann committed
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
###############################################################################

def set_tiges_colormap():
    global tiges_colors
    #Fonction pour construire le vecteur des couleurs pour les tiges
    if len(base_tiges) > 20:
        s = len(base_tiges)+1
    else:
        s = 20

    try:
        tiges_colors = mpl.cm.tab20(linspace(0, 1, s))
    except Exception as e:
        print(e, "Update Matplotlib!")
        tiges_colors = mpl.cm.hsv(linspace(0, 1, s))

def get_hdf5_tigeid(h5file, gui_tige_id):
    """Returns the id under which the tige is saved in the hdf5 file."""

    tiges_ids = h5store.get_tiges_indices(h5file)
    tigeid = tiges_ids[gui_tige_id]

    return tigeid
425

426
def load_hdf5_tiges(hdf5file, display_message=True):
427
    """
428
    Fonction pour recharger toutes les tiges depuis le fichier hdf5
Félix Hartmann's avatar
Félix Hartmann committed
429
    vers les variables globales d'Interekt.
430
431
432
433

    load_data: permet de charger en mémoire les données tiges_data et
               celle du post_processing pour afficher les profils des
               tiges voir la fonction Load_postprocessed_data()
434
    """
435
436
    global tiges_data, base_tiges, btige_plt, btige_text, tiges_names
    global tiges_plot_object
Félix Hartmann's avatar
Félix Hartmann committed
437

438
439
440
441
442
443
444
    # On trouve combien on a de tiges traitées
    Ntiges = h5store.get_number_of_tiges(hdf5file)

    # On crée les listes pour stoker les textes et les plots
    # pour chaque tiges
    btige_plt = [None]*Ntiges
    btige_text = [None]*Ntiges
445
    tiges_plot_object = [None]*Ntiges
Félix Hartmann's avatar
Félix Hartmann committed
446

447
    # Chargement du nom des tiges
448
    if display_message:
Félix Hartmann's avatar
Félix Hartmann committed
449
        interekt.display_message(_("""Loading data"""))
450
    tiges_names = h5store.get_tiges_names(hdf5file)
451
    base_tiges = h5store.get_tiges_bases(hdf5file)
452
453
    #Recharge la colormap pour les tiges ouvertes
    set_tiges_colormap()
Félix Hartmann's avatar
Félix Hartmann committed
454

455
    #Traitement des données
Félix Hartmann's avatar
Félix Hartmann committed
456
    print("Loading data from the h5 file")
457
    tiges_data = h5store.get_tigesmanager(hdf5file)
458
459
460
461
462
463
464
465

    # For each tige, let's check whether useful data have been stored by 'Traite_data'
    for tige_id in range(Ntiges):
        # Let's get the id of the tige in the hdf5 file
        hdf_tige_id = get_hdf5_tigeid(hdf5file, tige_id)
        angle = h5store.get_postprocessing(hdf5file, 'angle', hdf_tige_id)
        if angle is None:
            Traite_data(save_to_hdf5=True)
Félix Hartmann's avatar
Félix Hartmann committed
466

467
def load_hdf5_file(hdf5file):
Félix Hartmann's avatar
Félix Hartmann committed
468
    """Loads a hdf5 file into Interekt."""
469
    global dtphoto
Félix Hartmann's avatar
Félix Hartmann committed
470

471
472
    # On charge les données des tiges
    load_hdf5_tiges(hdf5file)
Félix Hartmann's avatar
Félix Hartmann committed
473

Félix Hartmann's avatar
Félix Hartmann committed
474
475
476
477
478
479
480
481
482
483
484
485
486
    interekt.get_photo_datetime.set(True)

    # Doit on charger le temps des photos
    #if interekt.get_photo_datetime.get():
    dtphoto = h5store.get_images_datetimes(hdf5file)

    # On regarde si tous les temps sont des datetime sinon on
    # prends le numéro de la photo
    for t in dtphoto:
        if t is None:
            print("Error: No timestamp for all photos; photo numbers are used instead.")
            dtphoto = []
            break
487
488
489
490

    # Si pas de temps dans les photos on mets l'option dans
    # l'interface graphique à False
    if dtphoto == []:
Félix Hartmann's avatar
Félix Hartmann committed
491
        interekt.get_photo_datetime.set(False)
492

493
494
495
496
497
    # 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
    interekt.exclude_steady_state_from_time_series.set(exclude_steady_state)

498

Félix Hartmann's avatar
Félix Hartmann committed
499
######################### HANDLING OF THE IMAGE LIST ##########################
hchauvet's avatar
hchauvet committed
500
501
502

def onChangeImage(event):
    try:
Félix Hartmann's avatar
Félix Hartmann committed
503
        sender = event.widget
hchauvet's avatar
hchauvet committed
504
505
        idx = sender.curselection()
        #print("idx %i"%idx)
Félix Hartmann's avatar
Félix Hartmann committed
506
        interekt.plot_image(idx[0], keep_zoom=True)
hchauvet's avatar
hchauvet committed
507
    except Exception as e:
Félix Hartmann's avatar
Félix Hartmann committed
508
        print("Erreur de chargement !!!")
hchauvet's avatar
hchauvet committed
509
510
511
        print(e)

def show_image_list():
512
513
514
515
    global tk_list_images, tk_toplevel_listimages

    if tk_toplevel_listimages is None:
        tk_toplevel_listimages = Tk.Toplevel(master=root)
Félix Hartmann's avatar
Félix Hartmann committed
516
        tk_toplevel_listimages.title(_("List of open images"))
hchauvet's avatar
hchauvet committed
517

518
519
520
521
522
        topsbar = Tk.Scrollbar(tk_toplevel_listimages, orient=Tk.VERTICAL)
        listb = Tk.Listbox(master=tk_toplevel_listimages,
                           yscrollcommand=topsbar.set)
        topsbar.config(command=listb.yview)
        topsbar.pack(side=Tk.RIGHT, fill=Tk.Y)
hchauvet's avatar
hchauvet committed
523

524
525
        for imgname in h5store.get_images_names(hdf5file):
            listb.insert(Tk.END, imgname)
hchauvet's avatar
hchauvet committed
526

527
528
529
530
531
532
533
        # Selection de l'image que l'on regarde
        if cur_image:
            listb.selection_set(cur_image)
            listb.see(cur_image)
        else:
            listb.selection_set(0)
            listb.see(0)
hchauvet's avatar
hchauvet committed
534

535
536
537
        listb.bind("<<ListboxSelect>>", onChangeImage)
        listb.pack(side=Tk.LEFT, fill=Tk.BOTH, expand=1)
        tk_list_images = listb
hchauvet's avatar
hchauvet committed
538

539
540
541
        # Signal pour déclencher la fonction qui ferme proprement la
        # liste d'image en gérant les globals
        tk_toplevel_listimages.protocol("WM_DELETE_WINDOW", destroy_list_images)
Félix Hartmann's avatar
Félix Hartmann committed
542

543
544
545
    else:
        # Si la fenêtre existe déjà mais est cachée on la ramène devant
        tk_toplevel_listimages.lift()
Félix Hartmann's avatar
Félix Hartmann committed
546

547
def destroy_list_images():
Félix Hartmann's avatar
Félix Hartmann committed
548
    """Safely closed the image list window."""
549
550
    global tk_list_images, tk_toplevel_listimages

Félix Hartmann's avatar
Félix Hartmann committed
551
    # On détruit la fenetre
552
553
554
555
556
    tk_toplevel_listimages.destroy()

    # On remet les variables global à None (Fortran Style)
    tk_list_images = None
    tk_toplevel_listimages = None
Félix Hartmann's avatar
Félix Hartmann committed
557

hchauvet's avatar
hchauvet committed
558
559
560
###############################################################################


561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
########################## HANDLING OF TIMES ##################################

def get_time_data():
    """Returns useful variables for plotting time series.

    Returns:
    --------
    - times: 1D array of photo times
    - time_units: dictionary with time-related units
    - time_label: label for the time axis in plots (str)
    - graduation: on the time axis of a plot, a tick will be placed
      at each multiple of 'graduation'
    - excluded_image: index of the image to be excluded from time
      series (otberwise, 'None')
    - mask: a mask array for excluding the above-mentioned image
    """

    nb_images = h5store.get_number_of_images(hdf5file)

    # We define a mask which will be useful if the steady-state image
    # has to be excluded from time series.
    mask = ones(nb_images, dtype=bool)
    if (interekt.steady_state_image is not None
            and interekt.exclude_steady_state_from_time_series.get()):
        excluded_image = interekt.steady_state_image
        mask[excluded_image] = False
    else:
        excluded_image = None

    if interekt.get_photo_datetime.get() and dtphoto:
        # photos have timestamps

        # time in minutes
        times = array([(t - dtphoto[0]).total_seconds() for t in dtphoto]) / 60.

        # total duration of the experiment in minutes
        total_minutes = times[mask].max()

        # choose time unit and graduation for the graphs,
        # based on the total duration
        if total_minutes < 12 * 60:  # less than 12 hours
            time_unit = strings["min"]
            graduation = 60   # a graduation every hour
        elif total_minutes < 24 * 60:  # between 12 and 24 hours
            times /= 60  # time in hours
            time_unit = strings["hours"]
            graduation = 1   # a graduation every hour
        elif total_minutes <  7 * 24 * 60:  # between one day and one week
            times /= 60  # time in hours
            time_unit = strings["hours"]
            graduation = 24   # a graduation every day
        elif total_minutes < 30 * 24 * 60:  # between one week and one month
            times /= 24 * 60  # time in days
            time_unit = strings["days"]
            graduation = 1   # a graduation every day
        elif total_minutes < 3 * 30 * 24 * 60:  # between one month and three month
            times /= 24 * 60  # time in days
            time_unit = strings["days"]
            graduation = 7   # a graduation every week
        elif total_minutes >= 3 * 30 * 24 * 60:  # more than three month
            times /= 24 * 60  # time in days
            time_unit = strings["days"]
            graduation = 30   # a graduation every 30 days

        time_label = strings["time"] + " (%s)"%time_unit
        time_units = {"time unit": time_unit,
                      "RER unit": "h-1",
                      "RER unit TeX": r"h$^{-1}$",
                      "dAdt unit": "rad.h-1",
                      "dAdt unit TeX": r"rad.h$^{-1}$"}

    else:
        times = arange(1, nb_images+1)  # time = image number

        # one tick every 60 minutes if photos taken every 6 minutes
        # (this is a legacy from the Murinas project)
        graduation = 10

        time_label = strings["image number"]
        RER_unit = strings["image"] + "-1"
        RER_unit_TeX = strings["image"] + r"$^{-1}$"
        time_units = {"time unit": strings["image"],
                      "RER unit": RER_unit,
                      "RER unit TeX": RER_unit_TeX,
                      "dAdt unit": "rad." + RER_unit,
                      "dAdt unit TeX": r"rad." + RER_unit_TeX}

    return times, time_units, time_label, graduation, excluded_image, mask


##########W####################################################################


hchauvet's avatar
hchauvet committed
654
655
########################## Pour le Traitement #################################
def _export_to_csv():
656
657
658
659
660
    """
    Fonction pour exporter la serie temporelle pour les tiges soit
    l'évolution de l'angle moyen au bout et de la taille au cours du
    temps
    """
hchauvet's avatar
hchauvet committed
661

662
    if len(base_tiges) > 0:
Félix Hartmann's avatar
Félix Hartmann committed
663
664
665
666
667
668
669
670
        proposed_filename = "time_series_tipangle_length.csv"
        outfileName = filedialog.asksaveasfilename(
                parent=root,
                filetypes=[("Comma Separated Value, csv","*.csv")],
                title=_("Export time series"),
                #title=_("Export séries temporelles"),
                initialfile=proposed_filename,
                initialdir=base_dir_path)
hchauvet's avatar
hchauvet committed
671
672
673

    if len(outfileName) > 0:

674
675
676
677
678
679
680
681
        # Creation du tableau Pandas pour stocquer les données
        data_out = pd.DataFrame(columns=['tige', 'angle', 'temps',
                                         'taille', 'rayon', 'angle_0_360'])

        # Récupérations des id des tiges dans le fichier h5
        hdf_tiges_id = h5store.get_tiges_indices(hdf5file)
        tiges_names = h5store.get_tiges_names(hdf5file)
        pictures_names = h5store.get_images_names(hdf5file)
Félix Hartmann's avatar
Félix Hartmann committed
682

683
        # Récupère le temps
684
        if interekt.get_photo_datetime.get() and dtphoto:
685
686
687
            tps = dtphoto
        else:
            tps = arange(len(pictures_names))
Félix Hartmann's avatar
Félix Hartmann committed
688

689
690
        # Boucle sur les tiges
        for i in range(len(base_tiges)):
hchauvet's avatar
hchauvet committed
691

692
            hdfid = hdf_tiges_id[i]
693
694
            tige_x, tige_y, tige_s, tige_taille, tige_angle, tige_tip_angle, tige_zone,\
                    _ = load_postprocessed_data(hdf5file, hdfid)
695
            tige_R = tiges_data.diam[i]/2.0
Félix Hartmann's avatar
Félix Hartmann committed
696
            tige_name = tiges_names[i]
Félix Hartmann's avatar
Félix Hartmann committed
697

Félix Hartmann's avatar
Félix Hartmann committed
698
            data_tmp = pd.DataFrame({'tige': tige_name, 'angle': tige_tip_angle,
699
700
                                     'temps': tps, 'taille': tige_taille,
                                     'rayon': tige_R.mean(1),
701
                                     'angle_0_360': convert_angle(tige_tip_angle)})
hchauvet's avatar
hchauvet committed
702

703
            data_out = data_out.append(data_tmp, ignore_index=True)
hchauvet's avatar
hchauvet committed
704
705

        #Add some usefull data
706
        #Ntige = data_out.tige.unique()
hchauvet's avatar
hchauvet committed
707
708
        output = []
        #print Ntige
709
        for tige, datatige in data_out.groupby('tige'):
710
            # print(dataout.tige)
Félix Hartmann's avatar
Félix Hartmann committed
711

hchauvet's avatar
hchauvet committed
712
            #Compute dt (min)
Félix Hartmann's avatar
Félix Hartmann committed
713
            if interekt.get_photo_datetime.get():
hchauvet's avatar
hchauvet committed
714
715
716
                dtps = (datatige['temps']-datatige['temps'].min())/timedelta64(1,'m')
                datatige.loc[:,'dt (min)'] = dtps

717
            datatige.loc[:,'pictures name'] = pictures_names
hchauvet's avatar
hchauvet committed
718

719
720
            # Trouve la position de la tige dans les données du GUI
            itige = tiges_names.index(tige)
Félix Hartmann's avatar
Félix Hartmann committed
721

722
            datatige.loc[:,'x base (pix)'] = [tiges_data.xc[itige,:,0].mean()]*len(datatige.index)
hchauvet's avatar
hchauvet committed
723
724
725
            output += [datatige]

        dataout = pd.concat(output)
726
        print(dataout.head())
hchauvet's avatar
hchauvet committed
727
728
729
730
        #print datatige.tail()
        dataout.to_csv(outfileName, index=False)

def _export_xytemps_to_csv():
731
732
733
734
735
    """
    Export du squelette des tiges/racines au cours du temps sous
    format csv, pour un pas de temps on aura le xy complet (soit pour
    chaque abscisse curviligne).
    """
hchauvet's avatar
hchauvet committed
736

737
    if len(base_tiges) > 0:
Félix Hartmann's avatar
Félix Hartmann committed
738
739
740
741
742
743
744
        proposed_filename = "skeleton.csv"
        outfileName = filedialog.asksaveasfilename(
                parent=root,
                filetypes=[("Comma Separated Value, csv","*.csv")],
                title=_("Export skeleton"),
                initialfile=proposed_filename,
                initialdir=base_dir_path)
hchauvet's avatar
hchauvet committed
745
746

    if len(outfileName) > 0:
747
748
749
750
751
752
753
754
755
        # Creation du tableau Pandas pour stocquer les données
        data_out = pd.DataFrame(columns=['tige', 'angle', 'temps',
                                         'taille', 'rayon', 'x', 'y', 'nom photo',
                                         'angle_0_360'])

        # Récupérations des id des tiges dans le fichier h5
        hdf_tiges_id = h5store.get_tiges_indices(hdf5file)
        tiges_names = h5store.get_tiges_names(hdf5file)
        pictures_names = h5store.get_images_names(hdf5file)
756

757
        # Récupère le temps
758
        if interekt.get_photo_datetime.get() and dtphoto:
759
            tps = dtphoto
hchauvet's avatar
hchauvet committed
760
        else:
761
            tps = arange(len(pictures_names))
hchauvet's avatar
hchauvet committed
762

763
764
        # Boucle sur les tiges
        for i in range(len(base_tiges)):
hchauvet's avatar
hchauvet committed
765

766
            hdfid = hdf_tiges_id[i]
767
768
            tige_x, tige_y, tige_s, tige_taille, tige_angle, tige_tip_angle, tige_zone,\
                    _ = load_postprocessed_data(hdf5file, hdfid)
769
            tige_R = tiges_data.diam[i]/2.0
Félix Hartmann's avatar
Félix Hartmann committed
770
            tige_name = tiges_names[i]
771

Félix Hartmann's avatar
Félix Hartmann committed
772
            data_tmp = pd.DataFrame({'tige': tige_name, 'angle': tige_tip_angle,
773
774
775
776
777
                                     'temps': tps, 'taille': tige_taille,
                                     'rayon': tige_R.mean(1),
                                     'x': tige_x.tolist(),
                                     'y': tige_y.tolist(),
                                     'nom photo': pictures_names,
778
                                     'angle_0_360': convert_angle(tige_tip_angle)})
779
780
781
782

            data_out = data_out.append(data_tmp, ignore_index=True)

        print(data_out.head())
Félix Hartmann's avatar
Félix Hartmann committed
783
        print("Enregistré dans %s" % outfileName)
784
        data_out.to_csv(outfileName, index=False)
hchauvet's avatar
hchauvet committed
785
786

def _export_mean_to_csv():
787
788
789
790
    """
    Fonction qui exporte la courbe moyennée pour toutes les tiges de
    l'angle et taille en fonction du temps
    """
hchauvet's avatar
hchauvet committed
791

792
    if len(base_tiges) > 0:
hchauvet's avatar
hchauvet committed
793
        proposed_filename = "Serie_tempotelle_moyenne.csv"
Félix Hartmann's avatar
Félix Hartmann committed
794
795
796
797
798
799
        outfileName = filedialog.asksaveasfilename(
                parent=root,
                filetypes=[("Comma Separated Value, csv","*.csv")],
                title="Export serie temporelle",
                initialfile=proposed_filename,
                initialdir=base_dir_path)
hchauvet's avatar
hchauvet committed
800
801

    if len(outfileName) > 0:
802

Félix Hartmann's avatar
Félix Hartmann committed
803
        # Creation du tableau Pandas pour stocquer les données
804
805
806
807
808
809
810
        data_out = pd.DataFrame(columns=['tige', 'angle', 'temps',
                                         'taille', 'rayon', 'angle_0_360'])

        # Récupérations des id des tiges dans le fichier h5
        hdf_tiges_id = h5store.get_tiges_indices(hdf5file)
        tiges_names = h5store.get_tiges_names(hdf5file)
        pictures_names = h5store.get_images_names(hdf5file)
Félix Hartmann's avatar
Félix Hartmann committed
811

812
        # Récupère le temps
813
        if interekt.get_photo_datetime.get() and dtphoto:
814
            tps = dtphoto
hchauvet's avatar
hchauvet committed
815
        else:
816
            tps = arange(len(pictures_names))
Félix Hartmann's avatar
Félix Hartmann committed
817

818
819
        # Boucle sur les tiges
        for i in range(len(base_tiges)):
hchauvet's avatar
hchauvet committed
820

821
            hdfid = hdf_tiges_id[i]
822
823
            tige_x, tige_y, tige_s, tige_taille, tige_angle, tige_tip_angle, tige_zone,\
                    _ = load_postprocessed_data(hdf5file, hdfid)
824
            tige_R = tiges_data.diam[i]/2.0
Félix Hartmann's avatar
Félix Hartmann committed
825
            tige_name = tiges_names[i]
Félix Hartmann's avatar
Félix Hartmann committed
826

Félix Hartmann's avatar
Félix Hartmann committed
827
            data_tmp = pd.DataFrame({'tige': tige_name, 'angle': tige_tip_angle,
828
829
                                     'temps': tps, 'taille': tige_taille,
                                     'rayon': tige_R.mean(1),
830
                                     'angle_0_360': convert_angle(tige_tip_angle)})
hchauvet's avatar
hchauvet committed
831

832
            data_out = data_out.append(data_tmp, ignore_index=True)
Félix Hartmann's avatar
Félix Hartmann committed
833

hchauvet's avatar
hchauvet committed
834
835

        #Creation de la moyenne
836
837
838
839
        datamoy = data_out.groupby('temps').mean()
        datamoy['temps'] = data_out.temps.unique()
        datamoy['tige'] = ['%s->%s'%(str(data_out['tige'].min()),
                                     str(data_out['tige'].max()))]*len(datamoy['temps'])
Félix Hartmann's avatar
Félix Hartmann committed
840

hchauvet's avatar
hchauvet committed
841
        #Convert to timedelta in minute
Félix Hartmann's avatar
Félix Hartmann committed
842
        if interekt.get_photo_datetime.get():
843
            dtps = (datamoy['temps']-datamoy['temps'][0])/timedelta64(1,'m')
hchauvet's avatar
hchauvet committed
844
845
            datamoy['dt (min)'] = dtps

846
        datamoy['pictures name'] = pictures_names
Félix Hartmann's avatar
Félix Hartmann committed
847
        print("Saved to %s"%outfileName)
hchauvet's avatar
hchauvet committed
848
849
850
        datamoy.to_csv(outfileName, index=False)

def _export_meandata_for_each_tiges():
851
852
853
854
855
    """
    Dans un dossier donnée par l'utilisateur on exporte les données
    taille et angle au cours de temps avec un fichier .csv par
    tiges/racines
    """
hchauvet's avatar
hchauvet committed
856
857

    #Ask for a directory where to save all files
Félix Hartmann's avatar
Félix Hartmann committed
858
859
    outdir = filedialog.askdirectory(
            title="Choisir un répertoire pour sauvegarder les tiges")
hchauvet's avatar
hchauvet committed
860
    if len(outdir) > 0:
861
862
863
        # Creation du tableau Pandas pour stocquer les données
        data_out = pd.DataFrame(columns=['tige', 'angle', 'temps',
                                         'taille', 'rayon', 'angle_0_360'])
hchauvet's avatar
hchauvet committed
864

865
866
867
868
        # Récupérations des id des tiges dans le fichier h5
        hdf_tiges_id = h5store.get_tiges_indices(hdf5file)
        tiges_names = h5store.get_tiges_names(hdf5file)
        pictures_names = h5store.get_images_names(hdf5file)
Félix Hartmann's avatar
Félix Hartmann committed
869

870
        # Récupère le temps
871
        if interekt.get_photo_datetime.get() and dtphoto:
872
873
874
            tps = dtphoto
        else:
            tps = arange(len(pictures_names))
Félix Hartmann's avatar
Félix Hartmann committed
875

876
877
        # Boucle sur les tiges
        for i in range(len(base_tiges)):
hchauvet's avatar
hchauvet committed
878

879
            hdfid = hdf_tiges_id[i]
880
881
            tige_x, tige_y, tige_s, tige_taille, tige_angle, tige_tip_angle, tige_zone,\
                    _ = load_postprocessed_data(hdf5file, hdfid)
882
            tige_R = tiges_data.diam[i]/2.0
Félix Hartmann's avatar
Félix Hartmann committed
883
            tige_name = tiges_names[i]
Félix Hartmann's avatar
Félix Hartmann committed
884

Félix Hartmann's avatar
Félix Hartmann committed
885
            data_tmp = pd.DataFrame({'tige': tige_name, 'angle': tige_tip_angle,
886
887
                                     'temps': tps, 'taille': tige_taille,
                                     'rayon': tige_R.mean(1),
888
                                     'angle_0_360': convert_angle(tige_tip_angle)})
hchauvet's avatar
hchauvet committed
889

890
            data_out = data_out.append(data_tmp, ignore_index=True)
Félix Hartmann's avatar
Félix Hartmann committed
891

hchauvet's avatar
hchauvet committed
892
        #Loop over tiges
893
        # Ntige = dataframe.tige.unique()
894
        for tige, datatige in data_out.groupby('tige'):
hchauvet's avatar
hchauvet committed
895
            #Compute dt (min)
Félix Hartmann's avatar
Félix Hartmann committed
896
            if interekt.get_photo_datetime.get():
897
                dtps = (datatige['temps']-datatige['temps'][datatige.index[0]])/timedelta64(1,'m')
hchauvet's avatar
hchauvet committed
898
899
                datatige['dt (min)'] = dtps

900
901
902
903
            datatige['pictures name'] = pictures_names
            # Trouve la position de la tige dans les données du GUI
            itige = tiges_names.index(tige)
            datatige['x base (pix)'] = [tiges_data.xc[itige,:,0].mean()]*len(datatige.index)
hchauvet's avatar
hchauvet committed
904
905

            #print datatige.head()
906
            outfileName = outdir+'/data_mean_for_tige_%s.csv'%str(tige)
Félix Hartmann's avatar
Félix Hartmann committed
907
            print("Sauvegardé dans %s"%outfileName)
hchauvet's avatar
hchauvet committed
908
909
            datatige.to_csv(outfileName, index=False)

Félix Hartmann's avatar
Félix Hartmann committed
910
911
###############################################################################

hchauvet's avatar
hchauvet committed
912
913
def update_tk_progress(infos, root):
    global old_step
914
    if infos is not None:
hchauvet's avatar
hchauvet committed
915
916
917
918

        im_num = infos['inum']
        old_num = infos['old_inum']
        tot = infos['tot']
Félix Hartmann's avatar
Félix Hartmann committed
919
        start_msg = _("Image processing")
Félix Hartmann's avatar
Félix Hartmann committed
920
921
        msg = start_msg + " %i / %i"%(int(im_num),int(tot))
        root.wm_title("Interekt | %s"%msg)
hchauvet's avatar
hchauvet committed
922
923
        root.update_idletasks()

Félix Hartmann's avatar
Félix Hartmann committed
924
        #New version with Tk progressbar
925
        if im_num != old_step and tot > 1:
hchauvet's avatar
hchauvet committed
926
927
928
929
            old_step = im_num
            #print(old_step, nstep, nstep-old_step)
            dstep = (im_num-old_num)/float(tot-1) * 100.
            #print(dstep)
Félix Hartmann's avatar
Félix Hartmann committed
930
931
            interekt.prog_bar.step(dstep)
            interekt.prog_bar.update_idletasks()
hchauvet's avatar
hchauvet committed
932
933
934
935
936
937
            root.update()

def plot_progress(**kwargs):
    global infos_traitement
    infos_traitement = kwargs

938
939
940
def none_print(**kwargs):
    output = kwargs

hchauvet's avatar
hchauvet committed
941
942
943
def check_process():
    global root, infos_traitement

944
    if thread_process.is_alive():
hchauvet's avatar
hchauvet committed
945
946
947
948
949
        update_tk_progress(infos_traitement, root)
        root.after(20, check_process)

    else:
        update_tk_progress(infos_traitement, root)
Félix Hartmann's avatar
Félix Hartmann committed
950
        root.wm_title("Interekt")
hchauvet's avatar
hchauvet committed
951
952
        thread_process.join()
        infos_traitement = None
953
954
955
956
957
        try:
            process_data()
        except Exception as e:
            print('Failed to process data')
            print(e)
hchauvet's avatar
hchauvet committed
958

Félix Hartmann's avatar
Félix Hartmann committed
959
def process_data(display_message=True):
960
    global data_out, tiges_data
hchauvet's avatar
hchauvet committed
961

962
    # Get queue result
hchauvet's avatar
hchauvet committed
963
964
    data_out = data_out.get()

965
    # When it's done get the tiges_data from the data from data_out
966
    tiges_data = data_out['data']['tiges_data']
Félix Hartmann's avatar
Félix Hartmann committed
967

968
    # On affiche que l'on fait la sauvegarde
Félix Hartmann's avatar
Félix Hartmann committed
969
970
    if display_message:
        interekt.display_message(_("Saving data into the .h5 file"))
971
972
973
974
975
976
977
978
979
    for idt in range(len(base_tiges)):
        # Recup l'id dans le fichier hdf
        idhdf = get_hdf5_tigeid(hdf5file, idt)
        tige_name = h5store.get_tiges_names(hdf5file, idhdf)
        h5store.tige_to_hdf5(hdf5file, idhdf, tige_name, base_tiges[idt],
                             tiges_data.xc[idt], tiges_data.yc[idt],
                             tiges_data.theta[idt], tiges_data.diam[idt],
                             tiges_data.xb1[idt], tiges_data.yb1[idt],
                             tiges_data.xb2[idt], tiges_data.yb2[idt])
Félix Hartmann's avatar
Félix Hartmann committed
980

981
    # On lance le traitement et on le sauvegarde dans le fichier hdf5
Félix Hartmann's avatar
Félix Hartmann committed
982
    if display_message:
Félix Hartmann's avatar
Félix Hartmann committed
983
        interekt.display_message(_("Processing extracted data"))
Félix Hartmann's avatar