Index: trunk/src/series.m
===================================================================
--- trunk/src/series.m	(revision 844)
+++ trunk/src/series.m	(revision 845)
@@ -1308,16 +1308,4 @@
 function RUN_Callback(hObject, eventdata, handles)
 
-%% read the data on the GUI series
-Param=read_GUI_series(handles);%displayed parameters
-SeriesData=get(handles.series,'UserData');%hidden parameters
-if ~isfield(SeriesData,'i1_series')
-    msgbox_uvmat('ERROR','The input field series needs to be refreshed: press REFRESH')
-    return
-end
-if isfield(Param,'InputFields')&& isequal(Param.InputFields.FieldName,'get_field...')
-    msgbox_uvmat('ERROR','input field name(s) not defined, select get_field...')
-    return
-end
-
 %% settings of the button RUN
 set(handles.RUN,'BusyAction','queue');% activation of STOP button will set BusyAction to 'cancel'
@@ -1326,5 +1314,35 @@
 drawnow
 set(handles.status,'Value',0)% desable status display if relevant
-status_Callback(hObject, eventdata, handles)
+status_Callback([], eventdata, handles)
+
+%% launch action
+errormsg=launch_action(handles);
+if ~isempty(errormsg)
+     msgbox_uvmat('ERROR',errormsg)
+end
+
+%% reset the GUI series
+update_waitbar(handles.Waitbar,1); % put the waitbar to end position to indicate launching is finished
+set(handles.RUN, 'Enable','On')
+set(handles.RUN,'BackgroundColor',[1 0 0])
+set(handles.RUN, 'Value',0)
+
+%------------------------------------------------------------------------
+% --- called by RUN_Callback
+%------------------------------------------------------------------------
+function errormsg=launch_action(handles)
+errormsg='';%default
+
+%% read the data on the GUI series
+Param=read_GUI_series(handles);%displayed parameters
+SeriesData=get(handles.series,'UserData');%hidden parameters
+if ~isfield(SeriesData,'i1_series')
+    errormsg='The input field series needs to be refreshed: press REFRESH';
+    return
+end
+if isfield(Param,'InputFields')&& isequal(Param.InputFields.FieldName,'get_field...')
+    errormsg='input field name(s) not defined, select get_field...';
+    return
+end
 
 %% select the Action mode, 'local', 'background' or 'cluster' (if available)
@@ -1341,5 +1359,4 @@
 ActionName=Param.Action.ActionName;
 ActionPath=Param.Action.ActionPath;
-
 path_series=fileparts(which('series'));
 
