//Display the results of a fit in a LaTeX table using cout void ResultFormatter::ReviewOutput( FitResult * OutputData ) { ResultParameterSet * outputParameters = OutputData->GetResultParameterSet(); vector<string> allNames = outputParameters->GetAllNames(); vector<string>::iterator nameIterator; cout << endl << endl; cout << "--------------------------------------------------" <<endl; cout << "\nFit Review:\t\tStatus:\t" <<OutputData->GetFitStatus()<<"\t\tNLL:\t"<<setprecision(10)<<OutputData->GetMinimumValue()<<endl<<endl; //Ouput each parameter for( nameIterator = allNames.begin(); nameIterator != allNames.end(); ++nameIterator ) { ResultParameter * outputParameter = outputParameters->GetResultParameter( *nameIterator ); double fitValue = outputParameter->GetValue(); double fitError = outputParameter->GetError(); string unit = outputParameter->GetUnit(); string name = *nameIterator; cout << setw(25) << name << " : " << setw(13) << setprecision(5) << fitValue; if( outputParameter->GetAssym() ) { cout << " + " << setprecision(5) << setw(8) << outputParameter->GetErrHi() << " - " << setw(6) << outputParameter->GetErrLow() << endl; } else { cout << " ± " << setw(13) << setprecision(5) << fitError << endl; } } cout << endl; cout << "--------------------------------------------------" <<endl; cout << endl <<endl; }
void ResultFormatter::LatexMinimumFitResultTable( FitResult * OutputData, stringstream& latex ) { ResultFormatter::TableHeader( latex, 2 ); latex << "Parameter & Fit result and error \\\\ \\hline \\hline\n" << endl; ResultParameterSet * outputParameters = OutputData->GetResultParameterSet(); vector<string> allNames = outputParameters->GetAllNames(); for( vector<string>::iterator nameIterator = allNames.begin(); nameIterator != allNames.end(); ++nameIterator ) { ResultParameter * outputParameter = outputParameters->GetResultParameter( *nameIterator ); double fitValue = outputParameter->GetValue(); double fitError = outputParameter->GetError(); string unit = outputParameter->GetUnit(); string name = *nameIterator; latex << setw(20) << EdStyle::GetParamLatexName(name) << " & " << setw(12) << setprecision(3) << fitValue; if( outputParameter->GetAssym() ) { latex << " + " << outputParameter->GetErrHi() << " - " << outputParameter->GetErrLow() << " "; } else { latex << " \\pm " << setw(10) << fitError << " "; } latex << setw(15) << EdStyle::GetParamLatexUnit(unit) << "\\\\" << endl; } ResultFormatter::TableFooter( latex ); }
//Add a new fit result bool FitResultVector::AddFitResult( FitResult * NewResult, const bool with_clock ) { vector<double> newParameterValues, newParameterErrors, newParameterPulls, newParameterGenValues; vector<string>::iterator nameIterator; ResultParameterSet * newSet = NewResult->GetResultParameterSet(); //Check all expected parameters are found for ( nameIterator = allNames.begin(); nameIterator != allNames.end(); ++nameIterator ) { ResultParameter * newResult = newSet->GetResultParameter( *nameIterator ); if ( newResult->GetUnit() == "NameNotFoundError" ) { //If any parameter is not found, fail cerr << "Expected fitted parameter \"" << *nameIterator << "\" not found" << endl; return false; } else { //Retrieve the parameter information newParameterValues.push_back( newResult->GetValue() ); newParameterErrors.push_back( newResult->GetError() ); newParameterPulls.push_back( newResult->GetPull() ); newParameterGenValues.push_back( newResult->GetOriginalValue() ); } } //If you've got this far, all the parameters have been found, so add them to the record allResults.push_back(NewResult); for (unsigned int nameIndex = 0; nameIndex < allNames.size(); ++nameIndex ) { allValues[nameIndex].push_back( newParameterValues[nameIndex] ); allErrors[nameIndex].push_back( newParameterErrors[nameIndex] ); allPulls[nameIndex].push_back( newParameterPulls[nameIndex] ); allGenValues[nameIndex].push_back( newParameterGenValues[nameIndex] ); } if( with_clock && clock != NULL ) { //Store the duration #ifdef RAPIDFIT_USETGLTIMER double thisTime = gl_clock->End(); allGLTimes.push_back( thisTime ); #endif clock->Stop(); allRealTimes.push_back( clock->RealTime() ); allCPUTimes.push_back( clock->CpuTime() ); } return true; }
//Display the results of a fit using cout void ResultFormatter::DebugOutputFitResult( FitResult * OutputData ) { cout << "Fit status: " << OutputData->GetFitStatus() << endl; cout << "Minimum function value: " << OutputData->GetMinimumValue() << endl; cout << "Name | Value | Minimum | Maximum" << endl; //Ouput each parameter ResultParameterSet * outputParameters = OutputData->GetResultParameterSet(); vector<string> allNames = outputParameters->GetAllNames(); vector<string>::iterator nameIterator; for ( nameIterator = allNames.begin(); nameIterator != allNames.end(); ++nameIterator ) { ResultParameter * outputParameter = outputParameters->GetResultParameter( *nameIterator ); cout << *nameIterator << " | " << outputParameter->GetValue() << " | "; cout << outputParameter->GetMinimum() << " | " << outputParameter->GetMaximum() << endl; } }
//Use Migrad to minimise the given function void FumiliWrapper::Minimise() { ParameterSet * newParameters = RapidFunction->GetParameterSet(); vector<string> allNames = newParameters->GetAllNames(); // int numParams = allNames.size(); /* // Fill a vector of doubles for each set of physics parameters that you // want to sample. What about case where Apara_sq + Aperp_sq > 1? vector< vector<double> > positions; PhysicsBottle* bottle = NewFunction->GetPhysicsBottle(); ParameterSet* parameters = bottle->GetParameterSet(); vector<string> names = parameters->GetAllNames(); double nsteps = 1; for( int k = 0; k < names.size(); ++k) { for( int j = 0; j < nsteps; ++j) { vector<double> tempPos; for( int i = 0; i < names.size(); ++i ) { double value; if ( i != k ) { value = parameters->GetPhysicsParameter(names[i])->GetValue(); } else { double min = parameters->GetPhysicsParameter(names[i])->GetMinimum(); double max = parameters->GetPhysicsParameter(names[i])->GetMaximum(); double step = (max - min)/nsteps; value = min + j * step; } tempPos.push_back(value); } positions.push_back(tempPos); } } */ // Fill a vector of doubles for each set of observables vector< vector<double> > positions; PhysicsBottle* bottle = RapidFunction->GetPhysicsBottle(); PhaseSpaceBoundary* boundary = bottle->GetResultDataSet(0)->GetBoundary(); vector<string> names = boundary->GetAllNames(); vector<double> observableSteps; int nsteps = 10; // Could make this faster... for ( int step = 0; step < nsteps; ++step) { vector<double> tempPos; for( unsigned int observable = 0; observable < names.size(); ++observable ) { if ( !boundary->GetConstraint(names[observable])->IsDiscrete() ) { double min = boundary->GetConstraint(names[observable])->GetMinimum(); double max = boundary->GetConstraint(names[observable])->GetMinimum(); double delta = (max - min)/nsteps; double position = min + step*delta; tempPos.push_back( position ); } else { double value = boundary->GetConstraint(names[observable])->CreateObservable()->GetValue(); tempPos.push_back( value ); } } positions.push_back(tempPos); } // Now, get the FumiliFCNBase function which will be passed to the Fumili minimiser FumiliStandardMaximumLikelihoodFCN fumFCN( *function, positions ); // Setup the minimiser MnFumiliMinimize fumili( fumFCN, *( function->GetMnUserParameters() ), (unsigned)Quality);//MINUIT_QUALITY); // Do the minimisation FunctionMinimum minimum = fumili( (unsigned)maxSteps, bestTolerance );//(int)MAXIMUM_MINIMISATION_STEPS, FINAL_GRADIENT_TOLERANCE ); // Once we have the FunctionMinimum, code same as in other Wrappers //Create the fit results const MnUserParameters * minimisedParameters = &minimum.UserParameters(); ResultParameterSet * fittedParameters = new ResultParameterSet( allNames ); for ( unsigned int nameIndex = 0; nameIndex < allNames.size(); ++nameIndex) { string parameterName = allNames[nameIndex]; PhysicsParameter * oldParameter = newParameters->GetPhysicsParameter( parameterName ); double parameterValue = minimisedParameters->Value( parameterName.c_str() ); double parameterError = minimisedParameters->Error( parameterName.c_str() ); fittedParameters->SetResultParameter( parameterName, parameterValue, oldParameter->GetOriginalValue(), parameterError, -oldParameter->GetMinimum(), oldParameter->GetMaximum(), oldParameter->GetType(), oldParameter->GetUnit() ); } int fitStatus; if ( !minimum.HasCovariance() ) { fitStatus = 0; } else if ( !minimum.HasAccurateCovar() ) { fitStatus = 1; } else if ( minimum.HasMadePosDefCovar() ) { fitStatus = 2; } else { fitStatus = 3; } PhysicsBottle* newBottle = RapidFunction->GetPhysicsBottle(); fitResult = new FitResult( minimum.Fval(), fittedParameters, fitStatus, newBottle ); }
//Display the results of a fit in a LaTeX table using cout void ResultFormatter::LatexOutputFitResult( FitResult * OutputData ) { //............................................. // Standard table for MC toys with pulls cout << "Fit result for MC toys with pulls" << endl; cout << "\n\\begin{center}" << endl; cout << "Fit status: " << OutputData->GetFitStatus() << endl; cout << setprecision(8) << "Minimum function value: " << OutputData->GetMinimumValue() << endl; cout << "\\begin{tabular}{|c|c|c|} \n\\hline" << endl; cout << setw(20) << "Parameter"<< " & " << setw(25) << "Fit result and error" << setw(21) << " & " << setw(20) << "$\\sigma$ from input \\\\ \t\t\\hline \\hline\n" << endl; //Ouput each parameter ResultParameterSet * outputParameters = OutputData->GetResultParameterSet(); vector<string> allNames = outputParameters->GetAllNames(); vector<string>::iterator nameIterator; for ( nameIterator = allNames.begin(); nameIterator != allNames.end(); ++nameIterator ) { ResultParameter * outputParameter = outputParameters->GetResultParameter( *nameIterator ); double fitValue = outputParameter->GetValue(); // double minValue = outputParameter->GetMinimum(); // double inputValue = outputParameter->GetOriginalValue(); double fitError = outputParameter->GetError(); double sigmaFromInputValue = outputParameter->GetPull(); string unit = outputParameter->GetUnit(); //if (fitError > 0.0) sigmaFromInputValue = (fitValue - inputValue)/fitError; //boost::regex pattern ("_",boost::regex_constants::icase|boost::regex_constants::perl); //string replace ("\\_"); //string newName = boost::regex_replace (*nameIterator, pattern, replace); //string name = FindAndReplaceString( *nameIterator ); //string name = StringProcessing::ReplaceString( *nameIterator, "_", "\\_" ); string name = *nameIterator; cout << setw(20) << EdStyle::GetParamLatexName(name) << " & " << setw(12) << setprecision(5) << fitValue << " $\\pm$ " << setw(10) << fitError << " " << setw(15) << EdStyle::GetParamLatexUnit(unit) << " & " << setw(20) << setprecision(2) << sigmaFromInputValue << "\\\\" << endl; } cout << "\\hline \n\\end{tabular}" << endl; cout << "\\end{center}\n" << endl; //................................................. //longer table for MC pull fits with absolute offsets cout << endl ; cout << "Fit result - for MC toys with pulls and absolute offsets " << endl; cout << "\n\\begin{center}" << endl; cout << "Fit status: " << OutputData->GetFitStatus() << endl; cout << setprecision(8) << "Minimum function value: " << OutputData->GetMinimumValue() << endl; cout << "\\begin{tabular}{|c|c|c|c|} \n\\hline" << endl; cout << setw(20)<< "Parameter"<< " & " << setw(25) << "Fit result and error" << setw(21) << " & "<< setw(20) <<"$\\sigma$ from input" << " & " << setw(20) << "Abs from input \\\\ \t\t\\hline \\hline\n" << endl; //Ouput each parameter for ( nameIterator = allNames.begin(); nameIterator != allNames.end(); ++nameIterator ) { ResultParameter * outputParameter = outputParameters->GetResultParameter( *nameIterator ); double fitValue = outputParameter->GetValue(); // double minValue = outputParameter->GetMinimum(); double inputValue = outputParameter->GetOriginalValue(); double fitError = outputParameter->GetError(); double sigmaFromInputValue = outputParameter->GetPull(); string unit = outputParameter->GetUnit(); //if (fitError > 0.0) sigmaFromInputValue = (fitValue - inputValue)/fitError; //boost::regex pattern ("_",boost::regex_constants::icase|boost::regex_constants::perl); //string replace ("\\_"); //string newName = boost::regex_replace (*nameIterator, pattern, replace); //string name = FindAndReplaceString( *nameIterator ); //string name = StringProcessing::ReplaceString( *nameIterator, "_", "\\_" ); string name = *nameIterator; cout << setw(20) << EdStyle::GetParamLatexName(name) << " & " << setw(12) << setprecision(5) << fitValue << " $\\pm$ " << setw(10) << fitError << " " << setw(15) << EdStyle::GetParamLatexUnit(unit) << " & " << setw(20) << setprecision(2) << sigmaFromInputValue << " & " << setw(15) << setprecision(5) << fitValue-inputValue << "\\\\" << endl; } cout << "\\hline \n\\end{tabular}" << endl; cout << "\\end{center}\n" << endl; //........................................ //short table for data fits cout << endl ; cout << "\n\\begin{center}" << endl; cout << "Fit result - for Data fits" << endl; cout << "Fit status: " << OutputData->GetFitStatus() << endl; cout << setprecision(8) << "Minimum function value: " << OutputData->GetMinimumValue() << endl; cout << "\\begin{tabular}{|c|c|} \n\\hline" << endl; cout << setw(20) << "Parameter" << " & " << setw(21) << "Fit result and error" << setw(21) << " " << " \\\\ \\hline \\hline\n" << endl; //Will need to do some comparisons // double Rperp =0, Rzp =0, ePerp =0 , eZp=0; //Ouput each parameter for ( nameIterator = allNames.begin(); nameIterator != allNames.end(); ++nameIterator ) { ResultParameter * outputParameter = outputParameters->GetResultParameter( *nameIterator ); double fitValue = outputParameter->GetValue(); // double minValue = outputParameter->GetMinimum(); // double inputValue = outputParameter->GetOriginalValue(); double fitError = outputParameter->GetError(); // double sigmaFromInputValue = outputParameter->GetPull(); string unit = outputParameter->GetUnit(); //string name = StringProcessing::ReplaceString( *nameIterator, "_", "\\_" ); string name = *nameIterator; cout << setw(20) << EdStyle::GetParamLatexName(name) << " & " << setw(12) << setprecision(3) << fitValue << " $\\pm$ " << setw(10) << fitError << " " << setw(15) << EdStyle::GetParamLatexUnit(unit) << "\\\\" << endl; } cout << "\\hline \n\\end{tabular}" << endl; cout << "\\end{center}\n" << endl; }
//Make pull plots from the output of a toy study void ResultFormatter::WriteFlatNtuple( const string FileName, const FitResultVector* ToyResult, const vector<string> inputXML, const vector<string> runtimeArgs, const string XMLForProjections, const string XMLForToys ) { TFile * rootFile = TFile::Open( FileName.c_str(), "RECREATE" ); rootFile->SetCompressionLevel( 9 ); //cout << "Storing Fit Result Vector" << endl; // Important! // The output from this is typically run through the RapidPlot file // For sake of backwards compatibility the RapidPlot tool makes use of the ability to look for the 'first' TTree in a ROOT file for some of it's internal logic // KEEP THIS TREE AS THE FIRST TREE CREATED AND WRITTEN TO THE FILE TO BE ABLE TO KEEP USING THIS TOOL!!! TTree* outputTree = new TTree( "RapidFitResult", "RapidFitResult" ); ResultParameterSet* resultSet = ToyResult->GetFitResult( 0 )->GetResultParameterSet(); vector<string> allNames = resultSet->GetAllNames(); for( unsigned int param_i=0; param_i< allNames.size(); ++param_i ) { string thisParamName( allNames[param_i] ); vector<double> ParameterValues, ParameterErrors, ParameterOriginalValues; vector<double> ParameterPulls, ParameterStepSizes; vector<double> ParameterErrorsHigh, ParameterErrorsLow; vector<double> ParameterMinimums, ParameterMaximums; vector<int> ParameterScanStatus, ParameterFixedStatus; for( unsigned int resultNum=0; resultNum< (unsigned)ToyResult->NumberResults(); ++resultNum ) { ResultParameter* thisParam = ToyResult->GetFitResult( (unsigned)resultNum )->GetResultParameterSet()->GetResultParameter( thisParamName ); ParameterValues.push_back( thisParam->GetValue() ); ParameterErrors.push_back( thisParam->GetError() ); ParameterPulls.push_back( thisParam->GetPull() ); ParameterMinimums.push_back( thisParam->GetMinimum() ); ParameterMaximums.push_back( thisParam->GetMaximum() ); ParameterOriginalValues.push_back( thisParam->GetOriginalValue() ); if( thisParam->GetType() == "Fixed" ) { ParameterFixedStatus.push_back( 1 ); } else { ParameterFixedStatus.push_back( 0 ); } //if( thisParam->GetScanStatus() ) cout << "Scanned: " << string(thisParamName) << endl; if( thisParam->GetScanStatus() ) { ParameterScanStatus.push_back( 1 ); } else { ParameterScanStatus.push_back( 0 ); } if( thisParam->GetAssym() ) { ParameterErrorsHigh.push_back( thisParam->GetErrHi() ); ParameterErrorsLow.push_back( thisParam->GetErrLow() ); } else { ParameterErrorsHigh.push_back( 0. ); ParameterErrorsLow.push_back( 0. ); } ParameterStepSizes.push_back( thisParam->GetStepSize() ); } string BranchName=allNames[param_i]; ResultFormatter::AddBranch( outputTree, BranchName+"_value", ParameterValues ); bool fixed_param = ToyResult->GetFitResult(0)->GetResultParameterSet()->GetResultParameter(thisParamName)->GetType() == "Fixed"; bool scanned_param = ToyResult->GetFitResult(0)->GetResultParameterSet()->GetResultParameter(thisParamName)->GetScanStatus(); if( (!fixed_param) || (scanned_param) ) { ResultFormatter::AddBranch( outputTree, BranchName+"_error", ParameterErrors ); ResultFormatter::AddBranch( outputTree, BranchName+"_gen", ParameterOriginalValues ); ResultFormatter::AddBranch( outputTree, BranchName+"_pull", ParameterPulls ); ResultFormatter::AddBranch( outputTree, BranchName+"_max", ParameterMaximums ); ResultFormatter::AddBranch( outputTree, BranchName+"_min", ParameterMinimums ); ResultFormatter::AddBranch( outputTree, BranchName+"_step", ParameterStepSizes ); ResultFormatter::AddBranch( outputTree, BranchName+"_errHi", ParameterErrorsHigh ); ResultFormatter::AddBranch( outputTree, BranchName+"_errLo", ParameterErrorsLow ); } ResultFormatter::AddBranch( outputTree, BranchName+"_scan", ParameterScanStatus ); ResultFormatter::AddBranch( outputTree, BranchName+"_fix", ParameterFixedStatus ); } //cout << "Stored Parameters" << endl; ResultFormatter::AddBranch( outputTree, "Fit_RealTime", ToyResult->GetAllRealTimes() ); ResultFormatter::AddBranch( outputTree, "Fit_CPUTime", ToyResult->GetAllCPUTimes() ); ResultFormatter::AddBranch( outputTree, "Fit_GLTime", ToyResult->GetAllGLTimes() ); vector<int> fitStatus; vector<double> NLL_Values, RealTimes, CPUTimes; for( unsigned int i=0; i< (unsigned) ToyResult->NumberResults(); ++i ) { fitStatus.push_back( ToyResult->GetFitResult( (int)i )->GetFitStatus() ); NLL_Values.push_back( ToyResult->GetFitResult( (int)i )->GetMinimumValue() ); } ResultFormatter::AddBranch( outputTree, "Fit_Status", fitStatus ); ResultFormatter::AddBranch( outputTree, "NLL", NLL_Values ); outputTree->Write("",TObject::kOverwrite); //ResultFormatter::AddBranch( outputTree, "Fit_RealTime", RealTimes ); //ResultFormatter::AddBranch( outputTree, "Fit_CPUTime", CPUTimes ); // Ntuples are 'stupid' objects in ROOT and the basic one can only handle float type objects /*TNtuple * parameterNTuple; parameterNTuple = new TNtuple("RapidFitResult", "RapidFitResult", ToyResult->GetFlatResultHeader()); Float_t * resultArr; for( int resultIndex = 0; resultIndex < ToyResult->NumberResults(); ++resultIndex ) { vector<double> result = ToyResult->GetFlatResult(resultIndex); resultArr = new Float_t [result.size()]; copy( result.begin(), result.end(), resultArr); parameterNTuple->Fill( resultArr ); delete [] resultArr; }*/ //cout << "Storing Correlation Matrix" << endl; if( ToyResult->GetFitResult(0)->GetResultParameterSet() != NULL ) { if( !ToyResult->GetFitResult(0)->GetResultParameterSet()->GetAllFloatNames().empty() ) { vector<double> MatrixElements; vector<string> MatrixNames; TTree * tree = new TTree("corr_matrix", "Elements from Correlation Matricies"); tree->Branch("MartrixElements", "std::vector<double>", &MatrixElements ); tree->Branch("MartrixNames", "std::vector<string>", &MatrixNames ); for( int resultIndex = 0; resultIndex < ToyResult->NumberResults(); ++resultIndex ) { TMatrixDSym* thisMatrix = ToyResult->GetFitResult(resultIndex)->GetCovarianceMatrix()->thisMatrix; if( thisMatrix == NULL ) continue; MatrixNames = ToyResult->GetFitResult(resultIndex)->GetCovarianceMatrix()->theseParameters; if( MatrixNames.empty() ) continue; double* MatrixArray = thisMatrix->GetMatrixArray(); if( MatrixArray == NULL ) continue; MatrixElements.clear(); for( unsigned int i=0; i< (unsigned) thisMatrix->GetNoElements(); ++i ) { MatrixElements.push_back( MatrixArray[i] ); } if( thisMatrix->GetNoElements() > 0 ) tree->Fill(); } tree->Write("",TObject::kOverwrite); } } //cout << "Saving XML and runtime" << endl; if( !inputXML.empty() ) { TTree* XMLTree = new TTree( "FittingXML", "FittingXML" ); vector<string> thisXML = inputXML; XMLTree->Branch( "FittingXML", "std::vector<string>", &thisXML ); XMLTree->Fill(); XMLTree->Write("",TObject::kOverwrite); } if( !runtimeArgs.empty() ) { TTree* RuntimeTree = new TTree( "RuntimeArgs", "RuntimeArgs" ); vector<string> thisRuntime = runtimeArgs; RuntimeTree->Branch( "RuntimeArgs", "std::vector<string>", &thisRuntime ); RuntimeTree->Fill(); RuntimeTree->Write("",TObject::kOverwrite); } if( !XMLForProjections.empty() ) { TTree* ProjectionXML = new TTree( "XMLForProjections", "XMLForProjections" ); string thisXML = XMLForProjections; ProjectionXML->Branch( "ProjectionXML", "std::string", &thisXML ); ProjectionXML->Fill(); ProjectionXML->Write("",TObject::kOverwrite); } if( !XMLForToys.empty() ) { TTree* ToyXML = new TTree( "XMLForToys", "XMLForToys" ); string thisXML = XMLForToys; ToyXML->Branch( "ToyXML", "std::string", &thisXML ); ToyXML->Fill(); ToyXML->Write("",TObject::kOverwrite); } rootFile->Write("",TObject::kOverwrite); rootFile->Close(); // THIS SHOULD BE SAFE... BUT THIS IS ROOT so 'of course' it isn't... //delete parameterNTuple; //delete rootFile; }