source: trunk/src/series.m @ 983

Last change on this file since 983 was 983, checked in by g7moreau, 4 years ago
  • Add Matlab load module with the good version
File size: 161.8 KB
Line 
1%'series': master function associated to the GUI series.m for analysis field series 
2%------------------------------------------------------------------------
3% function varargout = series(varargin)
4% associated with the GUI series.fig
5%
6%INPUT
7% param: structure with input parameters (link with the GUI uvmat)
8%      .menu_coord_str: string for the TransformName (menu for coordinate transforms)
9%      .menu_coord_val: value for TransformName (menu for coordinate transforms)
10%      .FileName: input file name
11%      .FileName_1: second input file name
12%      .list_field: menu of input fields
13%      .index_fields: chosen index
14%      .civ1=0 or 1, .interp1,  ... : input civ field type
15%
16
17%=======================================================================
18% Copyright 2008-2017, LEGI UMR 5519 / CNRS UGA G-INP, Grenoble, France
19%   http://www.legi.grenoble-inp.fr
20%   Joel.Sommeria - Joel.Sommeria (A) legi.cnrs.fr
21%
22%     This file is part of the toolbox UVMAT.
23%
24%     UVMAT is free software; you can redistribute it and/or modify
25%     it under the terms of the GNU General Public License as published
26%     by the Free Software Foundation; either version 2 of the license,
27%     or (at your option) any later version.
28%
29%     UVMAT is distributed in the hope that it will be useful,
30%     but WITHOUT ANY WARRANTY; without even the implied warranty of
31%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32%     GNU General Public License (see LICENSE.txt) for more details.
33%=======================================================================
34
35%------------------------------------------------------------------------
36%------------------------------------------------------------------------
37%  I - MAIN FUNCTION series
38%------------------------------------------------------------------------
39%------------------------------------------------------------------------
40function varargout = series(varargin)
41
42% Begin initialization code - DO NOT EDIT
43gui_Singleton = 1;
44gui_State = struct('gui_Name',       mfilename, ...
45                   'gui_Singleton',  gui_Singleton, ...
46                   'gui_OpeningFcn', @series_OpeningFcn, ...
47                   'gui_OutputFcn',  @series_OutputFcn, ...
48                   'gui_LayoutFcn',  [] , ...
49                   'gui_Callback',   []);
50if nargin && ischar(varargin{1})
51    gui_State.gui_Callback = str2func(varargin{1});
52end
53
54if nargout
55    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
56else
57    gui_mainfcn(gui_State, varargin{:});
58end
59% End initialization code - DO NOT EDIT
60
61%--------------------------------------------------------------------------
62% --- Executes just before series is made visible.
63%--------------------------------------------------------------------------
64function series_OpeningFcn(hObject, eventdata, handles,Param)
65
66% Choose default command line output for series
67handles.output = hObject;
68% Update handles structure
69guidata(hObject, handles);
70
71%% initial settings
72% position and  size of the GUI at opening
73set(0,'Unit','points')
74ScreenSize=get(0,'ScreenSize');%size of the current screen, in points (1/72 inch)
75Width=900;% prefered width of the GUI in points (1/72 inch)
76Height=624;% prefered height of the GUI in points (1/72 inch)
77%adjust to screen size (reduced by a min margin)
78RescaleFactor=min((ScreenSize(3)-80)/Width,(ScreenSize(4)-80)/Height);
79if RescaleFactor>1
80    RescaleFactor=min(RescaleFactor,1);
81end
82Width=Width*RescaleFactor;
83Height=Height*RescaleFactor;
84LeftX=80*RescaleFactor;%position of the left fig side, in pixels (put to the left side, with some margin)
85LowY=round(ScreenSize(4)/2-Height/2); % put at the middle height on the screen
86set(hObject,'Units','points')
87set(hObject,'Position',[LeftX LowY Width Height])% position and size of the GUI at opening
88
89% settings of table MinIndex_j
90set(handles.MinIndex_i,'ColumnFormat',{'numeric'})
91set(handles.MinIndex_i,'ColumnEditable',false)
92set(handles.MinIndex_i,'ColumnName',{'i min'})
93set(handles.MinIndex_i,'Data',[])% initiate Data to double (not cell)
94
95% settings of table MinIndex_j
96set(handles.MinIndex_j,'ColumnFormat',{'numeric'})
97set(handles.MinIndex_j,'ColumnEditable',false)
98set(handles.MinIndex_j,'ColumnName',{'j min'})
99set(handles.MinIndex_j,'Data',[])% initiate Data to double (not cell)
100
101% settings of table MaxIndex_i
102set(handles.MaxIndex_i,'ColumnFormat',{'numeric'})
103set(handles.MaxIndex_i,'ColumnEditable',false)
104set(handles.MaxIndex_i,'ColumnName',{'i max'})
105set(handles.MaxIndex_i,'Data',[])% initiate Data to double (not cell)
106
107% settings of table MaxIndex_j
108set(handles.MaxIndex_j,'ColumnFormat',{'numeric'})
109set(handles.MaxIndex_j,'ColumnEditable',false)
110set(handles.MaxIndex_j,'ColumnName',{'j max'})
111set(handles.MaxIndex_j,'Data',[])% initiate Data to double (not cell)
112
113% settings of table PairString
114set(handles.PairString,'ColumnName',{'pairs'})
115set(handles.PairString,'ColumnEditable',false)
116set(handles.PairString,'ColumnFormat',{'char'})
117set(handles.PairString,'Data',{''})
118
119% settings of table MaskTable
120set(handles.MaskTable,'ColumnName',{'mask name'})
121set(handles.PairString,'ColumnEditable',false)
122set(handles.PairString,'ColumnFormat',{'char'})
123set(handles.PairString,'Data',{''})
124
125series_ResizeFcn(hObject, eventdata, handles)%resize table according to series GUI size
126set(hObject,'WindowButtonDownFcn',{'mouse_down'})%allows mouse action with right button (zoom for uicontrol display)
127set(hObject,'DeleteFcn',{@closefcn})%
128
129% check default input data
130if ~exist('Param','var')
131    Param=[]; %default
132end
133
134%% list of builtin functions in the mebu ActionName
135ActionList={'check_data_files';'aver_stat';'time_series';'civ_series';'merge_proj'};% WARNING: fits with nb_builtin_ACTION=4 in ActionName_callback
136NbBuiltinAction=numel(ActionList);
137set(handles.Action,'UserData',NbBuiltinAction)
138[path_series,name,ext]=fileparts(which('series'));% path to the GUI series
139path_series_fct=fullfile(path_series,'series');%path of the functions in subdirectroy 'series'
140[code, message] = system...
141    ('LD_LIBRARY_PATH=$(echo $LD_LIBRARY_PATH | pyp "p.split('':'') |... [s for s in p if ''matlab'' not in s] | '':''.join(p)") python -c "import fluidimage"');
142if code==0
143    ActionExtList={'.m';'.sh';'.py (in dev.)'};% default choice of extensions (Matlab fct .m or compiled version .sh
144else
145    ActionExtList={'.m';'.sh'};  % python options not installed
146end
147ActionPathList=cell(NbBuiltinAction,1);%initiate the cell matrix of Action fct paths
148ActionPathList(:)={path_series_fct}; %set the default path to series fcts to all list members
149RunModeList={'local';'background'};% default choice of extensions (Matlab fct .m or compiled version .sh)
150[s,w]=system('oarstat');% look for cluster system 'oar'
151if isequal(s,0)
152    RunModeList=[RunModeList;{'cluster_oar'}];
153    set(handles.MonitorCluster,'Visible','on'); % make visible button for access to Monika
154    set(handles.num_CPUTime,'Visible','on'); % make visible button for access to Monika
155    set(handles.CPUTime_txt,'Visible','on'); % make visible button for access to Monika
156end
157[s,w]=system('qstat --version');% look for cluster system 'sge'
158if isequal(s,0)
159    if regexp(w,'^pbs')
160        RunModeList=[RunModeList;{'cluster_pbs'}];
161    else
162        RunModeList=[RunModeList;{'cluster_sge'}];
163    end
164end
165set(handles.RunMode,'String',RunModeList)
166
167%% list of builtin transform functions in the menu TransformName
168TransformList={'';'sub_field';'phys';'phys_polar'};% WARNING: must fit with the corresponding menu in uvmat and nb_builtin_transform=4 in  TransformName_callback
169NbBuiltinTransform=numel(TransformList);
170path_transform_fct=fullfile(path_series,'transform_field');
171TransformPathList=cell(NbBuiltinTransform,1);%initiate the cell matrix of Action fct paths
172TransformPathList(:)={path_transform_fct}; %set the default path to series fcts to all list members
173
174%% get the user defined functions stored in the personal file uvmat_perso.mat
175dir_perso=prefdir;
176profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
177if exist(profil_perso,'file')
178    h=load (profil_perso);
179    %get the list of previous input files in the upper bar menu Open
180    if isfield(h,'MenuFile')
181        for ifile=1:min(length(h.MenuFile),5)
182            set(handles.(['MenuFile_' num2str(ifile)]),'Label',h.MenuFile{ifile});
183            set(handles.(['MenuFile_' num2str(ifile+5)]),'Label',h.MenuFile{ifile});
184        end
185    end
186    %get the list of previous campaigns in the upper bar menu Open campaign
187    if isfield(h,'MenuCampaign')
188        for ifile=1:min(length(h.MenuCampaign),5)
189            set(handles.(['MenuCampaign_' num2str(ifile)]),'Label',h.MenuCampaign{ifile});
190        end
191    end
192    %get the menu of actions
193%     if isfield(h,'ActionExtListUser') && iscell(h.ActionExtListUser)
194%         ActionExtList=[ActionExtList; h.ActionExtListUser];
195%     end
196    if isfield(h,'ActionListUser') && iscell(h.ActionListUser) && isfield(h,'ActionPathListUser') && iscell(h.ActionPathListUser)
197        ActionList=[ActionList;h.ActionListUser];
198        ActionPathList=[ActionPathList;h.ActionPathListUser(:,1)];
199    end
200    %get the menu of transform fct
201    if isfield(h,'TransformListUser') && iscell(h.TransformListUser) && isfield(h,'TransformPathListUser') && iscell(h.TransformPathListUser)
202        TransformList=[TransformList;h.TransformListUser];
203        TransformPathList=[TransformPathList;h.TransformPathListUser];
204    end
205end
206
207%% selection of the input Action fct
208ActionCheckExist=true(size(ActionList));%initiate the check of the path to the listed action fct
209for ilist=NbBuiltinAction+1:numel(ActionList)%check  the validity of the path of the user defined Action fct
210    ActionCheckExist(ilist)=exist(fullfile(ActionPathList{ilist},[ActionList{ilist} '.m']),'file');
211end
212ActionPathList=ActionPathList(ActionCheckExist,:);% suppress the menu options which are not valid anymore
213ActionList=ActionList(ActionCheckExist);
214set(handles.ActionName,'String',[ActionList;{'more...'}])
215set(handles.ActionName,'UserData',ActionPathList)
216ActionIndex=[];
217if isfield(Param,'ActionName')% copy the selected menu index transferred in Param from uvmat
218    ActionIndex=find(strcmp(Param.ActionName,ActionList),1);
219end
220if isempty(ActionIndex)
221    ActionIndex=1;
222end
223set(handles.ActionName,'Value',ActionIndex)
224set(handles.ActionPath,'String',ActionPathList{ActionIndex})
225set(handles.ActionExt,'Value',1)
226set(handles.ActionExt,'String',ActionExtList)
227
228%% selection of the input transform fct
229TransformCheckExist=true(size(TransformList));
230for ilist=NbBuiltinTransform+1:numel(TransformList)
231    TransformCheckExist(ilist)=exist(fullfile(TransformPathList{ilist},[TransformList{ilist} '.m']),'file');
232end
233TransformPathList=TransformPathList(TransformCheckExist);
234TransformList=TransformList(TransformCheckExist);
235set(handles.TransformName,'String',[TransformList;{'more...'}])
236set(handles.TransformName,'UserData',TransformPathList)
237TransformIndex=[];
238if isfield(Param,'TransformName')% copy the selected menu index transferred in Param from uvmat
239    TransformIndex=find(strcmp(Param.TransformName,TransformList),1);
240end
241if isempty(TransformIndex)
242    TransformIndex=1;
243end
244set(handles.TransformName,'Value',TransformIndex)
245set(handles.TransformPath,'String',TransformPathList{TransformIndex})
246   
247%% fields input initialisation
248if isfield(Param,'list_fields')&& isfield(Param,'index_fields') &&~isempty(Param.list_fields) &&~isempty(Param.index_fields)
249    set(handles.FieldName,'String',Param.list_fields);% list menu fields
250    set(handles.FieldName,'Value',Param.index_fields);% selected string index
251end
252if isfield(Param,'Coordinates')
253    if isfield(Param.Coordinates,'Coord_x')
254        set(handles.Coord_x,'String',Param.Coordinates.Coord_x)
255    end
256    if isfield(Param.Coordinates,'Coord_y')
257        set(handles.Coord_y,'String',Param.Coordinates.Coord_y)
258    end
259    if isfield(Param.Coordinates,'Coord_z')
260        set(handles.Coord_z,'String',Param.Coordinates.Coord_z)
261    end
262end
263% if isfield(Param,'Coord_x_str') && ischar(Param.Coord_x_str)
264%         set(handles.Coord_x,'String',Param.Coord_x_str);% list menu fields
265% end
266% if isfield(Param,'Coord_y_str')&& ischar(Param.Coord_y_str)
267%         set(handles.Coord_y,'String',Param.Coord_y_str);% list menu fields
268% end
269
270%% introduce the input file name(s) if defined from input Param,
271set(handles.series,'UserData',[])% initiate Userdata
272if isfield(Param,'InputFile')
273   
274    %% fill the list of file series
275    InputTable=[{Param.InputFile.RootPath},{Param.InputFile.SubDir},{Param.InputFile.RootFile},{Param.InputFile.NomType},{Param.InputFile.FileExt}];
276    if isempty(find(cellfun('isempty',InputTable)==0));% if there is no input file, do not introduce input info
277        set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH button to magenta color to indicate that input refresh is needed
278        return
279    end
280    TimeTable=[{Param.InputFile.TimeName},{[]},{[]},{[]},{[]}];
281    if isfield(Param.InputFile,'RootPath_1')
282        InputTable=[InputTable;[{Param.InputFile.RootPath_1},{Param.InputFile.SubDir_1},{Param.InputFile.RootFile_1},{Param.InputFile.NomType_1},{Param.InputFile.FileExt_1}]];
283        TimeTable=[TimeTable; [{Param.InputFile.TimeName_1},{[]},{[]},{[]},{[]}]];
284    end
285    set(handles.InputTable,'Data',InputTable)
286    %% determine the selected reference field indices for pair display
287   
288    [tild,tild,tild,i1,i2,j1,j2]=fileparts_uvmat(Param.InputFile.FileIndex);
289    if isempty(i1)
290        i1=1;
291    end
292    if isempty(i2)
293        i2=i1;
294    end
295    ref_i=floor((i1+i2)/2);% reference image number corresponding to the file
296    % set(handles.num_ref_i,'String',num2str(ref_i));
297    if isempty(j1)
298        j1=1;
299    end
300    if isempty(j2)
301        j2=j1;
302    end
303    ref_j=floor((j1+j2)/2);% reference image number corresponding to the file
304    SeriesData.ref_i=ref_i;
305    SeriesData.ref_j=ref_j;
306    set(handles.series,'UserData',SeriesData)
307    update_rootinfo(handles,Param.HiddenData.i1_series{1},Param.HiddenData.i2_series{1},Param.HiddenData.j1_series{1},Param.HiddenData.j2_series{1},...
308        Param.HiddenData.FileInfo{1},Param.HiddenData.MovieObject{1},1)
309    if isfield(Param,'FileName_1')
310        %         display_file_name(handles,Param,2)
311        update_rootinfo(handles,Param.HiddenData.i1_series{2},Param.HiddenData.i2_series{2},Param.HiddenData.j1_series{2},Param.HiddenData.j2_series{2},...
312            Param.HiddenData.FileInfo{2},Param.HiddenData.MovieObject{2},2)
313    end
314    %% enable field and veltype menus, in accordance with the current action
315    ActionName_Callback([],[], handles)
316   
317    %% set length of waitbar
318    displ_time(handles)
319   
320else
321    set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH button to magenta color to indicate that input refresh is needed
322end
323if isfield(Param,'incr_i')
324    set(handles.num_incr_i,'String',num2str(Param.incr_i))
325else
326    set(handles.num_incr_i,'String','1')
327end
328if isfield(Param,'incr_j')
329    set(handles.num_incr_j,'String',num2str(Param.incr_j))
330else
331    set(handles.num_incr_j,'String','1')
332end
333
334%------------------------------------------------------------------------
335% --- Outputs from this function are returned to the command line.
336function varargout = series_OutputFcn(hObject, eventdata, handles)
337%------------------------------------------------------------------------
338varargout{1} = handles.output;
339
340%------------------------------------------------------------------------
341% --- executed when closing uvmat: delete or desactivate the associated figures if exist
342function closefcn(gcbo,eventdata)
343%------------------------------------------------------------------------
344
345% delete set_object_series if detected
346hh=findobj(allchild(0),'name','view_object_series');
347if ~isempty(hh)
348    delete(hh)
349end
350hh=findobj(allchild(0),'name','edit_object_series');
351if ~isempty(hh)
352    delete(hh)
353end
354
355%delete the bowser if detected
356hh=findobj(allchild(0),'tag','browser');
357if ~isempty(hh)
358    delete(hh)
359end
360
361
362%------------------------------------------------------------------------
363%------------------------------------------------------------------------
364%  II - FUNCTIONS FOR INTRODUCING THE INPUT FILES
365% automatically sets the global properties when the rootfile name is introduced
366% then activate the view-field actionname if selected
367% it is activated either by clicking on the RootPath window or by the
368% browser
369%------------------------------------------------------------------------
370%------------------------------------------------------------------------
371% --- fct activated by the browser under 'Open'
372%------------------------------------------------------------------------ 
373function MenuBrowse_Callback(hObject, eventdata, handles)
374%% look for the previously opened file 'oldfile'
375InputTable=get(handles.InputTable,'Data');
376oldfile=InputTable{1,1};
377if isempty(oldfile)
378    % use a file name stored in prefdir
379    dir_perso=prefdir;
380    profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
381    if exist(profil_perso,'file')
382        h=load (profil_perso);
383        if isfield(h,'RootPath') && ischar(h.RootPath)
384            oldfile=h.RootPath;
385        end
386    end
387end
388%% launch the browser
389fileinput=uigetfile_uvmat('pick an input file in the series',oldfile);
390hh=dir(fileinput);
391if numel(hh)>1
392    msgbox_uvmat('ERROR','invalid input, probably a broken link');
393else
394    if ~isempty(fileinput)
395        display_file_name(handles,fileinput,'one')
396    end
397end
398
399% --------------------------------------------------------------------
400function MenuBrowseAppend_Callback(hObject, eventdata, handles)
401
402%% look for the previously opened file 'oldfile'
403InputTable=get(handles.InputTable,'Data');
404RootPathCell=InputTable(:,1);
405if isempty(RootPathCell{1})% no input file in the table
406     MenuBrowse_Callback(hObject, eventdata, handles)%refresh the input table, not append
407     return
408end
409SubDirCell=InputTable(:,2);
410oldfile=fullfile(RootPathCell{1},SubDirCell{1});
411
412%% use a file name stored in prefdir
413dir_perso=prefdir;
414profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
415if exist(profil_perso,'file')
416    h=load (profil_perso);
417    if isfield(h,'RootPath') && ischar(h.RootPath)
418        oldfile=h.RootPath;
419    end
420end
421
422%% launch the browser
423fileinput=uigetfile_uvmat('pick a file to append in the input table',oldfile);
424hh=dir(fileinput);
425if numel(hh)>1
426    msgbox_uvmat('ERROR','invalid input, probably a broken link');
427else
428    if ~isempty(fileinput)
429        display_file_name(handles,fileinput,'append')
430    end
431end
432
433%------------------------------------------------------------------------
434% --- fct activated by selecting a previous file under the menu Open
435%------------------------------------------------------------------------
436function MenuFile_Callback(hObject, eventdata, handles)
437
438errormsg=display_file_name(handles,get(hObject,'Label'),'one');
439if ~isempty(errormsg)
440    set(hObject,'Label','')
441    MenuFile=[{get(handles.MenuFile_1,'Label')};{get(handles.MenuFile_2,'Label')};...
442        {get(handles.MenuFile_3,'Label')};{get(handles.MenuFile_4,'Label')};{get(handles.MenuFile_5,'Label')}];
443    str_find=strcmp(get(hObject,'Label'),MenuFile);
444    MenuFile(str_find)=[];% suppress the input file to the list
445    for ifile=1:numel(MenuFile)
446        set(handles.(['MenuFile_' num2str(ifile)]),'Label',MenuFile{ifile});
447    end
448end
449
450%------------------------------------------------------------------------
451% --- fct activated by selecting a previous file under the menu Open/append
452%------------------------------------------------------------------------
453function MenuFile_append_Callback(hObject, eventdata, handles)
454
455InputTable=get(handles.InputTable,'Data');
456if isempty(InputTable{1,1})% no input file in the table
457    display_file_name(handles,get(hObject,'Label'),'one') %refresh the input table, not append
458else
459    display_file_name(handles,get(hObject,'Label'),'append')% append the selected file to the current list of InputTable
460end
461
462%------------------------------------------------------------------------
463% --- fct activated by the browser under 'Open campaign/Browse...'
464%------------------------------------------------------------------------
465function MenuBrowseCampaign_Callback(hObject, eventdata, handles)
466
467%% look for the previously opened file 'oldfile'
468InputTable=get(handles.InputTable,'Data');
469if ~isempty(InputTable)
470oldfile=fullfile(InputTable{1,1},InputTable{1,2});
471else
472    % use a file name stored in prefdir
473    dir_perso=prefdir;
474    profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
475    if exist(profil_perso,'file')
476        h=load (profil_perso);
477        if isfield(h,'MenuCampaign') && ~isempty(h.MenuCampaign)&& ischar(h.MenuCampaign{1})
478            oldfile=h.MenuCampaign{1};
479        end
480    end
481end
482
483OutPut=browse_data(oldfile,'on','on');% open the GUI browse_data to get select a campaign dir, experiment and device
484NbLines=numel(OutPut.Experiment)*numel(OutPut.DataSeries);
485icount=0;
486for iexp=1:numel(OutPut.Experiment)
487    for idevice=1:numel(OutPut.DataSeries)
488        icount=icount+1;
489        InputTable{icount,1}=fullfile(OutPut.Campaign,OutPut.Experiment{iexp});
490        InputTable{icount,2}=OutPut.DataSeries{idevice};
491        if isempty(InputTable{icount,3})
492            if icount>1
493            InputTable{icount,3}=InputTable{icount-1,3};
494            else
495                InputTable{icount,3}='';
496            end
497        end
498        if isempty(InputTable{icount,4})
499            if icount>1
500            InputTable{icount,4}=InputTable{icount-1,4};
501            else
502                InputTable{icount,4}='';
503            end
504        end
505                if isempty(InputTable{icount,5})
506            if icount>1
507            InputTable{icount,5}=InputTable{icount-1,5};
508            else
509                InputTable{icount,5}='';
510            end
511        end
512    end
513end
514if size(InputTable,1)>icount
515    InputTable(icount+1:size(InputTable,1),:)=[];
516end
517set(handles.InputTable,'Data',InputTable)
518REFRESH_Callback(hObject, eventdata, handles)
519
520% --------------------------------------------------------------------
521function MenuCampaign_Callback(hObject, eventdata, handles)
522% --------------------------------------------------------------------
523
524OutPut=browse_data(get(hObject,'Label'),'on','on');% open the GUI browse_data to get select a campaign dir, experiment and device
525if ~isfield(OutPut,'Campaign')
526    return
527end
528NbLines=numel(OutPut.Experiment)*numel(OutPut.DataSeries);
529icount=0;
530InputTable=get(handles.InputTable,'Data');
531for iexp=1:numel(OutPut.Experiment)
532    for idevice=1:numel(OutPut.DataSeries)
533        icount=icount+1;
534        InputTable{icount,1}=fullfile(OutPut.Campaign,OutPut.Experiment{iexp});
535        InputTable{icount,2}=OutPut.DataSeries{idevice};
536        if isempty(InputTable{icount,3})
537            if icount>1
538                InputTable{icount,3}=InputTable{icount-1,3};
539            else
540                InputTable{icount,3}='';
541            end
542        end
543        if isempty(InputTable{icount,4})
544            if icount>1
545                InputTable{icount,4}=InputTable{icount-1,4};
546            else
547                InputTable{icount,4}='';
548            end
549        end
550        if isempty(InputTable{icount,5})
551            if icount>1
552                InputTable{icount,5}=InputTable{icount-1,5};
553            else
554                InputTable{icount,5}='';
555            end
556        end
557    end
558end
559if size(InputTable,1)>icount
560    InputTable(icount+1:size(InputTable,1),:)=[];
561end
562set(handles.InputTable,'Data',InputTable)
563REFRESH_Callback(hObject, eventdata, handles)
564
565
566% --- Executes when selected cell(s) is changed in InputTable.
567function InputTable_CellSelectionCallback(hObject, eventdata, handles)
568iline=[];
569if ~isempty(eventdata.Indices)
570    iline=eventdata.Indices(1);
571end
572set(handles.InputLine,'String',num2str(iline));
573% set(handles.InputTable,'UserData',iline);
574
575%------------------------------------------------------------------------
576% --- 'key_press_fcn:' function activated when a key is pressed on the keyboard
577%------------------------------------------------------------------------
578function InputTable_KeyPressFcn(hObject, eventdata, handles)
579set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH button to magenta color to indicate that input refresh is needed
580set(handles.OutputSubDir,'BackgroundColor',[1 0 1])% set edit box OutputSubDir to magenta color to indicate that refresh may be needed
581xx=double(get(handles.series,'CurrentCharacter')); %get the keyboard character
582if ~isempty(xx)
583    switch xx
584        case 31 %downward arrow
585            InputTable=get(handles.InputTable,'Data');
586            iline=str2double(get(handles.InputLine,'String'));
587            if isequal(iline,size(InputTable,1))% arrow downward
588                InputTable=[InputTable;InputTable(iline,:)];% create a new line as a copy of the last one
589                set(handles.InputTable,'Data',InputTable);
590            end
591        case 127  %key 'Suppress'
592            ClearLine_Callback(hObject, eventdata, handles)
593    end
594end
595
596%------------------------------------------------------------------------
597% --- Executes on button press in REFRESH.
598function REFRESH_Callback(hObject, eventdata, handles)
599%------------------------------------------------------------------------
600InputTable=get(handles.InputTable,'Data');
601set(handles.series,'Pointer','watch') % set the mouse pointer to 'watch'
602set(handles.REFRESH,'BackgroundColor',[1 1 0])% set REFRESH  button to yellow color (indicate activation)
603drawnow
604empty_line=false(size(InputTable,1),1);
605for iline=1:size(InputTable,1)
606    empty_line(iline)= isempty(cell2mat(InputTable(iline,1:3)));
607end
608if ~isempty(find(empty_line));
609    InputTable(empty_line,:)=[];%remove empty lines
610    set(handles.InputTable,'Data',InputTable)
611    ListTable={'MinIndex_i','MaxIndex_i','MinIndex_j','MaxIndex_j','PairString','TimeTable'};
612    for ilist=1:numel(ListTable)
613        Table=get(handles.(ListTable{ilist}),'Data');
614        Table(empty_line,:)=[];%remove empty lines
615        set(handles.(ListTable{ilist}),'Data',Table);
616    end
617    set(handles.series,'UserData',[])%refresh the stored info
618end
619nbview=size(InputTable,1);
620for iview=1:nbview
621    RootPath=fullfile(InputTable{iview,1},InputTable{iview,2});
622    if ~exist(RootPath,'dir')
623        i1_series=[];
624        RootFile='';
625    else %scan the input folder
626        if strcmp(InputTable{iview,4},'level')
627            [RootPath,~,RootFile,i1_series,i2_series,j1_series,j2_series,tild,FileInfo,MovieObject]=...
628                find_file_series(fullfile(InputTable{iview,1},InputTable{iview,2},'level0'),[InputTable{iview,3} '0' InputTable{iview,5}]);
629        else
630            [RootPath,~,RootFile,i1_series,i2_series,j1_series,j2_series,tild,FileInfo,MovieObject]=...
631                find_file_series(fullfile(InputTable{iview,1},InputTable{iview,2}),[InputTable{iview,3} InputTable{iview,4} InputTable{iview,5}]);
632        end
633    end
634    % if no file is found, open a browser
635    if isempty(RootFile)&& isempty(i1_series)
636        fileinput=uigetfile_uvmat(['wrong input at line ' num2str(iview) ':pick a new input file'],RootPath);
637        if isempty(fileinput)
638            set(handles.REFRESH,'BackgroundColor',[1 0 0])% set REFRESH  back to red color
639            return
640        else
641            display_file_name(handles,fileinput,iview)
642        end
643    else
644       update_rootinfo(handles,i1_series,i2_series,j1_series,j2_series,FileInfo,MovieObject,iview)
645    end
646end
647
648%% update MinIndex_i and MaxIndex_i if the input table content has been reduced in line nbre
649MinIndex_i_table=get(handles.MinIndex_i,'Data');%retrieve the min indices in the table MinIndex
650set(handles.MinIndex_i,'Data',MinIndex_i_table(1:nbview,:));
651MinIndex_j_table=get(handles.MinIndex_j,'Data');%retrieve the min indices in the table MinIndex
652set(handles.MinIndex_j,'Data',MinIndex_j_table(1:nbview,:));
653MaxIndex_i_table=get(handles.MaxIndex_i,'Data');%retrieve the min indices in the table MinIndex
654set(handles.MaxIndex_i,'Data',MaxIndex_i_table(1:nbview,:));
655MaxIndex_j_table=get(handles.MaxIndex_j,'Data');%retrieve the min indices in the table MinIndex
656set(handles.MaxIndex_j,'Data',MaxIndex_j_table(1:nbview,:));
657PairString=get(handles.PairString,'Data');%retrieve the min indices in the table MinIndex
658set(handles.PairString,'Data',PairString(1:nbview,:));
659TimeTable=get(handles.TimeTable,'Data');%retrieve the min indices in the table MinIndex
660set(handles.TimeTable,'Data',TimeTable(1:nbview,:));
661
662%% enable field and veltype menus, in accordance with the current action
663ActionName_Callback([],[], handles)
664
665%% set length of waitbar
666displ_time(handles)
667
668set(handles.REFRESH,'BackgroundColor',[1 0 0])% set REFRESH  button to red color (indicate activation finished)
669set(handles.series,'Pointer','arrow') % set the mouse pointer to 'watch'
670
671%------------------------------------------------------------------------
672% --- Function called when a new file is opened, either by series_OpeningFcn or by the browser
673%------------------------------------------------------------------------
674% INPUT:
675% handles: handles of elements in the GUI
676% Param: structure of input parameters, including  input file name and path
677% iview: line index in the input table
678%       or 'one': refresh the list
679%         'append': add a new line to the input table
680function errormsg=display_file_name(handles,Param,iview)
681 
682set(handles.REFRESH,'BackgroundColor',[1 1 0])% set REFRESH  button to yellow color (indicate activation)
683drawnow
684errormsg='';%default
685if ischar(Param)
686    fileinput=Param;
687else% input set when series is opened (called by the GUI uvmat)
688    fileinput=Param.FileName;
689end
690   
691%% get the input root name, indices, file extension and nomenclature NomType
692if ~exist(fileinput,'file')
693    errormsg=['input file ' fileinput  ' does not exist'];
694    msgbox_uvmat('ERROR',errormsg)
695    set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH  button to magenta color (refresh still needed)
696    return
697end
698
699%% detect root name, nomenclature and indices in the input file name:
700[FilePath,FileName,FileExt]=fileparts(fileinput);
701%%%%%%%%%%%%%%%%%%
702%TODO: case of input by uvmat: do not check agai the input seies %%%%%%%
703%%%%%%%%%%%%%%%%%%%
704% detect the file type, get the movie object if relevant, and look for the corresponding file series:
705% the root name and indices may be corrected by including the first index i1 if a corresponding xml file exists
706[RootPath,SubDir,RootFile,i1_series,i2_series,j1_series,j2_series,NomType,FileInfo,MovieObject,i1,i2,j1,j2]=find_file_series(FilePath,[FileName FileExt]);
707FileType=FileInfo.FileType;
708if isempty(RootFile)&&isempty(i1_series)
709    errormsg='no input file in the series';
710    msgbox_uvmat('ERROR',errormsg)
711    set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH  button to magenta color (end of activation)
712    return
713end
714if strcmp(FileType,'txt')
715    edit(fileinput)
716    set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH  button to  magenta color (end of activation)
717    return
718elseif strcmp(FileType,'xml')
719    editxml(fileinput)
720    set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH  button to magenta  color (end of activation)
721     return
722elseif strcmp(FileType,'figure')
723    open(fileinput)
724    set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH  button to magenta  color (end of activation)
725     return
726end
727
728%% enable other menus and uicontrols
729% set(handles.MenuOpenCampaign,'Enable','on')
730set(handles.MenuCampaign_1,'Enable','on')
731set(handles.MenuCampaign_2,'Enable','on')
732set(handles.MenuCampaign_3,'Enable','on')
733set(handles.MenuCampaign_4,'Enable','on')
734set(handles.MenuCampaign_5,'Enable','on')
735set(handles.RUN, 'Enable','On')
736set(handles.RUN,'BackgroundColor',[1 0 0])% set RUN button to red
737set(handles.InputTable,'BackgroundColor',[1 1 0]) % set RootPath edit box  to yellow
738drawnow
739
740
741%% fill the list of file series
742InputTable=get(handles.InputTable,'Data');
743SeriesData=get(handles.series,'UserData');
744if strcmp(iview,'append') % display the input data as a new line in the table
745    iview=size(InputTable,1)+1;% the next line in InputTable becomes the current line
746%     InputTable(iview,:)=[{RootPath},{SubDir},{RootFile},{NomType},{FileExt}];
747elseif strcmp(iview,'one') % refresh the list of  input  file series
748    iview=1; %the first line in InputTable becomes the current line
749    InputTable={'','','','',''};
750%     InputTable(iview,:)=[{RootPath},{SubDir},{RootFile},{NomType},{FileExt}];
751    set(handles.TimeTable,'Data',[{''},{[]},{[]},{[]},{[]}])
752    set(handles.MinIndex_i,'Data',[])
753    set(handles.MaxIndex_i,'Data',[])
754    set(handles.MinIndex_j,'Data',[])
755    set(handles.MaxIndex_j,'Data',[])
756    set(handles.PairString,'Data',{''})
757    SeriesData.CheckPair=0;%reset the list of input lines with pairs
758    SeriesData.i1_series={};
759    SeriesData.i2_series={};
760    SeriesData.j1_series={};
761    SeriesData.j2_series={};
762    SeriesData.FileType={};
763    SeriesData.FileInfo={};
764    SeriesData.Time={};
765end
766if isfield(SeriesData,'i1_series')
767    SeriesData.i1_series(iview+1:end)=[];
768    SeriesData.i2_series(iview+1:end)=[];
769    SeriesData.j1_series(iview+1:end)=[];
770    SeriesData.j2_series(iview+1:end)=[];
771    SeriesData.FileType(iview+1:end)=[];
772    SeriesData.FileInfo(iview+1:end)=[];
773    SeriesData.Time(iview+1:end)=[];
774end
775InputTable(iview,:)=[{RootPath},{SubDir},{RootFile},{NomType},{FileExt}];
776if iview >1
777    set(handles.InputLine,'String',num2str(iview))
778end
779set(handles.InputTable,'Data',InputTable)
780
781%% determine the selected reference field indices for pair display
782if isempty(i1)
783    i1=1;
784end
785if isempty(i2)
786    i2=i1;
787end
788ref_i=floor((i1+i2)/2);% reference image number corresponding to the file
789% set(handles.num_ref_i,'String',num2str(ref_i));
790if isempty(j1)
791    j1=1;
792end
793if isempty(j2)
794    j2=j1;
795end
796ref_j=floor((j1+j2)/2);% reference image number corresponding to the file
797SeriesData.ref_i=ref_i;
798SeriesData.ref_j=ref_j;
799
800%% update first and last indices if they do not exist
801Param=read_GUI(handles.series);
802first_j=[];
803if isfield(Param.IndexRange,'first_j'); first_j=Param.IndexRange.first_j; end
804last_j=[];
805if isfield(Param.IndexRange,'last_j'); last_j=Param.IndexRange.last_j; end
806PairString='';
807if isfield(Param.IndexRange,'PairString'); PairString=Param.IndexRange.PairString; end
808[i1,i2,j1,j2] = get_file_index(Param.IndexRange.first_i,first_j,PairString);
809FirstFileName=fullfile_uvmat(Param.InputTable{1,1},Param.InputTable{1,2},Param.InputTable{1,3},...
810    Param.InputTable{1,5},Param.InputTable{1,4},i1,i2,j1,j2);
811if ~exist(FirstFileName,'file')
812    set(handles.num_first_i,'String',num2str(ref_i))
813    set(handles.num_first_j,'String',num2str(ref_j))
814end
815[i1,i2,j1,j2] = get_file_index(Param.IndexRange.last_i,last_j,PairString);
816LastFileName=fullfile_uvmat(Param.InputTable{1,1},Param.InputTable{1,2},Param.InputTable{1,3},...
817    Param.InputTable{1,5},Param.InputTable{1,4},i1,i2,j1,j2);
818if ~exist(LastFileName,'file')
819    set(handles.num_last_i,'String',num2str(ref_i))
820    set(handles.num_last_j,'String',num2str(ref_j))
821end
822
823%% update the list of recent files in the menubar and save it for future opening
824MenuFile=[{get(handles.MenuFile_1,'Label')};{get(handles.MenuFile_2,'Label')};...
825    {get(handles.MenuFile_3,'Label')};{get(handles.MenuFile_4,'Label')};{get(handles.MenuFile_5,'Label')}];
826str_find=strcmp(fileinput,MenuFile);
827if isempty(find(str_find,1))
828    MenuFile=[{fileinput};MenuFile];%insert the current file if not already in the list
829end
830for ifile=1:min(length(MenuFile),5)
831    eval(['set(handles.MenuFile_' num2str(ifile) ',''Label'',MenuFile{ifile});'])
832end
833dir_perso=prefdir;
834profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
835if exist(profil_perso,'file')
836    save (profil_perso,'MenuFile','-append'); %store the file names for future opening of uvmat
837else
838    save (profil_perso,'MenuFile','-V6'); %store the file names for future opening of uvmat
839end
840% save the opened file to initiate future opening
841SeriesData.RefFile{iview}=fileinput;% reference opening file for line iview
842SeriesData.Ref_i1=i1;
843SeriesData.Ref_i2=i2;
844SeriesData.Ref_j1=j1;
845SeriesData.Ref_j2=j2;
846set(handles.series,'UserData',SeriesData)
847
848set(handles.InputTable,'BackgroundColor',[1 1 1])
849
850%% initiate input file series and refresh the current field view:     
851update_rootinfo(handles,i1_series,i2_series,j1_series,j2_series,FileInfo,MovieObject,iview);
852%% enable field and veltype menus, in accordance with the current action
853ActionName_Callback([],[], handles)
854
855%% set length of waitbar
856displ_time(handles)
857
858set(handles.REFRESH,'BackgroundColor',[1 0 0])% set REFRESH  button to red color (end of activation)
859
860%------------------------------------------------------------------------
861% --- Update information about a new field series (indices to scan, timing,
862%     calibration from an xml file
863function update_rootinfo(handles,i1_series,i2_series,j1_series,j2_series,FileInfo,VideoObject,iview)
864%------------------------------------------------------------------------
865InputTable=get(handles.InputTable,'Data');
866
867%% display the min and max indices for the whole file series
868if size(i1_series,2)==2 && min(min(i1_series(:,1,:)))==0
869    MinIndex_j=1;% index j set to 1 by default
870    MaxIndex_j=1;
871    MinIndex_i=find(i1_series(1,2,:), 1 )-1;% min ref index i detected in the series (corresponding to the first non-zero value of i1_series, except for zero index)
872    MaxIndex_i=find(i1_series(1,2,:),1,'last' )-1;%max ref index i detected in the series (corresponding to the last non-zero value of i1_series)
873else
874    ref_i=squeeze(max(i1_series(1,:,:),[],2));% select ref_j index for each ref_i
875    ref_j=squeeze(max(j1_series(1,:,:),[],3));% select ref_i index for each ref_j
876     MinIndex_i=min(find(ref_i))-1;
877     MaxIndex_i=max(find(ref_i))-1;
878     MaxIndex_j=max(find(ref_j))-1;
879     MinIndex_j=min(find(ref_j))-1;
880    diff_j_max=diff(ref_j);
881    diff_i_max=diff(ref_i);
882    if ~isempty(diff_i_max) && isequal (diff_i_max,diff_i_max(1)*ones(size(diff_i_max)))
883        set(handles.num_incr_i,'String',num2str(diff_i_max(1)))% detect an increment to dispaly by default
884    end
885    if ~isempty(diff_j_max) && isequal (diff_j_max,diff_j_max(1)*ones(size(diff_j_max)))
886        set(handles.num_incr_j,'String',num2str(diff_j_max(1)))
887    end
888end
889if isequal(MinIndex_i,-1)
890    MinIndex_i=0;
891end
892if isequal(MinIndex_j,-1)
893    MinIndex_j=0;
894end
895MinIndex_i_table=get(handles.MinIndex_i,'Data');%retrieve the min indices in the table MinIndex
896MinIndex_j_table=get(handles.MinIndex_j,'Data');%retrieve the min indices in the table MinIndex
897MaxIndex_i_table=get(handles.MaxIndex_i,'Data');%retrieve the min indices in the table MinIndex
898MaxIndex_j_table=get(handles.MaxIndex_j,'Data');%retrieve the min indices in the table MinIndex
899if ~isempty(MinIndex_i)&&~isempty(MaxIndex_i)
900    MinIndex_i_table(iview,1)=MinIndex_i;
901    MaxIndex_i_table(iview,1)=MaxIndex_i;
902end
903if ~isempty(MinIndex_j)&&~isempty(MaxIndex_j)
904    MinIndex_j_table(iview,1)=MinIndex_j;
905    MaxIndex_j_table(iview,1)=MaxIndex_j;
906end
907set(handles.MinIndex_i,'Data',MinIndex_i_table)%display the min indices in the table MinIndex
908set(handles.MinIndex_j,'Data',MinIndex_j_table)%display the max indices in the table MaxIndex
909set(handles.MaxIndex_i,'Data',MaxIndex_i_table)%display the min indices in the table MinIndex
910set(handles.MaxIndex_j,'Data',MaxIndex_j_table)%display the max indices in the table MaxIndex
911SeriesData=get(handles.series,'UserData');
912
913%% adjust the first and last indices for the selected series, only if requested by the bounds
914% i index, compare input to min index i
915first_i=str2num(get(handles.num_first_i,'String'));%retrieve previous first i
916% ref_i=str2num(get(handles.num_ref_i,'String'));%index i given by the input field
917ref_i=1;
918if isfield(SeriesData,'ref_i')
919    ref_i=SeriesData.ref_i;
920end
921if isempty(first_i)
922    first_i=ref_i;% first_i updated by the input value
923elseif first_i < MinIndex_i
924    first_i=MinIndex_i; % first_i set to the min i index (restricted by oter input lines)
925elseif first_i >MaxIndex_i
926    first_i=MaxIndex_i;% first_i set to the max i index (restricted by oter input lines)
927end
928% j index,  compare input to min index j
929first_j=str2num(get(handles.num_first_j,'String'));
930ref_j=1;
931if isfield(SeriesData,'ref_j')
932    ref_j=SeriesData.ref_j;
933end
934if isempty(first_j)
935    first_j=ref_j;% first_j updated by the input value
936elseif first_j<MinIndex_j
937    first_j=MinIndex_j; % first_j set to the min j index (restricted by oter input lines)
938elseif first_j >MaxIndex_j
939    first_j=MaxIndex_j; % first_j set to the max j index (restricted by oter input lines)
940end
941% i index, compare input to max index i
942last_i=str2num(get(handles.num_last_i,'String'));
943if isempty(last_i)
944    last_i=ref_i;
945elseif last_i > MaxIndex_i
946    last_i=MaxIndex_i;
947elseif last_i<first_i
948    last_i=first_i;
949end
950% j index, compare input to max index j
951last_j=str2num(get(handles.num_last_j,'String'));
952if isempty(last_j)
953    last_j=ref_j;
954elseif last_j>MaxIndex_j
955    last_j=MaxIndex_j;
956elseif last_j<first_j
957    last_j=first_j;
958end
959set(handles.num_first_i,'String',num2str(first_i));
960set(handles.num_first_j,'String',num2str(first_j));
961set(handles.num_last_i,'String',num2str(last_i));
962set(handles.num_last_j,'String',num2str(last_j));
963
964%% number of slices set by default
965NbSlice=[];%default
966% read  value set by the first series for the append mode (iwiew >1)
967if iview>1 && strcmp(get(handles.num_NbSlice,'Visible'),'on')
968    NbSlice=str2double(get(handles.num_NbSlice,'String'));
969end
970
971%% default time settings
972TimeUnit='';
973% read  value set by the first series for the append mode (iwiew >1)
974if iview>1
975    TimeUnit=get(handles.TimeUnit,'String');
976end
977TimeName='';
978Time=[];%default
979TimeMin=[];
980TimeFirst=[];
981TimeLast=[];
982TimeMax=[];
983
984%%  read image documentation file if found
985XmlData=[];
986check_calib=0;
987XmlFileName=find_imadoc(InputTable{iview,1},InputTable{iview,2},InputTable{iview,3},InputTable{iview,5});
988if ~isempty(XmlFileName)
989    [XmlData,errormsg]=imadoc2struct(XmlFileName);
990    if ~isempty(errormsg)
991        msgbox_uvmat('WARNING',['error in reading ' XmlFileName ': ' errormsg]);
992    end
993    % read time if available
994    if isfield(XmlData,'Time')
995        Time=XmlData.Time;
996        TimeName='xml';
997%                         if XmlData.Time(1,:)==XmlData.Time(2,:)% case starting with index 1
998%                     sizDti=size(XmlData.Time,1)-1;%size of the time vector explicitly defined in the xml file
999%                     ind_start=1;
1000%                 else
1001%                     sizDti=size(XmlData.Time,1);% case starting with index 0
1002%                     ind_start=0;
1003%                 end
1004%         % complement the input if the whole time series is not defined
1005%             if size(i1_series,3)>size(XmlData.Time,1)-ind_start %only the first time interval is defined, extrapolate to the whole series
1006%                 Dti_total=XmlData.Time(end)-XmlData.Time(1);%total time interval covered by the time vector
1007%                 missing_indices=sizDti+1+ind_start:size(i1_series,3)+1;% remaining set of frame indices for which time needs to be found
1008%                 repeat_nbre=1+floor((missing_indices-sizDti-ind_start)/(sizDti-1));% number of repetitions of Dti
1009%                 time_indices=1+mod(missing_indices-sizDti-1,sizDti-1);
1010%                 for j=1:size(XmlData.Time,2)
1011%                 Time(missing_indices,j)=XmlData.Time(time_indices,j)+repeat_nbre'*Dti_total;
1012%                 end
1013%                 % update the xml file with NbDti
1014%                 t=xmltree(XmlFileName);
1015%                 uid_NbDti=find(t,'ImaDoc/Camera/BurstTiming/NbDti')
1016%                 if isempty(uid_NbDti)
1017%                     uid_BurstTiming=find(t,'ImaDoc/Camera/BurstTiming')
1018%                     [t,uid_NbDti]=add(t,uid_BurstTiming,'element','NbDti');
1019%                 end
1020%                 [t,uid_NbDti]=add(t,uid_NbDti,'chardata',num2str(repeat_nbre(end)-1));
1021%                 save(t,XmlFileName)
1022%             end
1023    end
1024    if isfield(XmlData,'Camera')
1025        %         if isfield(XmlData.Camera,'NbSlice')&& ~isempty(XmlData.Camera.NbSlice)
1026        %             if iview>1 && ~isempty(NbSlice) && ~strcmp(NbSlice,XmlData.Camera.NbSlice)
1027        %                 msgbox_uvmat('WARNING','inconsistent number of slices with the first field series');
1028        %             end
1029        %             NbSlice=XmlData.Camera.NbSlice;% Nbre of slices from camera
1030        %         end
1031        if isfield(XmlData.Camera,'TimeUnit')&& ~isempty(XmlData.Camera.TimeUnit)
1032            if iview>1 && ~isempty(TimeUnit) && ~strcmp(TimeUnit,XmlData.Camera.TimeUnit)
1033                msgbox_uvmat('WARNING','inconsistent time unit with the first field series');
1034            end
1035            TimeUnit=XmlData.Camera.TimeUnit;
1036        end
1037    end
1038    % number of slices
1039    if isfield(XmlData,'TranslationMotor')&& isfield(XmlData.TranslationMotor,'NbSlice')
1040        NbSlice_motor=XmlData.TranslationMotor.NbSlice;
1041        if ~isempty(NbSlice) && ~isequal(NbSlice_motor,NbSlice)
1042                msgbox_uvmat('WARNING','inconsistent Z numbers of Z indices');
1043        else
1044            NbSlice=NbSlice_motor;
1045        end
1046    end
1047   
1048    if isfield(XmlData,'GeometryCalib')
1049        check_calib=1;
1050        if isfield(XmlData.GeometryCalib,'SliceCoord')
1051            siz=size(XmlData.GeometryCalib.SliceCoord);
1052            if ~isempty(NbSlice)&& ~isequal(size(1),NbSlice)
1053                msgbox_uvmat('WARNING','inconsistent numbers of Z indices between motor and calibration');
1054            else
1055                NbSlice=siz(1);
1056            end
1057        end
1058    end
1059end
1060if ~isempty(NbSlice)
1061set(handles.num_NbSlice,'String',num2str(NbSlice))
1062set(handles.num_NbSlice,'Visible','on')
1063end
1064
1065%% read timing  from the current file (prioritary)
1066if ~isempty(VideoObject)% case of movies
1067    imainfo=get(VideoObject);
1068    if isempty(j1_series); %frame index along i
1069        Time=zeros(imainfo.NumberOfFrames+1,2);
1070        Time(:,2)=(0:1/imainfo.FrameRate:(imainfo.NumberOfFrames)/imainfo.FrameRate)';
1071    else
1072        Time=[0;ones(size(i1_series,3)-1,1)]*(0:1/imainfo.FrameRate:(imainfo.NumberOfFrames)/imainfo.FrameRate);
1073    end
1074    TimeName='video';
1075end
1076
1077
1078%% determine the min and max times: case of Netcdf files will be treated later in FieldName_Callback
1079if ~isempty(TimeName)
1080    TimeMin=Time(MinIndex_i+1,MinIndex_j+1);
1081    if size(Time)>=[first_i+1 first_j+1]
1082        TimeFirst=Time(first_i+1,first_j+1);
1083    end
1084    if size(Time)>=[last_i+1 last_j+1]
1085        TimeLast=Time(last_i+1,last_j+1);
1086    end
1087    if size(Time)>=[MaxIndex_i+1 MaxIndex_j+1];
1088        TimeMax=Time(MaxIndex_i+1,MaxIndex_j+1);
1089    end
1090end
1091
1092%% update the time table
1093TimeTable=get(handles.TimeTable,'Data');
1094TimeTable{iview,1}=TimeName;
1095TimeTable{iview,2}=TimeMin;
1096TimeTable{iview,3}=TimeFirst;
1097TimeTable{iview,4}=TimeLast;
1098TimeTable{iview,5}=TimeMax;
1099set(handles.TimeTable,'Data',TimeTable)
1100
1101%% update the series info in 'UserData'
1102SeriesData.i1_series{iview}=i1_series;
1103SeriesData.i2_series{iview}=i2_series;
1104SeriesData.j1_series{iview}=j1_series;
1105SeriesData.j2_series{iview}=j2_series;
1106SeriesData.FileType{iview}=FileInfo.FileType;
1107SeriesData.FileInfo{iview}=FileInfo;
1108SeriesData.Time{iview}=Time;
1109% if ~isempty(TimeName)
1110%     SeriesData.TimeSource=TimeSource;
1111% end
1112if check_calib
1113    SeriesData.GeometryCalib{iview}=XmlData.GeometryCalib;
1114end
1115set(handles.series,'UserData',SeriesData)
1116
1117%% update pair menus
1118hset_pair=findobj(allchild(0),'Tag','set_pairs');
1119if ~isempty(hset_pair), delete(hset_pair); end % delete the GUI set_pair if opened
1120CheckPair= ~isempty(i2_series)||~isempty(j2_series); % check whether index pairs need to be defined
1121PairString=get(handles.PairString,'Data');
1122if CheckPair% if pairs need to be display for line iview
1123    [ModeMenu,ModeValue]=update_mode(i1_series,i2_series,j2_series);
1124    Menu=update_listpair(i1_series,i2_series,j1_series,j2_series,ModeMenu{ModeValue},Time,TimeUnit,ref_i,ref_j,TimeName,InputTable(iview,:),FileInfo);
1125    PairString{iview,1}=Menu{1};
1126else
1127    PairString{iview,1}='';%no pair for #iview
1128end
1129set(handles.PairString,'Data',PairString)
1130if isempty(find(cellfun('isempty',get(handles.PairString,'Data'))==0, 1))% if all lines of pairs are empty
1131    set(handles.PairString,'Visible','off')
1132    set(handles.SetPairs,'Visible','off')
1133else
1134    set(handles.PairString,'Visible','on')
1135    set(handles.SetPairs,'Visible','on')
1136end
1137
1138
1139%% display the set of existing files as an image
1140set(handles.FileStatus,'Units','pixels')
1141Position=get(handles.FileStatus,'Position');
1142set(handles.FileStatus,'Units','normalized')
1143%xI=0.5:Position(3)-0.5;
1144nbview=numel(SeriesData.i1_series);
1145j_max=cell(1,nbview);
1146MaxIndex_i=ones(1,nbview);%default
1147MinIndex_i=ones(1,nbview);%default
1148for iline=1:nbview
1149    pair_max=squeeze(max(SeriesData.i1_series{iline},[],1)); %max on pair index
1150    j_max{iline}=max(pair_max,[],1);%max on j index
1151    if ~isempty(j_max{iline})
1152    MaxIndex_i(iline)=max(find(j_max{iline}))-1;% max ref index i
1153    MinIndex_i(iline)=min(find(j_max{iline}))-1;% min ref index i
1154    end
1155end
1156MinIndex_i=min(MinIndex_i);
1157MaxIndex_i=max(MaxIndex_i);
1158range_index=MaxIndex_i-MinIndex_i+1;
1159range_y=max(1,floor(Position(4)/nbview));
1160npx=floor(Position(3));
1161file_indices=MinIndex_i+floor(((0.5:npx-0.5)/npx)*range_index)+1;
1162CData=zeros(nbview*range_y,npx);% initiate the image representing the existing files
1163for iline=1:nbview
1164    ind_y=1+(iline-1)*range_y:iline*range_y;
1165    LineData=zeros(size(file_indices));
1166    file_select=file_indices(file_indices<=numel(j_max{iline}));
1167    ind_select=find(file_indices<=numel(j_max{iline}));
1168    LineData(ind_select)=j_max{iline}(file_select)~=0;
1169    CData(ind_y,:)=ones(size(ind_y'))*LineData;
1170end
1171CData=cat(3,zeros(size(CData)),CData,zeros(size(CData)));%make color images r=0,g,b=0
1172set(handles.FileStatus,'CData',CData);
1173
1174%-----------------------------------------------------------guide -------------
1175%------------------------------------------------------------------------
1176%  III - FUNCTIONS ASSOCIATED TO THE FRAME IndexRange
1177%------------------------------------------------------------------------
1178
1179
1180% ---- determine the menu to put in mode and advice a default choice
1181%------------------------------------------------------------------------
1182function [ModeMenu,ModeValue]=update_mode(i1_series,i2_series,j2_series)
1183%------------------------------------------------------------------------   
1184ModeMenu={''};
1185if isempty(j2_series)% no j pair
1186    ModeValue=1;
1187    if ~isempty(i2_series)
1188        ModeMenu={'series(Di)'}; % pair menu with only option Di
1189    end
1190else %existence of j pairs
1191    pair_max=squeeze(max(i1_series,[],1)); %max on pair index
1192    j_max=max(pair_max,[],1);
1193    MaxIndex_i=find(j_max, 1, 'last' )-1;% max ref index i
1194    MinIndex_i=find(j_max, 1 )-1;% min ref index i
1195    i_max=max(pair_max,[],2);
1196    MaxIndex_j=find(i_max, 1, 'last' )-1;% max ref index i
1197    MinIndex_j=find(i_max, 1 )-1;% min ref index i
1198    if MaxIndex_j==MinIndex_j
1199        ModeValue=1;
1200        ModeMenu={'bursts'};
1201    elseif MaxIndex_i==MinIndex_i
1202        ModeValue=1;
1203        ModeMenu={'series(Dj)'};
1204    else
1205        ModeMenu={'bursts';'series(Dj)'};
1206        if (MaxIndex_j-MinIndex_j)>10
1207            ModeValue=2;%set mode to series(Dj) if more than 10 j values
1208        else
1209            ModeValue=1;
1210        end
1211    end
1212end
1213
1214
1215%------------------------------------------------------------------------
1216function displ_pair=update_listpair(i1_series,i2_series,j1_series,j2_series,mode,time,TimeUnit,ref_i,ref_j,TimeName,InputTable,FileInfo)
1217%------------------------------------------------------------------------
1218displ_pair={};
1219if isempty(TimeUnit)
1220    dtunit='e-03';
1221else
1222    dtunit=['m' TimeUnit];
1223end
1224switch mode
1225    case 'series(Di)'
1226        diff_i=i2_series-i1_series;
1227        min_diff=min(diff_i(diff_i>0));
1228        max_diff=max(diff_i(diff_i>0));
1229        for ipair=min_diff:max_diff
1230            if numel(diff_i(diff_i==ipair))>0
1231                pair_string=['Di= ' num2str(-floor(ipair/2)) '|' num2str(ceil(ipair/2)) ];
1232                if ~isempty(time)
1233                    if ref_i<=floor(ipair/2)
1234                        ref_i=floor(ipair/2)+1;% shift ref_i to get the first pair
1235                    end
1236                    Dt=time(ref_i+ceil(ipair/2),ref_j)-time(ref_i-floor(ipair/2),ref_j);
1237                    pair_string=[pair_string ', Dt=' num2str(Dt) ' ' dtunit];
1238                end
1239                displ_pair=[displ_pair;{pair_string}];
1240            end
1241        end
1242        if ~isempty(displ_pair)
1243            displ_pair=[displ_pair;{'Di=*|*'}];
1244        end
1245    case 'series(Dj)'
1246        if isempty(j2_series)
1247            msgbox_uvmat('ERROR','no j1-j2 pair available')
1248            return
1249        end
1250        diff_j=j2_series-j1_series;
1251        min_diff=min(diff_j(diff_j>0));
1252        max_diff=max(diff_j(diff_j>0));
1253        for ipair=min_diff:max_diff
1254            if numel(diff_j(diff_j==ipair))>0
1255                pair_string=['Dj= ' num2str(-floor(ipair/2)) '|' num2str(ceil(ipair/2)) ];
1256                if ~isempty(time)
1257                    if ref_j<=floor(ipair/2)
1258                        ref_j=floor(ipair/2)+1;% shift ref_i to get the first pair
1259                    end
1260                    Dt=time(ref_i,ref_j+ceil(ipair/2))-time(ref_i,ref_j-floor(ipair/2));
1261                    pair_string=[pair_string ', Dt=' num2str(Dt) ' ' dtunit];
1262                end
1263                displ_pair=[displ_pair;{pair_string}];
1264            end
1265        end
1266        if ~isempty(displ_pair)
1267            displ_pair=[displ_pair;{'Dj=*|*'}];
1268        end
1269    case 'bursts'
1270        if isempty(j2_series)
1271            msgbox_uvmat('ERROR','no j1-j2 pair available')
1272            return
1273        end
1274        %diff_j=j2_series-j1_series;
1275        min_j1=min(j1_series(j1_series>0));
1276        max_j1=max(j1_series(j1_series>0));
1277        min_j2=min(j2_series(j2_series>0));
1278        max_j2=max(j2_series(j2_series>0));
1279        for pair1=min_j1:min(max_j1,min_j1+20)
1280            for pair2=min_j2:min(max_j2,min_j2+20)
1281                if numel(j1_series(j1_series==pair1))>0 && numel(j2_series(j2_series==pair2))>0
1282                    pair_string=['j= ' num2str(pair1) '-' num2str(pair2)];
1283                    [TimeValue,DtValue]=get_time(ref_i,[],pair_string,InputTable,FileInfo,TimeName,'Dt');
1284                    %Dt=time(ref_i,pair2+1)-time(ref_i,pair1+1);
1285                    pair_string=[pair_string ', Dt=' num2str(DtValue) ' ' dtunit];
1286                    displ_pair=[displ_pair;{pair_string}];
1287                end
1288            end
1289        end
1290        if ~isempty(displ_pair)
1291            displ_pair=[displ_pair;{'j=*-*'}];
1292        end
1293end
1294
1295%------------------------------------------------------------------------
1296function num_first_i_Callback(hObject, eventdata, handles)
1297%------------------------------------------------------------------------
1298num_last_i_Callback(hObject, eventdata, handles)
1299
1300%------------------------------------------------------------------------
1301function num_last_i_Callback(hObject, eventdata, handles)
1302%------------------------------------------------------------------------
1303SeriesData=get(handles.series,'UserData');
1304if ~isfield(SeriesData,'Time')
1305    SeriesData.Time{1}=[];
1306end
1307displ_time(handles);
1308
1309%------------------------------------------------------------------------
1310function num_first_j_Callback(hObject, eventdata, handles)
1311%------------------------------------------------------------------------
1312 num_last_j_Callback(hObject, eventdata, handles)
1313
1314%------------------------------------------------------------------------
1315function num_last_j_Callback(hObject, eventdata, handles)
1316%------------------------------------------------------------------------
1317% first_j=str2num(get(handles.num_first_j,'String'));
1318% last_j=str2num(get(handles.num_last_j,'String'));
1319% ref_j=ceil((first_j+last_j)/2);
1320% set(handles.num_ref_j,'String', num2str(ref_j))
1321% num_ref_j_Callback(hObject, eventdata, handles)
1322SeriesData=get(handles.series,'UserData');
1323if ~isfield(SeriesData,'Time')
1324    SeriesData.Time{1}=[];
1325end
1326displ_time(handles);
1327
1328%------------------------------------------------------------------------
1329% ---- find the times corresponding to the first and last indices of a series
1330function displ_time(handles)
1331%------------------------------------------------------------------------
1332SeriesData=get(handles.series,'UserData');%
1333if ~isfield(SeriesData,'Time')
1334    return
1335end
1336PairString=get(handles.PairString,'Data');
1337ref_i_1=str2num(get(handles.num_first_i,'String'));%first reference index
1338ref_i_2=str2num(get(handles.num_last_i,'String'));%last reference index
1339ref_j_1=[];ref_j_2=[];
1340if strcmp(get(handles.num_first_j,'Visible'),'on')
1341ref_j_1=str2num(get(handles.num_first_j,'String'));
1342ref_j_2=str2num(get(handles.num_last_j,'String'));
1343end
1344[i1_1,i2_1,j1_1,j2_1] = get_file_index(ref_i_1,ref_j_1,PairString);
1345[i1_2,i2_2,j1_2,j2_2] = get_file_index(ref_i_2,ref_j_2,PairString);
1346TimeTable=get(handles.TimeTable,'Data');
1347%%%%%%
1348%TODO: read time in netcdf file, see ActionName_Callback
1349%%%%%%%
1350%Pairs=get(handles.PairString,'Data');
1351for iview=1:size(TimeTable,1)
1352    if size(SeriesData.Time,1)<iview
1353        break
1354    end
1355    TimeTable{iview,3}=[];
1356    TimeTable{iview,4}=[];
1357    if size(SeriesData.Time{iview},1)>=i2_2+1 && (isempty(ref_j_1)||size(SeriesData.Time{iview},2)>=j2_2+1)
1358        if isempty(ref_j_1)
1359            time_first=(SeriesData.Time{iview}(i1_1+1,2)+SeriesData.Time{iview}(i2_1+1,2))/2;
1360            time_last=(SeriesData.Time{iview}(i1_2+1,2)+SeriesData.Time{iview}(i2_2+1,2))/2;
1361        else
1362            time_first=(SeriesData.Time{iview}(i1_1+1,j1_1+1)+SeriesData.Time{iview}(i2_1+1,j2_1+1))/2;
1363            time_last=(SeriesData.Time{iview}(i1_2+1,j1_2+1)+SeriesData.Time{iview}(i2_2+1,j2_1+1))/2;
1364        end
1365        TimeTable{iview,3}=time_first; %TODO: take into account pairs
1366        TimeTable{iview,4}=time_last; %TODO: take into account pairs
1367    end
1368end
1369set(handles.TimeTable,'Data',TimeTable)
1370
1371%% set the waitbar position with respect to the min and max in the series
1372MinIndex_i=min(get(handles.MinIndex_i,'Data'));
1373MaxIndex_i=max(get(handles.MaxIndex_i,'Data'));
1374pos_first=(ref_i_1-MinIndex_i)/(MaxIndex_i-MinIndex_i+1);
1375pos_last=(ref_i_2-MinIndex_i+1)/(MaxIndex_i-MinIndex_i+1);
1376if isempty(pos_first), pos_first=0; end
1377if isempty(pos_last), pos_last=1; end
1378Position=get(handles.Waitbar,'Position');% position of the waitbar:= [ x,y, width, height]
1379Position_status=get(handles.FileStatus,'Position');
1380Position(1)=Position_status(1)+Position_status(3)*pos_first;
1381Position(3)=max(Position_status(3)*(pos_last-pos_first),0.001);% width must remain positive
1382set(handles.Waitbar,'Position',Position)
1383update_waitbar(handles.Waitbar,0)
1384
1385%------------------------------------------------------------------------
1386% --- Executes when selected cell(s) is changed in PairString.
1387function PairString_CellSelectionCallback(hObject, eventdata, handles)
1388%------------------------------------------------------------------------   
1389if numel(eventdata.Indices)>=1
1390    PairString=get(hObject,'Data');
1391    if ~isempty(PairString{eventdata.Indices(1)})
1392        SetPairs_Callback(hObject, eventdata.Indices(1), handles)
1393    end
1394end
1395
1396%-------------------------------------
1397function enable_i(handles,state)
1398set(handles.i_txt,'Visible',state)
1399set(handles.num_first_i,'Visible',state)
1400set(handles.num_last_i,'Visible',state)
1401set(handles.num_incr_i,'Visible',state)
1402
1403%-----------------------------------
1404function enable_j(handles,state)
1405set(handles.j_txt,'Visible',state)
1406set(handles.num_first_j,'Visible',state)
1407set(handles.num_last_j,'Visible',state)
1408set(handles.num_incr_j,'Visible',state)
1409set(handles.MinIndex_j,'Visible',state)
1410set(handles.MaxIndex_j,'Visible',state)
1411
1412
1413%%%%%%%%%%%%%%%%%%%%
1414%%  MAIN ActionName FUNCTIONS
1415%%%%%%%%%%%%%%%%%%%%
1416%------------------------------------------------------------------------
1417% --- Executes on button press in RUN.
1418%------------------------------------------------------------------------
1419function RUN_Callback(hObject, eventdata, handles)
1420
1421%% settings of the button RUN
1422set(handles.RUN,'BusyAction','queue');% activation of STOP button will set BusyAction to 'cancel'
1423set(handles.RUN, 'Enable','Off')% avoid further RUN action until the current one is finished
1424set(handles.RUN,'BackgroundColor',[1 1 0])%show activation of RUN by yellow color
1425drawnow
1426set(handles.status,'Value',0)% desable status display if relevant
1427status_Callback([], eventdata, handles)
1428
1429%% launch action
1430errormsg=launch_action(handles);
1431if ~isempty(errormsg)
1432     msgbox_uvmat('ERROR',errormsg)
1433end
1434
1435%% reset the GUI series
1436update_waitbar(handles.Waitbar,1); % put the waitbar to end position to indicate launching is finished
1437set(handles.RUN, 'Enable','On')
1438set(handles.RUN,'BackgroundColor',[1 0 0])
1439set(handles.RUN, 'Value',0)
1440
1441%------------------------------------------------------------------------
1442% --- called by RUN_Callback
1443%------------------------------------------------------------------------
1444function errormsg=launch_action(handles)
1445errormsg='';%default
1446
1447%% read the data on the GUI series
1448Param=read_GUI_series(handles);%displayed parameters
1449SeriesData=get(handles.series,'UserData');%hidden parameters
1450if isfield(SeriesData,'TransformInput')
1451    Param.TransformInput=SeriesData.TransformInput;
1452end
1453if ~isfield(SeriesData,'i1_series')
1454    errormsg='The input field series needs to be refreshed: press REFRESH';
1455    return
1456end
1457if isfield(Param,'InputFields')&& isfield(Param.InputFields,'FieldName')&& isequal(Param.InputFields.FieldName,'get_field...')
1458    errormsg='input field name(s) not defined, select get_field...';
1459    return
1460end
1461
1462%% select the Action mode, 'local', 'background' or 'cluster' (if available)
1463RunMode='local';%default (needed for first opening of the GUI series)
1464if isfield(Param.Action,'RunMode')
1465    RunMode=Param.Action.RunMode;
1466    Param.Action=rmfield(Param.Action,'RunMode');%remove from the recorded xml file to avoid interference during ImportConfig
1467end
1468ActionExt='.m';%default
1469if isfield(Param.Action,'ActionExt')
1470    ActionExt=Param.Action.ActionExt;% '.m', '.sh' (compiled)  or '.py' (Python)
1471    Param.Action=rmfield(Param.Action,'ActionExt');%remove from the recorded xml file to avoid interference during ImportConfig
1472end
1473ActionName=Param.Action.ActionName;
1474ActionPath=Param.Action.ActionPath;
1475path_series=fileparts(which('series'));
1476
1477%% create the Action fct handle if RunMode option = 'local'
1478if strcmp(RunMode,'local')
1479    if ~isequal(ActionPath,path_series)
1480        eval(['spath=which(''' ActionName ''');']) %spath = current path of the selected function ACTION
1481        if ~exist(ActionPath,'dir')
1482            errormsg=['The prescribed function path ' ActionPath ' does not exist'];
1483            return
1484        end
1485        if ~isequal(spath,ActionPath)
1486            addpath(ActionPath)% add the prescribed path if not the current one
1487        end
1488    end
1489    eval(['h_fun=@' ActionName ';'])%create a function handle for ACTION
1490    if ~isequal(ActionPath,path_series)
1491        rmpath(ActionPath)% add the prescribed path if not the current one
1492    end
1493end
1494
1495%% Get  PARAM.xml (not used at this stage)
1496errormsg='';%default error message
1497xmlfile=fullfile(path_series,'PARAM.xml');
1498if ~exist(xmlfile,'file')
1499    [success,message]=copyfile(fullfile(path_series,'PARAM.xml.default'),xmlfile);
1500end
1501if strcmp(ActionExt,'.sh')
1502    if exist(xmlfile,'file')
1503        s=xml2struct(xmlfile);
1504        if strcmp(RunMode,'cluster_oar') && isfield(s,'BatchParam')
1505            if isfield(s.BatchParam,'NbCore')
1506                NbCore=s.BatchParam.NbCore;
1507            end
1508        elseif (strcmp(RunMode,'background')||strcmp(RunMode,'local')) && isfield(s,'RunParam')
1509            if isfield(s.RunParam,'NbCore')
1510                NbCore=s.RunParam.NbCore;
1511            end
1512        end
1513    end
1514end
1515ActionFullName=fullfile(get(handles.ActionPath,'String'),ActionName);
1516
1517%% If a compiled version has been selected (ext .sh) check wether it needs to be recompiled
1518if strcmp(ActionExt,'.sh')
1519    TransformPath='';
1520    if ~isempty(get(handles.ActionExt,'UserData'))
1521        TransformPath=get(handles.ActionExt,'UserData');
1522    end
1523    set(handles.series,'Pointer','watch') % set the mouse pointer to 'watch'
1524    set(handles.ActionExt,'BackgroundColor',[1 1 0])
1525    [mcrmajor, mcrminor] = mcrversion;   
1526    MCRROOT = ['MCRROOT',int2str(mcrmajor),int2str(mcrminor)];
1527    RunTime = getenv(MCRROOT);
1528    ActionNameVersion=[ActionName '_' MCRROOT];
1529    ActionFullName=fullfile(get(handles.ActionPath,'String'),[ActionNameVersion '.sh']);
1530    % compile the .m file if the .sh file does not exist yet
1531    if ~exist(ActionFullName,'file')
1532        answer=msgbox_uvmat('INPUT_Y-N','compiled version has not been created: compile now?');
1533        if strcmp(answer,'Yes')
1534            set(handles.ActionExt,'BackgroundColor',[1 1 0])
1535            path_uvmat=fileparts(which('series'));
1536            currentdir=pwd;
1537            cd(get(handles.ActionPath,'String'))% go to the directory of Action
1538            addpath(path_uvmat)% add the path to uvmat to run the fct 'compile'
1539            compile(ActionName,TransformPath)
1540            cd(currentdir)
1541        else
1542            errormsg='Action launch interrupted';
1543            return
1544        end       
1545    else
1546        sh_file_info=dir(fullfile(get(handles.ActionPath,'String'),[ActionNameVersion '.sh']));
1547        m_file_info=dir(fullfile(get(handles.ActionPath,'String'),[ActionName '.m']));
1548        if isfield(m_file_info,'datenum') && m_file_info.datenum>sh_file_info.datenum
1549            set(handles.ActionExt,'BackgroundColor',[1 1 0])
1550            drawnow
1551            answer=msgbox_uvmat('INPUT_Y-N',[ActionNameVersion '.sh needs to be updated: recompile now?']);
1552            if strcmp(answer,'Yes')
1553                path_uvmat=fileparts(which('series'));
1554                currentdir=pwd;
1555                cd(get(handles.ActionPath,'String'))% go to the directory of Action
1556                addpath(path_uvmat)% add the path to uvmat to run the fct 'compile'
1557                addpath(fullfile(path_uvmat,'transform_field'))% add the path to uvmat to run the fct 'compile'
1558                compile(ActionName,TransformPath)
1559                cd(currentdir)
1560            end
1561        end
1562    end
1563
1564    set(handles.ActionExt,'BackgroundColor',[1 1 1])
1565     set(handles.series,'Pointer','arrow') % set the mouse pointer to 'watch
1566end
1567
1568%% set nbre of cluster cores and processes:
1569% NbCore is the number of computer processors used
1570% NbProcess is the number of independent processes in which the required calculation is split.
1571switch RunMode
1572    case {'local','background'}
1573        NbCore=1;% no need to split the calculation
1574    case 'cluster_oar'
1575        %%%%% TEST A REMETTRE%%%%%
1576 %       if strcmp(ActionExt,'.m')% case of Matlab function (uncompiled)
1577%             NbCore=1;% one core used only (limitation of Matlab licences)
1578%             answer=msgbox_uvmat('INPUT_Y-N','Number of cores =1: select the compiled version .sh for multi-core processing. Proceed with the .m version?');
1579%             if ~strcmp(answer,'Yes')
1580%                 errormsg='Action launch interrupted by user';
1581%                 return
1582%             end
1583%             extra_oar='';
1584 %       else
1585            answer=inputdlg({'Number of cores (max 36)','extra oar options'},'oarsub parameter',1,{'16',''});
1586            if isempty(answer)
1587                                errormsg='Action launch interrupted by user';
1588                return
1589            end
1590            NbCore=str2double(answer{1});
1591            extra_oar=answer{2};
1592 %       end
1593    case 'cluster_pbs'
1594        if strcmp(ActionExt,'.m')% case of Matlab function (uncompiled)
1595            NbCore=1;% one core used only (limitation of Matlab licences)
1596            answer=msgbox_uvmat('INPUT_Y-N','Number of cores =1: select the compiled version .sh for multi-core processing. Proceed with the .m version?');
1597            if ~strcmp(answer,'Yes')
1598                errormsg='Action launch interrupted';
1599                return
1600            end
1601            extra_oar='';
1602        else
1603            answer=inputdlg({'Number of cores (max 36)','extra oar options'},'oarsub parameter',1,{'12',''});
1604            NbCore=str2double(answer{1});
1605            %extra_oar=answer{2};%TODO : fix this for LMFA cluster. Maybe
1606            %extrs_oar and extra_pbs are not the best names
1607        end
1608end
1609if ~isfield(Param.IndexRange,'NbSlice')
1610    Param.IndexRange.NbSlice=[];
1611end
1612
1613%% create the output data directory if needed
1614OutputDir='';
1615if isfield(Param,'OutputSubDir')
1616    SubDirOut=[get(handles.OutputSubDir,'String') Param.OutputDirExt];
1617    SubDirOutNew=SubDirOut;
1618    detect=exist(fullfile(Param.InputTable{1,1},SubDirOutNew),'dir');% test if  the dir  already exist
1619    check_create=1; %need to create the result directory by default
1620    CheckOverwrite=1;
1621    if isfield(Param,'CheckOverwrite')
1622        CheckOverwrite=Param.CheckOverwrite;
1623    end
1624    while detect
1625        if CheckOverwrite
1626            comment=', possibly overwrite previous data';
1627        else
1628            comment=', will complement existing result files (no overwriting)';
1629        end
1630        answer=msgbox_uvmat('INPUT_Y-N-Cancel',['use existing ouput directory: ' fullfile(Param.InputTable{1,1},SubDirOutNew) comment]);
1631        if strcmp(answer,'Cancel')
1632            return
1633        elseif strcmp(answer,'Yes')
1634            detect=0;
1635            check_create=0;
1636        else
1637            r=regexp(SubDirOutNew,'(?<root>.*\D)(?<num1>\d+)$','names');%detect whether name ends by a number
1638            if isempty(r)
1639                r(1).root=[SubDirOutNew '_'];
1640                r(1).num1='0';
1641            end
1642            SubDirOutNew=[r(1).root num2str(str2num(r(1).num1)+1)];%increment the index by 1 or put 1
1643            detect=exist(fullfile(Param.InputTable{1,1},SubDirOutNew),'dir');% test if  the dir  already exists
1644            check_create=1;
1645        end
1646    end
1647    Param.OutputDirExt=regexprep(SubDirOutNew,Param.OutputSubDir,'');
1648    Param.OutputRootFile=Param.InputTable{1,3};% the first sorted RootFile taken for output
1649    set(handles.OutputDirExt,'String',Param.OutputDirExt)
1650    OutputDir=fullfile(Param.InputTable{1,1},[Param.OutputSubDir Param.OutputDirExt]);% full name (with path) of output directory
1651    if check_create    % create output directory if it does not exist
1652        [tild,msg1]=mkdir(OutputDir);
1653        if ~strcmp(msg1,'')
1654            errormsg=['cannot create ' OutputDir ': ' msg1];%error message for directory creation
1655            return
1656        end
1657    end
1658   
1659elseif isfield(Param,'ActionInput')&&isfield(Param.ActionInput,'LogPath')% custom definition of the output dir
1660    OutputDir=Param.ActionInput.LogPath;   
1661end
1662DirXml=fullfile(OutputDir,'0_XML');
1663if ~exist(DirXml,'dir')
1664    [~,msg1]=mkdir(DirXml);
1665    if ~strcmp(msg1,'')
1666        errormsg=['cannot create ' DirXml ': ' msg1];%error message for directory creation
1667        return
1668    end
1669end
1670OutputNomType=nomtype2pair(Param.InputTable{1,4});% nomenclature for output files
1671
1672%% get the set of reference input field indices
1673first_i=1;% first i index to process
1674last_i=1;% last i index to process
1675incr_i=1;% increment step in i index
1676first_j=1;% first j index to process
1677last_j=1;% last j index to process
1678incr_j=1;% increment step in j index
1679if isfield(Param.IndexRange,'first_i')
1680    first_i=Param.IndexRange.first_i;
1681    incr_i=Param.IndexRange.incr_i;
1682    last_i=Param.IndexRange.last_i;
1683end
1684if isfield(Param.IndexRange,'first_j')
1685    first_j=Param.IndexRange.first_j;
1686    last_j=Param.IndexRange.last_j;
1687    incr_j=Param.IndexRange.incr_j;
1688end
1689if last_i < first_i || last_j < first_j
1690    errormsg= 'series/Run_Callback:last field index must be larger or equal to the first one';
1691    return
1692end
1693%incr_i must be defined, =1 by default, if NbSlice is active
1694if isempty(incr_i)&& ~isempty(Param.IndexRange.NbSlice)
1695    incr_i=1;
1696    set(handles.num_incr_i,'String','1')
1697end
1698% case of no increment i defined: processing is done on the available files found in i1_series
1699if isempty(incr_i)
1700    if isempty(incr_j)
1701        [ref_j,ref_i]=find(squeeze(SeriesData.i1_series{1}(1,:,:)));
1702        ref_j=ref_j(ref_j>=first_j & ref_j<=last_j);
1703        ref_i=ref_i(ref_i>=first_i & ref_i<=last_i);
1704        ref_j=ref_j-1;
1705        ref_i=ref_i-1;
1706    else
1707        ref_j=first_j:incr_j:last_j;
1708        [tild,ref_i]=find(squeeze(SeriesData.i1_series{1}(1,:,:)));
1709        ref_i=ref_i-1;
1710        ref_i=ref_i(ref_i>=first_i & ref_i<=last_i);
1711    end
1712    % increment i is defined: processing is done on first_i:incr_i:last_i;
1713else
1714    ref_i=first_i:incr_i:last_i;
1715    if isempty(incr_j)% automatic finding of the existing j indices
1716        [ref_j,tild]=find(squeeze(SeriesData.i1_series{1}(1,:,:)));
1717        ref_j=ref_j-1;
1718        ref_j=ref_j(ref_j>=first_j & ref_j<=last_j);
1719    else
1720        ref_j=first_j:incr_j:last_j;
1721    end
1722end
1723CPUTime=1;% job time estimated at 1 min per iteration (on index i and j) by default
1724if isfield(Param.Action, 'CPUTime') && ~isempty(Param.Action.CPUTime)
1725    CPUTime=Param.Action.CPUTime;%Note: CpUTime for one iteration ref_i has to be multiplied by the number of j indices nbfield_j
1726end
1727nbfield_j=numel(ref_j); % number of j indices
1728BlockLength=numel(ref_i);% by default, job involves the full set of i field indices
1729NbProcess=1;
1730switch RunMode
1731    case {'cluster_oar','cluster_pbs'}
1732        if isempty(Param.IndexRange.NbSlice)% if NbSlice is not defined
1733            BlockLength= ceil(20/(CPUTime*nbfield_j));% short iterations are grouped such that the minimum time of a process is 20 min.
1734            BlockLength=max(BlockLength,ceil(numel(ref_i)/500));% possibly increase the BlockLength to have less than 500 jobs
1735            NbProcess=ceil(numel(ref_i)/BlockLength) ; % nbre of processes sent to oar
1736        else
1737            NbProcess=Param.IndexRange.NbSlice;% the parameter NbSlice sets the nbre of run processes
1738            NbCore=min(NbCore,NbProcess);% reduces the number of cores if it exceeds the number of processes
1739        end
1740    otherwise
1741        if ~isempty(Param.IndexRange.NbSlice)
1742            NbProcess=Param.IndexRange.NbSlice;% the parameter NbSlice sets the nbre of run processes
1743        end
1744end
1745
1746%% record nbre of output files and starting time for computation for status
1747StatusData=get(handles.status,'UserData');
1748if isfield(StatusData,'OutputFileMode')
1749    switch StatusData.OutputFileMode
1750        case 'NbInput'
1751            StatusData.NbOutputFile=numel(ref_i)*nbfield_j;
1752        case 'NbInput_i'
1753            StatusData.NbOutputFile=numel(ref_i);
1754        case 'NbSlice'
1755            StatusData.NbOutputFile=str2num(get(handles.num_NbSlice,'String'));
1756    end
1757end
1758StatusData.TimeStart=now;
1759set(handles.status,'UserData',StatusData)
1760
1761%% case of a function in Python
1762if strcmp(ActionExt, '.py (in dev.)')
1763    fprintf([
1764        '\n' ...
1765        '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n' ...
1766        'The option .py is used. It is still in development.\n' ...
1767        'Do not use it unless you really know what you do!\n' ...
1768        'To try it, first install Pyp and the most recent version of FluidImage.\n' ...
1769        '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'])
1770    RunMode = 'python';
1771end
1772
1773
1774%% direct processing on the current Matlab session or creation of command files
1775filexml=cell(1,NbProcess);% initialisation of the names of the files containing the processing parameters
1776extxml=cell(1,NbProcess); % initialisation of the set of labels used for the files documenting each process
1777for iprocess=1:NbProcess
1778    extxml{iprocess}='.xml';
1779end
1780for iprocess=1:NbProcess
1781    if ~strcmp(get(handles.RUN,'BusyAction'),'queue')% allow for STOP action
1782        disp('program stopped by user')
1783        return
1784    end
1785    if isempty(Param.IndexRange.NbSlice)
1786        Param.IndexRange.first_i=first_i+(iprocess-1)*BlockLength*incr_i;
1787        if Param.IndexRange.first_i>last_i
1788            NbProcess=iprocess-1;% leave the loop, we are at the end of the calculation
1789            break
1790        end
1791        Param.IndexRange.last_i=min(last_i,first_i+(iprocess)*BlockLength*incr_i-1);
1792    else %multislices (then incr_i is not empty)
1793        Param.IndexRange.first_i= first_i+iprocess-1;
1794        Param.IndexRange.incr_i=incr_i*Param.IndexRange.NbSlice;
1795    end
1796    for ilist=1:size(Param.InputTable,1)
1797        Param.InputTable{ilist,1}=regexprep(Param.InputTable{ilist,1},'\','/');%correct path name for PCWIN system
1798    end
1799   
1800    if isfield(Param,'OutputSubDir')
1801        t=struct2xml(Param);
1802        t=set(t,1,'name','Series');
1803        extxml{iprocess}=fullfile_uvmat('','',Param.InputTable{1,3},'.xml',OutputNomType,...
1804            Param.IndexRange.first_i,Param.IndexRange.last_i,first_j,last_j);
1805        filexml{iprocess}=fullfile(OutputDir,'0_XML',extxml{iprocess});
1806        try
1807            save(t, filexml{iprocess});% save the xml file containing the processing parameters
1808        catch ME
1809            if ~strcmp (RunMode,'local')
1810                errormsg=['error writting ' filexml{iprocess} ': ' ME.message];
1811                return
1812            end
1813        end
1814    end
1815    if strcmp (RunMode,'local')
1816        switch ActionExt
1817            case '.m'
1818                h_fun(Param);% direct launching
1819               
1820            case '.sh'
1821                switch computer
1822                    case {'PCWIN','PCWIN64'} %Windows system
1823                        filexml=regexprep(filexml,'\\','\\\\');% add '\' so that '\' are left as characters
1824                        system([ActionFullName ' ' RunTime ' ' filexml{iprocess}]);% TODO: adapt to DOS system
1825                    case {'GLNX86','GLNXA64','MACI64'}%Linux  system
1826                        system([ActionFullName ' ' RunTime ' ' filexml{iprocess}]);
1827                end
1828        end
1829    end
1830end
1831
1832if ~strcmp (RunMode,'local') && ~strcmp(RunMode,'python')
1833    %% processing on a different session of the same computer (background) or cluster, create executable files
1834    batch_file_list=cell(NbProcess,1);% initiate the list of executable files
1835    DirExe=fullfile(OutputDir,'0_EXE');%directory name for executable files
1836    switch computer
1837        case {'PCWIN','PCWIN64'} %Windows system
1838            ExeExt='.bat';
1839        case {'GLNX86','GLNXA64','MACI64'}%Linux  system
1840            ExeExt='.sh';
1841    end
1842    %create subdirectory for executable files
1843    if ~exist(DirExe,'dir')
1844        [tild,msg1]=mkdir(DirExe);
1845        if ~strcmp(msg1,'')
1846            errormsg=['cannot create ' DirExe ': ' msg1];%error message for directory creation
1847            return
1848        end
1849    end
1850    %create subdirectory for log files
1851    DirLog=fullfile(OutputDir,'0_LOG');
1852    if ~exist(DirLog,'dir')
1853        [tild,msg1]=mkdir(DirLog);
1854        if ~strcmp(msg1,'')
1855            errormsg=['cannot create ' DirLog ': ' msg1];%error message for directory creation
1856            return
1857        end
1858    end
1859   
1860    %create the executable file
1861    file_exe_global=fullfile_uvmat('','',Param.InputTable{1,3},ExeExt,OutputNomType,...
1862        first_i,last_i,first_j,last_j);
1863    file_exe_global=fullfile(OutputDir,'0_EXE',file_exe_global);
1864    filelog_global=fullfile_uvmat('','',Param.InputTable{1,3},'.log',OutputNomType,...
1865        first_i,last_i,first_j,last_j);
1866    filelog_global=fullfile(OutputDir,'0_LOG',filelog_global);
1867
1868    for iprocess=1:NbProcess
1869       
1870        %create the executable file
1871       
1872        batch_file_list{iprocess}=fullfile(OutputDir,'0_EXE',regexprep(extxml{iprocess},'.xml$',ExeExt));
1873       
1874        % set the log file name
1875        filelog{iprocess}=fullfile(OutputDir,'0_LOG',regexprep(extxml{iprocess},'.xml$','.log'));
1876       
1877    end
1878end
1879
1880%% launch the executable files for background or cluster processing
1881
1882switch RunMode
1883   
1884    case 'background'
1885        [fid,message]=fopen(file_exe_global,'w');
1886        if isequal(fid,-1)
1887            errormsg=['creation of ' file_exe_global ':' message];
1888            return
1889        end
1890        switch ActionExt
1891            case '.m'% Matlab function
1892                switch computer
1893                    case {'GLNX86','GLNXA64','MACI64'}
1894                        matlab_ver = ver('MATLAB');
1895                        matlab_version = matlab_ver.Version;
1896                        cmd=[...
1897                            '#!/bin/bash \n'...
1898                            'source /etc/profile \n'...
1899                            'module load matlab/''' matlab_version ''' \n'...% CHOICE OF MATLAB VERSION
1900                            'matlab -nodisplay -nosplash -nojvm -logfile ''' filelog_global ''' <<END_MATLAB \n'...
1901                            'addpath(''' path_series '''); \n'...
1902                            'addpath(''' Param.Action.ActionPath '''); \n'];
1903                        for iprocess=1:NbProcess
1904                            cmd=[cmd '' Param.Action.ActionName  '( ''' filexml{iprocess} '''); \n'];
1905                        end
1906                        cmd=[cmd  'exit \n' 'END_MATLAB \n'];
1907                        fprintf(fid,cmd);%fill the executable file with the  char string cmd
1908                        fclose(fid);% close the executable file
1909                        system(['chmod +x ' file_exe_global]);% set the file to executable
1910                    case {'PCWIN','PCWIN64'}
1911                        cmd=['matlab -automation -logfile ' regexprep(filelog{iprocess},'\\','\\\\')...
1912                            ' -r "addpath(''' regexprep(path_series,'\\','\\\\') ''');'...
1913                            'addpath(''' regexprep(Param.Action.ActionPath,'\\','\\\\') ''');'];
1914                        for iprocess=1:NbProcess
1915                            cmd=[cmd '' Param.Action.ActionName  '( ''' regexprep(filexml{iprocess},'\\','\\\\') ''');']
1916                        end
1917                        cmd=[cmd ';exit"'];
1918                        fprintf(fid,cmd);%fill the executable file with the  char string cmd
1919                        fclose(fid);% close the executable file
1920                end
1921                system([file_exe_global ' &'])% directly execute the command file
1922            case '.sh' % compiled Matlab function
1923                for iprocess=1:NbProcess
1924                    switch computer
1925                        case {'GLNX86','GLNXA64','MACI64'}
1926                            [fid,message]=fopen(batch_file_list{iprocess},'w');% create the executable file
1927                            if isequal(fid,-1)
1928                                errormsg=['creation of .bat file: ' message];
1929                                return
1930                            end
1931                            cmd=['#!/bin/bash \n '...
1932                                '#$ -cwd \n '...
1933                                'hostname && date \n '...
1934                                'umask 002 \n'...
1935                                ActionFullName ' ' RunTime ' ' filexml{iprocess}];%allow writting access to created files for user group
1936                            fprintf(fid,cmd);%fill the executable file with the  char string cmd
1937                            fclose(fid);% close the executable file
1938                            system(['chmod +x ' batch_file_list{iprocess}]);% set the file to executable
1939                            system([batch_file_list{iprocess} ' &'])% directly execute the command file
1940                        case {'PCWIN','PCWIN64'}
1941                            msgbox_uvmat('ERROR','option for compiled Matlab functions not implemented for Windows system')
1942                            return
1943                    end
1944                end
1945                msgbox_uvmat('CONFIRMATION',[ActionFullName ' launched in background: press STATUS to see results'])
1946        end
1947       
1948    case 'cluster_oar' % option 'oar-parexec' used
1949        %create subdirectory for oar commands
1950        for iprocess=1:NbProcess
1951            [fid,message]=fopen(batch_file_list{iprocess},'w');% create the executable file
1952            if isequal(fid,-1)
1953                errormsg=['creation of .bat file: ' message];
1954                return
1955            end
1956            if  strcmp(ActionExt,'.sh')
1957                cmd=['#!/bin/bash \n '...
1958                    '#$ -cwd \n '...
1959                    'hostname && date \n '...
1960                    'umask 002 \n'...
1961                    ActionFullName ' ' RunTime ' ' filexml{iprocess}];%allow writting access to created files for user group
1962            else
1963                matlab_ver = ver('MATLAB');
1964                matlab_version = matlab_ver.Version;
1965                cmd=[...
1966                    '#!/bin/bash \n'...
1967                    'source /etc/profile \n'...
1968                    'module load matlab/''' matlab_version ''' \n'...% CHOICE OF MATLAB VERSION
1969                    'matlab -nodisplay -nosplash -nojvm -singleCompThread -logfile ''' filelog{iprocess} ''' <<END_MATLAB \n'...
1970                    'addpath(''' path_series '''); \n'...
1971                    'addpath(''' Param.Action.ActionPath '''); \n'...
1972                    '' Param.Action.ActionName  '( ''' filexml{iprocess} '''); \n'...
1973                    'exit \n'...
1974                    'END_MATLAB \n'];
1975            end
1976            fprintf(fid,cmd);%fill the executable file with the  char string cmd
1977            fclose(fid);% close the executable file
1978            system(['chmod +x ' batch_file_list{iprocess}]);% set the file to executable
1979        end
1980        DirOAR=fullfile(OutputDir,'0_OAR');
1981        if exist(DirOAR,'dir')% delete the content of the dir 0_LOG to allow new input
1982            curdir=pwd;
1983            cd(DirOAR)
1984            delete('*')
1985            cd(curdir)
1986        else
1987            [tild,msg1]=mkdir(DirOAR);
1988            if ~strcmp(msg1,'')
1989                errormsg=['cannot create ' DirOAR ': ' msg1];%error message for directory creation
1990                return
1991            end
1992        end
1993        % create file containing the list of jobs
1994        filename_joblist=fullfile(DirOAR,'job_list.txt');% name of the file containing the list of executables
1995        fid=fopen(filename_joblist,'w');%open it for writting
1996        for iprocess=1:length(batch_file_list)
1997            fprintf(fid,[batch_file_list{iprocess} '\n']);% write list of exe files
1998        end
1999        fclose(fid);
2000        system(['chmod +x ' filename_joblist]);% set the file to executable
2001       
2002        filename_log=fullfile(DirLog,'job_list.stdout');%file for output messages of the master oar process
2003        filename_errors=fullfile(DirLog,'job_list.stderr');%file for error messages of the master oar process
2004        % the command job_list.txt contains the list of NbProcess independent individual jobs
2005        % in which the total calculation has been split. Those are written as executable files .sh in the folder /O_EXE.
2006        %  These individual jobs are grouped by the system as oar jobs on the NbCore processors.
2007        %  For each processor, the oar job must stop after the walltime which has been set, which is limited to 24 h.
2008        %  However, the oar job is automatically restarted (option 'idempotent') provided the individual jobs are
2009        % shorter than the wall time: in the time interval 'checkpoint' (WallTimeOneJob) before the end of the allowed duration,
2010        %  the oar job restarts when an individual job ends.
2011        JobTime=CPUTime*BlockLength*nbfield_j;% estimated time for one individual job (in minutes)
2012        % wall time (in hours ) for each oar job, allowing 10 individual jobs, but limited to 23 h:
2013        WallTimeTotal=min(23,4*JobTime/60);
2014        %disp(['WallTimeTotal: ' num2str(WallTimeTotal) ' hours'])
2015        % estimated time of an individual job (in min), with a margin of error
2016        WallTimeOneJob=min(4*JobTime+10,WallTimeTotal*60/2);% estimated max time of an individual job for checkpoint
2017        disp(['WallTimeOneJob: ' num2str(WallTimeOneJob) ' minutes'])
2018        oar_command=['oarsub -n UVmat_' ActionFullName ' '...
2019            '-t idempotent --checkpoint ' num2str(WallTimeOneJob*60) ' '...
2020            '-l /core=' num2str(NbCore) ','...
2021            'walltime=' datestr(WallTimeTotal/24,13) ' '...
2022            '-E ' filename_errors ' '...
2023            '-O ' filename_log ' '...
2024            extra_oar ' '...
2025            '"oar-parexec -s -f ' filename_joblist ' '...
2026            '-l ' filename_joblist '.log"'];
2027       
2028        fprintf(oar_command);% display  system command on the Matlab command window
2029        [status,result]=system(oar_command)% execute system command and show the result (ID number of the launched job) on the Matlab command window
2030        filename_oarcommand=fullfile(DirOAR,'0_oar_command');% keep track of the command in file '0-OAR/0_oar_command'
2031        fid=fopen(filename_oarcommand,'w');
2032        fprintf(fid,oar_command); % store the command
2033        fprintf(fid,result);% store the result (job ID number)
2034        fclose(fid);
2035        msgbox_uvmat('CONFIRMATION',[ActionFullName ' launched as  ' num2str(NbProcess) ' processes in cluster: press STATUS to see results'])
2036       
2037    case 'cluster_pbs' % for LMFA Kepler machine
2038        %create subdirectory for pbs command and log files
2039        DirPBS=fullfile(OutputDir,'0_PBS'); %todo : common name OAR/PBS
2040        if exist(DirPBS,'dir')% delete the content of the dir 0_LOG to allow new input
2041            curdir=pwd;
2042            cd(DirPBS)
2043            delete('*')
2044            cd(curdir)
2045        else
2046            [tild,msg1]=mkdir(DirPBS);
2047            if ~strcmp(msg1,'')
2048                errormsg=['cannot create ' DirPBS ': ' msg1];%error message for directory creation
2049                return
2050            end
2051        end
2052        max_walltime=3600*20; % 20h max total calculation (cannot exceed 24 h)
2053        walltime_onejob=1800; % seconds, max estimated time for asingle file index value
2054        filename_joblist=fullfile(DirPBS,'job_list.txt');%create name of the global executable file
2055        fid=fopen(filename_joblist,'w');
2056        for iprocess=1:length(batch_file_list)
2057            fprintf(fid,[batch_file_list{iprocess} '\n']);% list of exe files
2058        end
2059        fclose(fid);
2060        system(['chmod +x ' filename_joblist]);% set the file to executable
2061        pbs_command=['qstat -n CIVX '...
2062            '-t idempotent --checkpoint ' num2str(walltime_onejob+60) ' '...
2063            '-l /core=' num2str(NbCore) ','...
2064            'walltime=' datestr(min(1.05*walltime_onejob/86400*max(NbProcess*BlockLength*nbfield_j,NbCore)/NbCore,max_walltime/86400),13) ' '...
2065            '-E ' regexprep(filename_joblist,'\.txt\>','.stderr') ' '...
2066            '-O ' regexprep(filename_joblist,'\.txt\>','.log') ' '...
2067            extra_oar ' '...
2068            '"oar-parexec -s -f ' filename_joblist ' '...
2069            '-l ' filename_joblist '.log"'];
2070        filename_oarcommand=fullfile(DirPBS,'pbs_command');
2071        fid=fopen(filename_oarcommand,'w');
2072        fprintf(fid,pbs_command);
2073        fclose(fid);
2074        fprintf(pbs_command);% display in command line
2075        %system(pbs_command);
2076        msgbox_uvmat('CONFIRMATION',[ActionFullName ' command ready to be launched in cluster'])
2077    case 'python'
2078        command = [
2079            'LD_LIBRARY_PATH=$(echo $LD_LIBRARY_PATH | pyp "p.split('':'') | [s for s in p if ''matlab'' not in s] | '':''.join(p)") ' ...
2080            'python -m fluidimage.run_from_xml ' filexml{iprocess}];
2081        % fprintf(['command:\n' command '\n\n'])
2082        system(command, '-echo');
2083end
2084if exist(OutputDir,'dir')
2085    [SUCCESS,MESSAGE,MESSAGEID] = fileattrib (OutputDir)
2086    if MESSAGE.GroupWrite~=1
2087    [success,msg] = fileattrib(OutputDir,'+w','g','s');% allow writing access for the group of users, recursively in the folder
2088    if success==0
2089        msgbox_uvmat('WARNING',{['unable to set group write access to ' OutputDir ':']; msg});%error message for directory creation
2090    end
2091    end
2092end
2093
2094%------------------------------------------------------------------------
2095function STOP_Callback(hObject, eventdata, handles)
2096%------------------------------------------------------------------------
2097set(handles.RUN, 'BusyAction','cancel')
2098set(handles.RUN,'BackgroundColor',[1 0 0])
2099set(handles.RUN,'enable','on')
2100set(handles.RUN, 'Value',0)
2101
2102%------------------------------------------------------------------------
2103% --- read parameters from the GUI series
2104%------------------------------------------------------------------------
2105function Param=read_GUI_series(handles)
2106
2107%% read raw parameters from the GUI series
2108Param=read_GUI(handles.series);
2109
2110%% clean the output structure by removing unused information
2111if isfield(Param,'Pairs')
2112    Param=rmfield(Param,'Pairs'); %info Pairs not needed for output
2113end
2114if isfield(Param,'InputLine')
2115    Param=rmfield(Param,'InputLine');
2116end
2117if isfield(Param,'EditObject')
2118    Param=rmfield(Param,'EditObject');
2119end
2120Param.IndexRange.TimeSource=Param.IndexRange.TimeTable{end,1};
2121Param.IndexRange=rmfield(Param.IndexRange,'TimeTable');
2122empty_line=false(size(Param.InputTable,1),1);
2123for iline=1:size(Param.InputTable,1)
2124    empty_line(iline)=isempty(cell2mat(Param.InputTable(iline,1:3)));
2125end
2126Param.InputTable(empty_line,:)=[];
2127
2128%------------------------------------------------------------------------
2129% --- Executes on selection change in ActionName.
2130function ActionName_Callback(hObject, eventdata, handles)
2131%------------------------------------------------------------------------
2132
2133%% stop any ongoing series processing
2134if isequal(get(handles.RUN,'Value'),1)
2135    answer= msgbox_uvmat('INPUT_Y-N','stop current Action process?');
2136    if strcmp(answer,'Yes')
2137        STOP_Callback(hObject, eventdata, handles)
2138    else
2139        return
2140    end
2141end
2142set(handles.ActionName,'BackgroundColor',[1 1 0])
2143huigetfile=findobj(allchild(0),'tag','status_display');
2144if ~isempty(huigetfile)
2145    delete(huigetfile)
2146end
2147drawnow
2148
2149%% get Action name and path
2150NbBuiltinAction=get(handles.Action,'UserData'); %nbre of functions initially proposed in the menu ActionName (as defined in the Opening fct of series)
2151ActionList=get(handles.ActionName,'String');% list menu fields
2152ActionIndex=get(handles.ActionName,'Value');
2153if ~isequal(ActionIndex,1)% if we are not just opening series
2154    InputTable=get(handles.InputTable,'Data');
2155    if isempty(InputTable{1,4})
2156        msgbox_uvmat('ERROR','no input file available: use Open in the menu bar')
2157        return
2158    end
2159end
2160ActionName= ActionList{get(handles.ActionName,'Value')}; % selected function name
2161ActionPathList=get(handles.ActionName,'UserData');%list of recorded paths to functions of the list ActionName
2162
2163%% add a new function to the menu if 'more...' has been selected in the menu ActionName
2164if isequal(ActionName,'more...')
2165    [FileName, PathName] = uigetfile( ...
2166        {'*.m', ' (*.m)';
2167        '*.m',  '.m files '; ...
2168        '*.*', 'All Files (*.*)'}, ...
2169        'Pick a series processing function ',get(handles.ActionPath,'String'));
2170    if length(FileName)<2
2171        return
2172    end
2173    [tild,ActionName,ActionExt]=fileparts(FileName);
2174   
2175    % insert the choice in the menu ActionName
2176    ActionIndex=find(strcmp(ActionName,ActionList),1);% look for the selected function in the menu Action
2177    PathName=regexprep(PathName,'/$','');
2178    if ~isempty(ActionIndex) && ~strcmp(ActionPathList{ActionIndex},PathName)%compare the path to the existing fct
2179        ActionIndex=[]; % the selected path is different than the recorded one
2180    end
2181    if isempty(ActionIndex)%the qselected fct (with selected path) does not exist in the menu
2182        ActionIndex= length(ActionList);
2183        ActionList=[ActionList(1:end-1);{ActionName};ActionList(end)];% the selected function is appended in the menu, before the last item 'more...'
2184         ActionPathList=[ActionPathList; PathName];
2185    end
2186   
2187    % record the file extension and extend the path list if it is a new extension
2188    ActionExtList=get(handles.ActionExt,'String');
2189    ActionExtIndex=find(strcmp(ActionExt,ActionExtList), 1);
2190    if isempty(ActionExtIndex)
2191        set(handles.ActionExt,'String',[ActionExtList;{ActionExt}])
2192    end
2193
2194    % remove old Action options in the menu (keeping a menu length <nb_builtin_ACTION+5)
2195    if length(ActionList)>NbBuiltinAction+5; %nb_builtin_ACTION=nbre of functions always remaining in the initial menu
2196        nbremove=length(ActionList)-NbBuiltinAction-5;
2197        ActionList(NbBuiltinAction+1:end-5)=[];
2198        ActionPathList(NbBuiltinAction+1:end-4,:)=[];
2199        ActionIndex=ActionIndex-nbremove;
2200    end
2201   
2202    % record action menu, choice and path
2203    set(handles.ActionName,'Value',ActionIndex)
2204    set(handles.ActionName,'String',ActionList)
2205       set(handles.ActionName,'UserData',ActionPathList);
2206    set(handles.ActionExt,'Value',ActionExtIndex)
2207       
2208    %record the user defined menu additions in personal file profil_perso
2209    dir_perso=prefdir;
2210    profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
2211    if NbBuiltinAction+1<=numel(ActionList)-1
2212        ActionListUser=ActionList(NbBuiltinAction+1:numel(ActionList)-1);
2213        ActionPathListUser=ActionPathList(NbBuiltinAction+1:numel(ActionList)-1);
2214        ActionExtListUser={};
2215        if numel(ActionExtList)>2
2216            ActionExtListUser=ActionExtList(3:end);
2217        end
2218        if exist(profil_perso,'file')
2219            save(profil_perso,'ActionListUser','ActionPathListUser','ActionExtListUser','-append')
2220        else
2221            save(profil_perso,'ActionListUser','ActionPathListUser','ActionExtListUser','-V6')
2222        end
2223    end
2224end
2225
2226%% check the current ActionPath to the selected function
2227ActionPath=ActionPathList{ActionIndex};%current recorded path
2228set(handles.ActionPath,'String',ActionPath); %show the path to the senlected function
2229
2230%% reinitialise the waitbar
2231update_waitbar(handles.Waitbar,0)
2232
2233%% create the function handle for Action
2234if ~exist(ActionPath,'dir')
2235    msgbox_uvmat('ERROR',['The prescribed function path ' ActionPath ' does not exist']);
2236    return
2237end
2238current_dir=pwd;%current working dir
2239cd(ActionPath)
2240h_fun=str2func(ActionName);
2241cd(current_dir)
2242
2243%
2244% checkaddpath=0;
2245% path_series=which('series');
2246% %eval(['spath=which(''' ActionName ''');']) %spath = current path of the selected function ACTION
2247% spath=fileparts(which(ActionName)); %spath = current path of the selected function ACTION
2248% if ~exist(ActionPath,'dir')
2249%     msgbox_uvmat('ERROR',['The prescribed function path ' ActionPath ' does not exist']);
2250%     return
2251% end
2252% if ~strcmp(spath,ActionPath)
2253%     if strcmp(pwd,spath)
2254%         msgbox_uvmat('ERROR',[ 'a function called ' ActionName ' on your working space oversets the selected one']);
2255%         return
2256%     else
2257%         addpath(ActionPath)% add the prescribed path if not the current one
2258%         checkaddpath=1;
2259%     end
2260% end
2261% eval(['h_fun=@' ActionName ';'])%create a function handle for ACTION
2262% if checkaddpath && ~isequal(ActionPath,path_series)
2263%     rmpath(ActionPath)% add the prescribed path if not the current one
2264% end
2265
2266%% Activate the Action fct to adapt the configuration of the GUI series and bring specific parameters in SeriesData
2267Param=read_GUI_series(handles);% read the parameters from the GUI series
2268ParamOut=h_fun(Param);%run the selected Action function to get the relevant input
2269
2270%% Put the first line of the selected Action fct as tooltip help
2271try
2272    [fid,errormsg] =fopen([ActionName '.m']);
2273    InputText=textscan(fid,'%s',1,'delimiter','\n');
2274    fclose(fid);
2275    set(handles.ActionName,'ToolTipString',InputText{1}{1})% put the first line of the selected function as tooltip help
2276end
2277
2278
2279%% Visibility of VelType and VelType_1 menus asked by ActionName
2280VelTypeRequest=1;%VelType requested by default
2281VelTypeRequest_1=1;%VelType requested by default
2282if isfield(ParamOut,'VelType')
2283    VelTypeRequest=ismember(ParamOut.VelType,{'on','one','two'});
2284    VelTypeRequest_1=strcmp( ParamOut.VelType,'two');
2285end
2286FieldNameRequest=0;  %hidden by default
2287FieldNameRequest_1=0;  %hidden by default
2288if isfield(ParamOut,'FieldName')
2289    FieldNameRequest=ismember(ParamOut.FieldName,{'on','one','two'});
2290    FieldNameRequest_1=strcmp( ParamOut.FieldName,'two');
2291end
2292
2293%% Detect the types of input files and set menus and default options in 'VelType'
2294SeriesData=get(handles.series,'UserData');% info on the input file series
2295iview_civ=find(strcmp('civx',SeriesData.FileType)|strcmp('civdata',SeriesData.FileType));
2296iview_netcdf=find(strcmp('netcdf',SeriesData.FileType)|strcmp('civx',SeriesData.FileType)|strcmp('civdata',SeriesData.FileType));% all nc files, icluding civ
2297FieldList=get(handles.FieldName,'String');% previous list as default
2298if ~iscell(FieldList),FieldList={FieldList};end
2299FieldList_1=get(handles.FieldName_1,'String');% previous list as default
2300if ~iscell(FieldList_1),FieldList_1={FieldList_1};end
2301%CheckList=0;% indicate whether FieldName has been updated
2302CheckList_1=1;% indicate whether FieldName_1 has been updated
2303handles_coord=[handles.Coord_x handles.Coord_y handles.Coord_z handles.Coord_x_title handles.Coord_y_title handles.Coord_z_title];
2304if VelTypeRequest && numel(iview_civ)>=1
2305    menu=set_veltype_display(SeriesData.FileInfo{iview_civ(1)}.CivStage,SeriesData.FileType{iview_civ(1)});
2306    set(handles.VelType,'Value',1)% set first choice by default
2307    set(handles.VelType,'String',[{'*'};menu])
2308    set(handles.VelType,'Visible','on')
2309    set(handles.VelType_title,'Visible','on')
2310    FieldList=[set_field_list('U','V');{'C'};{'get_field...'}];%standard menu for civx data
2311    %CheckList=1;
2312    set(handles.FieldName,'Value',1); %velocity vector choice by default
2313    if  VelTypeRequest_1 && numel(iview_civ)>=2
2314        menu=set_veltype_display(SeriesData.FileInfo{iview_civ(2)}.CivStage,SeriesData.FileType{iview_civ(2)});
2315        set(handles.VelType_1,'Value',1)% set first choice by default
2316        set(handles.VelType_1,'String',[{'*'};menu])
2317        set(handles.VelType_1,'Visible','on')
2318        set(handles.VelType_title_1,'Visible','on')
2319        FieldList_1=[set_field_list('U','V');{'C'};{'get_field...'}];%standard menu for civx data
2320        CheckList_1=1;
2321        set(handles.FieldName_1,'Value',1); %velocity vector choice by default
2322    else
2323        set(handles.VelType_1,'Visible','off')
2324        set(handles.VelType_title_1,'Visible','off')
2325    end
2326else
2327    set(handles.VelType,'Visible','off')
2328    set(handles.VelType_title,'Visible','off')
2329end
2330
2331%% Detect the types of input files and set menus and default options in 'FieldName'
2332if (FieldNameRequest || VelTypeRequest) && numel(iview_netcdf)>=1
2333    set(handles.InputFields,'Visible','on')% set the frame InputFields visible
2334    if FieldNameRequest && isfield(SeriesData.FileInfo{iview_netcdf(1)},'ListVarName')
2335        set(handles.FieldName,'Visible','on')
2336        ListVarName=SeriesData.FileInfo{iview_netcdf(1)}.ListVarName;
2337        ind_var=get(handles.FieldName,'Value');%indices of previously selected variables
2338        for ilist=1:numel(ind_var)
2339            if isempty(find(strcmp(FieldList{ind_var(ilist)},ListVarName)))
2340                FieldList={};% previous choice not consistent with new input field
2341                set(handles.FieldName,'Value',1)
2342                break
2343            end
2344        end
2345        if ~isempty(FieldList)
2346            if isempty(find(strcmp(get(handles.Coord_x,'String'),ListVarName)))||...
2347                    isempty(find(strcmp(get(handles.Coord_y,'String'),ListVarName)))
2348                FieldList={};
2349                set(handles.Coord_x,'String','')
2350                set(handles.Coord_y,'String','')
2351            end
2352            Coord_z=get(handles.Coord_z,'String');
2353            if ~isempty(Coord_z) && isempty(find(strcmp(Coord_z,ListVarName)))
2354                FieldList={};
2355                set(handles.Coord_z,'String','')
2356            end
2357        end
2358    end
2359   
2360    set(handles_coord,'Visible','on')
2361    FieldList=[FieldList;{'get_field...'}];
2362    if FieldNameRequest_1 && numel(iview_netcdf)>=2
2363        set(handles.FieldName_1,'Visible','on')
2364        if CheckList_1==0        % not civ input made
2365            ListVarName=SeriesData.FileInfo{iview_netcdf(2)}.ListVarName;
2366            ind_var=get(handles.FieldName,'Value');%indices of previously selected variables
2367            for ilist=1:numel(ind_var)
2368                if isempty(find(strcmp(FieldList{ind_var(ilist)},ListVarName)))
2369                    FieldList_1={};% previous choice not consistent with new input field
2370                    set(handles.FieldName_1,'Value',1)
2371                    break
2372                end
2373            end
2374            warn_coord=0;
2375            if isempty(find(strcmp(get(handles.Coord_x,'String'),ListVarName)))||...
2376                    isempty(find(strcmp(get(handles.Coord_y,'String'),ListVarName)))
2377                warn_coord=1;
2378            end
2379            if ~isempty(Coord_z) && isempty(find(strcmp(Coord_z,ListVarName)))
2380                FieldList_1={};
2381                warn_coord=1;
2382            end
2383            if warn_coord
2384                msgbox_uvmat('WARNING','coordiante names do not exist in the second netcdf input file')
2385            end
2386           
2387            set(handles.FieldName_1,'Visible','on')
2388            set(handles.FieldName_1,'Value',1)
2389            set(handles.FieldName_1,'String',FieldList_1)
2390        end
2391    else
2392        set(handles.FieldName_1,'Visible','off')
2393    end
2394    if isempty(FieldList)
2395        set(handles.FieldName,'Visible','off')
2396    else
2397        set(handles.FieldName,'Visible','on')
2398        set(handles.FieldName,'String',FieldList)
2399    end
2400else
2401    set(handles.InputFields,'Visible','off')
2402end
2403
2404%% Introduce visibility of file overwrite option
2405if isfield(ParamOut,'CheckOverwriteVisible')&& strcmp(ParamOut.CheckOverwriteVisible,'on')
2406    set(handles.CheckOverwrite,'Visible','on')
2407else
2408    set(handles.CheckOverwrite,'Visible','off')
2409end
2410
2411%% Check whether alphabetical sorting of input Subdir is allowed by the Action fct  (for multiples series entries)
2412if isfield(ParamOut,'AllowInputSort')&&isequal(ParamOut.AllowInputSort,'on')&& size(Param.InputTable,1)>1
2413    [tild,iview]=sort(InputTable(:,2)); %subdirectories sorted in alphabetical order
2414    set(handles.InputTable,'Data',InputTable(iview,:));
2415    MinIndex_i=get(handles.MinIndex_i,'Data');
2416    MinIndex_j=get(handles.MinIndex_j,'Data');
2417    MaxIndex_i=get(handles.MaxIndex_i,'Data');
2418    MaxIndex_j=get(handles.MaxIndex_j,'Data');
2419    set(handles.MinIndex_i,'Data',MinIndex_i(iview,:));
2420    set(handles.MinIndex_j,'Data',MinIndex_j(iview,:));
2421    set(handles.MaxIndex_i,'Data',MaxIndex_i(iview,:));
2422    set(handles.MaxIndex_j,'Data',MaxIndex_j(iview,:));
2423    TimeTable=get(handles.TimeTable,'Data');
2424    set(handles.TimeTable,'Data',TimeTable(iview,:));
2425    PairString=get(handles.PairString,'Data');
2426    set(handles.PairString,'Data',PairString(iview,:));
2427end
2428
2429%% Impose the whole input file index range if requested
2430if isfield(ParamOut,'WholeIndexRange')&&isequal(ParamOut.WholeIndexRange,'on')
2431    MinIndex_i=get(handles.MinIndex_i,'Data');
2432    MinIndex_j=get(handles.MinIndex_j,'Data');
2433    MaxIndex_i=get(handles.MaxIndex_i,'Data');
2434    MaxIndex_j=get(handles.MaxIndex_j,'Data');
2435    set(handles.num_first_i,'String',num2str(MinIndex_i(1)))% set first as the min index (for the first line)
2436    set(handles.num_last_i,'String',num2str(MaxIndex_i(1)))% set last as the max index (for the first line)
2437    set(handles.num_incr_i,'String','1')
2438    set(handles.num_first_j,'String',num2str(MinIndex_j(1)))% set first as the min index (for the first line)
2439    set(handles.num_last_j,'String',num2str(MaxIndex_j(1)))% set last as the max index (for the first line)
2440    set(handles.num_incr_j,'String','1')
2441else  % check index ranges
2442    first_i=1;last_i=1;first_j=1;last_j=1;
2443    if isfield(Param.IndexRange,'first_i')
2444        first_i=Param.IndexRange.first_i;
2445        last_i=Param.IndexRange.last_i;
2446    end
2447    if isfield(Param.IndexRange,'first_j')
2448        first_j=Param.IndexRange.first_j;
2449        last_j=Param.IndexRange.last_j;
2450    end
2451    if last_i < first_i || last_j < first_j , msgbox_uvmat('ERROR','last field number must be larger than the first one'),...
2452            set(handles.RUN, 'Enable','On'), set(handles.RUN,'BackgroundColor',[1 0 0]),return,end;
2453end
2454
2455%% enable or desable j index visibility
2456status_j='on';%default
2457if isfield(ParamOut,'Desable_j_index')&&isequal(ParamOut.Desable_j_index,'on')
2458    status_j='off';
2459end
2460if isempty(find(~cellfun(@isempty,SeriesData.j1_series), 1)); % case of empty j indices
2461    status_j='off'; % no j index needed
2462elseif strcmp(get(handles.PairString,'Visible'),'on')
2463    check_burst=cellfun(@isempty,regexp(get(handles.PairString,'Data'),'^j'));%=0 for burst case, 1 otherwise
2464    if isempty(find(check_burst, 1))% if all pair string begins by j (burst)
2465        status_j='off'; % no j index needed for bust case
2466    end
2467end
2468enable_j(handles,status_j) % no j index needed
2469
2470
2471%% NbSlice visibility
2472%NbSliceVisible='off';%default
2473if isfield(ParamOut,'NbSlice') && (strcmp(ParamOut.NbSlice,'on')||isnumeric(ParamOut.NbSlice))
2474    set(handles.num_NbSlice,'Visible','on')
2475    set(handles.NbSlice_title,'Visible','on')
2476else
2477    set(handles.num_NbSlice,'Visible','off')
2478    set(handles.NbSlice_title,'Visible','off')
2479    %     set(handles.num_NbProcess,'String',get(handles.num_NbSlice,'String'))% the nbre of processes is imposed as the nbre of slices
2480    % else
2481    %     set(handles.num_NbProcess,'String','')% free nbre of processes
2482end
2483if isnumeric(ParamOut.NbSlice)
2484    set(handles.num_NbSlice,'String',num2str(ParamOut.NbSlice))
2485    set(handles.num_NbSlice,'Enable','off'); % NbSlice set by the activation of the Action function
2486else
2487    set(handles.num_NbSlice,'Enable','on'); % NbSlice can be modified on the GUI series
2488end
2489% set(handles.num_NbSlice,'Visible',NbSliceVisible)
2490% set(handles.NbSlice_title,'Visible',NbSliceVisible)
2491
2492
2493
2494%% Visibility of FieldTransform menu
2495FieldTransformVisible='off';  %hidden by default
2496if isfield(ParamOut,'FieldTransform')
2497    FieldTransformVisible=ParamOut.FieldTransform; 
2498    TransformName_Callback([],[], handles)
2499end
2500set(handles.FieldTransform,'Visible',FieldTransformVisible)
2501if isfield(ParamOut,'TransformPath')
2502    set(handles.ActionExt,'UserData',ParamOut.TransformPath)
2503else
2504    set(handles.ActionExt,'UserData',[])
2505end
2506
2507%% Visibility of projection object
2508ProjObjectVisible='off';  %hidden by default
2509if isfield(ParamOut,'ProjObject')
2510    ProjObjectVisible=ParamOut.ProjObject;
2511end
2512set(handles.CheckObject,'Visible',ProjObjectVisible)
2513if ~get(handles.CheckObject,'Value')
2514    ProjObjectVisible='off';
2515end
2516set(handles.ProjObject,'Visible',ProjObjectVisible)
2517set(handles.DeleteObject,'Visible',ProjObjectVisible)
2518set(handles.ViewObject,'Visible',ProjObjectVisible)
2519set(handles.EditObject,'Visible',ProjObjectVisible)
2520
2521%% Visibility of mask input
2522MaskVisible='off';  %hidden by default
2523if isfield(ParamOut,'Mask')
2524    MaskVisible=ParamOut.Mask;
2525end
2526set(handles.CheckMask,'Visible',MaskVisible);
2527
2528%% definition of the directory containing the output files
2529if  ~(isfield(SeriesData,'ActionName') && strcmp(ActionName,SeriesData.ActionName))
2530    OutputDirExt='.series'; %default
2531    if isfield(ParamOut,'OutputDirExt')&&~isempty(ParamOut.OutputDirExt)
2532        OutputDirExt=ParamOut.OutputDirExt;
2533    end
2534    set(handles.OutputDirExt,'String',OutputDirExt)
2535end
2536OutputDirVisible='off';
2537OutputSubDirMode='auto';%default
2538SubDirOut='';
2539if isfield(ParamOut,'OutputSubDirMode')
2540    OutputSubDirMode=ParamOut.OutputSubDirMode;
2541end
2542switch OutputSubDirMode
2543    case 'auto';%default
2544        OutputDirVisible='on';
2545        SubDir=InputTable(1:end,2); %set of subdirectories
2546        SubDirOut=SubDir{1};
2547        if numel(SubDir)>1
2548            for ilist=2:numel(SubDir)
2549                SubDirOut=[SubDirOut '-' regexprep(SubDir{ilist},'^/','')];
2550            end
2551        end
2552    case 'one'
2553        OutputDirVisible='on';
2554        SubDirOut=InputTable{1,2}; %use the first subdir name (+OutputDirExt) as output  subdirectory
2555    case 'two'
2556        OutputDirVisible='on';   
2557        SubDir=InputTable(1:2,2); %set of subdirectories
2558        SubDirOut=SubDir{1};
2559        if numel(SubDir)>1
2560                SubDirOut=[SubDirOut '-' regexprep(SubDir{2},'^/','')];
2561        end
2562    case 'last'
2563        OutputDirVisible='on';
2564        SubDirOut=InputTable{end,2}; %use the last subdir name (+OutputDirExt) as output  subdirectory
2565end
2566set(handles.OutputSubDir,'String',SubDirOut)
2567set(handles.OutputSubDir,'BackgroundColor',[1 1 1])% set edit box to white color to indicate refreshment
2568set(handles.OutputDirExt,'Visible',OutputDirVisible)
2569set(handles.OutputSubDir,'Visible',OutputDirVisible)
2570%set(handles.CheckOverwrite,'Visible',OutputDirVisible)
2571set(handles.OutputDir_title,'Visible',OutputDirVisible)
2572SeriesData.ActionName=ActionName;%record ActionName for next use
2573
2574
2575%% visibility of the run mode (local or background or cluster)
2576if strcmp(OutputSubDirMode,'none')
2577    RunModeVisible='off';% only local mode available if no output file is produced
2578else
2579    RunModeVisible='on';
2580end
2581set(handles.RunMode,'Visible',RunModeVisible)
2582set(handles.ActionExt,'Visible',RunModeVisible)
2583set(handles.RunMode_title,'Visible',RunModeVisible)
2584set(handles.ActionExt_title,'Visible',RunModeVisible)
2585
2586
2587%% Expected nbre of output files
2588if isfield(ParamOut,'OutputFileMode')
2589    StatusData.OutputFileMode=ParamOut.OutputFileMode;
2590    set(handles.status,'UserData',StatusData)
2591end
2592
2593%% definition of an additional parameter set, determined by an ancillary GUI
2594if isfield(ParamOut,'ActionInput')
2595    set(handles.ActionInput,'Visible','on')
2596    ParamOut.ActionInput.Program=ActionName; % record the program in ActionInput
2597    SeriesData.ActionInput=ParamOut.ActionInput;
2598else
2599    set(handles.ActionInput,'Visible','off')
2600    if isfield(SeriesData,'ActionInput')
2601        SeriesData=rmfield(SeriesData,'ActionInput');
2602    end
2603end
2604set(handles.series,'UserData',SeriesData)
2605set(handles.ActionName,'BackgroundColor',[1 1 1])
2606
2607%------------------------------------------------------------------------
2608% --- Executes on selection change in FieldName.
2609function FieldName_Callback(hObject, eventdata, handles)
2610%------------------------------------------------------------------------
2611field_str=get(handles.FieldName,'String');
2612field_index=get(handles.FieldName,'Value');
2613field=field_str{field_index(1)};
2614if isequal(field,'get_field...')
2615    SeriesData=get(handles.series,'UserData');
2616    % input line for which the field choice is relevant
2617    iview=find(ismember(SeriesData.FileType,{'netcdf','civx','civdata'}));% all nc files, icluding civ
2618    hget_field=findobj(allchild(0),'name','get_field');
2619    if ~isempty(hget_field)
2620        delete(hget_field)%delete opened versions of get_field
2621    end
2622    Param=read_GUI(handles.series);
2623    InputTable=Param.InputTable(iview,:);
2624    % check the existence of the first file in the series
2625    first_j=[];last_j=[];MinIndex_j=1;MaxIndex_j=1;%default setting for index j
2626    if isfield(Param.IndexRange,'first_j');% if index j is used     
2627        first_j=Param.IndexRange.first_j;
2628        last_j=Param.IndexRange.last_j;
2629        MinIndex_j=Param.IndexRange.MinIndex_j(iview);
2630        MaxIndex_j=Param.IndexRange.MaxIndex_j(iview);
2631    end
2632    PairString='';
2633    if isfield(Param.IndexRange,'PairString'); PairString=Param.IndexRange.PairString{iview}; end
2634    [i1,i2,j1,j2] = get_file_index(Param.IndexRange.first_i,first_j,PairString);
2635    LineIndex=iview(1);
2636    if numel(iview)>1     
2637        answer=msgbox_uvmat('INPUT_TXT',['select the line of the input table:' num2str(iview)] ,num2str(iview(1)));
2638        LineIndex=str2num(answer);
2639%         InputLine=str2num(get(handles.InputLine,'String'));
2640%         if ismember(InputLine,iview)
2641%             LineIndex=InputLine;
2642%         end
2643    end
2644    FirstFileName=fullfile_uvmat(InputTable{LineIndex,1},InputTable{LineIndex,2},InputTable{LineIndex,3},...
2645        InputTable{LineIndex,5},InputTable{LineIndex,4},i1,i2,j1,j2);
2646    if exist(FirstFileName,'file')
2647        ParamIn.Title='get_field: pick input variables and coordinates for series processing';
2648        ParamIn.SeriesInput=1;
2649        GetFieldData=get_field(FirstFileName,ParamIn);
2650        FieldList={};
2651        if isfield(GetFieldData,'FieldOption')% if a field has been selected
2652        switch GetFieldData.FieldOption
2653            case 'vectors'
2654                UName=GetFieldData.PanelVectors.vector_x;
2655                VName=GetFieldData.PanelVectors.vector_y;
2656                YName={GetFieldData.Coordinates.Coord_y};
2657                FieldList={['vec(' UName ',' VName ')'];...
2658                    ['norm(' UName ',' VName ')'];...
2659                    UName;VName};
2660            case {'scalar'}
2661                FieldList=GetFieldData.PanelScalar.scalar;
2662                YName={GetFieldData.Coordinates.Coord_y};
2663                if ischar(FieldList)
2664                    FieldList={FieldList};
2665                end
2666            case 'civdata...'
2667                FieldList=[set_field_list('U','V') ;{'C'}];
2668                set(handles.FieldName,'Value',1) % set menu to 'velocity
2669                XName='X';
2670                YName='y';
2671        end
2672        set(handles.FieldName,'Value',1)
2673        set(handles.FieldName,'String',[FieldList; {'get_field...'}]);
2674        if ~strcmp(GetFieldData.FieldOption,'civdata...')
2675           if ~isempty(regexp(FieldList{1},'^vec'))
2676                set(handles.FieldName,'Value',1)
2677           else
2678                set(handles.FieldName,'Value',1:numel(FieldList))%select all input fields by default
2679           end
2680            XName=GetFieldData.Coordinates.Coord_x;
2681            YName=GetFieldData.Coordinates.Coord_y;
2682            TimeNameStr=GetFieldData.Time.SwitchVarIndexTime;
2683            % get the time info                     
2684            TimeTable=get(handles.TimeTable,'Data');
2685            switch TimeNameStr
2686                case 'file index'
2687                    TimeName='';
2688                case 'attribute'
2689                    TimeName=['att:' GetFieldData.Time.TimeName];
2690                    % update the time table
2691                    TimeTable{LineIndex,2}=get_time(Param.IndexRange.MinIndex_i(LineIndex),MinIndex_j,PairString,InputTable,SeriesData.FileInfo{LineIndex},GetFieldData.Time.TimeName);  % Min time     
2692                    TimeTable{LineIndex,3}=get_time(Param.IndexRange.first_i,first_j,PairString,InputTable,SeriesData.FileInfo{LineIndex},GetFieldData.Time.TimeName);  % first time             
2693                    TimeTable{LineIndex,4}=get_time(Param.IndexRange.last_i,last_j,PairString,InputTable,SeriesData.FileInfo{LineIndex},GetFieldData.Time.TimeName);  % last time                     
2694                    TimeTable{LineIndex,5}=get_time(Param.IndexRange.MaxIndex_i(LineIndex),MaxIndex_j,PairString,InputTable,SeriesData.FileInfo{LineIndex},GetFieldData.Time.TimeName);  % Max time
2695                case 'variable'
2696                    set(handles.TimeName,'String',['var:' GetFieldData.Time.TimeName])
2697                    set(handles.NomType,'String','*')
2698                    set(handles.RootFile,'String',[get(handles.RootFile,'String') get(handles.FileIndex,'String')])% A VERIFIER !!!!!!
2699                    set(handles.FileIndex,'String','')
2700                    ParamIn.TimeVarName=GetFieldData.Time.TimeName;
2701                case 'matrix_index'
2702                    TimeName=['dim:' GetFieldData.Time.TimeName];
2703                    set(handles.NomType,'String','*')
2704                    set(handles.RootFile,'String',[get(handles.RootFile,'String') get(handles.FileIndex,'String')])
2705                    set(handles.FileIndex,'String','')
2706                    ParamIn.TimeDimName=GetFieldData.Time.TimeName;
2707            end
2708            TimeTable{LineIndex,1}=TimeName;
2709            set(handles.TimeTable,'Data',TimeTable);
2710        end
2711        set(handles.Coord_x,'String',XName)
2712        set(handles.Coord_y,'String',YName)
2713        set(handles.Coord_x,'Visible','on')
2714        set(handles.Coord_y,'Visible','on')
2715        end
2716    else
2717        msgbox_uvmat('ERROR',[FirstFileName ' does not exist'])
2718    end
2719end
2720
2721
2722function [TimeValue,DtValue]=get_time(ref_i,ref_j,PairString,InputTable,FileInfo,TimeName,DtName)
2723[i1,i2,j1,j2] = get_file_index(ref_i,ref_j,PairString);
2724FileName=fullfile_uvmat(InputTable{1},InputTable{2},InputTable{3},InputTable{5},InputTable{4},i1,i2,j1,j2);
2725Data=nc2struct(FileName,[]);
2726TimeValue=[];
2727DtValue=[];
2728if isequal(FileInfo.FileType,'civdata')
2729    if ismember(TimeName,{'civ1','filter1'})
2730        if isfield(Data,'Civ1_Time')
2731        TimeValue=Data.Civ1_Time;
2732        end
2733        if isfield(Data,'Civ1_Dt')
2734        DtValue=Data.Civ1_Dt;
2735        end
2736    else
2737        if isfield(Data,'Civ2_Time')
2738        TimeValue=Data.Civ2_Time;
2739        end
2740        if isfield(Data,'Civ2_Dt')
2741        DtValue=Data.Civ2_Dt;
2742        end
2743    end
2744else
2745    if ~isempty(TimeName)&& isfield(Data,TimeName)
2746        TimeValue=Data.(TimeName);
2747    end
2748    if exist('DtName','var') && isfield(Data,DtName)
2749        DtValue=Data.(DtName);
2750    end
2751end
2752
2753%------------------------------------------------------------------------
2754% --- Executes on selection change in FieldName_1.
2755function FieldName_1_Callback(hObject, eventdata, handles)
2756%------------------------------------------------------------------------
2757field_str=get(handles.FieldName_1,'String');
2758field_index=get(handles.FieldName_1,'Value');
2759field=field_str{field_index(1)};
2760if isequal(field,'get_field...')
2761    hget_field=findobj(allchild(0),'name','get_field');
2762    if ~isempty(hget_field)
2763        delete(hget_field)%delete opened versions of get_field
2764    end
2765    Param=read_GUI(handles.series);
2766    Param.InputTable=Param.InputTable(1,:);
2767    % check the existence of the first file in the series
2768    first_j=[];
2769    if isfield(Param.IndexRange,'first_j'); first_j=Param.IndexRange.first_j; end
2770    if isfield(Param.IndexRange,'last_j'); last_j=Param.IndexRange.last_j; end
2771    PairString='';
2772    if isfield(Param.IndexRange,'PairString'); PairString=Param.IndexRange.PairString; end
2773    [i1,i2,j1,j2] = get_file_index(Param.IndexRange.first_i,first_j,PairString);
2774    FirstFileName=fullfile_uvmat(Param.InputTable{1,1},Param.InputTable{1,2},Param.InputTable{1,3},...
2775        Param.InputTable{1,5},Param.InputTable{1,4},i1,i2,j1,j2);
2776    if exist(FirstFileName,'file')
2777        ParamIn.SeriesInput=1;
2778        GetFieldData=get_field(FirstFileName,ParamIn);
2779        FieldList={};
2780        switch GetFieldData.FieldOption
2781            case 'vectors'
2782                UName=GetFieldData.PanelVectors.vector_x;
2783                VName=GetFieldData.PanelVectors.vector_y;
2784                FieldList={['vec(' UName ',' VName ')'];...
2785                    ['norm(' UName ',' VName ')'];...
2786                    UName;VName};
2787            case {'scalar','pick variables'}
2788                FieldList=GetFieldData.PanelScalar.scalar;
2789                if ischar(FieldList)
2790                    FieldList={FieldList};
2791                end
2792            case '1D plot'
2793
2794            case 'civdata...'
2795                FieldList=set_field_list('U','V','C');
2796                set(handles.FieldName,'Value',2) % set menu to 'velocity
2797        end
2798        if ~strcmp(GetFieldData.FieldOption,'civdata...')
2799            TimeNameStr=GetFieldData.Time.SwitchVarIndexTime;
2800            switch TimeNameStr
2801                case 'file index'
2802                    set(handles.TimeName,'String','');
2803                case 'attribute'
2804                    set(handles.TimeName,'String',['att:' GetFieldData.Time.TimeName]);
2805                case 'variable'
2806                    set(handles.TimeName,'String',['var:' GetFieldData.Time.TimeName])
2807                    set(handles.NomType,'String','*')
2808                    set(handles.RootFile,'String',[get(handles.RootFile,'String') get(handles.FileIndex,'String')])% A VERIFIER !!!!!!
2809                    set(handles.FileIndex,'String','')
2810                    ParamIn.TimeVarName=GetFieldData.Time.TimeName;
2811                case 'matrix_index'
2812                    set(handles.TimeName,'String',['dim:' GetFieldData.Time.TimeName]);
2813                    set(handles.NomType,'String','*')
2814                    set(handles.RootFile,'String',[get(handles.RootFile,'String') get(handles.FileIndex,'String')])
2815                    set(handles.FileIndex,'String','')
2816                    ParamIn.TimeDimName=GetFieldData.Time.TimeName;
2817            end
2818        end
2819        set(handles.FieldName_1,'Value',1)
2820        set(handles.FieldName_1,'String',[FieldList; {'get_field...'}]);
2821    end
2822end   
2823
2824
2825%%%%%%%%%%%%%
2826function [ind_remove]=find_pairs(dirpair,ind_i,last_i)
2827indsel=ind_i;
2828indiff=diff(ind_i); %test index increment to detect multiplets (several pairs with the same index ind_i) and holes in the series
2829indiff=[1 indiff last_i-ind_i(end)+1];%for testing gaps with the imposed bounds
2830if ~isempty(indiff)
2831    indiff2=diff(indiff);
2832    indiffp=[indiff2 1];
2833    indiffm=[1 indiff2];
2834    ind_multi_m=find((indiff==0)&(indiffm<0))-1;%indices of first members of multiplets
2835    ind_multi_p=find((indiff==0)&(indiffp>0));%indices of last members of multiplets
2836    %for each multiplet, select the most recent file
2837    ind_remove=[];
2838    for i=1:length(ind_multi_m)
2839        ind_pairs=ind_multi_m(i):ind_multi_p(i);
2840        for imulti=1:length(ind_pairs)
2841            datepair(imulti)=datenum(dirpair(ind_pairs(imulti)).date);%dates of creation
2842        end
2843        [datenew,indsort2]=sort(datepair); %sort the multiplet by creation date
2844        ind_s=indsort2(1:end-1);%
2845        ind_remove=[ind_remove ind_pairs(ind_s)];%remove these indices, leave the last one
2846    end
2847end
2848
2849%------------------------------------------------------------------------
2850% --- determine the list of index pairstring of processing file
2851function [num_i1,num_i2,num_j1,num_j2,num_i_out,num_j_out]=find_file_indices(num_i,num_j,ind_shift,NomType,mode)
2852%------------------------------------------------------------------------
2853num_i1=num_i;% set of first image numbers by default
2854num_i2=num_i;
2855num_j1=num_j;
2856num_j2=num_j;
2857num_i_out=num_i;
2858num_j_out=num_j;
2859% if isequal (NomType,'_1-2_1') || isequal (NomType,'_1-2')
2860if isequal(mode,'series(Di)')
2861    num_i1_line=num_i+ind_shift(3);% set of first image numbers
2862    num_i2_line=num_i+ind_shift(4);
2863    % adjust the first and last field number
2864        indsel=find(num_i1_line >= 1);
2865    num_i_out=num_i(indsel);
2866    num_i1_line=num_i1_line(indsel);
2867    num_i2_line=num_i2_line(indsel);
2868    num_j1=meshgrid(num_j,ones(size(num_i1_line)));
2869    num_j2=meshgrid(num_j,ones(size(num_i1_line)));
2870    [xx,num_i1]=meshgrid(num_j,num_i1_line);
2871    [xx,num_i2]=meshgrid(num_j,num_i2_line);
2872elseif isequal (mode,'series(Dj)')||isequal (mode,'bursts')
2873    if isequal(mode,'bursts') %case of bursts (png_old or png_2D)
2874        num_j1=ind_shift(1)*ones(size(num_i));
2875        num_j2=ind_shift(2)*ones(size(num_i));
2876    else
2877        num_j1_col=num_j+ind_shift(1);% set of first image numbers
2878        num_j2_col=num_j+ind_shift(2);
2879        % adjust the first field number
2880        indsel=find((num_j1_col >= 1));   
2881        num_j_out=num_j(indsel);
2882        num_j1_col=num_j1_col(indsel);
2883        num_j2_col=num_j2_col(indsel);
2884        [num_i1,num_j1]=meshgrid(num_i,num_j1_col);
2885        [num_i2,num_j2]=meshgrid(num_i,num_j2_col);
2886    end   
2887end
2888
2889%------------------------------------------------------------------------
2890% --- Executes on button press in CheckObject.
2891function CheckObject_Callback(hObject, eventdata, handles)
2892%------------------------------------------------------------------------
2893hset_object=findobj(allchild(0),'tag','set_object');%find the set_object interface handle
2894if get(handles.CheckObject,'Value')
2895    SeriesData=get(handles.series,'UserData');
2896    if isfield(SeriesData,'ProjObject') && ~isempty(SeriesData.ProjObject)
2897        set(handles.ViewObject,'Value',1)
2898        ViewObject_Callback(hObject, eventdata, handles)
2899    else
2900        if ishandle(hset_object)
2901            uistack(hset_object,'top')% show the GUI set_object if opened
2902        else
2903            %get the object file
2904            InputTable=get(handles.InputTable,'Data');
2905            defaultname=InputTable{1,1};
2906            if isempty(defaultname)
2907                defaultname={''};
2908            end
2909            fileinput=uigetfile_uvmat('pick a xml object file (or use uvmat to create it)',defaultname,'.xml');
2910            if isempty(fileinput)% exit if no object file is selected
2911                set(handles.CheckObject,'Value',0)
2912                return
2913            end
2914            %read the file
2915            data=xml2struct(fileinput);
2916            if ~isfield(data,'Type')
2917                msgbox_uvmat('ERROR',[fileinput ' is not an object xml file'])
2918                set(handles.CheckObject,'Value',0)
2919                return
2920            end
2921            if ~isfield(data,'ProjMode')
2922                data.ProjMode='none';
2923            end
2924            hset_object=set_object(data);% call the set_object interface
2925            set(hset_object,'Name','set_object_series')% name to distinguish from set_object used with uvmat
2926        end
2927        ProjObject=read_GUI(hset_object);
2928        set(handles.ProjObject,'String',ProjObject.Name);%display the object name
2929        SeriesData=get(handles.series,'UserData');
2930        SeriesData.ProjObject=ProjObject;
2931        set(handles.series,'UserData',SeriesData);
2932    end
2933    set(handles.EditObject,'Visible','on');
2934    set(handles.DeleteObject,'Visible','on');
2935    set(handles.ViewObject,'Visible','on');
2936    set(handles.ProjObject,'Visible','on');
2937else
2938    set(handles.EditObject,'Visible','off');
2939    set(handles.DeleteObject,'Visible','off');
2940    set(handles.ViewObject,'Visible','off');
2941    if ~ishandle(hset_object)
2942        set(handles.ViewObject,'Value',0);
2943    end
2944    set(handles.ProjObject,'Visible','off');
2945end
2946
2947%------------------------------------------------------------------------
2948% --- Executes on button press in ViewObject.
2949%------------------------------------------------------------------------
2950function ViewObject_Callback(hObject, eventdata, handles)
2951
2952UserData=get(handles.series,'UserData');
2953hset_object=findobj(allchild(0),'Tag','set_object');
2954if ~isempty(hset_object)
2955    delete(hset_object)% refresh set_object if already opened
2956end
2957hset_object=set_object(UserData.ProjObject);
2958set(hset_object,'Name','view_object_series')
2959
2960
2961%------------------------------------------------------------------------
2962% --- Executes on button press in EditObject.
2963function EditObject_Callback(hObject, eventdata, handles)
2964%------------------------------------------------------------------------
2965if get(handles.EditObject,'Value')
2966    set(handles.ViewObject,'Value',0)
2967        UserData=get(handles.series,'UserData');
2968    hset_object=set_object(UserData.ProjObject);
2969    set(hset_object,'Name','edit_object_series')
2970    set(get(hset_object,'Children'),'Enable','on')
2971else
2972    hset_object=findobj(allchild(0),'Tag','set_object');
2973    if ~isempty(hset_object)
2974        set(get(hset_object,'Children'),'Enable','off')
2975    end
2976end
2977
2978%------------------------------------------------------------------------
2979% --- Executes on button press in DeleteObject.
2980function DeleteObject_Callback(hObject, eventdata, handles)
2981%------------------------------------------------------------------------
2982SeriesData=get(handles.series,'UserData');
2983SeriesData.ProjObject=[];
2984set(handles.series,'UserData',SeriesData)
2985set(handles.ProjObject,'String','')
2986set(handles.ProjObject,'Visible','off')
2987set(handles.CheckObject,'Value',0)
2988set(handles.ViewObject,'Visible','off')
2989set(handles.EditObject,'Visible','off')
2990hset_object=findobj(allchild(0),'name','set_object_series');
2991if ~isempty(hset_object)
2992    delete(hset_object)
2993end
2994set(handles.DeleteObject,'Visible','off')
2995
2996%------------------------------------------------------------------------
2997% --- Executed when CheckMask is activated
2998%------------------------------------------------------------------------
2999function CheckMask_Callback(hObject, eventdata, handles)
3000
3001if get(handles.CheckMask,'Value')
3002    InputTable=get(handles.InputTable,'Data');
3003    nbview=size(InputTable,1);
3004    MaskTable=cell(nbview,1);%default
3005    ListMask=cell(nbview,1);%default
3006    MaskData=get(handles.MaskTable,'Data');
3007    MaskData(size(MaskData,1):nbview,1)=cell(size(MaskData,1):nbview,1);%complement if undefined lines
3008    for iview=1:nbview
3009        ListMask{iview,1}=num2str(iview);
3010        RootPath=InputTable{iview,1};
3011        if ~isempty(RootPath)
3012            if isempty(MaskData{iview})
3013                SubDir=InputTable{iview,2};
3014                MaskPath=fullfile(RootPath,[regexprep(SubDir,'\..*','') '.mask']);%take the root part of SubDir, before the first dot '.'
3015                if exist(MaskPath,'dir')
3016                    ListStruct=dir(MaskPath);%look for a mask file
3017                    ListCells=struct2cell(ListStruct);% transform dir struct to a cell arrray
3018                    check_dir=cell2mat(ListCells(4,:));% =1 for directories, =0 for files
3019                    ListFiles=ListCells(1,:);%list of file and dri names
3020                    ListFiles=ListFiles(~check_dir);%list of file names (excluding dir)
3021                    mdetect=0;
3022                    if ~isempty(ListFiles)
3023                        for ifile=1:numel(ListFiles)
3024                            [tild,tild,MaskFile{ifile},i1_series,i2_series,j1_series,j2_series,MaskNomType,MaskFileType]=find_file_series(MaskPath,ListFiles{ifile},0);
3025                            if strcmp(MaskFileType,'image') && isempty(i2_series) && isempty(j2_series)
3026                                mdetect=1;
3027                                MaskName=ListFiles{ifile};
3028                            end
3029                            if ~strcmp(MaskFile{ifile},MaskFile{1})
3030                                mdetect=0;% cancel detection test in case of multiple masks, use the brower for selection
3031                                break
3032                            end
3033                        end
3034                    end
3035                    if mdetect==1
3036                        MaskName=fullfile(MaskPath,'mask_1.png');
3037                    else
3038                        MaskName=uigetfile_uvmat('select a mask file:',MaskPath,'image');
3039                    end
3040                else
3041                    MaskName=uigetfile_uvmat('select a mask file:',RootPath,'image');
3042                end
3043                MaskTable{iview,1}=MaskName ;
3044                ListMask{iview,1}=num2str(iview);
3045            end
3046        end
3047    end
3048    set(handles.MaskTable,'Data',MaskTable)
3049    set(handles.MaskTable,'Visible','on')
3050    set(handles.MaskBrowse,'Visible','on')
3051    set(handles.ListMask,'Visible','on')
3052    set(handles.ListMask,'String',ListMask)
3053    set(handles.ListMask,'Value',1)
3054else
3055    set(handles.MaskTable,'Visible','off')
3056    set(handles.MaskBrowse,'Visible','off')
3057    set(handles.ListMask,'Visible','off')
3058end
3059
3060%------------------------------------------------------------------------
3061% --- Executes on button press in MaskBrowse.
3062%------------------------------------------------------------------------
3063function MaskBrowse_Callback(hObject, eventdata, handles)
3064
3065InputTable=get(handles.InputTable,'Data');
3066iview=get(handles.ListMask,'Value');
3067RootPath=InputTable{iview,1};
3068MaskName=uigetfile_uvmat('select a mask file:',RootPath,'image');
3069if ~isempty(MaskName)
3070    MaskTable=get(handles.MaskTable,'Data');
3071    MaskTable{iview,1}=MaskName ;
3072    set(handles.MaskTable,'Data',MaskTable)
3073end
3074
3075%------------------------------------------------------------------------
3076% --- Executes when selected cell(s) is changed in MaskTable.
3077%------------------------------------------------------------------------
3078function MaskTable_CellSelectionCallback(hObject, eventdata, handles)
3079
3080if numel(eventdata.Indices)>=1
3081set(handles.ListMask,'Value',eventdata.Indices(1))
3082end
3083
3084%-------------------------------------------------------------------
3085function MenuHelp_Callback(hObject, eventdata, handles)
3086%-------------------------------------------------------------------
3087
3088
3089% path_to_uvmat=which ('uvmat');% check the path of uvmat
3090% pathelp=fileparts(path_to_uvmat);
3091% helpfile=fullfile(pathelp,'uvmat_doc','uvmat_doc.html');
3092% if isempty(dir(helpfile)), msgbox_uvmat('ERROR','Please put the help file uvmat_doc.html in the sub-directory /uvmat_doc of the UVMAT package')
3093% else
3094%     addpath (fullfile(pathelp,'uvmat_doc'))
3095%     web([helpfile '#series'])
3096% end
3097
3098%-------------------------------------------------------------------
3099% --- Executes on selection change in TransformName.
3100function TransformName_Callback(hObject, eventdata, handles)
3101%----------------------------------------------------------------------
3102TransformList=get(handles.TransformName,'String');
3103TransformIndex=get(handles.TransformName,'Value');
3104TransformName=TransformList{TransformIndex};
3105TransformPathList=get(handles.TransformName,'UserData');
3106nb_builtin_transform=4;
3107if isequal(TransformName,'more...');     
3108    FileName=uigetfile_uvmat('Pick a transform function',get(handles.TransformPath,'String'),'.m');
3109    if isempty(FileName)
3110        return     %browser closed without choice
3111    end
3112    [TransformPath,TransformName,TransformExt]=fileparts(FileName);% removes extension .m
3113    if ~strcmp(TransformExt,'.m')
3114        msgbox_uvmat('ERROR','a Matlab function .m must be introduced');
3115        return
3116    end
3117     % insert the choice in the menu
3118    TransformIndex=find(strcmp(TransformName,TransformList),1);% look for the selected function in the menu Action
3119    if isempty(TransformIndex)%the input string does not exist in the menu
3120        TransformIndex= length(TransformList);
3121        TransformList=[TransformList(1:end-1);{TransformName};TransformList(end)];% the selected function is appended in the menu, before the last item 'more...'
3122        set(handles.TransformName,'String',TransformList)
3123        TransformPathList=[TransformPathList;{TransformPath}];
3124    else% the input function already exist, we update its path (possibly new)
3125        TransformPathList{TransformIndex}=TransformPath;%
3126        set(handles.TransformName,'Value',TransformIndex)
3127    end
3128   % save the new menu in the personal file 'uvmat_perso.mat'
3129   dir_perso=prefdir;%personal Matalb directory
3130   profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
3131   if exist(profil_perso,'file')
3132       for ilist=nb_builtin_transform+1:numel(TransformPathList)
3133           TransformListUser{ilist-nb_builtin_transform}=TransformList{ilist};
3134           TransformPathListUser{ilist-nb_builtin_transform}=TransformPathList{ilist};
3135       end
3136       TransformPathListUser=TransformPathListUser';
3137       TransformListUser=TransformListUser';
3138       save (profil_perso,'TransformPathListUser','TransformListUser','-append'); %store the root name for future opening of uvmat
3139   end
3140end
3141
3142%display the current function path
3143set(handles.TransformPath,'String',TransformPathList{TransformIndex}); %show the path to the senlected function
3144set(handles.TransformName,'UserData',TransformPathList);
3145
3146%% create the function handle of the selected fct
3147if ~isempty(TransformName)
3148    if ~exist(TransformPathList{TransformIndex},'dir')
3149        msgbox_uvmat('ERROR',['The prescribed transform function path ' TransformPathList{TransformIndex} ' does not exist']);
3150        return
3151    end
3152    current_dir=pwd;%current working dir
3153    cd(TransformPathList{TransformIndex})
3154    transform_handle=str2func(TransformName);
3155    cd(current_dir)
3156    Field.Action.RUN=0;% indicate that the transform fct is called only to get input param
3157    DataOut=feval(transform_handle,Field,[]);% execute the transform fct to get the required conditions
3158    if isfield(DataOut,'TransformInput')%  used to add transform parameters at selection of the transform fct
3159        SeriesData=get(handles.series,'UserData');
3160        SeriesData.TransformInput=DataOut.TransformInput;
3161        set(handles.series,'UserData',SeriesData)
3162    end
3163end
3164
3165%------------------------------------------------------------------------
3166% --- fct activated by the upper bar menu ExportConfig
3167%------------------------------------------------------------------------
3168function MenuDisplayConfig_Callback(hObject, eventdata, handles)
3169
3170global Param
3171Param=read_GUI_series(handles);
3172evalin('base','global Param')%make CurData global in the workspace
3173display('current series config :')
3174evalin('base','Param') %display CurData in the workspace
3175commandwindow; %brings the Matlab command window to the front
3176
3177%------------------------------------------------------------------------
3178% --- fct activated by the upper bar menu InportConfig: import
3179%     menu settings from an xml file (stored in /0_XML for each run)
3180%------------------------------------------------------------------------
3181function MenuImportConfig_Callback(hObject, eventdata, handles)
3182
3183%% use a browser to choose the xml file containing the processing config
3184InputTable=get(handles.InputTable,'Data');
3185oldfile=InputTable{1,1};%current path in InputTable
3186if isempty(oldfile)
3187    % use a file name stored in prefdir
3188    dir_perso=prefdir;
3189    profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
3190    if exist(profil_perso,'file')
3191        h=load (profil_perso);
3192        if isfield(h,'RootPath') && ischar(h.RootPath)
3193            oldfile=h.RootPath;
3194        end
3195    end
3196end
3197filexml=uigetfile_uvmat('pick a xml parameter file',oldfile,'.xml');% get the xml file containing processing parameters
3198if isempty(filexml), return, end % quit function if an xml file has not been opened
3199
3200%% fill the GUI series with the content of the xml file
3201Param=xml2struct(filexml);% read the input xml file as a Matlab structure
3202
3203% ask to stop current Action if button RUN is in action (another process is already running)
3204if isequal(get(handles.RUN,'Value'),1)
3205    answer= msgbox_uvmat('INPUT_Y-N','stop current Action process?');
3206    if strcmp(answer,'Yes')
3207        STOP_Callback(hObject, eventdata, handles)
3208    else
3209        return
3210    end
3211end
3212Param.Action.RUN=0; %desactivate the input RUN=1
3213
3214fill_GUI(Param,handles.series)% fill the elements of the GUI series with the input parameters
3215SeriesData=get(handles.series,'UserData');
3216if isfield(Param,'InputFields')
3217    ListField=Param.InputFields.FieldName;
3218    if ischar(ListField),ListField={ListField}; end
3219    set(handles.FieldName,'String',[ListField;{'get-field...'}])
3220     set(handles.FieldName,'Value',1:numel(ListField))
3221     set(handles.FieldName,'Visible','on')
3222end       
3223if isfield(Param,'ActionInput')%  introduce  parameters specific to an Action fct, for instance PIV parameters
3224    set(handles.ActionInput,'Visible','on')
3225    set(handles.ActionInput,'Value',0)
3226    Param.ActionInput.ConfigSource=filexml;% record the source of config for future info
3227    SeriesData.ActionInput=Param.ActionInput;
3228end
3229if isfield(Param,'TransformInput')%  introduce  parameters specific to a transform fct
3230    SeriesData.TransformInput=Param.TransformInput;
3231end
3232if isfield(Param,'ProjObject') %introduce projection object if relevant
3233    SeriesData.ProjObject=Param.ProjObject;
3234end
3235set(handles.series,'UserData',SeriesData)
3236if isfield(Param,'CheckObject') && isequal(Param.CheckObject,1)
3237    set(handles.ProjObject,'String',Param.ProjObject.Name)
3238    set(handles.ViewObject,'Visible','on')
3239    set(handles.EditObject,'Visible','on')
3240    set(handles.DeleteObject,'Visible','on')
3241else     
3242    set(handles.ProjObject,'String','')
3243    set(handles.ProjObject,'Visible','off')
3244    set(handles.ViewObject,'Visible','off')
3245    set(handles.EditObject,'Visible','off')
3246    set(handles.DeleteObject,'Visible','off')     
3247end     
3248set(handles.REFRESH,'BackgroundColor',[1 0 1]); %paint REFRESH button in magenta to indicate that it should be activated
3249
3250
3251%------------------------------------------------------------------------
3252% --- Executes when the GUI series is resized.
3253%------------------------------------------------------------------------
3254function series_ResizeFcn(hObject, eventdata, handles)
3255
3256%% input table
3257set(handles.InputTable,'Unit','pixel')
3258Pos=get(handles.InputTable,'Position');
3259set(handles.InputTable,'Unit','normalized')
3260ColumnWidth=round([0.5 0.14 0.14 0.14 0.08]*(Pos(3)-52));
3261ColumnWidth=num2cell(ColumnWidth);
3262set(handles.InputTable,'ColumnWidth',ColumnWidth)
3263
3264%% MinIndex_j and MaxIndex_i
3265unit=get(handles.MinIndex_i,'Unit');
3266set(handles.MinIndex_i,'Unit','pixel')
3267Pos=get(handles.MinIndex_i,'Position');
3268set(handles.MinIndex_i,'Unit',unit)
3269set(handles.MinIndex_i,'ColumnWidth',{Pos(3)-18})
3270set(handles.MaxIndex_i,'ColumnWidth',{Pos(3)-18})
3271set(handles.MinIndex_j,'ColumnWidth',{Pos(3)-18})
3272set(handles.MaxIndex_j,'ColumnWidth',{Pos(3)-18})
3273
3274%% TimeTable
3275set(handles.TimeTable,'Unit','pixel')
3276Pos=get(handles.TimeTable,'Position');
3277set(handles.TimeTable,'Unit','normalized')
3278% ColumnWidth=get(handles.TimeTable,'ColumnWidth');
3279ColumnWidth=num2cell(floor([0.2 0.2 0.2 0.2 0.2]*(Pos(3)-20)));
3280set(handles.TimeTable,'ColumnWidth',ColumnWidth)
3281
3282
3283%% PairString
3284set(handles.PairString,'Unit','pixel')
3285Pos=get(handles.PairString,'Position');
3286set(handles.PairString,'Unit','normalized')
3287set(handles.PairString,'ColumnWidth',{Pos(3)-5})
3288
3289%% MaskTable
3290set(handles.MaskTable,'Unit','pixel')
3291Pos=get(handles.MaskTable,'Position');
3292set(handles.MaskTable,'Unit','normalized')
3293set(handles.MaskTable,'ColumnWidth',{Pos(3)-5})
3294
3295%------------------------------------------------------------------------
3296% --- Executes on button press in status.
3297%------------------------------------------------------------------------
3298function status_Callback(hObject, eventdata, handles)
3299
3300if get(handles.status,'Value')
3301    set(handles.status,'BackgroundColor',[1 1 0])
3302    drawnow
3303    Param=read_GUI(handles.series);
3304    RootPath=Param.InputTable{1,1};
3305    if ~isfield(Param,'OutputSubDir')   
3306        msgbox_uvmat('ERROR','no standard sub-directory definition for output files, use a browser to check the output')
3307        set(handles.status,'BackgroundColor',[0 1 0])
3308        return
3309    end
3310    OutputSubDir=[Param.OutputSubDir Param.OutputDirExt];% subdirectory for output files
3311    OutputDir=fullfile(RootPath,OutputSubDir);
3312    if exist(OutputDir,'dir')
3313        uigetfile_uvmat('status_display',OutputDir)
3314    else
3315        msgbox_uvmat('ERROR','output folder not created yet: calculation did not start')
3316        set(handles.status,'BackgroundColor',[0 1 0])
3317    end
3318else
3319    %% delete current display fig if selection is off
3320    set(handles.status,'BackgroundColor',[0 1 0])
3321    hfig=findobj(allchild(0),'name','status_display');
3322    if ~isempty(hfig)
3323        delete(hfig)
3324    end
3325    return
3326end
3327
3328
3329%------------------------------------------------------------------------   
3330% launched by selecting a file on the list
3331%------------------------------------------------------------------------
3332function view_file(hObject, eventdata)
3333
3334list=get(hObject,'String');
3335index=get(hObject,'Value');
3336rootroot=get(hObject,'UserData');
3337selectname=list{index};
3338ind_dot=regexp(selectname,'\.\.\.');
3339if ~isempty(ind_dot)
3340    selectname=selectname(1:ind_dot-1);
3341end
3342FullSelectName=fullfile(rootroot,selectname);
3343if exist(FullSelectName,'dir')% a directory has been selected
3344    ListFiles=dir(FullSelectName);
3345    ListDisplay=cell(numel(ListFiles),1);
3346    for ilist=2:numel(ListDisplay)% suppress the first line '.'
3347        ListDisplay{ilist-1}=ListFiles(ilist).name;
3348    end
3349    set(hObject,'Value',1)
3350    set(hObject,'String',ListDisplay)
3351    if strcmp(selectname,'..')
3352        FullSelectName=fileparts(fileparts(FullSelectName));
3353    end
3354    set(hObject,'UserData',FullSelectName)
3355    hfig=get(hObject,'parent');
3356    htitlebox=findobj(hfig,'tag','titlebox');   
3357    set(htitlebox,'String',FullSelectName)
3358elseif exist(FullSelectName,'file')%visualise the vel field if it exists
3359    FileInfo=get_file_info(FullSelectName);   
3360    if strcmp(FileInfo.FileType,'txt')
3361        edit(FullSelectName)
3362    elseif strcmp(FileInfo.FileType,'xml')
3363        editxml(FullSelectName)
3364    else
3365        uvmat(FullSelectName)
3366    end
3367    set(gcbo,'Value',1)
3368end
3369
3370
3371%------------------------------------------------------------------------   
3372% launched by refreshing the status figure
3373%------------------------------------------------------------------------
3374function refresh_GUI(hfig)
3375
3376htitlebox=findobj(hfig,'tag','titlebox');
3377hlist=findobj(hfig,'tag','list');
3378hseries=findobj(allchild(0),'tag','series');
3379hstatus=findobj(hseries,'tag','status');
3380StatusData=get(hstatus,'UserData');
3381OutputDir=get(htitlebox,'String');
3382if ischar(OutputDir),OutputDir={OutputDir};end
3383ListFiles=dir(OutputDir{1});
3384if numel(ListFiles)<1
3385    return
3386end
3387ListFiles(1)=[];%removes the first line ='.'
3388ListDisplay=cell(numel(ListFiles),1);
3389testrecent=0;
3390datnum=zeros(numel(ListDisplay),1);
3391for ilist=1:numel(ListDisplay)
3392    ListDisplay{ilist}=ListFiles(ilist).name;
3393      if ~ListFiles(ilist).isdir && isfield(ListFiles(ilist),'datenum')
3394            datnum(ilist)=ListFiles(ilist).datenum;%only available in recent matlab versions
3395            testrecent=1;
3396       end
3397end
3398set(hlist,'String',ListDisplay)
3399
3400%% Look at date of creation
3401ListDisplay=ListDisplay(datnum~=0);
3402datnum=datnum(datnum~=0);%keep the non zero values corresponding to existing files
3403NbOutputFile=[];
3404if isempty(datnum)
3405    if testrecent
3406        message='no civ result created yet';
3407    else
3408        message='';
3409    end
3410else
3411    [first,indfirst]=min(datnum);
3412    [last,indlast]=max(datnum);
3413    NbOutputFile_str='?';
3414    NbOutputFile=[];
3415    if isfield(StatusData,'NbOutputFile')
3416        NbOutputFile=StatusData.NbOutputFile;
3417        NbOutputFile_str=num2str(NbOutputFile);
3418    end
3419    message={[num2str(numel(datnum)) ' file(s) done over ' NbOutputFile_str] ;['oldest modification:  ' ListDisplay{indfirst} ' : ' datestr(first)];...
3420        ['latest modification:  ' ListDisplay{indlast} ' : ' datestr(last)]};
3421end
3422set(htitlebox,'String', [OutputDir{1};message])
3423
3424%% update the waitbar
3425hwaitbar=findobj(hfig,'tag','waitbar');
3426if ~isempty(NbOutputFile)
3427    BarPosition=get(hwaitbar,'Position');
3428    BarPosition(3)=0.9*numel(datnum)/NbOutputFile;
3429    set(hwaitbar,'Position',BarPosition)
3430end
3431
3432%------------------------------------------------------------------------
3433% --- Executes on selection change in ActionExt.
3434%------------------------------------------------------------------------
3435function ActionExt_Callback(hObject, eventdata, handles)
3436
3437ActionExtList=get(handles.ActionExt,'String');
3438ActionExt=ActionExtList{get(handles.ActionExt,'Value')};
3439if strcmp(ActionExt,'.py (in dev.)')
3440    set(handles.RunMode,'Value',2)
3441end
3442
3443%function num_NbProcess_Callback(hObject, eventdata, handles)
3444
3445
3446function num_NbSlice_Callback(hObject, eventdata, handles)
3447NbSlice=str2num(get(handles.num_NbSlice,'String'));
3448%set(handles.num_NbProcess,'String',num2str(NbSlice))
3449
3450%------------------------------------------------------------------------
3451% --- set the visibility of relevant velocity type menus:
3452function menu=set_veltype_display(Civ,FileType)
3453%------------------------------------------------------------------------
3454if ~exist('FileType','var')
3455    FileType='civx';
3456end
3457switch FileType
3458    case 'civx'
3459        menu={'civ1';'interp1';'filter1';'civ2';'interp2';'filter2'};
3460        if isequal(Civ,0)
3461            imax=0;
3462        elseif isequal(Civ,1) || isequal(Civ,2)
3463            imax=1;
3464        elseif isequal(Civ,3)
3465            imax=3;
3466        elseif isequal(Civ,4) || isequal(Civ,5)
3467            imax=4;
3468        elseif isequal(Civ,6) %patch2
3469            imax=6;
3470        end
3471    case 'civdata'
3472        menu={'civ1';'filter1';'civ2';'filter2'};
3473        if isequal(Civ,0)
3474            imax=0;
3475        elseif isequal(Civ,1) || isequal(Civ,2)
3476            imax=1;
3477        elseif isequal(Civ,3)
3478            imax=2;
3479        elseif isequal(Civ,4) || isequal(Civ,5)
3480            imax=3;
3481        else%if isequal(Civ,6) %patch2
3482            imax=4;
3483        end
3484end
3485menu=menu(1:imax);
3486
3487
3488% --- Executes on mouse motion over figure - except title and menu.
3489function series_WindowButtonMotionFcn(hObject, eventdata, handles)
3490set(hObject,'Pointer','arrow');
3491
3492
3493% --- Executes on button press in SetPairs.
3494function SetPairs_Callback(hObject, eventdata, handles)
3495
3496%% delete previous occurrence of 'set_pairs'
3497hfig=findobj(allchild(0),'Tag','set_pairs');
3498if ~isempty(hfig)
3499delete(hfig)
3500end
3501
3502%% create the GUI set_pairs
3503set(0,'Unit','points')
3504ScreenSize=get(0,'ScreenSize');% get the size of the screen, to put the fig on the upper right
3505Width=220;% fig width in points (1/72 inch)
3506Height=min(0.8*ScreenSize(4),300);
3507Left=ScreenSize(3)- Width-40; %right edge close to the right, with margin=40
3508Bottom=ScreenSize(4)-Height-40; %put fig at top right
3509hfig=findobj(allchild(0),'Tag','set_slice');
3510if ~isempty(hfig),delete(hfig), end; %delete existing version of the GUI
3511hfig=figure('name','set_pairs','tag','set_pairs','MenuBar','none','NumberTitle','off','Unit','points','Position',[Left,Bottom,Width,Height]);
3512BackgroundColor=get(hfig,'Color');
3513SeriesData=get(handles.series,'UserData');
3514TimeUnit=get(handles.TimeUnit,'String');
3515PairString=get(handles.PairString,'Data');
3516ListViewLines=find(cellfun('isempty',PairString)==0);%find list of non empty pairs
3517ListViewMenu=cell(numel(ListViewLines),1);
3518iview=get(handles.PairString,'Value');
3519for ilist=1:numel(ListViewLines)
3520    ListViewMenu{ilist}=num2str(ListViewLines(ilist));
3521end
3522if isempty(iview)
3523    ListViewValue=numel(ListViewLines);% we work by default on the pair option for the last line which requires pairs
3524    iview=ListViewLines(end);
3525else
3526    ListViewValue=find(ListViewLines==iview);
3527end
3528ref_i=str2num(get(handles.num_first_i,'String'));
3529ref_j=1;%default
3530if strcmp(get(handles.num_first_j,'String'),'Visible')
3531    ref_j=str2num(get(handles.num_first_j,'String'));
3532end
3533[ModeMenu,ModeValue]=update_mode(SeriesData.i1_series{iview},SeriesData.i2_series{iview},SeriesData.j2_series{iview});
3534displ_pair=update_listpair(SeriesData.i1_series{iview},SeriesData.i2_series{iview},SeriesData.j1_series{iview},SeriesData.j2_series{iview},ModeMenu{ModeValue},...
3535                                                     SeriesData.Time{iview},TimeUnit,ref_i,ref_j,SeriesData.FileInfo{iview});
3536% first raw of the GUI
3537uicontrol('Style','text','Units','normalized', 'Position', [0.05 0.88 0.5 0.1],'BackgroundColor',BackgroundColor,...
3538    'String','row to edit #','FontUnits','points','FontSize',12,'FontWeight','bold','ForegroundColor','blue','HorizontalAlignment','right');%title
3539uicontrol('Style','popupmenu','Units','normalized', 'Position', [0.54 0.8 0.3 0.2],'BackgroundColor',[1 1 1],...
3540    'Callback',@(hObject,eventdata)ListView_Callback(hObject,eventdata),'String',ListViewMenu,'Value',ListViewValue,'FontUnits','points','FontSize',12,'FontWeight','bold',...
3541    'Tag','ListView','TooltipString','''ListView'':choice of the file series w for pair display');
3542% second raw of the GUI
3543uicontrol('Style','text','Units','normalized', 'Position', [0.05 0.79 0.7 0.1],'BackgroundColor',BackgroundColor,...
3544    'String','mode of index pairing:','FontUnits','points','FontSize',12,'FontWeight','bold','ForegroundColor','blue','HorizontalAlignment','left');%title
3545uicontrol('Style','popupmenu','Units','normalized', 'Position', [0.05 0.62 0.9 0.2],'BackgroundColor',[1 1 1],...
3546    'Callback',@(hObject,eventdata)Mode_Callback(hObject,eventdata),'String',ModeMenu,'Value',ModeValue,'FontUnits','points','FontSize',12,'FontWeight','bold',...
3547    'Tag','Mode','TooltipString','''Mode'': choice of the image pair mode');
3548% third raw
3549uicontrol('Style','text','Units','normalized', 'Position', [0.05 0.6 0.7 0.1],'BackgroundColor',BackgroundColor,...
3550    'String','pair choice:','FontUnits','points','FontSize',12,'FontWeight','bold','ForegroundColor','blue','HorizontalAlignment','left');%title
3551uicontrol('Style','listbox','Units','normalized', 'Position', [0.05 0.42 0.9 0.2],'BackgroundColor',[1 1 1],...
3552    'Callback',@(hObject,eventdata)ListPair_Callback(hObject,eventdata),'String',displ_pair,'Value',1,'FontUnits','points','FontSize',12,'FontWeight','bold',...
3553    'Tag','ListPair','TooltipString','''ListPair'': menu for selecting the image pair');
3554uicontrol('Style','text','Units','normalized', 'Position', [0.1 0.22 0.8 0.1],'BackgroundColor',BackgroundColor,...
3555    'String','ref_i           ref_j','FontUnits','points','FontSize',12,'FontWeight','bold','ForegroundColor','blue','HorizontalAlignment','center');%title
3556uicontrol('Style','edit','Units','normalized', 'Position', [0.15 0.17 0.3 0.08],'BackgroundColor',[1 1 1],...
3557    'Callback',@(hObject,eventdata)num_ref_i_Callback(hObject,eventdata),'String',num2str(ref_i),'FontUnits','points','FontSize',12,'FontWeight','bold',...
3558    'Tag','num_ref_i','TooltipString','''num_ref_i'': reference field index i used to display dt in ''list_pair_civ''');
3559uicontrol('Style','edit','Units','normalized', 'Position', [0.55 0.17 0.3 0.08],'BackgroundColor',[1 1 1],...
3560    'Callback',@(hObject,eventdata)num_ref_j_Callback(hObject,eventdata),'String',num2str(ref_j),'FontUnits','points','FontSize',12,'FontWeight','bold',...
3561    'Tag','num_ref_j','TooltipString','''num_ref_j'': reference field index i used to display dt in ''list_pair_civ''');
3562uicontrol('Style','pushbutton','Units','normalized', 'Position', [0.01 0.01 0.3 0.12],'BackgroundColor',[0 1 0],...
3563    'Callback',@(hObject,eventdata)OK_Callback(hObject,eventdata),'String','OK','FontUnits','points','FontSize',12,'FontWeight','bold',...
3564    'Tag','OK','TooltipString','''OK'': validate the choice');
3565%  last raw  of the GUI: pushbuttons
3566% uicontrol('Style','pushbutton','Units','normalized', 'Position', [0.35 0.01 0.3 0.15],'BackgroundColor',[0 1 0],'String','OK','Callback',@(hObject,eventdata)OK_Callback(hObject,eventdata),...
3567%     'FontWeight','bold','FontUnits','points','FontSize',12,'TooltipString','''OK'': apply the output to the current field series in uvmat');
3568drawnow
3569
3570%------------------------------------------------------------------------
3571function ListView_Callback(hObject,eventdata)
3572Mode_Callback(hObject,eventdata)
3573
3574%------------------------------------------------------------------------   
3575function Mode_Callback(hObject,eventdata)
3576%% get input info
3577hseries=findobj(allchild(0),'tag','series');%handles of the GUI series
3578hhseries=guidata(hseries);%handles of the elements in the GUI series
3579TimeUnit=get(hhseries.TimeUnit,'String');
3580SeriesData=get(hseries,'UserData');
3581mode_list=get(hObject,'String');
3582mode=mode_list{get(hObject,'Value')};
3583hListView=findobj(get(hObject,'parent'),'Tag','ListView');
3584iview=get(hListView,'Value');
3585i1_series=SeriesData.i1_series{iview};
3586i2_series=SeriesData.i2_series{iview};
3587j1_series=SeriesData.j1_series{iview};
3588j2_series=SeriesData.j2_series{iview};
3589
3590%% enable j index visibility after the new choice
3591status_j='on';%default
3592if isempty(find(~cellfun(@isempty,SeriesData.j1_series), 1)); % case of empty j indices
3593    status_j='off'; % no j index needed
3594elseif strcmp(get(handles.PairString,'Visible'),'on')
3595    check_burst=cellfun(@isempty,regexp(PairString,'^j'));%=0 for burst case, 1 otherwise
3596    if isempty(find(check_burst, 1))% if all pair string begins by j (burst)
3597        status_j='off'; % no j index needed for bust case
3598    end
3599end
3600enable_j(handles,status_j) % no j index needed
3601
3602%% get the reference indices for the time interval Dt
3603href_i=findobj(get(hObject,'parent'),'Tag','ref_i');
3604ref_i=[];ref_j=[];
3605if strcmp(get(href_i,'Visible'),'on')
3606    ref_i=str2num(get(href_i,'String'));
3607end
3608if isempty(ref_i)
3609    ref_i=1;
3610end
3611if isempty(ref_j)
3612    ref_j=1;
3613end
3614
3615%% update the menu ListPair
3616Menu=update_listpair(i1_series,i2_series,j1_series,j2_series,mode,SeriesData.Time{iview},TimeUnit,ref_i,ref_j,FileInfo);
3617hlist_pairs=findobj(get(hObject,'parent'),'Tag','ListPair');
3618set(hlist_pairs,'Value',1)% set the first choice by default in ListPair
3619set(hlist_pairs,'String',Menu)% set the menu in ListPair
3620ListPair_Callback(hlist_pairs,[])% apply the default choice in ListPair
3621
3622%-------------------------------------------------------------
3623% --- Executes on selection in ListPair.
3624function ListPair_Callback(hObject,eventdata)
3625%------------------------------------------------------------
3626list_pair=get(hObject,'String');%get the menu of image pairs
3627if isempty(list_pair)
3628    string='';
3629else
3630    string=list_pair{get(hObject,'Value')};
3631   % string=regexprep(string,',.*','');%removes time indication (after ',')
3632end
3633hseries=findobj(allchild(0),'tag','series');
3634hPairString=findobj(hseries,'tag','PairString');
3635PairString=get(hPairString,'Data');
3636hListView=findobj(get(hObject,'parent'),'Tag','ListView');
3637iview=get(hListView,'Value');
3638PairString{iview,1}=string;
3639% report the selected pair string to the table PairString
3640set(hPairString,'Data',PairString)
3641
3642
3643%------------------------------------------------------------------------
3644function num_ref_i_Callback(hObject, eventdata)
3645%------------------------------------------------------------------------
3646Mode_Callback([],[])
3647
3648%------------------------------------------------------------------------
3649function num_ref_j_Callback(hObject, eventdata)
3650%------------------------------------------------------------------------
3651Mode_Callback([],[])
3652
3653%------------------------------------------------------------------------
3654function OK_Callback(hObject, eventdata)
3655%------------------------------------------------------------------------
3656delete(get(hObject,'parent'))
3657
3658
3659%------------------------------------------------------------------------
3660% --- Executes on button press in ClearLine.
3661%------------------------------------------------------------------------
3662function ClearLine_Callback(hObject, eventdata, handles)
3663InputTable=get(handles.InputTable,'Data');
3664iline=str2double(get(handles.InputLine,'String'));
3665if size(InputTable,1)>1
3666    InputTable(iline,:)=[];% suppress the current line if not the first
3667    set(handles.InputTable,'Data',InputTable);
3668end
3669set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH button to magenta color to indicate that input refr
3670
3671
3672% --- Executes on button press in MonitorCluster.
3673function MonitorCluster_Callback(hObject, eventdata, handles)
3674web('https://www.legi.grenoble-inp.fr/servfill/monika')
3675
3676function OutputSubDir_Callback(hObject, eventdata, handles)
3677set(handles.OutputSubDir,'BackgroundColor',[1 1 1])
3678
3679
3680% --- Executes on button press in CheckOverwrite.
3681function CheckOverwrite_Callback(hObject, eventdata, handles)
3682
3683
3684
3685% --- Executes on button press in TestCPUTime.
3686function TestCPUTime_Callback(hObject, eventdata, handles)
3687% hObject    handle to TestCPUTime (see GCBO)
3688% eventdata  reserved - to be defined in a future version of MATLAB
3689% handles    structure with handles and user data (see GUIDATA)
3690
3691
3692
3693
3694
Note: See TracBrowser for help on using the repository browser.