source: trunk/src/series.m @ 942

Last change on this file since 942 was 942, checked in by augier3pi, 8 years ago

Adapte pour fluidimage.

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