source: trunk/src/series.m @ 872

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

bugs corrected

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