diff --git a/1_preprocessing/gtPreprocessing.m b/1_preprocessing/gtPreprocessing.m
index 2b6dc5893fd4153f5b73a3fd67b02bd81a8e37fb..75b512e477e40de115ef0b9a4cd58ca8ea8b3923 100755
--- a/1_preprocessing/gtPreprocessing.m
+++ b/1_preprocessing/gtPreprocessing.m
@@ -299,6 +299,8 @@ parameters.acq.rotx=parameters.acq.rotu;
 if isfield(parameters.acq, 'no_direct_beam') && strcmpi(parameters.acq.no_direct_beam,'true')
     parameters.prep.udrift=zeros(1, totproj);
     parameters.prep.vdrift=zeros(1, totproj);
+    % hardcoded sep 27 lnervo
+    parameters.prep.udriftabs=zeros(1,totproj);
 else
     detcenter_abs=parameters.acq.xdet/2+0.5;
     bboxcenter_abs=(2*parameters.acq.bb(1)+parameters.acq.bb(3)-1)/2;
@@ -357,7 +359,6 @@ disp('Using OAR parameters:')
 OAR_parameters.walltime=sprintf('%02d:%02d:00', OARh, OARm);
 OAR_parameters.mem=2000;
 
-disp(sprintf('Number of OAR jobs: %d', OARjobs));
 disp('OAR parameters:')
 disp(OAR_parameters)
 % could adjust this calculation
