diff --git a/parameters/config.xml b/parameters/config.xml index 0a23a39..6c7ecfa 100644 --- a/parameters/config.xml +++ b/parameters/config.xml @@ -1,157 +1,158 @@ <nuisance> <!-- # ###################################################### --> <!-- # NUISANCE CONFIGURATION OPTIONS --> <!-- # This file is read in by default at runtime --> <!-- # If you want to override on a case by case bases use -q at runtime --> <!-- # ###################################################### --> <!-- # MAIN Configs --> <!-- # ###################################################### --> <!-- # Logger goes from --> <!-- # 1 Quiet --> <!-- # 2 Fitter --> <!-- # 3 Samples --> <!-- # 4 Reconfigure Loops --> <!-- # 5 Every Event print out (SHOUT) --> <!-- # -1 DEBUGGING --> -<config verbosity='3'/> -<config VERBOSITY='3'/> +<config verbosity='5'/> +<config VERBOSITY='5'/> <!-- # ERROR goes from --> <!-- # 0 NONE --> <!-- # 1 FATAL --> <!-- # 2 WARN --> <config ERROR='2'/> <config cores='2' /> +<config spline_test_throws='50' /> <!-- # Input Configs --> <!-- # ###################################################### --> <!-- # Default Requirements file for the externalDataFitter Package --> <!-- # MAX Events : -1 is no cut. Events will be scaled automatically to give good xsec predictions. --> <config input.maxevents='-1'/> <config MAXEVENTS='-1'/> <config input.MAXEVENTS='-1'/> <config includeemptystackhists='0'/> <!-- # Turn on/off event manager --> <!-- # EventManager enables us to only loop number of events once for multiple projections of the same measurements --> <!-- # e.g. MiniBooNE CC1pi+ Q2 and MiniBooNE CC1pi+ Tmu would ordinarily require 2 reconfigures, but with this enabled it requires only one --> <config input.eventmanager='1'/> <config EventManager='1'/> <!-- # Event Directories --> <!-- # Can setup default directories and use @EVENT_DIR/path to link to it --> <config EVENT_DIR='/data2/stowell/NIWG/'/> <config NEUT_EVENT_DIR='/data2/stowell/NIWG/neut/fit_samples_neut5.3.3/'/> <config GENIE_EVENT_DIR='/data2/stowell/NIWG/genie/fit_samples_R.2.10.0/'/> <config NUWRO_EVENT_DIR='/data2/stowell/NIWG/nuwro/fit_samples/'/> <config GIBUU_EVENT_DIR='/data/GIBUU/DIR/'/> <!-- # In PrepareGENIE the reconstructed splines can be saved into the file --> <config save_genie_splines='1'/> <!-- # In InputHandler the option to regenerate NuWro flux/xsec plots is available --> <!-- # Going to move this to its own app soon --> <config input.regen_nuwro_plots='0'/> <!-- # DEVEL CONFIG OPTION, don't touch! --> <config cachesize='0'/> <!-- # ReWeighting Configuration Options --> <!-- # ###################################################### --> <!-- # Set absolute twkdial for parameters --> <config params.setabstwk='0'/> <!-- # Convert Dials in output statements using dial conversion card --> <config convert_dials='0'/> <!-- # Make RW Calculations be quiet --> <config params.silentweighting='0'/> <!-- # Vetos can be used to specify RW dials NOT to be loaded in --> <!-- # Useful if one specific one has an issue --> <config FitWeight.fNIWGRW_veto=''/> <config FitWeight.fNuwroRW_veto=''/> <config FitWeight.fNeutRW_veto=''/> <config FitWeight.fGenieRW_veto=''/> <!-- # Output Options --> <!-- # ###################################################### --> <!-- # Save Nominal prediction with all rw engines at default --> <config savenominal='0'/> <!-- # Save prefit with values at starting values --> <config saveprefit='0'/> <!-- # Here's the full list of drawing options --> <!-- # See src/FitBase/Measurement1D::Write for more info --> <!-- #config drawopts DATA/MC/EVT/FINE/RATIO/MODES/SHAPE/RESIDUAL/MATRIX/FLUX/MASK/MAP --> <!-- #config drawopts DATA/MC --> <config drawopts='DATA/MC/EVT/FINE/RATIO/MODES/SHAPE/FLUX/XSEC/MASK/COV/INCOV/DECOMP/CANVPDG/CANVMC'/> <!-- # Save the shape scaling applied with option SHAPE into the main MC hist --> <config saveshapescaling='0'/> <!-- # Set style of 1D output histograms --> <config linecolour='1'/> <config linestyle='1'/> <config linewidth='1'/> <!-- # For GenericFlux --> <config isLiteMode='0'/> <!-- # Statistical Options --> <!-- # ###################################################### --> <!-- # Add MC Statistical error to likelihoods --> <config statutils.addmcerror='0'/> <!-- # NUISMIN Configurations --> <!-- # ###################################################### --> <config minimizer.maxcalls='1000000'/> <config minimizer.maxiterations='1000000'/> <config minimizer.tolerance='0.001'/> <!-- # Number of events required in low stats routines --> <config minimizer.lowstatevents='25000'/> <!-- # Error band generator configs --> <!-- # ###################################################### --> <!-- # For -f ErrorBands creates error bands for given measurements --> <!-- # How many throws do we want (The higher the better precision) --> <config error_throws='250'/> <!-- # Are we throwing uniform or according to Gaussian? --> <!-- # Only use uniform if wanting to study the limits of a dial. --> <config error_uniform='0'/> <!-- # Other Individual Case Configs --> <!-- # ###################################################### --> <!-- # Covariance throw options for fake data studies with MiniBooNE data. --> <config thrown_covariance='FULL'/> <config throw_mc_stat='0.0'/> <config throw_diag_syst='0'/> <config throw_corr_syst='0'/> <config throw_mc_stat='0'/> <!-- # Apply a shift to the muon momentum before calculation of Q2 --> <config muon_momentum_shift='0.0'/> <config muon_momentum_throw='0'/> <!-- # MINERvA Specific Configs --> <config MINERvA_XSec_CCinc_2DEavq3_nu.hadron_cut='0'/> <config MINERvA_CCinc_XSec_2DEavq3_nu.useq3true='0'/> <config Modes.split_PN_NN='0'/> <config SignalReconfigures='0'/> </nuisance> diff --git a/src/FCN/JointFCN.cxx b/src/FCN/JointFCN.cxx index 65f935c..3ba5a28 100755 --- a/src/FCN/JointFCN.cxx +++ b/src/FCN/JointFCN.cxx @@ -1,942 +1,962 @@ #include "JointFCN.h" #include <stdio.h> #include "FitUtils.h" // //*************************************************** // JointFCN::JointFCN(std::string cardfile, TFile* outfile) { // //*************************************************** // fOutputDir = gDirectory; // FitPar::Config().out = outfile; // fCardFile = cardfile; // LoadSamples(fCardFile); // fCurIter = 0; // fMCFilled = false; // fOutputDir->cd(); // fIterationTree = NULL; // fDialVals = NULL; // fNDials = 0; // fUsingEventManager = FitPar::Config().GetParB("EventManager"); // fOutputDir->cd(); // }; JointFCN::JointFCN(TFile* outfile) { fOutputDir = gDirectory; if (outfile) FitPar::Config().out = outfile; std::vector<nuiskey> samplekeys = Config::QueryKeys("sample"); LoadSamples(samplekeys); fCurIter = 0; fMCFilled = false; fIterationTree = NULL; fDialVals = NULL; fNDials = 0; fUsingEventManager = FitPar::Config().GetParB("EventManager"); fOutputDir->cd(); } JointFCN::JointFCN(std::vector<nuiskey> samplekeys, TFile* outfile) { fOutputDir = gDirectory; if (outfile) FitPar::Config().out = outfile; LoadSamples(samplekeys); fCurIter = 0; fMCFilled = false; fOutputDir->cd(); fIterationTree = NULL; fDialVals = NULL; fNDials = 0; fUsingEventManager = FitPar::Config().GetParB("EventManager"); fOutputDir->cd(); } //*************************************************** JointFCN::~JointFCN() { //*************************************************** // Delete Samples for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase* exp = *iter; delete exp; } for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) { ParamPull* pull = *iter; delete pull; } // Sort Tree if (fIterationTree) DestroyIterationTree(); if (fDialVals) delete fDialVals; if (fSampleLikes) delete fSampleLikes; }; //*************************************************** void JointFCN::CreateIterationTree(std::string name, FitWeight* rw) { //*************************************************** LOG(FIT) << " Creating new iteration tree! " << endl; if (fIterationTree && !name.compare(fIterationTree->GetName())) { fIterationTree->Reset(); return; } fIterationTree = new TTree(name.c_str(), name.c_str()); // Setup Main Branches fIterationTree->Branch("total_likelihood", &fLikelihood, "total_likelihood/D"); fIterationTree->Branch("total_ndof", &fNDOF, "total_ndof/I"); // Setup Sample Arrays int ninputs = fSamples.size() + fPulls.size(); fSampleLikes = new double[ninputs]; fSampleNDOF = new int[ninputs]; fNDOF = GetNDOF(); // Setup Sample Branches int count = 0; for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase* exp = *iter; std::string name = exp->GetName(); std::string liketag = name + "_likelihood"; std::string ndoftag = name + "_ndof"; fIterationTree->Branch(liketag.c_str(), &fSampleLikes[count], (liketag + "/D").c_str()); fIterationTree->Branch(ndoftag.c_str(), &fSampleNDOF[count], (ndoftag + "/D").c_str()); count++; } for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) { ParamPull* pull = *iter; std::string name = pull->GetName(); std::string liketag = name + "_likelihood"; std::string ndoftag = name + "_ndof"; fIterationTree->Branch(liketag.c_str(), &fSampleLikes[count], (liketag + "/D").c_str()); fIterationTree->Branch(ndoftag.c_str(), &fSampleNDOF[count], (ndoftag + "/D").c_str()); count++; } // Add Dial Branches std::vector<std::string> dials = rw->GetDialNames(); fNDials = dials.size(); fDialVals = new double[fNDials]; for (int i = 0; i < fNDials; i++) { fIterationTree->Branch(dials[i].c_str(), &fDialVals[i], (dials[i] + "/D").c_str()); } } //*************************************************** void JointFCN::DestroyIterationTree() { //*************************************************** if (!fIterationTree) { delete fIterationTree; } } //*************************************************** void JointFCN::WriteIterationTree() { //*************************************************** if (!fIterationTree) { ERR(FTL) << "Can't save empty iteration tree!" << endl; throw; } fIterationTree->Write(); } //*************************************************** void JointFCN::FillIterationTree(FitWeight* rw) { //*************************************************** if (!fIterationTree) { ERR(FTL) << "Trying to fill iteration_tree when it is NULL!" << endl; throw; } rw->GetAllDials(fDialVals, fNDials); fIterationTree->Fill(); } //*************************************************** double JointFCN::DoEval(const double* x) { //*************************************************** // WEIGHT ENGINE fDialChanged = FitBase::GetRW()->HasRWDialChanged(x); FitBase::GetRW()->UpdateWeightEngine(x); if (fDialChanged) { FitBase::GetRW()->Reconfigure(); FitBase::EvtManager().ResetWeightFlags(); } if (LOG_LEVEL(REC)) { FitBase::GetRW()->Print(); } // SORT SAMPLES ReconfigureSamples(); // GET TEST STAT fLikelihood = GetLikelihood(); // PRINT PROGRESS LOG(FIT) << "Current Stat (iter. " << this->fCurIter << ") = " << fLikelihood << std::endl; // UPDATE TREE if (fIterationTree) FillIterationTree(FitBase::GetRW()); return fLikelihood; } //*************************************************** int JointFCN::GetNDOF() { //*************************************************** int totaldof = 0; int count = 0; // Total number of Free bins in each MC prediction for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase* exp = *iter; int dof = exp->GetNDOF(); // Save Seperate DOF if (fIterationTree) { fSampleNDOF[count] = dof; } // Add to total totaldof += dof; count++; } // Loop over pulls for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) { ParamPull* pull = *iter; double dof = pull->GetLikelihood(); // Save seperate DOF if (fIterationTree) { fSampleNDOF[count] = dof; } // Add to total totaldof += dof; count++; } // Set Data Variable fNDOF = totaldof; return totaldof; } //*************************************************** double JointFCN::GetLikelihood() { //*************************************************** LOG(MIN) << std::left << std::setw(43) << "Getting likelihoods..." << " : " << "-2logL" << endl; // Loop and add up likelihoods in an uncorrelated way double like = 0.0; int count = 0; for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase* exp = *iter; double newlike = exp->GetLikelihood(); // Save seperate likelihoods if (fIterationTree) { fSampleLikes[count] = newlike; } LOG(MIN) << "-> " << std::left << std::setw(40) << exp->GetName() << " : " << newlike << endl; // Add Weight Scaling // like *= FitBase::GetRW()->GetSampleLikelihoodWeight(exp->GetName()); // Add to total like += newlike; count++; } // Loop over pulls for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) { ParamPull* pull = *iter; double newlike = pull->GetLikelihood(); // Save seperate likelihoods if (fIterationTree) { fSampleLikes[count] = newlike; } // Add to total like += newlike; count++; } // Set Data Variable fLikelihood = like; return like; }; void JointFCN::LoadSamples(std::vector<nuiskey> samplekeys) { - LOG(MIN) << "Loading Samples " << std::endl; + LOG(MIN) << "Loading Samples : " << samplekeys.size() << std::endl; for (size_t i = 0; i < samplekeys.size(); i++) { nuiskey key = samplekeys[i]; // Get Sample Options std::string samplename = key.GetS("name"); std::string samplefile = key.GetS("input"); std::string sampletype = key.GetS("type"); std::string fakeData = ""; + LOG(MIN) << "Loading Sample : " << samplename << std::endl; + fOutputDir->cd(); MeasurementBase* NewLoadedSample = SampleUtils::CreateSample(key); if (!NewLoadedSample) { ERR(FTL) << "Could not load sample provided: " << samplename << std::endl; ERR(FTL) << "Check spelling with that in src/FCN/SampleList.cxx" << endl; throw; } else { fSamples.push_back(NewLoadedSample); } } } // //*************************************************** // void JointFCN::LoadSamples(std::string cardinput) // //*************************************************** // { // LOG(MIN) << "Initializing Samples" << std::endl; // // Read the card file here and load objects // std::string line; // std::ifstream card(cardinput.c_str(), ifstream::in); // // Make sure they are created in correct working DIR // fOutputDir->cd(); // while (std::getline(card >> std::ws, line, '\n')) { // // Skip Empties // if (line.c_str()[0] == '#') continue; // if (line.empty()) continue; // // Parse line // std::vector<std::string> samplevect = GeneralUtils::ParseToStr(line, " "); // // Sample Inputs // if (!samplevect[0].compare("sample")) { // // Get all inputs // std::string name = samplevect[1]; // std::string files = samplevect[2]; // std::string type = "DEFAULT"; // if (samplevect.size() > 3) type = samplevect[3]; // // Create Sample Class // LOG(MIN) << "Loading up sample: " << name << " << " << files << " (" // << type << ")" << std::endl; // std::string fakeData = ""; // fOutputDir->cd(); // MeasurementBase* NewLoadedSample = SampleUtils::CreateSample(name, files, type, // fakeData, FitBase::GetRW()); // if (!NewLoadedSample) { // ERR(FTL) << "Could not load sample provided: " << name << std::endl; // ERR(FTL) << "Check spelling with that in src/FCN/SampleList.cxx" // << endl; // throw; // } else { // fSamples.push_back(NewLoadedSample); // } // } // // Sample Inputs // if (!samplevect[0].compare("covar") || !samplevect[0].compare("pulls") || // !samplevect[0].compare("throws")) { // // Get all inputs // std::string name = samplevect[1]; // std::string files = samplevect[2]; // std::string type = "DEFAULT"; // if (samplevect.size() > 3) { // type = samplevect[3]; // } else if (!samplevect[0].compare("pull")) { // type = "GAUSPULL"; // } else if (!samplevect[0].compare("throws")) { // type = "GAUSTHROWS"; // } // // Create Pull Class // LOG(MIN) << "Loading up pull term: " << name << " << " << files << " (" // << type << ")" << std::endl; // std::string fakeData = ""; // fOutputDir->cd(); // fPulls.push_back(new ParamPull(name, files, type)); // } // } // card.close(); // }; //*************************************************** void JointFCN::ReconfigureSamples(bool fullconfig) { //*************************************************** int starttime = time(NULL); LOG(REC) << "Starting Reconfigure iter. " << this->fCurIter << endl; // Event Manager Reconf if (fUsingEventManager) { if (!fullconfig and fMCFilled) ReconfigureFastUsingManager(); else ReconfigureUsingManager(); } else { // Loop over all Measurement Classes for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase* exp = *iter; // If RW Either do signal or full reconfigure. if (fDialChanged or !fMCFilled or fullconfig) { if (!fullconfig and fMCFilled) exp->ReconfigureFast(); else exp->Reconfigure(); // If RW Not needed just do normalisation } else { exp->Renormalise(); } } } // Loop over pulls and update for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) { ParamPull* pull = *iter; pull->Reconfigure(); } fMCFilled = true; LOG(MIN) << "Finished Reconfigure iter. " << fCurIter << " in " << time(NULL) - starttime << "s" << endl; fCurIter++; } //*************************************************** void JointFCN::ReconfigureSignal() { //*************************************************** this->ReconfigureSamples(false); } //*************************************************** void JointFCN::ReconfigureAllEvents() { //*************************************************** FitBase::GetRW()->Reconfigure(); FitBase::EvtManager().ResetWeightFlags(); ReconfigureSamples(true); } std::vector<InputHandlerBase*> JointFCN::GetInputList() { std::vector<InputHandlerBase*> InputList; fIsAllSplines = true; MeasListConstIter iterSam = fSamples.begin(); for (; iterSam != fSamples.end(); iterSam++) { MeasurementBase* exp = (*iterSam); std::vector<MeasurementBase*> subsamples = exp->GetSubSamples(); for (size_t i = 0; i < subsamples.size(); i++) { InputHandlerBase* inp = subsamples[i]->GetInput(); if (std::find(InputList.begin(), InputList.end(), inp) == InputList.end()) { if (subsamples[i]->GetInput()->GetType() != kSPLINEPARAMETER) fIsAllSplines = false; InputList.push_back(subsamples[i]->GetInput()); } } } return InputList; } std::vector<MeasurementBase*> JointFCN::GetSubSampleList() { std::vector<MeasurementBase*> SampleList; MeasListConstIter iterSam = fSamples.begin(); for (; iterSam != fSamples.end(); iterSam++) { MeasurementBase* exp = (*iterSam); std::vector<MeasurementBase*> subsamples = exp->GetSubSamples(); for (size_t i = 0; i < subsamples.size(); i++) { SampleList.push_back(subsamples[i]); } } return SampleList; } //*************************************************** void JointFCN::ReconfigureUsingManager() { //*************************************************** // 'Slow' Event Manager Reconfigure LOG(REC) << "Event Manager Reconfigure" << std::endl; int timestart = time(NULL); // Reset all samples MeasListConstIter iterSam = fSamples.begin(); for (; iterSam != fSamples.end(); iterSam++) { MeasurementBase* exp = (*iterSam); exp->ResetAll(); } // If we are siving signal, reset all containers. bool savesignal = (FitPar::Config().GetParB("SignalReconfigures")); if (savesignal) { // Reset all of our event signal vectors fSignalEventBoxes.clear(); fSignalEventFlags.clear(); fSampleSignalFlags.clear(); fSignalEventSplines.clear(); } // Make sure we have a list of inputs if (fInputList.empty()) { fInputList = GetInputList(); fSubSampleList = GetSubSampleList(); } // If all inputs are splines make sure the readers are told // they need to be reconfigured. std::vector<InputHandlerBase*>::iterator inp_iter = fInputList.begin(); if (fIsAllSplines) { for (; inp_iter != fInputList.end(); inp_iter++) { InputHandlerBase* curinput = (*inp_iter); // Tell reader in each BaseEvent it needs a Reconfigure next weight calc. BaseFitEvt* curevent = curinput->FirstBaseEvent(); if (curevent->fSplineRead) { curevent->fSplineRead->SetNeedsReconfigure(true); } } - - } - + } // MAIN INPUT LOOP ==================== int fillcount = 0; int inputcount = 0; inp_iter = fInputList.begin(); // Loop over each input in manager for (; inp_iter != fInputList.end(); inp_iter++) { InputHandlerBase* curinput = (*inp_iter); // Get event information FitEvent* curevent = curinput->FirstNuisanceEvent(); int i = 0; int nevents = curinput->GetNEvents(); int countwidth = nevents / 20; // Start event loop iterating until we get a NULL pointer. while (curevent) { // Get Event Weight curevent->RWWeight = FitBase::GetRW()->CalcWeight(curevent); curevent->Weight = curevent->RWWeight * curevent->InputWeight; double rwweight = curevent->Weight; // Logging if (LOG_LEVEL(REC)) { if (i % countwidth == 0) { LOG(REC) << "Processed " << i << " events. [M, W] = [" << curevent->Mode << ", " << rwweight << "]" << std::endl; } } // Setup flag for if signal found in at least one sample bool foundsignal = false; // Create a new signal bitset for this event std::vector<bool> signalbitset(fSubSampleList.size()); // Create a new signal box vector for this event std::vector<MeasurementVariableBox*> signalboxes; // Start measurement iterator size_t measitercount = 0; std::vector<MeasurementBase*>::iterator meas_iter = fSubSampleList.begin(); // Loop over all subsamples (sub in JointMeas) for (; meas_iter != fSubSampleList.end(); meas_iter++) { MeasurementBase* curmeas = (*meas_iter); // Compare input pointers, to current input, skip if not. // Pointer tells us if it matches without doing ID checks. if (curinput != curmeas->GetInput()) { if (savesignal) { // Set bit to 0 as definitely not signal signalbitset[measitercount] = 0; } // Count up what measurement we are on. measitercount++; // Skip sample as input not signal. continue; } // Fill events for matching inputs. MeasurementVariableBox* box = curmeas->FillVariableBox(curevent); bool signal = curmeas->isSignal(curevent); curmeas->SetSignal(signal); curmeas->FillHistograms(rwweight); // If its Signal tally up fills if (signal) { fillcount++; } // If we are saving signal/splines fill the bitset if (savesignal) { signalbitset[measitercount] = signal; } // If signal save a clone of the event box for use later. if (savesignal and signal) { foundsignal = true; signalboxes.push_back( box->CloneSignalBox() ); } // Keep track of Measurement we are on. measitercount++; } // Once we've filled the measurements, if saving signal // push back if any sample flagged this event as signal if (savesignal) { fSignalEventFlags.push_back(foundsignal); } // Save the vector of signal boxes for this event if (savesignal and foundsignal) { fSignalEventBoxes.push_back(signalboxes); fSampleSignalFlags.push_back(signalbitset); } // If all inputs are splines we can save the spline coefficients // for fast in memory reconfigures later. - if (fIsAllSplines) { + if (fIsAllSplines and savesignal and foundsignal) { // Make temp vector to push back with std::vector<float> coeff; for (size_t l = 0; l < (UInt_t)curevent->fSplineRead->GetNPar(); l++) { coeff.push_back( curevent->fSplineCoeff[l] ); } // Push back to signal event splines. Kept in sync with fSignalEventBoxes size. + int splinecount = fSignalEventSplines.size(); fSignalEventSplines.push_back(coeff); + + // if (splinecount % 1000 == 0) { + // std::cout << "Pushed Back Coeff " << splinecount << " : "; + // for (size_t l = 0; l < fSignalEventSplines[splinecount].size(); l++) { + // std::cout << " " << fSignalEventSplines[splinecount][l]; + // } + // std::cout << std::endl; + // } + } // Clean up vectors once done with this event signalboxes.clear(); signalbitset.clear(); // Iterate to the next event. curevent = curinput->NextNuisanceEvent(); i++; } // Keep track of what input we are on. inputcount++; } // End of Event Loop =============================== // Now event loop is finished loop over all Measurements // Converting Binned events to XSec Distributions iterSam = fSamples.begin(); for (; iterSam != fSamples.end(); iterSam++) { MeasurementBase* exp = (*iterSam); exp->ConvertEventRates(); } // Print out statements on approximate memory usage for profiling. LOG(REC) << "Filled " << fillcount << " signal events." << std::endl; if (savesignal) { int mem = ( //sizeof(fSignalEventBoxes) + // fSignalEventBoxes.size() * sizeof(fSignalEventBoxes.at(0)) + sizeof(MeasurementVariableBox1D) * fillcount) * 1E-6; LOG(REC) << " -> Saved " << fillcount << " signal boxes for faster access. (~" << mem << " MB)" << std::endl; if (fIsAllSplines and !fSignalEventSplines.empty()) { int splmem = sizeof(float) * fSignalEventSplines.size() * fSignalEventSplines[0].size() * 1E-6; - LOG(REC) << " -> Saved " << fillcount << " spline sets into memory. (~" << splmem << " MB)" << std::endl; + LOG(REC) << " -> Saved " << fillcount << " " << fSignalEventSplines.size() << " spline sets into memory. (~" << splmem << " MB)" << std::endl; } } LOG(REC) << "Time taken ReconfigureUsingManager() : " << time(NULL) - timestart << std::endl; // End of reconfigure return; }; //*************************************************** void JointFCN::ReconfigureFastUsingManager() { //*************************************************** // Get Start time for profilling int timestart = time(NULL); // Reset all samples MeasListConstIter iterSam = fSamples.begin(); for (; iterSam != fSamples.end(); iterSam++) { MeasurementBase* exp = (*iterSam); exp->ResetAll(); } // Check for saved variables if not do a full reconfigure. if (fSignalEventFlags.empty()) { ReconfigureUsingManager(); return; } // Setup fast vector iterators. std::vector<bool>::iterator inpsig_iter = fSignalEventFlags.begin(); std::vector< std::vector<MeasurementVariableBox*> >::iterator box_iter = fSignalEventBoxes.begin(); std::vector< std::vector<float> >::iterator spline_iter = fSignalEventSplines.begin(); std::vector< std::vector<bool> >::iterator samsig_iter = fSampleSignalFlags.begin(); + int splinecount = 0; // Setup stuff for logging int fillcount = 0; int nevents = fSignalEventFlags.size(); int countwidth = nevents / 5; // If All Splines tell splines they need a reconfigure. - std::vector<InputHandlerBase*>::iterator inp_iter = fInputList.begin(); - if (fIsAllSplines){ + std::vector<InputHandlerBase*>::iterator inp_iter = fInputList.begin(); + if (fIsAllSplines) { + LOG(REC) << "All Spline Inputs so using fast spline loop." << std::endl; for (; inp_iter != fInputList.end(); inp_iter++) { InputHandlerBase* curinput = (*inp_iter); // Tell each fSplineRead in BaseFitEvent to reconf next weight calc BaseFitEvt* curevent = curinput->FirstBaseEvent(); if (curevent->fSplineRead) curevent->fSplineRead->SetNeedsReconfigure(true); } } // Start of Fast Event Loop ============================ // Start input iterators inp_iter = fInputList.begin(); // Loop over all inputs for (; inp_iter != fInputList.end(); inp_iter++) { InputHandlerBase* curinput = (*inp_iter); // Get Only base event with RW info. BaseFitEvt* curevent = curinput->FirstBaseEvent(); int i = 0; // Iterate over all events and signal flags. while (curevent != 0 and (inpsig_iter != fSignalEventFlags.end())) { // Logging if (LOG_LEVEL(REC)) { if (i % countwidth == 0) { LOG(REC) << "Processed " << i << " signal events."; } } // If event has not been flagged as signal in vector skip it. if (!(*inpsig_iter)) { - inpsig_iter++; - i++; - if (LOG_LEVEL(REC)) { if (i % countwidth == 0) { std::cout << std::endl; } } + inpsig_iter++; + i++; + continue; } // Get The Base Event curevent = curinput->GetBaseEvent(i); // End iterator if NULL pointer at this entry.. if (!curevent) break; - // Setup signal splines pointer for this event if required. + // Setup signal splines pointer for this event if required. if (fIsAllSplines) { curevent->fSplineCoeff = &(*spline_iter)[0]; } // Get Event Weight curevent->RWWeight = FitBase::GetRW()->CalcWeight(curevent); curevent->Weight = curevent->RWWeight * curevent->InputWeight; double rwweight = curevent->Weight; // Weight Logging if (LOG_LEVEL(REC)) { if (i % countwidth == 0) { std::cout << " W = " << rwweight << std::endl; } } // Get iterators for this event std::vector<MeasurementBase*>::iterator meas_iter = fSubSampleList.begin(); std::vector<bool>::iterator subsamsig_iter = (*samsig_iter).begin(); std::vector<MeasurementVariableBox*>::iterator subbox_iter = (*box_iter).begin(); // Loop over all sub measurements. for (; meas_iter != fSubSampleList.end(); meas_iter++, subsamsig_iter++) { MeasurementBase* curmeas = (*meas_iter); // If event flagged as signal for this sample fill from the box. if (*subsamsig_iter) { curmeas->SetSignal(true); curmeas->FillHistogramsFromBox((*subbox_iter), rwweight); // Move onto next box if there is one. subbox_iter++; fillcount++; } } + // if (splinecount % 1000 == 0) { + // std::cout << "Read Back Coeff " << splinecount << " : "; + // for (size_t l = 0; l < fSignalEventSplines[splinecount].size(); l++) { + // std::cout << " " << fSignalEventSplines[splinecount][l]; + // } + // std::cout << std::endl; + // } + // Iterate over the main signal event containers. samsig_iter++; box_iter++; spline_iter++; - + splinecount++; // iterate to next signal event inpsig_iter++; i++; } } // End of Fast Event Loop =================== // Now loop over all Measurements // Convert Binned events iterSam = fSamples.begin(); for (; iterSam != fSamples.end(); iterSam++) { MeasurementBase* exp = (*iterSam); exp->ConvertEventRates(); } // Print some reconfigure profiling. LOG(REC) << "Filled " << fillcount << " signal events." << std::endl; LOG(REC) << "Time taken ReconfigureFastUsingManager() : " << time(NULL) - timestart << std::endl; } //*************************************************** void JointFCN::Write() { //*************************************************** // Loop over individual experiments and call Write LOG(MIN) << "Writing each of the data classes..." << endl; for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase* exp = *iter; exp->Write(); } // Save Pull Terms for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) { ParamPull* pull = *iter; pull->Write(); } if (FitPar::Config().GetParB("EventManager")) { // Get list of inputs std::map<int, InputHandlerBase*> fInputs = FitBase::EvtManager().GetInputs(); std::map<int, InputHandlerBase*>::const_iterator iterInp; for (iterInp = fInputs.begin(); iterInp != fInputs.end(); iterInp++) { InputHandlerBase* input = (iterInp->second); input->GetFluxHistogram()->Write(); input->GetXSecHistogram()->Write(); input->GetEventHistogram()->Write(); } } }; //*************************************************** void JointFCN::SetFakeData(std::string fakeinput) { //*************************************************** LOG(MIN) << "Setting fake data from " << fakeinput << endl; for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase* exp = *iter; exp->SetFakeDataValues(fakeinput); } return; } diff --git a/src/FitBase/EventManager.cxx b/src/FitBase/EventManager.cxx index 57673b2..b159527 100644 --- a/src/FitBase/EventManager.cxx +++ b/src/FitBase/EventManager.cxx @@ -1,137 +1,142 @@ // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret /******************************************************************************* * This file is part of NUISANCE. * * NUISANCE is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NUISANCE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NUISANCE. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ #include "EventManager.h" EventManager* EventManager::m_evtmgrInstance = NULL; EventManager& EventManager::Get(void) { if (!m_evtmgrInstance) { m_evtmgrInstance = new EventManager; } return *m_evtmgrInstance; } FitWeight* EventManager::GetRW() { return fRW; }; InputHandlerBase* EventManager::GetInput(int infile) { return finputs[infile]; }; FitEvent* EventManager::GetEvent(int infile, int i) { /* finputs[infile]->ReadEvent(i); FitEvent* evtpt = finputs[infile]->GetEventPointer(); // If we don't need a full reweight if (!frwneeded[infile][i]) { evtpt->Weight = calc_rw[infile][i]; // if we do need a full reweight } else { evtpt->RWWeight = fRW->CalcWeight(evtpt); evtpt->Weight = evtpt->RWWeight * evtpt->InputWeight; calc_rw[infile][i] = evtpt->Weight; frwneeded[infile][i] = false; } */ return NULL; } double EventManager::GetEventWeight(int infile, int i) { /* if (!frwneeded[infile][i]) { return calc_rw[infile][i]; } finputs[infile]->GetTreeEntry(i); FitEvent* evtpt = finputs[infile]->GetEventPointer(); double Weight = fRW->CalcWeight(evtpt) * evtpt->InputWeight; calc_rw[infile][i] = Weight; frwneeded[infile][i] = false; */ double Weight = 1.0; return Weight; } std::map<int, InputHandlerBase*> EventManager::GetInputs() { return finputs; } InputHandlerBase* EventManager::AddInput(std::string handle, std::string infile) { // Expect INPUTTYPE:FileLocation(s) std::vector<std::string> file_descriptor = GeneralUtils::ParseToStr(infile, ":"); if (file_descriptor.size() != 2) { ERR(FTL) << "File descriptor had no filetype declaration: \"" << infile << "\". expected \"FILETYPE:file.root\"" << std::endl; throw; } InputUtils::InputType inpType = InputUtils::ParseInputType(file_descriptor[0]); int id = GetInputID(file_descriptor[1]); if ((uint)id != fid.size()) { LOG(SAM) << "Event manager already contains " << file_descriptor[1] << std::endl; return finputs[id]; } fid[file_descriptor[1]] = id; finputs[id] = InputUtils::CreateInputHandler(handle, inpType, file_descriptor[1]); frwneeded[id] = std::vector<bool>(finputs[id]->GetNEvents(), true); calc_rw[id] = std::vector<double>(finputs[id]->GetNEvents(), 0.0); LOG(SAM) << "Registered " << handle << " with EventManager." << std::endl; return finputs[id]; } // Reset the weight flags // Should be called for every succesful event loop void EventManager::ResetWeightFlags() { /* // Loop over the inpts for (std::map<int, InputHandler*>::iterator iter = finputs.begin(); iter != finputs.end(); iter++) { int id = iter->first; frwneeded[id].clear(); // Reset so that all events need the reweight frwneeded[id] = std::vector<bool>(finputs[id]->GetNEvents(), true); } */ } EventManager::EventManager() { fRW = new FitWeight("FitWeight"); finputs.clear(); }; EventManager::~EventManager() { delete fRW; finputs.clear(); }; int EventManager::GetInputID(std::string infile) { if (fid.find(infile) == fid.end()) { return fid.size(); } return fid[infile]; } +void EventManager::SetRW(FitWeight* rw){ + fRW = rw; +} + + diff --git a/src/FitBase/EventManager.h b/src/FitBase/EventManager.h index 82ea12b..ff8c3ca 100644 --- a/src/FitBase/EventManager.h +++ b/src/FitBase/EventManager.h @@ -1,74 +1,78 @@ // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret /******************************************************************************* * This file is part of NUISANCE. * * NUISANCE is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NUISANCE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NUISANCE. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ #ifndef EVENTMANAGER_H #define EVENTMANAGER_H #include "InputHandler2.h" #include "FitWeight.h" #include "InputUtils.h" // This class is menat to manage one input file for many distributions class EventManager { public: static EventManager& Get(void); FitWeight* GetRW(); + void SetRW(FitWeight* rw); + InputHandlerBase* GetInput(int id); FitEvent* GetEvent(int id, int i); double GetEventWeight(int id, int i); InputHandlerBase* AddInput(std::string handle, std::string infile); void ResetWeightFlags(); int GetInputID(std::string infile); std::map< int, InputHandlerBase* > GetInputs(); protected: EventManager(); ~EventManager(); static EventManager* m_evtmgrInstance; FitWeight* fRW; std::map< std::string, int > fid; std::map< int, InputHandlerBase* > finputs; std::map< int, std::vector< bool > > frwneeded; std::map< int, std::vector< double > > calc_rw; }; namespace FitBase { inline EventManager& EvtManager(){ return EventManager::Get(); }; inline FitWeight* GetRW(){ return EvtManager().GetRW(); }; inline + void SetRW(FitWeight* rw){ EvtManager().SetRW(rw); }; + inline int GetInputID(std::string infile){ return EvtManager().GetInputID(infile); }; inline InputHandlerBase* GetInput(int infile){ return EvtManager().GetInput(infile); }; inline InputHandlerBase* AddInput(std::string handle, std::string infile){ return EvtManager().AddInput(handle, infile); }; } #endif diff --git a/src/FitBase/SplineInputHandler.cxx b/src/FitBase/SplineInputHandler.cxx index 3581470..a4ac669 100644 --- a/src/FitBase/SplineInputHandler.cxx +++ b/src/FitBase/SplineInputHandler.cxx @@ -1,196 +1,195 @@ #include "SplineInputHandler.h" SplineInputHandler::SplineInputHandler(std::string const& handle, std::string const& rawinputs) { LOG(SAM) << "Creating SplineInputHandler : " << handle << std::endl; // Run a joint input handling fName = handle; jointinput = false; jointindexswitch = 0; // Setup the TChain fFitEventTree = new TChain("nuisance_events"); fMaxEvents = FitPar::Config().GetParI("MAXEVENTS"); // Add to TChain fFitEventTree->Add( rawinputs.c_str() ); // Open File for histogram access int evtcounter = 0; TFile* inp_file = new TFile(rawinputs.c_str(), "READ"); if (LOG_LEVEL(SAM)) { std::cout << "\t\t|-> Input File 0" << " : " << rawinputs << std::endl; } // Get Flux/Event hist TH1D* fluxhist = (TH1D*)inp_file->Get( (PlotUtils::GetObjectWithName(inp_file, "nuisance_fluxhist")).c_str()); TH1D* eventhist = (TH1D*)inp_file->Get( (PlotUtils::GetObjectWithName(inp_file, "nuisance_eventhist")).c_str()); // Get N events TTree* neuttree = (TTree*)inp_file->Get("nuisance_events"); int nevents = neuttree->GetEntries(); // Push into individual input vectors jointfluxinputs.push_back( (TH1D*) fluxhist->Clone() ); jointeventinputs.push_back( (TH1D*) eventhist->Clone() ); jointindexlow.push_back(evtcounter); jointindexhigh.push_back(evtcounter + nevents); evtcounter += nevents; // Add to the total flux/event hist if (!fFluxHist) fFluxHist = (TH1D*) fluxhist->Clone(); else fFluxHist->Add(fluxhist); if (!fEventHist) fEventHist = (TH1D*) eventhist->Clone(); else fEventHist->Add(eventhist); // Setup NEvents and the FitEvent fNEvents = fFitEventTree->GetEntries(); fEventType = kNEWSPLINE; fNUISANCEEvent = new FitEvent(); fNUISANCEEvent->SetBranchAddress(fFitEventTree); if (LOG_LEVEL(SAM)) { std::cout << "\t\t|-> Total Entries : " << fNEvents << std::endl << "\t\t|-> Event Integral : " << fEventHist->Integral("width") * 1.E-38 << " events/nucleon" << std::endl << "\t\t|-> Flux Integral : " << fFluxHist->Integral("width") << " /cm2" << std::endl << "\t\t|-> Event/Flux : " << fEventHist->Integral("width") * 1.E-38 / fFluxHist->Integral("width") << " cm2/nucleon" << std::endl; } - // Setup Reader - fSplRead = new SplineReader(); - fSplRead->Read( (TTree*)inp_file->Get("spline_reader") ); - fNUISANCEEvent->fSplineRead = this->fSplRead; - // Load into memory - for (int j = 0; j < fNEvents; j++) { std::vector<float> tempval; fFitEventTree->GetEntry(j); //fSplTree->GetEntry(j); //for (int i = 0; i < fNPar; i++){ // tempval.push_back( fSplineCoeff[i] ); //} //fAllSplineCoeff.push_back(tempval); // if (j % (fNEvents/10) == 0 and j != 0) { // LOG(SAM) << "Pushed " << int(j*100/fNEvents)+1 << "% of spline sets into memory for " << fName // << " (~" << int(sizeof(float)*tempval.size()*fAllSplineCoeff.size()/1.E6) <<"MB)" << std::endl; //} fStartingWeights.push_back(fNUISANCEEvent->SavedRWWeight * fNUISANCEEvent->InputWeight); } fEventType = kSPLINEPARAMETER; // Normalise event histograms for relative flux contributions. for (size_t i = 0; i < jointeventinputs.size(); i++) { TH1D* eventhist = (TH1D*) jointeventinputs.at(i)->Clone(); double scale = double(fNEvents) / fEventHist->Integral("width"); scale *= eventhist->Integral("width"); scale /= double(jointindexhigh[i] - jointindexlow[i]); jointindexscale .push_back(scale); } fEventHist->SetNameTitle((fName + "_EVT").c_str(), (fName + "_EVT").c_str()); fFluxHist->SetNameTitle((fName + "_FLUX").c_str(), (fName + "_FLUX").c_str()); // Setup Max Events if (fMaxEvents > 1 && fMaxEvents < fNEvents) { if (LOG_LEVEL(SAM)) { std::cout << "\t\t|-> Read Max Entries : " << fMaxEvents << std::endl; } fNEvents = fMaxEvents; } // Setup Spline Reader LOG(SAM) << "Loading Spline Reader." << std::endl; + + fSplRead = new SplineReader(); + fSplRead->Read( (TTree*)inp_file->Get("spline_reader") ); + fNUISANCEEvent->fSplineRead = this->fSplRead; + fNPar = fSplRead->GetNPar(); // Setup Friend Spline TTree fSplTree = (TTree*)inp_file->Get("spline_tree"); fSplTree->SetBranchAddress( "SplineCoeff", fSplineCoeff ); fNUISANCEEvent->fSplineCoeff = this->fSplineCoeff; fBaseEvent = static_cast<BaseFitEvt*>(fNUISANCEEvent); }; FitEvent* SplineInputHandler::GetNuisanceEvent(const UInt_t entry) { // Make sure events setup if (entry >= (UInt_t)fNEvents) return NULL; // Reset all variables before tree read fNUISANCEEvent->ResetEvent(); // Read NUISANCE Tree fFitEventTree->GetEntry(entry); fSplTree->GetEntry(entry); fNUISANCEEvent->fSplineCoeff = fSplineCoeff; fNUISANCEEvent->eventid = entry; // Run Initial, FSI, Final, Other ordering. fNUISANCEEvent-> OrderStack(); // Setup Input scaling for joint inputs if (jointinput) { fNUISANCEEvent->InputWeight = fStartingWeights[entry] * GetInputWeight(entry); } else { fNUISANCEEvent->InputWeight = fStartingWeights[entry]; } return fNUISANCEEvent; } double SplineInputHandler::GetInputWeight(int entry) { // Find Switch Scale while ( entry < jointindexlow[jointindexswitch] || entry >= jointindexhigh[jointindexswitch] ) { jointindexswitch++; // Loop Around if (jointindexswitch == jointindexlow.size()) { jointindexswitch = 0; } } return jointindexscale[jointindexswitch]; }; BaseFitEvt* SplineInputHandler::GetBaseEvent(const UInt_t entry) { // Make sure events setup if (entry >= (UInt_t)fNEvents) return NULL; fBaseEvent->eventid = entry; // Set joint scaling if required if (jointinput) { fBaseEvent->InputWeight = fStartingWeights[entry] * GetInputWeight(entry); } else { fBaseEvent->InputWeight = fStartingWeights[entry]; } return fBaseEvent; } void SplineInputHandler::Print() {} diff --git a/src/Routines/SplineRoutines.cxx b/src/Routines/SplineRoutines.cxx index ce08e95..df3e04e 100755 --- a/src/Routines/SplineRoutines.cxx +++ b/src/Routines/SplineRoutines.cxx @@ -1,877 +1,1468 @@ // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret /******************************************************************************* * This file is part of NUISANCE. * * NUISANCE is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NUISANCE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NUISANCE. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ #include "StatusMessage.h" #include "SplineRoutines.h" /* Constructor/Destructor */ //************************ void SplineRoutines::Init() { //************************ fStrategy = "SaveEvents"; fRoutines.clear(); fCardFile = ""; fSampleFCN = NULL; fRW = NULL; fAllowedRoutines = ("SaveEvents,TestEvents,SaveSplineEvents"); }; //************************************* SplineRoutines::~SplineRoutines() { //************************************* }; /* Input Functions */ //************************************* SplineRoutines::SplineRoutines(int argc, char* argv[]) { //************************************* // Initialise Defaults Init(); nuisconfig configuration = Config::Get(); // Default containers std::string cardfile = ""; std::string maxevents = "-1"; int errorcount = 0; int verbocount = 0; std::vector<std::string> xmlcmds; std::vector<std::string> configargs; // Make easier to handle arguments. std::vector<std::string> args = GeneralUtils::LoadCharToVectStr(argc, argv); ParserUtils::ParseArgument(args, "-c", fCardFile, true); ParserUtils::ParseArgument(args, "-o", fOutputFile, false, false); ParserUtils::ParseArgument(args, "-n", maxevents, false, false); ParserUtils::ParseArgument(args, "-f", fStrategy, false, false); ParserUtils::ParseArgument(args, "-i", xmlcmds); ParserUtils::ParseArgument(args, "-q", configargs); ParserUtils::ParseCounter(args, "e", errorcount); ParserUtils::ParseCounter(args, "v", verbocount); ParserUtils::CheckBadArguments(args); // Add extra defaults if none given if (fCardFile.empty() and xmlcmds.empty()) { ERR(FTL) << "No input supplied!" << std::endl; throw; } if (fOutputFile.empty() and !fCardFile.empty()) { fOutputFile = fCardFile + ".root"; ERR(WRN) << "No output supplied so saving it to: " << fOutputFile << std::endl; } else if (fOutputFile.empty()) { ERR(FTL) << "No output file or cardfile supplied!" << std::endl; throw; } // Configuration Setup ============================= // Check no comp key is available nuiskey fCompKey; if (Config::Get().GetNodes("nuiscomp").empty()) { fCompKey = Config::Get().CreateNode("nuiscomp"); } else { fCompKey = Config::Get().GetNodes("nuiscomp")[0]; } if (!fCardFile.empty()) fCompKey.AddS("cardfile", fCardFile); - if (!fOutputFile.empty()) fCompKey.AddS("outputfile", fOutputFile); + fCompKey.AddS("outputfile", fOutputFile); if (!fStrategy.empty()) fCompKey.AddS("strategy", fStrategy); // Load XML Cardfile configuration.LoadConfig( fCompKey.GetS("cardfile"), ""); // Add CMD XML Structs for (size_t i = 0; i < xmlcmds.size(); i++) { configuration.AddXMLLine(xmlcmds[i]); } // Add Config Args for (size_t i = 0; i < configargs.size(); i++) { configuration.OverrideConfig(configargs[i]); } if (maxevents.compare("-1")) { std::cout << "[ NUISANCE ] : Overriding " << "MAXEVENTS=" + maxevents << std::endl; configuration.OverrideConfig("MAXEVENTS=" + maxevents); } // Finish configuration XML configuration.FinaliseConfig(fCompKey.GetS("outputfile") + ".xml"); // Add Error Verbo Lines verbocount += Config::Get().GetParI("VERBOSITY"); errorcount += Config::Get().GetParI("ERROR"); std::cout << "[ NUISANCE ]: Setting VERBOSITY=" << verbocount << std::endl; std::cout << "[ NUISANCE ]: Setting ERROR=" << errorcount << std::endl; FitPar::log_verb = verbocount; LOG_VERB(verbocount); ERR_VERB(errorcount); // Starting Setup // --------------------------- SetupRWEngine(); return; }; /* Setup Functions */ //************************************* void SplineRoutines::SetupRWEngine() { //************************************* fRW = new FitWeight("splineweight"); // std::vector<nuiskey> splinekeys = Config::QueryKeys("spline"); std::vector<nuiskey> parameterkeys = Config::QueryKeys("parameter"); // Add Parameters for (size_t i = 0; i < parameterkeys.size(); i++) { nuiskey key = parameterkeys[i]; std::string parname = key.GetS("name"); std::string partype = key.GetS("type"); double nom = key.GetD("nominal"); fRW->IncludeDial( key.GetS("name"), FitBase::ConvDialType(key.GetS("type")), nom); fRW->SetDialValue( key.GetS("name"), key.GetD("nominal") ); } fRW->Reconfigure(); return; } /* Fitting Functions */ //************************************* void SplineRoutines::UpdateRWEngine(std::map<std::string, double>& updateVals) { //************************************* for (UInt_t i = 0; i < fParams.size(); i++) { std::string name = fParams[i]; if (updateVals.find(name) == updateVals.end()) continue; fRW->SetDialValue(name, updateVals.at(name)); } fRW->Reconfigure(); return; } //************************************* void SplineRoutines::Run() { //************************************* std::cout << "Running " << std::endl; // Parse given routines fRoutines = GeneralUtils::ParseToStr(fStrategy, ","); if (fRoutines.empty()) { ERR(FTL) << "Trying to run ComparisonRoutines with no routines given!" << std::endl; throw; } for (size_t i = 0; i < fRoutines.size(); i++) { LOG(FIT) << "Running Routine: " << fRoutines[i] << std::endl; std::string rout = fRoutines[i]; if (!rout.compare("SaveEvents")) SaveEvents(); else if (!rout.compare("TestEvents")) TestEvents(); else if (!rout.compare("GenerateEventSplines")) GenerateEventSplines(); else if (!rout.compare("TestSplines_1DEventScan")) TestSplines_1DEventScan(); + else if (!rout.compare("TestSplines_NDEventThrow")) TestSplines_NDEventThrow(); + else if (!rout.compare("SaveSplinePlots")) SaveSplinePlots(); + else if (!rout.compare("TestSplines_1DLikelihoodScan")) TestSplines_1DLikelihoodScan(); + else if (!rout.compare("TestSplines_NDLikelihoodThrow")) TestSplines_NDLikelihoodThrow(); } } //************************************* void SplineRoutines::SaveEvents() { //************************************* if (fRW) delete fRW; SetupRWEngine(); fRW->Reconfigure(); fRW->Print(); // Generate a set of nominal events // Method, Loop over inputs, create input handler, then create a ttree std::vector<nuiskey> eventkeys = Config::QueryKeys("events"); for (size_t i = 0; i < eventkeys.size(); i++) { nuiskey key = eventkeys.at(i); // Get I/O std::string inputfilename = key.GetS("input"); if (inputfilename.empty()) { ERR(FTL) << "No input given for set of input events!" << std::endl; throw; } std::string outputfilename = key.GetS("output"); if (outputfilename.empty()) { outputfilename = inputfilename + ".nuisance.root"; ERR(FTL) << "No output give for set of output events! Saving to " << outputfilename << std::endl; } // Make new outputfile TFile* outputfile = new TFile(outputfilename.c_str(), "RECREATE"); outputfile->cd(); // Make a new input handler std::vector<std::string> file_descriptor = GeneralUtils::ParseToStr(inputfilename, ":"); if (file_descriptor.size() != 2) { ERR(FTL) << "File descriptor had no filetype declaration: \"" << inputfilename << "\". expected \"FILETYPE:file.root\"" << std::endl; throw; } InputUtils::InputType inptype = InputUtils::ParseInputType(file_descriptor[0]); InputHandlerBase* input = InputUtils::CreateInputHandler("eventsaver", inptype, file_descriptor[1]); // Get info from inputhandler int nevents = input->GetNEvents(); int countwidth = (nevents / 10); FitEvent* nuisevent = input->FirstNuisanceEvent(); // Setup a TTree to save the event outputfile->cd(); TTree* eventtree = new TTree("nuisance_events", "nuisance_events"); nuisevent->AddBranchesToTree(eventtree); // Loop over all events and fill the TTree int i = 0; // int countwidth = nevents / 5; while (nuisevent) { // Get Event Weight nuisevent->RWWeight = fRW->CalcWeight(nuisevent); // if (nuisevent->RWWeight != 1.0){ // std::cout << "Weight = " << nuisevent->RWWeight << std::endl; // } // Save everything eventtree->Fill(); // Logging if (i % countwidth == 0) { LOG(REC) << "Saved " << i << "/" << nevents << " nuisance events. [M, W] = [" << nuisevent->Mode << ", " << nuisevent->RWWeight << "]" << std::endl; } // iterate nuisevent = input->NextNuisanceEvent(); i++; } // Save flux and close file outputfile->cd(); eventtree->Write(); input->GetFluxHistogram()->Write("nuisance_fluxhist"); input->GetEventHistogram()->Write("nuisance_eventhist"); // Close Output outputfile->Close(); // Delete Inputs delete input; } // remove Keys eventkeys.clear(); // Finished LOG(FIT) << "Finished processing all nuisance events." << std::endl; } //************************************* void SplineRoutines::TestEvents() { //************************************* LOG(FIT) << "Testing events." << std::endl; // Create a new file for the test samples if (!fOutputRootFile) { fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE"); } // Loop over all tests int count = 0; std::vector<nuiskey> testkeys = Config::QueryKeys("sampletest"); for (std::vector<nuiskey>::iterator iter = testkeys.begin(); iter != testkeys.end(); iter++) { nuiskey key = (*iter); // 0. Create new measurement list std::list<MeasurementBase*> samplelist; // 1. Build Sample From Events std::string samplename = key.GetS("name"); std::string eventsid = key.GetS("inputid"); nuiskey eventskey = Config::QueryLastKey("events", "id=" + eventsid); std::string rawfile = eventskey.GetS("input"); LOG(FIT) << "Creating sample " << samplename << std::endl; MeasurementBase* rawsample = SampleUtils::CreateSample(samplename, rawfile, "", "", FitBase::GetRW()); // 2. Build Sample From Nuisance Events std::string eventsfile = eventskey.GetS("output"); LOG(FIT) << "Creating Fit Eevnt Sample " << samplename << " " << eventsfile << std::endl; MeasurementBase* nuissample = SampleUtils::CreateSample(samplename, "FEVENT:" + eventsfile, "", "", FitBase::GetRW()); // 3. Make some folders to save stuff TDirectory* sampledir = (TDirectory*) fOutputRootFile->mkdir(Form((samplename + "_test_%d").c_str(), count)); TDirectory* rawdir = (TDirectory*) sampledir->mkdir("raw"); TDirectory* nuisancedir = (TDirectory*) sampledir->mkdir("nuisance"); TDirectory* difdir = (TDirectory*) sampledir->mkdir("difference"); // 4. Reconfigure both rawdir->cd(); rawsample->Reconfigure(); rawsample->Write(); nuisancedir->cd(); nuissample->Reconfigure(); nuissample->Write(); // 4. Compare Raw to Nuisance Events // Loop over all keyse TIter next(rawdir->GetListOfKeys()); TKey *dirkey; while ((dirkey = (TKey*)next())) { // If not a 1D/2D histogram skip TClass *cl = gROOT->GetClass(dirkey->GetClassName()); if (!cl->InheritsFrom("TH1D") and !cl->InheritsFrom("TH2D")) continue; // Get TH1* from both dir TH1 *rawplot = (TH1*)rawdir->Get(dirkey->GetName()); TH1 *nuisanceplot = (TH1*)nuisancedir->Get(dirkey->GetName()); // Take Difference nuisanceplot->Add(rawplot, -1.0); // Save to dif folder difdir->cd(); nuisanceplot->Write(); } // 5. Tidy Up samplelist.clear(); // Iterator count++; } } //************************************* void SplineRoutines::GenerateEventSplines() { //************************************* if (fRW) delete fRW; SetupRWEngine(); // Setup the spline reader SplineWriter* splwrite = new SplineWriter(fRW); std::vector<nuiskey> splinekeys = Config::QueryKeys("spline"); // Add splines to splinewriter for (std::vector<nuiskey>::iterator iter = splinekeys.begin(); iter != splinekeys.end(); iter++) { nuiskey splkey = (*iter); // Add Spline Info To Reader splwrite->AddSpline(splkey); } splwrite->SetupSplineSet(); // Event Loop // Loop over all events and calculate weights for each parameter set. // Generate a set of nominal events // Method, Loop over inputs, create input handler, then create a ttree std::vector<nuiskey> eventkeys = Config::QueryKeys("events"); for (size_t i = 0; i < eventkeys.size(); i++) { nuiskey key = eventkeys.at(i); // Get I/O std::string inputfilename = key.GetS("input"); if (inputfilename.empty()) { ERR(FTL) << "No input given for set of input events!" << std::endl; throw; } std::string outputfilename = key.GetS("output"); if (outputfilename.empty()) { outputfilename = inputfilename + ".nuisance.root"; ERR(FTL) << "No output give for set of output events! Saving to " << outputfilename << std::endl; } // Make new outputfile TFile* outputfile = new TFile(outputfilename.c_str(), "RECREATE"); outputfile->cd(); // Make a new input handler std::vector<std::string> file_descriptor = GeneralUtils::ParseToStr(inputfilename, ":"); if (file_descriptor.size() != 2) { ERR(FTL) << "File descriptor had no filetype declaration: \"" << inputfilename << "\". expected \"FILETYPE:file.root\"" << std::endl; throw; } InputUtils::InputType inptype = InputUtils::ParseInputType(file_descriptor[0]); InputHandlerBase* input = InputUtils::CreateInputHandler("eventsaver", inptype, file_descriptor[1]); // Get info from inputhandler int nevents = input->GetNEvents(); - int countwidth = (nevents / 1000); + int countwidth = 1000; //(nevents / 1000); FitEvent* nuisevent = input->FirstNuisanceEvent(); // Setup a TTree to save the event outputfile->cd(); TTree* eventtree = new TTree("nuisance_events", "nuisance_events"); // Add a flag that allows just splines to be saved. nuisevent->AddBranchesToTree(eventtree); // Save the spline reader splwrite->Write("spline_reader"); // Setup the spline TTree TTree* splinetree = new TTree("spline_tree", "spline_tree"); splwrite->AddCoefficientsToTree(splinetree); int lasttime = time(NULL); // Loop over all events and fill the TTree while (nuisevent) { // std::cout << "Fitting event " << i << std::endl; // Calculate the weights for each parameter set splwrite->FitSplinesForEvent(nuisevent); // Save everything eventtree->Fill(); splinetree->Fill(); // nuisevent->Print(); // std::cout << "Done with event " << i << std::endl; // sleep(4); // Logging if (i % countwidth == 0) { std::ostringstream timestring; int timeelapsed = time(NULL) - lasttime; if (i != 0 and timeelapsed) { lasttime = time(NULL); int eventsleft = nevents - i; float speed = float(countwidth) / float(timeelapsed); float proj = (float(eventsleft) / float(speed)) / 60 / 60; timestring << proj << " hours remaining."; } LOG(REC) << "Saved " << i << "/" << nevents << " nuisance spline events. " << timestring.str() << std::endl; } // Iterate i++; nuisevent = input->NextNuisanceEvent(); } // Save flux and close file outputfile->cd(); eventtree->Write(); splinetree->Write(); input->GetFluxHistogram()->Write("nuisance_fluxhist"); input->GetEventHistogram()->Write("nuisance_eventhist"); // Close Output outputfile->Close(); // Delete Inputs delete input; } // remove Keys eventkeys.clear(); } //************************************* void SplineRoutines::MergeSplines() { //************************************* // Loop over all 'splinemerge' keys. // Add them to the Merger. // Call setup splines. // Get the key with eventinput // - remaining keys should have splineinput // - Loop over number of entries. // - FillEntry in merger. // - Fill NUISANCEEvent into a new TTree. SplineMerger* splmerge = new SplineMerger(); std::vector<nuiskey> splinekeys = Config::QueryKeys("splinemerge"); for (std::vector<nuiskey>::iterator iter = splinekeys.begin(); iter != splinekeys.end(); iter++) { nuiskey splkey = (*iter); TFile* infile = new TFile(splkey.GetS("input").c_str(), "READ"); splmerge->AddSplineSetFromFile(infile); } splmerge->SetupSplineSet(); // Now get Event File std::vector<nuiskey> eventkeys = Config::QueryKeys("eventmerge"); nuiskey key = eventkeys[0]; std::string inputfilename = key.GetS("input"); // Make a new input handler std::vector<std::string> file_descriptor = GeneralUtils::ParseToStr(inputfilename, ":"); if (file_descriptor.size() != 2) { ERR(FTL) << "File descriptor had no filetype declaration: \"" << inputfilename << "\". expected \"FILETYPE:file.root\"" << std::endl; throw; } InputUtils::InputType inptype = InputUtils::ParseInputType(file_descriptor[0]); InputHandlerBase* input = InputUtils::CreateInputHandler("eventsaver", inptype, file_descriptor[1]); std::string outputfilename = key.GetS("output"); if (outputfilename.empty()) { outputfilename = inputfilename + ".nuisance.root"; ERR(FTL) << "No output give for set of output events! Saving to " << outputfilename << std::endl; } // Make new outputfile TFile* outputfile = new TFile(outputfilename.c_str(), "RECREATE"); outputfile->cd(); // Get info from inputhandler int nevents = input->GetNEvents(); int countwidth = (nevents / 1000); FitEvent* nuisevent = input->FirstNuisanceEvent(); // Setup a TTree to save the event outputfile->cd(); TTree* eventtree = new TTree("nuisance_events", "nuisance_events"); // Add a flag that allows just splines to be saved. nuisevent->AddBranchesToTree(eventtree); // Save the spline reader splmerge->Write("spline_reader"); // Setup the spline TTree TTree* splinetree = new TTree("spline_tree", "spline_tree"); splmerge->AddCoefficientsToTree(splinetree); int lasttime = time(NULL); int i = 0; // Loop over all events and fill the TTree while (nuisevent) { // Calculate the weights for each parameter set splmerge->FillMergedSplines(i); // Save everything eventtree->Fill(); splinetree->Fill(); // Logging if (i % countwidth == 0) { std::ostringstream timestring; int timeelapsed = time(NULL) - lasttime; if (i != 0 and timeelapsed) { lasttime = time(NULL); int eventsleft = nevents - i; float speed = float(countwidth) / float(timeelapsed); float proj = (float(eventsleft) / float(speed)) / 60 / 60; timestring << proj << " hours remaining."; } LOG(REC) << "Saved " << i << "/" << nevents << " nuisance spline events. " << timestring.str() << std::endl; } // Iterate i++; nuisevent = input->NextNuisanceEvent(); } // Save flux and close file outputfile->cd(); eventtree->Write(); splinetree->Write(); input->GetFluxHistogram()->Write("nuisance_fluxhist"); input->GetEventHistogram()->Write("nuisance_eventhist"); // Close Output outputfile->Close(); // Delete Inputs delete input; } //************************************* void SplineRoutines::TestSplines_1DEventScan() { //************************************* // Setup RW Engine if (fRW) delete fRW; SetupRWEngine(); // Make a spline RW Engine too. FitWeight* splweight = new FitWeight("splinerwaweight"); // std::vector<nuiskey> splinekeys = Config::QueryKeys("spline"); std::vector<nuiskey> parameterkeys = Config::QueryKeys("parameter"); TH1D* parhisttemplate = new TH1D("parhist", "parhist", parameterkeys.size(), 0.0, float(parameterkeys.size())); // Add Parameters for (size_t i = 0; i < parameterkeys.size(); i++) { nuiskey key = parameterkeys[i]; std::string parname = key.GetS("name"); std::string partype = key.GetS("type"); double nom = key.GetD("nominal"); - parhisttemplate->SetBinContent(i+1, nom); - parhisttemplate->GetXaxis()->SetBinLabel(i+1, parname.c_str()); + parhisttemplate->SetBinContent(i + 1, nom); + parhisttemplate->GetXaxis()->SetBinLabel(i + 1, parname.c_str()); splweight->IncludeDial( key.GetS("name"), kSPLINEPARAMETER, nom); splweight->SetDialValue( key.GetS("name"), key.GetD("nominal") ); } splweight->Reconfigure(); // Make a high resolution spline set. std::vector<double> nomvals = fRW->GetDialValues(); int testres = FitPar::Config().GetParI("spline_test_resolution"); - std::vector< std::string > scanparset_names; std::vector< std::vector<double> > scanparset_vals; std::vector< TH1D* > scanparset_hists; // Loop over all params // Add Parameters for (size_t i = 0; i < parameterkeys.size(); i++) { nuiskey key = parameterkeys[i]; // Get Par Name std::string name = key.GetS("name"); if (!key.Has("low") or !key.Has("high") or !key.Has("step")) { continue; } // Push Back Scan double low = key.GetD("low"); double high = key.GetD("high"); double cur = low; double step = key.GetD("step"); while (cur <= high) { // Make new set std::vector<double> newvals = nomvals; newvals[i] = cur; // Add to vects - scanparset_names.push_back(name); scanparset_vals.push_back(newvals); TH1D* parhist = (TH1D*)parhisttemplate->Clone(); for (size_t j = 0; j < newvals.size(); j++) { parhist->SetBinContent(j + 1, newvals[j]); } scanparset_hists.push_back(parhist); // Move to next one cur += step; } } // Print out the parameter set to test - for (int i = 0; i < scanparset_names.size(); i++) { + for (int i = 0; i < scanparset_vals.size(); i++) { std::cout << "Parset " << i; for (int j = 0 ; j < scanparset_vals[i].size(); j++) { std::cout << " " << scanparset_vals[i][j]; } std::cout << std::endl; } // Weight holders double* rawweights = new double[scanparset_vals.size()]; double* splweights = new double[scanparset_vals.size()]; double* difweights = new double[scanparset_vals.size()]; int NParSets = scanparset_vals.size(); // Loop over all event I/O std::vector<nuiskey> eventkeys = Config::QueryKeys("events"); for (size_t i = 0; i < eventkeys.size(); i++) { nuiskey key = eventkeys.at(i); // Get I/O std::string inputfilename = key.GetS("input"); if (inputfilename.empty()) { ERR(FTL) << "No input given for set of input events!" << std::endl; throw; } std::string outputfilename = key.GetS("output"); if (outputfilename.empty()) { outputfilename = inputfilename + ".nuisance.root"; ERR(FTL) << "No output give for set of output events! Saving to " << outputfilename << std::endl; } // Make a new input handler std::vector<std::string> file_descriptor = GeneralUtils::ParseToStr(inputfilename, ":"); if (file_descriptor.size() != 2) { ERR(FTL) << "File descriptor had no filetype declaration: \"" << inputfilename << "\". expected \"FILETYPE:file.root\"" << std::endl; throw; } InputUtils::InputType inptype = InputUtils::ParseInputType(file_descriptor[0]); // Make handlers for input and output InputHandlerBase* input = InputUtils::CreateInputHandler("rawevents", inptype, file_descriptor[1]); InputHandlerBase* output = InputUtils::CreateInputHandler("splineevents", InputUtils::kEVSPLN_Input, outputfilename); // Get Base Events for each case. FitEvent* rawevent = input->FirstNuisanceEvent(); FitEvent* splevent = output->FirstNuisanceEvent(); // Setup outputfile std::string outputtest = outputfilename + ".splinetest.1DEventScan.root"; TFile* outputtestfile = new TFile(outputtest.c_str(), "RECREATE"); outputtestfile->cd(); // Save Parameter Sets for (size_t i = 0; i < scanparset_hists.size(); i++) { - scanparset_hists[i]->Write(Form("Paramater_Set_%i",(int)i)); + scanparset_hists[i]->Write(Form("Paramater_Set_%i", (int)i)); + } + + // Save a TTree of weights and differences. + TTree* weighttree = new TTree("weightscan", "weightscan"); + + // Make a branch for each weight set + for (size_t i = 0; i < scanparset_hists.size(); i++) { + weighttree->Branch(Form("RawWeights_Set_%i", (int)i), &rawweights[i], Form("RawWeights_Set_%i/D", (int)i) ); + weighttree->Branch(Form("SplineWeights_Set_%i", (int)i), &splweights[i], Form("SplineWeights_Set_%i/D", (int)i) ); + weighttree->Branch(Form("DifWeights_Set_%i", (int)i), &difweights[i], Form("DifWeights_Set_%i/D", (int)i) ); + + } + + // Count + int i = 0; + int nevents = input->GetNEvents(); + while (rawevent and splevent) { + + // Loop over 1D parameter sets. + for (size_t j = 0; j < scanparset_vals.size(); j++) { + + // Reconfigure + fRW->SetAllDials(&scanparset_vals[j][0], scanparset_vals[j].size()); + fRW->Reconfigure(); + + // Reconfigure spline RW + splweight->SetAllDials(&scanparset_vals[j][0], scanparset_vals[j].size()); + splweight->Reconfigure(); + + splevent->fSplineRead->SetNeedsReconfigure(true); + + // Calc weight for both events + rawweights[j] = fRW->CalcWeight(rawevent); + splweights[j] = splweight->CalcWeight(splevent); + difweights[j] = splweights[j] - rawweights[j]; + } + + + if (i % 1000 == 0) { + LOG(FIT) << "Processed " << i << "/" << nevents << std::endl; + } + + // Fill Array + weighttree->Fill(); + + // Iterate to next event. + i++; + rawevent = input->NextNuisanceEvent(); + splevent = output->NextNuisanceEvent(); + } + + outputtestfile->cd(); + weighttree->Write(); + outputtestfile->Close(); + } +} + + + +//************************************* +void SplineRoutines::TestSplines_NDEventThrow() { +//************************************* + + // Setup RW Engine + if (fRW) delete fRW; + SetupRWEngine(); + + // Make a spline RW Engine too. + FitWeight* splweight = new FitWeight("splinerwaweight"); + std::vector<nuiskey> parameterkeys = Config::QueryKeys("parameter"); + TH1D* parhisttemplate = new TH1D("parhist", "parhist", parameterkeys.size(), 0.0, float(parameterkeys.size())); + + // Add Parameters + for (size_t i = 0; i < parameterkeys.size(); i++) { + nuiskey key = parameterkeys[i]; + + std::string parname = key.GetS("name"); + std::string partype = key.GetS("type"); + double nom = key.GetD("nominal"); + + parhisttemplate->SetBinContent(i + 1, nom); + parhisttemplate->GetXaxis()->SetBinLabel(i + 1, parname.c_str()); + + splweight->IncludeDial( key.GetS("name"), + kSPLINEPARAMETER, nom); + splweight->SetDialValue( key.GetS("name"), key.GetD("nominal") ); + + } + splweight->Reconfigure(); + + // Make a high resolution spline set. + std::vector<double> nomvals = fRW->GetDialValues(); + int testres = FitPar::Config().GetParI("spline_test_resolution"); + + std::vector< std::string > scanparset_names; + std::vector< std::vector<double> > scanparset_vals; + std::vector< TH1D* > scanparset_hists; + + // Loop over all params + // Add Parameters + int nthrows = FitPar::Config().GetParI("spline_test_throws"); + for (int i = 0; i < nthrows; i++) { + + std::vector<double> newvals = nomvals; + + for (size_t j = 0; j < parameterkeys.size(); j++) { + nuiskey key = parameterkeys[j]; + + if (!key.Has("low") or !key.Has("high") or !key.Has("step")) { + continue; + } + + // Push Back Scan + double low = key.GetD("low"); + double high = key.GetD("high"); + newvals[j] = gRandom->Uniform(low, high); + + } + // Add to vects + scanparset_vals.push_back(newvals); + + TH1D* parhist = (TH1D*)parhisttemplate->Clone(); + for (size_t j = 0; j < newvals.size(); j++) { + parhist->SetBinContent(j + 1, newvals[j]); + } + scanparset_hists.push_back(parhist); + } + + // Print out the parameter set to test + for (int i = 0; i < scanparset_vals.size(); i++) { + std::cout << "Parset " << i; + for (int j = 0 ; j < scanparset_vals[i].size(); j++) { + std::cout << " " << scanparset_vals[i][j]; + } + std::cout << std::endl; + } + + + // Weight holders + double* rawweights = new double[scanparset_vals.size()]; + double* splweights = new double[scanparset_vals.size()]; + double* difweights = new double[scanparset_vals.size()]; + + int NParSets = scanparset_vals.size(); + + // Loop over all event I/O + std::vector<nuiskey> eventkeys = Config::QueryKeys("events"); + for (size_t i = 0; i < eventkeys.size(); i++) { + nuiskey key = eventkeys.at(i); + + // Get I/O + std::string inputfilename = key.GetS("input"); + if (inputfilename.empty()) { + ERR(FTL) << "No input given for set of input events!" << std::endl; + throw; + } + + std::string outputfilename = key.GetS("output"); + if (outputfilename.empty()) { + outputfilename = inputfilename + ".nuisance.root"; + ERR(FTL) << "No output give for set of output events! Saving to " + << outputfilename << std::endl; + } + + // Make a new input handler + std::vector<std::string> file_descriptor = + GeneralUtils::ParseToStr(inputfilename, ":"); + if (file_descriptor.size() != 2) { + ERR(FTL) << "File descriptor had no filetype declaration: \"" << inputfilename + << "\". expected \"FILETYPE:file.root\"" << std::endl; + throw; + } + InputUtils::InputType inptype = + InputUtils::ParseInputType(file_descriptor[0]); + + + // Make handlers for input and output + InputHandlerBase* input = InputUtils::CreateInputHandler("rawevents", inptype, file_descriptor[1]); + InputHandlerBase* output = InputUtils::CreateInputHandler("splineevents", InputUtils::kEVSPLN_Input, outputfilename); + + // Get Base Events for each case. + FitEvent* rawevent = input->FirstNuisanceEvent(); + FitEvent* splevent = output->FirstNuisanceEvent(); + + + // Setup outputfile + std::string outputtest = outputfilename + ".splinetest.NDEventThrow.root"; + TFile* outputtestfile = new TFile(outputtest.c_str(), "RECREATE"); + outputtestfile->cd(); + + // Save Parameter Sets + for (size_t i = 0; i < scanparset_hists.size(); i++) { + scanparset_hists[i]->Write(Form("Paramater_Set_%i", (int)i)); } // Save a TTree of weights and differences. TTree* weighttree = new TTree("weightscan", "weightscan"); // Make a branch for each weight set for (size_t i = 0; i < scanparset_hists.size(); i++) { weighttree->Branch(Form("RawWeights_Set_%i", (int)i), &rawweights[i], Form("RawWeights_Set_%i/D", (int)i) ); weighttree->Branch(Form("SplineWeights_Set_%i", (int)i), &splweights[i], Form("SplineWeights_Set_%i/D", (int)i) ); weighttree->Branch(Form("DifWeights_Set_%i", (int)i), &difweights[i], Form("DifWeights_Set_%i/D", (int)i) ); } // Count int i = 0; int nevents = input->GetNEvents(); while (rawevent and splevent) { // Loop over 1D parameter sets. for (size_t j = 0; j < scanparset_vals.size(); j++) { // Reconfigure fRW->SetAllDials(&scanparset_vals[j][0], scanparset_vals[j].size()); fRW->Reconfigure(); // Reconfigure spline RW splweight->SetAllDials(&scanparset_vals[j][0], scanparset_vals[j].size()); splweight->Reconfigure(); splevent->fSplineRead->SetNeedsReconfigure(true); // Calc weight for both events rawweights[j] = fRW->CalcWeight(rawevent); splweights[j] = splweight->CalcWeight(splevent); difweights[j] = splweights[j] - rawweights[j]; } if (i % 1000 == 0) { LOG(FIT) << "Processed " << i << "/" << nevents << std::endl; } // Fill Array weighttree->Fill(); // Iterate to next event. i++; rawevent = input->NextNuisanceEvent(); splevent = output->NextNuisanceEvent(); } outputtestfile->cd(); weighttree->Write(); outputtestfile->Close(); } } +void SplineRoutines::SaveSplinePlots() { + + if (fRW) delete fRW; + SetupRWEngine(); + + // Setup the spline reader + SplineWriter* splwrite = new SplineWriter(fRW); + std::vector<nuiskey> splinekeys = Config::QueryKeys("spline"); + + // Add splines to splinewriter + for (std::vector<nuiskey>::iterator iter = splinekeys.begin(); + iter != splinekeys.end(); iter++) { + nuiskey splkey = (*iter); + + // Add Spline Info To Reader + splwrite->AddSpline(splkey); + } + splwrite->SetupSplineSet(); + + + + // Event Loop + // Loop over all events and calculate weights for each parameter set. + + // Generate a set of nominal events + // Method, Loop over inputs, create input handler, then create a ttree + std::vector<nuiskey> eventkeys = Config::QueryKeys("events"); + for (size_t i = 0; i < eventkeys.size(); i++) { + nuiskey key = eventkeys.at(i); + + // Get I/O + std::string inputfilename = key.GetS("input"); + if (inputfilename.empty()) { + ERR(FTL) << "No input given for set of input events!" << std::endl; + throw; + } + + std::string outputfilename = key.GetS("output"); + if (outputfilename.empty()) { + outputfilename = inputfilename + ".nuisance.root"; + ERR(FTL) << "No output give for set of output events! Saving to " + << outputfilename << std::endl; + } + + // Make new outputfile + outputfilename += ".SplinePlots.root"; + TFile* outputfile = new TFile(outputfilename.c_str(), "RECREATE"); + outputfile->cd(); + + // Make a new input handler + std::vector<std::string> file_descriptor = + GeneralUtils::ParseToStr(inputfilename, ":"); + if (file_descriptor.size() != 2) { + ERR(FTL) << "File descriptor had no filetype declaration: \"" << inputfilename + << "\". expected \"FILETYPE:file.root\"" << std::endl; + throw; + } + InputUtils::InputType inptype = + InputUtils::ParseInputType(file_descriptor[0]); + + InputHandlerBase* input = InputUtils::CreateInputHandler("eventsaver", inptype, file_descriptor[1]); + + // Get info from inputhandler + int nevents = input->GetNEvents(); + int countwidth = (nevents / 1000); + FitEvent* nuisevent = input->FirstNuisanceEvent(); + + outputfile->cd(); + + int lasttime = time(NULL); + TCanvas* fitcanvas = NULL; + + // Loop over all events and fill the TTree + while (nuisevent) { + + // std::cout << "Fitting event " << i << std::endl; + // Calculate the weights for each parameter set + splwrite->FitSplinesForEvent(nuisevent, fitcanvas, true); + + if (fitcanvas) { + outputfile->cd(); + fitcanvas->Write(Form("Event_SplineCanvas_%i", (int)i)); + } + + // Logging + if (i % countwidth == 0) { + LOG(REC) << "Saved " << i << "/" << nevents << " nuisance spline plots. " << std::endl; + } + + // Iterate + i++; + nuisevent = input->NextNuisanceEvent(); + } + // Save flux and close file + outputfile->cd(); + + // Close Output + outputfile->Close(); + + // Delete Inputs + delete input; + } + + // remove Keys + eventkeys.clear(); + +} + +void SplineRoutines::TestSplines_NDLikelihoodThrow() { + + // Setup RW Engine + if (fRW) delete fRW; + SetupRWEngine(); + + // Make a spline RW Engine too. + FitWeight* splweight = new FitWeight("splinerwaweight"); + std::vector<nuiskey> parameterkeys = Config::QueryKeys("parameter"); + TH1D* parhisttemplate = new TH1D("parhist", "parhist", parameterkeys.size(), 0.0, float(parameterkeys.size())); + + // Add Parameters + for (size_t i = 0; i < parameterkeys.size(); i++) { + nuiskey key = parameterkeys[i]; + + std::string parname = key.GetS("name"); + std::string partype = key.GetS("type"); + double nom = key.GetD("nominal"); + + parhisttemplate->SetBinContent(i + 1, nom); + parhisttemplate->GetXaxis()->SetBinLabel(i + 1, parname.c_str()); + + splweight->IncludeDial( key.GetS("name"), + kSPLINEPARAMETER, nom); + splweight->SetDialValue( key.GetS("name"), key.GetD("nominal") ); + + } + splweight->Reconfigure(); + + // Make a high resolution spline set. + std::vector<double> nomvals = fRW->GetDialValues(); + int testres = FitPar::Config().GetParI("spline_test_resolution"); + + std::vector< std::string > scanparset_names; + std::vector< std::vector<double> > scanparset_vals; + std::vector< TH1D* > scanparset_hists; + + // Loop over all params + // Add Parameters + int nthrows = FitPar::Config().GetParI("spline_test_throws"); + for (int i = 0; i < nthrows; i++) { + + std::vector<double> newvals = nomvals; + + for (size_t j = 0; j < parameterkeys.size(); j++) { + nuiskey key = parameterkeys[j]; + + if (!key.Has("low") or !key.Has("high") or !key.Has("step")) { + continue; + } + + // Push Back Scan + double low = key.GetD("low"); + double high = key.GetD("high"); + newvals[j] = gRandom->Uniform(low, high); + + } + // Add to vects + scanparset_vals.push_back(newvals); + + TH1D* parhist = (TH1D*)parhisttemplate->Clone(); + for (size_t j = 0; j < newvals.size(); j++) { + parhist->SetBinContent(j + 1, newvals[j]); + } + scanparset_hists.push_back(parhist); + } + + // Print out the parameter set to test + for (int i = 0; i < scanparset_vals.size(); i++) { + std::cout << "Parset " << i; + for (int j = 0 ; j < scanparset_vals[i].size(); j++) { + std::cout << " " << scanparset_vals[i][j]; + } + std::cout << std::endl; + } + + // Make a new set of Raw/Spline Sample Keys + std::vector<nuiskey> eventkeys = Config::QueryKeys("events"); + std::vector<nuiskey> testkeys = Config::QueryKeys("sampletest"); + + std::vector<nuiskey> rawkeys; + std::vector<nuiskey> splkeys; + + + for (std::vector<nuiskey>::iterator iter = testkeys.begin(); + iter != testkeys.end(); iter++) { + nuiskey key = (*iter); + + std::string samplename = key.GetS("name"); + std::string eventsid = key.GetS("inputid"); + nuiskey eventskey = Config::QueryLastKey("events", "id=" + eventsid); + std::string rawfile = eventskey.GetS("input"); + std::string splfile = eventskey.GetS("output"); + + nuiskey rawkeytemp = Config::CreateKey("sample"); + rawkeytemp.SetS("name", samplename); + rawkeytemp.SetS("input", rawfile); + + nuiskey splkeytemp = Config::CreateKey("sample"); + splkeytemp.SetS("name", samplename); + splkeytemp.SetS("input", "EVSPLN:" + splfile); + + rawkeys.push_back(rawkeytemp); + splkeys.push_back(splkeytemp); + } + + if (fOutputRootFile) delete fOutputRootFile; + fOutputRootFile = new TFile(fOutputFile.c_str(), "RECREATE"); + + fOutputRootFile->ls(); + // Make two new JointFCN + JointFCN* rawfcn = new JointFCN(rawkeys, fOutputRootFile); + JointFCN* splfcn = new JointFCN(splkeys, fOutputRootFile); + + // Create iteration tree in output file + fOutputRootFile->cd(); + rawfcn->CreateIterationTree("raw_iterations", fRW); + splfcn->CreateIterationTree("spl_iterations", splweight); + + // Loop over parameter sets. + for (size_t j = 0; j < scanparset_vals.size(); j++) { + + FitBase::SetRW(fRW); + double rawtotal = rawfcn->DoEval(&scanparset_vals[j][0]); + + FitBase::SetRW(splweight); + double spltotal = splfcn->DoEval(&scanparset_vals[j][0]); + + LOG(FIT) << "RAW SPLINE DIF = " << rawtotal << " " << spltotal << " " << spltotal - rawtotal << std::endl; + } + + fOutputRootFile->cd(); + + rawfcn->WriteIterationTree(); + splfcn->WriteIterationTree(); + +} + + +void SplineRoutines::TestSplines_1DLikelihoodScan() { + + // Setup RW Engine. + if (fRW) delete fRW; + SetupRWEngine(); + + // Setup Parameter Set. + // Make a spline RW Engine too. + FitWeight* splweight = new FitWeight("splinerwaweight"); + // std::vector<nuiskey> splinekeys = Config::QueryKeys("spline"); + std::vector<nuiskey> parameterkeys = Config::QueryKeys("parameter"); + TH1D* parhisttemplate = new TH1D("parhist", "parhist", parameterkeys.size(), 0.0, float(parameterkeys.size())); + + // Add Parameters + for (size_t i = 0; i < parameterkeys.size(); i++) { + nuiskey key = parameterkeys[i]; + + std::string parname = key.GetS("name"); + std::string partype = key.GetS("type"); + double nom = key.GetD("nominal"); + + parhisttemplate->SetBinContent(i + 1, nom); + parhisttemplate->GetXaxis()->SetBinLabel(i + 1, parname.c_str()); + + splweight->IncludeDial( key.GetS("name"), + kSPLINEPARAMETER, nom); + splweight->SetDialValue( key.GetS("name"), key.GetD("nominal") ); + + } + splweight->Reconfigure(); + + // Make a high resolution spline set. + std::vector<double> nomvals = fRW->GetDialValues(); + int testres = FitPar::Config().GetParI("spline_test_resolution"); + + std::vector< std::vector<double> > scanparset_vals; + std::vector< TH1D* > scanparset_hists; + + // Loop over all params + // Add Parameters + for (size_t i = 0; i < parameterkeys.size(); i++) { + nuiskey key = parameterkeys[i]; + + // Get Par Name + std::string name = key.GetS("name"); + + if (!key.Has("low") or !key.Has("high") or !key.Has("step")) { + continue; + } + + // Push Back Scan + double low = key.GetD("low"); + double high = key.GetD("high"); + double cur = low; + double step = key.GetD("step"); + + while (cur <= high) { + + // Make new set + std::vector<double> newvals = nomvals; + newvals[i] = cur; + + // Add to vects + scanparset_vals.push_back(newvals); + + TH1D* parhist = (TH1D*)parhisttemplate->Clone(); + for (size_t j = 0; j < newvals.size(); j++) { + parhist->SetBinContent(j + 1, newvals[j]); + } + scanparset_hists.push_back(parhist); + + + // Move to next one + cur += step; + } + } + + // Print out the parameter set to test + for (int i = 0; i < scanparset_vals.size(); i++) { + std::cout << "Parset " << i; + for (int j = 0 ; j < scanparset_vals[i].size(); j++) { + std::cout << " " << scanparset_vals[i][j]; + } + std::cout << std::endl; + } + + // Make a new set of Raw/Spline Sample Keys + std::vector<nuiskey> eventkeys = Config::QueryKeys("events"); + std::vector<nuiskey> testkeys = Config::QueryKeys("sampletest"); + + std::vector<nuiskey> rawkeys; + std::vector<nuiskey> splkeys; + + + for (std::vector<nuiskey>::iterator iter = testkeys.begin(); + iter != testkeys.end(); iter++) { + nuiskey key = (*iter); + + std::string samplename = key.GetS("name"); + std::string eventsid = key.GetS("inputid"); + nuiskey eventskey = Config::QueryLastKey("events", "id=" + eventsid); + std::string rawfile = eventskey.GetS("input"); + std::string splfile = eventskey.GetS("output"); + + nuiskey rawkeytemp = Config::CreateKey("sample"); + rawkeytemp.SetS("name", samplename); + rawkeytemp.SetS("input", rawfile); + + nuiskey splkeytemp = Config::CreateKey("sample"); + splkeytemp.SetS("name", samplename); + splkeytemp.SetS("input", "EVSPLN:" + splfile); + + rawkeys.push_back(rawkeytemp); + splkeys.push_back(splkeytemp); + } + + if (fOutputRootFile) delete fOutputRootFile; + fOutputRootFile = new TFile(fOutputFile.c_str(), "RECREATE"); + + fOutputRootFile->ls(); + // Make two new JointFCN + JointFCN* rawfcn = new JointFCN(rawkeys, fOutputRootFile); + JointFCN* splfcn = new JointFCN(splkeys, fOutputRootFile); + + // Create iteration tree in output file + fOutputRootFile->cd(); + rawfcn->CreateIterationTree("raw_iterations", fRW); + splfcn->CreateIterationTree("spl_iterations", splweight); + + // Loop over parameter sets. + for (size_t j = 0; j < scanparset_vals.size(); j++) { + + FitBase::SetRW(fRW); + double rawtotal = rawfcn->DoEval(&scanparset_vals[j][0]); + + FitBase::SetRW(splweight); + double spltotal = splfcn->DoEval(&scanparset_vals[j][0]); + + LOG(FIT) << "RAW SPLINE DIF = " << rawtotal << " " << spltotal << " " << spltotal - rawtotal << std::endl; + } + + fOutputRootFile->cd(); + + rawfcn->WriteIterationTree(); + splfcn->WriteIterationTree(); + +} + + /* MISC Functions */ //************************************* int SplineRoutines::GetStatus() { //************************************* return 0; } diff --git a/src/Routines/SplineRoutines.h b/src/Routines/SplineRoutines.h index 58b05a0..54170a9 100755 --- a/src/Routines/SplineRoutines.h +++ b/src/Routines/SplineRoutines.h @@ -1,197 +1,194 @@ // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret /******************************************************************************* * This file is part of NUISANCE. * * NUISANCE is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NUISANCE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NUISANCE. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ #ifndef SPLINE_ROUTINES_H #define SPLINE_ROUTINES_H /*! * \addtogroup Minimizer * @{ */ #include "TH1.h" #include "TF1.h" #include "TMatrixD.h" #include "TVectorD.h" #include "TSystem.h" #include "TFile.h" #include "TProfile.h" #include <vector> #include <string> #include <iostream> #include <sstream> #include <cstring> #include "FitEvent.h" #include "JointFCN.h" #include "FitParameters.h" #include "FitLogger.h" #include "BaseFitEvt.h" #include "NuisConfig.h" #include "NuisKey.h" #include "SplineReader.h" #include "SplineWriter.h" #include "SplineMerger.h" #include "ParserUtils.h" enum minstate { kErrorStatus = -1, kGoodStatus, kFitError, kNoChange, kFitFinished, kFitUnfinished, kStateChange, }; //************************************* //! Collects all possible fit routines into a single class to avoid repeated code class SplineRoutines{ //************************************* public: /* Constructor/Destructor */ //! Constructor reads in arguments given at the command line for the fit here. SplineRoutines(int argc, char* argv[]); //! Default destructor ~SplineRoutines(); //! Reset everything to default/NULL void Init(); /* Input Functions */ //! Splits the arguments ready for initial setup void ParseArgs(int argc, char* argv[]); /* Setup Functions */ //! Setup the configuration given the arguments passed at the commandline and card file void SetupConfig(); //! Setups up our custom RW engine with all the parameters passed in the card file void SetupRWEngine(); void Run(); void SaveEvents(); void TestEvents(); void GenerateEventSplines(); /* Testing Functions */ /// Scan parameter space in 1D at finer resolution than points. Compare Raw/Spline on an event by event basis. void TestSplines_1DEventScan(); /// Scan parameter space in 1D at finer resolution than points. Compare likelihoods for all testsamples. - void TestSplines_1DLikelihoodScan(){}; - - /// Scan parameter space in 2D at 0.5 point resolution, compare average weight difference. - void TestSplines_2DEventScan(){}; - - /// Scan parameter space in 2D at 0.5 point resolution, compare likelihoods for all testsamples. - void TestSplines_2DLikelihoodScan(){}; + void TestSplines_1DLikelihoodScan(); /// Randomly throw in parameter space. For each throw, calc average weight difference. - void TestSplines_NDEventThrow(){}; + void TestSplines_NDEventThrow(); /// Randomly thow in parameter space. For each throw, calc likelihood difference for each sample. - void TestSplines_NDLikelihoodThrow(){}; + void TestSplines_NDLikelihoodThrow(); + + /// Generate a set of spline vs weight canvases and save to file + void SaveSplinePlots(); /* Fitting Functions */ //! Given a new map change the values that the RW engine is currently set to void UpdateRWEngine(std::map<std::string,double>& updateVals); /* MISC Functions */ //! Get previous fit status from a file Int_t GetStatus(); void MergeSplines(); protected: //! Our Custom ReWeight Object FitWeight* rw; FitWeight* fRW; std::string fOutputFile; std::string fInputFile; TFile* fInputRootFile; TFile* fOutputRootFile; JointFCN* fSampleFCN; std::list<MeasurementBase*> fSamples; std::string fCardFile; std::string fStrategy; std::vector<std::string> fRoutines; std::string fAllowedRoutines; // Input Dial Vals //! Vector of dial names std::vector<std::string> fParams; std::map<std::string, std::string> fStateVals; std::map<std::string, double> fStartVals; std::map<std::string, double> fCurVals; std::map<std::string, double> fErrorVals; std::map<std::string, double> fMinVals; std::map<std::string, double> fMaxVals; std::map<std::string, double> fStepVals; std::map<std::string, int> fTypeVals; std::map<std::string, bool> fFixVals; std::map<std::string, bool> fStartFixVals; std::vector<std::string> fGenericInputNames; std::map<std::string, std::string> fGenericInputFiles; std::map<std::string, std::string> fGenericOutputFiles; std::map<std::string, std::string> fGenericOutputTypes; std::map<std::string, InputHandlerBase*> fGenericInputs; std::vector<std::string> fSplineNames; std::map<std::string, std::string> fSplineTypes; std::map<std::string, std::string> fSplinePoints; nuiskey fCompKey; }; /*! @} */ #endif diff --git a/src/Splines/CMakeLists.txt b/src/Splines/CMakeLists.txt index d62ef5a..aada294 100644 --- a/src/Splines/CMakeLists.txt +++ b/src/Splines/CMakeLists.txt @@ -1,62 +1,64 @@ # Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret ################################################################################ # This file is part of NUISANCE. # # NUISANCE is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # NUISANCE is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with NUISANCE. If not, see <http://www.gnu.org/licenses/>. ################################################################################ set(IMPLFILES FitSpline.cxx FitSplineHead.cxx SplineReader.cxx SplineWriter.cxx SplineMerger.cxx +SplineUtils.cxx Spline.cxx ) set(HEADERFILES FitSpline.h FitSplineHead.h SplineReader.h SplineWriter.h +SplineUtils.h SplineMerger.h Spline.h ) set(LIBNAME Splines) if(CMAKE_BUILD_TYPE MATCHES DEBUG) add_library(${LIBNAME} STATIC ${IMPLFILES}) else(CMAKE_BUILD_TYPE MATCHES RELEASE) add_library(${LIBNAME} SHARED ${IMPLFILES}) endif() include_directories(${RWENGINE_INCLUDE_DIRECTORIES}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${CMAKE_SOURCE_DIR}/src/FitBase) include_directories(${CMAKE_SOURCE_DIR}/src/Reweight) include_directories(${CMAKE_SOURCE_DIR}/src/Utils) set_target_properties(${LIBNAME} PROPERTIES VERSION "${ExtFit_VERSION_MAJOR}.${ExtFit_VERSION_MINOR}.${ExtFit_VERSION_REVISION}") set_target_properties(${LIBNAME} PROPERTIES LINK_FLAGS ${ROOT_LD_FLAGS}) if(DEFINED PROJECTWIDE_EXTRA_DEPENDENCIES) add_dependencies(${LIBNAME} ${PROJECTWIDE_EXTRA_DEPENDENCIES}) endif() install(TARGETS ${LIBNAME} DESTINATION lib) #Can uncomment this to install the headers... but is it really neccessary? install(FILES ${HEADERFILES} DESTINATION include) set(MODULETargets ${MODULETargets} ${LIBNAME} PARENT_SCOPE) diff --git a/src/Splines/Spline.cxx b/src/Splines/Spline.cxx index 78692df..4367761 100644 --- a/src/Splines/Spline.cxx +++ b/src/Splines/Spline.cxx @@ -1,368 +1,569 @@ #include "Spline.h" +using namespace SplineUtils; +// Setup Functions +// ---------------------------------------------- +Spline::Spline(std::string splname, std::string form, std::string points) { -Spline::Spline(std::string splname, std::string form, - std::vector<double> x) { - - // Initial setup - fSplineNames = GeneralUtils::ParseToStr(splname, ":"); + // Save Definition fName = splname; fForm = form; + fPoints = points; +// functor = NULL; + minimizer = NULL; - fXScan.clear(); - for (size_t i = 0; i < x.size(); i++){ - fXScan.push_back(x[i]); - } + // Run Checks + // if ((UInt_t)fNDim != fSplineNames.size()) { + // ERR(FTL) << "Spline Dim:Names mismatch!" << std::endl; + // throw; + // } - fX = 0.0; + // Setup Min Max for each Parameter + fSplitNames = GeneralUtils::ParseToStr(splname, ";"); + std::vector< std::vector<double> > gridvals = SplineUtils::GetSplitDialPoints(fPoints); - // Set X Min/Max from scan points - fXMax = -99999; - fXMin = 99999; - for (size_t i = 0; i < fXScan.size(); i++) { - if (fXScan[i] > fXMax) fXMax = fXScan[i]; - if (fXScan[i] < fXMin) fXMin = fXScan[i]; - } + for (size_t i = 0; i < fSplitNames.size(); i++) { - // Setup iters - iter_low = fXScan.begin(); - iter_high = fXScan.begin(); - iter_high++; - off = 0; + for (size_t j = 0; j < gridvals.size(); j++) { + if (i == 0) fXScan.push_back(gridvals[j][0]); + if (i == 1) fXScan.push_back(gridvals[j][1]); + } + + double xmin = 9999.9; + double xmax = -9999.9; + for (size_t j = 0; j < gridvals.size(); j++) { + if (gridvals[j][i] < xmin) xmin = gridvals[j][i]; + if (gridvals[j][i] > xmax) xmax = gridvals[j][i]; + } + + fVal.push_back(0.0); + fValMin.push_back(xmin); + fValMax.push_back(xmax); + + // Define TSpline3 1D iterators here + if (i == 0) { + iter_low = fXScan.begin(); + iter_high = fXScan.begin(); + iter_high++; + off = 0; + } + } // Set form from list if (!fForm.compare("1DPol1")) { Setup( k1DPol1, 1, 2 ); } else if (!fForm.compare("1DPol2")) { Setup( k1DPol2, 1, 3 ); } else if (!fForm.compare("1DPol3")) { Setup( k1DPol3, 1, 4 ); } else if (!fForm.compare("1DPol4")) { Setup( k1DPol4, 1, 5 ); } else if (!fForm.compare("1DPol5")) { Setup( k1DPol5, 1, 6 ); } else if (!fForm.compare("1DPol6")) { Setup( k1DPol6, 1, 7 ); } else if (!fForm.compare("1DTSpline3")) { Setup( k1DTSpline3, 1, fXScan.size() * 4 ); } + else if (!fForm.compare("2DPol6")) { Setup( k2DPol6, 2, 28 ); } + else if (!fForm.compare("2DGaus")) { Setup( k2DGaus, 2, 8 ); } + else if (!fForm.compare("2DTSpline3")) { Setup (k2DTSpline3, 2, fXScan.size() * fYScan.size() * 8); } else { ERR(FTL) << "Unknown spline form : " << fForm << std::endl; throw; } - // Run Checks - if ((UInt_t)fNDim != fSplineNames.size()) { - ERR(FTL) << "Spline Dim:Names mismatch!" << std::endl; - throw; - } - + std::cout << "Setup Spline " << fForm << " = " << fType << " " << fNPar << std::endl; }; void Spline::Setup(int type, int ndim, int npar) { fType = type; fNDim = ndim; fNPar = npar; } + +// Reconfigure Functions +// ---------------------------------------------- +void Spline::Reconfigure(float x, int index) { + // std::cout << "Reconfigured spline : " << fName << " : " << fForm << " to be " << x << " " << index << std::endl; + fVal[index] = x; + fOutsideLimits = false; + + if (fVal[index] > fValMax[index]) fVal[index] = fValMax[index]; + if (fVal[index] < fValMin[index]) fVal[index] = fValMin[index]; + // std::cout << "Set at edge = " << fVal[index] << " " << index << std::endl; +} + +void Spline::Reconfigure(std::string name, float x) { + for (size_t i = 0; i < fSplitNames.size(); i++) { + // std::cout << "-> Comparing in spline " << name << " to " << fSplitNames[i] << " = " << !fSplitNames[i].compare(name.c_str()) << std::endl; + + if (!fSplitNames[i].compare(name.c_str())) { + // std::cout << "-> Reconfigured spline : " << fSplitNames[i] << " " << name << " to be " << x << " " << i << std::endl; + Reconfigure(x, i); + } + } + +} + + +// Evaluation Functions +// ---------------------------------------------- double Spline::operator()(const Double_t* x, const Double_t* par) const { - Float_t tempx; - tempx = x[0]; + Float_t* tempx = new Float_t[fNDim]; + for (size_t i = 0; i < (UInt_t)fNDim; i++) { + tempx[i] = x[i]; + } Float_t* tempp = new Float_t[fNPar]; - for (size_t i = 0; i < (UInt_t)fNPar; i++){ + for (size_t i = 0; i < (UInt_t)fNPar; i++) { tempp[i] = par[i]; } - float val = DoEval(&tempx, tempp); + float val = DoEval(tempx, tempp); delete tempp; + delete tempx; if (val < 0.0) val = 0.0; return val; } float Spline::operator()(const Float_t* x, const Float_t* par) const { float val = DoEval(x, par); if (val < 0.0) val = 0.0; return val; } -/* -void Spline::Reconfigure(double x) { - // std::cout << "Reconfigured spline : " << fName << " : " << fForm << " to be " << x << std::endl; - fX = x; - fOutsideLimits = false; +// double Spline::operator()(const Double_t* x, const Double_t* y, const Double_t* par) const { +// Float_t temp[2]; +// temp[0] = x[0]; +// temp[1] = y[0]; - if (fX > fXMax) fX = fXMax; - if (fX < fXMin) fX = fXMin; -} -*/ +// float val = DoEval(temp, par); +// if (val < 0.0) val = 0.0; +// return val; +// } -void Spline::Reconfigure(float x) { - // std::cout << "Reconfigured spline : " << fName << " : " << fForm << " to be " << x << std::endl; - fX = x; - fOutsideLimits = false; - - if (fX > fXMax) fX = fXMax; - if (fX < fXMin) fX = fXMin; -} -/* -double Spline::DoEval(const Double_t* x, const Double_t* par) const { - - // Setup current fX to value - fX = x[0]; - if (fX > fXMax) fX = fXMax; - if (fX < fXMin) fX = fXMin; - - double w = DoEval(&par[0], false); - - if (w < 0.0) w = 0.0; - // Now evaluate spline how FitWeight will do it. - return w; -} -*/ float Spline::DoEval(const Float_t* x, const Float_t* par) const { // Setup current fX to value - fX = x[0]; - if (fX > fXMax) fX = fXMax; - if (fX < fXMin) fX = fXMin; + for (size_t i = 0; i < (UInt_t) fNDim; i++) { + fVal[i] = x[i]; + if (fVal[i] > fValMax[i]) fVal[i] = fValMax[i]; + if (fVal[i] < fValMin[i]) fVal[i] = fValMin[i]; + // std::cout << "Set " << i << " fVal to " << x[i] << std::endl; + } double w = DoEval(&par[0], false); if (w < 0.0) w = 0.0; // Now evaluate spline how FitWeight will do it. return w; } -/* -double Spline::DoEval(const Double_t* par, bool checkresponse) const { - - Float_t* temp = new Float_t[fNPar]; - for (size_t i = 0; i < fNPar; i++){ - temp[i] = par[i]; - } - double val = DoEval(temp, checkresponse); - delete temp; - return val; -} -*/ + float Spline::DoEval(const Float_t* par, bool checkresponse) const { - if (!par) return 1.0; + if (!par) + return 1.0; - // std::cout << "Spline::DoEval = " << par << std::endl; + // std::cout << "Spline::DoEval = " << par << std::endl; // Check response if (checkresponse) { bool hasresponse = false; for (int i = 0; i < fNPar; i++) { if (par[i] != 0.0) { hasresponse = true; break; } } if (!hasresponse) { // std::cout << "No Response" << std::endl; return 1.0; } } + // std::cout << "TYpe = " << fType << " "<< fForm << std::endl; // Now evaluate spline switch (fType) { case k1DPol1: { return Spline1DPol1(par); } case k1DPol2: { return Spline1DPol2(par); } case k1DPol3: { return Spline1DPol3(par); } case k1DPol4: { return Spline1DPol4(par); } case k1DPol5: { return Spline1DPol5(par); } case k1DPol6: { return Spline1DPol6(par); } case k1DTSpline3: { return Spline1DTSpline3(par); } + case k2DPol6: { return Spline2DPol(par, 6); } + case k2DGaus: { return Spline2DGaus(par); } + case k2DTSpline3: { return Spline2DTSpline3(par); } } // Return nominal weight return 1.0; }; // Spline Functions // ---------------------------------------------- + +// 1D Functions +// ---------------------------------------------- float Spline::Spline1DPol1(const Float_t* par) const { - float xp = fX; - //std::cout << "Eval 1DPol1 with " << par[0] << " " << par[1] << " " << xp << " " << par[0] + par[1] * xp << std::endl; + float xp = fVal[0]; return par[0] + par[1] * xp; }; float Spline::Spline1DPol2(const Float_t* par) const { - float xp = fX; + float xp = fVal[0]; return par[0] + par[1] * xp + par[2] * xp * xp; }; float Spline::Spline1DPol3(const Float_t* par) const { - float xp = fX; + float xp = fVal[0]; return par[0] + par[1] * xp + par[2] * xp * xp + par[3] * xp * xp * xp; }; float Spline::Spline1DPol4(const Float_t* par) const { - float xp = fX; + float xp = fVal[0]; return (par[0] + par[1] * xp + par[2] * xp * xp + par[3] * xp * xp * xp + par[4] * xp * xp * xp * xp); }; float Spline::Spline1DPol5(const Float_t* par) const { - float xp = fX; + float xp = fVal[0]; return (par[0] + par[1] * xp + par[2] * xp * xp + par[3] * xp * xp * xp + par[4] * xp * xp * xp * xp + par[5] * xp * xp * xp * xp * xp); }; float Spline::Spline1DPol6(const Float_t* par) const { - float xp = fX; + float xp = fVal[0]; float w = 0.0; // std::cout << "Pol Eval " << std::endl; - for (int i = fNPar-1; i > 0; i--){ - w = xp * (par[0+i] + w); + for (int i = fNPar - 1; i > 0; i--) { + w = xp * (par[0 + i] + w); } - w += par[0]; + w += par[0]; return w; }; -float Spline::Spline1DTSpline3(const Float_t* par) const { - // std::cout << "Doing Spline Eval " << fX << " " << par << std::endl; + +float Spline::GetMonomial(int p) const { + + // // Copied From ROOT + // Int_t i = 0; + // Double_t p1 = 1; + // Double_t p2 = 0; + // Double_t p3 = 0; + // Double_t r = 0; + + // switch (p) { + // case 1: + // r = 1; + // break; + // case 2: + // r = x; + // break; + // default: + // p2 = x; + // for (i = 3; i <= p; i++) { + // p3 = p2 * x; + // p1 = p2; + // p2 = p3; + // } + // r = p3; + // } + + return 0.0; +} + +float Spline::Spline2DTSpline3(const Float_t* par) const { + // Find matching point - iter_low = fXScan.begin(); - iter_high = fXScan.begin(); - iter_high++; + std::vector<float>::iterator iter_low_x = fXScan.begin(); + std::vector<float>::iterator iter_high_x = fXScan.begin(); + std::vector<float>::iterator iter_low_y = fYScan.begin(); + std::vector<float>::iterator iter_high_y = fYScan.begin(); + iter_high_x++; + iter_high_y++; + off = 0; - - while ( iter_high != fXScan.end() and - (fX < (*iter_low) or fX >= (*iter_high)) ) { - off += 4; - iter_low++; - iter_high++; + fX = fVal[0]; + fY = fVal[1]; + + while ( (iter_high_x != fXScan.end() and + iter_high_y != fYScan.end()) and + (fX < (*iter_low_y) or + fX >= (*iter_high) or + fY < (*iter_low_y) or + fY >= (*iter_low_y)) ) { + off += 9; + iter_low_x++; + iter_high_x++; + + if (iter_high_x == fXScan.end()) { + iter_low_x = fXScan.begin(); + iter_high_x = fXScan.begin(); + iter_low_y++; + iter_high_y++; + std::cout << "Skipping to next tspline 3 rung " << *iter_low_y << std::endl; + } } - float dx = fX - (*iter_low); + std::cout << "Evaluting TSpline3 at " << fX << " " << (*iter_low_x) << " " << fY << " " << (*iter_low_y) << std::endl; + // sleep(1.0); + float dx = fX - (*iter_low_x); + float dy = fY - (*iter_low_y); + float weight = (par[off] + dx * (par[off + 1] + dx * (par[off + 2] + dx * par[off + 3]))); + float weight2 = (par[off + 4] + dy * (par[off + 5] + dy * (par[off + 6] + dy * par[off + 7]))); - return weight; + return weight * weight2 * par[off + 8]; }; -void Spline::FitCoeff(int n, double* x, double* y, float* coeff, bool draw) { - switch (fType) { - // Polynominal Graph Fits - case k1DPol1: - case k1DPol2: - case k1DPol3: - case k1DPol4: - case k1DPol5: - case k1DPol6: - FitCoeff1DGraph(n, x, y, coeff, draw); - break; - - // Spline Fits use TSpline3 Class - case k1DTSpline3: - GetCoeff1DTSpline3(n, x, y, coeff, draw); - break; - } -} +float Spline::Spline2DPol(const Float_t* par, int n) const { + // float wx = 2.0 * (fVal[0] - fValMin[0] - (fValMax[0] - fValMin[0]) / 2.0) / (fValMax[0] - fValMin[0]); + // float wy = 2.0 * (fVal[1] - fValMin[1] - (fValMax[1] - fValMin[1]) / 2.0) / (fValMax[1] - fValMin[1]); + float wx = (fVal[0] - fValMin[0]) / (fValMax[0] - fValMin[0]); + float wy = (fVal[1] - fValMin[1]) / (fValMax[1] - fValMin[1]); -// Fitting Functions -void Spline::FitCoeff1DGraph(int n, double* x, double* y, float* coeff, bool draw) { + int count = 0; + bool speak = false; - TGraph* gr = new TGraph(n, x, y); - double xmin = 99999.9; - double xmax = -99999.9; - for (int i = 0; i < n; i++) { - if (x[i] > xmax) xmax = x[i]; - if (x[i] < xmin) xmin = x[i]; - } + // float w = 0.0; + // // std::cout << "Pol Eval " << std::endl; + // for (int i = 7 - 1; i > 0; i--) { + // w = xp * (par[0 + i] + w); + // } + // w += par[0]; - double xwidth = xmax - xmin; - xmin = xmin - xwidth * 0.01; - xmax = xmax + xwidth * 0.01; + // float w2 = 0.0; + // // std::cout << "Pol Eval " << std::endl; + // for (int i = 13 - 1; i > 0; i--) { + // w2 = xp * (par[7 + i] + w2); + // } - // Create a new function for fitting. - TF1* func = new TF1("f1", this, -30, 30, this->GetNPar()); - func->SetNpx(400); - func->FixParameter(0, 1.0); // Fix so 1.0 at nominal + // return w1 * w2; - // Run the actual spline fit - StopTalking(); - - // If linear fit with two points - if (n == 2 and fType == k1DPol1){ - float m = (y[1] - y[0]) / (x[1] - x[0]); - float c = y[0] - (0.0 - x[0]) * m; - func->SetParameter(0, c); - func->SetParameter(1, m); - } else if (fType == k1DPol1){ - gr->Fit(func, "WQ"); - } else { - gr->Fit(func, "FMWQ"); - } - StartTalking(); + // for (int i = 0; i < n; i++){ + + // if (i == 0) + + // } +// float w = 0.0; +// w += par[count++]; +// w += par[count++] * wx; +// w += par[count++] * wy; + +// w += par[count++] * wx * wy; // / 10.0; +// w += par[count++] * wx * wx; // / 10.0; +// w += par[count++] * wy * wy; // / 10.0; + +// w += par[count++] * wx * wx * wy; // / 100.0; +// w += par[count++] * wx * wy * wy; // / 100.0; +// w += par[count++] * wx * wx * wx; // / 100.0; +// w += par[count++] * wy * wy * wy; // / 100.0; + + +// w += par[count++] * wx * wx * wx * wx; // / 100.0; +// w += par[count++] * wx * wx * wx * wy; // / 100.0; +// w += par[count++] * wx * wx * wy * wy; // / 100.0; +// w += par[count++] * wx * wy * wy * wy; // / 100.0; +// w += par[count++] * wy * wy * wy * wy; // / 100.0; + +// w += par[count++] * wx * wx * wx * wx * wx; // / 1000.0; +// w += par[count++] * wx * wx * wx * wx * wy; // / 1000.0; +// w += par[count++] * wx * wx * wx * wy * wy; // / 1000.0; +// w += par[count++] * wx * wx * wy * wy * wy; // / 1000.0; +// w += par[count++] * wx * wy * wy * wy * wy; // / 1000.0; +// w += par[count++] * wy * wy * wy * wy * wy; // / 1000.0; + +// w += par[count++] * wx * wx * wx * wx * wx * wx; // / 10000.0; +// w += par[count++] * wx * wx * wx * wx * wx * wy; // / 10000.0; +// w += par[count++] * wx * wx * wx * wx * wy * wy; // / 10000.0; +// w += par[count++] * wx * wx * wx * wy * wy * wy; // / 10000.0; +// w += par[count++] * wx * wx * wy * wy * wy * wy; // / 10000.0; +// w += par[count++] * wx * wy * wy * wy * wy * wy; // / 10000.0; +// w += par[count++] * wy * wy * wy * wy * wy * wy; // / 10000.0; + + // float w = 0.0; + // int power = 6; + // for (int i = 0; i < power; i++){ + // int xpower = power; + // int ypower = 0; + // while (ypower <= power){ + // w += par[count++] * pow(wx,xpower) * pow(wy, ypower); + // xpower--; + // ypower++; + // } + // } - for (int i = 0; i < this->GetNPar(); i++) { - coeff[i] = func->GetParameter(i); - } - if (draw) { - gr->Draw("APL"); - gPad->Update(); - gPad->SaveAs(("plot_test_" + fName + ".pdf").c_str()); - std::cout << "Saving Graph" << std::endl; - sleep(3); + float w = 0.0; + + w += par[count++] * wx; + w += par[count++] * wy; + + w += par[count++] * wx * wy; // / 10.0; + w += par[count++] * wx * wx; // / 10.0; + w += par[count++] * wy * wy; // / 10.0; + + w += par[count++] * wx * wx * wy; // / 100.0; + w += par[count++] * wx * wy * wy; // / 100.0; + w += par[count++] * wx * wx * wx; // / 100.0; + w += par[count++] * wy * wy * wy; // / 100.0; + + + w += par[count++] * wx * wx * wx * wx; // / 100.0; + w += par[count++] * wx * wx * wx * wy; // / 100.0; + w += par[count++] * wx * wx * wy * wy; // / 100.0; + w += par[count++] * wx * wy * wy * wy; // / 100.0; + w += par[count++] * wy * wy * wy * wy; // / 100.0; + + w += par[count++] * wx * wx * wx * wx * wx; // / 1000.0; + w += par[count++] * wx * wx * wx * wx * wy; // / 1000.0; + w += par[count++] * wx * wx * wx * wy * wy; // / 1000.0; + w += par[count++] * wx * wx * wy * wy * wy; // / 1000.0; + w += par[count++] * wx * wy * wy * wy * wy; // / 1000.0; + w += par[count++] * wy * wy * wy * wy * wy; // / 1000.0; + + w += par[count++] * wx * wx * wx * wx * wx * wx; // / 10000.0; + w += par[count++] * wx * wx * wx * wx * wx * wy; // / 10000.0; + w += par[count++] * wx * wx * wx * wx * wy * wy; // / 10000.0; + w += par[count++] * wx * wx * wx * wy * wy * wy; // / 10000.0; + w += par[count++] * wx * wx * wy * wy * wy * wy; // / 10000.0; + w += par[count++] * wx * wy * wy * wy * wy * wy; // / 10000.0; + w += par[count++] * wy * wy * wy * wy * wy * wy; // / 10000.0; + + + + if (wx != 0.0 and speak) { + for (int i = 0; i < count; i++) { + std::cout << "Evaluated " << fName << " spline coeff " << i << " = " << par[i] << std::endl; + } + std::cout << "End Weight = " << w << " " << wx << " " << wy << std::endl; + // sleep(1); } + // Add up all coefficients. + // for (int i = 0; i <= n; i++) { + // wx += pow(x, i) * par[count++]; + // } + // for (int i = 0; i <= n; i++) { + // wy += pow(y, i) * par[count++]; + // } - delete func; - delete gr; + return w; } +float Spline::Spline2DGaus(const Float_t* par) const { -// Spline extraction Functions -void Spline::GetCoeff1DTSpline3(int n, double* x, double* y, float* coeff, bool draw) { + double Norm = 5.0 + par[1] * 20.0; + double Tilt = par[2] * 10.0; //vals[kPosTilt]; + double Pq0 = 1.0 + par[3] * 1.0; //vals[kPosPq0]; + double Wq0 = 0.5 + par[4] * 1.0; //vals[kPosWq0]; + double Pq3 = 1.0 + par[5] * 1.0; //vals[kPosPq3]; + double Wq3 = 0.5 + par[6] * 1.0; //vals[kPosWq3]; + double q0 = (fVal[0] - fValMin[0]) / (fValMax[0] - fValMin[0]); + double q3 = (fVal[1] - fValMin[1]) / (fValMax[1] - fValMin[1]); - StopTalking(); - TSpline3 temp_spline = TSpline3("temp_spline", x, y, n); - StartTalking(); + // double w = Norm; + // w *= TMath::Gaus(q0, Pq0, Wq0); + // w *= TMath::Gaus(q3, Pq3*sin(Tilt), Wq3); - for (size_t i = 0; i < (UInt_t)n; i++) { + double a = cos(Tilt) * cos(Tilt) / (2 * Wq0 * Wq0); + a += sin(Tilt) * sin(Tilt) / (2 * Wq3 * Wq3); - double a, b, c, d, e; - temp_spline.GetCoeff(i, a, b, c, d, e); + double b = - sin(2 * Tilt) / (4 * Wq0 * Wq0); + b += sin(2 * Tilt) / (4 * Wq3 * Wq3); - coeff[i * 4] = y[i]; - coeff[i * 4 + 1] = c; - coeff[i * 4 + 2] = d; - coeff[i * 4 + 3] = e; - } + double c = sin(Tilt) * sin(Tilt) / (2 * Wq0 * Wq0); + c += cos(Tilt) * cos(Tilt) / (2 * Wq3 * Wq3); - if (draw) { - TGraph* gr = new TGraph(n, x, y); - temp_spline.Draw("CA"); - gr->Draw("PL SAME"); - gPad->Update(); - gPad->SaveAs(("plot_test_" + fName + ".pdf").c_str()); - // sleep(3); - delete gr; - } + double w = Norm; + w *= exp(-a * (q0 - Pq0) * (q0 - Pq0)); + w *= exp(+2.0 * b * (q0 - Pq0) * (q3 - Pq3)); + w *= exp(-c * (q3 - Pq3) * (q3 - Pq3)); + + // Norm = par[7]; + // Tilt = par[8]*50.0;//vals[kPosTilt]; + // Pq0 = par[9]*10.0;//vals[kPosPq0]; + // Wq0 = par[10]*10.0;//vals[kPosWq0]; + // Pq3 = par[11]*10.0; //vals[kPosPq3]; + // Wq3 = par[12]*10.0; //vals[kPosWq3]; + + // // double w = Norm; + // // w *= TMath::Gaus(q0, Pq0, Wq0); + // // w *= TMath::Gaus(q3, Pq3*sin(Tilt), Wq3); - return; + // a = cos(Tilt)*cos(Tilt) / (2*Wq0*Wq0); + // a += sin(Tilt)*sin(Tilt) / (2*Wq3*Wq3); + + // b = - sin(2*Tilt) / (4*Wq0*Wq0); + // b += sin(2*Tilt) / (4*Wq3*Wq3); + + // c = sin(Tilt)*sin(Tilt) / (2*Wq0*Wq0); + // c += cos(Tilt)*cos(Tilt) / (2*Wq3*Wq3); + + // double w2 = Norm; + // w2 *= exp(-a * (q0 - Pq0)*(q0 - Pq0)); + // w2 *= exp(+2.0*b * (q0 - Pq0)*(q3 - Pq3)); + // w2 *= exp(-c * (q3 - Pq3)*(q3 - Pq3)); + + +// std::cout << "GausWeight = " << w << std::endl; + return w; } + +float Spline::Spline1DTSpline3(const Float_t* par) const { + + // Find matching point + iter_low = fXScan.begin(); + iter_high = fXScan.begin(); + iter_high++; + off = 0; + fX = fVal[0]; + + while ( iter_high != fXScan.end() and + (fX < (*iter_low) or fX >= (*iter_high)) ) { + off += 4; + iter_low++; + iter_high++; + } + + // std::cout << "Evaluting TSpline3 at " << fX << " " << (*iter_low) << std::endl; + // sleep(1.0); + float dx = fX - (*iter_low); + float weight = (par[off] + dx * (par[off + 1] + dx * (par[off + 2] + dx * par[off + 3]))); + + return weight; +}; + + +// 2D Functions +// ---------------------------------------------- + + + + + + + diff --git a/src/Splines/Spline.h b/src/Splines/Spline.h index 3936eec..82e4d90 100644 --- a/src/Splines/Spline.h +++ b/src/Splines/Spline.h @@ -1,101 +1,163 @@ #ifndef SPLINE_H #define SPLINE_H #include <vector> #include "TObject.h" #include "FitParameters.h" // #include "PlotUtils.h" // #include "FitUtils.h" #include "stdint.h" #include "stdlib.h" #include "TCanvas.h" #include <list> #include "TF1.h" #include "TSpline.h" +#include "SplineUtils.h" +#include "TGraph2D.h" +#include "TF2.h" + +#include "Math/Minimizer.h" +#include "Math/Factory.h" +#include "Math/Functor.h" +#include "TH1D.h" // Spline Class class Spline { public: - Spline(std::string splname, std::string form, std::vector<double> x); + Spline(std::string splname, std::string form, std::string points); ~Spline() {}; void Setup(int type, int ndim, int npar); double operator()(const Double_t* x, const Double_t* par) const; + // double operator()(const Double_t* x, const Double_t* y, const Double_t* par) const; + // double DoEval(const Double_t* x, const Double_t* par) const; // double DoEval(const Double_t* par, bool checkresponse=true) const; float operator()(const Float_t* x, const Float_t* par) const; + float DoEval(const Float_t* x, const Float_t* par) const; - float DoEval(const Float_t* par, bool checkresponse=true) const; - + float DoEval(const Float_t* par, bool checkresponse = true) const; + // void FitCoeff(int n, double* x, double* y, double* par, bool draw); - void FitCoeff(int n, double* x, double* y, float* par, bool draw); + void FitCoeff(std::vector< std::vector<double> > v, std::vector<double> w, float* coeff, bool draw); inline std::string GetName(void) { return fName; }; inline int GetNDim(void) { return fNDim; }; inline int GetType(void) { return fType; }; inline int GetNPar(void) { return fNPar; }; inline std::string GetForm() {return fForm;}; //void Reconfigure(double x); - void Reconfigure(float x); + void Reconfigure(float x, int index = 0); + void Reconfigure(std::string name, float x); + std::string fName; - std::vector<std::string> fSplineNames; int fType; int fNDim; int fNPar; std::string fForm; + std::string fPoints; bool fOutsideLimits; + std::vector<std::string> fSplitNames; + std::vector<std::string> fSplitPoints; + + mutable std::vector<float> fVal; + mutable std::vector<float> fValMin; + mutable std::vector<float> fValMax; + + mutable std::vector< std::vector<float> > fSplitScan; + + + + mutable std::vector<float> fXScan; mutable float fX; mutable float fXMin; mutable float fXMax; + + mutable std::vector<float> fYScan; + mutable float fY; + mutable float fYMin; + mutable float fYMax; + int fSplineOffset; + // TSpline3 Objects. mutable std::vector<float>::iterator iter_low; mutable std::vector<float>::iterator iter_high; mutable int off; - // Spline List - enum spline_types { - k1DPol1 = 1, - k1DPol2, - k1DPol3, - k1DPol4, - k1DPol5, - k1DPol6, - k1DPol1C, - k1DPol2C, - k1DPol3C, - k1DPol4C, - k1DPol5C, - k1DPol5C_LX, - k1DPol10, - k1DTSpline3, - k1DPol25, - k2DPol6 - }; + // Create a new function for fitting. + ROOT::Math::Minimizer* minimizer; // Available Spline Functions float Spline1DPol1(const Float_t* par) const; float Spline1DPol2(const Float_t* par) const; float Spline1DPol3(const Float_t* par) const; float Spline1DPol4(const Float_t* par) const; float Spline1DPol5(const Float_t* par) const; float Spline1DPol6(const Float_t* par) const; + float Spline2DPol(const Float_t* par, int n) const; + float Spline2DGaus(const Float_t* par) const; +float GetMonomial(int p) const; float Spline1DTSpline3(const Float_t* par) const; +float Spline2DTSpline3(const Float_t* par) const; - // Available Fitting Functions - void FitCoeff1DGraph(int n, double* x, double* y, float* coeff, bool draw); - void GetCoeff1DTSpline3(int n, double* x, double* y, float* coeff, bool draw); +// void FitCoeff2DGraph(std::vector< std::vector<double> > v, std::vector<double> w, float* coeff, bool draw); +}; +// class SplineFCN { +// public: + +// SplineFCN(Spline* spl, std::vector<std::vector<double> > v, std::vector<double> w) { fSpl = spl; fVal = v; fWeight = w; }; +// ~SplineFCN() {}; + +// double operator()(const double* x) const; +// double DoEval(const double *x) const; +// void SaveAs(std::string name, const double* x); + +// std::vector< std::vector<double> > fVal; +// std::vector< double > fWeight; +// Spline* fSpl; + +// }; + +namespace SplineUtils { +// // Available Fitting Functions +// void FitCoeff1DGraph(Spline* spl, int n, double* x, double* y, float* coeff, bool draw); +// void GetCoeff1DTSpline3(Spline* spl, int n, double* x, double* y, float* coeff, bool draw); +// // void FitCoeff2DGraph(Spline* spl, int n, double* x, double* y, double* z, float* coeff, bool draw); + +// Spline List +enum spline_types { + k1DPol1 = 1, + k1DPol2, + k1DPol3, + k1DPol4, + k1DPol5, + k1DPol6, + k1DPol1C, + k1DPol2C, + k1DPol3C, + k1DPol4C, + k1DPol5C, + k1DPol5C_LX, + k1DPol10, + k1DTSpline3, + k1DPol25, + k2DPol6, + k2DGaus, + k2DTSpline3 }; +} + #endif diff --git a/src/Splines/SplineReader.cxx b/src/Splines/SplineReader.cxx index 844677c..dca7ebf 100644 --- a/src/Splines/SplineReader.cxx +++ b/src/Splines/SplineReader.cxx @@ -1,135 +1,135 @@ #include "SplineReader.h" // Spline reader should have access to every spline. // Should know when reconfigure is called what its limits are and adjust accordingly. // Then should pass it the index required in the stack as &xvals[index], and &pars[parindex] void SplineReader::AddSpline(nuiskey splinekey) { // Read info from key std::string splname = splinekey.GetS("name"); std::string type = splinekey.GetS("type"); std::string form = splinekey.GetS("form"); std::string points = splinekey.GetS("points"); std::string extrapolate = splinekey.GetS("extrapolate"); // std::cout << "AddSpline " << splname << " " << type << " " << form << " " << points << std::endl; // Add the spline to the list of all forms - fAllSplines.push_back( Spline(splname, form, GeneralUtils::ParseToDbl(points, ",")) ); + fAllSplines.push_back( Spline(splname, form, points) ); fSpline.push_back(splname); fType.push_back(type); fForm.push_back(form); fPoints.push_back(points); } void SplineReader::Read(TTree* tr) { std::vector<std::string>* tempspline = 0; std::vector<std::string>* temptype = 0; std::vector<std::string>* tempform = 0; std::vector<std::string>* temppoints = 0; // Loop over all splines and add a TString in the TTree for its inputs tr->SetBranchAddress("Spline", &tempspline); tr->SetBranchAddress("Type", &temptype); tr->SetBranchAddress("Form", &tempform); tr->SetBranchAddress("Points", &temppoints); tr->GetEntry(0); // Copy over for (size_t i = 0; i < tempspline->size(); i++){ fSpline.push_back(tempspline->at(i)); fType.push_back(temptype->at(i)); fForm.push_back(tempform->at(i)); fPoints.push_back(temppoints->at(i)); } // Loop through and add splines from read type. for (size_t i = 0; i < fSpline.size(); i++) { LOG(SAM) << "Registering Input Spline " << fSpline[i] << " " << fForm[i] << " " << fPoints[i] << std::endl; - fAllSplines.push_back( Spline(fSpline[i], fForm[i], - GeneralUtils::ParseToDbl(fPoints[i], ",")) ); + fAllSplines.push_back( Spline(fSpline[i], fForm[i], fPoints[i]) ); } } void SplineReader::Reconfigure(std::map< std::string, double >& vals) { + // std::cout << "NEW SPLINE READER =========" << std::endl; for (std::map<std::string, double>::iterator iter = vals.begin(); iter != vals.end(); iter++){ - // std::cout << " Found " << iter->first << " in map handed to reader." << std::endl; + // std::cout << "Found " << iter->first << " in map handed to reader." << std::endl; for (size_t i = 0; i < fSpline.size(); i++){ - // std::cout << " Comparing it to : " << fSpline[i] << std::endl; - if (!fSpline[i].compare(iter->first.c_str())){ - //std::cout << "Reconfiguring Value inside Reader to be " << fSpline[i] << " " << iter->second << std::endl; - fAllSplines[i].Reconfigure(iter->second); - } + // std::cout << "Passing it to : " << fSpline[i] << std::endl; + // if (!fSpline[i].compare(iter->first.c_str())){ + // std::cout << "Reconfiguring Value inside Reader to be " << fSpline[i] << " " << iter->second << std::endl; + fAllSplines[i].Reconfigure(iter->first, iter->second); + // } } } fNeedsReconfigure = false; } bool SplineReader::NeedsReconfigure() { return fNeedsReconfigure; } void SplineReader::SetNeedsReconfigure(bool val) { fNeedsReconfigure = val; } double SplineReader::CalcWeight(float* coeffs) { int off = 0; double rw_weight = 1.0; // Form Offset list std::vector<int> offsets; for (size_t i = 0; i < fAllSplines.size(); i++) { offsets.push_back(off); off += fAllSplines[i].GetNPar(); } // #pragma omp parrallel for for (size_t i = 0; i < fAllSplines.size(); i++) { // std::cout << "Evaluating spline " << fAllSplines[i].GetName() << " at coeff offset " << off << "(" << coeffs << ")" << std::endl; // for (int j = 0; j < fAllSplines[i].GetNPar(); j++){ // std::cout << "Coeff " << j+off << " " << coeffs[off+j] << std::endl; // } double w = fAllSplines[i].DoEval( &coeffs[offsets[i]] ); rw_weight *= w; // std::cout << "Spline RW Weight = " << rw_weight << " " << w << std::endl; } if (rw_weight <= 0.0) rw_weight = 1.0; // std::cout << "Returning spline rw_weight = " << rw_weight << std::endl; return rw_weight; } int SplineReader::GetNPar(){ int n = 0; for (size_t i = 0; i < fAllSplines.size(); i++){ n += fAllSplines[i].GetNPar(); } return n; } diff --git a/src/Splines/SplineUtils.cxx b/src/Splines/SplineUtils.cxx new file mode 100644 index 0000000..0c723ba --- /dev/null +++ b/src/Splines/SplineUtils.cxx @@ -0,0 +1,111 @@ +#include "SplineUtils.h" + + +// std::vector<int> SplineUtils::GetSplitDialPositions(FitWeight* rw, std::string names) { +// std::vector<std::string> splitnames = GeneralUtils::ParseToStr(names, ";"); +// std::vector<int> splitpos; + +// for (size_t i = 0; i < splitnames.size(); i++) { +// int pos = fRW->GetDialPos(splitnames[i]); +// splitpos.push_back(pos); +// } + +// return splitpos; +// } + +std::vector< std::vector<double> > SplineUtils::GetSplitDialPoints(std::string points) { + + // Determine Type + std::vector<std::string> splittype = GeneralUtils::ParseToStr(points, ":"); + std::string deftype = ""; + if (splittype.size() == 1) { + deftype = "GRID"; + } else if (splittype.size() > 1) { + deftype = splittype[0]; + splittype.erase(splittype.begin()); + } else { + throw; + } + + // Make Grid + std::vector<std::vector<double> > gridpoints; + + // Possible Point Types + if (!deftype.compare("GRID")) { + + std::vector<std::string> splitpoints = GeneralUtils::ParseToStr(splittype[0], ";"); + + // CBA writing an ND iterator to build this grids. 1D, 2D, and 3D are below.. + if (splitpoints.size() == 1) { + std::vector<double> tempcont = std::vector<double>(1, 0.0); + std::vector<double> tempsplit = GeneralUtils::ParseToDbl(splitpoints[0], ","); + + for (size_t i = 0; i < tempsplit.size(); i++) { + tempcont[0] = tempsplit[i]; + gridpoints.push_back(tempcont); + } + + // 2D + } else if (splitpoints.size() == 2) { + + std::vector<double> tempcont = std::vector<double>(2, 0.0); + std::vector<double> tempsplit1 = GeneralUtils::ParseToDbl(splitpoints[0],","); + std::vector<double> tempsplit2 = GeneralUtils::ParseToDbl(splitpoints[1],","); + + for (size_t i = 0; i < tempsplit1.size(); i++) { + for (size_t j = 0; j < tempsplit2.size(); j++) { + tempcont[0] = tempsplit1[i]; + tempcont[1] = tempsplit2[j]; + gridpoints.push_back(tempcont); + } + } + // 3D + } else if (splitpoints.size() == 3) { + + std::vector<double> tempcont = std::vector<double>(3, 0.0); + std::vector<double> tempsplit1 = GeneralUtils::ParseToDbl(splitpoints[0],","); + std::vector<double> tempsplit2 = GeneralUtils::ParseToDbl(splitpoints[1],","); + std::vector<double> tempsplit3 = GeneralUtils::ParseToDbl(splitpoints[2],","); + + for (size_t i = 0; i < tempsplit1.size(); i++) { + for (size_t j = 0; j < tempsplit2.size(); j++) { + for (size_t k = 0; k < tempsplit3.size(); k++) { + tempcont[0] = tempsplit1[i]; + tempcont[1] = tempsplit2[j]; + tempcont[2] = tempsplit3[j]; + gridpoints.push_back(tempcont); + } + } + } + } + } else if (!deftype.compare("DIAG2D")) { + std::vector<std::string> splitpoints = GeneralUtils::ParseToStr(splittype[0], ";"); + + std::vector<double> tempcont = std::vector<double>(2, 0.0); + std::vector<double> tempsplit1 = GeneralUtils::ParseToDbl(splitpoints[0],","); + + for (size_t i = 0; i < tempsplit1.size(); i++) { + tempcont[0] = tempsplit1[i]; + tempcont[1] = 0.0; + gridpoints.push_back(tempcont); + } + + for (size_t i = 0; i < tempsplit1.size(); i++) { + tempcont[0] = 0.0; + tempcont[1] = tempsplit1[i]; + gridpoints.push_back(tempcont); + } + for (size_t i = 0; i < tempsplit1.size(); i++) { + tempcont[0] = tempsplit1[i]; + tempcont[1] = tempsplit1[i]; + gridpoints.push_back(tempcont); + } + + for (size_t i = 0; i < tempsplit1.size(); i++) { + tempcont[0] = tempsplit1[i]; + tempcont[1] = tempsplit1[ tempsplit1.size() - 1 - i]; + gridpoints.push_back(tempcont); + } + } + return gridpoints; +} \ No newline at end of file diff --git a/src/Splines/SplineUtils.h b/src/Splines/SplineUtils.h new file mode 100644 index 0000000..859f92d --- /dev/null +++ b/src/Splines/SplineUtils.h @@ -0,0 +1,12 @@ +#ifndef SPLINE_UTILS_H +#define SPLINE_UTILS_H + +//#include "FitWeight.h" +#include "GeneralUtils.h" + +namespace SplineUtils { + //std::vector<int> GetSplitDialPositions(FitWeight* rw, std::string names); + std::vector< std::vector<double> > GetSplitDialPoints(std::string points); +}; + +#endif \ No newline at end of file diff --git a/src/Splines/SplineWriter.cxx b/src/Splines/SplineWriter.cxx index 0af9863..807d308 100644 --- a/src/Splines/SplineWriter.cxx +++ b/src/Splines/SplineWriter.cxx @@ -1,279 +1,677 @@ #include "SplineWriter.h" - +using namespace SplineUtils; // Spline reader should have access to every spline. // Should know when reconfigure is called what its limits are and adjust accordingly. // Then should pass it the index required in the stack as &xvals[index], and &pars[parindex] void SplineWriter::Write(std::string name) { // Create a TTree with each form and scan points in it. TTree* tr = new TTree(name.c_str(), name.c_str()); // Loop over all splines and add a TString in the TTree for its inputs tr->Branch("Spline", &fSpline); tr->Branch("Type", &fType); tr->Branch("Form", &fForm); tr->Branch("Points", &fPoints); tr->Fill(); tr->Write(); delete tr; } void SplineWriter::AddCoefficientsToTree(TTree* tr) { // Add only the fitted spline coefficients to the ttree std::cout << "Saving Spline Coeff to TTree = " << Form("SplineCoeff[%d]/F", fNCoEff) << std::endl; // sleep(1); tr->Branch("SplineCoeff", fCoEffStorer, Form("SplineCoeff[%d]/F", fNCoEff)); } void SplineWriter::SetupSplineSet() { std::cout << "Setting up spline set" << std::endl; // Create the coefficients double* fNCoEff = 0; for (size_t i = 0; i < fAllSplines.size(); i++) { fNCoEff += fAllSplines[i].GetNPar(); } fCoEffStorer = new float[fNCoEff]; std::cout << "NCoeff = " << fNCoEff << std::endl; // Calculate the grid of parsets // Setup the list of parameter coefficients. std::vector<double> nomvals = fRW->GetDialValues(); fParVect.clear(); fSetIndex.clear(); fParVect.push_back(nomvals); fSetIndex.push_back(0); fWeightList.push_back(1.0); - fValList.push_back(0.0); + fValList.push_back(std::vector<double>(1, 0.0)); // Loop over all splines. for (size_t i = 0; i < fAllSplines.size(); i++) { // For each dial loop over all points within a given position std::vector<double> newvals = nomvals; - // Create a new set of nom vals for that dial set, and attribute it to the spline index. - int pos = fRW->GetDialPos(fSpline[i]); + std::vector<int> pos; // = SplineUtils::GetSplitDialPositions(fRW, fSpline[i]); + std::vector<std::string> splitnames = GeneralUtils::ParseToStr(fSpline[i], ";"); + + for (size_t j = 0; j < splitnames.size(); j++) { + int temppos = fRW->GetDialPos(splitnames[j]); + pos.push_back(temppos); + } + + std::vector< std::vector<double> > vals = SplineUtils::GetSplitDialPoints(fPoints[i]); - // Split Points - std::vector<double> vals = GeneralUtils::ParseToDbl(fPoints[i], ","); for (size_t j = 0; j < vals.size(); j++) { - newvals[pos] = vals[j]; + + for (size_t k = 0; k < pos.size(); k++) { + newvals[ pos[k] ] = vals[j][k]; + } fParVect.push_back(newvals); fValList.push_back(vals[j]); fWeightList.push_back(1.0); - fSetIndex.push_back(i+1); + fSetIndex.push_back(i + 1); } } // Print out the parameter set LOG(FIT) << "Parset | Index | Pars --- " << std::endl; for (size_t i = 0; i < fSetIndex.size(); i++) { LOG(FIT) << " Set " << i << ". | " << fSetIndex[i] << " | "; - if (LOG_LEVEL(FIT)){ + if (LOG_LEVEL(FIT)) { for (size_t j = 0; j < fParVect[i].size(); j++) { - std::cout << " " << fParVect[i][j]; + std::cout << " " << fParVect[i][j]; } - std::cout << std::endl; + std::cout << std::endl; } } } -void SplineWriter::FitSplinesForEvent(FitEvent* event) { +void SplineWriter::FitSplinesForEvent(FitEvent* event, TCanvas* fitcanvas, bool saveplot ) { // Get Starting Weight fRW->SetAllDials(&fParVect[0][0], fParVect[0].size()); double nomweight = fRW->CalcWeight(event); event->RWWeight = nomweight; - if (fDrawSplines){ + if (fDrawSplines) { std::cout << "Nominal Spline Weight = " << nomweight << std::endl; } // Loop over parameter sets for (size_t i = 1; i < fParVect.size(); i++) { // Update FRW fRW->SetAllDials(&fParVect[i][0], fParVect[i].size()); // Calculate a weight for event double weight = fRW->CalcWeight(event); - if (weight >= 0.0 and weight < 200){ + if (weight >= 0.0 and weight < 200) { // Fill Weight Set - fWeightList[i] = weight/nomweight; - if (fDrawSplines) std::cout << "Calculating values from weight set " << i << " " << fParVect[i][0] << " = " << weight << " " << weight/nomweight << std::endl; + fWeightList[i] = weight / nomweight; + if (fDrawSplines) std::cout << "Calculating values from weight set " << i << " " << fParVect[i][0] << " = " << weight << " " << weight / nomweight << std::endl; } else { fWeightList[i] = 1.0; } } // Loop over splines // int count = 0; int coeffcount = 0; int n = fAllSplines.size(); std::vector<int> splinecounter; for (int i = 0; i < n; i++) { splinecounter.push_back(coeffcount); coeffcount += fAllSplines[i].GetNPar(); } - // int parrallel = int(!fDrawSplines); - //#pragma omp parallel for if (parrallel) for (int i = 0; i < n; i++) { // Store X/Y Vals - std::vector<double> xvals; - std::vector<double> yvals; + std::vector<std::vector<double> > dialvals; + std::vector<double> weightvals; bool hasresponse = false; int npar = (fAllSplines[i]).GetNPar(); coeffcount = splinecounter[i]; for (size_t j = 0; j < fSetIndex.size(); j++) { - if (fSetIndex[j] != i+1) continue; - xvals.push_back(fValList[j]); - yvals.push_back(fWeightList[j] - 0.0); + if (fSetIndex[j] != i + 1) continue; + dialvals.push_back(fValList[j]); + weightvals.push_back(fWeightList[j] - 0.0); if (fWeightList[j] != 1.0) hasresponse = true; } // Make a new graph and fit coeff if response if (hasresponse) { - (fAllSplines[i]).FitCoeff(int(xvals.size()), &xvals[0], &yvals[0], &fCoEffStorer[coeffcount], fDrawSplines); + FitCoeff(&fAllSplines[i], dialvals, weightvals, &fCoEffStorer[coeffcount], fDrawSplines); + // for (int k = 0; k < npar; k++){ + // std::cout << "Spline Coeff " << k << " saved as " << fCoEffStorer[coeffcount+k] << std::endl; + // } + + // Move spline fitting to inside SplineWriter as thats where it is done. + // Make sure that one minimizer is created PER spline. + // Make sure that spline has the ability to calculate the difference between a list of weights and its current set. + // by fast calculation. + } else { // std::cout << "Spline " << fSpline[i] << " has no response. " << std::endl; for (int i = 0; i < npar; i++) { fCoEffStorer[coeffcount + i] = 0.0; } } + } + + + // Check overrides + // if (saveplot) { + // coeffcount = 0; + + // // Make new canvas to save stuff into + // if (fitcanvas) delete fitcanvas; + // fitcanvas = new TCanvas("c1", "c1", fAllSplines.size() * 400 , 600); + // fitcanvas->Divide(fAllSplines.size(), 1); + + // // Clear out points + // for (size_t i = 0; i < fAllDrawnGraphs.size(); i++) { + // if (fAllDrawnGraphs[i]) delete fAllDrawnGraphs[i]; + // if (fAllDrawnHists[i]) delete fAllDrawnHists[i]; + // } + // fAllDrawnGraphs.clear(); + // fAllDrawnHists.clear(); + + + // for (size_t i = 0; i < fAllSplines.size(); i++) { + + // fitcanvas->cd(i + 1); + + // // Store X/Y Vals + // std::vector<std::vector<double> > dialvals; + // std::vector<double> weightvals; + // bool hasresponse = false; + // int npar = (fAllSplines[i]).GetNPar(); + + // for (size_t j = 0; j < fSetIndex.size(); j++) { + // if ((UInt_t)fSetIndex[j] != (UInt_t)i + 1) continue; + // dialvals.push_back(fValList[j]); + // weightvals.push_back(fWeightList[j] - 0.0); + // if (fWeightList[j] != 1.0) hasresponse = true; + // } + + // if (hasresponse) { + + // TGraph* gr = new TGraph(dialvals.size(), dialvals, weightvals); + // fAllDrawnGraphs.push_back(gr); + + // // Get XMax Min + // int n = xvals.size(); + // double xmin = 99999.9; + // double xmax = -99999.9; + // for (int j = 0; j < n; j++) { + // if (xvals[j] > xmax) xmax = xvals[j]; + // if (xvals[j] < xmin) xmin = xvals[j]; + // } + + // TH1D* hist = new TH1D("temp", "temp", 100, xmin, xmax); + // fAllDrawnHists.push_back(hist); + + // for (int k = 0; k < 100; k++) { + // double xtemp = hist->GetXaxis()->GetBinCenter(k + 1); + // fAllSplines[i].Reconfigure(xtemp); + // double ytemp = fAllSplines[i].DoEval(&fCoEffStorer[coeffcount]); + // hist->SetBinContent(k + 1, ytemp); + // } + + // // gr->Draw("APL"); + // hist->SetLineColor(kRed); + // hist->Draw("HIST C"); + // hist->SetTitle("Spline Response"); + // // hist->GetYaxis()->SetRangeUser(0.0, 3.0); + + // // gStyle->SetOptStat(0); + // hist->SetStats(0); + // gr->SetMarkerStyle(20); + // gr->SetTitle("True Weight Points"); + // gr->Draw("P SAME"); + // gPad->BuildLegend(0.6, 0.6, 0.85, 0.85); + // gPad->Update(); + + // hist->SetTitle(fSpline[i].c_str()); + // hist->GetXaxis()->SetTitle("Dial Variation"); + // hist->GetYaxis()->SetTitle("Event Weight"); + // fitcanvas->Update(); + // } + // coeffcount += npar; + // } + // } +} + + + + +// Fitting +// ---------------------------------------------- +void SplineWriter::FitCoeff(Spline* spl, std::vector< std::vector<double> >& v, std::vector<double>& w, float* coeff, bool draw) { + + std::vector<double> x; + std::vector<double> y; + std::vector<double> z; + for (size_t i = 0; i < v.size(); i++) { + x.push_back(v[i][0]); + if (v[i].size() > 1) y.push_back(v[i][1]); + if (v[i].size() > 2) z.push_back(v[i][2]); + } + + switch (spl->GetType()) { + + // Polynominal Graph Fits + case k1DPol1: + case k1DPol2: + case k1DPol3: + case k1DPol4: + case k1DPol5: + case k1DPol6: + + + + FitCoeff1DGraph(spl, v.size(), &x[0], &w[0], coeff, draw); + break; + + case k1DTSpline3: + + GetCoeff1DTSpline3(spl, x.size(), &x[0], &w[0], coeff, draw); + break; + + case k2DPol6: + case k2DGaus: + case k2DTSpline3: + FitCoeff2DGraph(spl, v, w, coeff, draw); + break; + + default: + break; + } + +} + +void SplineWriter::FitCoeff1DGraph(Spline* spl, int n, double* x, double* y, float* coeff, bool draw) { + + TGraph* gr = new TGraph(n, x, y); + double xmin = 99999.9; + double xmax = -99999.9; + for (int i = 0; i < n; i++) { + if (x[i] > xmax) xmax = x[i]; + if (x[i] < xmin) xmin = x[i]; + } + + double xwidth = xmax - xmin; + xmin = xmin - xwidth * 0.01; + xmax = xmax + xwidth * 0.01; + + // Create a new function for fitting. + TF1* func = new TF1("f1", spl, -30.0, 30.0, spl->GetNPar()); + func->SetNpx(400); + func->FixParameter(0, 1.0); // Fix so 1.0 at nominal + + // Run the actual spline fit + StopTalking(); + + // If linear fit with two points + if (n == 2 and spl->GetType() == k1DPol1) { + + float m = (y[1] - y[0]) / (x[1] - x[0]); + float c = y[0] - (0.0 - x[0]) * m; + + func->SetParameter(0, c); + func->SetParameter(1, m); + + } else if (spl->GetType() == k1DPol1) { + gr->Fit(func, "WQ"); + } else { + gr->Fit(func, "FMWQ"); + } + + + StartTalking(); + + for (int i = 0; i < spl->GetNPar(); i++) { + coeff[i] = func->GetParameter(i); + } + + if (draw) { + gr->Draw("APL"); + gPad->Update(); + gPad->SaveAs(("plot_test_" + spl->GetName() + ".pdf").c_str()); + std::cout << "Saving Graph" << std::endl; + sleep(3); + } + + delete func; + delete gr; +} + +double SplineFCN::operator()(const double* x) const { + return DoEval(x); +} + +double SplineFCN::DoEval(const double* x) const { + + float* fx = new float[fSpl->GetNPar()]; + for (int i = 0; i < fSpl->GetNPar(); i++) { + fx[i] = x[i]; + }// + + double tot = 0; + for (size_t i = 0; i < fVal.size(); i++) { + + int nonzero = 0; + for (size_t j = 0; j < fVal[i].size(); j++) { + fSpl->Reconfigure(fVal[i][j], j); + // std::cout << "Reconfiguring " << fVal[i][j] << " " << j << std::endl; + if (fVal[i][j] != 0.0) nonzero++; + } + if (uncorrelated and nonzero > 1) continue; + + double w = fSpl->DoEval(fx); + double wdif = (w - fWeight[i]);// / (fWeight[i] * 0.05); + tot += sqrt(wdif * wdif); + } + + // delete fx; + + return tot; +} + +void SplineFCN::UpdateWeights(std::vector<double>& w) { + for (int i = 0; i < w.size(); i++) { + fWeight[i] = w[i]; + } +} + +void SplineFCN::SetCorrelated(bool state) { + uncorrelated = !state; +} + + + +void SplineFCN::SaveAs(std::string name, const float* fx) { + + + if (fVal[0].size() != 2) { + TCanvas* c1 = new TCanvas("c1", "c1", 800, 600); + c1->Divide(2, 1); + TH1D* histmc = new TH1D("hist", "hist", fVal.size(), 0.0, double(fVal.size())); + TH1D* histdt = new TH1D("histdt", "histdt", fVal.size(), 0.0, double(fVal.size())); - // Make a new plot - if (fDrawSplines and hasresponse) { - TGraph* gr = new TGraph(xvals.size(), &xvals[0], &yvals[0]); - - // Get XMax Min - int n = xvals.size(); - double xmin = 99999.9; - double xmax = -99999.9; - for (int j = 0; j < n; j++) { - if (xvals[j] > xmax) xmax = xvals[j]; - if (xvals[j] < xmin) xmin = xvals[j]; + for (size_t i = 0; i < fVal.size(); i++) { + for (size_t j = 0; j < fVal[i].size(); j++) { + fSpl->Reconfigure(fVal[i][j], j); } - //double xwidth = xmax - xmin; - xmin = xmin - 0.01; - xmax = xmax + 0.01; - - TH1D* hist = new TH1D("temp", "temp", 100, xmin, xmax); - for (int k = 0; k < 100; k++) { - double xtemp = hist->GetXaxis()->GetBinCenter(k + 1); - fAllSplines[i].Reconfigure(xtemp); - double ytemp = fAllSplines[i].DoEval(&fCoEffStorer[coeffcount]); - hist->SetBinContent(k + 1, ytemp); - // std::cout << "Set Temp " << k << " " << ytemp << std::endl; + histmc->SetBinContent( i + 1, fSpl->DoEval(fx) ); + histdt->SetBinContent( i + 1, fWeight[i] ); + } + + // histmc->Add(histdt,-1.0); + + c1->cd(1); + histmc->SetTitle("Spline;Parameter Set;Weight"); + histmc->Draw("HIST"); + histdt->SetLineColor(kRed); + histdt->Draw("SAME HIST"); + + c1->cd(2); + TH1D* histdif = (TH1D*) histmc->Clone(); + histdif->Add(histdt, -1.0); + histdif->Draw("HIST"); + + c1->Update(); + c1->SaveAs(name.c_str()); + delete c1; + } else { + + TGraph2D* histmc = new TGraph2D(); + TGraph2D* histdt = new TGraph2D(); + TGraph2D* histdif = new TGraph2D(); + + for (size_t i = 0; i < fVal.size(); i++) { + for (size_t j = 0; j < fVal[i].size(); j++) { + fSpl->Reconfigure(fVal[i][j], j); } - // gr->Draw("APL"); - hist->SetLineColor(kRed); - hist->Draw("HIST C"); - gr->SetMarkerStyle(20); - gr->Draw("P SAME"); + histmc->SetPoint(histmc->GetN(), fVal[i][0], fVal[i][1], fSpl->DoEval(fx)); + histdt->SetPoint(histdt->GetN(), fVal[i][0], fVal[i][1], fWeight[i]); + histdif->SetPoint(histdif->GetN(), fVal[i][0], fVal[i][1], fabs(fSpl->DoEval(fx) - fWeight[i])); - gPad->Update(); - std::cout << "Writing : " << ("F1eval_" + fSpline[i] + ".pdf") << std::endl; - //gPad->SaveAs(("F1eval_" + fSpline[i] + ".pdf").c_str()); - delete gr; - // delete f1; } + TCanvas* c1 = new TCanvas("c1", "c1", 800, 600); + c1->Divide(3, 1); + c1->cd(1); + histmc->SetTitle(("Spline;" + fSpl->GetName()).c_str()); + histmc->Draw("COLZ"); + gPad->Update(); + c1->cd(2); + histdt->SetTitle(("Raw;" + fSpl->GetName()).c_str()); + histdt->Draw("COLZ"); + c1->cd(3); + histdif->SetTitle(("Dif;" + fSpl->GetName()).c_str()); + histdif->Draw("COLZ"); + gPad->SetRightMargin(0.15); + // gPad->SetLogz(1); + + gPad->Update(); + c1->SaveAs(name.c_str()); + delete c1; + } - // std::cout << "Finished Calcing splines for " << fAllSplines[i].GetName() << std::endl; - // coeffcount += npar; + + + // gPad->SaveAs(name.c_str()); +} + +namespace SplineUtils { +Spline* gSpline = NULL; +} + +double SplineUtils::Func2DWrapper(double* x, double* p) { + // std::cout << "2D Func Wrapper " << x[0] << " " << x[1] << std::endl; + return (*gSpline)(x, p); +} + +void SplineWriter::FitCoeff2DGraph(Spline* spl, std::vector< std::vector<double> >& v, std::vector<double>& w, float* coeff, bool draw) { + +// Make a 2D Function + SplineUtils::gSpline = spl; + TF2* f2 = new TF2("f2", SplineUtils::Func2DWrapper, -30.0, 30.0, -30.0, 30.0, spl->GetNPar()); + TGraph2D* histmc = new TGraph2D(); + for (size_t i = 0; i < v.size(); i++) { + histmc->SetPoint(histmc->GetN(), v[i][0], v[i][1], w[i]); } + StopTalking(); + histmc->Fit(f2,"FMWQ"); + StartTalking(); + for (int i = 0; i < spl->GetNPar(); i++) { + coeff[i] = f2->GetParameter(i); + // std::cout << "Fit 2D Func " << i << " = " << coeff[i] << std::endl; + } - // Check overrides - if (fDrawSplines) { - coeffcount = 0; - for (size_t i = 0; i < fAllSplines.size(); i++) { + delete f2; + delete histmc; + // fSplineFCNs[spl] = new SplineFCN(spl, v, w); + // fSplineFCNs[spl]->SaveAs("mysplinetest_" + spl->GetName() + ".pdf", coeff); + // sleep(1); + // delete fSplineFCNs[spl]; - // Store X/Y Vals - std::vector<double> xvals; - std::vector<double> yvals; - bool hasresponse = false; - int npar = (fAllSplines[i]).GetNPar(); - for (size_t j = 0; j < fSetIndex.size(); j++) { - if ((UInt_t)fSetIndex[j] != (UInt_t)i+1) continue; - xvals.push_back(fValList[j]); - yvals.push_back(fWeightList[j] - 0.0); - if (fWeightList[j] != 1.0) hasresponse = true; - } +} + + +void SplineWriter::FitCoeffNDGraph(Spline* spl, std::vector< std::vector<double> >& v, std::vector<double>& w, float* coeff, bool draw) { - if (hasresponse) { - - TGraph* gr = new TGraph(xvals.size(), &xvals[0], &yvals[0]); - - // Get XMax Min - int n = xvals.size(); - double xmin = 99999.9; - double xmax = -99999.9; - for (int j = 0; j < n; j++) { - if (xvals[j] > xmax) xmax = xvals[j]; - if (xvals[j] < xmin) xmin = xvals[j]; - } - - // double xwidth = xmax - xmin; - // xmin = xmin - xwidth * 0.01; - //xmax = xmax + xwidth * 0.01; - - TH1D* hist = new TH1D("temp", "temp", 100, xmin, xmax); - // for (int k = 0; k < fAllSplines[i].GetNPar(); k++){ - // std::cout << fAllSplines[i].GetName() << " Coeff " << k << " = " << fCoEffStorer[coeffcount + k] << std::endl; - // } - - for (int k = 0; k < 100; k++) { - double xtemp = hist->GetXaxis()->GetBinCenter(k + 1); - fAllSplines[i].Reconfigure(xtemp); - double ytemp = fAllSplines[i].DoEval(&fCoEffStorer[coeffcount]); - hist->SetBinContent(k + 1, ytemp); - - // std::cout << "Set Temp " << k << " " << ytemp << " First Coeff = " << fCoEffStorer[coeffcount] << std::endl; - } - - // gr->Draw("APL"); - hist->SetLineColor(kRed); - hist->Draw("HIST C"); - hist->SetTitle("Spline Response"); - hist->GetYaxis()->SetRangeUser(0.0,3.0); - // gStyle->SetOptStat(0); - hist->SetStats(0); - gr->SetMarkerStyle(20); - gr->SetTitle("True Weight Points"); - gr->Draw("P SAME"); - gPad->BuildLegend(); - gPad->Update(); - - hist->SetTitle(fSpline[i].c_str()); - hist->GetXaxis()->SetTitle("Dial Variation"); - hist->GetYaxis()->SetTitle("Event Weight"); - gPad->Update(); - gPad->SaveAs(("F2_eval_" + fSpline[i] + ".pdf").c_str()); - - delete gr; - std::cout << "Saved hist for " << fSpline[i] << std::endl; - sleep(5); - // delete f1; + // TGraph2D* gr = new TGraph2D(n, x, y); + // double xmin = 99999.9; + // double xmax = -99999.9; + // double ymin = 99999.9; + // double ymax = -99999.9; + // for (int i = 0; i < n; i++) { + // if (x[i] > xmax) xmax = x[i]; + // if (x[i] < xmin) xmin = x[i]; + // if (y[i] > ymax) ymax = y[i]; + // if (y[i] < ymin) ymin = y[i]; + // } + // double xwidth = xmax - xmin; + // xmin = xmin - xwidth * 0.01; + // xmax = xmax + xwidth * 0.01; + // double ywidth = ymax - ymin; + // ymin = ymin - ywidth * 0.01; + // ymax = ymax + ywidth * 0.01; + + + // StopTalking(); + + // Build if not already in writer + // if (fSplineFCNs.find(spl) != fSplineFCNs.end()) { + // fSplineFCNs.erase(spl); + // } + // fSplineFCNs[spl] = new SplineFCN(spl, v, w); + + + if (fSplineFunctors.find(spl) != fSplineFunctors.end()) { + delete fSplineFunctors[spl]; + fSplineFunctors.erase(spl); + } + + if (fSplineFCNs.find(spl) != fSplineFCNs.end()) { + delete fSplineFCNs[spl]; + fSplineFCNs.erase(spl); + } + + if (fSplineMinimizers.find(spl) != fSplineMinimizers.end()) { + delete fSplineMinimizers[spl]; + fSplineMinimizers.erase(spl); + } + + + + if (fSplineMinimizers.find(spl) == fSplineMinimizers.end()) { + std::cout << "Building new ND minimizer for " << spl << std::endl; + fSplineFCNs[spl] = new SplineFCN(spl, v, w); + + // fSplineFCNs[spl] = new SplineFCN(spl, v, w); + fSplineFunctors[spl] = new ROOT::Math::Functor( *fSplineFCNs[spl], spl->GetNPar() ); +// fitclass = "GSLSimAn"; fittype = ""; + fSplineMinimizers[spl] = ROOT::Math::Factory::CreateMinimizer("Minuit2", "Combined"); + fSplineMinimizers[spl]->SetMaxFunctionCalls(1E8); + fSplineMinimizers[spl]->SetMaxIterations(1E8); + fSplineMinimizers[spl]->SetTolerance(1.E-6); + fSplineMinimizers[spl]->SetStrategy(2); + + for (int j = 0; j < spl->GetNPar(); j++) { + if (j != 0) { + fSplineMinimizers[spl]->SetVariable(j, Form("Par_%i", j), 0.1, 0.1); + // fSplineMinimizers[spl]->SetParameter(j, Form("Par_%i", j), 0.1, 0.1, -100.0, 100.0 ); + } else { + fSplineMinimizers[spl]->SetVariable(j, Form("Par_%i", j), 1.0, 0.1); + // fSplineMinimizers[spl]->SetParameter(j, Form("Par_%i", j), 1.0, 0.1, -100.0, 100.0 ); + // fSplineMinimizers[spl]->FixVariable(j); } - coeffcount += npar; } + // fSplineMinimizers[spl]->SetFunction(*fSplineFunctors[spl]); + sleep(1); } + // Create a new function for fitting. + // StopTalking(); + + // Update FCN + fSplineFCNs[spl]->UpdateWeights(w); + // fSplineMinimizers[spl]->SetDefaultOptions(); + // fSplineMinimizers[spl]->Clear(); + for (int j = 0; j < spl->GetNPar(); j++) { + if (j != 0) { + fSplineMinimizers[spl]->SetVariableValue(j, 0.1); + // fSplineMinimizers[spl]->SetParameter(j, Form("Par_%i", j), 0.1, 0.1, -100.0, 100.0 ); + + // fSplineMinimizers[spl]->SetVariableValue(j, 0.1); + } + } + // fSplineFCNs[spl]->SetCorrelated(false); + // fSplineFunctors[spl] = new ROOT::Math::Functor( *fSplineFCNs[spl], spl->GetNPar() ); + // fSplineMinimizers[spl]->SetFunction(*fSplineFunctors[spl]); + // fSplineMinimizers[spl]->Minimize(); + + fSplineFCNs[spl]->SetCorrelated(true); + delete fSplineFunctors[spl]; + fSplineFunctors[spl] = new ROOT::Math::Functor( *fSplineFCNs[spl], spl->GetNPar() ); + fSplineMinimizers[spl]->SetFunction(*fSplineFunctors[spl]); + // ((TFitterMinuit*)fSplineMinimizers[spl])->CreateMinimizer(TFitterMinuit::kMigrad); + fSplineMinimizers[spl]->Minimize(); + fSplineMinimizers[spl]->Minimize(); + + // ((TFitterMinuit*)fSplineMinimizers[spl])->CreateMinimizer(TFitterMinuit::kMigrad); + // fSplineMinimizers[spl]->Minimize(); + + // delete minimizer; + // StartTalking(); + + // Now Get Parameters + const double *values = fSplineMinimizers[spl]->X(); + for (int i = 0; i < spl->GetNPar(); i++) { + + std::cout << "Updated Coeff " << i << " " << values[i] << std::endl; + coeff[i] = values[i]; + } + + // Save a sample + fSplineFCNs[spl]->SaveAs("mysplinetest_" + spl->GetName() + ".pdf", coeff); + sleep(1); + + // delete values; + // delete minimizer; +} + + + +// Spline extraction Functions +void SplineWriter::GetCoeff1DTSpline3(Spline* spl, int n, double* x, double* y, float* coeff, bool draw) { + + StopTalking(); + TSpline3 temp_spline = TSpline3("temp_spline", x, y, n); + StartTalking(); + + for (size_t i = 0; i < (UInt_t)n; i++) { + + double a, b, c, d, e; + temp_spline.GetCoeff(i, a, b, c, d, e); + + coeff[i * 4] = y[i]; + coeff[i * 4 + 1] = c; + coeff[i * 4 + 2] = d; + coeff[i * 4 + 3] = e; + + // std::cout << "Setting Spline Coeff Set " << i << " to " << y[i] << " " << c << " " << d << " " << e << std::endl; + } + + if (draw) { + TGraph* gr = new TGraph(n, x, y); + temp_spline.Draw("CA"); + gr->Draw("PL SAME"); + gPad->Update(); + gPad->SaveAs(("plot_test_" + spl->GetName() + ".pdf").c_str()); + + delete gr; + } + + return; } + diff --git a/src/Splines/SplineWriter.h b/src/Splines/SplineWriter.h index ac2fe86..4cfcdaf 100644 --- a/src/Splines/SplineWriter.h +++ b/src/Splines/SplineWriter.h @@ -1,35 +1,82 @@ #ifndef SPLINEWRITER_H #define SPLINEWRITER_H #include "FitWeight.h" #include "Spline.h" #include "FitParameters.h" +#include "SplineUtils.h" +#include "TFitterMinuit.h" + +class SplineFCN { +public: + + SplineFCN(Spline* spl, std::vector<std::vector<double> > v, std::vector<double> w) { fSpl = spl; fVal = v; fWeight = w; }; + ~SplineFCN() {}; + + double operator()(const double* x) const; + double DoEval(const double *x) const; + void SaveAs(std::string name, const float* fx); + void UpdateWeights(std::vector<double>& w); + void SetCorrelated(bool state = true); + + bool uncorrelated; + std::vector< std::vector<double> > fVal; + std::vector< double > fWeight; + Spline* fSpl; + +}; + class SplineWriter : public SplineReader { - public: - SplineWriter(FitWeight* fw){ +public: + SplineWriter(FitWeight* fw) { fRW = fw; fDrawSplines = FitPar::Config().GetParB("drawsplines"); }; - ~SplineWriter(){}; + ~SplineWriter() {}; void SetupSplineSet(); void Write(std::string name); void AddCoefficientsToTree(TTree* tree); - void FitSplinesForEvent(FitEvent* event); - + void FitSplinesForEvent(FitEvent* event, TCanvas* fitcanvas = NULL, bool saveplot = false); int fNCoEff; // double* fCoEffStorer; float* fCoEffStorer; std::vector< std::vector<double> > fParVect; std::vector< int > fSetIndex; std::vector< double > fWeightList; - std::vector< double > fValList; + std::vector< std::vector<double> > fValList; FitWeight* fRW; bool fDrawSplines; - + + std::vector<TH1D*> fAllDrawnHists; + std::vector<TGraph*> fAllDrawnGraphs; + + std::map<Spline*,SplineFCN*> fSplineFCNs; + std::map<Spline*,ROOT::Math::Functor*> fSplineFunctors; + std::map<Spline*,ROOT::Math::Minimizer*> fSplineMinimizers; + + // Available Fitting Functions +void FitCoeff(Spline* spl, std::vector< std::vector<double> >& v, std::vector<double>& w, float* coeff, bool draw); +void FitCoeff1DGraph(Spline* spl, int n, double* x, double* y, float* coeff, bool draw); +void GetCoeff1DTSpline3(Spline* spl, int n, double* x, double* y, float* coeff, bool draw); +void FitCoeff2DGraph(Spline* spl, std::vector< std::vector<double> >& v, std::vector<double>& w, float* coeff, bool draw); +void FitCoeffNDGraph(Spline* spl, std::vector< std::vector<double> >& v, std::vector<double>& w, float* coeff, bool draw); + + }; + +namespace SplineUtils { + +double Func2DWrapper(double* x, double* p); +extern Spline* gSpline; + // return 1.0; +// } +// void FitCoeff2DGraph(Spline* spl, int n, double* x, double* y, double* z, float* coeff, bool draw); + +} + #endif