source: trunk/src/series.m @ 937

Last change on this file since 937 was 937, checked in by sommeria, 5 years ago

various upgrades

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