source: trunk/src/series.m @ 985

Last change on this file since 985 was 984, checked in by sommeria, 7 years ago

introduce .cine in various functions, improve stero PIV

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