// A simple C++ program to illustrate the use of ROOT class TMinuit // for function minimization. The example shows a Maximum Likelihood // fit in which TMinuit minimizes - 2*log(L). // fcn passes back f = -2*ln L by reference; this is the function to minimize. // The factor of -2 allows MINUIT to get the errors using the same // recipe as for least squares, i.e., go up from the minimum by 1. // TMinuit does not allow fcn to be a member function, and the function // arguments are fixed, so the one of the only ways to bring the data // into fcn is to declare a pointer to the data (xVecPtr) as global. // For more info on TMinuit see root.cern.ch/root/html/TMinuit.html . // Glen Cowan // RHUL Physics // 9 August, 2011 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; // Declare pointers to data as global (not elegant but TMinuit needs this). vector* Rdata = new vector(); vector* VLongCables = new vector(); vector* VShortCables = new vector(); vector* dVLC = new vector(); vector* dVSC = new vector(); void plotFit(TCanvas* canvas, string outfile, double xMin, double xMax, double yMin, double yMax, double par[], vector* xVec, vector* yVec, vector* dyVec); double BandpassIntegral(double R, double C){ const double pi = 3.14159265; static vector fVec; static vector g2Vec; static bool firstCall = true; if (firstCall) { firstCall = false; string fileName = "./FilterData.txt"; ifstream inFile; inFile.open(fileName.c_str()); if (inFile.fail()) { cout << "Couldn't open filter data file!" << endl; exit(1); } istringstream instream; // Declare an input string stream string line; int lineNum = 0; while ( getline(inFile, line) ) { bool useLine = !( line.substr(0,1) == "#" || line.substr(0,1) == "!"); if ( useLine ) { instream.clear(); // Reset from possible previous errors instream.str(line); // Use line as source of input double f, v0, vi, g2, b; lineNum++; instream >> f >> v0 >> vi >> g2 >> b; fVec.push_back(f); g2Vec.push_back(g2); } } } // end of initialization double bpi = 0.; for (int i=0; i* Rdata, vector* VLongCables, vector* VShortCables){ // string fileName; // cout << "Enter file name: "; // cin >> fileName; string fileName = "VrmsData.txt"; ifstream inFile; inFile.open(fileName.c_str()); if (inFile.fail()) { cout << "Couldn't open file!" << endl; exit(1); } // KLUDGE -- for now set 2% relative errors by hand double relErrLC = 0.02; double relErrSC = 0.02; istringstream instream; // Declare an input string stream string line; int lineNum = 0; while ( getline(inFile, line) ) { bool useLine = !( line.substr(0,1) == "#" || line.substr(0,1) == "!"); if ( useLine ) { instream.clear(); // Reset from possible previous errors instream.str(line); // Use line as source of input double r, vlc, vsc; lineNum++; instream >> r >> vlc >> vsc; Rdata->push_back(r); VLongCables->push_back(vlc*1.e-6); // convert nV to V VShortCables->push_back(vsc*1.e-6); // convert nV to V dVLC->push_back(relErrLC*vlc*1.e-6); dVSC->push_back(relErrSC*vsc*1.e-6); } } int numPoints = Rdata->size(); cout << "Read info for " << numPoints << " data points" << endl; for (int i=0; iSetFillColor(0); canvas->UseCurrentStyle(); canvas->SetBorderMode(0); // still leaves red frame bottom and right canvas->SetFrameBorderMode(0); // need this to turn off red hist frame! gROOT->SetStyle("Plain"); canvas->UseCurrentStyle(); gROOT->ForceStyle(); gROOT->SetStyle("Plain"); gStyle->SetOptStat(0); gStyle->SetTitleBorderSize(0); gStyle->SetTitleSize(0.04); gStyle->SetTitleFont(42, "hxy"); // for histogram and axis titles gStyle->SetLabelFont(42, "xyz"); // for axis labels (values) gROOT->ForceStyle(); // Read in the data (declared global) getData(Rdata, VLongCables, VShortCables); // Initialize minuit, set initial values etc. of parameters. const int npar = 4; // the number of parameters TMinuit minuit(npar); minuit.SetFCN(fcn); double par[npar]; // the start values double stepSize[npar]; // step sizes double minVal[npar]; // minimum bound on parameter double maxVal[npar]; // maximum bound on parameter string parName[npar]; par[0] = 1e-23; // a guess stepSize[0] = 1e-24; minVal[0] = 0.0; maxVal[0] = 0.0; parName[0] = "kB"; par[1] = 72.8e-12; // Farads stepSize[1] = 3.e-12; // minVal[1] = 0.0; maxVal[1] = 0.0; parName[1] = "CL"; par[2] = 49.2e-12; // Farads stepSize[2] = 3.e-12; // minVal[2] = 0.0; maxVal[2] = 0.0; parName[2] = "CS"; par[3] = 300.; // Kelvin stepSize[3] = 0.; // minVal[3] = 0.0; maxVal[3] = 0.0; parName[3] = "T"; for (int i=0; iClose(); delete canvas; return 0; } void plotFit(TCanvas* canvas, string outfile, double xMin, double xMax, double yMin, double yMax, double par[], vector* xVec, vector* yVec, vector* dyVec){ gPad->SetLeftMargin(0.15); gPad->SetRightMargin(0.15); gPad->SetTopMargin(0.1); gPad->SetBottomMargin(0.2); TF1* func = new TF1("func", Vrms, xMin, xMax, 3); func->SetLineStyle(1); // 1 = solid, 2 = dashed, 3 = dotted func->SetLineColor(1); // black (default) func->SetLineWidth(1); func->SetParameters(par); func->Draw(); TH1* axhist = func->GetHistogram(); axhist->SetTitle(""); axhist->SetXTitle("R (Ohms)"); axhist->SetYTitle("V_{rms} (Volts)"); axhist->SetMinimum(yMin); axhist->SetMaximum(yMax); axhist->SetAxisRange(xMin, xMax); TAxis* xa = axhist->GetXaxis(); TAxis* ya = axhist->GetYaxis(); xa->SetTitleOffset(1.4); // factor multiplies default offset ya->SetTitleOffset(1.4); xa->SetLabelOffset(0.015); ya->SetLabelOffset(0.015); xa->SetTickLength(0.015); // default = 0.03 ya->SetTickLength(0.015); // default = 0.03 xa->SetTitleSize(0.04); ya->SetTitleSize(0.04); // gPad->SetLogx(1); // xa->SetLimits(90., 700.); xa->SetNdivisions(-5); // negative value should force number of divisions? ya->SetNdivisions(-5); xa->SetLabelSize(0.04); ya->SetLabelSize(0.04); // add the data points int numPoints = (*xVec).size(); double xArray[numPoints]; double yArray[numPoints]; double* dxArray = 0; double dyArray[numPoints]; for (int i=0; iSetMarkerColor(1); tg->SetMarkerSize(0.8); tg->SetMarkerStyle(20); tg->Draw("P,same"); canvas->Show(); string psfile = outfile + ".eps"; string giffile = outfile + ".gif"; canvas->Print(psfile.c_str(), "eps"); canvas->Print(giffile.c_str(), "gif"); string command; cout << "Enter any key to continue: "; getline(cin, command); }