source: trunk/src/series.m @ 1001

Last change on this file since 1001 was 1001, checked in by sommeria, 4 years ago

tubcorrelation added, compilation improved to accept tranform fct

File size: 167.4 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'
155[code, message] = system...
156    ('LD_LIBRARY_PATH=$(echo $LD_LIBRARY_PATH | pyp "p.split('':'') |... [s for s in p if ''matlab'' not in s] | '':''.join(p)") python -c "import fluidimage"');
157if code==0
158    ActionExtList={'.m';'.sh';'.py (in dev.)'}; % default choice of extensions (Matlab fct .m or compiled version .sh
159else
160    ActionExtList={'.m';'.sh'};  % python options not installed
161end
162ActionPathList=cell(NbBuiltinAction,1); % initiate the cell matrix of Action fct paths
163ActionPathList(:)={path_series_fct}; % set the default path to series fcts to all list members
164RunModeList={'local';'background'}; % default choice of extensions (Matlab fct .m or compiled version .sh)
165[s,w]=system('oarstat'); % look for cluster system 'oar'
166if isequal(s,0)
167    RunModeList=[RunModeList;{'cluster_oar'}];
168    set(handles.MonitorCluster,'Visible','on'); % make visible button for access to Monika
169    set(handles.num_CPUTime,'Visible','on'); % make visible button for access to Monika
170    set(handles.CPUTime_txt,'Visible','on'); % make visible button for access to Monika
171end
172[s,w]=system('qstat -help'); % look for cluster system 'sge'
173if isequal(s,0)
174    if regexp(w,'^pbs')
175        RunModeList=[RunModeList;{'cluster_pbs'}];
176    elseif regexp(w,'^SGE')
177        RunModeList=[RunModeList;{'cluster_sge'}];
178    else
179        RunModeList=[RunModeList;{'cluster_qstat_unknown'}];
180    end
181end
182set(handles.RunMode,'String',RunModeList)% display the menu of available run modes, local, background or cluster manager
183
184%% list of builtin transform functions in the menu TransformName
185TransformList={'';'sub_field';'phys';'phys_polar'}; % WARNING: must fit with the corresponding menu in uvmat and nb_builtin_transform=4 in  TransformName_callback
186NbBuiltinTransform=numel(TransformList);
187path_transform_fct=fullfile(path_series,'transform_field');
188TransformPathList=cell(NbBuiltinTransform,1); % initiate the cell matrix of Action fct paths
189TransformPathList(:)={path_transform_fct}; % set the default path to series fcts to all list members
190SeriesData.TransformPath=path_transform_fct;% store the standard path for trqnsform functions (needed for compilation)
191
192%% get the user defined functions stored in the personal file uvmat_perso.mat
193dir_perso=prefdir;
194profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
195if exist(profil_perso,'file')
196    h=load (profil_perso);
197    %get the list of previous input files in the upper bar menu Open
198    if isfield(h,'MenuFile')
199        for ifile=1:min(length(h.MenuFile),5)
200            set(handles.(['MenuFile_' num2str(ifile)]),'Label',h.MenuFile{ifile});
201            set(handles.(['MenuFile_' num2str(ifile+5)]),'Label',h.MenuFile{ifile});
202        end
203    end
204    %get the list of previous campaigns in the upper bar menu Open campaign
205    if isfield(h,'MenuCampaign')
206        for ifile=1:min(length(h.MenuCampaign),5)
207            set(handles.(['MenuCampaign_' num2str(ifile)]),'Label',h.MenuCampaign{ifile});
208        end
209    end
210    %get the menu of actions
211%     if isfield(h,'ActionExtListUser') && iscell(h.ActionExtListUser)
212%         ActionExtList=[ActionExtList; h.ActionExtListUser];
213%     end
214    if isfield(h,'ActionListUser') && iscell(h.ActionListUser) && isfield(h,'ActionPathListUser') && iscell(h.ActionPathListUser)
215        ActionList=[ActionList;h.ActionListUser];
216        ActionPathList=[ActionPathList;h.ActionPathListUser(:,1)];
217    end
218    %get the menu of transform fct
219    if isfield(h,'TransformListUser') && iscell(h.TransformListUser) && isfield(h,'TransformPathListUser') && iscell(h.TransformPathListUser)
220        TransformList=[TransformList;h.TransformListUser];
221        TransformPathList=[TransformPathList;h.TransformPathListUser];
222    end
223end
224
225%% selection of the input Action fct
226ActionCheckExist=true(size(ActionList)); % initiate the check of the path to the listed action fct
227for ilist=NbBuiltinAction+1:numel(ActionList)%check  the validity of the path of the user defined Action fct
228    ActionCheckExist(ilist)=exist(fullfile(ActionPathList{ilist},[ActionList{ilist} '.m']),'file');
229end
230ActionPathList=ActionPathList(ActionCheckExist,:); % suppress the menu options which are not valid anymore
231ActionList=ActionList(ActionCheckExist);
232set(handles.ActionName,'String',[ActionList;{'more...'}])
233set(handles.ActionName,'UserData',ActionPathList)
234ActionIndex=[];
235if isfield(Param,'ActionName')% copy the selected menu index transferred in Param from uvmat
236    ActionIndex=find(strcmp(Param.ActionName,ActionList),1);
237end
238if isempty(ActionIndex)
239    ActionIndex=1;
240end
241set(handles.ActionName,'Value',ActionIndex)
242set(handles.ActionPath,'String',ActionPathList{ActionIndex})
243set(handles.ActionExt,'Value',1)
244set(handles.ActionExt,'String',ActionExtList)
245
246%% selection of the input transform fct
247TransformCheckExist=true(size(TransformList));
248for ilist=NbBuiltinTransform+1:numel(TransformList)
249    TransformCheckExist(ilist)=exist(fullfile(TransformPathList{ilist},[TransformList{ilist} '.m']),'file');
250end
251TransformPathList=TransformPathList(TransformCheckExist);
252TransformList=TransformList(TransformCheckExist);
253set(handles.TransformName,'String',[TransformList;{'more...'}])
254set(handles.TransformName,'UserData',TransformPathList)
255TransformIndex=[];
256if isfield(Param,'TransformName')% copy the selected menu index transferred in Param from uvmat
257    TransformIndex=find(strcmp(Param.TransformName,TransformList),1);
258end
259if isempty(TransformIndex)
260    TransformIndex=1;
261end
262set(handles.TransformName,'Value',TransformIndex)
263set(handles.TransformPath,'String',TransformPathList{TransformIndex})
264   
265%% fields input initialisation
266if isfield(Param,'list_fields')&& isfield(Param,'index_fields') &&~isempty(Param.list_fields) &&~isempty(Param.index_fields)
267    set(handles.FieldName,'String',Param.list_fields); % list menu fields
268    set(handles.FieldName,'Value',Param.index_fields); % selected string index
269end
270if isfield(Param,'Coordinates')
271    if isfield(Param.Coordinates,'Coord_x')
272        set(handles.Coord_x,'String',Param.Coordinates.Coord_x)
273    end
274    if isfield(Param.Coordinates,'Coord_y')
275        set(handles.Coord_y,'String',Param.Coordinates.Coord_y)
276    end
277    if isfield(Param.Coordinates,'Coord_z')
278        set(handles.Coord_z,'String',Param.Coordinates.Coord_z)
279    end
280end
281% if isfield(Param,'Coord_x_str') && ischar(Param.Coord_x_str)
282%         set(handles.Coord_x,'String',Param.Coord_x_str); % list menu fields
283% end
284% if isfield(Param,'Coord_y_str')&& ischar(Param.Coord_y_str)
285%         set(handles.Coord_y,'String',Param.Coord_y_str); % list menu fields
286% end
287
288%% introduce the input file name(s) if defined from input Param,
289set(handles.series,'UserData',SeriesData)% initiate Userdata
290if isfield(Param,'InputFile')
291   
292    %% fill the list of file series
293    InputTable=[{Param.InputFile.RootPath},{Param.InputFile.SubDir},{Param.InputFile.RootFile},{Param.InputFile.NomType},{Param.InputFile.FileExt}];
294    if isempty(find(cellfun('isempty',InputTable)==0)); % if there is no input file, do not introduce input info
295        set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH button to magenta color to indicate that input refresh is needed
296        return
297    end
298    TimeTable=[{Param.InputFile.TimeName},{[]},{[]},{[]},{[]}];
299    if isfield(Param.InputFile,'RootPath_1')
300        InputTable=[InputTable;[{Param.InputFile.RootPath_1},{Param.InputFile.SubDir_1},{Param.InputFile.RootFile_1},{Param.InputFile.NomType_1},{Param.InputFile.FileExt_1}]];
301        TimeTable=[TimeTable; [{Param.InputFile.TimeName_1},{[]},{[]},{[]},{[]}]];
302    end
303    set(handles.InputTable,'Data',InputTable)
304    %% determine the selected reference field indices for pair display
305   
306    [tild,tild,tild,i1,i2,j1,j2]=fileparts_uvmat(Param.InputFile.FileIndex);
307    if isempty(i1)
308        i1=1;
309    end
310    if isempty(i2)
311        i2=i1;
312    end
313    ref_i=floor((i1+i2)/2); % reference image number corresponding to the file
314    % set(handles.num_ref_i,'String',num2str(ref_i));
315    if isempty(j1)
316        j1=1;
317    end
318    if isempty(j2)
319        j2=j1;
320    end
321    ref_j=floor((j1+j2)/2); % reference image number corresponding to the file
322    SeriesData.ref_i=ref_i;
323    SeriesData.ref_j=ref_j;
324    set(handles.series,'UserData',SeriesData)
325    update_rootinfo(handles,Param.HiddenData.i1_series{1},Param.HiddenData.i2_series{1},Param.HiddenData.j1_series{1},Param.HiddenData.j2_series{1},...
326        Param.HiddenData.FileInfo{1},Param.HiddenData.MovieObject{1},1)
327    if isfield(Param,'FileName_1')
328        %         display_file_name(handles,Param,2)
329        update_rootinfo(handles,Param.HiddenData.i1_series{2},Param.HiddenData.i2_series{2},Param.HiddenData.j1_series{2},Param.HiddenData.j2_series{2},...
330            Param.HiddenData.FileInfo{2},Param.HiddenData.MovieObject{2},2)
331    end
332    %% enable field and veltype menus, in accordance with the current action
333    ActionName_Callback([],[], handles)
334   
335    %% set length of waitbar
336    displ_time(handles)
337   
338else
339    set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH button to magenta color to indicate that input refresh is needed
340end
341if isfield(Param,'incr_i')
342    set(handles.num_incr_i,'String',num2str(Param.incr_i))
343else
344    set(handles.num_incr_i,'String','1')
345end
346if isfield(Param,'incr_j')
347    set(handles.num_incr_j,'String',num2str(Param.incr_j))
348else
349    set(handles.num_incr_j,'String','1')
350end
351
352%------------------------------------------------------------------------
353% --- Outputs from this function are returned to the command line.
354function varargout = series_OutputFcn(hObject, eventdata, handles)
355%------------------------------------------------------------------------
356varargout{1} = handles.output;
357
358%------------------------------------------------------------------------
359% --- executed when closing uvmat: delete or desactivate the associated figures if exist
360function closefcn(gcbo,eventdata)
361%------------------------------------------------------------------------
362
363% delete set_object_series if detected
364hh=findobj(allchild(0),'name','view_object_series');
365if ~isempty(hh)
366    delete(hh)
367end
368hh=findobj(allchild(0),'name','edit_object_series');
369if ~isempty(hh)
370    delete(hh)
371end
372
373%delete the bowser if detected
374hh=findobj(allchild(0),'tag','browser');
375if ~isempty(hh)
376    delete(hh)
377end
378
379
380%------------------------------------------------------------------------
381%------------------------------------------------------------------------
382%  II - FUNCTIONS FOR INTRODUCING THE INPUT FILES
383% automatically sets the global properties when the rootfile name is introduced
384% then activate the view-field actionname if selected
385% it is activated either by clicking on the RootPath window or by the
386% browser
387%------------------------------------------------------------------------
388%------------------------------------------------------------------------
389% --- fct activated by the browser under 'Open'
390%------------------------------------------------------------------------ 
391function MenuBrowse_Callback(hObject, eventdata, handles)
392%% look for the previously opened file 'oldfile'
393InputTable=get(handles.InputTable,'Data');
394oldfile=InputTable{1,1};
395if isempty(oldfile)
396    % use a file name stored in prefdir
397    dir_perso=prefdir;
398    profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
399    if exist(profil_perso,'file')
400        h=load (profil_perso);
401        if isfield(h,'RootPath') && ischar(h.RootPath)
402            oldfile=h.RootPath;
403        end
404    end
405end
406%% launch the browser
407fileinput=uigetfile_uvmat('pick an input file in the series',oldfile);
408hh=dir(fileinput);
409if numel(hh)>1
410    msgbox_uvmat('ERROR','invalid input, probably a broken link');
411else
412    if ~isempty(fileinput)
413        display_file_name(handles,fileinput,'one')
414    end
415end
416
417% --------------------------------------------------------------------
418function MenuBrowseAppend_Callback(hObject, eventdata, handles)
419
420%% look for the previously opened file 'oldfile'
421InputTable=get(handles.InputTable,'Data');
422RootPathCell=InputTable(:,1);
423if isempty(RootPathCell{1})% no input file in the table
424     MenuBrowse_Callback(hObject, eventdata, handles)%refresh the input table, not append
425     return
426end
427SubDirCell=InputTable(:,2);
428oldfile=fullfile(RootPathCell{1},SubDirCell{1});
429
430%% use a file name stored in prefdir
431dir_perso=prefdir;
432profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
433if exist(profil_perso,'file')
434    h=load (profil_perso);
435    if isfield(h,'RootPath') && ischar(h.RootPath)
436        oldfile=h.RootPath;
437    end
438end
439
440%% launch the browser
441fileinput=uigetfile_uvmat('pick a file to append in the input table',oldfile);
442hh=dir(fileinput);
443if numel(hh)>1
444    msgbox_uvmat('ERROR','invalid input, probably a broken link');
445else
446    if ~isempty(fileinput)
447        display_file_name(handles,fileinput,'append')
448    end
449end
450
451%------------------------------------------------------------------------
452% --- fct activated by selecting a previous file under the menu Open
453%------------------------------------------------------------------------
454function MenuFile_Callback(hObject, eventdata, handles)
455
456errormsg=display_file_name(handles,get(hObject,'Label'),'one');
457if ~isempty(errormsg)
458    set(hObject,'Label','')
459    MenuFile=[{get(handles.MenuFile_1,'Label')};{get(handles.MenuFile_2,'Label')};...
460        {get(handles.MenuFile_3,'Label')};{get(handles.MenuFile_4,'Label')};{get(handles.MenuFile_5,'Label')}];
461    str_find=strcmp(get(hObject,'Label'),MenuFile);
462    MenuFile(str_find)=[]; % suppress the input file to the list
463    for ifile=1:numel(MenuFile)
464        set(handles.(['MenuFile_' num2str(ifile)]),'Label',MenuFile{ifile});
465    end
466end
467
468%------------------------------------------------------------------------
469% --- fct activated by selecting a previous file under the menu Open/append
470%------------------------------------------------------------------------
471function MenuFile_append_Callback(hObject, eventdata, handles)
472
473InputTable=get(handles.InputTable,'Data');
474if isempty(InputTable{1,1})% no input file in the table
475    display_file_name(handles,get(hObject,'Label'),'one') %refresh the input table, not append
476else
477    display_file_name(handles,get(hObject,'Label'),'append')% append the selected file to the current list of InputTable
478end
479
480%------------------------------------------------------------------------
481% --- fct activated by the browser under 'Open campaign/Browse...'
482%------------------------------------------------------------------------
483function MenuBrowseCampaign_Callback(hObject, eventdata, handles)
484
485%% look for the previously opened file 'oldfile'
486InputTable=get(handles.InputTable,'Data');
487if ~isempty(InputTable)
488oldfile=fullfile(InputTable{1,1},InputTable{1,2});
489else
490    % use a file name stored in prefdir
491    dir_perso=prefdir;
492    profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
493    if exist(profil_perso,'file')
494        h=load (profil_perso);
495        if isfield(h,'MenuCampaign') && ~isempty(h.MenuCampaign)&& ischar(h.MenuCampaign{1})
496            oldfile=h.MenuCampaign{1};
497        end
498    end
499end
500
501OutPut=browse_data(oldfile,'on','on'); % open the GUI browse_data to get select a campaign dir, experiment and device
502NbLines=numel(OutPut.Experiment)*numel(OutPut.DataSeries);
503icount=0;
504for iexp=1:numel(OutPut.Experiment)
505    for idevice=1:numel(OutPut.DataSeries)
506        icount=icount+1;
507        InputTable{icount,1}=fullfile(OutPut.Campaign,OutPut.Experiment{iexp});
508        InputTable{icount,2}=OutPut.DataSeries{idevice};
509        if isempty(InputTable{icount,3})
510            if icount>1
511            InputTable{icount,3}=InputTable{icount-1,3};
512            else
513                InputTable{icount,3}='';
514            end
515        end
516        if isempty(InputTable{icount,4})
517            if icount>1
518            InputTable{icount,4}=InputTable{icount-1,4};
519            else
520                InputTable{icount,4}='';
521            end
522        end
523                if isempty(InputTable{icount,5})
524            if icount>1
525            InputTable{icount,5}=InputTable{icount-1,5};
526            else
527                InputTable{icount,5}='';
528            end
529        end
530    end
531end
532if size(InputTable,1)>icount
533    InputTable(icount+1:size(InputTable,1),:)=[];
534end
535set(handles.InputTable,'Data',InputTable)
536REFRESH_Callback(hObject, eventdata, handles)
537
538% --------------------------------------------------------------------
539function MenuCampaign_Callback(hObject, eventdata, handles)
540% --------------------------------------------------------------------
541
542OutPut=browse_data(get(hObject,'Label'),'on','on'); % open the GUI browse_data to get select a campaign dir, experiment and device
543if ~isfield(OutPut,'Campaign')
544    return
545end
546NbLines=numel(OutPut.Experiment)*numel(OutPut.DataSeries);
547icount=0;
548InputTable=get(handles.InputTable,'Data');
549for iexp=1:numel(OutPut.Experiment)
550    for idevice=1:numel(OutPut.DataSeries)
551        icount=icount+1;
552        InputTable{icount,1}=fullfile(OutPut.Campaign,OutPut.Experiment{iexp});
553        InputTable{icount,2}=OutPut.DataSeries{idevice};
554        if isempty(InputTable{icount,3})
555            if icount>1
556                InputTable{icount,3}=InputTable{icount-1,3};
557            else
558                InputTable{icount,3}='';
559            end
560        end
561        if isempty(InputTable{icount,4})
562            if icount>1
563                InputTable{icount,4}=InputTable{icount-1,4};
564            else
565                InputTable{icount,4}='';
566            end
567        end
568        if isempty(InputTable{icount,5})
569            if icount>1
570                InputTable{icount,5}=InputTable{icount-1,5};
571            else
572                InputTable{icount,5}='';
573            end
574        end
575    end
576end
577if size(InputTable,1)>icount
578    InputTable(icount+1:size(InputTable,1),:)=[];
579end
580set(handles.InputTable,'Data',InputTable)
581REFRESH_Callback(hObject, eventdata, handles)
582
583
584% --- Executes when selected cell(s) is changed in InputTable.
585function InputTable_CellSelectionCallback(hObject, eventdata, handles)
586iline=[];
587if ~isempty(eventdata.Indices)
588    iline=eventdata.Indices(1);
589end
590set(handles.InputLine,'String',num2str(iline));
591
592%------------------------------------------------------------------------
593% --- 'key_press_fcn:' function activated when a key is pressed on the keyboard
594%------------------------------------------------------------------------
595function InputTable_KeyPressFcn(hObject, eventdata, handles)
596set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH button to magenta color to indicate that input refresh is needed
597set(handles.OutputSubDir,'BackgroundColor',[1 0 1])% set edit box OutputSubDir to magenta color to indicate that refresh may be needed
598xx=double(get(handles.series,'CurrentCharacter')); % get the keyboard character
599if ~isempty(xx)
600    switch xx
601        case 31 %downward arrow
602            InputTable=get(handles.InputTable,'Data');
603            iline=str2double(get(handles.InputLine,'String'));
604            if isequal(iline,size(InputTable,1))% arrow downward
605                InputTable=[InputTable;InputTable(iline,:)]; % create a new line as a copy of the last one
606                set(handles.InputTable,'Data',InputTable);
607            end
608        case 127  %key 'Suppress'
609            ClearLine_Callback(hObject, eventdata, handles)
610    end
611end
612
613%------------------------------------------------------------------------
614% --- Executes on button press in REFRESH.
615function REFRESH_Callback(hObject, eventdata, handles)
616%------------------------------------------------------------------------
617InputTable=get(handles.InputTable,'Data');
618set(handles.series,'Pointer','watch') % set the mouse pointer to 'watch'
619set(handles.REFRESH,'BackgroundColor',[1 1 0])% set REFRESH  button to yellow color (indicate activation)
620drawnow
621empty_line=false(size(InputTable,1),1);
622for iline=1:size(InputTable,1)
623    empty_line(iline)= isempty(cell2mat(InputTable(iline,1:3)));
624end
625if ~isempty(find(empty_line));
626    InputTable(empty_line,:)=[]; % remove empty lines
627    set(handles.InputTable,'Data',InputTable)
628    ListTable={'MinIndex_i','MaxIndex_i','MinIndex_j','MaxIndex_j','PairString','TimeTable'};
629    for ilist=1:numel(ListTable)
630        Table=get(handles.(ListTable{ilist}),'Data');
631        Table(empty_line,:)=[]; % remove empty lines
632        set(handles.(ListTable{ilist}),'Data',Table);
633    end
634    set(handles.series,'UserData',[])%refresh the stored info
635end
636nbview=size(InputTable,1);
637for iview=1:nbview
638    RootPath=fullfile(InputTable{iview,1},InputTable{iview,2});
639    if ~exist(RootPath,'dir')
640        i1_series=[];
641        RootFile='';
642    else %scan the input folder
643            [RootPath,~,RootFile,i1_series,i2_series,j1_series,j2_series,tild,FileInfo,MovieObject]=...
644                find_file_series(fullfile(InputTable{iview,1},InputTable{iview,2}),[InputTable{iview,3} InputTable{iview,4} InputTable{iview,5}]);
645    end
646    % if no file is found, open a browser
647    if isempty(RootFile)&& isempty(i1_series)
648        fileinput=uigetfile_uvmat(['wrong input at line ' num2str(iview) ':pick a new input file'],RootPath);
649        if isempty(fileinput)
650            set(handles.REFRESH,'BackgroundColor',[1 0 0])% set REFRESH  back to red color
651            return
652        else
653            display_file_name(handles,fileinput,iview)
654        end
655    else
656       update_rootinfo(handles,i1_series,i2_series,j1_series,j2_series,FileInfo,MovieObject,iview)
657    end
658end
659
660%% update MinIndex_i and MaxIndex_i if the input table content has been reduced in line nbre
661MinIndex_i_table=get(handles.MinIndex_i,'Data'); % retrieve the min indices in the table MinIndex
662set(handles.MinIndex_i,'Data',MinIndex_i_table(1:nbview,:));
663MinIndex_j_table=get(handles.MinIndex_j,'Data'); % retrieve the min indices in the table MinIndex
664set(handles.MinIndex_j,'Data',MinIndex_j_table(1:nbview,:));
665MaxIndex_i_table=get(handles.MaxIndex_i,'Data'); % retrieve the min indices in the table MinIndex
666
667set(handles.MaxIndex_i,'Data',MaxIndex_i_table(1:nbview,:));
668MaxIndex_j_table=get(handles.MaxIndex_j,'Data'); % retrieve the min indices in the table MinIndex
669set(handles.MaxIndex_j,'Data',MaxIndex_j_table(1:nbview,:));
670PairString=get(handles.PairString,'Data'); % retrieve the min indices in the table MinIndex
671set(handles.PairString,'Data',PairString(1:nbview,:));
672TimeTable=get(handles.TimeTable,'Data'); % retrieve the min indices in the table MinIndex
673set(handles.TimeTable,'Data',TimeTable(1:nbview,:));
674
675%% set length of waitbar
676displ_time(handles)
677set(handles.REFRESH,'BackgroundColor',[1 0 0])% set REFRESH  button to red color (indicate activation finished)
678set(handles.series,'Pointer','arrow') % set the mouse pointer to 'watch'
679
680%% enable field and veltype menus, in accordance with the current action
681ActionInput_Callback([],[], handles)
682
683
684%------------------------------------------------------------------------
685% --- Function called when a new file is opened, either by series_OpeningFcn or by the browser
686%------------------------------------------------------------------------
687% INPUT:
688% handles: handles of elements in the GUI
689% Param: structure of input parameters, including  input file name and path
690% iview: line index in the input table
691%       or 'one': refresh the list
692%         'append': add a new line to the input table
693function errormsg=display_file_name(handles,Param,iview)
694 
695set(handles.REFRESH,'BackgroundColor',[1 1 0])% set REFRESH  button to yellow color (indicate activation)
696drawnow
697errormsg=''; % default
698if ischar(Param)
699    fileinput=Param;
700else% input set when series is opened (called by the GUI uvmat)
701    fileinput=Param.FileName;
702end
703   
704%% get the input root name, indices, file extension and nomenclature NomType
705if ~exist(fileinput,'file')
706    errormsg=['input file ' fileinput  ' does not exist'];
707    msgbox_uvmat('ERROR',errormsg)
708    set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH  button to magenta color (refresh still needed)
709    return
710end
711
712%% detect root name, nomenclature and indices in the input file name:
713[FilePath,FileName,FileExt]=fileparts(fileinput);
714%%%%%%%%%%%%%%%%%%
715%TODO: case of input by uvmat: do not check agai the input seies %%%%%%%
716%%%%%%%%%%%%%%%%%%%
717% detect the file type, get the movie object if relevant, and look for the corresponding file series:
718% the root name and indices may be corrected by including the first index i1 if a corresponding xml file exists
719[RootPath,SubDir,RootFile,i1_series,i2_series,j1_series,j2_series,NomType,FileInfo,MovieObject,i1,i2,j1,j2]=find_file_series(FilePath,[FileName FileExt]);
720FileType=FileInfo.FileType;
721if isempty(RootFile)&&isempty(i1_series)
722    errormsg='no input file in the series';
723    msgbox_uvmat('ERROR',errormsg)
724    set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH  button to magenta color (end of activation)
725    return
726end
727if strcmp(FileType,'txt')
728    edit(fileinput)
729    set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH  button to  magenta color (end of activation)
730    return
731elseif strcmp(FileType,'xml')
732    editxml(fileinput)
733    set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH  button to magenta  color (end of activation)
734     return
735elseif strcmp(FileType,'figure')
736    open(fileinput)
737    set(handles.REFRESH,'BackgroundColor',[1 0 1])% set REFRESH  button to magenta  color (end of activation)
738     return
739end
740
741%% enable other menus and uicontrols
742% set(handles.MenuOpenCampaign,'Enable','on')
743set(handles.MenuCampaign_1,'Enable','on')
744set(handles.MenuCampaign_2,'Enable','on')
745set(handles.MenuCampaign_3,'Enable','on')
746set(handles.MenuCampaign_4,'Enable','on')
747set(handles.MenuCampaign_5,'Enable','on')
748set(handles.RUN, 'Enable','On')
749set(handles.RUN,'BackgroundColor',[1 0 0])% set RUN button to red
750set(handles.InputTable,'BackgroundColor',[1 1 0]) % set RootPath edit box  to yellow
751drawnow
752
753
754%% fill the list of file series
755InputTable=get(handles.InputTable,'Data');
756SeriesData=get(handles.series,'UserData');
757if strcmp(iview,'append') % display the input data as a new line in the table
758    iview=size(InputTable,1)+1; % the next line in InputTable becomes the current line
759%     InputTable(iview,:)=[{RootPath},{SubDir},{RootFile},{NomType},{FileExt}];
760elseif strcmp(iview,'one') % refresh the list of  input  file series
761    iview=1; % the first line in InputTable becomes the current line
762    InputTable={'','','','',''};
763%     InputTable(iview,:)=[{RootPath},{SubDir},{RootFile},{NomType},{FileExt}];
764    set(handles.TimeTable,'Data',[{''},{[]},{[]},{[]},{[]}])
765    set(handles.MinIndex_i,'Data',[])
766    set(handles.MaxIndex_i,'Data',[])
767    set(handles.MinIndex_j,'Data',[])
768    set(handles.MaxIndex_j,'Data',[])
769    set(handles.PairString,'Data',{''})
770    SeriesData.CheckPair=0; % reset the list of input lines with pairs
771    SeriesData.i1_series={};
772    SeriesData.i2_series={};
773    SeriesData.j1_series={};
774    SeriesData.j2_series={};
775    SeriesData.FileType={};
776    SeriesData.FileInfo={};
777    SeriesData.Time={};
778end
779if isfield(SeriesData,'i1_series')
780    SeriesData.i1_series(iview+1:end)=[];
781    SeriesData.i2_series(iview+1:end)=[];
782    SeriesData.j1_series(iview+1:end)=[];
783    SeriesData.j2_series(iview+1:end)=[];
784    SeriesData.FileType(iview+1:end)=[];
785    SeriesData.FileInfo(iview+1:end)=[];
786    SeriesData.Time(iview+1:end)=[];
787end
788InputTable(iview,:)=[{RootPath},{SubDir},{RootFile},{NomType},{FileExt}];
789if iview >1
790    set(handles.InputLine,'String',num2str(iview))
791end
792set(handles.InputTable,'Data',InputTable)
793
794%% determine the selected reference field indices for pair display
795if isempty(i1)
796    i1=1;
797end
798if isempty(i2)
799    i2=i1;
800end
801ref_i=floor((i1+i2)/2); % reference image number corresponding to the file
802% set(handles.num_ref_i,'String',num2str(ref_i));
803if isempty(j1)
804    j1=1;
805end
806if isempty(j2)
807    j2=j1;
808end
809ref_j=floor((j1+j2)/2); % reference image number corresponding to the file
810SeriesData.ref_i=ref_i;
811SeriesData.ref_j=ref_j;
812
813%% update first and last indices if they do not exist
814Param=read_GUI(handles.series);
815first_j=[];
816if isfield(Param.IndexRange,'first_j'); first_j=Param.IndexRange.first_j; end
817last_j=[];
818if isfield(Param.IndexRange,'last_j'); last_j=Param.IndexRange.last_j; end
819PairString='';
820if isfield(Param.IndexRange,'PairString'); PairString=Param.IndexRange.PairString; end
821[i1,i2,j1,j2] = get_file_index(Param.IndexRange.first_i,first_j,PairString);
822FirstFileName=fullfile_uvmat(Param.InputTable{1,1},Param.InputTable{1,2},Param.InputTable{1,3},...
823    Param.InputTable{1,5},Param.InputTable{1,4},i1,i2,j1,j2);
824if ~exist(FirstFileName,'file')
825    set(handles.num_first_i,'String',num2str(ref_i))
826    set(handles.num_first_j,'String',num2str(ref_j))
827end
828[i1,i2,j1,j2] = get_file_index(Param.IndexRange.last_i,last_j,PairString);
829LastFileName=fullfile_uvmat(Param.InputTable{1,1},Param.InputTable{1,2},Param.InputTable{1,3},...
830    Param.InputTable{1,5},Param.InputTable{1,4},i1,i2,j1,j2);
831if ~exist(LastFileName,'file')
832    set(handles.num_last_i,'String',num2str(ref_i))
833    set(handles.num_last_j,'String',num2str(ref_j))
834end
835
836%% update the list of recent files in the menubar and save it for future opening
837MenuFile=[{get(handles.MenuFile_1,'Label')};{get(handles.MenuFile_2,'Label')};...
838    {get(handles.MenuFile_3,'Label')};{get(handles.MenuFile_4,'Label')};{get(handles.MenuFile_5,'Label')}];
839str_find=strcmp(fileinput,MenuFile);
840if isempty(find(str_find,1))
841    MenuFile=[{fileinput};MenuFile]; % insert the current file if not already in the list
842end
843for ifile=1:min(length(MenuFile),5)
844    eval(['set(handles.MenuFile_' num2str(ifile) ',''Label'',MenuFile{ifile});'])
845end
846dir_perso=prefdir;
847profil_perso=fullfile(dir_perso,'uvmat_perso.mat');
848if exist(profil_perso,'file')
849    save (profil_perso,'MenuFile','-append'); % store the file names for future opening of uvmat
850else
851    save (profil_perso,'MenuFile','-V6'); % store the file names for future opening of uvmat
852end
853% save the opened file to initiate future opening
854SeriesData.RefFile{iview}=fileinput; % reference opening file for line iview
855SeriesData.Ref_i1=i1;
856SeriesData.Ref_i2=i2;
857SeriesData.Ref_j1=j1;
858SeriesData.Ref_j2=j2;
859set(handles.series,'UserData',SeriesData)
860
861set(handles.InputTable,'BackgroundColor',[1 1 1])
862
863%% initiate input file series and refresh the current field view:     
864update_rootinfo(handles,i1_series,i2_series,j1_series,j2_series,FileInfo,MovieObject,iview);
865%% enable field and veltype menus, in accordance with the current action
866ActionName_Callback([],[], handles)
867
868%% set length of waitbar
869displ_time(handles)
870
871set(handles.REFRESH,'BackgroundColor',[1 0 0])% set REFRESH  button to red color (end of activation)
872
873%------------------------------------------------------------------------
874% --- Update information about a new field series (indices to scan, timing,
875%     calibration from an xml file
876function update_rootinfo(handles,i1_series,i2_series,j1_series,j2_series,FileInfo,VideoObject,iview)
877%------------------------------------------------------------------------
878InputTable=get(handles.InputTable,'Data');
879
880%% display the min and max indices for the whole file series
881if size(i1_series,2)==2 && min(min(i1_series(:,1,:)))==0
882    MinIndex_j=1; % index j set to 1 by default
883    MaxIndex_j=1;
884    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)
885    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)
886else
887    ref_i=squeeze(max(i1_series(1,:,:),[],2)); % select ref_j index for each ref_i
888    ref_j=squeeze(max(j1_series(1,:,:),[],3)); % select ref_i index for each ref_j
889     MinIndex_i=min(find(ref_i))-1;
890     MaxIndex_i=max(find(ref_i))-1;
891     MaxIndex_j=max(find(ref_j))-1;
892     MinIndex_j=min(find(ref_j))-1;
893    diff_j_max=diff(ref_j);
894    diff_i_max=diff(ref_i);
895    if ~isempty(diff_i_max) && isequal (diff_i_max,diff_i_max(1)*ones(size(diff_i_max)))
896        set(handles.num_incr_i,'String',num2str(diff_i_max(1)))% detect an increment to dispaly by default
897    end
898    if ~isempty(diff_j_max) && isequal (diff_j_max,diff_j_max(1)*ones(size(diff_j_max)))
899        set(handles.num_incr_j,'String',num2str(diff_j_max(1)))
900    end
901end
902if isequal(MinIndex_i,-1)
903    MinIndex_i=0;
904end
905if isequal(MinIndex_j,-1)
906    MinIndex_j=0;
907end
908MinIndex_i_table=get(handles.MinIndex_i,'Data'); % retrieve the min indices in the table MinIndex
909MinIndex_j_table=get(handles.MinIndex_j,'Data'); % retrieve the min indices in the table MinIndex
910MaxIndex_i_table=get(handles.MaxIndex_i,'Data'); % retrieve the min indices in the table MinIndex
911MaxIndex_j_table=get(handles.MaxIndex_j,'Data'); % retrieve the min indices in the table MinIndex
912if ~isempty(MinIndex_i)&&~isempty(MaxIndex_i)
913    MinIndex_i_table(iview,1)=MinIndex_i;
914    MaxIndex_i_table(iview,1)=MaxIndex_i;
915end
916if ~isempty(MinIndex_j)&&~isempty(MaxIndex_j)
917    MinIndex_j_table(iview,1)=MinIndex_j;
918    MaxIndex_j_table(iview,1)=MaxIndex_j;
919end
920set(handles.MinIndex_i,'Data',MinIndex_i_table)%display the min indices in the table MinIndex
921set(handles.MinIndex_j,'Data',MinIndex_j_table)%display the max indices in the table MaxIndex
922set(handles.MaxIndex_i,'Data',MaxIndex_i_table)%display the min indices in the table MinIndex
923set(handles.MaxIndex_j,'Data',MaxIndex_j_table)%display the max indices in the table MaxIndex
924SeriesData=get(handles.series,'UserData');
925
926%% adjust the first and last indices for the selected series, only if requested by the bounds
927% i index, compare input to min index i
928first_i=str2num(get(handles.num_first_i,'String')); % retrieve previous first i
929% ref_i=str2num(get(handles.num_ref_i,'String')); % index i given by the input field
930ref_i=1;
931if isfield(SeriesData,'ref_i')
932    ref_i=SeriesData.ref_i;
933end
934if isempty(first_i)
935    first_i=ref_i; % first_i updated by the input value
936elseif first_i < MinIndex_i
937    first_i=MinIndex_i; % first_i set to the min i index (restricted by oter input lines)
938elseif first_i >MaxIndex_i
939    first_i=MaxIndex_i; % first_i set to the max i index (restricted by oter input lines)
940end
941% j index,  compare input to min index j
942first_j=str2num(get(handles.num_first_j,'String'));
943ref_j=1;
944if isfield(SeriesData,'ref_j')
945    ref_j=SeriesData.ref_j;
946end
947if isempty(first_j)
948    first_j=ref_j; % first_j updated by the input value
949elseif first_j<MinIndex_j
950    first_j=MinIndex_j; % first_j set to the min j index (restricted by oter input lines)
951elseif first_j >MaxIndex_j
952    first_j=MaxIndex_j; % first_j set to the max j index (restricted by oter input lines)
953end
954% i index, compare input to max index i
955last_i=str2num(get(handles.num_last_i,'String'));
956if isempty(last_i)
957    last_i=ref_i;
958elseif last_i > MaxIndex_i
959    last_i=MaxIndex_i;
960elseif last_i<first_i
961    last_i=first_i;
962end
963% j index, compare input to max index j
964last_j=str2num(get(handles.num_last_j,'String'));
965if isempty(last_j)
966    last_j=ref_j;
967elseif last_j>MaxIndex_j
968    last_j=MaxIndex_j;
969elseif last_j<first_j
970    last_j=first_j;
971end
972set(handles.num_first_i,'String',num2str(first_i));
973set(handles.num_first_j,'String',num2str(first_j));
974set(handles.num_last_i,'String',num2str(last_i));
975set(handles.num_last_j,'String',num2str(last_j));
976
977%% number of slices set by default
978NbSlice=[]; % default
979% read  value set by the first series for the append mode (iwiew >1)
980if iview>1 && strcmp(get(handles.num_NbSlice,'Visible'),'on')
981    NbSlice=str2double(get(handles.num_NbSlice,'String'));
982end
983
984%% default time settings
985TimeUnit='';
986% read  value set by the first series for the append mode (iwiew >1)
987if iview>1
988    TimeUnit=get(handles.TimeUnit,'String');
989end
990TimeName='';
991Time=[]; % default
992TimeMin=[];
993TimeFirst=[];
994TimeLast=[];
995TimeMax=[];
996
997%%  read image documentation file if found
998XmlData=[];
999check_calib=0;
1000XmlFileName=find_imadoc(InputTable{iview,1},InputTable{iview,2},InputTable{iview,3},InputTable{iview,5});
1001if ~isempty(XmlFileName)
1002    [XmlData,errormsg]=imadoc2struct(XmlFileName);
1003    if ~isempty(errormsg)
1004        msgbox_uvmat('WARNING',['error in reading ' XmlFileName ': ' errormsg]);
1005    end
1006    % read time if available
1007    if isfield(XmlData,'Time')
1008        Time=XmlData.Time;
1009        TimeName='xml';
1010%                         if XmlData.Time(1,:)==XmlData.Time(2,:)% case starting with index 1
1011%                     sizDti=size(XmlData.Time,1)-1; % size of the time vector explicitly defined in the xml file
1012%                     ind_start=1;
1013%                 else
1014%                     sizDti=size(XmlData.Time,1); % case starting with index 0
1015%                     ind_start=0;
1016%                 end
1017%         % complement the input if the whole time series is not defined
1018%             if size(i1_series,3)>size(XmlData.Time,1)-ind_start %only the first time interval is defined, extrapolate to the whole series
1019%                 Dti_total=XmlData.Time(end)-XmlData.Time(1); % total time interval covered by the time vector
1020%                 missing_indices=sizDti+1+ind_start:size(i1_series,3)+1; % remaining set of frame indices for which time needs to be found
1021%                 repeat_nbre=1+floor((missing_indices-sizDti-ind_start)/(sizDti-1)); % number of repetitions of Dti
1022%                 time_indices=1+mod(missing_indices-sizDti-1,sizDti-1);
1023%                 for j=1:size(XmlData.Time,2)
1024%                 Time(missing_indices,j)=XmlData.Time(time_indices,j)+repeat_nbre'*Dti_total;
1025%                 end
1026%                 % update the xml file with NbDti
1027%                 t=xmltree(XmlFileName);
1028%                 uid_NbDti=find(t,'ImaDoc/Camera/BurstTiming/NbDti')
1029%                 if isempty(uid_NbDti)
1030%                     uid_BurstTiming=find(t,'ImaDoc/Camera/BurstTiming')
1031%                     [t,uid_NbDti]=add(t,uid_BurstTiming,'element','NbDti');
1032%                 end
1033%                 [t,uid_NbDti]=add(t,uid_NbDti,'chardata',num2str(repeat_nbre(end)-1));
1034%                 save(t,XmlFileName)
1035%             end
1036    end
1037    if isfield(XmlData,'Camera')
1038        %         if isfield(XmlData.Camera,'NbSlice')&& ~isempty(XmlData.Camera.NbSlice)
1039        %             if iview>1 && ~isempty(NbSlice) && ~strcmp(NbSlice,XmlData.Camera.NbSlice)
1040        %                 msgbox_uvmat('WARNING','inconsistent number of slices with the first field series');
1041        %             end
1042        %             NbSlice=XmlData.Camera.NbSlice; % Nbre of slices from camera
1043        %         end
1044        if isfield(XmlData.Camera,'TimeUnit')&& ~isempty(XmlData.Camera.TimeUnit)
1045            if iview>1 && ~isempty(TimeUnit) && ~strcmp(TimeUnit,XmlData.Camera.TimeUnit)
1046                msgbox_uvmat('WARNING','inconsistent time unit with the first field series');
1047            end
1048            TimeUnit=XmlData.Camera.TimeUnit;
1049        end
1050    end
1051    % number of slices
1052    if isfield(XmlData,'TranslationMotor')&& isfield(XmlData.TranslationMotor,'NbSlice')
1053        NbSlice_motor=XmlData.TranslationMotor.NbSlice;
1054        if ~isempty(NbSlice) && ~isequal(NbSlice_motor,NbSlice)
1055                msgbox_uvmat('WARNING','inconsistent Z numbers of Z indices');
1056        else
1057            NbSlice=NbSlice_motor;
1058        end
1059    end
1060   
1061    if isfield(XmlData,'GeometryCalib')
1062        check_calib=1;
1063        if isfield(XmlData.GeometryCalib,'SliceCoord')
1064            siz=size(XmlData.GeometryCalib.SliceCoord);
1065            if ~isempty(NbSlice)&& ~isequal(size(1),NbSlice)
1066                msgbox_uvmat('WARNING','inconsistent numbers of Z indices between motor and calibration');
1067            else
1068                NbSlice=siz(1);
1069            end
1070        end
1071    end
1072end
1073if ~isempty(NbSlice)
1074set(handles.num_NbSlice,'String',num2str(NbSlice))
1075set(handles.num_NbSlice,'Visible','on')
1076end
1077
1078%% read timing  from the current file (prioritary)
1079if ~isempty(VideoObject)% case of movies
1080    imainfo=get(VideoObject);
1081    if isempty(j1_series); % frame index along i
1082        Time=zeros(imainfo.NumberOfFrames+1,2);
1083        Time(:,2)=(0:1/imainfo.FrameRate:(imainfo.NumberOfFrames)/imainfo.FrameRate)';
1084    else
1085        Time=[0;ones(size(i1_series,3)-1,1)]*(0:1/imainfo.FrameRate:(imainfo.NumberOfFrames)/imainfo.FrameRate);
1086    end
1087    TimeName='video';
1088end
1089
1090
1091%% determine the min and max times: case of Netcdf files will be treated later in FieldName_Callback
1092if ~isempty(TimeName)
1093    TimeMin=Time(MinIndex_i+1,MinIndex_j+1);
1094    if size(Time)>=[first_i+1 first_j+1]
1095        TimeFirst=Time(first_i+1,first_j+1);
1096    end
1097    if size(Time)>=[last_i+1 last_j+1]
1098        TimeLast=Time(last_i+1,last_j+1);
1099    end
1100    if size(Time)>=[MaxIndex_i+1 MaxIndex_j+1];
1101        TimeMax=Time(MaxIndex_i+1,MaxIndex_j+1);
1102    end
1103end
1104
1105%% update the time table
1106TimeTable=get(handles.TimeTable,'Data');
1107TimeTable{iview,1}=TimeName;
1108TimeTable{iview,2}=TimeMin;
1109TimeTable{iview,3}=TimeFirst;
1110TimeTable{iview,4}=TimeLast;
1111TimeTable{iview,5}=TimeMax;
1112set(handles.TimeTable,'Data',TimeTable)
1113
1114%% update the series info in 'UserData'
1115SeriesData.i1_series{iview}=i1_series;
1116SeriesData.i2_series{iview}=i2_series;
1117SeriesData.j1_series{iview}=j1_series;
1118SeriesData.j2_series{iview}=j2_series;
1119SeriesData.FileType{iview}=FileInfo.FileType;
1120SeriesData.FileInfo{iview}=FileInfo;
1121SeriesData.Time{iview}=Time;
1122% if ~isempty(TimeName)
1123%     SeriesData.TimeSource=TimeSource;
1124% end
1125if check_calib
1126    SeriesData.GeometryCalib{iview}=XmlData.GeometryCalib;
1127end
1128set(handles.series,'UserData',SeriesData)
1129
1130%% update pair menus
1131hset_pair=findobj(allchild(0),'Tag','set_pairs');
1132if ~isempty(hset_pair), delete(hset_pair); end % delete the GUI set_pair if opened
1133CheckPair= ~isempty(i2_series)||~isempty(j2_series); % check whether index pairs need to be defined
1134PairString=get(handles.PairString,'Data');
1135if CheckPair% if pairs need to be display for line iview
1136    [ModeMenu,ModeValue]=update_mode(i1_series,i2_series,j2_series);
1137    Menu=update_listpair(i1_series,i2_series,j1_series,j2_series,ModeMenu{ModeValue},Time,TimeUnit,ref_i,ref_j,TimeName,InputTable(iview,:),FileInfo);
1138    PairString{iview,1}=Menu{1};
1139else
1140    PairString{iview,1}=''; % no pair for #iview
1141end
1142set(handles.PairString,'Data',PairString)
1143if isempty(find(cellfun('isempty',get(handles.PairString,'Data'))==0, 1))% if all lines of pairs are empty
1144    set(handles.PairString,'Visible','off')
1145    set(handles.SetPairs,'Visible','off')
1146else
1147    set(handles.PairString,'Visible','on')
1148    set(handles.SetPairs,'Visible','on')
1149end
1150
1151
1152%% display the set of existing files as an image
1153set(handles.FileStatus,'Units','pixels')
1154Position=get(handles.FileStatus,'Position');
1155set(handles.FileStatus,'Units','normalized')
1156%xI=0.5:Position(3)-0.5;
1157nbview=numel(SeriesData.i1_series);
1158j_max=cell(1,nbview);
1159MaxIndex_i=ones(1,nbview); % default
1160MinIndex_i=ones(1,nbview); % default
1161for iline=1:nbview
1162    pair_max=squeeze(max(SeriesData.i1_series{iline},[],1)); % max on pair index
1163    j_max{iline}=max(pair_max,[],1); % max on j index
1164    if ~isempty(j_max{iline})
1165    MaxIndex_i(iline)=max(find(j_max{iline}))-1; % max ref index i
1166    MinIndex_i(iline)=min(find(j_max{iline}))-1; % min ref index i
1167    end
1168end
1169MinIndex_i=min(MinIndex_i);
1170MaxIndex_i=max(MaxIndex_i);
1171range_index=MaxIndex_i-MinIndex_i+1;
1172range_y=max(1,floor(Position(4)/nbview));
1173npx=floor(Position(3));
1174file_indices=MinIndex_i+floor(((0.5:npx-0.5)/npx)*range_index)+1;
1175CData=zeros(nbview*range_y,npx); % initiate the image representing the existing files
1176for iline=1:nbview
1177    ind_y=1+(iline-1)*range_y:iline*range_y;
1178    LineData=zeros(size(file_indices));
1179    file_select=file_indices(file_indices<=numel(j_max{iline}));
1180    ind_select=find(file_indices<=numel(j_max{iline}));
1181    LineData(ind_select)=j_max{iline}(file_select)~=0;
1182    CData(ind_y,:)=ones(size(ind_y'))*LineData;
1183end
1184CData=cat(3,zeros(size(CData)),CData,zeros(size(CData))); % make color images r=0,g,b=0
1185set(handles.FileStatus,'CData',CData);
1186
1187%-----------------------------------------------------------guide -------------
1188%------------------------------------------------------------------------
1189%  III - FUNCTIONS ASSOCIATED TO THE FRAME IndexRange
1190%------------------------------------------------------------------------
1191
1192
1193% ---- determine the menu to put in mode and advice a default choice
1194%------------------------------------------------------------------------
1195function [ModeMenu,ModeValue]=update_mode(i1_series,i2_series,j2_series)
1196%------------------------------------------------------------------------   
1197ModeMenu={''};
1198if isempty(j2_series)% no j pair
1199    ModeValue=1;
1200    if ~isempty(i2_series)
1201        ModeMenu={'series(Di)'}; % pair menu with only option Di
1202    end
1203else %existence of j pairs
1204    pair_max=squeeze(max(i1_series,[],1)); % max on pair index
1205    j_max=max(pair_max,[],1);
1206    MaxIndex_i=find(j_max, 1, 'last' )-1; % max ref index i
1207    MinIndex_i=find(j_max, 1 )-1; % min ref index i
1208    i_max=max(pair_max,[],2);
1209    MaxIndex_j=find(i_max, 1, 'last' )-1; % max ref index i
1210    MinIndex_j=find(i_max, 1 )-1; % min ref index i
1211    if MaxIndex_j==MinIndex_j
1212        ModeValue=1;
1213        ModeMenu={'bursts'};
1214    elseif MaxIndex_i==MinIndex_i
1215        ModeValue=1;
1216        ModeMenu={'series(Dj)'};
1217    else
1218        ModeMenu={'bursts';'series(Dj)'};
1219        if (MaxIndex_j-MinIndex_j)>10
1220            ModeValue=2; % set mode to series(Dj) if more than 10 j values
1221        else
1222            ModeValue=1;
1223        end
1224    end
1225end
1226
1227
1228%------------------------------------------------------------------------
1229function displ_pair=update_listpair(i1_series,i2_series,j1_series,j2_series,mode,time,TimeUnit,ref_i,ref_j,TimeName,InputTable,FileInfo)
1230%------------------------------------------------------------------------
1231displ_pair={};
1232if isempty(TimeUnit)
1233    dtunit='e-03';
1234else
1235    dtunit=['m' TimeUnit];
1236end
1237switch mode
1238    case 'series(Di)'
1239        diff_i=i2_series-i1_series;
1240        min_diff=min(diff_i(diff_i>0));
1241        max_diff=max(diff_i(diff_i>0));
1242        for ipair=min_diff:max_diff
1243            if numel(diff_i(diff_i==ipair))>0
1244                pair_string=['Di= ' num2str(-floor(ipair/2)) '|' num2str(ceil(ipair/2)) ];
1245                if ~isempty(time)
1246                    if ref_i<=floor(ipair/2)
1247                        ref_i=floor(ipair/2)+1; % shift ref_i to get the first pair
1248                    end
1249                    Dt=time(ref_i+ceil(ipair/2),ref_j)-time(ref_i-floor(ipair/2),ref_j);
1250                    pair_string=[pair_string ', Dt=' num2str(Dt) ' ' dtunit];
1251                end
1252                displ_pair=[displ_pair;{pair_string}];
1253            end
1254        end
1255        if ~isempty(displ_pair)
1256            displ_pair=[displ_pair;{'Di=*|*'}];
1257        end
1258    case 'series(Dj)'
1259        if isempty(j2_series)
1260            msgbox_uvmat('ERROR','no j1-j2 pair available')
1261            return
1262        end
1263        diff_j=j2_series-j1_series;
1264        min_diff=min(diff_j(diff_j>0));
1265        max_diff=max(diff_j(diff_j>0));
1266        for ipair=min_diff:max_diff
1267            if numel(diff_j(diff_j==ipair))>0
1268                pair_string=['Dj= ' num2str(-floor(ipair/2)) '|' num2str(ceil(ipair/2)) ];
1269                if ~isempty(time)
1270                    if ref_j<=floor(ipair/2)
1271                        ref_j=floor(ipair/2)+1; % shift ref_i to get the first pair
1272                    end
1273                    Dt=time(ref_i,ref_j+ceil(ipair/2))-time(ref_i,ref_j-floor(ipair/2));
1274                    pair_string=[pair_string ', Dt=' num2str(Dt) ' ' dtunit];
1275                end
1276                displ_pair=[displ_pair;{pair_string}];
1277            end
1278        end
1279        if ~isempty(displ_pair)
1280            displ_pair=[displ_pair;{'Dj=*|*'}];
1281        end
1282    case 'bursts'
1283        if isempty(j2_series)
1284            msgbox_uvmat('ERROR','no j1-j2 pair available')
1285            return
1286        end
1287        %diff_j=j2_series-j1_series;
1288        min_j1=min(j1_series(j1_series>0));
1289        max_j1=max(j1_series(j1_series>0));
1290        min_j2=min(j2_series(j2_series>0));
1291        max_j2=max(j2_series(j2_series>0));
1292        for pair1=min_j1:min(max_j1,min_j1+20)
1293            for pair2=min_j2:min(max_j2,min_j2+20)
1294                if numel(j1_series(j1_series==pair1))>0 && numel(j2_series(j2_series==pair2))>0
1295                    pair_string=['j= ' num2str(pair1) '-' num2str(pair2)];
1296                    [TimeValue,DtValue]=get_time(ref_i,[],pair_string,InputTable,FileInfo,TimeName,'Dt');
1297                    %Dt=time(ref_i,pair2+1)-time(ref_i,pair1+1);
1298                    pair_string=[pair_string ', Dt=' num2str(DtValue) ' ' dtunit];
1299                    displ_pair=[displ_pair;{pair_string}];
1300                end
1301            end
1302        end
1303        if ~isempty(displ_pair)
1304            displ_pair=[displ_pair;{'j=*-*'}];
1305        end
1306end
1307
1308%------------------------------------------------------------------------
1309function num_first_i_Callback(hObject, eventdata, handles)
1310%------------------------------------------------------------------------
1311num_last_i_Callback(hObject, eventdata, handles)
1312
1313%------------------------------------------------------------------------
1314function num_last_i_Callback(hObject, eventdata, handles)
1315%------------------------------------------------------------------------
1316SeriesData=get(handles.series,'UserData');
1317if ~isfield(SeriesData,'Time')
1318    SeriesData.Time{1}=[];
1319end
1320displ_time(handles);
1321
1322%------------------------------------------------------------------------
1323function num_first_j_Callback(hObject, eventdata, handles)
1324%------------------------------------------------------------------------
1325 num_last_j_Callback(hObject, eventdata, handles)
1326
1327%------------------------------------------------------------------------
1328function num_last_j_Callback(hObject, eventdata, handles)
1329%------------------------------------------------------------------------
1330% first_j=str2num(get(handles.num_first_j,'String'));
1331% last_j=str2num(get(handles.num_last_j,'String'));
1332% ref_j=ceil((first_j+last_j)/2);
1333% set(handles.num_ref_j,'String', num2str(ref_j))
1334% num_ref_j_Callback(hObject, eventdata, handles)
1335SeriesData=get(handles.series,'UserData');
1336if ~isfield(SeriesData,'Time')
1337    SeriesData.Time{1}=[];
1338end
1339displ_time(handles);
1340
1341%------------------------------------------------------------------------
1342% ---- find the times corresponding to the first and last indices of a series
1343function displ_time(handles)
1344%------------------------------------------------------------------------
1345SeriesData=get(handles.series,'UserData'); %
1346if ~isfield(SeriesData,'Time')
1347    return
1348end
1349PairString=get(handles.PairString,'Data');
1350ref_i_1=str2num(get(handles.num_first_i,'String')); % first reference index
1351ref_i_2=str2num(get(handles.num_last_i,'String')); % last reference index
1352ref_j_1=[];ref_j_2=[];
1353if strcmp(get(handles.num_first_j,'Visible'),'on')
1354ref_j_1=str2num(get(handles.num_first_j,'String'));
1355ref_j_2=str2num(get(handles.num_last_j,'String'));
1356end
1357[i1_1,i2_1,j1_1,j2_1] = get_file_index(ref_i_1,ref_j_1,PairString);
1358[i1_2,i2_2,j1_2,j2_2] = get_file_index(ref_i_2,ref_j_2,PairString);
1359TimeTable=get(handles.TimeTable,'Data');
1360%%%%%%
1361%TODO: read time in netcdf file, see ActionName_Callback
1362%%%%%%%
1363%Pairs=get(handles.PairString,'Data');
1364for iview=1:size(TimeTable,1)
1365    if size(SeriesData.Time,1)<iview
1366        break
1367    end
1368    TimeTable{iview,3}=[];
1369    TimeTable{iview,4}=[];
1370    if size(SeriesData.Time{iview},1)>=i2_2+1 && (isempty(ref_j_1)||size(SeriesData.Time{iview},2)>=j2_2+1)
1371        if isempty(ref_j_1)
1372            time_first=(SeriesData.Time{iview}(i1_1+1,2)+SeriesData.Time{iview}(i2_1+1,2))/2;
1373            time_last=(SeriesData.Time{iview}(i1_2+1,2)+SeriesData.Time{iview}(i2_2+1,2))/2;
1374        else
1375            time_first=(SeriesData.Time{iview}(i1_1+1,j1_1+1)+SeriesData.Time{iview}(i2_1+1,j2_1+1))/2;
1376            time_last=(SeriesData.Time{iview}(i1_2+1,j1_2+1)+SeriesData.Time{iview}(i2_2+1,j2_1+1))/2;
1377        end
1378        TimeTable{iview,3}=time_first; % TODO: take into account pairs
1379        TimeTable{iview,4}=time_last; % TODO: take into account pairs
1380    end
1381end
1382set(handles.TimeTable,'Data',TimeTable)
1383
1384%% set the waitbar position with respect to the min and max in the series
1385MinIndex_i=min(get(handles.MinIndex_i,'Data'));
1386MaxIndex_i=max(get(handles.MaxIndex_i,'Data'));
1387pos_first=(ref_i_1-MinIndex_i)/(MaxIndex_i-MinIndex_i+1);
1388pos_last=(ref_i_2-MinIndex_i+1)/(MaxIndex_i-MinIndex_i+1);
1389if isempty(pos_first), pos_first=0; end
1390if isempty(pos_last), pos_last=1; end
1391Position=get(handles.Waitbar,'Position'); % position of the waitbar:= [ x,y, width, height]
1392Position_status=get(handles.FileStatus,'Position');
1393Position(1)=Position_status(1)+Position_status(3)*pos_first;
1394Position(3)=max(Position_status(3)*(pos_last-pos_first),0.001); % width must remain positive
1395set(handles.Waitbar,'Position',Position)
1396update_waitbar(handles.Waitbar,0)
1397
1398%------------------------------------------------------------------------
1399% --- Executes when selected cell(s) is changed in PairString.
1400function PairString_CellSelectionCallback(hObject, eventdata, handles)
1401%------------------------------------------------------------------------   
1402if numel(eventdata.Indices)>=1
1403    PairString=get(hObject,'Data');
1404    if ~isempty(PairString{eventdata.Indices(1)})
1405        SetPairs_Callback(hObject, eventdata.Indices(1), handles)
1406    end
1407end
1408
1409%-------------------------------------
1410function enable_i(handles,state)
1411set(handles.i_txt,'Visible',state)
1412set(handles.num_first_i,'Visible',state)
1413set(handles.num_last_i,'Visible',state)
1414set(handles.num_incr_i,'Visible',state)
1415
1416%-----------------------------------
1417function enable_j(handles,state)
1418set(handles.j_txt,'Visible',state)
1419set(handles.num_first_j,'Visible',state)
1420set(handles.num_last_j,'Visible',state)
1421set(handles.num_incr_j,'Visible',state)
1422set(handles.MinIndex_j,'Visible',state)
1423set(handles.MaxIndex_j,'Visible',state)
1424
1425
1426%%%%%%%%%%%%%%%%%%%%
1427%%  MAIN ActionName FUNCTIONS
1428%%%%%%%%%%%%%%%%%%%%
1429%------------------------------------------------------------------------
1430% --- Executes on button press in RUN.
1431%------------------------------------------------------------------------
1432function RUN_Callback(hObject, eventdata, handles)
1433
1434%% settings of the button RUN
1435if ~isequal(get(handles.ActionInput,'BackgroundColor'),[1 0 0])
1436    msgbox_uvmat('ERROR','first activate the button ActionInput')
1437    return
1438end
1439set(handles.RUN,'BusyAction','queue'); % activation of STOP button will set BusyAction to 'cancel'
1440set(handles.RUN, 'Enable','Off')% avoid further RUN action until the current one is finished
1441set(handles.RUN,'BackgroundColor',[1 1 0])%show activation of RUN by yellow color
1442drawnow
1443set(handles.status,'Value',0)% desable status display if relevant
1444status_Callback([], eventdata, handles)
1445
1446%% launch action
1447errormsg=launch_action(handles);
1448if ~isempty(errormsg)
1449     msgbox_uvmat('ERROR',errormsg)
1450end
1451
1452%% reset the GUI series
1453update_waitbar(handles.Waitbar,1); % put the waitbar to end position to indicate launching is finished
1454set(handles.RUN, 'Enable','On')
1455set(handles.RUN,'BackgroundColor',[1 0 0])
1456set(handles.RUN, 'Value',0)
1457
1458%------------------------------------------------------------------------
1459% --- called by RUN_Callback
1460%------------------------------------------------------------------------
1461% The calculations are launched in three different ways:
1462% RunMode='local': calculation on the local Matlab session, will prevent other actions during that time.
1463% RunMode='background': calculation on the local computer, but in a new Matlab session (with no graphic output).
1464% RunMode='cluster': calculations dispatched in a cluster, using a managing system, 'oar, 'sge, or 'sgb'.
1465% In the latter case, the calculation is split in 'packets' of i index (all j indices are contained in a single packet).
1466% This splitting is possible only if the different calculations in the series are independent. Otherwise the action
1467% function imposes a number of processes NbSlice in input, for instance NbSlice=1 for a time series.
1468% If NbSlice is not imposed, the splitting in packets (jobs) is determined
1469% so that a job is optimum length AdvisedJobCPUTime), and the total job number in any case smaller
1470% than MaxJobNumber (these parameters are defined in the file series.xml in
1471% accordance with the management strategy for the cluster). The jobs are
1472% dispatched in parallel into NbCore processors by the cluster managing system.
1473
1474function errormsg=launch_action(handles)
1475errormsg=''; % default
1476
1477%% read the data on the GUI series
1478Param=read_GUI_series(handles); % displayed parameters
1479SeriesData=get(handles.series,'UserData'); % hidden parameters
1480if isfield(SeriesData,'TransformInput')
1481    Param.TransformInput=SeriesData.TransformInput;
1482end
1483if ~isfield(SeriesData,'i1_series')
1484    errormsg='The input field series needs to be refreshed: press REFRESH';
1485    return
1486end
1487if isfield(Param,'InputFields')&& isfield(Param.InputFields,'FieldName')&& isequal(Param.InputFields.FieldName,'get_field...')
1488    errormsg='input field name(s) not defined, select get_field...';
1489    return
1490end
1491
1492%% select the Action mode, 'local', 'background' or 'cluster' (if available)
1493RunMode='local'; % default (needed for first opening of the GUI series)
1494if isfield(Param.Action,'RunMode')
1495    RunMode=Param.Action.RunMode;
1496    Param.Action=rmfield(Param.Action,'RunMode'); % remove from the recorded xml file to avoid interference during ImportConfig
1497end
1498ActionExt='.m'; % default
1499if isfield(Param.Action,'ActionExt')
1500    ActionExt=Param.Action.ActionExt; % '.m', '.sh' (compiled)  or '.py' (Python)
1501    Param.Action=rmfield(Param.Action,'ActionExt'); % remove from the recorded xml file to avoid interference during ImportConfig
1502end
1503ActionName=Param.Action.ActionName;
1504ActionPath=Param.Action.ActionPath;
1505path_series=fileparts(which('series'));
1506
1507%% create the Action fct handle if RunMode option = 'local'
1508if strcmp(RunMode,'local')
1509    if ~isequal(ActionPath,path_series)
1510        eval(['spath=which(''' ActionName ''');']) %spath = current path of the selected function ACTION
1511        if ~exist(ActionPath,'dir')
1512            errormsg=['The prescribed function path ' ActionPath ' does not exist'];
1513            return
1514        end
1515        if ~isequal(spath,ActionPath)
1516            addpath(ActionPath)% add the prescribed path if not the current one
1517        end
1518    end
1519    eval(['h_fun=@' ActionName ';'])%create a function handle for ACTION
1520    if ~isequal(ActionPath,path_series)
1521        rmpath(ActionPath)% add the prescribed path if not the current one
1522    end
1523end
1524
1525%% Get  parameters from series.xml
1526errormsg=''; % default error message
1527ActionFullName=fullfile(get(handles.ActionPath,'String'),ActionName);
1528
1529%% If a compiled version has been selected (ext .sh) check wether it needs to be recompiled
1530if strcmp(ActionExt,'.sh')
1531    TransformPath='';
1532    if isfield(SeriesData,'TransformPath')
1533        TransformPath=SeriesData.TransformPath;
1534        if isfield(SeriesData,'TransformList')
1535            TransformList=get(handles.TransformName,'String');
1536            TransformIndex=get(handles.TransformName,'Value');
1537            TransformName=TransformList{TransformIndex};
1538            if ~ismember(TransformName,SeriesData.TransformList)
1539                TransformPath='';
1540            end
1541        end
1542    end
1543    if ~isempty(TransformPath)&&...
1544          ~strcmp(TransformPath,get(handles.TransformPath,'String'))% if the transform is not in paths set for compilation
1545        msgbox_uvmat('ERROR', 'compilation not available for this transform function, select .m')
1546        return
1547    end
1548    set(handles.series,'Pointer','watch') % set the mouse pointer to 'watch'
1549    set(handles.ActionExt,'BackgroundColor',[1 1 0])
1550    [mcrmajor, mcrminor] = mcrversion;   
1551    MCRROOT = ['MCRROOT',int2str(mcrmajor),int2str(mcrminor)];
1552    RunTime = getenv(MCRROOT);
1553    ActionNameVersion=[ActionName '_' MCRROOT];
1554    ActionFullName=fullfile(get(handles.ActionPath,'String'),[ActionNameVersion '.sh']);
1555    % compile the .m file if the .sh file does not exist yet
1556    if ~exist(ActionFullName,'file')
1557        answer=msgbox_uvmat('INPUT_Y-N','compiled version has not been created: compile now?');
1558        if strcmp(answer,'Yes')
1559            set(handles.ActionExt,'BackgroundColor',[1 1 0])
1560            path_uvmat=fileparts(which('series'));
1561            currentdir=pwd;
1562            cd(get(handles.ActionPath,'String'))% go to the directory of Action
1563            addpath(path_uvmat)% add the path to uvmat to run the fct 'compile'
1564            compile(ActionName,TransformPath)
1565            cd(currentdir)
1566        else
1567            errormsg='Action launch interrupted';
1568            return
1569        end       
1570    else
1571        sh_file_info=dir(fullfile(get(handles.ActionPath,'String'),[ActionNameVersion '.sh']));
1572        m_file_info=dir(fullfile(get(handles.ActionPath,'String'),[ActionName '.m']));
1573        if isfield(m_file_info,'datenum') && m_file_info.datenum>sh_file_info.datenum
1574            set(handles.ActionExt,'BackgroundColor',[1 1 0])
1575            drawnow
1576            answer=msgbox_uvmat('INPUT_Y-N',[ActionNameVersion '.sh needs to be updated: recompile now?']);
1577            if strcmp(answer,'Yes')
1578                path_uvmat=fileparts(which('series'));
1579                currentdir=pwd;
1580                cd(get(handles.ActionPath,'String'))% go to the directory of Action
1581                addpath(path_uvmat)% add the path to uvmat to run the fct 'compile'
1582                addpath(fullfile(path_uvmat,'transform_field'))% add the path to uvmat to run the fct 'compile'
1583                compile(ActionName,TransformPath)
1584                cd(currentdir)
1585            end
1586        end
1587    end
1588
1589    set(handles.ActionExt,'BackgroundColor',[1 1 1])
1590     set(handles.series,'Pointer','arrow') % set the mouse pointer to 'watch
1591end
1592
1593%% set nbre of cluster cores and processes:
1594% NbCore is the number of computer processors used
1595% NbProcess is the number of independent processes in which the required calculation is split.
1596switch RunMode
1597    case {'local','background'}
1598        NbCore=1; % no need to split the calculation
1599    case 'cluster_oar'
1600        %proposed number of cores to reserve in the cluster
1601        NbCoreAdvised=SeriesData.SeriesParam.OarParam.NbCoreAdvised;
1602        NbCoreMax=SeriesData.SeriesParam.OarParam.NbCoreMax;
1603        if strcmp(ActionExt,'.m')% case of Matlab function (uncompiled)
1604            warning_string=', preferably use .sh option to save Matlab licences';
1605        else
1606            warning_string=')';
1607        end
1608        answer=inputdlg({['Number of cores (max ' num2str(NbCoreMax) warning_string],'extra oar options'},'oarsub parameter',1,{num2str(NbCoreAdvised),''});
1609        if isempty(answer)
1610            errormsg='Action launch interrupted by user';
1611            return
1612        end
1613        NbCore=str2double(answer{1});
1614        extra_oar=answer{2};
1615    case {'cluster_pbs', 'cluster_sge', 'cluster_qstat_unknown'}
1616        if strcmp(ActionExt,'.m')% case of Matlab function (uncompiled)
1617            NbCore=1; % one core used only (limitation of Matlab licences)
1618            answer=msgbox_uvmat('INPUT_Y-N','Number of cores =1: select the compiled version .sh for multi-core processing. Proceed with the .m version?');
1619            if ~strcmp(answer,'Yes')
1620                errormsg='Action launch interrupted';
1621                return
1622            end
1623            extra_oar='';
1624        else
1625            answer=inputdlg({'Number of jobs (max 1000)','Queue'},'qsub parameters',1,{'100','piv_debian'});
1626            NbCore=str2double(answer{1});
1627            qstat_Queue=answer{2};
1628            %extra_oar=answer{2}; % TODO : fix this for LMFA cluster. Maybe
1629            %extrs_oar and extra_pbs are not the best names
1630        end
1631end
1632if ~isfield(Param.IndexRange,'NbSlice')
1633    Param.IndexRange.NbSlice=[];
1634end
1635
1636%% create the output data directory if needed
1637OutputDir='';
1638if isfield(Param,'OutputSubDir')
1639    SubDirOut=[get(handles.OutputSubDir,'String') Param.OutputDirExt];
1640    SubDirOutNew=SubDirOut;
1641    detect=exist(fullfile(Param.InputTable{1,1},SubDirOutNew),'dir'); % test if  the dir  already exist
1642    check_create=1; % need to create the result directory by default
1643    CheckOverwrite=1;
1644    if isfield(Param,'CheckOverwrite')
1645        CheckOverwrite=Param.CheckOverwrite;
1646    end
1647    while detect
1648        if CheckOverwrite
1649            comment=', possibly overwrite previous data';
1650        else
1651            comment=', will complement existing result files (no overwriting)';
1652        end
1653        answer=msgbox_uvmat('INPUT_Y-N-Cancel',['use existing ouput directory: ' fullfile(Param.InputTable{1,1},SubDirOutNew) comment]);
1654        if strcmp(answer,'Cancel')
1655            return
1656        elseif strcmp(answer,'Yes')
1657            detect=0;
1658            check_create=0;
1659        else
1660            r=regexp(SubDirOutNew,'(?<root>.*\D)(?<num1>\d+)$','names'); % detect whether name ends by a number
1661            if isempty(r)
1662                r(1).root=[SubDirOutNew '_'];
1663                r(1).num1='0';
1664            end
1665            SubDirOutNew=[r(1).root num2str(str2num(r(1).num1)+1)]; % increment the index by 1 or put 1
1666            detect=exist(fullfile(Param.InputTable{1,1},SubDirOutNew),'dir'); % test if  the dir  already exists
1667            check_create=1;
1668        end
1669    end
1670    Param.OutputDirExt=regexprep(SubDirOutNew,Param.OutputSubDir,'');
1671    Param.OutputRootFile=Param.InputTable{1,3}; % the first sorted RootFile taken for output
1672    set(handles.OutputDirExt,'String',Param.OutputDirExt)
1673    OutputDir=fullfile(Param.InputTable{1,1},[Param.OutputSubDir Param.OutputDirExt]); % full name (with path) of output directory
1674    if check_create    % create output directory if it does not exist
1675        [tild,msg1]=mkdir(OutputDir);
1676        if ~strcmp(msg1,'')
1677            errormsg=['cannot create ' OutputDir ': ' msg1]; % error message for directory creation
1678            return
1679        end
1680    end
1681   
1682elseif isfield(Param,'ActionInput')&&isfield(Param.ActionInput,'LogPath')% custom definition of the output dir
1683    OutputDir=Param.ActionInput.LogPath;   
1684end
1685DirXml=fullfile(OutputDir,'0_XML');
1686if ~exist(DirXml,'dir')
1687    [~,msg1]=mkdir(DirXml);
1688    if ~strcmp(msg1,'')
1689        errormsg=['cannot create ' DirXml ': ' msg1]; % error message for directory creation
1690        return
1691    end
1692end
1693OutputNomType=nomtype2pair(Param.InputTable{1,4}); % nomenclature for output files
1694
1695%% get the set of reference input field indices
1696first_i=1; % first i index to process
1697last_i=1; % last i index to process
1698incr_i=1; % increment step in i index
1699first_j=1; % first j index to process
1700last_j=1; % last j index to process
1701incr_j=1; % increment step in j index
1702if isfield(Param.IndexRange,'first_i')
1703    first_i=Param.IndexRange.first_i;
1704    incr_i=Param.IndexRange.incr_i;
1705    last_i=Param.IndexRange.last_i;
1706end
1707if isfield(Param.IndexRange,'incr_j')
1708    first_j=Param.IndexRange.first_j;
1709    last_j=Param.IndexRange.last_j;
1710    incr_j=Param.IndexRange.incr_j;
1711end
1712if last_i < first_i || last_j < first_j
1713    errormsg= 'series/Run_Callback:last field index must be larger or equal to the first one';
1714    return
1715end
1716%incr_i must be defined, =1 by default, if NbSlice is active
1717if isempty(incr_i)&& ~isempty(Param.IndexRange.NbSlice)
1718    incr_i=1;
1719    set(handles.num_incr_i,'String','1')
1720end
1721% case of no increment i defined: processing is done on the available files found in i1_series
1722if isempty(incr_i)
1723    if isempty(incr_j)
1724        [ref_j,ref_i]=find(squeeze(SeriesData.i1_series{1}(1,:,:)));
1725        ref_j=ref_j(ref_j>=first_j & ref_j<=last_j);
1726        ref_i=ref_i(ref_i>=first_i & ref_i<=last_i);
1727        ref_j=ref_j-1;
1728        ref_i=ref_i-1;
1729    else
1730        ref_j=first_j:incr_j:last_j;
1731        [tild,ref_i]=find(squeeze(SeriesData.i1_series{1}(1,:,:)));
1732        ref_i=ref_i-1;
1733        ref_i=ref_i(ref_i>=first_i & ref_i<=last_i);
1734    end
1735    % increment i is defined: processing is done on first_i:incr_i:last_i;
1736else
1737    ref_i=first_i:incr_i:last_i;
1738    if isempty(incr_j)% automatic finding of the existing j indices
1739        [ref_j,tild]=find(squeeze(SeriesData.i1_series{1}(1,:,:)));
1740        ref_j=ref_j-1;
1741        ref_j=ref_j(ref_j>=first_j & ref_j<=last_j);
1742    else
1743        ref_j=first_j:incr_j:last_j;
1744    end
1745end
1746CPUTime=1; % job time estimated at 1 min per iteration (on index i and j) by default
1747if isfield(Param.Action, 'CPUTime') && ~isempty(Param.Action.CPUTime)
1748    CPUTime=Param.Action.CPUTime; % Note: CpUTime for one iteration ref_i has to be multiplied by the number of j indices nbfield_j
1749end
1750nbfield_j=numel(ref_j); % number of j indices
1751BlockLength=numel(ref_i); % by default, job involves the full set of i field indices
1752NbProcess=1;
1753switch RunMode
1754    case {'cluster_oar','cluster_pbs','cluster_sge','cluster_qstat_unknown'}
1755        JobNumberMax=SeriesData.SeriesParam.OarParam.JobNumberMax;
1756        JobCPUTimeAdvised=SeriesData.SeriesParam.OarParam.JobCPUTimeAdvised;
1757        if isempty(Param.IndexRange.NbSlice)% if NbSlice is not defined
1758            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.
1759            BlockLength=max(BlockLength,ceil(numel(ref_i)/JobNumberMax)); % possibly increase the BlockLength to have less than MaxJobNumber jobs
1760            NbProcess=ceil(numel(ref_i)/BlockLength) ; % nbre of processes sent to oar
1761        else
1762            NbProcess=Param.IndexRange.NbSlice; % the parameter NbSlice sets the nbre of run processes
1763        end
1764        NbCore=min(NbCore,NbProcess); % reduces the number of cores if it exceeds the number of processes
1765    otherwise
1766        if ~isempty(Param.IndexRange.NbSlice)
1767            NbProcess=Param.IndexRange.NbSlice; % the parameter NbSlice sets the nbre of run processes
1768        end
1769end
1770
1771%% record nbre of output files and starting time for computation for status
1772StatusData=get(handles.status,'UserData');
1773if isfield(StatusData,'OutputFileMode')
1774    switch StatusData.OutputFileMode
1775        case 'NbInput'
1776            StatusData.NbOutputFile=numel(ref_i)*nbfield_j;
1777        case 'NbInput_i'
1778            StatusData.NbOutputFile=numel(ref_i);
1779        case 'NbSlice'
1780            StatusData.NbOutputFile=str2num(get(handles.num_NbSlice,'String'));
1781    end
1782end
1783StatusData.TimeStart=now;
1784set(handles.status,'UserData',StatusData)
1785
1786%% case of a function in Python
1787if strcmp(ActionExt, '.py (in dev.)')
1788    fprintf([
1789        '\n' ...
1790        '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n' ...
1791        'The option .py is used. It is still in development.\n' ...
1792        'Do not use it unless you really know what you do!\n' ...
1793        'To try it, first install Pyp and the most recent version of FluidImage.\n' ...
1794        '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n'])
1795    RunMode = 'python';
1796end
1797
1798
1799%% direct processing on the current Matlab session or creation of command files
1800filexml=cell(1,NbProcess); % initialisation of the names of the files containing the processing parameters
1801extxml=cell(1,NbProcess); % initialisation of the set of labels used for the files documenting each process
1802for iprocess=1:NbProcess
1803    extxml{iprocess}='.xml';
1804end
1805for iprocess=1:NbProcess
1806    if ~strcmp(get(handles.RUN,'BusyAction'),'queue')% allow for STOP action
1807        disp('program stopped by user')
1808        return
1809    end
1810    if isempty(Param.IndexRange.NbSlice)
1811        Param.IndexRange.first_i=first_i+(iprocess-1)*BlockLength*incr_i;
1812        if Param.IndexRange.first_i>last_i
1813            NbProcess=iprocess-1; % leave the loop, we are at the end of the calculation
1814            break
1815        end
1816        Param.IndexRange.last_i=min(last_i,first_i+(iprocess)*BlockLength*incr_i-1);
1817    else %multislices (then incr_i is not empty)
1818        Param.IndexRange.first_i= first_i+iprocess-1;
1819        Param.IndexRange.incr_i=incr_i*Param.IndexRange.NbSlice;
1820    end
1821    for ilist=1:size(Param.InputTable,1)
1822        Param.InputTable{ilist,1}=regexprep(Param.InputTable{ilist,1},'\','/'); % correct path name for PCWIN system
1823    end
1824   
1825    if isfield(Param,'OutputSubDir')
1826        t=struct2xml(Param);
1827        t=set(t,1,'name','Series');
1828        extxml{iprocess}=fullfile_uvmat('','',Param.InputTable{1,3},'.xml',OutputNomType,...
1829            Param.IndexRange.first_i,Param.IndexRange.last_i,first_j,last_j);
1830        filexml{iprocess}=fullfile(OutputDir,'0_XML',extxml{iprocess});
1831        try
1832            save(t, filexml{iprocess}); % save the xml file containing the processing parameters
1833        catch ME
1834            if ~strcmp (RunMode,'local')
1835                errormsg=['error writting ' filexml{iprocess} ': ' ME.message];
1836                return
1837            end
1838        end
1839    end
1840    if strcmp (RunMode,'local')
1841        switch ActionExt
1842            case '.m'
1843                h_fun(Param); % direct launching
1844               
1845            case '.sh'
1846                switch computer
1847                    case {'PCWIN','PCWIN64'} %Windows system
1848                        filexml=regexprep(filexml,'\\','\\\\'); % add '\' so that '\' are left as characters
1849                        system([ActionFullName ' ' RunTime ' ' filexml{iprocess}]); % TODO: adapt to DOS system
1850                    case {'GLNX86','GLNXA64','MACI64'}%Linux  system
1851                        system([ActionFullName ' ' RunTime ' ' filexml{iprocess}]);
1852                end
1853        end
1854    end
1855end
1856
1857if ~strcmp (RunMode,'local') && ~strcmp(RunMode,'python')
1858    %% processing on a different session of the same computer (background) or cluster, create executable files
1859    batch_file_list=cell(NbProcess,1); % initiate the list of executable files
1860    DirExe=fullfile(OutputDir,'0_EXE'); % directory name for executable files
1861    switch computer
1862        case {'PCWIN','PCWIN64'} %Windows system
1863            ExeExt='.bat';
1864        case {'GLNX86','GLNXA64','MACI64'}%Linux  system
1865            ExeExt='.sh';
1866    end
1867    %create subdirectory for executable files
1868    if ~exist(DirExe,'dir')
1869        [tild,msg1]=mkdir(DirExe);
1870        if ~strcmp(msg1,'')
1871            errormsg=['cannot create ' DirExe ': ' msg1]; % error message for directory creation
1872            return
1873        end
1874    end
1875    %create subdirectory for log files
1876    DirLog=fullfile(OutputDir,'0_LOG');
1877    if ~exist(DirLog,'dir')
1878        [tild,msg1]=mkdir(DirLog);
1879        if ~strcmp(msg1,'')
1880            errormsg=['cannot create ' DirLog ': ' msg1]; % error message for directory creation
1881            return
1882        end
1883    end
1884   
1885    %create the executable file
1886    file_exe_global=fullfile_uvmat('','',Param.InputTable{1,3},ExeExt,OutputNomType,...
1887        first_i,last_i,first_j,last_j);
1888    file_exe_global=fullfile(OutputDir,'0_EXE',file_exe_global);
1889    filelog_global=fullfile_uvmat('','',Param.InputTable{1,3},'.log',OutputNomType,...
1890        first_i,last_i,first_j,last_j);
1891    filelog_global=fullfile(OutputDir,'0_LOG',filelog_global);
1892
1893    for iprocess=1:NbProcess   
1894        %create the executable file       
1895        batch_file_list{iprocess}=fullfile(OutputDir,'0_EXE',regexprep(extxml{iprocess},'.xml$',ExeExt));
1896       
1897        % set the log file name
1898        filelog{iprocess}=fullfile(OutputDir,'0_LOG',regexprep(extxml{iprocess},'.xml$','.log'));     
1899    end
1900end
1901
1902%% launch the executable files for background or cluster processing
1903
1904switch RunMode
1905   
1906    case 'background'
1907        [fid,message]=fopen(file_exe_global,'w');
1908        if isequal(fid,-1)
1909            errormsg=['creation of ' file_exe_global ':' message];
1910            return
1911        end
1912        switch ActionExt
1913            case '.m'% Matlab function
1914                switch computer
1915                    case {'GLNX86','GLNXA64','MACI64'}
1916                        matlab_ver = ver('MATLAB');
1917                        matlab_version = matlab_ver.Version;
1918                        cmd=[...
1919                            '#!/bin/bash \n'...
1920                            'source /etc/profile \n'...
1921                            'module load matlab/''' matlab_version ''' \n'...% CHOICE OF MATLAB VERSION
1922                            'matlab -nodisplay -nosplash -nojvm -logfile ''' filelog_global ''' <<END_MATLAB \n'...
1923                            'addpath(''' path_series '''); \n'...
1924                            'addpath(''' Param.Action.ActionPath '''); \n'];
1925                        for iprocess=1:NbProcess
1926                            cmd=[cmd '' Param.Action.ActionName  '( ''' filexml{iprocess} '''); \n'];
1927                        end
1928                        cmd=[cmd  'exit \n' 'END_MATLAB \n'];
1929                        fprintf(fid,cmd); % fill the executable file with the  char string cmd
1930                        fclose(fid); % close the executable file
1931                        system(['chmod +x ' file_exe_global]); % set the file to executable
1932                    case {'PCWIN','PCWIN64'}
1933                        cmd=['matlab -automation -logfile ' regexprep(filelog{iprocess},'\\','\\\\')...
1934                            ' -r "addpath(''' regexprep(path_series,'\\','\\\\') ''');'...
1935                            'addpath(''' regexprep(Param.Action.ActionPath,'\\','\\\\') ''');'];
1936                        for iprocess=1:NbProcess
1937                            cmd=[cmd '' Param.Action.ActionName  '( ''' regexprep(filexml{iprocess},'\\','\\\\') ''');']
1938                        end
1939                        cmd=[cmd ';exit"'];
1940                        fprintf(fid,cmd); % fill the executable file with the  char string cmd
1941                        fclose(fid); % close the executable file
1942                end
1943                system([file_exe_global ' &'])% directly execute the command file
1944            case '.sh' % compiled Matlab function
1945                for iprocess=1:NbProcess
1946                    switch computer
1947                        case {'GLNX86','GLNXA64','MACI64'}
1948                            [fid,message]=fopen(batch_file_list{iprocess},'w'); % create the executable file
1949                            if isequal(fid,-1)
1950                                errormsg=['creation of .bat file: ' message];
1951                                return
1952                            end
1953                            cmd=['#!/bin/bash \n '...
1954                                '#$ -cwd \n '...
1955                                'hostname && date \n '...
1956                                'umask 002 \n'...
1957                                ActionFullName ' ' RunTime ' ' filexml{iprocess}]; % allow writting access to created files for user group
1958                            fprintf(fid,cmd); % fill the executable file with the  char string cmd
1959                            fclose(fid); % close the executable file
1960                            system(['chmod +x ' batch_file_list{iprocess}]); % set the file to executable
1961                            system([batch_file_list{iprocess} ' &'])% directly execute the command file
1962                        case {'PCWIN','PCWIN64'}
1963                            msgbox_uvmat('ERROR','option for compiled Matlab functions not implemented for Windows system')
1964                            return
1965                    end
1966                end
1967                msgbox_uvmat('CONFIRMATION',[ActionFullName ' launched in background: press STATUS to see results'])
1968        end
1969       
1970    case 'cluster_oar' % option 'oar-parexec' used
1971        %create subdirectory for oar commands
1972        for iprocess=1:NbProcess
1973            [fid,message]=fopen(batch_file_list{iprocess},'w'); % create the executable file
1974            if isequal(fid,-1)
1975                errormsg=['creation of .bat file: ' message];
1976                return
1977            end
1978            if  strcmp(ActionExt,'.sh')
1979                cmd=['#!/bin/bash \n '...
1980                    '#$ -cwd \n '...
1981                    'hostname && date \n '...
1982                    'umask 002 \n'...
1983                    ActionFullName ' ' RunTime ' ' filexml{iprocess}]; % allow writting access to created files for user group
1984            else
1985                matlab_ver = ver('MATLAB');
1986                matlab_version = matlab_ver.Version;
1987                cmd=[...
1988                    '#!/bin/bash \n'...
1989                    'source /etc/profile \n'...
1990                    'module load matlab/''' matlab_version ''' \n'...% CHOICE OF MATLAB VERSION
1991                    'matlab -nodisplay -nosplash -nojvm -singleCompThread -logfile ''' filelog{iprocess} ''' <<END_MATLAB \n'...
1992                    'addpath(''' path_series '''); \n'...
1993                    'addpath(''' Param.Action.ActionPath '''); \n'...
1994                    '' Param.Action.ActionName  '( ''' filexml{iprocess} '''); \n'...
1995                    'exit \n'...
1996                    'END_MATLAB \n'];
1997            end
1998            fprintf(fid,cmd); % fill the executable file with the  char string cmd
1999            fclose(fid); % close the executable file
2000            system(['chmod +x ' batch_file_list{iprocess}]); % set the file to executable
2001        end
2002        DirOAR=fullfile(OutputDir,'0_OAR');
2003        if exist(DirOAR,'dir')% delete the content of the dir 0_LOG to allow new input
2004            curdir=pwd;
2005            cd(DirOAR)
2006            delete('*')
2007            cd(curdir)
2008        else
2009            [tild,msg1]=mkdir(DirOAR);
2010            if ~strcmp(msg1,'')
2011                errormsg=['cannot create ' DirOAR ': ' msg1]; % error message for directory creation
2012                return
2013            end
2014        end
2015        % create file containing the list of jobs
2016        filename_joblist=fullfile(DirOAR,'job_list.txt'); % name of the file containing the list of executables
2017        fid=fopen(filename_joblist,'w'); % open it for writting
2018        for iprocess=1:length(batch_file_list)
2019            fprintf(fid,[batch_file_list{iprocess} '\n']); % write list of exe files
2020        end
2021        fclose(fid);
2022        system(['chmod +x ' filename_joblist]); % set the file to executable
2023       
2024        filename_log=fullfile(DirLog,'job_list.stdout'); % file for output messages of the master oar process
2025        filename_errors=fullfile(DirLog,'job_list.stderr'); % file for error messages of the master oar process
2026        % the command job_list.txt contains the list of NbProcess independent individual jobs
2027        % in which the total calculation has been split. Those are written as executable files .sh in the folder /O_EXE.
2028        %  These individual jobs are grouped by the system as oar jobs on the NbCore processors.
2029        %  For each processor, the oar job must stop after the walltime which has been set, which is limited to 24 h.
2030        %  However, the oar job is automatically restarted (option 'idempotent') provided the individual jobs are
2031        % shorter than the wall time: in the time interval 'checkpoint' (WallTimeOneJob) before the end of the allowed duration,
2032        %  the oar job restarts when an individual job ends.
2033        WallTimeMax=SeriesData.SeriesParam.OarParam.WallTimeMax;
2034        JobTime=CPUTime*BlockLength*nbfield_j; % estimated CPU time for one individual job (in minutes)
2035        % wall time (in hours ) for each oar job, allowing 10 individual jobs, but limited to 23 h:
2036        WallTimeTotal=min(WallTimeMax,4*JobTime/60);
2037        %disp(['WallTimeTotal: ' num2str(WallTimeTotal) ' hours'])
2038        % estimated time of an individual job (in min), with a margin of error
2039        WallTimeOneJob=min(4*JobTime+10,WallTimeTotal*60/2); % estimated max time of an individual job for checkpoint
2040        disp(['WallTimeOneJob: ' num2str(WallTimeOneJob) ' minutes'])
2041        oar_command=['oarsub -n UVmat_' ActionFullName ' '...
2042            '-t idempotent --checkpoint ' num2str(WallTimeOneJob*60) ' '...
2043            '-l "/core=' num2str(NbCore)...
2044            '+{type = ' char(39) 'bigiojob' char(39) '}/licence=1'... % char(39) is quote - bigiojob limit UVmat parallel launch on cluster
2045            ',walltime=' datestr(WallTimeTotal/24,13) '" '...
2046            '-E ' filename_errors ' '...
2047            '-O ' filename_log ' '...
2048            extra_oar ' '...
2049            '"oar-parexec -s -f ' filename_joblist ' '...
2050            '-l ' filename_joblist '.log"'];
2051       
2052        fprintf(oar_command); % display  system command on the Matlab command window
2053        [status,result]=system(oar_command)% execute system command and show the result (ID number of the launched job) on the Matlab command window
2054        filename_oarcommand=fullfile(DirOAR,'0_oar_command'); % keep track of the command in file '0-OAR/0_oar_command'
2055        fid=fopen(filename_oarcommand,'w');
2056        fprintf(fid,oar_command); % store the command
2057        fprintf(fid,result); % store the result (job ID number)
2058        fclose(fid);
2059        msgbox_uvmat('CONFIRMATION',[ActionFullName ' launched as  ' num2str(NbProcess) ' processes in cluster: press STATUS to see results'])
2060       
2061    case 'cluster_pbs' % for LMFA Kepler machine
2062        %create subdirectory for pbs command and log files
2063        DirPBS=fullfile(OutputDir,'0_PBS'); % todo : common name OAR/PBS
2064        if exist(DirPBS,'dir')% delete the content of the dir 0_LOG to allow new input
2065            curdir=pwd;
2066            cd(DirPBS)
2067            delete('*')
2068            cd(curdir)
2069        else
2070            [tild,msg1]=mkdir(DirPBS);
2071            if ~strcmp(msg1,'')
2072                errormsg=['cannot create ' DirPBS ': ' msg1]; % error message for directory creation
2073                return
2074            end
2075        end
2076        max_walltime=3600*20; % 20h max total calculation (cannot exceed 24 h)
2077        walltime_onejob=1800; % seconds, max estimated time for asingle file index value
2078        filename_joblist=fullfile(DirPBS,'job_list.txt'); % create name of the global executable file
2079        fid=fopen(filename_joblist,'w');
2080        for iprocess=1:length(batch_file_list)
2081            fprintf(fid,[batch_file_list{iprocess} '\n']); % list of exe files
2082        end
2083        fclose(fid);
2084        system(['chmod +x ' filename_joblist]); % set the file to executable
2085        pbs_command=['qsub -n CIVX '...
2086            '-t idempotent --checkpoint ' num2str(walltime_onejob+60) ' '...
2087            '-l /core=' num2str(NbCore) ','...
2088            'walltime=' datestr(min(1.05*walltime_onejob/86400*max(NbProcess*BlockLength*nbfield_j,NbCore)/NbCore,max_walltime/86400),13) ' '...
2089            '-E ' regexprep(filename_joblist,'\.txt\>','.stderr') ' '...
2090            '-O ' regexprep(filename_joblist,'\.txt\>','.log') ' '...
2091            extra_qstat ' '...
2092            '"oar-parexec -s -f ' filename_joblist ' '...
2093            '-l ' filename_joblist '.log"'];
2094        filename_oarcommand=fullfile(DirPBS,'pbs_command');
2095        fid=fopen(filename_oarcommand,'w');
2096        fprintf(fid,pbs_command);
2097        fclose(fid);
2098        fprintf(pbs_command); % display in command line
2099        %system(pbs_command);
2100        msgbox_uvmat('CONFIRMATION',[ActionFullName ' command ready to be launched in cluster'])
2101
2102     case 'cluster_sge' % for PSMN
2103        % Au PSMN, on ne cr??e pas 1 job avec plusieurs c??urs, mais N jobs de 1 c??urs
2104        % o?? N < 1000.
2105        %create subdirectory for pbs command and log files
2106
2107        DirSGE=fullfile(OutputDir,'0_SGE');
2108        if exist(DirSGE,'dir')% delete the content of the dir 0_LOG to allow new input
2109            curdir=pwd;
2110            cd(DirSGE)
2111            delete('*')
2112            cd(curdir)
2113        else
2114            [tild,msg1]=mkdir(DirSGE);
2115            if ~strcmp(msg1,'')
2116                errormsg=['cannot create ' DirSGE ': ' msg1]; % error message for directory creation
2117                return
2118            end
2119        end
2120        maxImgsPerJob = ceil(length(batch_file_list)/NbCore);
2121        disp(['Max number of jobs: ' num2str(NbCore)])
2122        disp(['Images per job: ' num2str(maxImgsPerJob)])
2123       
2124        iprocess = 1;
2125        imgsInJob = [];
2126        currJobIndex = 1;
2127        done = 0;
2128        while(~done)
2129            if(iprocess <= length(batch_file_list))
2130                imgsInJob = [imgsInJob, iprocess];
2131            end
2132            if((numel(imgsInJob) >= maxImgsPerJob) || (iprocess == length(batch_file_list)))
2133                cmd=['#!/bin/sh \n'...
2134                     '#$ -cwd \n'...
2135                     'hostname && date\n']
2136                for ii=1:numel(imgsInJob)
2137                    cmd=[cmd ActionFullName ' /softs/matlab ' filexml{imgsInJob(ii)} '\n'];
2138                end
2139                [fid, message] = fopen([DirSGE '/job' num2str(currJobIndex) '.sh'], 'w');
2140                fprintf(fid, cmd);
2141                fclose(fid);
2142                system(['chmod +x ' DirSGE '/job' num2str(currJobIndex) '.sh'])
2143                sge_command=['qsub -N civ_' num2str(currJobIndex) ' '...
2144                    '-q ' qstat_Queue ' '...
2145                    '-e ' fullfile([DirSGE '/job' num2str(currJobIndex) '.out']) ' '...
2146                    '-o ' fullfile([DirSGE '/job' num2str(currJobIndex) '.out']) ' '...
2147                    fullfile([DirSGE '/job' num2str(currJobIndex) '.sh'])];
2148                fprintf(sge_command); % display in command line
2149                [status, result] = system(sge_command);
2150                fprintf(result);
2151                currJobIndex = currJobIndex + 1;
2152                imgsInJob = [];
2153            end
2154            if(iprocess == length(batch_file_list))
2155                done = 1;
2156            end
2157            iprocess = iprocess + 1;
2158        end
2159        msgbox_uvmat('CONFIRMATION',[num2str(currJobIndex-1) ' jobs launched on queue ' qstat_Queue '.'])
2160    case 'python'
2161        command = [
2162            'LD_LIBRARY_PATH=$(echo $LD_LIBRARY_PATH | pyp "p.split('':'') | [s for s in p if ''matlab'' not in s] | '':''.join(p)") ' ...
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.