source: trunk/src/series/civ_series.m @ 624

Last change on this file since 624 was 624, checked in by sommeria, 11 years ago

waitbar system for series improved to aloow use as stand alone fcts.

to add at the head of series fcts:
hseries=findobj(allchild(0),'Tag','series');
RUNHandle=findobj(hseries,'Tag','RUN');%handle of RUN button in GUI series
WaitbarHandle?=findobj(hseries,'Tag','Waitbar');%handle of waitbar in GUI series

call to waitbar:

update_waitbar(WaitbarHandle?,index/nbfield)
if ishandle(RUNHandle) && ~strcmp(get(RUNHandle,'BusyAction?'),'queue')

disp('program stopped by user')
break

end

File size: 45.4 KB
Line 
1%'civ_series': PIV function activated by the general GUI series
2% --- call the sub-functions:
3%   civ: PIV function itself
4%   fix: removes false vectors after detection by various criteria
5%   filter_tps: make interpolation-smoothing
6%------------------------------------------------------------------------
7% function [Data,errormsg,result_conv]= civ_series(Param,ncfile)
8%
9%OUTPUT
10% Data=structure containing the PIV results and information on the processing parameters
11% errormsg=error message char string, default=''
12% resul_conv: image inter-correlation function for the last grid point (used for tests)
13%
14%INPUT:
15% Param: input images and processing parameters
16%     .Civ1: for civ1
17%     .Fix1:
18%     .Patch1:
19%     .Civ2: for civ2
20%     .Fix2:
21%     .Patch2:
22% ncfile: name of a netcdf file to be created for the result (extension .nc)
23%
24%AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
25%  Copyright  2011, LEGI / CNRS-UJF-INPG, joel.sommeria@legi.grenoble-inp.fr.
26%AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
27%     This is part of the toolbox UVMAT.
28%
29%     UVMAT is free software; you can redistribute it and/or modify
30%     it under the terms of the GNU General Public License as published by
31%     the Free Software Foundation; either version 2 of the License, or
32%     (at your option) any later version.
33%
34%     UVMAT is distributed in the hope that it will be useful,
35%     but WITHOUT ANY WARRANTY; without even the implied warranty of
36%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37%     GNU General Public License (open UVMAT/COPYING.txt) for more details.
38%AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
39
40function [Data,errormsg,result_conv]= civ_series(Param,ncfile)
41errormsg='';
42path_series=fileparts(which('series'));
43addpath(fullfile(path_series,'series'))
44%% set the input elements needed on the GUI series when the action is selected in the menu ActionName or InputTable refreshed
45if isstruct(Param) && isequal(Param.Action.RUN,0)
46    Data=civ_input(Param);% introduce the civ parameters using the GUI civ_input
47    Data.Program=mfilename;%gives the name of the current function
48    Data.AllowInputSort='off';% allow alphabetic sorting of the list of input file SubDir (options 'off'/'on', 'off' by default)
49    Data.WholeIndexRange='off';% prescribes the file index ranges from min to max (options 'off'/'on', 'off' by default)
50    Data.NbSlice='off'; %nbre of slices ('off' by default)
51    Data.VelType='off';% menu for selecting the velocity type (options 'off'/'one'/'two',  'off' by default)
52    Data.FieldName='off';% menu for selecting the field (s) in the input file(options 'off'/'one'/'two', 'off' by default)
53    Data.FieldTransform = 'off';%can use a transform function
54    Data.ProjObject='off';%can use projection object(option 'off'/'on',
55    Data.Mask='off';%can use mask option   (option 'off'/'on', 'off' by default)
56    Data.OutputDirExt='.civ';%set the output dir extension
57    filecell=get_file_series(Param);%check existence of the first input file
58    if ~exist(filecell{1,1},'file')
59        msgbox_uvmat('WARNING','the first input file does not exist')
60    else
61        FileType=get_file_type(filecell{1,1});
62        if isempty(find(strcmp(FileType,{'civdata','image','multimage','mmreader','video'})));% =1 for images
63            msgbox_uvmat('ERROR',['bad input file type for ' mfilename ': an image or civdata file is needed'])
64        end
65    end
66    return
67end
68
69%% read input parameters from an xml file if input is a file name (batch mode)
70checkrun=1;
71if ischar(Param)
72    Param=xml2struct(Param);% read Param as input file (batch case)
73    checkrun=0;
74end
75hseries=findobj(allchild(0),'Tag','series');
76RUNHandle=findobj(hseries,'Tag','RUN');%handle of RUN button in GUI series
77WaitbarHandle=findobj(hseries,'Tag','Waitbar');%handle of waitbar in GUI series
78
79%% input files and indexing
80NbField=1;
81MaxIndex=cell2mat(Param.IndexRange.MaxIndex);
82MinIndex=cell2mat(Param.IndexRange.MinIndex);
83if isfield(Param,'InputTable')
84    [filecell,i_series,tild,j_series]=get_file_series(Param);
85    if ~exist(filecell{1,1},'file')
86        displ('ERROR: the first input file does not exist')
87        return
88    else
89        FileType=get_file_type(filecell{1,1});
90        iview_nc=0;
91        iview_A=0;
92        iview_B=0;
93        switch FileType
94            case 'civdata';% =1 for images
95                iview_nc=1;
96                if size(filecell,1)>=2
97                    iview_A=2;iview_B=2;
98                    if size(filecell,1)>=3
99                        iview_B=3;
100                    end
101                end
102            case {'image','multimage','mmreader','video'}
103                iview_A=1;
104                if size(filecell,1)>=2
105                    iview_B=2;
106                end
107        end
108    end
109    if iview_A~=0
110        [FileType_A,FileInfo_A,VideoObject_A]=get_file_type(filecell{1,1});
111        if isempty(strcmp(FileType_A,{'multimage','mmreader','video'}))
112            displ(['ERROR: the file line ' num2str(iview_A) ' must be an image'])
113        end
114        RootPath=Param.InputTable{1,1};
115        RootFile=Param.InputTable{1,3};
116        SubDir=Param.InputTable{1,2};
117        NomType=Param.InputTable{1,4};
118        FileExt=Param.InputTable{1,5};
119    end
120    if iview_B==0
121        FileType_B=FileType_A;
122VideoObject_B=VideoObject_A;
123        PairCiv1=Param.ActionInput.PairIndices.ListPairCiv1;
124        PairCiv2='';
125        if isfield(Param.ActionInput.PairIndices,'ListPairCiv2')
126            PairCiv2=Param.ActionInput.PairIndices.ListPairCiv2;
127        end
128        [i1_series_Civ1,i2_series_Civ1,j1_series_Civ1,j2_series_Civ1,check_bounds,NomTypeNc]=...
129            find_pair_indices(PairCiv1,i_series{1},j_series{1},MinIndex,MaxIndex);
130        if ~isempty(PairCiv2)
131            [i1_series_Civ2,i2_series_Civ2,j1_series_Civ2,j2_series_Civ2,check_bounds_Civ2]=...
132                find_pair_indices(PairCiv2,i_series{1},j_series{1},MinIndex,MaxIndex);
133            check_bounds=check_bounds | check_bounds_Civ2;
134        end
135        i1_series_Civ1=i1_series_Civ1(~check_bounds);
136        i2_series_Civ1=i2_series_Civ1(~check_bounds);
137        j1_series_Civ1=j1_series_Civ1(~check_bounds);
138        j2_series_Civ1=j2_series_Civ1(~check_bounds);
139        if isempty(j_series{1})
140            FrameIndex_A_Civ1=i1_series_Civ1;
141            FrameIndex_B_Civ1=i2_series_Civ1;
142        else
143            FrameIndex_A_Civ1=j1_series_Civ1;
144            FrameIndex_B_Civ1=j2_series_Civ1;
145        end
146        if ~isempty(PairCiv2)
147            i1_series_Civ2=i1_series_Civ2(~check_bounds);
148            i2_series_Civ2=i2_series_Civ2(~check_bounds);
149            j1_series_Civ2=j1_series_Civ2(~check_bounds);
150            j2_series_Civ2=j2_series_Civ2(~check_bounds);
151            if isempty(j_series{1})
152                FrameIndex_A_Civ2=i1_series_Civ2;
153                FrameIndex_B_Civ2=i2_series_Civ2;
154            else
155                FrameIndex_A_Civ2=j1_series_Civ2;
156                FrameIndex_B_Civ2=j2_series_Civ2;
157            end
158        end
159    else
160           [FileType_B,FileInfo,VideoObject_B]=get_file_type(filecell{2,1});
161        if isempty(find(strcmp(FileType_B,{'multimage','mmreader','video'})))
162            displ(['ERROR: the file line ' num2str(iview_B) ' must be an image'])
163        end   
164        %TODO : introduce the second file series if relevant: case %displacement
165    end
166end
167NbField=numel(i1_series_Civ1);
168
169%% Output directory
170OutputDir=[Param.OutputSubDir Param.OutputDirExt];
171
172Data.ListGlobalAttribute={'Conventions','Program','CivStage'};
173Data.Conventions='uvmat/civdata';% states the conventions used for the description of field variables and attributes
174Data.Program='civ_series';
175Data.CivStage=0;%default
176ListVarCiv1={'Civ1_X','Civ1_Y','Civ1_U','Civ1_V','Civ1_C','Civ1_F'}; %variables to read
177ListVarFix1={'Civ1_X','Civ1_Y','Civ1_U','Civ1_V','Civ1_C','Civ1_F','Civ1_FF'};
178mask='';
179maskname='';%default
180check_civx=0;%default
181check_civ1=0;%default
182check_patch1=0;%default
183
184%% get timing from the ImaDoc file or input video
185XmlFileName=find_imadoc(RootPath,SubDir,RootFile,FileExt);
186time=[];
187if ~isempty(XmlFileName)
188    XmlData=imadoc2struct(XmlFileName);
189        if isfield(XmlData,'Time')
190            time=XmlData.Time;
191            TimeSource='xml';
192        end
193        if isfield(XmlData,'Camera')
194            if isfield(XmlData.Camera,'NbSlice')&& ~isempty(XmlData.Camera.NbSlice)
195                NbSlice_calib{iview}=XmlData.Camera.NbSlice;% Nbre of slices for Zindex in phys transform
196                if ~isequal(NbSlice_calib{iview},NbSlice_calib{1})
197                    msgbox_uvmat('WARNING','inconsistent number of Z indices for the two field series');
198                end
199            end
200            if isfield(XmlData.Camera,'TimeUnit')&& ~isempty(XmlData.Camera.TimeUnit)
201                TimeUnit=XmlData.Camera.TimeUnit;
202            end
203        end
204end
205if ~isempty(find(strcmp(FileType_A,{'mmreader','video'})))% case of video input
206    time=zeros(2,FileInfo_A.NumberOfFrames+1);
207    time(2,:)=(0:1/FileInfo_A.FrameRate:(FileInfo_A.NumberOfFrames)/FileInfo_A.FrameRate);
208    TimeSource='video';
209    % set(han:dles.Dt_txt,'String',['Dt=' num2str(1000/imainfo.FrameRate) 'ms']);%display the elementary time interval in millisec
210    ColorType='truecolor';
211end
212if length(FileInfo_A) >1 %case of image with multiple frames
213    nbfield=length(FileInfo_A);
214    nbfield_j=1;
215end
216
217%%%%% MAIN LOOP %%%%%%
218for ifield=1:NbField
219    update_waitbar(WaitbarHandle,index/nbfield)
220    if ishandle(RUNHandle) && ~strcmp(get(RUNHandle,'BusyAction'),'queue')
221        disp('program stopped by user')
222        break
223    end
224    %% Civ1
225    if isfield (Param.ActionInput,'Civ1')
226        par_civ1=Param.ActionInput.Civ1;
227        if isfield(par_civ1,'reverse_pair')% A REVOIR
228            if par_civ1.reverse_pair
229                if ischar(par_civ1.ImageB)
230                    temp=par_civ1.ImageA;
231                    par_civ1.ImageA=imread(par_civ1.ImageB);
232                end
233                if ischar(temp)
234                    par_civ1.ImageB=imread(temp);
235                end
236            end
237        else
238            ImageName_A=fullfile_uvmat(RootPath,SubDir,RootFile,FileExt,NomType,i1_series_Civ1(ifield),[],j1_series_Civ1(ifield));
239            [par_civ1.ImageA,VideoObject_A] = read_image(ImageName_A,FileType_A,VideoObject_A,FrameIndex_A_Civ1(ifield));
240            ImageName_B=fullfile_uvmat(RootPath,SubDir,RootFile,FileExt,NomType,i2_series_Civ1(ifield),[],j2_series_Civ1(ifield));
241            [par_civ1.ImageB,VideoObject_B] = read_image(ImageName_B,FileType_B,VideoObject_B,FrameIndex_B_Civ1(ifield));
242        end
243        ncfile=fullfile_uvmat(RootPath,OutputDir,RootFile,'.nc',NomTypeNc,i1_series_Civ1(ifield),i2_series_Civ1(ifield),...
244            j1_series_Civ1(ifield),j2_series_Civ1(ifield));
245        par_civ1.ImageWidth=FileInfo_A.Width;
246        par_civ1.ImageHeight=FileInfo_A.Height;
247        list_param=(fieldnames(Param.ActionInput.Civ1))';
248        Civ1_param=regexprep(list_param,'^.+','Civ1_$0');% insert 'Civ1_' before  each string in list_param
249        Civ1_param=[{'Civ1_ImageA','Civ1_ImageB','Civ1_Time','Civ1_Dt'} Civ1_param]; %insert the names of the two input images
250        %indicate the values of all the global attributes in the output data
251        Data.Civ1_ImageA=ImageName_A;
252        Data.Civ1_ImageB=ImageName_B;
253        i1=i1_series_Civ1(ifield);
254        i2=i1;
255        if ~isempty(i2_series_Civ1)
256            i2=i2_series_Civ1(ifield);
257        end
258        j1=1;
259        if ~isempty(j1_series_Civ1)
260            j1=j1_series_Civ1(ifield);
261        end
262        j2=j1;
263        if ~isempty(j2_series_Civ1)
264            j2=j2_series_Civ1(ifield);
265        end
266        Data.Civ1_Time=(time(i2+1,j2+1)+time(i1+1,j1+1))/2;
267        Data.Civ1_Dt=time(i2+1,j2+1)-time(i1+1,j1+1);
268        for ilist=1:length(list_param)
269            Data.(Civ1_param{4+ilist})=Param.ActionInput.Civ1.(list_param{ilist});
270        end
271        Data.ListGlobalAttribute=[Data.ListGlobalAttribute Civ1_param];
272        Data.CivStage=1;
273       
274        % set the list of variables
275        Data.ListVarName={'Civ1_X','Civ1_Y','Civ1_U','Civ1_V','Civ1_F','Civ1_C'};%  cell array containing the names of the fields to record
276        Data.VarDimName={'nb_vec_1','nb_vec_1','nb_vec_1','nb_vec_1','nb_vec_1','nb_vec_1'};
277        Data.VarAttribute{1}.Role='coord_x';
278        Data.VarAttribute{2}.Role='coord_y';
279        Data.VarAttribute{3}.Role='vector_x';
280        Data.VarAttribute{4}.Role='vector_y';
281        Data.VarAttribute{5}.Role='warnflag';
282       
283        if strcmp(Param.ActionInput.ListCompareMode, 'PIV volume')
284            Data.ListVarName=[Data.ListVarName 'Civ1_Z'];
285            Data.Civ1_X=[];Data.Civ1_Y=[];Data.Civ1_Z=[];
286            Data.Civ1_U=[];Data.Civ1_V=[];Data.Civ1_C=[];Data.Civ1_F=[];
287            for ivol=1:NbSlice
288                % caluclate velocity data (y and v in indices, reverse to y component)
289                [xtable ytable utable vtable ctable F result_conv errormsg] = civ (par_civ1);
290                if ~isempty(errormsg)
291                    return
292                end
293                Data.Civ1_X=[Data.Civ1_X reshape(xtable,[],1)];
294                Data.Civ1_Y=[Data.Civ1_Y reshape(Param.Civ1.ImageHeight-ytable+1,[],1)];
295                Data.Civ1_Z=[Data.Civ1_Z ivol*ones(numel(xtable),1)];% z=image index in image coordinates
296                Data.Civ1_U=[Data.Civ1_U reshape(utable,[],1)];
297                Data.Civ1_V=[Data.Civ1_V reshape(-vtable,[],1)];
298                Data.Civ1_C=[Data.Civ1_C reshape(ctable,[],1)];
299                Data.Civ1_F=[Data.Civ1_C reshape(F,[],1)];
300            end
301        else %usual PIV
302            % caluclate velocity data (y and v in indices, reverse to y component)
303            [xtable ytable utable vtable ctable F result_conv errormsg] = civ (par_civ1);
304            if ~isempty(errormsg)
305                return
306            end
307            Data.Civ1_X=reshape(xtable,[],1);
308            Data.Civ1_Y=reshape(par_civ1.ImageHeight-ytable+1,[],1);
309            Data.Civ1_U=reshape(utable,[],1);
310            Data.Civ1_V=reshape(-vtable,[],1);
311            Data.Civ1_C=reshape(ctable,[],1);
312            Data.Civ1_F=reshape(F,[],1);
313        end
314    else
315        if exist('ncfile','var')
316            CivFile=ncfile;
317        elseif isfield(Param.Patch1,'CivFile')
318            CivFile=Param.Patch1.CivFile;
319        end
320        Data=nc2struct(CivFile,'ListGlobalAttribute','absolut_time_T0'); %look for the constant 'absolut_time_T0' to detect old civx data format
321        if isfield(Data,'Txt')
322            errormsg=Data.Txt;
323            return
324        end
325        if ~isempty(Data.absolut_time_T0')%read civx file
326            check_civx=1;% test for old civx data format
327            [Data,vardetect,ichoice]=nc2struct(CivFile);%read the variables in the netcdf file
328        else
329            Data=nc2struct(CivFile);%read civ1 and fix1 data in the existing netcdf file
330        end
331    end
332   
333    %% Fix1
334    if isfield (Param.ActionInput,'Fix1')
335        ListFixParam=fieldnames(Param.ActionInput.Fix1);
336        for ilist=1:length(ListFixParam)
337            ParamName=ListFixParam{ilist};
338            ListName=['Fix1_' ParamName];
339            eval(['Data.ListGlobalAttribute=[Data.ListGlobalAttribute ''' ParamName '''];'])
340            eval(['Data.' ListName '=Param.ActionInput.Fix1.' ParamName ';'])
341        end
342        if check_civx
343            if ~isfield(Data,'fix')
344                Data.ListGlobalAttribute=[Data.ListGlobalAttribute 'fix'];
345                Data.fix=1;
346                Data.ListVarName=[Data.ListVarName {'vec_FixFlag'}];
347                Data.VarDimName=[Data.VarDimName {'nb_vectors'}];
348            end
349            Data.vec_FixFlag=fix(Param.ActionInput.Fix1,Data.vec_F,Data.vec_C,Data.vec_U,Data.vec_V,Data.vec_X,Data.vec_Y);
350        else
351            Data.ListVarName=[Data.ListVarName {'Civ1_FF'}];
352            Data.VarDimName=[Data.VarDimName {'nb_vec_1'}];
353            nbvar=length(Data.ListVarName);
354            Data.VarAttribute{nbvar}.Role='errorflag';
355            Data.Civ1_FF=fix(Param.ActionInput.Fix1,Data.Civ1_F,Data.Civ1_C,Data.Civ1_U,Data.Civ1_V);
356            Data.CivStage=2;
357        end
358    end
359    %% Patch1
360    if isfield (Param.ActionInput,'Patch1')
361        if check_civx
362            errormsg='Civ Matlab input needed for patch';
363            return
364        end
365       
366        Data.ListGlobalAttribute=[Data.ListGlobalAttribute {'Patch1_Rho','Patch1_Threshold','Patch1_SubDomain'}];
367        Data.Patch1_FieldSmooth=Param.ActionInput.Patch1.FieldSmooth;
368        Data.Patch1_MaxDiff=Param.ActionInput.Patch1.MaxDiff;
369        Data.Patch1_SubDomainSize=Param.ActionInput.Patch1.SubDomainSize;
370        nbvar=length(Data.ListVarName);
371        Data.ListVarName=[Data.ListVarName {'Civ1_U_smooth','Civ1_V_smooth','Civ1_SubRange','Civ1_NbCentres','Civ1_Coord_tps','Civ1_U_tps','Civ1_V_tps'}];
372        Data.VarDimName=[Data.VarDimName {'nb_vec_1','nb_vec_1',{'nb_coord','nb_bounds','nb_subdomain_1'},'nb_subdomain_1',...
373            {'nb_tps_1','nb_coord','nb_subdomain_1'},{'nb_tps_1','nb_subdomain_1'},{'nb_tps_1','nb_subdomain_1'}}];
374        Data.VarAttribute{nbvar+1}.Role='vector_x';
375        Data.VarAttribute{nbvar+2}.Role='vector_y';
376        Data.VarAttribute{nbvar+5}.Role='coord_tps';
377        Data.VarAttribute{nbvar+6}.Role='vector_x';
378        Data.VarAttribute{nbvar+7}.Role='vector_y';
379        Data.Civ1_U_smooth=zeros(size(Data.Civ1_X));
380        Data.Civ1_V_smooth=zeros(size(Data.Civ1_X));
381        if isfield(Data,'Civ1_FF')
382            ind_good=find(Data.Civ1_FF==0);
383        else
384            ind_good=1:numel(Data.Civ1_X);
385        end
386        [Data.Civ1_SubRange,Data.Civ1_NbCentres,Data.Civ1_Coord_tps,Data.Civ1_U_tps,Data.Civ1_V_tps,tild,Ures, Vres,tild,FFres]=...
387            filter_tps([Data.Civ1_X(ind_good) Data.Civ1_Y(ind_good)],Data.Civ1_U(ind_good),Data.Civ1_V(ind_good),[],Data.Patch1_SubDomainSize,Data.Patch1_FieldSmooth,Data.Patch1_MaxDiff);
388        Data.Civ1_U_smooth(ind_good)=Ures;
389        Data.Civ1_V_smooth(ind_good)=Vres;
390        Data.Civ1_FF(ind_good)=FFres;
391        Data.CivStage=3;
392    end
393   
394    %% Civ2
395    if isfield (Param.ActionInput,'Civ2')
396        par_civ2=Param.ActionInput.Civ2;
397        par_civ2.ImageA=[];
398        par_civ2.ImageB=[];
399        %         if ~isfield(Param.Civ1,'ImageA')
400        ImageName_A_Civ2=fullfile_uvmat(RootPath,SubDir,RootFile,FileExt,NomType,i1_series_Civ2(ifield),[],j1_series_Civ2(ifield));
401
402        if strcmp(ImageName_A_Civ2,ImageName_A) && isequal(FrameIndex_A_Civ1(ifield),FrameIndex_A_Civ2)
403            par_civ2.ImageA=par_civ1.ImageA;
404        else
405            [par_civ2.ImageA,VideoObject_A] = read_image(ImageName_A,FileType_A,VideoObject_A,FrameIndex_A_Civ2);
406        end
407        ImageName_B_Civ2=fullfile_uvmat(RootPath,SubDir,RootFile,FileExt,NomType,i2_series_Civ2(ifield),[],j2_series_Civ2(ifield));
408        if strcmp(ImageName_B_Civ2,ImageName_B) && isequal(FrameIndex_B_Civ1(ifield),FrameIndex_B_Civ2)
409            par_civ2.ImageB=par_civ1.ImageB;
410        else
411            [par_civ2.ImageB,VideoObject_B] = read_image(ImageName_B,FileType_B,VideoObject_B,FrameIndex_B_Civ2);
412        end     
413       
414        ncfile=fullfile_uvmat(RootPath,OutputDir,RootFile,'.nc',NomTypeNc,i1_series_Civ2(ifield),i2_series_Civ2(ifield),...
415            j1_series_Civ2(ifield),j2_series_Civ2(ifield));
416        par_civ2.ImageWidth=FileInfo.Width;
417        par_civ2.ImageHeight=FileInfo.Height;
418       
419        if isfield(par_civ2,'Grid')% grid points set as input file
420            if ischar(par_civ2.Grid)%read the grid file if the input is a file name
421                par_civ2.Grid=dlmread(par_civ2.Grid);
422                par_civ2.Grid(1,:)=[];%the first line must be removed (heading in the grid file)
423            end
424        else% automatic grid
425            minix=floor(par_civ2.Dx/2)-0.5;
426            maxix=minix+par_civ2.Dx*floor((par_civ2.ImageWidth-1)/par_civ2.Dx);
427            miniy=floor(par_civ2.Dy/2)-0.5;
428            maxiy=minix+par_civ2.Dy*floor((par_civ2.ImageHeight-1)/par_civ2.Dy);
429            [GridX,GridY]=meshgrid(minix:par_civ2.Dx:maxix,miniy:par_civ2.Dy:maxiy);
430            par_civ2.Grid(:,1)=reshape(GridX,[],1);
431            par_civ2.Grid(:,2)=reshape(GridY,[],1);
432        end
433        Shiftx=zeros(size(par_civ2.Grid,1),1);% shift expected from civ1 data
434        Shifty=zeros(size(par_civ2.Grid,1),1);
435        nbval=zeros(size(par_civ2.Grid,1),1);
436        if par_civ2.CheckDeformation
437            DUDX=zeros(size(par_civ2.Grid,1),1);
438            DUDY=zeros(size(par_civ2.Grid,1),1);
439            DVDX=zeros(size(par_civ2.Grid,1),1);
440            DVDY=zeros(size(par_civ2.Grid,1),1);
441        end
442        NbSubDomain=size(Data.Civ1_SubRange,3);
443        % get the guess from patch1
444        for isub=1:NbSubDomain
445            nbvec_sub=Data.Civ1_NbCentres(isub);
446            ind_sel=find(GridX>=Data.Civ1_SubRange(1,1,isub) & GridX<=Data.Civ1_SubRange(1,2,isub) & GridY>=Data.Civ1_SubRange(2,1,isub) & GridY<=Data.Civ1_SubRange(2,2,isub));
447            epoints = [GridX(ind_sel) GridY(ind_sel)];% coordinates of interpolation sites
448            ctrs=Data.Civ1_Coord_tps(1:nbvec_sub,:,isub) ;%(=initial points) ctrs
449            nbval(ind_sel)=nbval(ind_sel)+1;% records the number of values for eacn interpolation point (in case of subdomain overlap)
450            EM = tps_eval(epoints,ctrs);
451            Shiftx(ind_sel)=Shiftx(ind_sel)+EM*Data.Civ1_U_tps(1:nbvec_sub+3,isub);
452            Shifty(ind_sel)=Shifty(ind_sel)+EM*Data.Civ1_V_tps(1:nbvec_sub+3,isub);
453            if par_civ2.CheckDeformation
454                [EMDX,EMDY] = tps_eval_dxy(epoints,ctrs);%2D matrix of distances between extrapolation points epoints and spline centres (=site points) ctrs
455                DUDX(ind_sel)=DUDX(ind_sel)+EMDX*Data.Civ1_U_tps(1:nbvec_sub+3,isub);
456                DUDY(ind_sel)=DUDY(ind_sel)+EMDY*Data.Civ1_U_tps(1:nbvec_sub+3,isub);
457                DVDX(ind_sel)=DVDX(ind_sel)+EMDX*Data.Civ1_V_tps(1:nbvec_sub+3,isub);
458                DVDY(ind_sel)=DVDY(ind_sel)+EMDY*Data.Civ1_V_tps(1:nbvec_sub+3,isub);
459            end
460        end
461        mask='';
462        if par_civ2.CheckMask&&~isempty(par_civ2.Mask)&& ~strcmp(maskname,par_civ2.Mask)% mask exist, not already read in civ1
463            mask=imread(par_civ2.Mask);
464        end
465        ibx2=ceil(par_civ2.CorrBoxSize(1)/2);
466        iby2=ceil(par_civ2.CorrBoxSize(2)/2);
467        par_civ2.SearchBoxSize(1)=2*ibx2+9;% search ara +-4 pixels around the guess
468        par_civ2.SearchBoxSize(2)=2*iby2+9;
469        par_civ2.SearchBoxShift=[Shiftx(nbval>=1)./nbval(nbval>=1) Shifty(nbval>=1)./nbval(nbval>=1)];
470        par_civ2.Grid=[GridX(nbval>=1)-par_civ2.SearchBoxShift(:,1)/2 GridY(nbval>=1)-par_civ2.SearchBoxShift(:,2)/2];% grid taken at the extrapolated origin of the displacement vectors
471        if par_civ2.CheckDeformation
472            par_civ2.DUDX=DUDX./nbval;
473            par_civ2.DUDY=DUDY./nbval;
474            par_civ2.DVDX=DVDX./nbval;
475            par_civ2.DVDY=DVDY./nbval;
476        end
477        % caluclate velocity data (y and v in indices, reverse to y component)
478        [xtable ytable utable vtable ctable F] = civ (par_civ2);
479
480        list_param=(fieldnames(Param.ActionInput.Civ2))';
481        Civ2_param=regexprep(list_param,'^.+','Civ2_$0');% insert 'Civ2_' before  each string in list_param
482        Civ2_param=[{'Civ2_ImageA','Civ2_ImageB','Civ2_Time','Civ2_Dt'} Civ2_param]; %insert the names of the two input images
483        %indicate the values of all the global attributes in the output data
484        Data.Civ2_ImageA=ImageName_A;
485        Data.Civ2_ImageB=ImageName_B;
486        Data.Civ2_Time=1;
487        Data.Civ2_Dt=1;
488        for ilist=1:length(list_param)
489            Data.(Civ2_param{4+ilist})=Param.ActionInput.Civ2.(list_param{ilist});
490        end
491        Data.ListGlobalAttribute=[Data.ListGlobalAttribute Civ2_param];
492       
493        nbvar=numel(Data.ListVarName);
494        Data.ListVarName=[Data.ListVarName {'Civ2_X','Civ2_Y','Civ2_U','Civ2_V','Civ2_F','Civ2_C'}];%  cell array containing the names of the fields to record
495        Data.VarDimName=[Data.VarDimName {'nb_vec_2','nb_vec_2','nb_vec_2','nb_vec_2','nb_vec_2','nb_vec_2'}];
496        Data.VarAttribute{nbvar+1}.Role='coord_x';
497        Data.VarAttribute{nbvar+2}.Role='coord_y';
498        Data.VarAttribute{nbvar+3}.Role='vector_x';
499        Data.VarAttribute{nbvar+4}.Role='vector_y';
500        Data.VarAttribute{nbvar+5}.Role='warnflag';
501        Data.Civ2_X=reshape(xtable,[],1);
502        Data.Civ2_Y=reshape(size(par_civ2.ImageA,1)-ytable+1,[],1);
503        Data.Civ2_U=reshape(utable,[],1);
504        Data.Civ2_V=reshape(-vtable,[],1);
505        Data.Civ2_C=reshape(ctable,[],1);
506        Data.Civ2_F=reshape(F,[],1);
507        Data.CivStage=Data.CivStage+1;
508    end
509   
510    %% Fix2
511    if isfield (Param.ActionInput,'Fix2')
512        ListFixParam=fieldnames(Param.ActionInput.Fix2);
513        for ilist=1:length(ListFixParam)
514            ParamName=ListFixParam{ilist};
515            ListName=['Fix2_' ParamName];
516            eval(['Data.ListGlobalAttribute=[Data.ListGlobalAttribute ''' ParamName '''];'])
517            eval(['Data.' ListName '=Param.ActionInput.Fix2.' ParamName ';'])
518        end
519        if check_civx
520            if ~isfield(Data,'fix2')
521                Data.ListGlobalAttribute=[Data.ListGlobalAttribute 'fix2'];
522                Data.fix2=1;
523                Data.ListVarName=[Data.ListVarName {'vec2_FixFlag'}];
524                Data.VarDimName=[Data.VarDimName {'nb_vectors2'}];
525            end
526            Data.vec_FixFlag=fix(Param.Fix2,Data.vec2_F,Data.vec2_C,Data.vec2_U,Data.vec2_V,Data.vec2_X,Data.vec2_Y);
527        else
528            Data.ListVarName=[Data.ListVarName {'Civ2_FF'}];
529            Data.VarDimName=[Data.VarDimName {'nb_vec_2'}];
530            nbvar=length(Data.ListVarName);
531            Data.VarAttribute{nbvar}.Role='errorflag';
532            Data.Civ2_FF=fix(Param.ActionInput.Fix2,Data.Civ2_F,Data.Civ2_C,Data.Civ2_U,Data.Civ2_V);
533            Data.CivStage=Data.CivStage+1;
534        end
535       
536    end
537   
538    %% Patch2
539    if isfield (Param.ActionInput,'Patch2')
540        Data.ListGlobalAttribute=[Data.ListGlobalAttribute {'Patch2_Rho','Patch2_Threshold','Patch2_SubDomain'}];
541        Data.Patch2_FieldSmooth=Param.ActionInput.Patch2.FieldSmooth;
542        Data.Patch2_MaxDiff=Param.ActionInput.Patch2.MaxDiff;
543        Data.Patch2_SubDomainSize=Param.ActionInput.Patch2.SubDomainSize;
544        nbvar=length(Data.ListVarName);
545        Data.ListVarName=[Data.ListVarName {'Civ2_U_smooth','Civ2_V_smooth','Civ2_SubRange','Civ2_NbCentres','Civ2_Coord_tps','Civ2_U_tps','Civ2_V_tps'}];
546        Data.VarDimName=[Data.VarDimName {'nb_vec_2','nb_vec_2',{'nb_coord','nb_bounds','nb_subdomain_2'},{'nb_subdomain_2'},...
547            {'nb_tps_2','nb_coord','nb_subdomain_2'},{'nb_tps_2','nb_subdomain_2'},{'nb_tps_2','nb_subdomain_2'}}];
548       
549        Data.VarAttribute{nbvar+1}.Role='vector_x';
550        Data.VarAttribute{nbvar+2}.Role='vector_y';
551        Data.VarAttribute{nbvar+5}.Role='coord_tps';
552        Data.VarAttribute{nbvar+6}.Role='vector_x';
553        Data.VarAttribute{nbvar+7}.Role='vector_y';
554        Data.Civ2_U_smooth=zeros(size(Data.Civ2_X));
555        Data.Civ2_V_smooth=zeros(size(Data.Civ2_X));
556        if isfield(Data,'Civ2_FF')
557            ind_good=find(Data.Civ2_FF==0);
558        else
559            ind_good=1:numel(Data.Civ2_X);
560        end
561        [Data.Civ2_SubRange,Data.Civ2_NbCentres,Data.Civ2_Coord_tps,Data.Civ2_U_tps,Data.Civ2_V_tps,tild,Ures, Vres,tild,FFres]=...
562            filter_tps([Data.Civ2_X(ind_good) Data.Civ2_Y(ind_good)],Data.Civ2_U(ind_good),Data.Civ2_V(ind_good),[],Data.Patch2_SubDomainSize,Data.Patch2_FieldSmooth,Data.Patch2_MaxDiff);
563        Data.Civ2_U_smooth(ind_good)=Ures;
564        Data.Civ2_V_smooth(ind_good)=Vres;
565        Data.Civ2_FF(ind_good)=FFres;
566        Data.CivStage=Data.CivStage+1;
567    end
568   
569    %% write result in a netcdf file if requested
570    if exist('ncfile','var')
571        errormsg=struct2nc(ncfile,Data);
572        if isempty(errormsg)
573            disp([ncfile ' written'])
574        else
575            disp(errormsg)
576        end
577    end
578end
579
580% 'civ': function piv.m adapted from PIVlab http://pivlab.blogspot.com/
581%--------------------------------------------------------------------------
582% function [xtable ytable utable vtable typevector] = civ (image1,image2,ibx,iby step, subpixfinder, mask, roi)
583%
584% OUTPUT:
585% xtable: set of x coordinates
586% ytable: set of y coordiantes
587% utable: set of u displacements (along x)
588% vtable: set of v displacements (along y)
589% ctable: max image correlation for each vector
590% typevector: set of flags, =1 for good, =0 for NaN vectors
591%
592%INPUT:
593% par_civ: structure of input parameters, with fields:
594%  .CorrBoxSize
595%  .SearchBoxSize
596%  .SearchBoxShift
597%  .ImageHeight
598%  .ImageWidth
599%  .Dx, Dy
600%  .Grid
601%  .Mask
602%  .MinIma
603%  .MaxIma
604%  .image1:first image (matrix)
605% image2: second image (matrix)
606% ibx2,iby2: half size of the correlation box along x and y, in px (size=(2*iby2+1,2*ibx2+1)
607% isx2,isy2: half size of the search box along x and y, in px (size=(2*isy2+1,2*isx2+1)
608% shiftx, shifty: shift of the search box (in pixel index, yshift reversed)
609% step: mesh of the measurement points (in px)
610% subpixfinder=1 or 2 controls the curve fitting of the image correlation
611% mask: =[] for no mask
612% roi: 4 element vector defining a region of interest: x position, y position, width, height, (in image indices), for the whole image, roi=[];
613function [xtable ytable utable vtable ctable F result_conv errormsg] = civ (par_civ)
614%this funtion performs the DCC PIV analysis. Recent window-deformation
615%methods perform better and will maybe be implemented in the future.
616
617%% prepare measurement grid
618if isfield(par_civ,'Grid')% grid points set as input
619    if ischar(par_civ.Grid)%read the drid file if the input is a file name
620        par_civ.Grid=dlmread(par_civ.Grid);
621        par_civ.Grid(1,:)=[];%the first line must be removed (heading in the grid file)
622    end
623else% automatic grid
624    minix=floor(par_civ.Dx/2)-0.5;
625    maxix=minix+par_civ.Dx*floor((par_civ.ImageWidth-1)/par_civ.Dx);
626    miniy=floor(par_civ.Dy/2)-0.5;
627    maxiy=minix+par_civ.Dy*floor((par_civ.ImageHeight-1)/par_civ.Dy);
628    [GridX,GridY]=meshgrid(minix:par_civ.Dx:maxix,miniy:par_civ.Dy:maxiy);
629    par_civ.Grid(:,1)=reshape(GridX,[],1);
630    par_civ.Grid(:,2)=reshape(GridY,[],1);
631end
632nbvec=size(par_civ.Grid,1);
633
634%% prepare correlation and search boxes
635ibx2=ceil(par_civ.CorrBoxSize(1)/2);
636iby2=ceil(par_civ.CorrBoxSize(2)/2);
637isx2=ceil(par_civ.SearchBoxSize(1)/2);
638isy2=ceil(par_civ.SearchBoxSize(2)/2);
639shiftx=round(par_civ.SearchBoxShift(:,1));
640shifty=-round(par_civ.SearchBoxShift(:,2));% sign minus because image j index increases when y decreases
641if numel(shiftx)==1% case of a unique shift for the whole field( civ1)
642    shiftx=shiftx*ones(nbvec,1);
643    shifty=shifty*ones(nbvec,1);
644end
645
646%% Default output
647xtable=par_civ.Grid(:,1);
648ytable=par_civ.Grid(:,2);
649utable=zeros(nbvec,1);
650vtable=zeros(nbvec,1);
651ctable=zeros(nbvec,1);
652F=zeros(nbvec,1);
653result_conv=[];
654errormsg='';
655
656%% prepare mask
657if isfield(par_civ,'Mask') && ~isempty(par_civ.Mask)
658    if strcmp(par_civ.Mask,'all')
659        return    % get the grid only, no civ calculation
660    elseif ischar(par_civ.Mask)
661        par_civ.Mask=imread(par_civ.Mask);
662    end
663end
664check_MinIma=isfield(par_civ,'MinIma');% test for image luminosity threshold
665check_MaxIma=isfield(par_civ,'MaxIma') && ~isempty(par_civ.MaxIma);
666
667% %% prepare images
668% if isfield(par_civ,'reverse_pair')
669%     if par_civ.reverse_pair
670%         if ischar(par_civ.ImageB)
671%             temp=par_civ.ImageA;
672%             par_civ.ImageA=imread(par_civ.ImageB);
673%         end
674%         if ischar(temp)
675%             par_civ.ImageB=imread(temp);
676%         end
677%     end
678% else
679%     if ischar(par_civ.ImageA)
680%         par_civ.ImageA=imread(par_civ.ImageA);
681%     end
682%     if ischar(par_civ.ImageB)
683%         par_civ.ImageB=imread(par_civ.ImageB);
684%     end
685% end
686par_civ.ImageA=sum(double(par_civ.ImageA),3);%sum over rgb component for color images
687par_civ.ImageB=sum(double(par_civ.ImageB),3);
688[npy_ima npx_ima]=size(par_civ.ImageA);
689if ~isequal(size(par_civ.ImageB),[npy_ima npx_ima])
690    errormsg='image pair with unequal size';
691    return
692end
693
694%% Apply mask
695    % Convention for mask IDEAS TO IMPLEMENT ?
696    % mask >200 : velocity calculated
697    %  200 >=mask>150;velocity not calculated, interpolation allowed (bad spots)
698    % 150>=mask >100: velocity not calculated, nor interpolated
699    %  100>=mask> 20: velocity not calculated, impermeable (no flux through mask boundaries)
700    %  20>=mask: velocity=0
701checkmask=0;
702MinA=min(min(par_civ.ImageA));
703MinB=min(min(par_civ.ImageB));
704if isfield(par_civ,'Mask') && ~isempty(par_civ.Mask)
705   checkmask=1;
706   if ~isequal(size(par_civ.Mask),[npy_ima npx_ima])
707        errormsg='mask must be an image with the same size as the images';
708        return
709   end
710  %  check_noflux=(par_civ.Mask<100) ;%TODO: to implement
711    check_undefined=(par_civ.Mask<200 & par_civ.Mask>=20 );
712    par_civ.ImageA(check_undefined)=MinA;% put image A to zero (i.e. the min image value) in the undefined  area
713    par_civ.ImageB(check_undefined)=MinB;% put image B to zero (i.e. the min image value) in the undefined  area
714end
715
716%% compute image correlations: MAINLOOP on velocity vectors
717corrmax=0;
718sum_square=1;% default
719mesh=1;% default
720CheckDecimal=isfield(par_civ,'CheckDecimal')&& par_civ.CheckDecimal==1;
721if CheckDecimal
722    mesh=0.2;%mesh in pixels for subpixel image interpolation
723    CheckDeformation=isfield(par_civ,'CheckDeformation')&& par_civ.CheckDeformation==1;
724end
725% vector=[0 0];%default
726for ivec=1:nbvec
727    iref=round(par_civ.Grid(ivec,1)+0.5);% xindex on the image A for the middle of the correlation box
728    jref=round(par_civ.ImageHeight-par_civ.Grid(ivec,2)+0.5);% yindex on the image B for the middle of the correlation box
729    %if ~(checkmask && par_civ.Mask(jref,iref)<=20) %velocity not set to zero by the black mask
730    %         if jref-iby2<1 || jref+iby2>par_civ.ImageHeight|| iref-ibx2<1 || iref+ibx2>par_civ.ImageWidth||...
731    %               jref+shifty(ivec)-isy2<1||jref+shifty(ivec)+isy2>par_civ.ImageHeight|| iref+shiftx(ivec)-isx2<1 || iref+shiftx(ivec)+isx2>par_civ.ImageWidth  % we are outside the image
732    %             F(ivec)=3;
733    %         else
734    F(ivec)=0;
735    subrange1_x=iref-ibx2:iref+ibx2;% x indices defining the first subimage
736    subrange1_y=jref-iby2:jref+iby2;% y indices defining the first subimage
737    subrange2_x=iref+shiftx(ivec)-isx2:iref+shiftx(ivec)+isx2;%x indices defining the second subimage
738    subrange2_y=jref+shifty(ivec)-isy2:jref+shifty(ivec)+isy2;%y indices defining the second subimage
739    image1_crop=MinA*ones(numel(subrange1_y),numel(subrange1_x));% default value=min of image A
740    image2_crop=MinA*ones(numel(subrange2_y),numel(subrange2_x));% default value=min of image A
741    check1_x=subrange1_x>=1 & subrange1_x<=par_civ.ImageWidth;% check which points in the subimage 1 are contained in the initial image 1
742    check1_y=subrange1_y>=1 & subrange1_y<=par_civ.ImageHeight;
743    check2_x=subrange2_x>=1 & subrange2_x<=par_civ.ImageWidth;% check which points in the subimage 2 are contained in the initial image 2
744    check2_y=subrange2_y>=1 & subrange2_y<=par_civ.ImageHeight;
745   
746    image1_crop(check1_y,check1_x)=par_civ.ImageA(subrange1_y(check1_y),subrange1_x(check1_x));%extract a subimage (correlation box) from image A
747    image2_crop(check2_y,check2_x)=par_civ.ImageB(subrange2_y(check2_y),subrange2_x(check2_x));%extract a larger subimage (search box) from image B
748    image1_mean=mean(mean(image1_crop));
749    image2_mean=mean(mean(image2_crop));
750    %threshold on image minimum
751    if check_MinIma && (image1_mean < par_civ.MinIma || image2_mean < par_civ.MinIma)
752        F(ivec)=3;
753    end
754    %threshold on image maximum
755    if check_MaxIma && (image1_mean > par_civ.MaxIma || image2_mean > par_civ.MaxIma)
756        F(ivec)=3;
757    end
758    %         end
759    if F(ivec)~=3
760        image1_crop=image1_crop-image1_mean;%substract the mean
761        image2_crop=image2_crop-image2_mean;
762        if CheckDecimal
763            xi=(1:mesh:size(image1_crop,2));
764            yi=(1:mesh:size(image1_crop,1))';
765            if CheckDeformation
766                [XI,YI]=meshgrid(xi-ceil(size(image1_crop,2)/2),yi-ceil(size(image1_crop,1)/2));
767                XIant=XI-par_civ.DUDX(ivec)*XI-par_civ.DUDY(ivec)*YI+ceil(size(image1_crop,2)/2);
768                YIant=YI-par_civ.DVDX(ivec)*XI-par_civ.DVDY(ivec)*YI+ceil(size(image1_crop,1)/2);
769                image1_crop=interp2(image1_crop,XIant,YIant);
770            else
771                image1_crop=interp2(image1_crop,xi,yi);
772            end
773            xi=(1:mesh:size(image2_crop,2));
774            yi=(1:mesh:size(image2_crop,1))';
775            image2_crop=interp2(image2_crop,xi,yi);
776        end
777        sum_square=sum(sum(image1_crop.*image1_crop));
778        %reference: Oliver Pust, PIV: Direct Cross-Correlation
779        result_conv= conv2(image2_crop,flipdim(flipdim(image1_crop,2),1),'valid');
780        corrmax= max(max(result_conv));
781        result_conv=(result_conv/corrmax)*255; %normalize, peak=always 255
782        %Find the correlation max, at 255
783        [y,x] = find(result_conv==255,1);
784        if ~isempty(y) && ~isempty(x)
785            try
786                if par_civ.CorrSmooth==1
787                    [vector,F(ivec)] = SUBPIXGAUSS (result_conv,x,y);
788                elseif par_civ.CorrSmooth==2
789                    [vector,F(ivec)] = SUBPIX2DGAUSS (result_conv,x,y);
790                end
791                utable(ivec)=vector(1)*mesh+shiftx(ivec);
792                vtable(ivec)=vector(2)*mesh+shifty(ivec);
793                xtable(ivec)=iref+utable(ivec)/2-0.5;% convec flow (velocity taken at the point middle from imgae 1 and 2)
794                ytable(ivec)=jref+vtable(ivec)/2-0.5;% and position of pixel 1=0.5 (convention for image coordinates=0 at the edge)
795                iref=round(xtable(ivec));% image index for the middle of the vector
796                jref=round(ytable(ivec));
797                if checkmask && par_civ.Mask(jref,iref)<200 && par_civ.Mask(jref,iref)>=100
798                    utable(ivec)=0;
799                    vtable(ivec)=0;
800                    F(ivec)=3;
801                end
802                ctable(ivec)=corrmax/sum_square;% correlation value
803            catch ME
804                F(ivec)=3;
805            end
806        else
807            F(ivec)=3;
808        end
809    end
810end
811result_conv=result_conv*corrmax/(255*sum_square);% keep the last correlation matrix for output
812
813%------------------------------------------------------------------------
814% --- Find the maximum of the correlation function after interpolation
815function [vector,F] = SUBPIXGAUSS (result_conv,x,y)
816%------------------------------------------------------------------------
817vector=[0 0]; %default
818F=0;
819[npy,npx]=size(result_conv);
820
821% if (x <= (size(result_conv,1)-1)) && (y <= (size(result_conv,1)-1)) && (x >= 1) && (y >= 1)
822    %the following 8 lines are copyright (c) 1998, Uri Shavit, Roi Gurka, Alex Liberzon, Technion ï¿œ Israel Institute of Technology
823    %http://urapiv.wordpress.com
824    peaky = y;
825    if y <= npy-1 && y >= 1
826        f0 = log(result_conv(y,x));
827        f1 = real(log(result_conv(y-1,x)));
828        f2 = real(log(result_conv(y+1,x)));
829        peaky = peaky+ (f1-f2)/(2*f1-4*f0+2*f2);
830    else
831        F=-2; % warning flag for vector truncated by the limited search box
832    end
833    peakx=x;
834    if x <= npx-1 && x >= 1
835        f0 = log(result_conv(y,x));
836        f1 = real(log(result_conv(y,x-1)));
837        f2 = real(log(result_conv(y,x+1)));
838        peakx = peakx+ (f1-f2)/(2*f1-4*f0+2*f2);
839    else
840        F=-2; % warning flag for vector truncated by the limited search box
841    end
842    vector=[peakx-floor(npx/2)-1 peaky-floor(npy/2)-1];
843
844%------------------------------------------------------------------------
845% --- Find the maximum of the correlation function after interpolation
846function [vector,F] = SUBPIX2DGAUSS (result_conv,x,y)
847%------------------------------------------------------------------------
848vector=[0 0]; %default
849F=-2;
850peaky=y;
851peakx=x;
852[npy,npx]=size(result_conv);
853if (x <= npx-1) && (y <= npy-1) && (x >= 1) && (y >= 1)
854    F=0;
855    for i=-1:1
856        for j=-1:1
857            %following 15 lines based on
858            %H. Nobach ï¿œ M. Honkanen (2005)
859            %Two-dimensional Gaussian regression for sub-pixel displacement
860            %estimation in particle image velocimetry or particle position
861            %estimation in particle tracking velocimetry
862            %Experiments in Fluids (2005) 38: 511ï¿œ515
863            c10(j+2,i+2)=i*log(result_conv(y+j, x+i));
864            c01(j+2,i+2)=j*log(result_conv(y+j, x+i));
865            c11(j+2,i+2)=i*j*log(result_conv(y+j, x+i));
866            c20(j+2,i+2)=(3*i^2-2)*log(result_conv(y+j, x+i));
867            c02(j+2,i+2)=(3*j^2-2)*log(result_conv(y+j, x+i));
868        end
869    end
870    c10=(1/6)*sum(sum(c10));
871    c01=(1/6)*sum(sum(c01));
872    c11=(1/4)*sum(sum(c11));
873    c20=(1/6)*sum(sum(c20));
874    c02=(1/6)*sum(sum(c02));
875    deltax=(c11*c01-2*c10*c02)/(4*c20*c02-c11^2);
876    deltay=(c11*c10-2*c01*c20)/(4*c20*c02-c11^2);
877    if abs(deltax)<1
878        peakx=x+deltax;
879    end
880    if abs(deltay)<1
881        peaky=y+deltay;
882    end
883end
884vector=[peakx-floor(npx/2)-1 peaky-floor(npy/2)-1];
885
886%'RUN_FIX': function for fixing velocity fields:
887%-----------------------------------------------
888% RUN_FIX(filename,field,flagindex,thresh_vecC,thresh_vel,iter,flag_mask,maskname,fileref,fieldref)
889%
890%filename: name of the netcdf file (used as input and output)
891%field: structure specifying the names of the fields to fix (depending on civ1 or civ2)
892    %.vel_type='civ1' or 'civ2';
893    %.nb=name of the dimension common to the field to fix ('nb_vectors' for civ1);
894    %.fixflag=name of fix flag variable ('vec_FixFlag' for civ1)
895%flagindex: flag specifying which values of vec_f are removed:
896        % if flagindex(1)=1: vec_f=-2 vectors are removed
897        % if flagindex(2)=1: vec_f=3 vectors are removed
898        % if flagindex(3)=1: vec_f=2 vectors are removed (if iter=1) or vec_f=4 vectors are removed (if iter=2)
899%iter=1 for civ1 fields and iter=2 for civ2 fields
900%thresh_vecC: threshold in the image correlation vec_C
901%flag_mask: =1 mask used to remove vectors (0 else)
902%maskname: name of the mask image file for fix
903%thresh_vel: threshold on velocity, or on the difference with the reference file fileref if exists
904%inf_sup=1: remove values smaller than threshold thresh_vel, =2, larger than threshold
905%fileref: .nc file name for a reference velocity (='': refrence 0 used)
906%fieldref: 'civ1','filter1'...feld used in fileref
907
908function FF=fix(Param,F,C,U,V,X,Y)
909FF=zeros(size(F));%default
910
911%criterium on warn flags
912FlagName={'CheckFmin2','CheckF2','CheckF3','CheckF4'};
913FlagVal=[-2 2 3 4];
914for iflag=1:numel(FlagName)
915    if isfield(Param,FlagName{iflag}) && Param.(FlagName{iflag})
916        FF=(FF==1| F==FlagVal(iflag));
917    end
918end
919%criterium on correlation values
920if isfield (Param,'MinCorr')
921    FF=FF==1 | C<Param.MinCorr;
922end
923if (isfield(Param,'MinVel')&&~isempty(Param.MinVel))||(isfield (Param,'MaxVel')&&~isempty(Param.MaxVel))
924    Umod= U.*U+V.*V;
925    if isfield (Param,'MinVel')&&~isempty(Param.MinVel)
926        FF=FF==1 | Umod<(Param.MinVel*Param.MinVel);
927    end
928    if isfield (Param,'MaxVel')&&~isempty(Param.MaxVel)
929        FF=FF==1 | Umod>(Param.MaxVel*Param.MaxVel);
930    end
931end
932
933
934%------------------------------------------------------------------------
935% --- determine the list of index pairs of processing file
936function [i1_series,i2_series,j1_series,j2_series,check_bounds,NomTypeNc]=...
937    find_pair_indices(str_civ,i_series,j_series,MinIndex,MaxIndex)
938%------------------------------------------------------------------------
939i1_series=i_series;% set of first image indexes
940i2_series=i_series;
941j1_series=ones(size(i_series));% set of first image numbers
942j2_series=ones(size(i_series));
943check_bounds=false(size(i_series));
944r=regexp(str_civ,'^\D(?<ind>[i|j])=( -| )(?<num1>\d+)\|(?<num2>\d+)','names');
945if ~isempty(r)
946    mode=['D' r.ind];
947    ind1=str2num(r.num1);
948    ind2=str2num(r.num2);
949else
950    mode='burst';
951    r=regexp(str_civ,'^j= (?<num1>[a-z])-(?<num2>[a-z])','names');
952    if ~isempty(r)
953        NomTypeNc='_1ab';
954    else
955        r=regexp(str_civ,'^j= (?<num1>[A-Z])-(?<num2>[A-Z])','names');
956        if ~isempty(r)
957            NomTypeNc='_1AB';
958        else
959            r=regexp(str_civ,'^j= (?<num1>\d+)-(?<num2>\d+)','names');
960            if ~isempty(r)
961                NomTypeNc='_1_1-2';
962            end           
963        end
964    end
965    if isempty(r)
966        display('wrong pair mode input option')
967    else
968    ind1=stra2num(r.num1);
969    ind2=stra2num(r.num2);
970    end
971end
972if strcmp (mode,'Di')
973    i1_series=i_series-ind1;% set of first image numbers
974    i2_series=i_series+ind2;
975    check_bounds=i1_series<MinIndex(1,1) | i2_series>MaxIndex(1,1);
976    if isempty(j_series)
977        NomTypeNc='_1-2';
978    else
979        j1_series=j_series;
980        j2_series=j_series;
981        NomTypeNc='_1-2_1';
982    end
983elseif strcmp (mode,'Dj')
984    j1_series=j_series-ind1;
985    j2_series=j_series+ind2;
986    check_bounds=j1_series<MinIndex(1,2) | j2_series>MaxIndex(1,2);
987    NomTypeNc='_1_1-2';
988else  %bursts
989    j1_series=ind1*ones(size(i_series));
990    j2_series=ind2*ones(size(i_series));
991end
992
993%     if length(indsel)>=1
994%         firstind=indsel(1);
995%         lastind=indsel(end);
996%         set(handles.first_j,'String',num2str(ref_j(firstind)))%update the display of first and last fields
997%         set(handles.last_j,'String',num2str(ref_j(lastind)))
998%         ref_j=ref_j(indsel);
999%         j1_civ1=j1_civ1(indsel);
1000%         j2_civ1=j2_civ1(indsel);
1001%         j1_civ2=j1_civ2(indsel);
1002%         j2_civ2=j2_civ2(indsel);
1003%     end
1004% elseif isequal(mode,'pair j1-j2') %case of bursts (png_old or png_2D)
1005%     displ_num=get(handles.ListPairCiv1,'UserData');
1006%     i1_civ1=ref_i;
1007%     i2_civ1=ref_i;
1008%     j1_civ1=displ_num(1,index_civ1);
1009%     j2_civ1=displ_num(2,index_civ1);
1010%     i1_civ2=ref_i;
1011%     i2_civ2=ref_i;
1012%     j1_civ2=displ_num(1,index_civ2);
1013%     j2_civ2=displ_num(2,index_civ2);
1014% elseif isequal(mode,'displacement')
1015%     i1_civ1=ref_i;
1016%     i2_civ1=ref_i;
1017%     j1_civ1=ref_j;
1018%     j2_civ1=ref_j;
1019%     i1_civ2=ref_i;
1020%     i2_civ2=ref_i;
1021%     j1_civ2=ref_j;
1022%     j2_civ2=ref_j;
1023% end
1024
1025
1026
1027
Note: See TracBrowser for help on using the repository browser.