source: trunk/src/series.m @ 963

Last change on this file since 963 was 963, checked in by sommeria, 8 years ago

series adapted to level

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