source: trunk/src/series.m @ 910

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

bugs corrected in fix in civ_series. vectors set to 0 inside mask

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