source: trunk/src/series.m @ 918

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

job launching procedure modified in series

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