source: trunk/src/series.m @ 881

Last change on this file since 881 was 880, checked in by sommeria, 10 years ago

various bug fixes

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