source: trunk/src/series.m @ 1003

Last change on this file since 1003 was 1003, checked in by campagne8a, 4 years ago

Fluidiamage compatibility

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