source: trunk/src/series.m @ 914

Last change on this file since 914 was 914, checked in by sommeria, 9 years ago

minor change in series

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