@@ -1349,5 +1366,5 @@
         eval(['spath=which(''' ActionName ''');']) %spath = current path of the selected function ACTION
         if ~exist(ActionPath,'dir')
-            msgbox_uvmat('ERROR',['The prescribed function path ' ActionPath ' does not exist']);
+            errormsg=['The prescribed function path ' ActionPath ' does not exist'];
             return
         end
@@ -1390,5 +1407,5 @@
     end
     if isempty(RunTime) && strcmp(RunMode,'cluster_oar')
-        msgbox_uvmat('ERROR','RunTime name not found in PARAM.xml, compiled version .sh cannot run on cluster')
+       errormsg='RunTime name not found in PARAM.xml, compiled version .sh cannot run on cluster';
         return
     end
@@ -1463,5 +1480,5 @@
 
 %% create the output data directory if needed
-OutpuDir='';
+OutputDir='';
 if isfield(Param,'OutputSubDir')
     SubDirOut=[get(handles.OutputSubDir,'String') Param.OutputDirExt];
@@ -1472,5 +1489,5 @@
         answer=msgbox_uvmat('INPUT_Y-N',['use existing ouput directory: ' fullfile(Param.InputTable{1,1},SubDirOutNew) ', possibly delete previous data']);
         if strcmp(answer,'Cancel')
-            errormsg='Cancel';
+            set(handles.RUN,'backgroundcolor',[1 0 0])
             return
         elseif strcmp(answer,'Yes')
@@ -1495,5 +1512,5 @@
         [tild,msg1]=mkdir(OutputDir);
         if ~strcmp(msg1,'')
-            msgbox_uvmat('ERROR',['cannot create ' OutputDir ': ' msg1]);%error message for directory creation
+            errormsg=['cannot create ' OutputDir ': ' msg1];%error message for directory creation
             return
         end
@@ -1501,5 +1518,4 @@
         if success==0
             msgbox_uvmat('WARNING',{['unable to set group write access to ' OutputDir ':']; msg1});%error message for directory creation
-            return
         end
     end
@@ -1512,5 +1528,5 @@
     [tild,msg1]=mkdir(DirXml);
     if ~strcmp(msg1,'')
-        msgbox_uvmat('ERROR',['cannot create ' DirXml ': ' msg1]);%error message for directory creation
+        errormsg=['cannot create ' DirXml ': ' msg1];%error message for directory creation
         return
     end
@@ -1540,7 +1556,5 @@
 end
 if last_i < first_i || last_j < first_j 
-    msgbox_uvmat('ERROR', 'series/Run_Callback:last field index must be larger or equal to the first one')
-    set(handles.RUN, 'Enable','On'),
-    set(handles.RUN,'BackgroundColor',[1 0 0])
+    errormsg= 'series/Run_Callback:last field index must be larger or equal to the first one';
     return
 end
@@ -1626,7 +1640,4 @@
         end
     end
-% elseif strcmp(get(handles.OutputDirExt,'Visible'),'off')
-%     msgbox_uvmat('ERROR',['no output file for Action ' ActionName ', use run mode = local']);% a output dir is needed for background option
-%     return
 else
     %% processing on a different session of the same computer (background) or cluster, create executable files
@@ -1643,5 +1654,5 @@
         [tild,msg1]=mkdir(DirBat);
         if ~strcmp(msg1,'')
-            msgbox_uvmat('ERROR',['cannot create ' DirBat ': ' msg1]);%error message for directory creation
+            errormsg=['cannot create ' DirBat ': ' msg1];%error message for directory creation
             return
         end
@@ -1652,5 +1663,5 @@
         [tild,msg1]=mkdir(DirLog);
         if ~strcmp(msg1,'')
-            msgbox_uvmat('ERROR',['cannot create ' DirLog ': ' msg1]);%error message for directory creation
+            errormsg=['cannot create ' DirLog ': ' msg1];%error message for directory creation
             return
         end
@@ -1684,5 +1695,5 @@
         [fid,message]=fopen(filebat,'w');% create the executable file
         if isequal(fid,-1)
-            msgbox_uvmat('ERROR', ['creation of .bat file: ' message]);
+            errormsg=['creation of .bat file: ' message];
             return
         end
@@ -1742,5 +1753,5 @@
         for iprocess=1:NbProcess
             system([batch_file_list{iprocess} ' &'])% directly execute the command file for each process
-            msgbox_uvmat('CONFIRMATION',[ActionName 'launched in background: press STATUS to see results'])
+            msgbox_uvmat('CONFIRMATION',[ActionName ' launched in background: press STATUS to see results'])
         end
     case 'cluster_oar' % option 'oar-parexec' used
@@ -1755,5 +1766,5 @@
             [tild,msg1]=mkdir(DirOAR);
             if ~strcmp(msg1,'')
-                msgbox_uvmat('ERROR',['cannot create ' DirOAR ': ' msg1]);%error message for directory creation
+                errormsg=['cannot create ' DirOAR ': ' msg1];%error message for directory creation
                 return
             end
@@ -1785,10 +1796,4 @@
         msgbox_uvmat('CONFIRMATION',[ActionName ' launched in cluster: press STATUS to see results'])
 end
-
-%% reset the GUI series
-update_waitbar(handles.Waitbar,1); % put the waitbar to end position to indicate launching is finished
-set(handles.RUN, 'Enable','On')
-set(handles.RUN,'BackgroundColor',[1 0 0])
-set(handles.RUN, 'Value',0)
 
 %------------------------------------------------------------------------
@@ -2192,45 +2197,46 @@
     end
     set(handles.OutputDirExt,'String',OutputDirExt)
-    OutputDirVisible='off';
-    OutputSubDirMode='auto';%default
-    SubDirOut='';
-    if isfield(ParamOut,'OutputSubDirMode')
-        OutputSubDirMode=ParamOut.OutputSubDirMode;
-    end
-    switch OutputSubDirMode
-        case 'auto';%default
-            OutputDirVisible='on';
-            SubDir=InputTable(1:end,2); %set of subdirectories
-            SubDirOut=SubDir{1};
-            if numel(SubDir)>1
-                for ilist=2:numel(SubDir)
-                    SubDirOut=[SubDirOut '-' SubDir{ilist}];
-                end
+end
+OutputDirVisible='off';
+OutputSubDirMode='auto';%default
+SubDirOut='';
+if isfield(ParamOut,'OutputSubDirMode')
+    OutputSubDirMode=ParamOut.OutputSubDirMode;
+end
+switch OutputSubDirMode
+    case 'auto';%default
+        OutputDirVisible='on';
+        SubDir=InputTable(1:end,2); %set of subdirectories
+        SubDirOut=SubDir{1};
+        if numel(SubDir)>1
+            for ilist=2:numel(SubDir)
+                SubDirOut=[SubDirOut '-' SubDir{ilist}];
             end
-        case 'first'
-            OutputDirVisible='on';
-            SubDirOut=InputTable{1,2}; %use the first subdir name (+OutputDirExt) as output  subdirectory
-        case 'last'
-            OutputDirVisible='on';
-            SubDirOut=InputTable{end,2}; %use the last subdir name (+OutputDirExt) as output  subdirectory
-    end
-    set(handles.OutputSubDir,'String',SubDirOut)
-    set(handles.OutputDirExt,'Visible',OutputDirVisible)
-    set(handles.OutputSubDir,'Visible',OutputDirVisible)
-    set(handles.OutputDir_title,'Visible',OutputDirVisible)
-    SeriesData.ActionName=ActionName;%record ActionName for next use
-    
-    
-    %% visibility of the run mode (local or background or cluster)
-    if strcmp(OutputSubDirMode,'none')
-        RunModeVisible='off';% only local mode available if no output file is produced
-    else
-        RunModeVisible='on';
-    end
-    set(handles.RunMode,'Visible',RunModeVisible)
-    set(handles.ActionExt,'Visible',RunModeVisible)
-    set(handles.RunMode_title,'Visible',RunModeVisible)
-    set(handles.ActionExt_title,'Visible',RunModeVisible)
-end
+        end
+    case 'first'
+        OutputDirVisible='on';
+        SubDirOut=InputTable{1,2}; %use the first subdir name (+OutputDirExt) as output  subdirectory
+    case 'last'
+        OutputDirVisible='on';
+        SubDirOut=InputTable{end,2}; %use the last subdir name (+OutputDirExt) as output  subdirectory
+end
+set(handles.OutputSubDir,'String',SubDirOut)
+set(handles.OutputDirExt,'Visible',OutputDirVisible)
+set(handles.OutputSubDir,'Visible',OutputDirVisible)
+set(handles.OutputDir_title,'Visible',OutputDirVisible)
+SeriesData.ActionName=ActionName;%record ActionName for next use
+
+
+%% visibility of the run mode (local or background or cluster)
+if strcmp(OutputSubDirMode,'none')
+    RunModeVisible='off';% only local mode available if no output file is produced
+else
+    RunModeVisible='on';
+end
+set(handles.RunMode,'Visible',RunModeVisible)
+set(handles.ActionExt,'Visible',RunModeVisible)
+set(handles.RunMode_title,'Visible',RunModeVisible)
+set(handles.ActionExt_title,'Visible',RunModeVisible)
+
 
 %% Expected nbre of output files
@@ -2987,4 +2993,5 @@
     if ~isfield(Param,'OutputSubDir')   
         msgbox_uvmat('ERROR','no standard sub-directory definition for output files, use a browser to check the output')
+        set(handles.status,'BackgroundColor',[0 1 0])
         return
     end
Index: trunk/src/series/stereo_civ.m
===================================================================
--- trunk/src/series/stereo_civ.m	(revision 844)
+++ trunk/src/series/stereo_civ.m	(revision 845)
@@ -39,8 +39,13 @@
 
 function [Data,errormsg,result_conv]= stereo_civ(Param)
+Data=[];
 errormsg='';
 
 %% set the input elements needed on the GUI series when the action is selected in the menu ActionName or InputTable refreshed
 if isstruct(Param) && isequal(Param.Action.RUN,0)% function activated from the GUI series but not RUN 
+    if size(Param.InputTable,1)<2
+        msgbox_uvmat('WARNING','two input file series must be entered')
+        return
+    end
     path_series=fileparts(which('series'));
     addpath(fullfile(path_series,'series'))
@@ -285,6 +290,5 @@
         end
         [A,Rangx,Rangy]=phys_ima(A,XmlData,1);
-        
-
+        [Npy,Npx]=size(A{1});
         PhysImageA=fullfile_uvmat(RootPath_A,Civ1Dir,RootFile_A,'.png','_1a',i1_series_Civ1(ifield),[],1);
         PhysImageB=fullfile_uvmat(RootPath_A,Civ1Dir,RootFile_A,'.png','_1a',i1_series_Civ1(ifield),[],2);
@@ -323,6 +327,6 @@
         
         % set the list of variables
-        Data.ListVarName={'Civ1_X','Civ1_Y','Civ1_U','Civ1_V','Civ1_F','Civ1_C'};%  cell array containing the names of the fields to record
-        Data.VarDimName={'nb_vec_1','nb_vec_1','nb_vec_1','nb_vec_1','nb_vec_1','nb_vec_1'};
+        Data.ListVarName={'Civ1_X','Civ1_Y','Civ1_U','Civ1_V','Civ1_F','Civ1_C','Xphys','Yphys','Zphys','Civ1_E'};%  cell array containing the names of the fields to record
+        Data.VarDimName={'nb_vec_1','nb_vec_1','nb_vec_1','nb_vec_1','nb_vec_1','nb_vec_1','nb_vec_1','nb_vec_1','nb_vec_1','nb_vec_1'};
         Data.VarAttribute{1}.Role='coord_x';
         Data.VarAttribute{2}.Role='coord_y';
@@ -334,16 +338,20 @@
         % calculate velocity data (y and v in indices, reverse to y component)
         [xtable ytable utable vtable ctable F result_conv errormsg] = civ (par_civ1);
-        if ~isempty(errormsg)
-            disp_uvmat('ERROR',errormsg,checkrun)
-            return
-        end
         Data.Civ1_X=reshape(xtable,[],1);
         Data.Civ1_Y=reshape(par_civ1.ImageHeight-ytable+1,[],1);
         % get z from u and v (displacements)
         Data.Civ1_U=reshape(utable,[],1);
-        Data.Civ1_V=reshape(-vtable,[],1);
-        
+        Data.Civ1_V=reshape(-vtable,[],1);      
         Data.Civ1_C=reshape(ctable,[],1);
         Data.Civ1_F=reshape(F,[],1);
+        Data.Xphys=Rangx(1)+(Rangx(2)-Rangx(1))*(Data.Civ1_X-0.5)/(Npx-1);
+        Data.Yphys=Rangy(1)+(Rangy(2)-Rangy(1))*(Data.Civ1_Y-0.5)/(Npy-1);
+        U=Data.Civ1_U*(Rangx(2)-Rangx(1))/(Npx-1);
+        V=Data.Civ1_V*(Rangy(2)-Rangy(1))/(Npy-1);
+        [Data.Zphys,Data.Civ1_E]=shift2z(Data.Xphys,Data.Yphys,U,V,XmlData);
+        if ~isempty(errormsg)
+            disp_uvmat('ERROR',errormsg,checkrun)
+            return
+        end
     end
     
@@ -1016,5 +1024,52 @@
 end
 
-
-
-
+%INPUT:
+% xmid- u/2: set of apparent phys x coordinates in the ref plane, image A
+% ymid- v/2: set of apparent phys y coordinates in the ref plane, image A
+% xmid+ u/2: set of apparent phys x coordinates in the ref plane, image B
+% ymid+ v/2: set of apparent phys y coordinates in the ref plane, image B
+% XmlData: content of the xml files containing geometric calibration parameters
+function [z,error]=shift2z(xmid, ymid, u, v,XmlData)
+z=0;
+error=0;
+
+%% first image
+Calib_A=XmlData{1}.GeometryCalib;
+R=(Calib_A.R)';
+x_a=xmid- u/2;
+y_a=ymid- v/2;
+z_a=R(7)*x_a+R(8)*y_a+R(9)*Calib_A.SliceCoord(1,3);
+X=(R(1)*x_a+R(2)*y_a+R(3)*Calib_A.SliceCoord(1,3))./z_a;
+Y=(R(4)*x_a+R(5)*y_a+R(6)*Calib_A.SliceCoord(1,3))./z_a;
+A_1_1=R(1)-R(7)*x_a;
+A_1_2=R(2)-R(8)*x_a;
+A_1_3=R(3)-R(9)*x_a;
+A_2_1=R(4)-R(7)*y_a;
+A_2_2=R(5)-R(8)*y_a;
+A_2_3=R(6)-R(9)*y_a;
+Det=A_1_1.*A_2_2-A_1_2.*A_2_1;
+Dxa=(A_1_2.*A_2_3-A_2_2.*A_1_3)./Det;
+Dya=(A_2_1.*A_1_3-A_1_1.*A_2_3)./Det;
+
+%% second image
+Calib_A=XmlData{1}.GeometryCalib;
+R=(Calib_A.R)';
+x_a=xmid+ u/2;
+y_a=ymid+ v/2;
+z_a=R(7)*x_a+R(8)*y_a+R(9)*Calib_A.SliceCoord(1,3);
+X=(R(1)*x_a+R(2)*y_a+R(3)*Calib_A.SliceCoord(1,3))./z_a;
+Y=(R(4)*x_a+R(5)*y_a+R(6)*Calib_A.SliceCoord(1,3))./z_a;
+A_1_1=R(1)-R(7)*x_a;
+A_1_2=R(2)-R(8)*x_a;
+A_1_3=R(3)-R(9)*x_a;
+A_2_1=R(4)-R(7)*y_a;
+A_2_2=R(5)-R(8)*y_a;
+A_2_3=R(6)-R(9)*y_a;
+Det=A_1_1.*A_2_2-A_1_2.*A_2_1;
+Dxb=(A_1_2.*A_2_3-A_2_2.*A_1_3)./Det;
+Dyb=(A_2_1.*A_1_3-A_1_1.*A_2_3)./Det;
+
+%% result
+Den=(Dxb-Dxa).*(Dxb-Dxa)+(Dyb-Dya).*(Dyb-Dya);
+error=((Dyb-Dya).*u-(Dxb-Dxa).*v)./Den;
+z=((Dxb-Dxa).*u-(Dyb-Dya).*v)./Den;
