source: trunk/src/series.m @ 996

Last change on this file since 996 was 996, checked in by sommeria, 7 years ago

button ActionInput? introduced in series

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