source: trunk/src/series.m @ 810

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