diff --git a/1_preprocessing/gtSetupCalibrationQuali.m b/1_preprocessing/gtSetupCalibrationQuali.m
index e1adfd3cb05d427791af810d240eb1c12f9660bc..16d95c3823077153d58703803f3e6b0a5b196704 100755
--- a/1_preprocessing/gtSetupCalibrationQuali.m
+++ b/1_preprocessing/gtSetupCalibrationQuali.m
@@ -52,7 +52,7 @@ if strcmpi(parameters.calib.type,'180degree') || strcmpi(parameters.calib.type,'
   disp(' ')
   disp('Creating dark.edf image of calibration scan')
   parameters.calib.name=parameters.calib.dir(find(parameters.calib.dir=='/',1,'last')+1:end);
-  xmlfname_calib=sprintf('%s/%s.xml',parameters.calib.dir,parameters.calib.name);
+  xmlfname_calib=sprintf('%s/%s.xml',parameters.calib.dir,parameters.calib.name)
   if ~exist(xmlfname_calib,'file')
     error('Cannot proceed - missing xml file of calibration scan.')
   end
diff --git a/3_match_extspot/gtCalculateTwotheta.m b/3_match_extspot/gtCalculateTwotheta.m
index e639ca4fd20964c779d31d4ff449c91d1f1ba7b3..efaa9929927db44098249207c2dec0b40ad59e75 100644
--- a/3_match_extspot/gtCalculateTwotheta.m
+++ b/3_match_extspot/gtCalculateTwotheta.m
@@ -48,7 +48,8 @@ energy=acq.energy;
 lambda=gtConvEnergyToWavelength(energy);%mod LNervo
 latticepar=acq.latticepar;
 
-if isfield(acq,'detanglemin') && isfield(acq,'detanglemax')
+if (isfield(acq,'detanglemin') && isfield(acq,'detanglemax')) && ...
+        (~isempty(acq.detanglemin) && ~isempty(acq.detanglemax))
 	minangle=acq.detanglemin;
 	maxangle=acq.detanglemax;
 else
@@ -279,8 +280,7 @@ if nargout==2
         results.reflections=hkl;  %from file
         results.tt=tt;  %from file
         results.d0=d0;  %from file
-        results.twoth=twoth';
-        results.dsp=dsp';
+        
    
 end
 
diff --git a/zUtil_OAR/OAR_make.m b/zUtil_OAR/OAR_make.m
index 561cd63d29c2dca114c081410b515fc6013fca95..6f41bf0725c6224b93bc7fe861340f8d4bd39229 100644
--- a/zUtil_OAR/OAR_make.m
+++ b/zUtil_OAR/OAR_make.m
@@ -21,25 +21,27 @@ function OAR_make(executable,first,last,njobs,otherparameters,submitflag,varargi
 
 %
 %     Version 008 22-09-2011 by LNervo
-%         Adjust part of oardirectives (=varargin)
+%         Adjust part of oardirectives (=varargin). Passed by pairs
 %
-%         Available directives:
+%         Available directives (default values are shown)
+%
+%             NAME                 VALUE         OAR SYNTAX
 %             interactive          false         -I / --interactive
-%             queue='default';% -q <queue> / --queue=<queue>
-%             name=executable;% -n <text> / --name=<text>
-%             notify='';%  --notify "mail:name\@domain.com"
-%             resubmit=-1;% --resumbit=<jobid>
-%             xml=false;% -X / --xml
-%             stdout='';% -O <outfile> / --stdout=<outfile>
-%             stderr='';% -E <errfile> / --stderr=<errfile>
-%             version=false;% -V / --version
-%             node=1;
-%             cpu=1;
-%             core=1;
-%             gpu='NO';% -p "gpu='NO'"
-%             host='';% -p "host like '<name>%'"
-%             mem=2000;
-%             walltime='2:00:00';
+%             queue                'default'     -q <queue> / --queue=<queue>
+%             name                 executable    -n <text> / --name=<text>
+%             notify               ''            --notify "mail:name\@domain.com"
+%             resubmit             -1            --resumbit=<jobid>
+%             xml                  false         -X / --xml
+%             stdout               ''            -O <outfile> / --stdout=<outfile>
+%             stderr               ''            -E <errfile> / --stderr=<errfile>
+%             version              false         -V / --version
+%             node                 1             -l /node=<nnode>
+%             cpu                  1             -l /cpu=<ncpu>
+%             core                 1             -l /core=<ncore>
+%             gpu                  'NO'          -p gpu = '<gpuvalue>'
+%             host                 ''            -p host like '<name>%'
+%             mem                  2000          -p mem > <memory>
+%             walltime             '2:00:00'     -l walltime=<walltime>
 % 
 %     Version 007 29-04-2011 by LNervo:
 %         Change name of structure parameters into oarparameters
@@ -51,6 +53,8 @@ function OAR_make(executable,first,last,njobs,otherparameters,submitflag,varargi
 % clean the screen each time
 clc
 debug=false; 
+
+% default OAR directives
 app.interactive=false;% -I / --interactive
 app.queue='default';% -q <queue> / --queue=<queue>
 app.name=executable;% -n <text> / --name=<text>
@@ -69,6 +73,7 @@ app.mem=2000;
 app.walltime='2:00:00';
 app=parse_pv_pairs(app,varargin);
 
+
 oarpars=app;
 
 %%%%%%%%%%%%%%
@@ -357,7 +362,7 @@ if strcmpi(matlab,'false')
     cmd=sprintf('more %s | grep -m 2 %s ',mpath,fname);
     [s,help]=system(cmd);
     if isempty(help)
-        help=sprintf('# This file has been generated by using MATLAB function OAR_make_v6,\nrunning the module ''%s''\n',executable);
+        help=sprintf('# This file has been generated by using MATLAB function OAR_make_v7,\nrunning the module ''%s''\n',executable);
     else
         fprintf(fid,'# %s',help);
     end
diff --git a/zUtil_Optimization/addMatFile.m b/zUtil_Optimization/addMatFile.m
new file mode 100644
index 0000000000000000000000000000000000000000..1e35ce1f11af3a3546b08087e021f14a5094bb8d
--- /dev/null
+++ b/zUtil_Optimization/addMatFile.m
@@ -0,0 +1,32 @@
+function updateVar=addMatFile(mat1,var,update)
+% updateVar=addMatFile(mat1,var,update)
+
+if ~exist('update','var') || isempty(update)
+    update=false;
+end
+
+names=fieldnames(var);
+
+for i=1:length(names)
+    if ~isfield(mat1,char(names(i))) 
+        mat1.(char(names(i)))=var.(char(names(i)));
+    else
+        if ~update
+            variable=char(names(i))
+            oldvalue=mat1.(char(names(i)))
+            newvalue=var.(char(names(i)))
+
+            check=inputwdefault('Do you want to replace it with the new value?','n')
+            if strcmpi(check,'y')
+                mat1.(char(names(i)))=var.(char(names(i)));
+            end
+
+        else
+            mat1.(char(names(i)))=var.(char(names(i)));  
+        end
+    end
+end
+
+updateVar=mat1;
+end
+    
\ No newline at end of file
diff --git a/zUtil_Optimization/calculateUVWfromGeo.m b/zUtil_Optimization/calculateUVWfromGeo.m
new file mode 100644
index 0000000000000000000000000000000000000000..7339e77c64b3e6bce0e9a64678e73dfe24b2e076
--- /dev/null
+++ b/zUtil_Optimization/calculateUVWfromGeo.m
@@ -0,0 +1,41 @@
+%% Compute uv coordinates and w(omega) values from grain given an arbitrary
+%% geometry
+function fed=calculateUVWfromGeo(geometry,grain)
+
+detdiru = geometry.detdiru0';
+detdirv = geometry.detdirv0';
+Qdet = gtFedDetectorProjectionTensor(detdiru,detdirv,1,1);
+tn = cross(detdiru,detdirv);
+detpos = geometry.detpos0';
+uvorig = [geometry.detucen0, geometry.detvcen0]';
+omstep=180/geometry.nproj;
+
+csam=grain.center';
+
+% grain.allblobs.[variable]
+srot=grain.srot;
+dvec=grain.dvec;
+omega=grain.omega;
+
+fed.uv  = [];
+fed.uvw = [];
+
+n=size(omega,1)/4;
+for j=1:n % must be from 0 to n-1
+    
+    % from grainFed=gtFedGenerateRandomGRain2(grain{grainid},full)
+    S=srot(12*j-11:12*j,:);
+    D=dvec(4*j-3:4*j,:);
+    O=omega(4*j-3:4*j); % omega values ordered like small, small+180, big, big+180 for the 4
+        
+    uv1a=gtFedPredictUVW(S(1:3,:),D(1,:)',csam,detpos,tn,Qdet,uvorig,O(1),omstep);
+    uv1b=gtFedPredictUVW(S(4:6,:),D(2,:)',csam,detpos,tn,Qdet,uvorig,O(2),omstep);
+    uv2a=gtFedPredictUVW(S(7:9,:),D(3,:)',csam,detpos,tn,Qdet,uvorig,O(3),omstep);
+    uv2b=gtFedPredictUVW(S(10:12,:),D(4,:)',csam,detpos,tn,Qdet,uvorig,O(4),omstep);
+    
+    fed.uv     =  [fed.uv;uv1a(1),uv1a(2);uv1b(1),uv1b(2);uv2a(1),uv2a(2);uv2b(1),uv2b(2)];
+    fed.uvw    =  [fed.uvw;uv1a(1),uv1a(2),uv1a(3);uv1b(1),uv1b(2),uv1b(3);uv2a(1),uv2a(2),uv2a(3);uv2b(1),uv2b(2),uv2b(3)];
+
+end % size /4
+
+end % end function
\ No newline at end of file
diff --git a/zUtil_Optimization/checkSpot.m b/zUtil_Optimization/checkSpot.m
new file mode 100644
index 0000000000000000000000000000000000000000..cb0997655d2edcb82549420f559f69547ca64210
--- /dev/null
+++ b/zUtil_Optimization/checkSpot.m
@@ -0,0 +1,11 @@
+function checkSpot(parameters,bbox)
+
+for i=1:length(bbox.expected_id)
+    vol=gtDBBrowseDiffractionVolume(parameters.acq.name,bbox.expected_id(i));
+    figure;imshow(sum(vol,3),[0 2000])
+    bbox.all(i,:)
+    title(sprintf('#%d id %d x,y [%f %f]',i,bbox.expected_id(i),bbox.xcen(i),bbox.ycen(i)))
+    waitforbuttonpress
+end
+
+end
\ No newline at end of file
diff --git a/zUtil_Optimization/findSpot.m b/zUtil_Optimization/findSpot.m
new file mode 100644
index 0000000000000000000000000000000000000000..59bd33ee64feb3ab35ebed656277790615f98fc9
--- /dev/null
+++ b/zUtil_Optimization/findSpot.m
@@ -0,0 +1,29 @@
+function [spot,range,box,omegamean]=findSpot(parameters,imagemin,imagemax,ymin,ymax,xmin,xmax,number)
+
+dir=parameters.acq.dir;
+cd(sprintf('%s/1_preprocessing/full',dir));
+
+sum=zeros(parameters.acq.xdet);
+for i=imagemin:imagemax
+   im=edf_read(sprintf('full%04d.edf',i));
+   sum=sum+im;
+end
+
+spot=sum(ymin:ymax,xmin:xmax);
+box=[ymin ymax xmin xmax];
+range=[imagemin imagemax];
+
+cd(dir);
+name=sprintf('spot%d.edf',number);
+if exist(name,'file')
+    fprintf('The file %s already exist. ',name)
+    check=inputwdefault('Overwrite it?','y');
+    if strcmpi(check,'y')
+        edf_write(spot,name);
+    end
+else
+    edf_write(spot,name);
+end
+omegamean=mean([imagemin imagemax])*180/parameters.acq.nproj;
+
+end
\ No newline at end of file
diff --git a/zUtil_Optimization/findSpotsWoIndexter.m b/zUtil_Optimization/findSpotsWoIndexter.m
new file mode 100644
index 0000000000000000000000000000000000000000..56ba27943abbb8cb728a8675c232a464e8fb2dde
--- /dev/null
+++ b/zUtil_Optimization/findSpotsWoIndexter.m
@@ -0,0 +1,106 @@
+function bbox=findSpotsWoIndexter(parameters,uvfed,omegafed,bbsizemean,areamin,areamax)
+% bbox=findSpotsWoIndexter(parameters,uvfed,omegafed,bbsizemean,areamin,areamax)
+
+if nargin < 6
+    disp('Usage: bbox=findSpotsWoIndexter(parameters,uvfed,omegafed,bbsizemean,areamin,areamax)')
+    return
+end
+
+if isfield(parameters,'acq')
+    name=parameters.acq.name;
+    omstep=180/parameters.acq.nproj;
+else
+    name=parameters.name;
+    omstep=180/parameters.nproj;
+end
+bbsize=bbsizemean; % pixels
+
+expected_id=[];
+image=[];
+omega=[];
+x0=[];
+y0=[];
+xsize=[];
+ysize=[];
+xcen=[];
+ycen=[];
+feduv=[];
+area=[];
+ind=[];
+dbuv=[];
+
+dif_Xsize=bbsize;
+dif_Ysize=bbsize;
+deltaImage=10;
+
+
+gtDBConnect
+
+for i=1:length(uvfed)
+    
+    myquery=sprintf(['select difspotID from %sdifspot where '...
+        '(%d between CentroidImage-%d and CentroidImage+%d) '...
+        'and (abs(%sdifspot.CentroidX-%f)/%d)<0.5 '...
+        'and (abs(%sdifspot.CentroidY-%f)/%d)<0.5 '...   
+        'and (Area between %d and %d) '...
+        'order by ((abs(BoundingBoxXsize-%d)/%d)+(abs(BoundingBoxYsize-%d)/%d)) limit 1'],...
+        name,...
+        round(omegafed(i)/omstep),deltaImage,deltaImage,...
+        name, uvfed(i,1), dif_Xsize,...
+        name, uvfed(i,2), dif_Ysize,...
+        areamin,areamax,...
+        dif_Xsize, dif_Xsize, dif_Ysize, dif_Ysize);
+    
+        [difspotID] = mym(myquery);
+    
+    if ~isempty(difspotID)
+        expected_id=[expected_id; difspotID];
+        secquery=sprintf('select BoundingBoxXOrigin, BoundingBoxYOrigin, BoundingBoxXSize, BoundingBoxYSize, CentroidX, CentroidY, CentroidImage, Area from %sdifspot where difspotID=%d',...
+            name, difspotID);
+        
+        [BoundingBoxXorigin, BoundingBoxYorigin, BoundingBoxXsize, BoundingBoxYsize, CentroidX, CentroidY, CentroidImage, Area]=mym(secquery);
+        
+        % disp(sprintf('CentroidImage between CentroidImage-10 and CentroidImage+10 = %d',CentroidImage))
+        % disp(sprintf('abs(CentroidX-uvfed(i,1))/dif_Xsize = %f',abs(CentroidX-uvfed(i,1))/dif_Xsize))
+        % disp(sprintf('abs(CentroidY-uvfed(i,2))/dif_Ysize = %f',abs(CentroidY-uvfed(i,2))/dif_Ysize))
+        % disp(sprintf('Area between %d and %d = %d',areamin,areamax,Area))
+        
+        
+        
+        image=[image; CentroidImage];
+        omega=[omega; CentroidImage*omstep];
+        x0=[x0; BoundingBoxXorigin];
+        y0=[y0; BoundingBoxYorigin];
+        xsize=[xsize; BoundingBoxXsize];
+        ysize=[ysize; BoundingBoxYsize];
+        xcen=[xcen; CentroidX];
+        ycen=[ycen; CentroidY];
+        uvdb=[CentroidX CentroidY];
+        dbuv=[dbuv;uvdb];
+        area=[area; Area];
+        ind=[ind;i];
+        feduv=[feduv;uvfed(i,:)];
+    end
+%     
+end
+
+bbox.expected_id=expected_id;
+bbox.x0=x0;
+bbox.y0=y0;
+bbox.xsize=xsize;
+bbox.ysize=ysize;
+bbox.xcen=xcen;
+bbox.ycen=ycen;
+bbox.image=image;
+bbox.omega=omega;
+bbox.area=area;
+bbox.dbuv=dbuv;
+bbox.all=[expected_id x0 y0 xcen ycen xsize ysize omega];
+bbox.title='expected_id x0 y0 xcen ycen xsize ysize omega';
+bbox.query={'CentroidImage',[-deltaImage deltaImage],'Area',[areamin areamax],...
+    'CentroidX-u', [dif_Xsize 0.5],...
+    'CentroidY-v', [dif_Ysize 0.5]};
+bbox.ind=ind;
+bbox.feduv=feduv;
+
+end
\ No newline at end of file
diff --git a/zUtil_Optimization/gtCalculateDist.m b/zUtil_Optimization/gtCalculateDist.m
new file mode 100644
index 0000000000000000000000000000000000000000..e1663c20ea2d9d5081657df371e95b0cf471c734
--- /dev/null
+++ b/zUtil_Optimization/gtCalculateDist.m
@@ -0,0 +1,87 @@
+function [dsp,crystal_system,tt]=gtCalculateDist(hkl,parameters)
+% [dsp,crystal_system]=gtCalculateDist(hkl,parameters)
+%      hkl <double 1x3>
+
+if nargin < 2
+   disp('Usage: [dsp,crystal]=gtCalculateDist(hkl,parameters)')
+   return
+end
+
+latticepar=parameters.acq.latticepar;
+spacegroup=parameters.acq.spacegroup;
+
+a=latticepar(1);b=latticepar(2);c=latticepar(3);
+alpha=latticepar(4);beta=latticepar(5);gamma=latticepar(6);
+
+if size(hkl,2)==4 %hexagonal materials
+    h=hkl(1);k=hkl(2);l=hkl(4);
+else
+    h=hkl(1);k=hkl(2);l=hkl(3);
+end
+        
+if ~isfield(parameters.acq,'hermann_mauguin')
+   hermann=readSpaceGroup(spacegroup); 
+end
+
+% calculate twotheta (twoth) for different spacegroups
+if between(spacegroup,1,2)
+    crystal='triclinic';
+    Y=h^2/a^2*(sind(alpha))^2 + k^2/b^2*(sind(beta))^2 + l^2/c^2*(sind(gamma))^2;
+    Z=2*k*l/b/c*(cosd(beta)*cosd(gamma)-cosd(alpha)) + ...
+             2*l*h/c/a*(cosd(gamma)*cosd(alpha)-cosd(beta)) + ...
+             2*h*k/a/b*(cosd(alpha)*cosd(beta)-cosd(gamma));
+    invdsp2=1/(1-(cosd(alpha))^2-(cosd(beta))^2-(cosd(gamma))^2+2*cosd(alpha)*cosd(beta)*cosd(gamma)) * ( Y + Z );
+end
+if between(spacegroup,3,15)
+    crystal='monoclinic';
+    invdsp2=h^2/(a*sind(beta))^2 + k^2/b^2 + l^2/(c*sind(beta))^2 - (2*h*l*cosd(beta)) / (a*c*(sind(beta))^2);
+end
+if between(spacegroup,16,74)
+    crystal='orthorhombic';
+    invdsp2=h^2/a^2+k^2/b^2+l^2/c^2;
+end
+if between(spacegroup,75,142)
+    crystal='tetragonal';
+    invdsp2=(h^2+k^2)/a^2+l^2/c^2;
+end
+if between(spacegroup,143,167)
+    crystal='trigonal';
+    if ~isempty(strfind(hermann,'P')) % hexagonal system
+        invdsp2=4/(3*a^2) * (h^2 + k^2 + h*k) + l^2/c^2;
+    elseif ~isempty(strfind(hermann,'R')) % rhombohedral system
+        Y1=h^2+k^2+h*k;
+        Y2=2*(h*k+h*l+k*l);
+        Z1=(sind(alpha))^2;
+        Z2=(cosd(alpha))^2-cosd(alpha);
+        W=1+2*(cosd(alpha))^3-3*(cosd(alpha))^2;
+        invdsp2=1/a^2*(Y1*Z1+Y2*Z2)/W;
+    end
+end
+if between(spacegroup,168,194) || spacegroup==663 % snow case
+    crystal='hexagonal';
+    invdsp2=4/(3*a^2) * (h^2 + k^2 + h*k) + l^2/c^2;
+end
+if between(spacegroup,195,230)
+    crystal='cubic';
+    invdsp2=(h^2+k^2+l^2)/a^2;
+end
+dsp=1/(invdsp2)^0.5;
+lambda=gtConvEnergyToWavelength(parameters.acq.energy);
+twoth=2*asind(lambda/(2*dsp));
+
+if nargout == 2
+    crystal_system=crystal;
+end
+
+if nargout == 3
+    crystal_system=crystal;
+    tt=twoth;
+end
+
+if ~isfield(parameters.acq,'crystal_system')
+   parameters.acq.crystal_system=crystal;
+   save parameters parameters
+end
+
+
+end
\ No newline at end of file
diff --git a/zUtil_Optimization/gtCalculateUVWfromGeo.m b/zUtil_Optimization/gtCalculateUVWfromGeo.m
new file mode 100644
index 0000000000000000000000000000000000000000..7063046746e9071e6fed716e66ae25573c9e354b
--- /dev/null
+++ b/zUtil_Optimization/gtCalculateUVWfromGeo.m
@@ -0,0 +1,38 @@
+%% Compute uv coordinates and w(omega) values from grain given an arbitrary
+%% geometry
+function out=gtCalculateUVWfromGeo(geometry,grainFed)
+
+detdiru = geometry.detdiru0';
+detdirv = geometry.detdirv0';
+Qdet = gtFedDetectorProjectionTensor(detdiru,detdirv,1,1);
+tn = cross(detdiru,detdirv);
+detpos = geometry.detpos0';
+uvorig = [geometry.detucen0, geometry.detvcen0]';
+omstep=180/geometry.nproj;
+
+csam=grainFed.center';
+
+fed.uv = [];
+fed.uvw = [];
+
+n=size(grainFed.allblobs.omega,1)/4;
+for j=1:n % must be from 0 to n-1
+    
+    % from grainFed=gtFedGenerateRandomGRain2(grain{grainid},full)
+    S=grainFed.allblobs.srot(12*j-11:12*j,:);
+    D=grainFed.allblobs.dvec(4*j-3:4*j,:);
+    O=grainFed.allblobs.omega(4*j-3:4*j); % omega values ordered like small, small+180, big, big+180 for the 4
+        
+    uv1a=gtFedPredictUVW(S(1:3,:),D(1,:)',csam,detpos,tn,Qdet,uvorig,O(1),omstep);
+    uv1b=gtFedPredictUVW(S(4:6,:),D(2,:)',csam,detpos,tn,Qdet,uvorig,O(2),omstep);
+    uv2a=gtFedPredictUVW(S(7:9,:),D(3,:)',csam,detpos,tn,Qdet,uvorig,O(3),omstep);
+    uv2b=gtFedPredictUVW(S(10:12,:),D(4,:)',csam,detpos,tn,Qdet,uvorig,O(4),omstep);
+    
+    fed.uv    =  [fed.uv;uv1a(1),uv1a(2);uv1b(1),uv1b(2);uv2a(1),uv2a(2);uv2b(1),uv2b(2)];
+    fed.uvw    =  [fed.uvw;uv1a(1),uv1a(2),uv1a(3);uv1b(1),uv1b(2),uv1b(3);uv2a(1),uv2a(2),uv2a(3);uv2b(1),uv2b(2),uv2b(3)];
+
+end % size /4
+
+out=fed;
+
+end % end function
\ No newline at end of file
diff --git a/zUtil_Optimization/gtCheckParameters.m b/zUtil_Optimization/gtCheckParameters.m
new file mode 100644
index 0000000000000000000000000000000000000000..8fb0ce4f66443c4fe7697077aaf748e3ab05e1a7
--- /dev/null
+++ b/zUtil_Optimization/gtCheckParameters.m
@@ -0,0 +1,185 @@
+function gtCheckParameters(parameters)
+
+field{1,1}='detpos0';         field{1,2}='Detector position';
+field{2,1}='detdiru0';        field{2,2}='Detector u-direction';
+field{3,1}='detdirv0';        field{3,2}='Detector v-direction';
+field{4,1}='beamdir0';        field{4,2}='Beam direction';
+field{5,1}='rotdir0';         field{5,2}='Rotation axis direction';
+field{6,1}='detucen0';        field{6,2}='Detector u-centre';
+field{7,1}='detvcen0';        field{7,2}='Detector v-centre';
+field{8,1}='detdir0';         field{8,2}='Detector direction';
+field{9,1}='hermann_mauguin'; field{9,2}='Hermann Mauguin short symbol';
+field{10,1}='xop';            field{10,2}='Output from xop/Diamond';
+field{11,1}='crystal_system'; field{11,2}='crystal system';
+field{12,1}='detanglemin';    field{12,2}='Detector minimum 2Theta';
+field{13,1}='detanglemax';    field{13,2}='Detector maximum 2Theta';    
+field{14,1}='no_direct_beam'; field{14,2}='No beam into the detector';    
+field{15,1}='rotation_axis';  field{15,2}='rotation axis';    
+field{16,1}='dist';           field{16,2}='distance sample-detector'; 
+field{16,1}='name';           field{16,2}='name of the dataset'; 
+
+if ~exist('paraemters','var')
+   load('parameters.mat');
+end
+
+names=fieldnames(parameters.acq);
+
+for i=1:length(names)
+    list{i,1}=names{i};
+end
+
+if all(isfield(parameters.acq,field(:,1)))
+    % check if values are correct
+    
+    correct=true;
+    %%% detpos %%%
+    if norm(parameters.acq.detpos0)~=parameters.acq.dist
+        disp('The norm of detpos0 and dist are different. They may be corrupted.')    
+        correct=false;
+    end
+    
+    %%% vertical detector %%%
+    if strcmpi(parameters.acq.no_direct_beam,'f') || ...
+            strcmpi(parameters.acq.no_direct_beam,'false') || ...
+            strcmpi(parameters.acq.no_direct_beam,'no')
+        parameters.acq.no_direct_beam=false;
+        save parameters parameters
+    end
+    if strcmpi(parameters.acq.no_direct_beam,'t') || ...
+            strcmpi(parameters.acq.no_direct_beam,'true') || ...
+            strcmpi(parameters.acq.no_direct_beam,'yes')
+        parameters.acq.no_direct_beam=true;
+        save parameters parameters
+    end
+    if parameters.acq.no_direct_beam || strcmpi(parameters.acq.rotation_axis,'horizontal')
+        if strcmpi(parameters.acq.rotation_axis,'vertical')
+            disp('The rotation axis should not be vertical in this case.')
+            correct=false;
+        end
+        if parameters.acq.rotdir0(3)~=0
+           disp('The rotation axis should be the horizontal plane. Check the third component.') 
+           correct=false;
+        end
+        if (parameters.acq.no_direct_beam && strcmpi(parameters.acq.rotation_axis,'vertical')) || ...
+                (~parameters.acq.no_direct_beam && strcmpi(parameters.acq.rotation_axis,'horizontal'))
+           disp('Check the rotation axis and the direct beam, which may be corrupted.') 
+           correct=false;
+        end
+        
+    end
+    
+    %%% beam %%%
+    if parameters.acq.beamdir0~=[1 0 0]
+        disp('The beam direction may be corrupted.') 
+        parameters.acq.beamdir0=[1 0 0];
+        save parameters parameters
+        disp('beam direction corrected')
+    end
+        
+    %%% detdir0 %%%
+    if parameters.acq.detdir0~=cross(parameters.acq.detdiru0,parameters.acq.detdirv0)
+        disp('The detector direction may be corrupted. Check the u,v directions too.') 
+        parameters.acq.detdir0=cross(parameters.acq.detdiru0,parameters.acq.detdirv0);
+        disp('detector direction corrected.')
+    end
+    
+    %%% angles %%%
+    [min,max]=gtLimitsTwoTheta(0,1)
+    if parameters.acq.detanglemin~=min
+        disp('detanglemin may be corrupted.')
+        [min,max]=gtLimitsTwoTheta(1,1);
+        min
+        disp('detanglemin corrected.')
+    end
+    if parameters.acq.detanglemax~=max
+        disp('detanglemax may be corrupted.')
+        [min,max]=gtLimitsTwoTheta(1,1);
+        max
+        disp('detanglemax corrected.')
+    end
+    
+    %%% latticepar %%%
+    if strcmpi(parameters.acq.crystal_system,'cubic')
+        lat=parameters.acq.latticepar; 
+        if ~isequal(lat(1),lat(2),lat(3)) || ~isequal(lat(4),lat(5),lat(6))
+            disp('Lattice parameters must be [a a a alpha alpha alpha]')
+            correct=false;
+        end
+    end
+    if strcmpi(parameters.acq.crystal_system,'hexagonal')
+        lat=parameters.acq.latticepar; 
+        if ~isequal(lat(1),lat(2)) || ~isequal(lat(4),lat(5))
+            disp('Lattice parameters must be [a a c alpha alpha gamma]')
+            correct=false;
+        end
+    end
+    
+    %%% name %%%
+    count=0;
+    for i=1:length(names)
+        if ischar(parameters.acq.(char(names(i))))
+            ind=strfind(char(parameters.acq.(char(names(i)))),parameters.acq.name);
+            if ~isempty(ind)
+                count=count+1;
+            end
+        end
+    end
+    if count~=6
+       disp('The name of one or more directory or table is corrupted.') 
+       correct=false;
+    end
+    
+    if ~correct
+        disp('Check the values of the parameters...')
+        parameters.acq=gtModifyStructure(parameters.acq, list,'Display parameters.acq:');
+        save parameters parameters
+        %gtCheckParameters
+    else
+        disp('Parameters are corrected.') 
+    end
+    
+else
+    f=isfield(parameters.acq,field(:,1));
+    field(:,2)=num2cell(f);
+    for i=1:length(field)
+        if isfield(parameters.acq,char(field(i,1)))
+            name=parameters.acq.(char(field(i,1)));
+            if isvector(name)
+                field(i,3)={name};
+            elseif isfloat(name)
+                field(i,3)=num2cell(name);
+            else
+                field(i,3)=cellstr(name);
+            end
+        else
+            field{i,3}='';
+            fprintf('The variable %s is missing...\n',char(field(i,1)))
+            missing.(char(field(i,1)))='';
+        end
+    end
+    disp(field)
+    disp(' ')
+    disp(missing)
+    
+    newnames=fieldnames(missing);
+    
+    for l=1:length(newnames)
+        parameters.acq.(char(newnames(l)))='';
+        newlist{l,1}=newnames{l};
+        for k=1:size(field,2) 
+            if strcmpi(newnames{l},field{k,2})
+                newlist{l,2}=field{k,2};
+            else
+                newlist{l,2}='';
+            end
+        end
+    end
+
+    disp('Add the values of the missing parameters...')
+    parameters.acq = gtModifyStructure(parameters.acq, newlist,'Missing parameters.acq:');
+    save parameters parameters
+    %gtCheckParameters
+    
+end
+
+end
\ No newline at end of file
diff --git a/zUtil_Optimization/gtFindUVW3.m b/zUtil_Optimization/gtFindUVW3.m
new file mode 100644
index 0000000000000000000000000000000000000000..71988b7bfa979233e6ba46120714cb2288e0c328
--- /dev/null
+++ b/zUtil_Optimization/gtFindUVW3.m
@@ -0,0 +1,85 @@
+function [F,M,x] = gtFindUVW3(x,xdata,csam,uvorig)
+% detdiru (3x1)
+% detdirv (3x1)
+% detpos (3x1)
+% uvorig (2x1)
+% x (1x9)
+%
+% xdata (Nx4,3)
+% srot (Nx3,3)
+% dvec (N,3)
+
+if size(x,1) ~= 1 && size(x,2) ~= 9
+    disp('Please check the size of x')
+    return
+end
+
+%detdiru=[x(1);sqrt(1-x(1)^2-x(2)^2);x(2)];
+%detdirv=[x(3);x(4);sqrt(1-x(3)^2-x(4)^2)];
+%detpos=[x(5);x(6);x(7)];
+
+detpos=[x(7);x(8);x(9)];
+
+% Gram - Schmidt process for orthonormalization
+
+x1=[x(1);x(2);x(3)];
+x2=[x(4);x(5);x(6)];
+x3=cross(x1,x2);
+norm12=dot(x1,x2); % alpha
+norm23=dot(x2,x3); % beta
+norm13=dot(x1,x3); % gamma
+
+%disp('Gram-Schmidt process')
+y=orthonormGS(x1,x2,x3);
+x(1:6)=[y(1,:),y(2,:)];
+% new detector reference system
+M=y;
+
+
+detdiru=y(1,:)';
+normu=norm(detdiru);
+detdirv=y(2,:)';
+normv=norm(detdirv);
+tn=y(3,:)';
+normt=norm(tn);
+
+% normalize
+detdiru=detdiru/norm(detdiru);
+detdirv=detdirv/norm(detdirv);
+
+% split the xdata into two matrices
+n3=size(xdata,1)/4*3;
+srot=xdata(1:n3,:);
+dvec=xdata(n3+1:end,:);
+
+detscaleu=1;
+detscalev=1;
+
+%    Q - projection matrix from LAB to DETECTOR coordinates %2x3
+Qdet = [ detdiru'*detscaleu; detdirv'*detscalev];
+
+F=[];
+n=size(dvec,1);
+for j=1:n
+    % rotation tensor
+    S = srot(3*j-2:3*j,:); %3x3
+    % diffraction vector
+    D = dvec(j,:)'; %3x1 unit vector
+    
+    %grain coord. in LAB system
+    clab = S*csam; %3x1
+    % diffraction factor
+    dfac = tn'*(detpos-clab)/(tn'*D); %1x1 
+    
+    % diffraction vector in the u,v plane from uvorig
+    duvpl = clab + dfac*D - detpos; %3x1 
+    
+    uv = uvorig + Qdet*duvpl; %2x1
+    
+    F = [F; uv(1),uv(2)]; % Nx2
+   
+end
+
+
+
+end % end function
\ No newline at end of file
diff --git a/zUtil_Optimization/gtForwardSimulate2_ln.m b/zUtil_Optimization/gtForwardSimulate2_ln.m
new file mode 100644
index 0000000000000000000000000000000000000000..8782fc02a4f304dfea4ad0e6fc4cf87517207117
--- /dev/null
+++ b/zUtil_Optimization/gtForwardSimulate2_ln.m
@@ -0,0 +1,830 @@
+function [grain,o] = gtForwardSimulate2_ln(grain,parameters,varargin)
+%% GTFORWARDSIMULATE2_LN Forward simulation
+% [grain,o] = gtForwardSimulate2_ln(grain,parameters,varargin)
+%
+% should be integrated into gtINDEXTER later
+%
+% - searches database for missing reflections ...
+% - identify new pairs
+% - calculate theta,eta,omega,hkl,pn, et... for each of the new spot
+% - update grain structure
+% - update spotpair table
+% - update difspot table
+%
+% WL 04/2009:  overworked previous version gtForwardSimulate_360
+%
+% INPUT: 
+%   grain{grainid}
+%   parameters
+%
+%
+% OPTIONAL INPUT: 
+%   update_db (<logical 1x1> {0})
+%   show_results (<logical 1x1> {0})
+%   connectdb (<logical 1x1> {1})
+%   
+%
+% OUTPUT:
+%   grain{grainid} updated with additional fields:
+%     - newdifspots      difspotID of added spots
+%     - newpairs         pairID of added pairs
+%     - completeness     ratio of theoretically expected over actually found reflections
+%     - missing_refl     contains information concerning those reflections
+%                        which could not be found in the database
+%
+%   o (output) has fields:
+%     - image     : image number
+%     - omega     : omega value in degrees
+%     - udirect   : u (horiz.) coordinate of extspot
+%     - vdirect   : v (vertical) coordinate of extspot
+%     - udiffr    : u (horiz.) coordinate of difspot
+%     - vdiffr    : v (vertical) coordinate of difspot
+%     - omega     : omega in degrees
+%     - eta       : eta in degrees
+%     - theta     : theta in degrees
+%     - h,k,l     : (signed) hkl indices of the reflection
+%     - flag      : NaN: reflection geometrically not accessible
+%                   -1: no spot matching the search criteria has been found, although expected (overlaps, segmentation problem, etc...)
+%                    0: spot position outside sensitive area of the detector
+%                    1: new spot to be included in calculation of completeness
+%                    2: spot pair which has already been assigned to the grain by gtINDEXTER
+%                    4: spotpair which has been matched, but not assigned to the grain during Indexing
+%                    5: problem
+%     - difspotID : difspotID...
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+if nargin < 2
+    disp('Usage:   [grain,o] = gtForwardSimulate2_ln(grain,parameters,varargin)')
+    grain=[];
+    o=[];
+    return
+end
+app.connectdb=1;
+app.update_db=0;
+app.show_results=0;
+app=parse_pv_pairs(app,varargin);
+
+
+
+% new fields
+grain.missing_refl=[];    % will be used to keep track of reflections which could not be found in the database (e.g. segmentation problem, weak intensity, overlaps...)
+grain.newdifspots=[];     % difspotID of spots which have been added to the grain
+grain.nof_newpairs=[];    % pairID of pairs identified in newdifspots
+grain.completeness=[];    % ratio of found over expected reflections
+
+% connect to the database
+if app.connectdb
+    gtDBConnect 
+end
+
+
+%% read parameters
+
+acq=parameters.acq;
+name=acq.name;
+spacegroup=acq.spacegroup;
+difspottable=[name,'difspot'];
+db=parameters.database;
+latticepar=acq.latticepar;
+
+%get the mean difspot, X and Y sizes for the current spots in the grain
+dif_Xsize=grain.stat.bbxsmean;
+dif_Xsize_ratio=grain.stat.bbxsrat*1.3;
+dif_Ysize=grain.stat.bbysmean;
+dif_Ysize_ratio=grain.stat.bbysrat*1.3;
+
+dif_Xsearch=2*grain.stat.bbxsstd;
+dif_Ysearch=4*grain.stat.bbysstd;
+
+
+% Deal with the problem that old versions of gtMatchDifspots did not add fields
+% etaB and omegaB to the spotpair_table
+[a,b,c,d,e,f]=mym(sprintf('show columns from %s like "etaB"',acq.pair_tablename));
+if isempty(a)
+    %add fields etaB and omegaB to old tables
+    mym(sprintf('ALTER TABLE %s.%s ADD COLUMN etaB FLOAT AFTER omega',db.name,acq.pair_tablename));
+    mym(sprintf('ALTER TABLE %s.%s ADD COLUMN omegaB FLOAT AFTER etaB',db.name,acq.pair_tablename));
+    disp('adding etaB and omegaB  fields to the spotpair table')
+    % here we need to run through the table and fill in these two fields -
+    % maybe we should add also the hkl and plane normal information
+    % this still needs to be done, sorry.
+end
+
+if ~isfield(grain.stat,'areamean')
+    % we need to add this value in gtINDEXTER
+    grain.stat.areamean=0.7*grain.stat.bbxsmean*grain.stat.bbysmean;  % 0.7 is a rough estimate of the spot area / BB-area ratio
+end
+dif_int=grain.stat.intmean;
+dif_area=grain.stat.areamean;
+dif_area_ratio=dif_Xsize_ratio*dif_Ysize_ratio;
+
+
+%% get all possible hkls
+
+[hkltypes_used,info]=gtCrystSpacegroupReflections;
+
+disp('Simulated HKL reflections:')
+disp(hkltypes_used)
+disp(['hkltypes_used: ' num2str(size(hkltypes_used))])
+
+
+% 4 columns needed for hexagonal
+if strcmpi(acq.crystal_system,'hexagonal')
+    hkltypes_used(:,4) = hkltypes_used(:,3);
+    hkltypes_used(:,3) = -hkltypes_used(:,1)-hkltypes_used(:,2);
+end
+
+hklsp  = [];
+hkl    = [];
+thtype = [];
+
+for i = 1:size(hkltypes_used,1)
+    allhkls_i = gtCrystSignedHKLs(hkltypes_used(i,:),spacegroup);
+    nhkls   = size(allhkls_i,1)/2;
+    hklsp   = [hklsp; allhkls_i(nhkls+1:end,:)];
+    hkl     = [hkl; repmat(hkltypes_used(i,:),nhkls,1)];
+    thtype  = [thtype; repmat(i,nhkls,1)];
+end
+
+%disp(['hkl: ' num2str(size(hkl))])
+%disp(['allhkls_i: ' num2str(size(allhkls_i))])
+disp(['hklsp: ' num2str(size(hklsp))])
+
+disp('Getting cartesian coordinates from lattice coordinates...')
+for i=1:size(hklsp,1)
+    normalised_hkls(i,:)=gtHKL2Cart_ln(hklsp(i,:),spacegroup); % modified by LNervo
+end
+
+% produce all possible plane normals using R_vector
+g = Rod2g(grain.R_vector);
+% warning('using g, rather than inv(g), in eq. 3.6 in Poulsen - Rod2g or coords problem?')
+all_normals = (g * normalised_hkls')';
+all_hkls=hklsp;
+%disp(['all_normals: ' num2str(size(all_normals))])
+
+grain.hklsp=hklsp;
+grain.all_normals=all_normals;
+
+%% Forward simulation
+% now do forward simuation - where do we expect dif and ext spots ?
+disp('Starting forward simulation...')
+
+j=1;
+for i=1:size(all_normals,1)
+
+    [image,udirect,vdirect,udiffr,vdiffr,omega,eta,theta] = gtPredictPositions_3D_ln(all_normals(i,:), all_hkls(i,:), grain.center, 0, parameters, 1);
+    
+    len=length(image);
+    h=repmat(all_hkls(i,1),len,1);
+    k=repmat(all_hkls(i,2),len,1);
+
+    if size(all_hkls,2)==4
+        i_hkl=repmat(all_hkls(i,3),len,1);
+        l=repmat(all_hkls(i,4),len,1);
+    else
+        l=repmat(all_hkls(i,3),len,1);
+        i_hkl=NaN;
+        i_hkl=repmat(i_hkl,len,1);
+    end
+
+    
+    if isnan(image)
+        o.flag(j)=NaN;
+        o.h(j)=h;
+        o.k(j)=k;
+        o.i(j)=i_hkl;
+        o.l(j)=l;
+        o.ind(j)=i;
+        disp(sprintf('Reflection %s is not accessible',num2str(all_hkls(i,:))))
+%         if size(all_hkls,2)==3
+%             disp(sprintf('Reflection %d %d %d is not accessible',all_hkls(i,1),all_hkls(i,2),all_hkls(i,3)));
+%         else
+%             disp(sprintf('Reflection %d %d %d %d is not accessible',all_hkls(i,1),all_hkls(i,2),all_hkls(i,3),all_hkls(i,4)));
+%         end
+        j=j+1;
+    else
+        for ind=1:len
+            o.image(j)     = image(ind);
+            o.udirect(j)   = udirect(ind);
+            o.vdirect(j)   = vdirect(ind);
+            o.udiffr(j)    = udiffr(ind);
+            o.vdiffr(j)    = vdiffr(ind);
+            o.omega(j)     = omega(ind);
+            o.eta(j)       = eta(ind);
+            o.theta(j)     = theta(ind);
+            o.h(j)         = h(ind);
+            o.k(j)         = k(ind);
+            o.i(j)         = i_hkl(ind);
+            o.l(j)         = l(ind);
+            o.flag(j)      = 1;
+            o.difspotID(j) = 0;
+            o.ind(j)       = i;
+            j=j+1;
+        end
+    end
+
+end
+
+nop=grain.nof_pairs;
+grain.hklA=zeros(nop,4);
+
+%% Interogate the database(s) to find predicted spots
+
+
+% variables expected and found will be used for calculation of completeness
+expected=0;
+found=0;
+radius1=sqrt((dif_Xsize/2)^2+(dif_Ysize/2)^2);  % half diagonal of average difspot BoundingBox
+
+for i=1:length(o.image)
+    radius2=sqrt((o.udiffr(i)-acq.xdet/2)^2+(o.vdiffr(i)-acq.ydet/2)^2);  % distance between center and spot
+    radius=radius1+radius2;  % approximate (maximum) radius of the difspot
+    % don't look at spots which potentially touch the blind area or direct beam area of the detector
+    if (   o.udiffr(i) < dif_Xsize/2 || o.udiffr(i) > acq.xdet-dif_Xsize/2 ...
+            || o.vdiffr(i) < dif_Ysize/2 || o.vdiffr(i) > acq.ydet-dif_Ysize/2 ...
+            || radius > acq.maxradius ...
+            || (     o.udiffr(i)+dif_Xsize/2>parameters.seg.bb(1) && o.udiffr(i)-dif_Xsize/2 < parameters.seg.bb(1)+parameters.seg.bb(3) ...
+            && o.vdiffr(i)+dif_Ysize/2 > parameters.seg.bb(2) && o.vdiffr(i)-dif_Ysize/2 < parameters.seg.bb(2)+parameters.seg.bb(4) ) ...
+            )
+        o.flag(i)=0;   % don't consider these reflections
+        if isnan(o.i(i))
+            disp(sprintf('%d %d %d spot close to border or outside of active area - skipping...',o.h(i),o.k(i),o.l(i)));
+        else
+            disp(sprintf('%d %d %d %d spot close to border or outside of active area - skipping...',o.h(i),o.k(i),o.i(i),o.l(i)));
+        end
+        continue % skip this reflection and go to next one
+    else
+        expected=expected+1;
+        % use selection criteria similar to match difspots (match)
+        match=parameters.match;
+        thr_max_offset=min(20,round(match.thr_max_offset/(abs(sind(o.eta(i))))));  % allow for a 1/sin(eta) dependency on omega search range - limited to a max offset of 20 images
+        firstquery=sprintf(['select difspotID, CentroidX, CentroidY, CentroidImage, BoundingBoxXsize, BoundingBoxYsize, Area, grainID  from %sdifspot where '...
+            '(%d between CentroidImage-%d and CentroidImage+%d) '...
+            'and (abs(%sdifspot.CentroidX-%d)/%d)<0.5 '...
+            'and (abs(%sdifspot.CentroidY-%d)/%d)<0.5 '...
+            'order by ((abs(BoundingBoxXsize-%d)/%d)+(abs(BoundingBoxYsize-%d)/%d)) limit 1'],...
+            name,...
+            o.image(i), thr_max_offset, thr_max_offset,...
+            name, o.udiffr(i), dif_Xsize,...
+            name, o.vdiffr(i), dif_Ysize,...
+            dif_Xsize, dif_Xsize, dif_Ysize, dif_Ysize);    % use relaxed conditions for the COM positions
+
+        [candidates, CentroidX, CentroidY, CentroidImage, BoundingBoxXsize, BoundingBoxYsize, Area, grainID] = mym(firstquery);
+
+        if isempty(candidates)  % segmentation problem ?
+
+            o.flag(i)=-1;
+            if isnan(o.i(i))   % get the display right for hkil notation in hexagonal, trigonal, etc...
+                disp(sprintf('Can not find %d %d %d reflection (segmentation problem ?) skipping...',o.h(i),o.k(i),o.l(i)));
+                grain.missing_refl=[grain.missing_refl;o.h(i),o.k(i),o.l(i)];
+
+            else
+                disp(sprintf('Can not find %d %d %d %d reflection (segmentation problem ?) skipping...',o.h(i),o.k(i),o.i(i),o.l(i)));
+                grain.missing_refl=[grain.missing_refl;o.h(i),o.k(i),o.i(i),o.l(i)];
+            end
+
+            if app.show_results
+                disp(firstquery)
+
+                %convert Omega to image number
+                start_image = o.image(i)-5;
+                if start_image<0
+                    start_image=0;
+                end
+                end_image = o.image(i)+5;
+                if end_image>(2*acq.nproj)-1;
+                    end_image=(2*acq.nproj)-1;
+                end
+
+                start_image
+                end_image
+
+                full=zeros(acq.ydet,acq.xdet);
+                for im=start_image:end_image
+                    full=full+edf_read(sprintf('1_preprocessing/full/full%04d.edf',im));
+                end
+                full=full./(end_image-start_image+1);
+
+                % ajout sabine%
+
+                figure(1)
+                imshow((full),[-100 100]);
+                impixelinfo
+                text=sprintf('%d %d %d reflection',o.h(i),o.k(i), o.l(i));
+                title(text)
+                hold on;
+                plot(o.udirect(i),o.vdirect(i),'go')
+                plot(o.udiffr(i),o.vdiffr(i),'ro')
+                disp('click image to close and check next reflection')
+                %keyboard
+                waitforbuttonpress;
+            end
+
+        else
+            found=found+1;
+
+            % we assume that part of the intensity stems from our grain and increment the completeness counter...
+            % now refine the search criteria
+            query=sprintf(['select difspotID from %sdifspot where '...
+                '(%d between CentroidImage-%d and CentroidImage+%d) '...
+                'and (abs(%sdifspot.CentroidX-%d)/%d)<%f '...
+                'and (abs(%sdifspot.CentroidY-%d)/%d)<%f '...
+                'and (BoundingBoxXsize between %f and %f) and (BoundingBoxYsize between %f and %f) '...
+                'and (Area between %f and %f) '...
+                'and (grainID=0 or grainID=%d) '...   % only look at spots which have not already been assigned
+                'order by ((abs(BoundingBoxXsize-%d)/%d)+(abs(BoundingBoxYsize-%d)/%d)) limit 1'],...   % this could be improved according to Peters goodness criteria...
+                name,...
+                o.image(i), thr_max_offset, thr_max_offset,...
+                name, o.udiffr(i), dif_Xsize, dif_Xsearch/dif_Xsize,...
+                name, o.vdiffr(i), dif_Ysize, dif_Xsearch/dif_Xsize,...    % use the same (more relaxed) X condition for the Y COM position
+                dif_Xsize/dif_Xsize_ratio, dif_Xsize*dif_Xsize_ratio, dif_Ysize/dif_Ysize_ratio, dif_Ysize*dif_Ysize_ratio,...
+                dif_area/dif_area_ratio, dif_area*dif_area_ratio,...
+                grain.id,...
+                dif_Xsize, dif_Xsize, dif_Ysize, dif_Ysize);
+
+            [difspotID] = mym(query);
+
+            % classify spots with flag:
+            % NaN:  not accessible reflection
+            % -1 :  no intensity found at expected position (loose criteria)
+            %  0 :  there is some intensity - but the spot does not match strictsearch criteria
+            %  1 :  spot matching the strict criteria
+            %  2 :  spot which already had been found by gtINDEXTER
+
+            if isempty(difspotID)
+                disp(sprintf('Found some intensity for the %d %d %d reflection, but the spot does not match the strict search criteria - excluding this spot...)...',o.h(i),o.k(i),o.l(i)));
+
+                o.flag(i)=0;
+
+                if app.show_results
+                    sprintf(['CentroidImage: %d is expected between %d and %d\n'...
+                        'CentroidX: %f is expected between %f and %f \n '...
+                        'CentroidY: %f is expected between %f and %f \n' ...
+                        'BoundingBoxXsize: %d is expected between %f and %f \n' ...
+                        'BoundingBoxYsize: %d is expected between %f and %f \n' ...
+                        'Area: %f: is expected between %f and %f \n' ...
+                        'grainID: %d should be 0 or %d'],...
+                        CentroidImage, CentroidImage-thr_max_offset, CentroidImage+thr_max_offset,...
+                        CentroidX,o.udiffr(i)-dif_Xsearch,o.udiffr(i)+dif_Xsearch,...
+                        CentroidY,o.vdiffr(i)-dif_Ysearch,o.vdiffr(i)+dif_Ysearch,...
+                        BoundingBoxXsize,dif_Xsize/dif_Xsize_ratio, dif_Xsize*dif_Xsize_ratio,...
+                        BoundingBoxYsize,dif_Ysize/dif_Ysize_ratio, dif_Ysize*dif_Ysize_ratio,...
+                        Area, dif_area/dif_area_ratio, dif_area*dif_area_ratio,...
+                        grainID,grainID)
+
+
+                    canspot=gtGetSummedDifSpot(candidates,parameters);
+                    figure(2);imshow(canspot,[])
+                    %convert Omega to image number
+                    start_image = o.image(i)-5;
+                    if start_image<0
+                        start_image=0;
+                    end
+                    end_image = o.image(i)+5;
+                    if end_image>(2*acq.nproj)-1;
+                        end_image=(2*acq.nproj)-1;
+                    end
+
+                    start_image
+                    end_image
+
+                    full=zeros(acq.ydet,acq.xdet);
+                    for im=start_image:end_image
+                        full=full+edf_read(sprintf('1_preprocessing/full/full%04d.edf',im));
+                    end
+                    full=full./(end_image-start_image+1);
+
+                    % ajout sabine%
+
+                    figure(1)
+                    imshow((full),[-100 100]);
+                    impixelinfo
+                    text=sprintf('%d %d %d reflection',o.h(i),o.k(i), o.l(i));
+                    title(text)
+                    hold on;
+                    plot(o.udirect(i),o.vdirect(i),'go')
+                    plot(o.udiffr(i),o.vdiffr(i),'ro')
+                    disp('click image to close and check next reflection')
+                    %keyboard
+                    k=waitforbuttonpress;
+                end
+                % elseif length(difspotID>1)
+                % select the most probable spot...to be implemented
+            else
+                disp(sprintf('Found spot matching the strict criteria for the %d %d %d reflection',o.h(i),o.k(i),o.l(i)));
+                o.flag(i)=1;
+                o.difspotID(i)=difspotID; % this spot has been detected
+                index=find(grain.difspots==difspotID); % do we already have a difspot with this ID number?
+
+                if ~isempty(index)
+                    o.flag(i)=2;  % this spot had already been paired and indexed by gtINDEXTER
+                    if index>nop  % this spot is in the second half of the scan - we can update the hkl information of the pair spot in the first half...
+                        index=index-nop;
+                        grain.hklA(index,:)=-[o.h(i), o.k(i), o.i(i), o.l(i)];   % the pair spot has negative hkil indices
+                    else
+                        grain.hklA(index,:)=[o.h(i), o.k(i), o.i(i), o.l(i)];
+                    end
+
+                    if app.update_db
+                        mysqlcmd=dbUpdate(difspottable,'difspotID',difspotID,'GrainID',grain.id);
+                        mym(mysqlcmd);
+                    end
+                end
+
+            end % if  a difspot has been found at the expected position
+        end  % if isempty candidates
+    end % if there could be a spot on the detector
+end    % loop over predicted spot positions
+
+
+grain.completeness=found/expected;
+
+%% Are there any Friedel pairs in the remaining list of detected spots ?
+%
+% Pairs will be processed as such (calculation of
+% eta, theta, omega from the Friedel pair...
+difspotID=[];
+j=1;
+for i=1:length(o.flag)
+    if o.flag(i)==1
+        ind(j)=i;   % ind indicates lines in output structure containing unpaired spots
+        omega(j)=o.omega(i);
+        eta(j)=o.eta(i);
+        theta(j)=o.theta(i);
+        hkl(j,1:4)=[o.h(i),o.k(i),o.i(i),o.l(i)];
+        difspotID(j)=o.difspotID(i);
+        j=j+1;
+    end
+end
+
+
+
+grain.newdifspots=difspotID;
+
+grain.hklB=zeros(nop,4);
+grain.plA=zeros(nop,3);
+grain.plB=zeros(nop,3);
+%nop=grain.nof_pairs;
+grain.difspotA=zeros(nop,1);
+grain.difspotB=zeros(nop,1);
+grain.omegaA=zeros(nop,1);
+grain.omegaB=zeros(nop,1);
+grain.etaA=zeros(nop,1);
+grain.etaB=zeros(nop,1);
+grain.thetaA=zeros(nop,1);
+grain.thetaB=zeros(nop,1);
+
+% define new variables
+grain.difspotA(1:nop)=grain.difspots(1:nop);
+grain.difspotB(1:nop)=grain.difspots(nop+1:end);
+grain.omegaA(1:nop)=grain.omega(1:nop);
+grain.omegaB(1:nop)=grain.omega(1:nop)+180;
+grain.etaA(1:nop)=grain.eta(1:nop);
+grain.etaB(1:nop)=180-grain.eta(1:nop);
+grain.thetaA(1:nop)=grain.theta(1:nop);
+grain.thetaB(1:nop)=grain.theta(1:nop);
+
+grain.hklB(1:nop,:)=-grain.hklA(1:nop,:);
+grain.plA(1:nop,:)=grain.pl(1:nop,:);
+grain.plB(1:nop,:)=-grain.plA(1:nop,:);
+% Have any of these spots already been matched, but not been assigned to the grain ?
+
+
+if size(grain.hkl,2)==3
+    grain.hkl(:,4)=grain.hkl(:,3);
+    grain.hkl(:,3)=NaN;
+end
+
+for j=1:length(difspotID)
+    [pid, gid, difaid, difbid, omega_p, eta_p, theta_p]=mym(sprintf('select pairid, grainid, difaid, difbid, omega, eta, theta from %s where difaid=%d or difbid=%d',acq.pair_tablename, difspotID(j), difspotID(j)));
+    if ~isempty(pid) && isnan(gid) %if there is a pair, we can update the grainid to this grain to stop it being considered again
+
+        if length(pid)>=2
+            disp('hm - found two or more entries for the same difspot in pairtable...will take the first one - database corrupted ?!?');
+            pid=pid(1);
+            gid=gid(1);
+            difaid=difaid(1);
+            difbid=difbid(1);
+            omega_p=omega_p(1);
+            eta_p=eta_p(1);
+            theta_p=theta_p(1);
+        end
+
+        if difaid==difspotID(j)
+            pairspotID=difbid;
+        else
+            pairspotID=difaid;
+        end
+        [tmp,index]=find(o.difspotID==pairspotID);
+        if isempty(index)
+            disp(sprintf('Matching thinks that spot %d has a pair, but ForwardSimulation can not find it, we will exclude this spot...',difspotID(j)));
+            o.flag(ind(j))=5;  % 5 for problem
+        else
+            nop=nop+1;
+            o.flag(ind(j))=4;
+            o.flag(index)=4;
+            h=o.h(ind(j));
+            k=o.k(ind(j));
+            i=o.i(ind(j));
+            l=o.l(ind(j));
+
+            mysqlcmd=sprintf('select plX, plY, plZ from %s where difAID=%d',acq.pair_tablename, difaid);
+            [plX, plY, plZ]=mym(mysqlcmd);
+
+
+            grain.pairid=[grain.pairid,pid];
+            grain.difspotA=[grain.difspotA;difaid];
+            grain.difspotB=[grain.difspotB;difbid];
+            grain.omegaA=[grain.omegaA;omega_p];
+            grain.omegaB=[grain.omegaB;omega_p+180];
+            grain.etaA=[grain.etaA;eta_p];
+            grain.etaB=[grain.etaB;180-eta_p];
+            grain.thetaA=[grain.thetaA;theta_p];
+            grain.thetaB=[grain.thetaB;theta_p];
+            grain.hklA=[grain.hkl;[h k i l]];
+            grain.hklB=[-grain.hkl;-[h k i l]];
+            grain.plA=[grain.pl;[plX plY plZ]];
+            grain.plB=[-grain.pl;-[plX plY plZ]];
+
+            if app.update_db
+                %update grainID in spotpair table
+                mysqlcmd=dbUpdate(acq.pair_tablename,'pairid',pid,'GrainID',grain.id);
+                mym(mysqlcmd);
+            end
+        end
+    end
+end
+
+hkl=[];
+
+j=1;
+
+% Looking for pairs in the remaining list of unpaired spots
+ind=[];
+for i=1:length(o.flag)
+    if o.flag(i)==1
+        ind(j)=i;   % ind contains line-ids of remaining flag "1" spots in output structure
+        omega(j)=o.omega(i);
+        eta(j)=o.eta(i);
+        theta(j)=o.theta(i);
+        hkl(j,1:4)=[o.h(i),o.k(i),o.i(i),o.l(i)];
+        difspotID(j)=o.difspotID(i);
+        j=j+1;
+    end
+end
+
+%% try to find the 180 degree offset (omega-pair) spot of the spot
+
+newpairs=[];
+j=1;
+
+for i=1:length(ind)
+
+
+    index1=[];
+    index2=[];
+    index=[];
+
+    [dummy,dummy2,index1]=intersect(-hkl(i,:),hkl,'rows');  % find the first instance of -h-k-l in the list of spots
+    if ~isempty(index1)
+        hkl(index1,:)=[0 0 0 0];  % a first -h-k-l has been found - set it temporarily to 0 0 0
+        [dummy,dummy2,index2]=intersect(-hkl(i,:),hkl,'rows'); % is there a second -h -k -l ?
+        hkl(index1,:)=-hkl(i,:);   % set back the first one to its original values
+        if ~isempty(index2)
+            index=[index1,index2];    % these are the possible pair candidates - now investigate if valid
+        end
+
+        pair_omega=mod(omega(i)+180,360);   % calculate the 180 degree offset omega value
+        delta_omega=abs(omega(index)-pair_omega);
+        goodone=find(delta_omega==min(delta_omega),1);   % select the -h-k-l reflection fulfilling omega2=omega1+180
+
+        thr_max_offset=min(20,2*round(match.thr_max_offset/(abs(sind(eta(i))))))*180/acq.nproj;
+
+        if delta_omega(goodone)<thr_max_offset
+            newpairs(j,1)=i;
+            newpairs(j,2)=index(goodone);
+
+            j=j+1;
+        else
+            if isnan(o.i(1))
+                disp(sprintf('Could not find the omega pair spot of %d %d %d', hkl(i,1),hkl(i,2),hkl(i,4)));
+            else
+                disp(sprintf('Could not find the omega pair spot of %d %d %d %d', hkl(i,1),hkl(i,2),hkl(i,3),hkl(i,4)));
+            end
+        end %if delta_omega
+    end
+end
+
+newpairs=sort(newpairs,2);
+newpairs=unique(newpairs,'rows');
+
+if ~isempty(newpairs)
+    newhkl=hkl(newpairs(:,1),:);
+else
+    newhkl=[];
+end
+
+%% get eta, theta, omega from these pairs
+
+% Theoretical Bragg angles from energy and crystal structure
+% modified by LNervo
+%[tmp,results]=gtnew_calculate_twotheta() ;
+%comp_2thetas=results.centre; % coloumn vector of all valid 2theta angles in degrees
+info
+comp_2thetas=info.tt; % coloumn vector of all valid 2theta angles in degrees
+thr_ang=match.thr_ang;
+
+
+corr_rot_to_det=match.corr_rot_to_det;   % correction of rot_to_det in pixels (0)
+rot_to_det=acq.dist/acq.pixelsize+corr_rot_to_det;
+tiltY=match.tiltY;
+tiltZ=match.tiltZ;
+sorZ = floor(acq.ydet/2) + 0.5; % between two central pixels (if even)
+
+
+
+
+% now fill in the information into the grain structure
+% first spot should correspond to spot in first half of scan
+grain.nof_newpairs=size(newpairs,1);
+
+
+for i=1:size(newpairs,1)
+    if omega(newpairs(i,1))>omega(newpairs(i,2))
+        newpairs(i,:)=newpairs(i,[2,1]);
+        newhkl(i,:)=-newhkl(i,:); % check this !!!!
+    end
+
+    nop=nop+1;
+    difAID=difspotID(newpairs(i,1));
+    difBID=difspotID(newpairs(i,2));
+    query=sprintf('select CentroidX,CentroidY,CentroidImage,BoundingBoxXsize,BoundingBoxYsize,Integral from %sdifspot where DifspotID=%d',name,difAID);
+    [sp1.centX,sp1.centY,sp1.cenIM,sp1.bbXsize,sp1.bbYsize,sp1.integral]=mym(query);
+    query=sprintf('select CentroidX,CentroidY,CentroidImage,BoundingBoxXsize,BoundingBoxYsize,Integral from %sdifspot where DifspotID=%d',name,difBID);
+    [sp2.centX,sp2.centY,sp2.cenIM,sp2.bbXsize,sp2.bbYsize,sp2.integral]=mym(query);
+
+    theta= gtThetaOfPairs(sp1.centX,sp1.centY,sp2.centX,sp2.centY,rot_to_det,tiltY,tiltZ,acq.rotx,sorZ) ;  % check with Peter if tilts are taken correctly into account
+    % Check theta angle and plane family for each candidate
+    [theta_OK,angle_diff,thetatype] = sfCheck_thetas(sp1.centX,sp1.centY,sp2.centX,sp2.centY,...
+        rot_to_det,tiltY,tiltZ,acq.rotx,sorZ,comp_2thetas,2*thr_ang);   % increased the angle tolerance to 2*thr_ang here
+
+
+    eta= gtEtaOfPairs(sp1.centX,sp1.centY,sp2.centX,sp2.centY,tiltY,tiltZ,acq.rotx,sorZ) ;
+    etaB=mod(180-eta,360); % eta of spotB
+    omega1=sp1.cenIM/acq.nproj*180;   %nproj is number of images over 180 degrees
+    omega2=sp2.cenIM/acq.nproj*180;
+    omegamean=mean([omega1,omega2-180]);
+    omegaB=omegamean+180;
+    sp1.id=difAID;
+    sp2.id=difBID;
+    % Diffraction vector in LAB coordinates:
+    diff_vec_setup= gtDiffVecInLab(sp1.centX,sp1.centY,sp2.centX,sp2.centY,rot_to_det,tiltY,tiltZ,acq.rotx,sorZ) ;
+
+    % Plane normal in LAB coordinates:
+    pl_vec_setup= gtDiffPlaneNormInLab(sp1.centX,sp1.centY,sp2.centX,sp2.centY,rot_to_det,tiltY,tiltZ,acq.rotx,sorZ);
+
+    % Diffraction vector and plane normal in SAMPLE coordinates:
+    [diff_vec_sam(1),diff_vec_sam(2),diff_vec_sam(3)] = gtTrLabToSam(diff_vec_setup(1),diff_vec_setup(2),diff_vec_setup(3),omegamean) ;
+    [pl_vec_sam(1),pl_vec_sam(2),pl_vec_sam(3)] = gtTrLabToSam(pl_vec_setup(1),pl_vec_setup(2),pl_vec_setup(3),omegamean) ;
+
+    % Spot centers from SCINTILLATOR PLANE into LAB coordinates (in 3D):
+    [lab_cent1(1),lab_cent1(2),lab_cent1(3)] = gtTrScToLab(sp1.centX,sp1.centY,rot_to_det,tiltY,tiltZ,acq.rotx,sorZ) ;
+    [lab_cent2(1),lab_cent2(2),lab_cent2(3)] = gtTrScToLab(sp2.centX,sp2.centY,rot_to_det,tiltY,tiltZ,acq.rotx,sorZ) ;
+
+    % Spot centers from LAB into SAMPLE coordinates:
+    [samcentA(1),samcentA(2),samcentA(3)] = gtTrLabToSam(lab_cent1(1),lab_cent1(2),lab_cent1(3),omega1) ;
+    [samcentB(1),samcentB(2),samcentB(3)] = gtTrLabToSam(lab_cent2(1),lab_cent2(2),lab_cent2(3),omega2) ;
+
+    % Average intensity and bounding box sizes from the two spots:
+    av_intint=(sp1.integral+sp2.integral)/2 ;
+    av_bbXsize=(sp1.bbXsize+sp2.bbXsize)/2 ;
+    av_bbYsize=(sp1.bbYsize+sp2.bbYsize)/2 ;
+
+    if app.update_db
+        % Variables in table
+        % samcent: difspot centroid in the sample system
+        % lines connecing the two spots in the sample system
+        % lor: line origin (centroid of spot A);
+        % ldir: unit vector of line direction
+        % pl: plane normal in sample system
+
+        mysqlcmd=sprintf(['INSERT INTO %s (difAID, difBID, theta, eta, omega, etaB, omegaB, '...
+            'avintint, avbbXsize, avbbYsize, '...
+            'samcentXA, samcentYA, samcentZA, samcentXB, samcentYB, samcentZB, '...
+            'ldirX, ldirY, ldirZ, plX, plY, plZ, thetatype) ',...
+            'VALUES (%d,%d,%0.20g,%0.20g,%0.20g,%0.20g,%0.20g,%0.20g,%0.20g,%0.20g,'...
+            '%0.20g,%0.20g,%0.20g,%0.20g,%0.20g,%0.20g,%0.20g,%0.20g,%0.20g,%0.20g,%0.20g,%0.20g,%d)'],...
+            acq.pair_tablename,sp1.id,sp2.id,theta,eta,omegamean,etaB,omegaB,av_intint,av_bbXsize,av_bbYsize,...
+            samcentA(1),samcentA(2),samcentA(3),samcentB(1),samcentB(2),samcentB(3),...
+            diff_vec_sam(1),diff_vec_sam(2),diff_vec_sam(3),pl_vec_sam(1),pl_vec_sam(2),pl_vec_sam(3),thetatype) ;
+        mym(mysqlcmd);
+        pairid=mym(sprintf('select pairid from %s where difaid=%d',acq.pair_tablename,sp1.id));
+        grain.pairid=[grain.pairid,pairid(1)];
+    end
+
+
+    grain.difspotA(nop)=difspotID(newpairs(i,1));
+    grain.difspotB(nop)=difspotID(newpairs(i,2));
+    grain.omegaA(nop)=omegamean;
+    grain.omegaB(nop)=omegamean+180;
+    grain.etaA(nop)=eta;
+    grain.etaB(nop)=etaB;
+    grain.thetaA(nop)=theta;
+    grain.thetaB(nop)=theta;
+    grain.plA(nop,:)=pl_vec_setup;
+    grain.plB(nop,:)=-pl_vec_setup;
+    grain.hklA(nop,:)=newhkl(i,:);
+    grain.hklB(nop,:)=-newhkl(i,:);
+
+    % and fill in the output structure
+    ind1=ind(newpairs(i,1));
+    ind2=ind(newpairs(i,2));
+    o.omega(ind1)=omegamean;
+    o.omega(ind2)=omegamean+180;
+    o.theta(ind1)=theta;
+    o.theta(ind2)=theta;
+    o.eta(ind1)=eta;
+    o.eta(ind2)=180-eta;
+    o.flag(ind1)=4;
+    o.flag(ind2)=4;
+end
+
+
+%%
+% try to calculate in the missing information for the remaining, unpaired
+% spots based on the measured spot positions and known grain position
+
+
+ind=[];
+j=1;
+for i=1:length(o.image)
+    if o.flag(i)==1
+        ind(j)=i;   % ind now contains the remaining unpaired spots
+        j=j+1;
+    end
+end
+
+grain.nof_singles=length(ind);
+
+% allocate vectors containing single spots
+grain.difspotC=zeros(length(ind),1);
+grain.omegaC=zeros(length(ind),1);
+grain.etaC=zeros(length(ind),1);
+grain.thetaC=zeros(length(ind),1);
+grain.hklC=zeros(length(ind),4);
+grain.plC=zeros(length(ind),3);
+
+for j=1:length(ind)
+
+    [grainx,grainy,grainz]=gtTrSamToLab(grain.center(1),grain.center(2),grain.center(3),o.omega(ind(j)));
+
+    % calculate the distances in pixels with respect to the laboratory system
+    dx= acq.dist/acq.pixelsize-grainx;
+    dy= o.udiffr(ind(j))-acq.rotx-grainy;
+    dz= acq.ydet/2-o.vdiffr(ind(j))-grainz;
+
+    grain.omegaC(j) = o.omega(ind(j));
+    grain.etaC(j)= atan2(dy,dz)/pi*180;
+    grain.thetaC(j) = atand(sqrt(dy.^2+dz.^2)/dx)/2;
+    grain.difspotC(j)=o.difspotID(ind(j));
+
+    kh=[dx dy dz];
+    kh=kh/norm(kh);  % normalized difracted beam direction
+    k0=[1 0 0];      % normalized incoming beam direction
+    G= (kh-k0)/norm(kh-k0);        % normalized Laboratory system scattering vector
+    %refl         = find(abs(tt.centre-Theta(ndx+j)*2)==min(abs(tt.centre-Theta(ndx+j)*2)));  % find out what type of reflection this Theta corresponds to
+    grain.hklC(j,:) = [o.h(ind(j)), o.k(ind(j)), o.i(ind(j)), o.l(ind(j))];
+    [pn(1),pn(2),pn(3)]= gtTrLabToSam(G(1),G(2),G(3),o.omega(ind(j))); % normalized plane_normal in sample coordinate system
+    grain.plC(j,:)=[pn(1),pn(2),pn(3)];
+
+end
+
+
+if any(isnan(o.i))
+    grain.hklA=grain.hklA(:,[1 2 4]);
+    grain.hklB=grain.hklB(:,[1 2 4]);
+    grain.hklC=grain.hklC(:,[1 2 4]);
+end
+
+disp(sprintf('\n\n Forward Simulation has detected %d new spotpairs and %d single spots\n\n',grain.nof_newpairs,grain.nof_singles));
+
+
+%%
+    function [theta_OK,angle_diff,thetatype]=sfCheck_thetas(scXA,scYA,scXB,scYB,rottodet,tiltY,tiltZ,rotx,sorZ,comp_2thetas,thr_ang)
+        % Checks whether the position of two spots gives a diffraction vector which
+        % corresponds to a valid 2theta angle within the given threshold.
+
+        angle=2*gtThetaOfPairs(scXA,scYA,scXB,scYB,rottodet,tiltY,tiltZ,rotx,sorZ);
+
+        diff=angle-comp_2thetas;
+
+        if all(abs(diff) > thr_ang) % checks if all values are non-zero
+            theta_OK=false;
+        else
+            theta_OK=true ;
+        end
+        [mini,thetatype]=min(abs(diff));
+        angle_diff=diff(thetatype);
+    end
+
+end
\ No newline at end of file
diff --git a/zUtil_Optimization/gtFullOptimizer3.m b/zUtil_Optimization/gtFullOptimizer3.m
new file mode 100644
index 0000000000000000000000000000000000000000..7b3a49eaf1c9d256658e7c1ed33cc98579f53a45
--- /dev/null
+++ b/zUtil_Optimization/gtFullOptimizer3.m
@@ -0,0 +1,72 @@
+function gtFullOptimizer3(grainid, parameters, difspots)
+% gtFullOptimizer3(grainid, parameters, difspots)
+% grainid = grain{grainid}
+% difspots = list of spots id
+
+% save some info in the opt structure
+opt.id=grainid.id;
+opt.workdir=pwd;
+
+if ~isfield(grainid,'difspots')
+    grainid.difspots=difspots;
+end
+
+ind=strfind(pwd,'/');
+opt.dataset=opt.workdir(ind(end)+1:end);
+
+opt.grain='grain.mat';
+opt.parfile='parameters.mat';
+opt.gcenter=grainid.center;
+opt.gR_vector=grainid.R_vector;
+
+% Create the full summed difspots image
+if isfield(grainid,'difspots')
+   full=gtPlaceDifspotinFull_ln(grainid.difspots,parameters,'save',1);
+else
+   full=gtPlaceDifspotinFull_ln(difspots,parameters);
+end
+
+% generate grain fed
+name=sprintf('gr%d_fed.mat',grainid.id);
+if ~exist(name,'file')
+    gr=gtFedGenerateRandomGrain2(grainid,full,parameters,'save',1);
+else
+    check=inputwdefault('Do you want to load the existing fed grain?','y');
+    if strcmpi(check,'y')
+        gr=load(name);
+        gr=gr.grain;
+    else
+        gr=gtFedGenerateRandomGrain2(grainid,full,parameters);
+    end
+end
+
+% load original geometry
+[geometry,pippo]=gtOptimizeDetector2(gr,parameters); % was gtOptimizeDetector
+opt.fed.geo=geometry;
+opt.fed.uv=gr.allblobs.uv;
+% removes NaN
+ind=find(isnan(opt.fed.uv(:,1))); % size -> size/2
+opt.ind.nan=ind;
+opt.fed.uv(ind,:)=[];
+opt.db.uv=[pippo.bbox.xcen pippo.bbox.ycen];
+% removes zeros from database
+ind2=find(opt.db.uv(:,1)==0);
+ind3=find(opt.db.uv(:,1)~=0);
+opt.db.uv(ind2,:)=[];
+opt.ind.zeros=ind2;
+opt.ind.nonzeros=ind3;
+
+% fit the spots positions taken from the database with the current geometry as guess
+disp('*** Fit ***')
+fitgeo=gtTuneDetector3(opt.fed.geo,gr,opt.db.uv,ind3);
+opt.fit.geo=fitgeo;
+opt.fit.uv=fitgeo.Fnew(:,1:2);
+
+
+name=sprintf('opt%d.mat',grainid.id);
+save(name,'opt');
+
+tmp=gtPlotUVW(full,opt.fit.uv,'r',opt.fed.geo,[0 200],'After optimization : ');
+
+
+end % end function
diff --git a/zUtil_Optimization/gtGetGeometry.m b/zUtil_Optimization/gtGetGeometry.m
new file mode 100644
index 0000000000000000000000000000000000000000..fc23452db4e2e6ddefde37844b8dec455b4ee9f4
--- /dev/null
+++ b/zUtil_Optimization/gtGetGeometry.m
@@ -0,0 +1,54 @@
+function geo = gtGetGeometry(parameters, fed)
+%% FUNCTION GTGETGEOMETRY Get geometry from parameters
+%  geo = gtGetGeometry(parameters, fed)
+%
+%    fed = flag for fed analysis <logical 1x1> {0}
+%
+%  Version 002 21-09-2011 LNervo
+
+if ~exist('fed','var') || isempty(fed)
+    fed=false;
+end
+if fed
+geometry{1}='detpos0';
+geometry{2}='detdiru0';
+geometry{3}='detdirv0';
+geometry{4}='beamdir0';
+geometry{5}='rotdir0';
+geometry{6}='detucen0';
+geometry{7}='detvcen0';
+
+if ~fed
+    geometry{8}='detdir0';
+    geometry{9}='pixelsize';
+    geometry{10}='nproj';
+    geometry{11}='rotation_axis';
+end
+
+if ~exist('parameters','var') || isempty(parameters) 
+    load parameters
+end
+
+if isfield(parameters,'acq')
+    acq=parameters.acq;
+else
+    acq=parameters;%25/08/2011
+end
+
+if ~all(isfield(acq,geometry))
+    disp('Some parameters are missing. Running gtCheckParameters...')
+    gtCheckParameters
+    return
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% save the current geometry
+for i=1:length(geometry) 
+    var=char(geometry(i));
+    if fed
+        var=var(1:end-1);
+    end
+    geo.(var)=acq.(char(geometry(i)));
+end
+
+end
\ No newline at end of file
diff --git a/zUtil_Optimization/gtLimitsTwoTheta.m b/zUtil_Optimization/gtLimitsTwoTheta.m
new file mode 100644
index 0000000000000000000000000000000000000000..9930db66cb033d58b66b05427e99a491adf5c157
--- /dev/null
+++ b/zUtil_Optimization/gtLimitsTwoTheta.m
@@ -0,0 +1,147 @@
+function [minangle,maxangle]=gtLimitsTwoTheta(updatepar,calc)
+%% GTLIMITSTWOTHETA Calculate TwoTheta maximum and minimum
+% [minangle,maxangle]=gtLimitsTwoTheta(updatepar)
+%
+%     Load parameters.mat and save (if updatepar=1) new fields in parameters.acq:
+%
+%       detanglemin = minimum twotheta seen from the detector
+%       detanglemax = maximum twotheta seen from the detector
+%       
+%         maxradius = maximum radius from the center of the detector
+%           detdir0 = direction normal to the detector (been the detector)
+% 
+%     Possible detector configuration:
+%       1) inline detector and centered w.r.t. beam direction - detpos0(x,0,0)
+%       2) inline detector with z-offset - detpos0(x,0,z)
+%       3) vertical detector centered w.r.t. the sample - detpos0(x,0,z)
+%
+% FUNCTIONS USED:
+%
+%   gtConvEnergyToWavelength(energy) : lambda  
+%     ->  energy <double 1x1> [keV]
+%         lambda <double 1x1> [Angstrom (Ã…)]
+%
+
+if exist('parameters.mat','file')
+    load parameters;
+else
+    error('Cannot find the parameters.mat file!')
+end
+
+if ~exist('updatepar','var') || isempty(updatepar)
+    updatepar=0;
+end
+if ~exist('calc','var') || isempty(calc)
+    calc=1;
+end
+
+acq=parameters.acq;
+spacegroup=acq.spacegroup;
+energy=acq.energy;
+lambda=gtConvEnergyToWavelength(energy);
+latticepar=acq.latticepar;
+detpos=acq.detpos0
+
+% Calculate minimum and maximum twotheta angle of the experiment
+
+upd=calc;
+if isfield(parameters.acq,'detanglemin') && isfield(parameters.acq,'detanglemax') && ...
+    ~isempty(parameters.acq.detanglemin) && ~isempty(parameters.acq.detanglemax) ...
+    && parameters.acq.detanglemax~=0
+
+    minangle=parameters.acq.detanglemin;
+    maxangle=parameters.acq.detanglemax;
+    upd=false;
+else
+    upd=true;
+end
+
+
+if upd
+    if ~isfield(parameters.acq,'maxradius')
+        maxradius=sqrt((acq.ydet/2)^2+(acq.xdet/2)^2);% in pixel
+        parameters.acq.maxradius=maxradius;
+        if updatepar
+            save parameters parameters
+        end
+    else
+        maxradius=acq.maxradius;
+    end
+
+    % dist in mm
+    % maxradius in pixel
+    % detpos0 in mm
+
+    if isfield(parameters.acq,'detdir0')
+        detdir=parameters.acq.detdir0;
+    else
+        detdir=cross(parameters.acq.detdiru0,parameters.acq.detdirv0);
+        parameters.acq.detdir0=detdir;
+        if updatepar
+           save parameters parameters
+        end
+    end
+
+    x=[1 0 0];
+    y=[0 1 0];
+    z=[0 0 1];
+    if abs(dot(detdir,x))==1 % detector inline normal // axis X
+        % suppose detpos(2)=0
+        % detector must be perpendicular to the plane x-z
+        % case inline detector and centered w.r.t. beam direction
+        disp('Inline detector')
+        R=maxradius*acq.pixelsize;
+        if detpos(3)==0
+            minangle=0;
+        else
+            % case inline detector with z-dir offset
+            minangle=atand( ((detpos(3) - R)/detpos(1)) );
+        end
+        maxangle=atand( ((detpos(3) + R)/detpos(1)) );
+
+    elseif abs(dot(detdir,z))==1 % detector vertical normal // axis Z
+        disp('Vertical detector')
+        % case vertical detector offset by xd w.r.t. z-axis (LAB ref.)
+        % detector must be perpendicular to the plane x-z
+        % suppose detpos(2)=0
+        % D distance sample center - detector center
+        %D=sqrt(detpos(1)+detpos(3)); % ?????????
+        R=maxradius*acq.pixelsize;
+        maxangle=atand( abs(detpos(3))/(detpos(1)-R) );
+        minangle=atand( abs(detpos(3))/(detpos(1)+R) );
+        if minangle < 0
+           minangle = abs(minangle)+90; 
+        end
+        if maxangle < 0
+           maxangle = abs(maxangle)+90; 
+        end
+
+    elseif abs(dot(detdir,y))==1 % detector vertical but rotated normal // axis Y
+        disp('Vertical detector - rotated 90 deg')
+        % case vertical detector
+        % suppose detpos(3)=0
+        % D distance sample center - detector center
+        R=maxradius*acq.pixelsize;
+        %D=sqrt(detpos(1)*detpos(1)+detpos(2)*detpos(2));
+        maxangle=atand( abs(detpos(2))/(detpos(1)-R) );
+        minangle=atand( abs(detpos(2))/(detpos(1)+R) );
+        if maxangle < 0
+           maxangle = abs(maxangle)+90; 
+        end
+        if minangle < 0
+           minangle = abs(minangle)+90; 
+        end
+    else
+        error('Check if detector direction is unusual. Normally the detector is inline or vertical.')
+    end
+
+    parameters.acq.detanglemin=minangle;
+    parameters.acq.detanglemax=maxangle;
+    if updatepar
+        save parameters parameters
+    end
+end
+
+end
+
+%%%
\ No newline at end of file
diff --git a/zUtil_Optimization/gtOptimizeDetector2.m b/zUtil_Optimization/gtOptimizeDetector2.m
new file mode 100644
index 0000000000000000000000000000000000000000..9c1657b69e4e5d25a41dfe791d2ecdbb10956e2d
--- /dev/null
+++ b/zUtil_Optimization/gtOptimizeDetector2.m
@@ -0,0 +1,333 @@
+function [geo,newgr]=gtOptimizeDetector2(grainFed,parameters)
+%% newgr=gtOptimizeDetector2(grainFed,parameters)
+%  
+%  Get geometry from parameters, get difspots positions and bbox from
+%  database, predict positions from fed code and 
+%
+%  INPUT:
+%    grainFed = output from gtFedGenerateRandomGrain2
+%    parameters
+%
+%  OUTPUT: 
+%      geo = geometry from the parameters file
+%    newgr = structure with geometry (current geometry), 
+%                           bbox (values read from database)
+%                           fed (values predicted with fed code)
+%                           table (comparison between fed and database
+%                                  values)
+
+geo=gtGetGeometry(parameters);
+
+%% Current geometry
+
+disp('Getting the detector geometry...')
+
+detdiru = geo.detdiru0';%
+detdirv = geo.detdirv0';%
+Qdet = gtFedDetectorProjectionTensor(detdiru,detdirv,1,1);%
+tn = cross(detdiru,detdirv);%
+detpos = (geo.detpos0./geo.pixelsize)'; % pixels
+omstep = 180/geo.nproj;
+uvorig = [geo.detucen0, geo.detvcen0]';
+
+disp('...done!')
+
+%% Getting info from grain
+
+if isempty(grainFed)
+   disp('Calculating output from gtFedGenerateRandomGrain2...')
+   grain=load('grain.mat');
+   full=gtPlaceDifspotinFull_ln(grain{grainFed.id}.difspots,parameters);
+   gr=gtFedGenerateRandomGrain2(grain{grainFed.id},full);
+   grainFed=gr;
+end
+
+grainID=grainFed.id;
+csam = grainFed.center';
+R_vector=grainFed.R_vector;
+difspots=grainFed.difspots;
+
+all=grainFed.allblobs;
+fedtable=[];
+
+
+% NaN rows
+indn=find(isnan(all.uvw(:,1)));
+
+hklsp=all.hklsp;hklsp(indn,:)=[];
+srot=all.srot;
+for i=1:size(indn)
+    srot(indn*3-2:indn*3,:)=[];
+end
+gfomega=all.omega;gfomega(indn,:)=[];
+dvec=all.dvec;dvec(indn,:)=[];
+theta=all.theta;theta(indn,:)=[];
+eta=all.eta;eta(indn,:)=[];
+uvwfed=all.uvw;uvwfed(indn,:)=[];
+uvfed=all.uv;uvfed(indn,:)=[];
+images=round((gfomega/180)*geo.nproj);
+
+
+fed.grainID=grainID;
+fed.center=csam;
+fed.R_vector=R_vector;
+fed.hklsp=hklsp;
+fed.omega=gfomega;
+fed.theta=theta;
+fed.eta=eta;
+fed.uvwfed=uvwfed;
+fed.uvfed=uvfed;
+fed.difspots=difspots';
+
+%% Get info from the database
+
+match=parameters.match;
+name=parameters.acq.name;
+
+%get the mean difspot, X and Y sizes for the current spots in the grain
+dif_Xsize=grainFed.stat.bbxsmean;
+dif_Xsize_ratio=grainFed.stat.bbxsrat*1.3;
+dif_Ysize=grainFed.stat.bbysmean;
+dif_Ysize_ratio=grainFed.stat.bbysrat*1.3;
+
+dif_Xsearch=2*grainFed.stat.bbxsstd;
+dif_Ysearch=4*grainFed.stat.bbysstd;
+
+if ~isfield(grainFed.stat,'areamean')
+    % we need to add this value in gtINDEXTER
+    grainFed.stat.areamean=0.7*grainFed.stat.bbxsmean*grainFed.stat.bbysmean;  % 0.7 is a rough estimate of the spot area / BB-area ratio
+end
+
+dif_int=grainFed.stat.intmean;
+dif_area=grainFed.stat.areamean;
+dif_area_ratio=dif_Xsize_ratio*dif_Ysize_ratio;
+
+
+
+
+gtDBConnect
+
+grain_id=[];
+expected_id=[];
+found_id=[];
+image=[];
+omega=[];
+x0=[];
+y0=[];
+xsize=[];
+ysize=[];
+xcen=[];
+ycen=[];
+bbxcen=[];
+bbycen=[];
+area=[];
+        
+
+for i=1:length(gfomega)
+    
+    thr_max_offset=min(20,round(match.thr_max_offset/(abs(sind(eta(i))))));  % allow for a 1/sin(eta) dependency on omega search range - limited to a max offset of 20 images
+    mysqlcmd=sprintf(['select grainID, difspotID, CentroidX, CentroidY, '...
+        'BoundingBoxXorigin, BoundingBoxYorigin, BoundingBoxXsize, '...
+        'BoundingBoxYsize, CentroidImage, Area  from %sdifspot where '...
+        '(%d between CentroidImage-%d and CentroidImage+%d) '...
+        'and (abs(%sdifspot.CentroidX-%d)/%d)<0.5 '...
+        'and (abs(%sdifspot.CentroidY-%d)/%d)<0.5 '...
+        'order by ((abs(BoundingBoxXsize-%d)/%d)+(abs(BoundingBoxYsize-%d)/%d)) limit 1'],...
+        name,...
+        round(gfomega(i)/omstep), thr_max_offset, thr_max_offset,...
+        name, uvfed(i,1), dif_Xsize,...
+        name, uvfed(i,2), dif_Ysize,...
+        dif_Xsize, dif_Xsize, dif_Ysize, dif_Ysize);
+
+
+    [grainID, expected, CentroidX, CentroidY, ...
+        BoundingBoxXorigin, BoundingBoxYorigin, ...
+        BoundingBoxXsize, BoundingBoxYsize, ...
+        CentroidImage, Area] = mym(mysqlcmd);
+
+    if isempty(expected)
+        grain_id=[grain_id; 0];
+        expected_id=[expected_id; 0];
+        image=[image; 0];
+        omega=[omega; 0];
+        x0=[x0; 0];
+        y0=[y0; 0];
+        xsize=[xsize; 0];
+        ysize=[ysize; 0];
+        xcen=[xcen; 0];
+        ycen=[ycen; 0];
+        bbxcen=[bbxcen; 0];
+        bbycen=[bbycen; 0];
+        area=[area; 0];
+        found_id=[found_id; 0];
+    else
+        grain_id=[grain_id; grainID];
+        expected_id=[expected_id; expected];
+        fprintf('expected_id: %d \n',expected);
+        image=[image; CentroidImage];
+        omega=[omega; CentroidImage*omstep];
+        x0=[x0; BoundingBoxXorigin];
+        y0=[y0; BoundingBoxYorigin];
+        xsize=[xsize; BoundingBoxXsize];
+        ysize=[ysize; BoundingBoxYsize];
+        xcen=[xcen; CentroidX];
+        ycen=[ycen; CentroidY];
+        bbxcen=[bbxcen; BoundingBoxXorigin+BoundingBoxXsize/2];
+        bbycen=[bbycen; BoundingBoxYorigin+BoundingBoxYsize/2];
+        area=[area; Area];
+
+    query=sprintf(['select difspotID from %sdifspot where '...
+        '(%d between CentroidImage-%d and CentroidImage+%d) '...
+        'and (abs(%sdifspot.CentroidX-%d)/%d)<%f '...
+        'and (abs(%sdifspot.CentroidY-%d)/%d)<%f '...
+        'and (BoundingBoxXsize between %f and %f) and (BoundingBoxYsize between %f and %f) '...
+        'and (Area between %f and %f) '...
+        'order by ((abs(BoundingBoxXsize-%d)/%d)+(abs(BoundingBoxYsize-%d)/%d)) limit 1'],...   % this could be improved according to Peters goodness criteria...
+        name,...
+        round(gfomega(i)/omstep), thr_max_offset, thr_max_offset,...
+        name, uvfed(i,1), dif_Xsize, dif_Xsearch/dif_Xsize,...
+        name, uvfed(i,2), dif_Ysize, dif_Ysearch/dif_Ysize,...    % use the same (more relaxed) X condition for the Y COM position
+        dif_Xsize/dif_Xsize_ratio, dif_Xsize*dif_Xsize_ratio, dif_Ysize/dif_Ysize_ratio, dif_Ysize*dif_Ysize_ratio,...
+        dif_area/dif_area_ratio, dif_area*dif_area_ratio,...
+        dif_Xsize, dif_Xsize, dif_Ysize, dif_Ysize);
+
+    [found] = mym(query);
+
+    if ~isempty(found)
+        found_id=[found_id; found];
+        fprintf('found_id: %d \n',found);
+    else
+        found_id=[found_id; 0];
+    end
+
+    end % end expected
+
+end %loop on omega
+
+% save info into parameters
+
+bbox.grain_id=grain_id;
+bbox.expected_id=expected_id;
+bbox.found_id=found_id;
+bbox.x0=x0;
+bbox.y0=y0;
+bbox.xsize=xsize;
+bbox.ysize=ysize;
+bbox.xcen=xcen;
+bbox.ycen=ycen;
+bbox.bbxcen=bbxcen;
+bbox.bbycen=bbycen;
+bbox.image=image;
+bbox.omega=omega;
+bbox.area=area;
+
+fed.omstep=omstep;
+
+%% Find the differences between found and expected  
+
+diff=findDifspots(bbox.expected_id,bbox.found_id,name);
+diff.query='expected_id and found_id';
+bbox.diff=diff;
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Compute uv coordinates and w(omega) values
+
+% fed.UV = [];
+% fed.UVW = [];
+% 
+% n=size(gfomega,1)/4;
+% for j=1:n % must be from 0 to n-1
+%     
+%     % from grainFed=gtFedGenerateRandomGRain2(grain{grainid},full)
+%     S=all.srot(12*j-11:12*j,:);
+%     D=all.dvec(4*j-3:4*j,:);
+%     O=all.omega(4*j-3:4*j); % omega values ordered like small, small+180, big, big+180 for the 4
+%         
+%     uv1a=gtFedPredictUVW(S(1:3,:),D(1,:)',csam,detpos,tn,Qdet,uvorig,O(1),omstep)
+%     uv1b=gtFedPredictUVW(S(4:6,:),D(2,:)',csam,detpos,tn,Qdet,uvorig,O(2),omstep)
+%     uv2a=gtFedPredictUVW(S(7:9,:),D(3,:)',csam,detpos,tn,Qdet,uvorig,O(3),omstep)
+%     uv2b=gtFedPredictUVW(S(10:12,:),D(4,:)',csam,detpos,tn,Qdet,uvorig,O(4),omstep)
+%     
+%     fed.UV  =  [fed.UV;uv1a(1),uv1a(2);uv1b(1),uv1b(2);uv2a(1),uv2a(2);uv2b(1),uv2b(2)];
+%     fed.UVW =  [fed.UVW;uv1a(1),uv1a(2),uv1a(3);uv1b(1),uv1b(2),uv1b(3);uv2a(1),uv2a(2),uv2a(3);uv2b(1),uv2b(2),uv2b(3)];
+% end % size /4
+
+newgr.fed=fed;
+newgr.geometry=geo;
+
+
+%% Try to match the difspots and the hkl values
+
+if ~isempty(bbox.found_id)
+    diff2=findDifspots(bbox.found_id,fed.difspots,name);
+diff2.query='found_id and difspots';
+bbox.diff2=diff2;
+end
+
+newgr.bbox=bbox;
+
+size(fed.omega)
+size(bbox.omega)
+size(fed.uvfed)
+size(bbox.xcen)
+size(bbox.ycen)
+size(bbox.expected_id)
+size(bbox.found_id)
+size(fed.hklsp)
+
+if size(fed.omega,1)~=size(bbox.omega,1)
+    return
+end
+% table to compare fed results with database 
+table=int32([fed.omega bbox.omega ...
+             fed.uvfed(:,1) bbox.xcen ...
+             fed.uvfed(:,2) bbox.ycen ...
+             bbox.expected_id bbox.found_id ...
+             fed.hklsp]);
+newgr.table=table;
+nonzero=find(table(:,2)~=0);
+newgr.ind=nonzero;
+
+%newgr.ind=find(bbox.expected_id~=0);
+
+end % end function
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+function list=findDifspots(list1,list2,name)
+
+
+[rows,ia,ib,neq,dif]=findDifferentRowIntoMatrix(list1,list2);
+
+dif(find(dif(:,1)==0),:)=[];
+list.ind=dif(:,2)';
+list.ID=dif(:,1)';
+
+for j=1:size(dif(:,1),1)
+    mysqlcmd=sprintf(['select grainID, CentroidX, CentroidY, CentroidImage, Integral, '...
+        'BoundingBoxXorigin, BoundingBoxYorigin, BoundingBoxXsize, BoundingBoxYsize, Area from %sdifspot where difspotID=%d'],...
+        name, dif(j,1));
+    
+    [grainID, CentroidX, CentroidY, CentroidImage, Integral, BoundingBoxXorigin, BoundingBoxYorigin, BoundingBoxXsize, BoundingBoxYsize, Area]=mym(mysqlcmd);
+    
+    if ~isempty(BoundingBoxXorigin)
+        list.x0(j)=BoundingBoxXorigin;
+        list.y0(j)=BoundingBoxYorigin;
+        list.xsize(j)=BoundingBoxXsize;
+        list.ysize(j)=BoundingBoxYsize;
+        list.xcen(j)=CentroidX;
+        list.ycen(j)=CentroidY;
+        list.image(j)=CentroidImage;
+        list.int(j)=Integral;
+        list.area(j)=Area;
+        list.grainid(j)=grainID;
+    end
+end
+
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
diff --git a/zUtil_Optimization/gtOptimizeVertical.m b/zUtil_Optimization/gtOptimizeVertical.m
new file mode 100644
index 0000000000000000000000000000000000000000..37ffe174729f3045fd8aeec64db5e46885d7ce75
--- /dev/null
+++ b/zUtil_Optimization/gtOptimizeVertical.m
@@ -0,0 +1,79 @@
+function [newgeo,bbox,full_all,gr]=gtOptimizeVertical(grain,parameters,bbxsizemean,areamin,areamax,color,greys,save)
+% [newgeo,bbox,full_all,gr]=gtOptimizeVertical(grain,parameters,bbxsizemean,areamin,areamax,[color],[greys],[save])
+%
+% INPUT:
+%             grain = grain{grainid}
+%        parameters = parameters file
+%       bbxsizemean = discrepancy between fed u,v and spot centroid u,v
+%                     | difspot.CentroidX - u | < 0.5 * bbxsizemean
+%                     | difspot.CentroidY - v | < 0.5 * bbxsizemean
+%   areamin/areamax = Area < areamax & Area > areamin
+%             color = color of predicted u,v points
+%             greys = grey scale
+%              save = true if saving 
+%
+% OUTPUT:
+%     newgeo = optimized geometry
+%       bbox = structure with information from the database and from fed
+%   full_all = image with spots
+%         gr = grain updated structure
+
+if nargin < 5
+    disp('Usage: gtOptimizeVertical(grain,parameters,bbxsizemean,areamin,areamax,[color],[greys],[save])')
+    return
+end
+if isempty(color)
+    color='b';
+end
+if isempty(greys)
+    greys=[];
+end
+if ~exist('save','var') || isempty(save)
+    save=false;
+end
+
+
+gr=gtFedGenerateRandomGrain2(grain,zeros(parameters.acq.xdet),parameters,'save',save);
+uv=gr.allblobs.uv;
+omega=gr.allblobs.omega;
+
+% find spots' indexes intersecting the detector
+[uvdet,inddet]=findOnDet(uv);
+omegadet=omega(inddet);
+length(uv)
+
+% search in the database
+bbox=findSpotsWoIndexter(parameters,uvdet,omegadet,bbxsizemean,areamin,areamax);
+length(bbox.feduv)
+
+% place spots in the image (figure not shown)
+full_all=gtPlaceDifspotinFull_ln(bbox.expected_id,parameters,'save',save,'connected',true);
+
+% plot the spots using the current geometry
+tmp=gtPlotUVW(full_all,bbox.feduv,'b',parameters.acq,greys,sprintf('Before optimization : |x-u| < %2.0f : area [%d %d]',bbxsizemean*0.5,areamin,areamax),false);
+
+% get the indexes of spots found in the database from the full uv list
+[r,ia,ib,d]=findRowIntoMatrix(uv,bbox.feduv);
+[r2,ia2,ib2,d2]=findRowIntoMatrix(uv(ia,:),bbox.feduv);
+ind=sortrows([ib2 ia]);
+indsorted=ind(:,2);
+bbox.indsorted=indsorted;
+
+% optimize detector
+newgeo=gtTuneDetector3(parameters.acq,gr,bbox.dbuv,indsorted);
+
+disp('detdiru0: ')
+disp(newgeo.detdiru0)
+disp('detdirv0: ')
+disp(newgeo.detdirv0)
+
+% plot the spots positions with the optimized geometry
+tmp2=gtPlotUVW(full_all,newgeo.Fnew(:,1:2),color,newgeo,greys,sprintf('After optimization : blue [bbox.dbuv] %s [bbox.feduv]',color),true);
+hold on
+for i=1:length(bbox.dbuv)
+    plot(bbox.dbuv(i,1),bbox.dbuv(i,2),'g.','MarkerSize',20)
+end
+
+
+end
+
diff --git a/zUtil_Optimization/gtPlotUVW.m b/zUtil_Optimization/gtPlotUVW.m
new file mode 100644
index 0000000000000000000000000000000000000000..7f12b1d64ede1e113e8e6c8c56e636a74b5a633d
--- /dev/null
+++ b/zUtil_Optimization/gtPlotUVW.m
@@ -0,0 +1,141 @@
+function noiseuv=gtPlotUVW(im,uv,color,geo,scale,titlename,debug,noise,numnoise)
+% noiseuv=gtPlotUVW(im,uv,color,geo,titlename,debug,noise,numnoise)
+% 
+% INPUT:
+%           im = output from gtPlaceDifspotsinfull <double 2048x2048>
+%           uv = u,v list to plot <double Nx2>
+%        color = color to be used in the plot <char 1x1>
+%          geo = output from gtTuneDetector3
+%        scale = gray scaled from -100 to 400
+%    titlename = title name <string 1x1>
+%        debug = print comments or info <logical 1x1> {0}
+%        noise = number of pixels noise <int8 1x1 {2}>
+%     numnoise = percentage of noised spots <double 1x1 {}>
+% 
+% OUTPUT:
+%      noiseuv = list u,v noised
+
+figure
+if ~isempty(im)
+    if ~isempty(scale) 
+        imshow(im,scale)
+    else
+        imshow(im,[])
+    end
+    hold on
+end
+
+if ~exist('titlename','var') || isempty(titlename)
+    titlename='';
+end
+
+if ~exist('debug','var') || isempty(debug)
+    debug=false;
+end
+if ~exist('noise','var') || isempty(noise)
+    noise=2;
+end
+if ~exist('numnoise','var') || isempty(numnoise)
+    numnoise=[];
+end
+
+N=size(uv,1);
+
+detusize=2048;
+detvsize=2048;
+uvorig=[1024.5;1024.5];
+beamdir=geo.beamdir0';
+detdiru=geo.detdiru0';
+detdirv=geo.detdirv0';
+detdir=cross(detdiru,detdirv);
+detpos=geo.detpos0; % mm
+
+if isfield(geo,'Xzero')
+    olddiru=geo.Xzero(1:3);
+    olddirv=geo.Xzero(4:6);
+    oldpos=geo.Xzero(7:9).*geo.pixelsize; % mm
+else
+   olddiru=detdiru;
+   olddirv=detdirv;
+   oldpos=geo.detpos0;%.*geo.pixelsize
+end
+
+
+% Image frame
+plot([0 detusize+1],[0 0],'k')
+plot([0 detusize+1],[detvsize+1 detvsize+1],'k')
+plot([0 0],[0 detvsize+1],'k')
+plot([detusize+1 detusize+1],[0 detvsize+1],'k')
+
+%% Midlines
+plot([0 detusize+1],[detvsize/2+0.5 detvsize/2+0.5],'-.y','Linewidth',1)
+plot([detusize/2+0.5 detusize/2+0.5],[0 detvsize+1],'-.y','Linewidth',1)
+
+Qdet = gtFedDetectorProjectionTensor(detdiru,detdirv,1,1);
+
+%% Beam direction in image
+beamuv = Qdet*beamdir;
+% Arrow in figure indicating beam direction
+
+if (dot(beamdir,detdir)-1)<0.001 % // 1
+    plot(uvorig(1),uvorig(2),'.w','MarkerSize',20)
+elseif (dot(beamdir,detdir)+1)<0.001 % // -1
+    plot(uvorig(1),uvorig(2),'xw','MarkerSize',20)
+else
+    quiver(uvorig(1),uvorig(2),beamuv(1),beamuv(2),1000,'-w','Linewidth',2)
+end
+impixelinfo
+
+%% origin u,v
+plot(0,0,'.y','MarkerSize',20)
+plot(0,0,'oy','MarkerSize',10)
+
+% unit vectors u,v
+quiver(0,0,0,1,150,'-y','Linewidth',2)
+quiver(0,0,1,0,150,'-y','Linewidth',2)
+
+%% center displacement
+shift=oldpos-detpos;
+newcenu=uvorig(1)+dot(shift,olddiru)./geo.pixelsize;
+newcenv=uvorig(2)+dot(shift,olddirv)./geo.pixelsize;
+plot(newcenu,newcenv,'+y','MarkerSize',20)
+
+
+for i=1:N
+    plot(uv(i,1),uv(i,2),['o' color],'MarkerSize',10)
+end
+
+% title
+title(titlename)
+
+
+%% noise
+
+if ~isempty(numnoise)
+    
+    rnoise=(rand(N,size(uv,2))-0.5)*noise*2;
+    ind=randperm(N);
+    color=rand(1,3);
+    newuv(ind,:)=rnoise(ind,:)+uv(ind,:);
+    plot(newuv(ind,1),newuv(ind,2),['o' color],'MarkerSize',10)
+    noiseuv=newuv;
+
+else
+    noiseuv=uv;
+end
+
+
+if debug
+    disp('detpos:')
+    disp(detpos)
+    disp('oldpos:')
+    disp(oldpos)
+    disp('shift:')
+    disp(shift)
+    disp('beamuv:')
+    disp(beamuv)
+end
+
+end
+    
+    
\ No newline at end of file
diff --git a/zUtil_Optimization/gtTuneDetector3.m b/zUtil_Optimization/gtTuneDetector3.m
new file mode 100644
index 0000000000000000000000000000000000000000..caa805c30b4dc831fece6aee3b8fe8818d1ce32a
--- /dev/null
+++ b/zUtil_Optimization/gtTuneDetector3.m
@@ -0,0 +1,200 @@
+function newgeo=gtTuneDetector3(geometry,grainFed,uvdb,induv,debug,varargin)
+%% newgeo=gtTuneDetector3(geometry,grainFed,uvdb,induv,debug,varargin)
+%    INPUT:
+%      grainFed = output from gtFedGenerateRandomGrain2
+%      geometry = output from gtOptimizeDetector
+%          uvdb = uv from database
+%         induv = indexes of uvdb to be used from the full list of
+%                 grainFed.allblobs.uv
+%         debug = print comments
+%      varargin = optional arguments for options
+%                 options = optimset(varargin);
+%                 DEFAULT: options =
+%                 optimset('TolFun',1e-2,'MaxFunEvals',3000,'MaxIter',700)
+%
+%    OUTPUT:
+%      newgeo = new geometry 
+%
+%
+% OPTIMSET PARAMETERS for MATLAB
+%     Display - Level of display [ off | iter | notify | final ]
+%     MaxFunEvals - Maximum number of function evaluations allowed
+%                          [ positive integer ]
+%     MaxIter - Maximum number of iterations allowed [ positive scalar ]
+%     TolFun - Termination tolerance on the function value [ positive scalar ]
+%     TolX - Termination tolerance on X [ positive scalar ]
+%     FunValCheck - Check for invalid values, such as NaN or complex, from 
+%                   user-supplied functions [ {off} | on ]
+%     OutputFcn - Name(s) of output function [ {[]} | function ] 
+%               All output functions are called by the solver after each
+%               iteration.
+%     PlotFcns - Name(s) of plot function [ {[]} | function ]
+%               Function(s) used to plot various quantities in every iteration
+%
+
+tic
+disp('Start gtTuneDetector3...')
+
+if ~exist('debug','var') || isempty(debug)
+   debug=false; 
+end
+
+%% get info from newgr and grainFed
+newgeo=geometry;
+
+pixelsize = geometry.pixelsize;
+detdiru = geometry.detdiru0;
+detdirv = geometry.detdirv0;
+detpos  = geometry.detpos0
+check=inputwdefault('Is the detpos correct (unit length must be mm)? y/n','y');
+if strcmpi(check,'n')
+    detpos=input('Insert the right value of detpos between []: ');
+else
+    
+end
+detpos=detpos./pixelsize;
+uvorig  = [geometry.detucen0, geometry.detvcen0]';
+omstep  = 180/geometry.nproj;
+pixelsize = geometry.pixelsize;
+
+if ~isfield(geometry,'detdir0')
+    detdir = cross(detdiru,detdirv);
+else
+    detdir = geometry.detdir0;
+end
+
+if dot(detdiru,detdirv)>1e-4
+    disp('u,v are not perpendicular. Quitting...')
+    return
+end
+
+% grain.allblobs.[variable]
+srot  = grainFed.allblobs.srot;
+dvec  = grainFed.allblobs.dvec;
+omega = grainFed.allblobs.omega;
+csam  = grainFed.center';
+
+uvwfed = grainFed.allblobs.uvw;
+
+%% method minimum squares
+
+% parameters for lsqcurvefit
+% ux uy uz vx vy vz dx dy dz
+X0=[detdiru detdirv detpos];
+
+% avoid NAN difspot entries
+% % ind=find(~isnan(uvwfed(:,1))); % empty u coord.
+% % dvec=dvec(ind,:);
+% % omega=omega(ind,:);
+% % uvwfed=uvwfed(ind,:);
+
+% apply induv to the lists with size (Nx3,1)
+dvec=dvec(induv,:);
+omega=omega(induv,:);
+
+pippo=[];
+for i=1:size(dvec,1)
+    j=induv(i);% was ind(i)
+    pippo=[pippo;srot(j*3-2:j*3,:)];
+end
+srot=pippo;
+
+%srot=srot(induv,:);
+
+xdata=[srot;dvec];
+ydata=uvdb; % uv coordinates found in the database (Nx2)
+
+
+if debug
+    size(srot)
+    size(dvec)
+    size(omega)
+    size(xdata)
+    size(ydata)
+end
+
+newgeo.uvwfed=uvwfed;
+newgeo.Xzero=X0;
+
+% calculate the old uvw coordinates from the current geometry
+[Fzero,Mzero] = gtFindUVW3(X0,xdata,csam,uvorig);
+Fzero(:,3)=mod(omega,360)/omstep;
+newgeo.Fzero=Fzero;
+% current detector reference system
+newgeo.Mzero=Mzero;
+
+% comparison between f(x,xdata) and ydata
+% min sum [(f(x,xdata,par)-ydata)^2]
+%  x
+%
+% input: X0    = the current geometry parameters 1x12
+%        xdata = (Nx4,3) list from [srot;dvec]
+%        ydata = [bbox.xcen,bbox.ycen]
+%        par   = list of constants in the function (csam, detpos)
+%
+% output: X    = the optimized geometry parameters from lsq
+
+
+% change some options for the fit
+if ~exist('varargin','var')|| isempty(varargin)
+    options = optimset('TolFun',1e-2,'MaxFunEvals',3000,'MaxIter',700);
+else
+    options = optimset(varargin);
+end
+
+disp('Start fitting...')
+f = @(x,xdata) gtFindUVW3(x,xdata,csam,uvorig);
+UB=[];
+LB=[];
+[X,a,b,c,d,e,f] = lsqcurvefit(f,X0,xdata,ydata,[],[],options);
+
+% calculate the new uvw (F) values with the optimized geometry (X)
+[F,M,Xnew] = gtFindUVW3(X,xdata,csam,uvorig);
+F(:,3)=mod(omega,360)/omstep;
+newgeo.X = X;
+newgeo.F = F;
+newgeo.M = M;
+% recalculate uvw (Fnew) with the orthonormal axes (Xnew)
+
+[Fnew,Mnew] = gtFindUVW3(Xnew,xdata,csam,uvorig);
+Fnew(:,3)=mod(omega,360)/omstep;
+
+newgeo.Xnew=Xnew;
+newgeo.Fnew=Fnew;
+% new detector reference system
+newgeo.Mnew=Mnew;
+
+% calculate the dot products
+newgeo.dotuv=dot(Mnew(1,:),Mnew(2,:));
+newgeo.dotut=dot(Mnew(1,:),Mnew(3,:));
+newgeo.dotvt=dot(Mnew(2,:),Mnew(3,:));
+
+% get the new geometry
+newgeo.detdiru0=Mnew(1,:);
+newgeo.detdirv0=Mnew(2,:);
+newpos=Xnew(7:9).*pixelsize
+check=inputwdefault('Must the detpos be reconverted into mm? y/n','n');
+if strcmpi(check,'y')
+    newpos=newpos.*pixelsize;
+end
+newgeo.detdir0=Mnew(3,:);
+
+% new center
+oldpos=X0(7:9).*pixelsize;
+newgeo.detpos0=newpos;
+olddiru=X0(1:3);
+olddirv=X0(4:6);
+shift=oldpos-newpos;
+newcenu=uvorig(1)+dot(shift,olddiru)./pixelsize;
+newcenv=uvorig(2)+dot(shift,olddirv)./pixelsize;
+
+newgeo.newdetucen0=newcenu;
+newgeo.newdetvcen0=newcenv;
+newgeo.dist=norm(newpos);
+
+toc
+
+
+
+
+end % end function
\ No newline at end of file