diff --git a/Software/AutomatedMeasurements/ElectronicMonkeyFocusing.py b/Software/AutomatedMeasurements/ElectronicMonkeyFocusing.py index 98c3063..e24f7b3 100644 --- a/Software/AutomatedMeasurements/ElectronicMonkeyFocusing.py +++ b/Software/AutomatedMeasurements/ElectronicMonkeyFocusing.py @@ -4,7 +4,9 @@ Date: January 5th, 2015 Description: -Automated measurement for focusing. After the measurement, the position of the laser along x and z is reset. +Automated measurement for focusing. +The script moves the laser to the starting position along x and z and then takes care of the data acquisitions with the Alibava system. +After the measurement, the position of the laser along x and z is reset. Parameters: - , the first x position; @@ -87,12 +89,31 @@ # Find Arduino. ser = serial.Serial('/dev/ttyACM0',9600) +# Move the laser to the starting position along x and z. +print 'Move the laser to the starting position along x and z.' +# +10 if firstx is positive, +20 if firstx is negative, firstx times. +for xcounter in range(abs(firstx)) : + print 'Step along x %i of %i' % (xcounter,firstx) + if (firstx > 0) : + ser.write('+10') + elif (firstx < 0) : + ser.write('+20') + time.sleep(1) +# +01 if firstz is positive, +02 if firstz is negative, firstz times. +for zcounter in range(abs(firstz)) : + print 'Step along z %i of %i' % (zcounter,firstz) + if (firstz > 0) : + ser.write('+01') + elif (firstz < 0) : + ser.write('+02') + time.sleep(1) + # Perform the measurement. for posz in range(firstz,lastz+stepz,stepz) : for posx in range(firstx,lastx+stepx,stepx) : print 'Position along x: %i steps' % posx print 'Position along z: %i steps' % posz - filename = folder+"/Hans410/Test/"+str(yyyymmdd)+"-216-"+str(posx)+"x-"+str(posz)+"z-las.ali" + filename = folder+"/Hans410/Alignment/"+str(yyyymmdd)+"-216-"+str(posx)+"x-"+str(posz)+"z-las.ali" printcommand = "echo alibava-gui --no-gui --nevts="+str(nevents)+" --out="+filename+" --laser "+config command = "alibava-gui --no-gui --nevts="+str(nevents)+" --out="+filename+" --laser "+config print '***' @@ -126,4 +147,23 @@ time.sleep(2) print '***' +# Move the laser to the starting position along x and z. +print 'Move the laser to the starting position along x and z.' +# +20 if firstx is positive, +10 if firstx is negative, firstx times. +for xcounter in range(abs(firstx)) : + print 'Step along x %i of %i' % (xcounter,firstx) + if (firstx > 0) : + ser.write('+20') + elif (firstx < 0) : + ser.write('+10') + time.sleep(1) +# +02 if firstz is positive, +01 if firstz is negative, firstz times. +for zcounter in range(abs(firstz)) : + print 'Step along z %i of %i' % (zcounter,firstz) + if (firstz > 0) : + ser.write('+02') + elif (firstz < 0) : + ser.write('+01') + time.sleep(1) + print 'End of the measurement!' diff --git a/Software/Focusing/Focusing.C b/Software/Focusing/Focusing.C index 5790df2..9ff6485 100644 --- a/Software/Focusing/Focusing.C +++ b/Software/Focusing/Focusing.C @@ -5,7 +5,10 @@ /* Focusing reads all the ROOT files of a given focusing data taking and calculates the z coordinate of the focus. -For each z position, it fits the s-curve with two erf functions, one for the left side and one for the right side, and returns the mu and sigma, that will be used to determine the focus. +For each z position, it fits the s-curve with two erf functions, one for the left side and one for the right side, and returns the mu and sigma, that will be used to calculate the z coordinate of the focus. The starting values and the limits of the parameters of the two erf functions are set according to the filename of the measurement, by using the "assignParInfo" procedure. +The mu and sigma as a function of the z position are fitted by the functions +mu = p0+p1*z and sigma = q0*|z-q1|+q2, respectively, and the values returned by the fit are printed out on the screen. +Knowing p1, the angle alpha = arctan(p1) between the laser and the normal to the surface of the sensor is also determined. Its uncertainty is calculated from its derivative, which is a good estimate for the moment, but not fully correct. The focusing data taking is identified by the following information: - , that is, the type of sensor (Hans410, ...); @@ -46,6 +49,10 @@ Double_t fLeft(Double_t *x, Double_t *par); Double_t fRight(Double_t *x, Double_t *par); +Double_t fSigma(Double_t *x, Double_t *par); + +void assignParInfo(string filename, Float_t zvalue, Float_t *minRight, Float_t *maxRight, Float_t *minLeft, Float_t *maxLeft, Float_t par[], Int_t length); + int main(int argc, char *argv[]) { getLHCbStyle(); @@ -55,7 +62,40 @@ { cout << "**************************************************" << endl; - cout << "Some comments." << endl; + cout << "Focusing reads all the ROOT files of a given focusing data taking and calculates the z coordinate of the focus." << endl; + cout << "For each z position, it fits the s-curve with two erf functions, one for the left side and one for the right side, and returns the mu and sigma, that will be used to calculate the z coordinate of the focus. The starting values and the limits of the parameters of the two erf functions are set according to the filename of the measurement, by using the 'assignParInfo' procedure." << endl; + cout << "The mu and sigma as a function of the z position are fitted by the functions mu = p0+p1*z and sigma = q0*|z-q1|+q2, respectively, and the values returned by the fit are printed out on the screen." << endl; + cout << "Knowing p1, the angle alpha = arctan(p1) between the laser and the normal to the surface of the sensor is also determined. Its uncertainty is calculated from its derivative, which is a good estimate for the moment, but not fully correct." << endl; + + cout << "**************************************************" << endl; + + cout << "The focusing data taking is identified by the following information:" << endl; + cout << "- , that is, the type of sensor (Hans410, ...);" << endl; + cout << "- , that is, the filename excluding the position value and the run type." << endl; + cout << "- , that is, the first position along x;" << endl; + cout << "- , that is, the last position along x;" << endl; + cout << "- , that is, the step between two subsequent data acquisitions in x (1 step = 5 microns);" << endl; + cout << "- , that is, the first position along z;" << endl; + cout << "- , that is, the last position along z;" << endl; + cout << "- , that is, the step between two subsequent data acquisitions in z (1 step = 5 microns)." << endl; + + cout << "**************************************************" << endl; + + cout << "Compile with:" << endl; + + cout << "make" << endl; + + cout << "Run with:" << endl; + + cout << "./Focusing [sensor] [filename] [firstx] [lastx] [stepx] [firstz] [lastz] [stepz] [additional folder]" << endl; + + cout << "For example:" << endl; + + cout << "./Focusing Hans410 ProcessRawData-20141219 0 50 2 -400 -200 20" << endl; + + cout << "A folder named AnalysisResults will be created in a fixed location and a ROOT file will be saved in there. A folder named Figures will be created inside the folder named AnalysisResults, with some monitoring plots." << endl; + + cout << "If needed, an additional folder can be specified, that will be created inside the folder named AnalysisResults." << endl; cout << "**************************************************" << endl; @@ -161,12 +201,33 @@ const Int_t stepsz = (Int_t)((lastz-firstz)/stepz+1); Float_t z[stepsz]; + Float_t uz[stepsz]; + + for (int i=0;iSetParameter(0,100.); - fitRight->SetParameter(1,80.); - fitRight->SetParameter(2,10.); - fitRight->SetParameter(3,200.); - fitRight->SetParLimits(1,60.,100.); - fitRight->SetParLimits(2,0.,20.); + fitRight->SetParameter(0,par[0]); + fitRight->SetParameter(1,par[1]); + fitRight->SetParameter(2,par[2]); + fitRight->SetParameter(3,par[3]); + fitRight->SetParLimits(0,par[4],par[5]); + fitRight->SetParLimits(1,par[6],par[7]); + fitRight->SetParLimits(2,par[8],par[9]); + fitRight->SetParLimits(3,par[10],par[11]); gcheckAlignment4[zcounter]->Fit(fitRight,"BR"); + aRight[zcounter] = fitRight->GetParameter(0); muRight[zcounter] = fitRight->GetParameter(1); sigmaRight[zcounter] = fitRight->GetParameter(2); - cout << "Right side, z = " << zcounter << ", mu = " << muRight[zcounter] << ", sigma = " << sigmaRight[zcounter] << endl; + bRight[zcounter] = fitRight->GetParameter(3); + uaRight[zcounter] = fitRight->GetParError(0); + umuRight[zcounter] = fitRight->GetParError(1); + usigmaRight[zcounter] = fitRight->GetParError(2); + ubRight[zcounter] = fitRight->GetParError(3); - // Left side. - Float_t minLeft = 140.; - Float_t maxLeft = 240.; + cout << "Right side, z = " << zcounter << ", a = " << aRight[zcounter] << ", mu = " << muRight[zcounter] << ", sigma = " << sigmaRight[zcounter] << ", b = " << bRight[zcounter] << endl; + + // Left side (decreasing y). TF1 *fitLeft = new TF1("fitLeft",fLeft,minLeft,maxLeft,4); - fitLeft->SetParameter(0,100.); - fitLeft->SetParameter(1,210.); - fitLeft->SetParameter(2,10.); - fitLeft->SetParameter(3,200.); - fitLeft->SetParLimits(1,200.,240.); - fitLeft->SetParLimits(2,0.,20.); + fitLeft->SetParameter(0,par[12]); + fitLeft->SetParameter(1,par[13]); + fitLeft->SetParameter(2,par[14]); + fitLeft->SetParameter(3,par[15]); + // fitLeft->SetParLimits(0,90.,170.); + fitLeft->SetParLimits(1,par[18],par[19]); + fitLeft->SetParLimits(2,par[20],par[21]); + // fitLeft->SetParLimits(3,150.,220.); gcheckAlignment4[zcounter]->Fit(fitLeft,"BR"); + aLeft[zcounter] = fitLeft->GetParameter(0); muLeft[zcounter] = fitLeft->GetParameter(1); sigmaLeft[zcounter] = fitLeft->GetParameter(2); - cout << "Left side, z = " << zcounter << ", mu = " << muLeft[zcounter] << ", sigma = " << sigmaLeft[zcounter] << endl; + bLeft[zcounter] = fitLeft->GetParameter(3); + + uaLeft[zcounter] = fitLeft->GetParError(0); + umuLeft[zcounter] = fitLeft->GetParError(1); + usigmaLeft[zcounter] = fitLeft->GetParError(2); + ubLeft[zcounter] = fitLeft->GetParError(3); + + cout << "Left side, z = " << zcounter << ", a = " << aLeft[zcounter] << ", mu = " << muLeft[zcounter] << ", sigma = " << sigmaLeft[zcounter] << ", b = " << bLeft[zcounter] << endl; @@ -289,30 +380,184 @@ - for (Int_t zcounter=0;zcounterGetXaxis()->SetLimits(z[0]-100.,z[stepsz-1]+100.); - TGraph *gmuRight = new TGraph(stepsz,z,muRight); - InitGraph(gmuRight,"Focusing - right side","z (#mum)","#mu_{right}"); + TF1 *fitMuLeft = new TF1("fitMuLeft","pol1",minMu,maxMu); + fitMuLeft->SetLineColor(kRed); + gmuLeft->Fit(fitMuLeft,"BR"); + + p0Left = fitMuLeft->GetParameter(0); + up0Left = fitMuLeft->GetParError(0); + p1Left = fitMuLeft->GetParameter(1); + up1Left = fitMuLeft->GetParError(1); + + alphaLeft = atan(p1Left); + ualphaLeft = up1Left/(1+p1Left*p1Left); + + DrawGraphErrors(cmuLeft,gmuLeft,"AP",path_to_figures); + + // Mu - right edge. + TGraphErrors *gmuRight = new TGraphErrors(stepsz,z,muRight,uz,umuRight); + InitGraphErrors(gmuRight,"Focusing - right side","z (#mum)","#mu_{right}"); TCanvas *cmuRight = new TCanvas("cmuRight","",400,300); - DrawGraph(cmuRight,gmuRight,"AP",path_to_figures); + gmuRight->GetXaxis()->SetLimits(z[0]-100.,z[stepsz-1]+100.); - // Sigma. - TGraph *gsigmaLeft = new TGraph(stepsz,z,sigmaLeft); - InitGraph(gsigmaLeft,"Focusing - left side","z (#mum)","#sigma_{left}"); + TF1 *fitMuRight = new TF1("fitMuRight","pol1",minMu,maxMu); + fitMuRight->SetLineColor(kRed); + gmuRight->Fit(fitMuRight,"BR"); + + p0Right = fitMuRight->GetParameter(0); + up0Right = fitMuRight->GetParError(0); + p1Right = fitMuRight->GetParameter(1); + up1Right = fitMuRight->GetParError(1); + + alphaRight = atan(p1Right); + ualphaRight = up1Right/(1+p1Right*p1Right); + + DrawGraphErrors(cmuRight,gmuRight,"AP",path_to_figures); + + // Sigma - parameters. + // y = p0*|x-p1|+p2, with x = z position (microns) and y = sigma (microns). + Float_t q0Left; + Float_t uq0Left; + Float_t q1Left; + Float_t uq1Left; + Float_t q2Left; + Float_t uq2Left; + + Float_t q0Right; + Float_t uq0Right; + Float_t q1Right; + Float_t uq1Right; + Float_t q2Right; + Float_t uq2Right; + + // Sigma - range. + Float_t minSigma = z[0]; + Float_t maxSigma = z[stepsz-1]; + + // Sigma - left edge. + TGraphErrors *gsigmaLeft = new TGraphErrors(stepsz,z,sigmaLeft,uz,usigmaLeft); + InitGraphErrors(gsigmaLeft,"Focusing - left side","z (#mum)","#sigma_{left}"); TCanvas *csigmaLeft = new TCanvas("csigmaLeft","",400,300); - DrawGraph(csigmaLeft,gsigmaLeft,"AP",path_to_figures); + gsigmaLeft->GetXaxis()->SetLimits(z[0]-100.,z[stepsz-1]+100.); - TGraph *gsigmaRight = new TGraph(stepsz,z,sigmaRight); - InitGraph(gsigmaRight,"Focusing - right side","z (#mum)","#sigma_{right}"); + TF1 *fitSigmaLeft = new TF1("fitSigmaLeft",fSigma,minSigma,maxSigma,3); + fitSigmaLeft->SetParameter(0,5.); + fitSigmaLeft->SetParameter(1,600.); + fitSigmaLeft->SetParameter(2,0.025); + fitSigmaLeft->SetParLimits(0,0.,10.); + fitSigmaLeft->SetParLimits(1,500.,700.); + // fitSigmaLeft->SetParLimits(2,.,.); + fitSigmaLeft->SetLineColor(kRed); + gsigmaLeft->Fit(fitSigmaLeft,"BR"); + + q0Left = fitSigmaLeft->GetParameter(0); + uq0Left = fitSigmaLeft->GetParError(0); + q1Left = fitSigmaLeft->GetParameter(1); + uq1Left = fitSigmaLeft->GetParError(1); + q2Left = fitSigmaLeft->GetParameter(2); + uq2Left = fitSigmaLeft->GetParError(2); + + DrawGraphErrors(csigmaLeft,gsigmaLeft,"AP",path_to_figures); + + // Sigma - right edge. + TGraphErrors *gsigmaRight = new TGraphErrors(stepsz,z,sigmaRight,uz,usigmaRight); + InitGraphErrors(gsigmaRight,"Focusing - right side","z (#mum)","#sigma_{right}"); TCanvas *csigmaRight = new TCanvas("csigmaRight","",400,300); - DrawGraph(csigmaRight,gsigmaRight,"AP",path_to_figures); + gsigmaRight->GetXaxis()->SetLimits(z[0]-100.,z[stepsz-1]+100.); + + TF1 *fitSigmaRight = new TF1("fitSigmaRight",fSigma,minSigma,maxSigma,3); + fitSigmaRight->SetParameter(0,5.); + fitSigmaRight->SetParameter(1,600.); + fitSigmaRight->SetParameter(2,0.025); + fitSigmaRight->SetParLimits(0,0.,10.); + fitSigmaRight->SetParLimits(1,500.,700.); + // fitSigmaRight->SetParLimits(2,.,.); + fitSigmaRight->SetLineColor(kRed); + gsigmaRight->Fit(fitSigmaRight,"BR"); + + q0Right = fitSigmaRight->GetParameter(0); + uq0Right = fitSigmaRight->GetParError(0); + q1Right = fitSigmaRight->GetParameter(1); + uq1Right = fitSigmaRight->GetParError(1); + q2Right = fitSigmaRight->GetParameter(2); + uq2Right = fitSigmaRight->GetParError(2); + + DrawGraphErrors(csigmaRight,gsigmaRight,"AP",path_to_figures); + + + + // Print parameters. + cout << "**********************************" << endl; + + cout << "Fit results - left edge" << endl; + + cout << "" << endl; + + cout << "mu = p0+p1*z, with:" << endl; + cout << "- p0 = (" << p0Left << " p/m " << up0Left << ") microns" << endl; + cout << "- p1 = " << p1Left << " p/m " << up1Left << endl; + cout << "Angle with respect to the normal: (" << alphaLeft << " p/m " << ualphaLeft << ") rad" << endl; + + cout << "" << endl; + + cout << "sigma = q0*|z-q1|+q2, with:" << endl; + cout << "- q0 = " << q0Left << " p/m " << uq0Left << endl; + cout << "- q1 = (" << q1Left << " p/m " << uq1Left << ") microns ---> position of the focus along z" << endl; + cout << "- q2 = (" << q2Left << " p/m " << uq2Left << ") microns ---> minimum sigma" << endl; + + cout << "" << endl; + + cout << "Fit results - right edge" << endl; + cout << "mu = p0+p1*z, with:" << endl; + cout << "- p0 = (" << p0Right << " p/m " << up0Right << ") microns" << endl; + cout << "- p1 = " << p1Right << " p/m " << up1Right << endl; + cout << "Angle with respect to the normal: (" << alphaRight << " p/m " << ualphaRight << ") rad" << endl; + + cout << "" << endl; + + cout << "sigma = q0*|z-q1|+q2, with:" << endl; + cout << "- q0 = " << q0Right << " p/m " << uq0Right << endl; + cout << "- q1 = (" << q1Right << " p/m " << uq1Right << ") microns ---> position of the focus along z" << endl; + cout << "- q2 = (" << q2Right << " p/m " << uq2Right << ") microns ---> minimum sigma" << endl; + + cout << "**********************************" << endl; @@ -325,14 +570,237 @@ return; } -// fLeft has four parameters. +// fLeft has four parameters: +// - par[0] is the y-spread around the middle of the curve; +// - par[1] is the x-coordinate of the middle of the curve; +// - par[2] is the steepness of the curve; +// - par[3] is the y-coordinate of the middle of the curve. Double_t fLeft(Double_t *x, Double_t *par) { return par[0]*(1.-erf((x[0]-par[1])/(sqrt(2.)*par[2])))+par[3]; } -// fRight has four parameters. +// fRight has four parameters: +// - par[0] is the y-spread around the middle of the curve; +// - par[1] is the x-coordinate of the middle of the curve; +// - par[2] is the steepness of the curve; +// - par[3] is the y-coordinate of the middle of the curve. Double_t fRight(Double_t *x, Double_t *par) { return par[0]*erf((x[0]-par[1])/(sqrt(2.)*par[2]))+par[3]; } + +// fSigma is used to fit the sigma as a function of the z position and has three parameters: +// - par[0] is is angular coefficient of the two straight lines; +// - par[1] is the x-coordinate of the lowest point; +// - par[2] is the y-coordinate of the lowest point. +Double_t fSigma(Double_t *x, Double_t *par) +{ + return par[0]*abs(x[0]-par[1])+par[2]; +} + +void assignParInfo(string filename, Float_t zvalue, Float_t *minRight, Float_t *maxRight, Float_t *minLeft, Float_t *maxLeft, Float_t par[], Int_t length) +{ + if (filename == "ProcessRawData-201501093-216") { + // Right. + if (zvalue < 120.) + { + *minRight = 70.; + *maxRight = 180.; + } + else + { + *minRight = 60.; + *maxRight = 140.; + } + + // Left. + if (zvalue < 40.) + { + *minLeft = 180.; + *maxLeft = 280.; + } + else if (zvalue < 120.) + { + *minLeft = 180.; + *maxLeft = 270.; + } + else + { + *minLeft = 180.; + *maxLeft = 260.; + } + + // Right. + if (zvalue < 120.) + par[0] = 125.; + else + par[0] = 140.; + par[1] = 95.; + par[2] = 10.; + par[3] = 200.; + + par[4] = 90.; + par[5] = 170.; + par[6] = 70.; + par[7] = 120.; + par[8] = 3.; + par[9] = 20.; + par[10] = 150.; + par[11] = 220.; + + // Left. + if (zvalue < 120.) + par[12] = 125.; + else + par[12] = 140.; + par[13] = 230.; + par[14] = 10.; + par[15] = 200.; + + // fitLeft->SetParLimits(0,90.,170.); + par[18] = 215.; + par[19] = 250.; + par[20] = 3.; + par[21] = 20.; + // fitLeft->SetParLimits(3,150.,220.); + } + + // It does not look very nice. + else if (filename == "ProcessRawData-20150111-216") { + // Right. + if (zvalue < 105.) + { + *minRight = 60.; + *maxRight = 120.; + } + else + { + *minRight = 50.; + *maxRight = 120.; + } + + // Left. + *minLeft = 180.; + *maxLeft = 250.; + + // Right. + par[0] = 140.; + par[1] = 85.; + par[2] = 6.; + par[3] = 175.; + + par[4] = 110.; + par[5] = 170.; + par[6] = 70.; + par[7] = 100.; + par[8] = 3.; + par[9] = 10.; + par[10] = 150.; + par[11] = 200.; + + // Left. + par[12] = 140.; + par[13] = 220.; + par[14] = 6.; + par[15] = 175.; + + // fitLeft->SetParLimits(0,90.,170.); + par[18] = 210.; + par[19] = 230.; + par[20] = 3.; + par[21] = 10.; + // fitLeft->SetParLimits(3,150.,220.); + } + + + + + else if (filename == "ProcessRawData-201501124-216") { + // Right. + if (zvalue < 80.) + { + *minRight = -8440.; + *maxRight = -8350.; + } + else if (zvalue < 180.) + { + *minRight = -8450.; + *maxRight = -8370.; + } + else + { + *minRight = -8460.; + *maxRight = -8370.; + } + + // Left. + if (zvalue == 100.) + { + *minLeft = -8320.; + *maxLeft = -8240.; + } + else if (zvalue < 120.) + { + *minLeft = -8350.; + *maxLeft = -8240.; + } + else if (zvalue < 180.) + { + *minLeft = -8350.; + *maxLeft = -8250.; + } + else + { + *minLeft = -8360.; + *maxLeft = -8260.; + } + + // Right. + if (zvalue < 100.) + par[0] = 100.; + else + par[0] = 130.; + if (zvalue < 100.) + par[1] = -8400.; + else + par[1] = -8420.; + par[2] = 10.; + if (zvalue < 100.) + par[3] = 200.; + else + par[3] = 170.; + + par[4] = 80.; + par[5] = 140.; + par[6] = -8450.; + par[7] = -8370.; + par[8] = 3.; + par[9] = 20.; + par[10] = 150.; + par[11] = 250.; + + // Left. + if (zvalue < 100.) + par[12] = 100.; + else + par[12] = 135.; + par[13] = -8280.; + par[14] = 10.; + if (zvalue < 100.) + par[15] = 200.; + else + par[15] = 180.; + + // fitLeft->SetParLimits(0,90.,170.); + par[18] = -8300.; + par[19] = -8250.; + par[20] = 3.; + par[21] = 20.; + // fitLeft->SetParLimits(3,150.,220.); + } + + + + return; +}