diff --git a/Code/FCNCFitter/Bp2Kstmumu_predictions.py b/Code/FCNCFitter/Bp2Kstmumu_predictions.py new file mode 100644 index 0000000..5f172f6 --- /dev/null +++ b/Code/FCNCFitter/Bp2Kstmumu_predictions.py @@ -0,0 +1,91 @@ +import flavio +from wilson import Wilson +from uncertainties import ufloat + +angobs = ['FL', 'S3', 'S4', 'S5', 'AFB', 'S7', 'S8', 'S9'] +#angobs = ['P1', 'P2', 'P3', 'P4p', 'P5p', 'P6p', 'P8p'] + +#q2bins = [[0.1, 0.98], [1.1, 2.5], [2.5, 4], [4, 6], [6, 8], [11, 12.5], [15, 17], [17, 19]] +q2bins = [[0.1, 4.0],[4.0,5.0]]#, [4, 8], [11.0,12.5], [15.0,19.0]] +SMpred, NPpred = {}, {} # to be filled + +# setting Wilson coefficients for NP +w = Wilson({ 'C9_bsmumu': -1}, scale=160, eft='WET', basis='flavio') + +doNP = False +doSM = True +# getting predictions for both SM and NP +for ibin, q2bin in enumerate(q2bins): + print(f'Bin {q2bin}') + SMpred[ibin], NPpred[ibin] = {}, {} + if (doSM): + for o in angobs: + SMpred[ibin][o] = ufloat(flavio.sm_prediction(f'<{o}>(B+->K*mumu)', + q2min=q2bin[0], q2max=q2bin[1]), + flavio.sm_uncertainty(f'<{o}>(B+->K*mumu)', + q2min=q2bin[0], q2max=q2bin[1], N=100)) #N=10k for the final plots, N=100 for the fitter + if (doNP): + for o in angobs: + NPpred[ibin][o] = ufloat(flavio.np_prediction(f'<{o}>(B+->K*mumu)', w, + q2min=q2bin[0], q2max=q2bin[1]), + flavio.np_uncertainty(f'<{o}>(B+->K*mumu)', w, + q2min=q2bin[0], q2max=q2bin[1])) + +# Just printing everything out in human-readable format here +def printout(dic): + for ibin, q2bin in enumerate(q2bins): + print(f'Bin {q2bin}') + for o in angobs: + if o=='FL': + print(f'\tS1s = {3/4*(1-dic[ibin][o])}') + elif o=='AFB': + print(f'\tS6s = {4/3*dic[ibin][o]}') + else: + print(f'\t{o} = {dic[ibin][o]}') + +def printoutCpp(dic): + for o in angobs: + if o=='FL': + print('\tS1s[8] = {') + elif o=='AFB': + print('\tS6s[8] = {') + else: + print(f'\t{o}[8] = {{') + for ibin, q2bin in enumerate(q2bins): + if o=='FL': + print(f'{3/4*(1-dic[ibin][o].n)},', end='') + elif o=='AFB': + print(f'{4/3*dic[ibin][o].n},', end='') + else: + print(f'{dic[ibin][o].n},', end='') + print(f'}};') + for o in angobs: + if o=='FL': + print('\tS1s_error[8] = {') + elif o=='AFB': + print('\tS6s_error[8] = {') + else: + print(f'\t{o}_error[8] = {{') + for ibin, q2bin in enumerate(q2bins): + if o=='FL': + print(f'{3/4*(dic[ibin][o].s)},', end='') + elif o=='AFB': + print(f'{4/3*dic[ibin][o].s},', end='') + else: + print(f'{dic[ibin][o].s},', end='') + print('};') + + +if(doSM): + print('############## SM predictions #################') + printout(SMpred) + + printoutCpp(SMpred) + + print('\n\n\n') + +if(doNP): + print('############## NP predictions #################') + printout(NPpred) + + printoutCpp(NPpred) diff --git a/Code/FCNCFitter/CMakeLists.txt b/Code/FCNCFitter/CMakeLists.txt new file mode 100644 index 0000000..4b2ed62 --- /dev/null +++ b/Code/FCNCFitter/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.0) +set(CMAKE_VERBOSE_MAKEFILE True) + +project(FCNCFitter) + +#get the SPDlog +set(SPDLOG_INCLUDE_DIR "~/B2KstarMuMu/code/spdlog/include/") +set(SPDLOG_INCLUDE_DIR_TWO "~/B2KstarMuMu/code/spdlog/include/spdlog/") + +#Get the source dir +set(SOURCE_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/sources/") + +#get the GSL +include(FindGSL.cmake) + +#try to get ROOT +include(FindROOT.cmake) + +set(CMAKE_CXX_FLAGS "-g -Wall -O3 -std=c++11") + +#specify directories +include_directories( +${ROOT_INCLUDE_DIR} +${SPDLOG_INCLUDE_DIR} +${SPDLOG_INCLUDE_DIR_TWO} +${PROJECT_BINARY_DIR} +${GSL_INCLUDE_DIRS} +${SOURCE_INCLUDE_DIR} +${SOURCE_INCLUDE_DIR}Helpers +${SOURCE_INCLUDE_DIR}Core +${SOURCE_INCLUDE_DIR}Run +${SOURCE_INCLUDE_DIR}Params +) +link_directories( +${ROOT_LIBRARY_DIR} +${GSL_LIBRARY_DIRS} +${SOURCE_INCLUDE_DIR} +${SOURCE_INCLUDE_DIR}Helpers +${SOURCE_INCLUDE_DIR}Core +${SOURCE_INCLUDE_DIR}Run +${SOURCE_INCLUDE_DIR}Params +) + + +# ------------------------------ Bu 2 Kst mu mu ----------------------------# +add_executable(bu2kstarmumu bu2kstarmumu.cc + ${SOURCE_INCLUDE_DIR}Helpers/helpers.cc + ${SOURCE_INCLUDE_DIR}Core/options.cc + ${SOURCE_INCLUDE_DIR}paths.cc + ${SOURCE_INCLUDE_DIR}parse.cc + ${SOURCE_INCLUDE_DIR}Params/constants.cc + ${SOURCE_INCLUDE_DIR}Params/parameters.cc + ${SOURCE_INCLUDE_DIR}Params/parameterscan.cc + ${SOURCE_INCLUDE_DIR}Helpers/design.cc + ${SOURCE_INCLUDE_DIR}Core/fitter.cc + ${SOURCE_INCLUDE_DIR}Core/folder.cc + ${SOURCE_INCLUDE_DIR}Run/mcfit.cc + ${SOURCE_INCLUDE_DIR}Run/massfit.cc + ${SOURCE_INCLUDE_DIR}Run/mainfit.cc + ${SOURCE_INCLUDE_DIR}Run/backgroundfit.cc + ${SOURCE_INCLUDE_DIR}Run/genlvlfit.cc + ${SOURCE_INCLUDE_DIR}Run/momfit.cc + ${SOURCE_INCLUDE_DIR}Run/toysfit.cc + ${SOURCE_INCLUDE_DIR}Run/angularcorr.cc + ${SOURCE_INCLUDE_DIR}Core/bu2kstarmumu_pdf.cc + ${SOURCE_INCLUDE_DIR}Core/bu2kstarmumu_parameters.cc + ${SOURCE_INCLUDE_DIR}Core/bu2kstarmumu_generator.cc + ${SOURCE_INCLUDE_DIR}Core/bu2kstarmumu_plotter.cc + ${SOURCE_INCLUDE_DIR}Core/bu2kstarmumu_loader.cc + ${SOURCE_INCLUDE_DIR}Run/multifit.cc + ${SOURCE_INCLUDE_DIR}Core/funcs.cc + ${SOURCE_INCLUDE_DIR}Core/integrals.cc + ${SOURCE_INCLUDE_DIR}Core/event.cc + ${SOURCE_INCLUDE_DIR}Run/angularcorr.cc + ${SOURCE_INCLUDE_DIR}Run/generatetoys.cc + ${SOURCE_INCLUDE_DIR}Run/pulls.cc + ${SOURCE_INCLUDE_DIR}help.cc + ${SOURCE_INCLUDE_DIR}tests.cc + ${SOURCE_INCLUDE_DIR}Run/likelihoodscan.cc + ${SOURCE_INCLUDE_DIR}Run/feldman_cousins.cc + ${SOURCE_INCLUDE_DIR}Scripts/RunningScripts.cc + ${SOURCE_INCLUDE_DIR}Scripts/ScriptHelpers.cc + ${SOURCE_INCLUDE_DIR}Scripts/ReferencePlots.cc + ${SOURCE_INCLUDE_DIR}Scripts/GenLvlvsMC.cc + ${SOURCE_INCLUDE_DIR}Scripts/EvaluateToys.cc + ${SOURCE_INCLUDE_DIR}Scripts/GetMeanError.cc +) + +#link in these libraries +target_link_libraries( +bu2kstarmumu +${ROOT_LIBRARIES} Minuit MathCore GenVector pthread MathMore gsl gslcblas RooFitCore RooFit +) + + diff --git a/Code/FCNCFitter/Coeffs/Coeffs_KplusPi0Resolved_Run1.txt b/Code/FCNCFitter/Coeffs/Coeffs_KplusPi0Resolved_Run1.txt new file mode 100644 index 0000000..a768b03 --- /dev/null +++ b/Code/FCNCFitter/Coeffs/Coeffs_KplusPi0Resolved_Run1.txt @@ -0,0 +1,126 @@ +1.507323382429900e+00 +-5.613459181592237e-01 +-1.396539684676599e+00 +1.983790804262259e+00 +1.099832513149885e-01 +-2.960130056065321e+00 +-8.187336300741772e-02 +-3.952269555379559e-01 +1.902473503564140e+00 +1.291016482104303e+00 +-3.044469238695420e+00 +-1.804014854108751e+00 +-1.361226650837114e+00 +8.184400573186876e-01 +2.188187203378385e+00 +-5.268186533667468e+00 +-5.195967261112107e-01 +6.647385323311585e+00 +-1.762717917089729e-01 +-6.288537612127318e-01 +1.481671395194009e+00 +-1.329083440491552e+00 +-1.344976403314151e+00 +2.265252888334087e+00 +1.296995380042890e-01 +5.561799558311068e-01 +-2.191671996448252e+00 +-1.166820051612482e+00 +3.290509301920541e+00 +1.444268719410366e+00 +2.952333101187788e-01 +-2.679087845180141e-01 +-2.766919899388740e+00 +7.553625609611633e+00 +2.018757191268887e+00 +-8.466577152377019e+00 +3.428774063411943e-02 +3.189236174613467e-01 +-6.247951417803510e-01 +3.532986332980050e-01 +6.660176321117172e-01 +-6.783329810934459e-01 +-5.326990625397907e-02 +-1.841701555167321e-01 +8.702448804063465e-01 +1.087521378610431e-01 +-1.278422788350668e+00 +-1.481036116778629e-01 +7.077764062651405e-02 +6.735349589285888e-02 +7.946513765494528e-01 +-3.138093850225143e+00 +-6.708174701497344e-01 +3.325058606097596e+00 +-2.042990555796284e-03 +-6.101419131394252e-02 +1.120351640144091e-01 +-5.617086304979706e-02 +-1.323009868002902e-01 +1.080962174293581e-01 +1.087555224021463e-02 +2.108138237484863e-02 +-1.625620726429654e-01 +6.541798314265089e-02 +2.318935115760752e-01 +-6.898604266766525e-02 +-2.647732855321056e-02 +-1.276105538490090e-02 +-8.732345927716964e-02 +5.663342493001184e-01 +8.428725540316630e-02 +-5.842603840687339e-01 +-1.729471478606428e-05 +5.342588040003147e-03 +-1.014659802328625e-02 +5.632334609953240e-03 +1.288390058161915e-02 +-9.681241631728722e-03 +-1.139208040412161e-03 +-8.631017076588197e-04 +1.540969215410285e-02 +-1.299870138751872e-02 +-2.132315500901466e-02 +1.407968081921587e-02 +3.092489772137845e-03 +1.329021820636794e-03 +3.369803886853596e-03 +-5.142994389491435e-02 +-4.136109126106910e-03 +5.261930213060970e-02 +3.356572617668553e-06 +-2.157766379251036e-04 +4.550553445790157e-04 +-3.115654729962487e-04 +-6.027734180344174e-04 +4.626890113905933e-04 +5.696446128918103e-05 +2.855781915769282e-06 +-7.098611712007801e-04 +8.210790139906973e-04 +9.591944591790252e-04 +-8.946194333053164e-04 +-1.591053820078826e-04 +-7.535884994557332e-05 +2.602983157685458e-05 +2.342626014941303e-03 +2.714574860772960e-05 +-2.401103804179887e-03 +-4.616325947783928e-08 +3.248544926215157e-06 +-7.971468229930025e-06 +6.878251229529367e-06 +1.077620280883021e-05 +-9.033462116805898e-06 +-1.073160891944817e-06 +3.461138887560188e-07 +1.257790573371964e-05 +-1.709479499601841e-05 +-1.674682301220750e-05 +1.869135235670497e-05 +3.043794935918759e-06 +1.788377958539638e-06 +-3.035174991266011e-06 +-4.264198150380982e-05 +2.136482341139993e-06 +4.393697931906842e-05 diff --git a/Code/FCNCFitter/Coeffs/Coeffs_KplusPi0Resolved_Run12.txt b/Code/FCNCFitter/Coeffs/Coeffs_KplusPi0Resolved_Run12.txt new file mode 100644 index 0000000..87608f0 --- /dev/null +++ b/Code/FCNCFitter/Coeffs/Coeffs_KplusPi0Resolved_Run12.txt @@ -0,0 +1,560 @@ +1.438775795892140e+00 +0.000000000000000e+00 +-5.320173364832224e-01 +0.000000000000000e+00 +-3.344212851882981e-01 +0.000000000000000e+00 +-5.754925163685108e+00 +0.000000000000000e+00 +1.816007109971708e+00 +0.000000000000000e+00 +1.912798962994150e+01 +0.000000000000000e+00 +-5.294311772743945e+00 +0.000000000000000e+00 +-1.765717474764447e+01 +0.000000000000000e+00 +1.035719343875640e-01 +0.000000000000000e+00 +3.505275673679937e-01 +0.000000000000000e+00 +-1.182431181762031e+00 +0.000000000000000e+00 +-1.104518853405788e+01 +0.000000000000000e+00 +1.368758570762299e+01 +0.000000000000000e+00 +4.213895081025900e+01 +0.000000000000000e+00 +-2.057659828966389e+01 +0.000000000000000e+00 +-3.965291029373369e+01 +0.000000000000000e+00 +2.105191789829710e-02 +0.000000000000000e+00 +-1.076042568396231e+00 +0.000000000000000e+00 +-4.838828348266116e+00 +0.000000000000000e+00 +2.867608106739681e+01 +0.000000000000000e+00 +-1.449205650435084e+00 +0.000000000000000e+00 +-9.460419277002873e+01 +0.000000000000000e+00 +1.957689792126931e+01 +0.000000000000000e+00 +8.318481759121497e+01 +0.000000000000000e+00 +-1.175921822659067e-01 +0.000000000000000e+00 +-9.980101411716920e-02 +0.000000000000000e+00 +5.496903124677671e-01 +0.000000000000000e+00 +8.916891917008284e+00 +0.000000000000000e+00 +-1.170580962348195e+01 +0.000000000000000e+00 +-3.746018825427566e+01 +0.000000000000000e+00 +1.856713806050986e+01 +0.000000000000000e+00 +3.571052274314119e+01 +0.000000000000000e+00 +-1.576684974996945e+00 +0.000000000000000e+00 +1.160940662441611e+00 +0.000000000000000e+00 +6.936392259471095e+00 +0.000000000000000e+00 +-2.095850982890060e+01 +0.000000000000000e+00 +-6.387583012722485e+00 +0.000000000000000e+00 +7.444771339228321e+01 +0.000000000000000e+00 +-9.533586483509936e+00 +0.000000000000000e+00 +-6.469243238612529e+01 +0.000000000000000e+00 +3.786957453615991e-02 +0.000000000000000e+00 +3.717500226174972e-01 +0.000000000000000e+00 +-2.462493212458895e+00 +0.000000000000000e+00 +1.093956581812932e+00 +0.000000000000000e+00 +5.473950337904350e+00 +0.000000000000000e+00 +-8.745028987540548e+00 +0.000000000000000e+00 +-1.536248451391230e+00 +0.000000000000000e+00 +9.860862753636210e+00 +0.000000000000000e+00 +4.621331372544226e-02 +0.000000000000000e+00 +-4.579595632364576e-01 +0.000000000000000e+00 +-1.299154177622542e+00 +0.000000000000000e+00 +1.787533356786050e+01 +0.000000000000000e+00 +-1.437119161537443e+01 +0.000000000000000e+00 +-6.542883645795507e+01 +0.000000000000000e+00 +2.730054668591722e+01 +0.000000000000000e+00 +6.011327044891651e+01 +0.000000000000000e+00 +-1.864698783685063e+00 +0.000000000000000e+00 +-1.634967689639657e+00 +0.000000000000000e+00 +1.692921886694123e+01 +0.000000000000000e+00 +-6.127192950135031e+00 +0.000000000000000e+00 +-3.915030529639013e+01 +0.000000000000000e+00 +4.392774373294450e+01 +0.000000000000000e+00 +1.904377272188025e+01 +0.000000000000000e+00 +-4.301303029651035e+01 +0.000000000000000e+00 +-1.259938774581686e-01 +0.000000000000000e+00 +2.403374440219687e-01 +0.000000000000000e+00 +3.920058464318085e+00 +0.000000000000000e+00 +-1.780158724917398e+01 +0.000000000000000e+00 +8.535552497391024e+00 +0.000000000000000e+00 +6.674324979688666e+01 +0.000000000000000e+00 +-2.370770680180561e+01 +0.000000000000000e+00 +-6.041670678251972e+01 +0.000000000000000e+00 +2.087628522607423e+00 +0.000000000000000e+00 +2.464770771469158e+00 +0.000000000000000e+00 +-1.921939028738314e+01 +0.000000000000000e+00 +-5.229842394469818e-01 +0.000000000000000e+00 +5.130799215963741e+01 +0.000000000000000e+00 +-2.655248636059042e+01 +0.000000000000000e+00 +-3.360773122099580e+01 +0.000000000000000e+00 +2.475557501813477e+01 +0.000000000000000e+00 +-7.838698322371812e-02 +0.000000000000000e+00 +-2.965297143504900e-01 +0.000000000000000e+00 +1.457502312799310e+00 +0.000000000000000e+00 +8.930152409856069e-01 +0.000000000000000e+00 +-3.868115258581269e+00 +0.000000000000000e+00 +4.226114862515917e-01 +0.000000000000000e+00 +2.273180546899596e+00 +0.000000000000000e+00 +-1.646140420403231e+00 +0.000000000000000e+00 +-9.668116287533587e-02 +0.000000000000000e+00 +-2.805849371310622e-02 +0.000000000000000e+00 +1.752211731814707e+00 +0.000000000000000e+00 +-6.318249208106420e+00 +0.000000000000000e+00 +3.199216300242701e+00 +0.000000000000000e+00 +2.513222127535989e+01 +0.000000000000000e+00 +-9.657830202851095e+00 +0.000000000000000e+00 +-2.376837728625016e+01 +0.000000000000000e+00 +9.053204467103039e-01 +0.000000000000000e+00 +1.853910151336333e+00 +0.000000000000000e+00 +-9.164297735637788e+00 +0.000000000000000e+00 +-7.249514664566603e+00 +0.000000000000000e+00 +2.500666446675933e+01 +0.000000000000000e+00 +5.967401217112787e+00 +0.000000000000000e+00 +-1.750289158375252e+01 +0.000000000000000e+00 +-7.559396024990840e-01 +0.000000000000000e+00 +1.676033098208083e-01 +0.000000000000000e+00 +1.252871664355280e-01 +0.000000000000000e+00 +-3.450371185792210e+00 +0.000000000000000e+00 +6.180513796734813e+00 +0.000000000000000e+00 +6.272055273600520e-01 +0.000000000000000e+00 +-2.520713723518794e+01 +0.000000000000000e+00 +7.324827447589672e+00 +0.000000000000000e+00 +2.350577922709661e+01 +0.000000000000000e+00 +-7.820867167399690e-01 +0.000000000000000e+00 +-2.296502092281568e+00 +0.000000000000000e+00 +9.940559181227361e+00 +0.000000000000000e+00 +1.012736855723503e+01 +0.000000000000000e+00 +-3.006999831887735e+01 +0.000000000000000e+00 +-1.377134621329661e+01 +0.000000000000000e+00 +2.362261550086852e+01 +0.000000000000000e+00 +8.905596442335503e+00 +0.000000000000000e+00 +2.149207116460980e-02 +0.000000000000000e+00 +7.031058856992323e-02 +0.000000000000000e+00 +-3.123031180728542e-01 +0.000000000000000e+00 +-3.007799949021578e-01 +0.000000000000000e+00 +8.574732574133230e-01 +0.000000000000000e+00 +2.344905997231403e-01 +0.000000000000000e+00 +-5.652896727683847e-01 +0.000000000000000e+00 +7.286199721180446e-02 +0.000000000000000e+00 +3.023742831366822e-02 +0.000000000000000e+00 +4.297485729087461e-02 +0.000000000000000e+00 +-4.866306704261839e-01 +0.000000000000000e+00 +9.553783890047559e-01 +0.000000000000000e+00 +-2.339255342425295e-01 +0.000000000000000e+00 +-4.245197536727919e+00 +0.000000000000000e+00 +1.578384106607524e+00 +0.000000000000000e+00 +4.162531720344779e+00 +0.000000000000000e+00 +-1.743057528061254e-01 +0.000000000000000e+00 +-4.968851391432376e-01 +0.000000000000000e+00 +1.913858332257758e+00 +0.000000000000000e+00 +2.649020922190229e+00 +0.000000000000000e+00 +-5.519125958406552e+00 +0.000000000000000e+00 +-4.442474893656162e+00 +0.000000000000000e+00 +4.257728468427891e+00 +0.000000000000000e+00 +2.701925485057490e+00 +0.000000000000000e+00 +-4.854858473238228e-02 +0.000000000000000e+00 +-6.048564208859245e-02 +0.000000000000000e+00 +8.752156884131288e-01 +0.000000000000000e+00 +-8.890918857551118e-01 +0.000000000000000e+00 +-6.330570323714021e-01 +0.000000000000000e+00 +4.106787453833199e+00 +0.000000000000000e+00 +-1.056194598185934e+00 +0.000000000000000e+00 +-3.997273913028845e+00 +0.000000000000000e+00 +1.383613819479332e-01 +0.000000000000000e+00 +5.940126065333567e-01 +0.000000000000000e+00 +-2.027521466150096e+00 +0.000000000000000e+00 +-3.341998889425934e+00 +0.000000000000000e+00 +6.419584474162086e+00 +0.000000000000000e+00 +6.322776810847349e+00 +0.000000000000000e+00 +-5.374585908504311e+00 +0.000000000000000e+00 +-4.522040918298464e+00 +0.000000000000000e+00 +-2.352897656066623e-03 +0.000000000000000e+00 +-7.447989204307380e-03 +0.000000000000000e+00 +3.103352874560045e-02 +0.000000000000000e+00 +3.553383173326718e-02 +0.000000000000000e+00 +-8.621110594635656e-02 +0.000000000000000e+00 +-4.053840362135074e-02 +0.000000000000000e+00 +5.991926216536642e-02 +0.000000000000000e+00 +7.847601421659699e-03 +0.000000000000000e+00 +-3.742085432487565e-03 +0.000000000000000e+00 +-6.534570918236404e-03 +0.000000000000000e+00 +5.549239473395826e-02 +0.000000000000000e+00 +-7.398274330638235e-02 +0.000000000000000e+00 +4.719128880467884e-04 +0.000000000000000e+00 +3.654114392965154e-01 +0.000000000000000e+00 +-1.351046414076875e-01 +0.000000000000000e+00 +-3.695230579318745e-01 +0.000000000000000e+00 +1.638424923566694e-02 +0.000000000000000e+00 +5.578652299592122e-02 +0.000000000000000e+00 +-1.888745480474452e-01 +0.000000000000000e+00 +-3.350704991167671e-01 +0.000000000000000e+00 +5.587587719988736e-01 +0.000000000000000e+00 +6.517132932317535e-01 +0.000000000000000e+00 +-4.529197999738007e-01 +0.000000000000000e+00 +-4.372176049571402e-01 +0.000000000000000e+00 +5.776903423777896e-03 +0.000000000000000e+00 +7.741740246597733e-03 +0.000000000000000e+00 +-9.547086666506932e-02 +0.000000000000000e+00 +6.683341051161629e-02 +0.000000000000000e+00 +8.601895187072051e-02 +0.000000000000000e+00 +-3.454137856068547e-01 +0.000000000000000e+00 +8.501531873758481e-02 +0.000000000000000e+00 +3.488252097716409e-01 +0.000000000000000e+00 +-1.256900059103441e-02 +0.000000000000000e+00 +-6.654167688682400e-02 +0.000000000000000e+00 +1.967100373274677e-01 +0.000000000000000e+00 +4.178703916393939e-01 +0.000000000000000e+00 +-6.358440838511148e-01 +0.000000000000000e+00 +-8.728629242960712e-01 +0.000000000000000e+00 +5.517358147655766e-01 +0.000000000000000e+00 +6.372890315878379e-01 +0.000000000000000e+00 +1.140696533038911e-04 +0.000000000000000e+00 +3.663922480127318e-04 +0.000000000000000e+00 +-1.458502153390674e-03 +0.000000000000000e+00 +-1.858183660669370e-03 +0.000000000000000e+00 +4.093404793891319e-03 +0.000000000000000e+00 +2.524988035341650e-03 +0.000000000000000e+00 +-2.957863177921585e-03 +0.000000000000000e+00 +-9.282734944998121e-04 +0.000000000000000e+00 +2.035662853579077e-04 +0.000000000000000e+00 +3.717913837572671e-04 +0.000000000000000e+00 +-2.827739409223422e-03 +0.000000000000000e+00 +2.929121145905270e-03 +0.000000000000000e+00 +5.397922551179735e-04 +0.000000000000000e+00 +-1.573383251203580e-02 +0.000000000000000e+00 +5.886912059317175e-03 +0.000000000000000e+00 +1.627351618259381e-02 +0.000000000000000e+00 +-7.472977440972072e-04 +0.000000000000000e+00 +-2.833919021575961e-03 +0.000000000000000e+00 +8.884769325996444e-03 +0.000000000000000e+00 +1.826391554363844e-02 +0.000000000000000e+00 +-2.665885357580526e-02 +0.000000000000000e+00 +-3.818505305612446e-02 +0.000000000000000e+00 +2.232208217654531e-02 +0.000000000000000e+00 +2.666374076623913e-02 +0.000000000000000e+00 +-3.062274077050677e-04 +0.000000000000000e+00 +-3.926269966852447e-04 +0.000000000000000e+00 +4.728538004443471e-03 +0.000000000000000e+00 +-2.707697250967722e-03 +0.000000000000000e+00 +-4.470975428314534e-03 +0.000000000000000e+00 +1.488416284326369e-02 +0.000000000000000e+00 +-3.753974599926874e-03 +0.000000000000000e+00 +-1.537816905205145e-02 +0.000000000000000e+00 +5.642369912874341e-04 +0.000000000000000e+00 +3.404070095285076e-03 +0.000000000000000e+00 +-9.139585579346044e-03 +0.000000000000000e+00 +-2.280842720270515e-02 +0.000000000000000e+00 +2.983199107666091e-02 +0.000000000000000e+00 +5.014487914108524e-02 +0.000000000000000e+00 +-2.652645201170698e-02 +0.000000000000000e+00 +-3.698380769982702e-02 +0.000000000000000e+00 +-2.065795427176309e-06 +0.000000000000000e+00 +-6.805488452400124e-06 +0.000000000000000e+00 +2.624990916899325e-05 +0.000000000000000e+00 +3.633634590260819e-05 +0.000000000000000e+00 +-7.457195654258806e-05 +0.000000000000000e+00 +-5.566854143366552e-05 +0.000000000000000e+00 +5.576523316450006e-05 +0.000000000000000e+00 +2.613309135430335e-05 +0.000000000000000e+00 +-4.054639045630379e-06 +0.000000000000000e+00 +-7.364031032797539e-06 +0.000000000000000e+00 +5.335436131562981e-05 +0.000000000000000e+00 +-4.724298518908045e-05 +0.000000000000000e+00 +-1.462581314186175e-05 +0.000000000000000e+00 +2.685741849262721e-04 +0.000000000000000e+00 +-1.026565264923978e-04 +0.000000000000000e+00 +-2.819096106126082e-04 +0.000000000000000e+00 +1.320860423575568e-05 +0.000000000000000e+00 +5.373200137240333e-05 +0.000000000000000e+00 +-1.604323462283919e-04 +0.000000000000000e+00 +-3.636290109404678e-04 +0.000000000000000e+00 +4.857371511248402e-04 +0.000000000000000e+00 +7.956041706547389e-04 +0.000000000000000e+00 +-4.166319904317815e-04 +0.000000000000000e+00 +-5.687490529226589e-04 +0.000000000000000e+00 +5.984661520442252e-06 +0.000000000000000e+00 +6.959044921584107e-06 +0.000000000000000e+00 +-8.741418289565478e-05 +0.000000000000000e+00 +4.716232550343118e-05 +0.000000000000000e+00 +8.132057161200026e-05 +0.000000000000000e+00 +-2.598884274079568e-04 +0.000000000000000e+00 +6.965843319857185e-05 +0.000000000000000e+00 +2.707702291959757e-04 +0.000000000000000e+00 +-9.896688255823778e-06 +0.000000000000000e+00 +-6.508132303629572e-05 +0.000000000000000e+00 +1.636642455810912e-04 +0.000000000000000e+00 +4.552717134254304e-04 +0.000000000000000e+00 +-5.365008619516782e-04 +0.000000000000000e+00 +-1.034352404051811e-03 +0.000000000000000e+00 +4.858636040291626e-04 +0.000000000000000e+00 +7.683610839659139e-04 +0.000000000000000e+00 diff --git a/Code/FCNCFitter/Coeffs/Coeffs_KplusPi0Resolved_Run2.txt b/Code/FCNCFitter/Coeffs/Coeffs_KplusPi0Resolved_Run2.txt new file mode 100644 index 0000000..a64c9c9 --- /dev/null +++ b/Code/FCNCFitter/Coeffs/Coeffs_KplusPi0Resolved_Run2.txt @@ -0,0 +1,126 @@ +1.425748136766992e+00 +-1.125449036737295e+00 +-7.136744552272524e-01 +1.578305680181076e+00 +-4.377763974159898e-01 +-2.387538789410834e+00 +-8.192845344202955e-02 +-2.569889874363624e-01 +1.050389756021345e+00 +1.508358445254409e+00 +-1.709255073896953e+00 +-1.623905914817130e+00 +-9.987961638321898e-01 +1.238913826227640e+00 +-9.257039680312273e-01 +-3.262549344763562e+00 +2.790493060780307e+00 +5.258765220248638e+00 +-3.341911492172595e-02 +6.634160854582765e-01 +-5.153661149169929e-01 +-3.527294079469729e+00 +1.173951841944042e+00 +4.572466870718657e+00 +1.361616155836471e-01 +4.242729976067579e-01 +-1.744690199403312e+00 +-2.054796238211036e+00 +2.584640329295740e+00 +2.044285596404793e+00 +-2.369016946464934e-01 +-1.024326449238952e+00 +2.826580857637501e+00 +5.773731831490826e+00 +-4.577594345717358e+00 +-8.396164861706662e+00 +-4.700809613086387e-02 +-3.269680764772347e-01 +3.231259522763095e-01 +1.767539903326413e+00 +-5.786873772580493e-01 +-2.175521709997738e+00 +-6.331829359515367e-02 +-2.566340000037504e-01 +8.559476486570767e-01 +1.108290964043222e+00 +-1.242684217346282e+00 +-1.054089502509917e+00 +2.812292170758831e-01 +5.026814704650281e-01 +-1.403922731117348e+00 +-2.872901368663196e+00 +1.975855755802969e+00 +3.832681927283749e+00 +1.578748431273701e-02 +6.645169556355776e-02 +-7.730007858648250e-02 +-3.591182262380354e-01 +1.236061140846164e-01 +4.329110772318094e-01 +1.278085349117730e-02 +6.255803569109382e-02 +-1.753366943832027e-01 +-2.547190900416993e-01 +2.536385138348534e-01 +2.355652880287911e-01 +-6.338268751841022e-02 +-1.063582509805134e-01 +2.820726456611351e-01 +5.695638526536142e-01 +-3.745466604631191e-01 +-7.295677187875779e-01 +-1.842172996187120e-03 +-6.517383409436638e-03 +8.445085684208537e-03 +3.467474981121118e-02 +-1.277067496391555e-02 +-4.138470574691289e-02 +-1.247283942855627e-03 +-6.966658753004382e-03 +1.712580067989015e-02 +2.755171176799024e-02 +-2.487604500572418e-02 +-2.502134412061325e-02 +6.284727380487962e-03 +1.030474700520226e-02 +-2.727953805369800e-02 +-5.338299121672108e-02 +3.542039807667625e-02 +6.720039830249271e-02 +9.136215946218000e-05 +3.038524035658523e-04 +-4.222017254808240e-04 +-1.588575902326166e-03 +6.240737517321463e-04 +1.888228339227199e-03 +5.832444635778836e-05 +3.571774675736975e-04 +-7.943607158280465e-04 +-1.394302758459940e-03 +1.162747702632733e-03 +1.251779251004430e-03 +-2.917657559835222e-04 +-4.634935104904542e-04 +1.259015675253705e-03 +2.383921872787487e-03 +-1.627806229955408e-03 +-2.982637657996925e-03 +-1.660539161064591e-06 +-5.377994080863866e-06 +7.868603066291942e-06 +2.779884342547798e-05 +-1.156420644896280e-05 +-3.302485938687721e-05 +-1.050839536278033e-06 +-6.848855984921923e-06 +1.409170019941946e-05 +2.662548870051602e-05 +-2.081343532119322e-05 +-2.373813615589443e-05 +5.159095194771221e-06 +7.914832466953750e-06 +-2.223685773065029e-05 +-4.098491476249987e-05 +2.889349837723718e-05 +5.122450688753855e-05 diff --git a/Code/FCNCFitter/FCNCFitter.pro b/Code/FCNCFitter/FCNCFitter.pro new file mode 100644 index 0000000..9f3a677 --- /dev/null +++ b/Code/FCNCFitter/FCNCFitter.pro @@ -0,0 +1,104 @@ +TEMPLATE = app +CONFIG += console +CONFIG -= app_bundle +CONFIG -= qt + +SOURCES += bu2kstarmumu.cc \ + sources/Core/bu2kstarmumu_generator.cc \ + sources/Core/bu2kstarmumu_loader.cc \ + sources/Core/bu2kstarmumu_parameters.cc \ + sources/Core/bu2kstarmumu_pdf.cc \ + sources/Core/bu2kstarmumu_plotter.cc \ + sources/Core/event.cc \ + sources/Core/fitter.cc \ + sources/Core/folder.cc \ + sources/Core/funcs.cc \ + sources/Core/integrals.cc \ + sources/Core/options.cc \ + sources/Core/toystudy.cc \ + sources/Helpers/design.cc \ + sources/Helpers/helpers.cc \ + sources/Params/constants.cc \ + sources/Params/parameters.cc \ + sources/Params/parameterscan.cc \ + sources/Run/angularcorr.cc \ + sources/Run/backgroundfit.cc \ + sources/Run/feldman_cousins.cc \ + sources/Run/generatetoys.cc \ + sources/Run/genlvlfit.cc \ + sources/Run/likelihoodscan.cc \ + sources/Run/mainfit.cc \ + sources/Run/massfit.cc \ + sources/Run/mcfit.cc \ + sources/Run/momfit.cc \ + sources/Run/multifit.cc \ + sources/Run/pulls.cc \ + sources/Run/toysfit.cc \ + sources/Scripts/GenLvlvsMC.cc \ + sources/Scripts/GetMeanError.cc \ + sources/Scripts/PlotMCfit.cc \ + sources/Scripts/ReferencePlots.cc \ + sources/Scripts/RunningScripts.cc \ + sources/Scripts/ScriptHelpers.cc \ + sources/Scripts/EvaluateToys.cc \ + sources/help.cc \ + sources/parse.cc \ + sources/paths.cc \ + sources/tests.cc + +HEADERS += sources/Core/bu2kstarmumu_generator.hh \ + sources/Core/bu2kstarmumu_loader.hh \ + sources/Core/bu2kstarmumu_parameters.hh \ + sources/Core/bu2kstarmumu_pdf.hh \ + sources/Core/bu2kstarmumu_plotter.hh \ + sources/Core/event.hh \ + sources/Core/fitter.hh \ + sources/Core/folder.hh \ + sources/Core/funcs.hh \ + sources/Core/generator.hh \ + sources/Core/integrals.hh \ + sources/Core/options.hh \ + sources/Core/pdf.hh \ + sources/Core/plotter.hh \ + sources/Core/toystudy.hh \ + sources/Helpers/colors.hh \ + sources/Helpers/design.hh \ + sources/Helpers/helpers.hh \ + sources/Params/constants.hh \ + sources/Params/parameters.hh \ + sources/Params/parameterscan.hh \ + sources/Params/values.hh \ + sources/Run/angularcorr.hh \ + sources/Run/backgroundfit.hh \ + sources/Run/feldman_cousins.hh \ + sources/Run/generatetoys.hh \ + sources/Run/genlvlfit.hh \ + sources/Run/likelihoodscan.hh \ + sources/Run/mainfit.hh \ + sources/Run/massfit.hh \ + sources/Run/mcfit.hh \ + sources/Run/momfit.hh \ + sources/Run/multifit.hh \ + sources/Run/pulls.hh \ + sources/Run/toysfit.hh \ + sources/Scripts/GenLvlvsMC.hh \ + sources/Scripts/GetMeanError.hh \ + sources/Scripts/PlotMCfit.hh \ + sources/Scripts/ReferencePlots.hh \ + sources/Scripts/RunningScripts.hh \ + sources/Scripts/ScriptHelpers.hh \ + sources/Scripts/EvaluateToys.hh \ + sources/help.hh \ + sources/parse.hh \ + sources/paths.hh \ + sources/tests.hh + +INCLUDEPATH +=/home/renata/B2KMuMu/sigma0/B2KstarMuMu/code/ewp-Bplus2Kstmumu-AngAna/FCNCfitter/sources/ +INCLUDEPATH +=/home/renata/B2KMuMu/sigma0/B2KstarMuMu/code/ewp-Bplus2Kstmumu-AngAna/FCNCfitter/sources/Core/ +INCLUDEPATH +=/home/renata/B2KMuMu/sigma0/B2KstarMuMu/code/ewp-Bplus2Kstmumu-AngAna/FCNCfitter/sources/Helpers/ +INCLUDEPATH +=/home/renata/B2KMuMu/sigma0/B2KstarMuMu/code/ewp-Bplus2Kstmumu-AngAna/FCNCfitter/sources/Params/ +INCLUDEPATH +=/home/renata/B2KMuMu/sigma0/B2KstarMuMu/code/ewp-Bplus2Kstmumu-AngAna/FCNCfitter/sources/Run/ +INCLUDEPATH +=/home/lhcb/kopecna/B2KstarMuMu/code/spdlog/include/spdlog/ + +unix: CONFIG += link_pkgconfig +unix: PKGCONFIG += /usr/local/root/build/lib/pkgconfig/liblzma.pc diff --git a/Code/FCNCFitter/FindGSL.cmake b/Code/FCNCFitter/FindGSL.cmake new file mode 100644 index 0000000..ec9071d --- /dev/null +++ b/Code/FCNCFitter/FindGSL.cmake @@ -0,0 +1,153 @@ +# Try to find gnu scientific library GSL +# See +# http://www.gnu.org/software/gsl/ and +# http://gnuwin32.sourceforge.net/packages/gsl.htm +# +# Based on a script of Felix Woelk and Jan Woetzel +# (www.mip.informatik.uni-kiel.de) +# +# It defines the following variables: +# GSL_FOUND - system has GSL lib +# GSL_INCLUDE_DIRS - where to find headers +# GSL_LIBRARIES - full path to the libraries +# GSL_LIBRARY_DIRS, the directory where the PLplot library is found. +# GSL_CFLAGS, additional c (c++) required + +message(STATUS "Look for GSL in folder: $ENV{GSL_DIR}") + +set( GSL_FOUND OFF ) +set( GSL_CBLAS_FOUND OFF ) + +if(GSL_INCLUDE_DIR OR GSL_CONFIG_EXECUTABLE) + set(GSL_FIND_QUIETLY 1) +endif() + +# Windows, but not for Cygwin and MSys where gsl-config is available +if( WIN32 AND NOT CYGWIN AND NOT MSYS ) + # look for headers + find_path( GSL_INCLUDE_DIR + NAMES gsl/gsl_cdf.h gsl/gsl_randist.h + PATHS $ENV{GSL_DIR}/include ${GSL_DIR}/include + ) + if( GSL_INCLUDE_DIR ) + # look for gsl library + find_library( GSL_LIBRARY + NAMES gsl + PATHS $ENV{GSL_DIR}/lib ${GSL_DIR}/lib + ) + if( GSL_LIBRARY ) + set( GSL_INCLUDE_DIRS ${GSL_INCLUDE_DIR} ) + get_filename_component( GSL_LIBRARY_DIRS ${GSL_LIBRARY} PATH ) + set( GSL_FOUND ON ) + endif( GSL_LIBRARY ) + + # look for gsl cblas library + find_library( GSL_CBLAS_LIBRARY + NAMES gslcblas + PATHS $ENV{GSL_DIR}/lib ${GSL_DIR}/lib + ) + if( GSL_CBLAS_LIBRARY ) + set( GSL_CBLAS_FOUND ON ) + endif( GSL_CBLAS_LIBRARY ) + + set( GSL_LIBRARIES ${GSL_LIBRARY} ${GSL_CBLAS_LIBRARY} ) + set( GSL_CFLAGS "-DGSL_DLL") + endif( GSL_INCLUDE_DIR ) + + mark_as_advanced( + GSL_INCLUDE_DIR + GSL_LIBRARY + GSL_CBLAS_LIBRARY + ) +else( WIN32 AND NOT CYGWIN AND NOT MSYS ) + if( UNIX OR MSYS ) + find_program( GSL_CONFIG_EXECUTABLE gsl-config + $ENV{GSL_DIR}/bin + ${GSL_DIR}/bin + /usr/bin/ + /usr/local/bin + ) + + if( GSL_CONFIG_EXECUTABLE ) + set( GSL_FOUND ON ) + + # run the gsl-config program to get cxxflags + execute_process( + COMMAND sh "${GSL_CONFIG_EXECUTABLE}" --cflags + OUTPUT_VARIABLE GSL_CFLAGS + RESULT_VARIABLE RET + ERROR_QUIET + ) + if( RET EQUAL 0 ) + string( STRIP "${GSL_CFLAGS}" GSL_CFLAGS ) + separate_arguments( GSL_CFLAGS ) + + # parse definitions from cflags; drop -D* from CFLAGS + string( REGEX MATCHALL "-D[^;]+" + GSL_DEFINITIONS "${GSL_CFLAGS}" ) + string( REGEX REPLACE "-D[^;]+;" "" + GSL_CFLAGS "${GSL_CFLAGS}" ) + + # parse include dirs from cflags; drop -I prefix + string( REGEX MATCHALL "-I[^;]+" + GSL_INCLUDE_DIRS "${GSL_CFLAGS}" ) + string( REPLACE "-I" "" + GSL_INCLUDE_DIRS "${GSL_INCLUDE_DIRS}") + string( REGEX REPLACE "-I[^;]+;" "" + GSL_CFLAGS "${GSL_CFLAGS}") + else( RET EQUAL 0 ) + set( GSL_FOUND FALSE ) + endif( RET EQUAL 0 ) + + # run the gsl-config program to get the libs + execute_process( + COMMAND sh "${GSL_CONFIG_EXECUTABLE}" --libs + OUTPUT_VARIABLE GSL_LIBRARIES + RESULT_VARIABLE RET + ERROR_QUIET + ) + if( RET EQUAL 0 ) + string(STRIP "${GSL_LIBRARIES}" GSL_LIBRARIES ) + separate_arguments( GSL_LIBRARIES ) + + # extract linkdirs (-L) for rpath (i.e., LINK_DIRECTORIES) + string( REGEX MATCHALL "-L[^;]+" + GSL_LIBRARY_DIRS "${GSL_LIBRARIES}" ) + string( REPLACE "-L" "" + GSL_LIBRARY_DIRS "${GSL_LIBRARY_DIRS}" ) + else( RET EQUAL 0 ) + set( GSL_FOUND FALSE ) + endif( RET EQUAL 0 ) + + MARK_AS_ADVANCED( + GSL_CFLAGS + ) + if(NOT GSL_FIND_QUIETLY) + execute_process( + COMMAND sh "${GSL_CONFIG_EXECUTABLE}" --prefix + OUTPUT_VARIABLE GSL_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE) + message( STATUS "Using GSL from ${GSL_PREFIX}") + endif() + else( GSL_CONFIG_EXECUTABLE ) + message( STATUS "FindGSL: gsl-config not found.") + endif( GSL_CONFIG_EXECUTABLE ) + endif( UNIX OR MSYS ) +endif( WIN32 AND NOT CYGWIN AND NOT MSYS ) + +if( GSL_FOUND ) + if( NOT GSL_FIND_QUIETLY ) + message( STATUS "Found GSL: ${GSL_INCLUDE_DIRS} ${GSL_LIBRARIES}" ) + endif( NOT GSL_FIND_QUIETLY ) +else( GSL_FOUND ) + if( GSL_FIND_REQUIRED ) + message( FATAL_ERROR "FindGSL: Could not find GSL headers or library" ) + endif( GSL_FIND_REQUIRED ) +endif( GSL_FOUND ) + +mark_as_advanced( + GSL_CONFIG_EXECUTABLE + GSL_INCLUDE_DIR + GSL_LIBRARY + GSL_CBLAS_LIBRARY +) + diff --git a/Code/FCNCFitter/FindROOT.cmake b/Code/FCNCFitter/FindROOT.cmake new file mode 100644 index 0000000..5fe418f --- /dev/null +++ b/Code/FCNCFitter/FindROOT.cmake @@ -0,0 +1,270 @@ +# - Find ROOT instalation +# This module tries to find the ROOT installation on your system. +# It tries to find the root-config script which gives you all the needed information. +# If the system variable ROOTSYS is set this is straight forward. +# If not the module uses the pathes given in ROOT_CONFIG_SEARCHPATH. +# If you need an other path you should add this path to this varaible. +# The root-config script is then used to detect basically everything else. +# This module defines a number of key variables and macros. + +# F.Uhlig@gsi.de (fairroot.gsi.de) + + +MESSAGE(STATUS "Looking for Root...") + +SET(ROOT_CONFIG_SEARCHPATH + ${SIMPATH}/tools/root/bin + $ENV{ROOTSYS}/bin + /usr/bin +) + +SET(ROOT_DEFINITIONS "") + +SET(ROOT_INSTALLED_VERSION_TOO_OLD FALSE) + +SET(ROOT_CONFIG_EXECUTABLE ROOT_CONFIG_EXECUTABLE-NOTFOUND) + +FIND_PROGRAM(ROOT_CONFIG_EXECUTABLE NAMES root-config PATHS + ${ROOT_CONFIG_SEARCHPATH} + NO_DEFAULT_PATH) + +IF (${ROOT_CONFIG_EXECUTABLE} MATCHES "ROOT_CONFIG_EXECUTABLE-NOTFOUND") + MESSAGE( FATAL_ERROR "ROOT not installed in the searchpath and ROOTSYS is not set. Please + set ROOTSYS or add the path to your ROOT installation in the Macro FindROOT.cmake in the + subdirectory cmake/modules.") +ELSE (${ROOT_CONFIG_EXECUTABLE} MATCHES "ROOT_CONFIG_EXECUTABLE-NOTFOUND") + STRING(REGEX REPLACE "(^.*)/bin/root-config" "\\1" test ${ROOT_CONFIG_EXECUTABLE}) + SET( ENV{ROOTSYS} ${test}) + set( ROOTSYS ${test}) +ENDIF (${ROOT_CONFIG_EXECUTABLE} MATCHES "ROOT_CONFIG_EXECUTABLE-NOTFOUND") + + +IF (ROOT_CONFIG_EXECUTABLE) + + SET(ROOT_FOUND FALSE) + + EXEC_PROGRAM(${ROOT_CONFIG_EXECUTABLE} ARGS "--version" OUTPUT_VARIABLE ROOTVERSION) + + MESSAGE(STATUS "Looking for Root... - found $ENV{ROOTSYS}/bin/root") + MESSAGE(STATUS "Looking for Root... - version ${ROOTVERSION} ") + + # we need at least version 6.00/00 + IF (NOT ROOT_MIN_VERSION) + SET(ROOT_MIN_VERSION "6.00/00") + ENDIF (NOT ROOT_MIN_VERSION) + + # now parse the parts of the user given version string into variables + STRING(REGEX REPLACE "^([0-9]+)\\.[0-9][0-9]+\\/[0-9][0-9]+" "\\1" req_root_major_vers "${ROOT_MIN_VERSION}") + STRING(REGEX REPLACE "^[0-9]+\\.([0-9][0-9])+\\/[0-9][0-9]+.*" "\\1" req_root_minor_vers "${ROOT_MIN_VERSION}") + STRING(REGEX REPLACE "^[0-9]+\\.[0-9][0-9]+\\/([0-9][0-9]+)" "\\1" req_root_patch_vers "${ROOT_MIN_VERSION}") + + # and now the version string given by qmake + STRING(REGEX REPLACE "^([0-9]+)\\.[0-9][0-9]+\\/[0-9][0-9]+.*" "\\1" found_root_major_vers "${ROOTVERSION}") + STRING(REGEX REPLACE "^[0-9]+\\.([0-9][0-9])+\\/[0-9][0-9]+.*" "\\1" found_root_minor_vers "${ROOTVERSION}") + STRING(REGEX REPLACE "^[0-9]+\\.[0-9][0-9]+\\/([0-9][0-9]+).*" "\\1" found_root_patch_vers "${ROOTVERSION}") + + IF (found_root_major_vers LESS 5) + MESSAGE( FATAL_ERROR "Invalid ROOT version \"${ROOTERSION}\", at least major version 4 is required, e.g. \"5.00/00\"") + ENDIF (found_root_major_vers LESS 5) + + # compute an overall version number which can be compared at once + MATH(EXPR req_vers "${req_root_major_vers}*10000 + ${req_root_minor_vers}*100 + ${req_root_patch_vers}") + MATH(EXPR found_vers "${found_root_major_vers}*10000 + ${found_root_minor_vers}*100 + ${found_root_patch_vers}") + + IF (found_vers LESS req_vers) + SET(ROOT_FOUND FALSE) + SET(ROOT_INSTALLED_VERSION_TOO_OLD TRUE) + ELSE (found_vers LESS req_vers) + SET(ROOT_FOUND TRUE) + ENDIF (found_vers LESS req_vers) + +ENDIF (ROOT_CONFIG_EXECUTABLE) + + +IF (ROOT_FOUND) + + # ask root-config for the library dir + # Set ROOT_LIBRARY_DIR + + EXEC_PROGRAM( ${ROOT_CONFIG_EXECUTABLE} + ARGS "--libdir" + OUTPUT_VARIABLE ROOT_LIBRARY_DIR_TMP ) + + IF(EXISTS "${ROOT_LIBRARY_DIR_TMP}") + SET(ROOT_LIBRARY_DIR ${ROOT_LIBRARY_DIR_TMP} ) + ELSE(EXISTS "${ROOT_LIBRARY_DIR_TMP}") + MESSAGE("Warning: ROOT_CONFIG_EXECUTABLE reported ${ROOT_LIBRARY_DIR_TMP} as library path,") + MESSAGE("Warning: but ${ROOT_LIBRARY_DIR_TMP} does NOT exist, ROOT must NOT be installed correctly.") + ENDIF(EXISTS "${ROOT_LIBRARY_DIR_TMP}") + + # ask root-config for the binary dir + EXEC_PROGRAM(${ROOT_CONFIG_EXECUTABLE} + ARGS "--bindir" + OUTPUT_VARIABLE root_bins ) + SET(ROOT_BINARY_DIR ${root_bins}) + + # ask root-config for the include dir + EXEC_PROGRAM( ${ROOT_CONFIG_EXECUTABLE} + ARGS "--incdir" + OUTPUT_VARIABLE root_headers ) + SET(ROOT_INCLUDE_DIR ${root_headers}) + # CACHE INTERNAL "") + + # ask root-config for the library varaibles + EXEC_PROGRAM( ${ROOT_CONFIG_EXECUTABLE} +# ARGS "--noldflags --noauxlibs --libs" + ARGS "--glibs" + OUTPUT_VARIABLE root_flags ) + +# STRING(REGEX MATCHALL "([^ ])+" root_libs_all ${root_flags}) +# STRING(REGEX MATCHALL "-L([^ ])+" root_library ${root_flags}) +# REMOVE_FROM_LIST(root_flags "${root_libs_all}" "${root_library}") + + SET(ROOT_LIBRARIES ${root_flags}) + + # Make variables changeble to the advanced user + MARK_AS_ADVANCED( ROOT_LIBRARY_DIR ROOT_INCLUDE_DIR ROOT_DEFINITIONS) + + # Set ROOT_INCLUDES + SET( ROOT_INCLUDES ${ROOT_INCLUDE_DIR}) + + SET(LD_LIBRARY_PATH ${LD_LIBRARY_PATH} ${ROOT_LIBRARY_DIR}) + + ####################################### + # + # Check the executables of ROOT + # ( rootcint ) + # + ####################################### + + FIND_PROGRAM(ROOT_CINT_EXECUTABLE + NAMES rootcint + PATHS ${ROOT_BINARY_DIR} + NO_DEFAULT_PATH + ) + +ENDIF (ROOT_FOUND) + + + + ########################################### + # + # Macros for building ROOT dictionary + # + ########################################### + +MACRO (ROOT_GENERATE_DICTIONARY_OLD ) + + set(INFILES "") + + foreach (_current_FILE ${ARGN}) + + IF (${_current_FILE} MATCHES "^.*\\.h$") + IF (${_current_FILE} MATCHES "^.*Link.*$") + set(LINKDEF_FILE ${_current_FILE}) + ELSE (${_current_FILE} MATCHES "^.*Link.*$") + set(INFILES ${INFILES} ${_current_FILE}) + ENDIF (${_current_FILE} MATCHES "^.*Link.*$") + ELSE (${_current_FILE} MATCHES "^.*\\.h$") + IF (${_current_FILE} MATCHES "^.*\\.cxx$") + set(OUTFILE ${_current_FILE}) + ELSE (${_current_FILE} MATCHES "^.*\\.cxx$") + set(INCLUDE_DIRS ${INCLUDE_DIRS} -I${_current_FILE}) + ENDIF (${_current_FILE} MATCHES "^.*\\.cxx$") + ENDIF (${_current_FILE} MATCHES "^.*\\.h$") + + endforeach (_current_FILE ${ARGN}) + +# MESSAGE("INFILES: ${INFILES}") +# MESSAGE("OutFILE: ${OUTFILE}") +# MESSAGE("LINKDEF_FILE: ${LINKDEF_FILE}") +# MESSAGE("INCLUDE_DIRS: ${INCLUDE_DIRS}") + + STRING(REGEX REPLACE "(^.*).cxx" "\\1.h" bla "${OUTFILE}") +# MESSAGE("BLA: ${bla}") + SET (OUTFILES ${OUTFILE} ${bla}) + + ADD_CUSTOM_COMMAND(OUTPUT ${OUTFILES} + COMMAND ${ROOT_CINT_EXECUTABLE} + ARGS -f ${OUTFILE} -c -DHAVE_CONFIG_H ${INCLUDE_DIRS} ${INFILES} ${LINKDEF_FILE} DEPENDS ${INFILES}) + +# MESSAGE("ROOT_CINT_EXECUTABLE has created the dictionary ${OUTFILE}") + +ENDMACRO (ROOT_GENERATE_DICTIONARY_OLD) + + ########################################### + # + # Macros for building ROOT dictionary + # + ########################################### + +MACRO (ROOT_GENERATE_DICTIONARY INFILES LINKDEF_FILE OUTFILE INCLUDE_DIRS_IN) + + set(INCLUDE_DIRS) + + foreach (_current_FILE ${INCLUDE_DIRS_IN}) + set(INCLUDE_DIRS ${INCLUDE_DIRS} -I${_current_FILE}) + endforeach (_current_FILE ${INCLUDE_DIRS_IN}) + + +# MESSAGE("INFILES: ${INFILES}") +# MESSAGE("OutFILE: ${OUTFILE}") +# MESSAGE("LINKDEF_FILE: ${LINKDEF_FILE}") +# MESSAGE("INCLUDE_DIRS: ${INCLUDE_DIRS}") + + STRING(REGEX REPLACE "^(.*)\\.(.*)$" "\\1.h" bla "${OUTFILE}") +# MESSAGE("BLA: ${bla}") + SET (OUTFILES ${OUTFILE} ${bla}) + + + if (CMAKE_SYSTEM_NAME MATCHES Linux) + ADD_CUSTOM_COMMAND(OUTPUT ${OUTFILES} + COMMAND LD_LIBRARY_PATH=${ROOT_LIBRARY_DIR} ROOTSYS=${ROOTSYS} ${ROOT_CINT_EXECUTABLE} + ARGS -f ${OUTFILE} -c -DHAVE_CONFIG_H ${INCLUDE_DIRS} ${INFILES} ${LINKDEF_FILE} DEPENDS ${INFILES} ${LINKDEF_FILE}) + else (CMAKE_SYSTEM_NAME MATCHES Linux) + if (CMAKE_SYSTEM_NAME MATCHES Darwin) + ADD_CUSTOM_COMMAND(OUTPUT ${OUTFILES} + COMMAND DYLD_LIBRARY_PATH=${ROOT_LIBRARY_DIR} ROOTSYS=${ROOTSYS} ${ROOT_CINT_EXECUTABLE} + ARGS -f ${OUTFILE} -c -DHAVE_CONFIG_H ${INCLUDE_DIRS} ${INFILES} ${LINKDEF_FILE} DEPENDS ${INFILES} ${LINKDEF_FILE}) + endif (CMAKE_SYSTEM_NAME MATCHES Darwin) + endif (CMAKE_SYSTEM_NAME MATCHES Linux) + +ENDMACRO (ROOT_GENERATE_DICTIONARY) + +MACRO (GENERATE_ROOT_TEST_SCRIPT SCRIPT_FULL_NAME) + + get_filename_component(path_name ${SCRIPT_FULL_NAME} PATH) + get_filename_component(file_extension ${SCRIPT_FULL_NAME} EXT) + get_filename_component(file_name ${SCRIPT_FULL_NAME} NAME_WE) + set(shell_script_name "${file_name}.sh") + + #MESSAGE("PATH: ${path_name}") + #MESSAGE("Ext: ${file_extension}") + #MESSAGE("Name: ${file_name}") + #MESSAGE("Shell Name: ${shell_script_name}") + + string(REPLACE ${PROJECT_SOURCE_DIR} + ${PROJECT_BINARY_DIR} new_path ${path_name} + ) + + #MESSAGE("New PATH: ${new_path}") + + file(MAKE_DIRECTORY ${new_path}/data) + + CONVERT_LIST_TO_STRING(${LD_LIBRARY_PATH}) + set(MY_LD_LIBRARY_PATH ${output}) + set(my_script_name ${SCRIPT_FULL_NAME}) + + if(CMAKE_SYSTEM MATCHES Darwin) + configure_file(${PROJECT_SOURCE_DIR}/cmake/scripts/root_macro_macos.sh.in + ${new_path}/${shell_script_name} + ) + else(CMAKE_SYSTEM MATCHES Darwin) + configure_file(${PROJECT_SOURCE_DIR}/cmake/scripts/root_macro.sh.in + ${new_path}/${shell_script_name} + ) + endif(CMAKE_SYSTEM MATCHES Darwin) + + EXEC_PROGRAM(/bin/chmod ARGS "u+x ${new_path}/${shell_script_name}") + +ENDMACRO (GENERATE_ROOT_TEST_SCRIPT) diff --git a/Code/FCNCFitter/LaTeXfiles/fileForGit b/Code/FCNCFitter/LaTeXfiles/fileForGit new file mode 100644 index 0000000..e69de29 diff --git a/Code/FCNCFitter/SetPaths.sh b/Code/FCNCFitter/SetPaths.sh new file mode 100644 index 0000000..f44405a --- /dev/null +++ b/Code/FCNCFitter/SetPaths.sh @@ -0,0 +1,4 @@ +#configuration of source and lib paths to compile FCNCfitter +LD_LIBRARY_PATH=/cvmfs/lhcb.cern.ch/lib/lcg/releases/gcc/4.9.3/x86_64-slc6/lib64:/cvmfs/lhcb.cern.ch/lib/lcg/releases/LCG_84/ROOT/6.06.02/x86_64-slc6-gcc49-opt/lib + +PATH=/cvmfs/lhcb.cern.ch/lib/lcg/releases/LCG_84/gcc/4.9.3/x86_64-slc6/bin:/cvmfs/lhcb.cern.ch/lib/lcg/releases/LCG_84/ROOT/6.06.02/x86_64-slc6-gcc49-opt/bin:/cvmfs/lhcb.cern.ch/lib/lcg/releases/gcc/4.9.3/x86_64-slc6/bin:/usr/sue/bin:/usr/lib64/qt-3.3/bin:/cvmfs/lhcb.cern.ch/lib/bin/x86_64-slc6:/cvmfs/lhcb.cern.ch/lib/bin/Linux-x86_64:/cvmfs/lhcb.cern.ch/lib/bin:/cvmfs/lhcb.cern.ch/lib/var/lib/LbEnv/1020/stable/linux-64/bin:/bin:/usr/bin:/usr/sbin:/sbin diff --git a/Code/FCNCFitter/bu2kstarmumu.cc b/Code/FCNCFitter/bu2kstarmumu.cc new file mode 100644 index 0000000..d3d2ef0 --- /dev/null +++ b/Code/FCNCFitter/bu2kstarmumu.cc @@ -0,0 +1,412 @@ +/** + * @file bu2kstarmumu.cc + * @author Christoph Langenbruch, David Gerick, Renata Kopecna + * @date 2020-30-11 + * + * Main control file for the Bu -> K*+mumu analysis + */ + +#include +#include +#include +#include +#include + +//Yes, I know that <> is not ideal for compilation time, +//but I was lazy to always put the correct path there at the begining +//when files were moved around rather often +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sources/Scripts/RunningScripts.hh" + +#include +#include + + +int main ( int argc, char *argv[] ) +{ + //Set gROOT and gStyle + gROOT->SetStyle("Plain"); + set_gStyle(); + //Initiliaze pretty colors + myColorScheme::init(); + //gStyle->SetPaintTextFormat("4.1f m"); + //gStyle->SetCanvasPreferGL(true); + + ///set the fitting options + fcnc::options opts; + opts = fcnc::options("-1"); + + //how many events should be taken per Test/ToyFit? + UInt_t nMCEvents = 350; + + + //Retun errors: + //1: wrong options + //5: Inexplicable stuff + //404: not found + + basic_params pars = basic_params(); + basic_actions acts = basic_actions(); + //The pars and acts are a bit wonky at the moment, hopefully as I progress this will get better + if (parseOpts(argc, argv, pars, acts, nMCEvents) == 1) return 1; + if (checkOpts(pars,acts) == 1) return 1; + + //Set opts.folding according to the parsed options + //default should be -1 + opts.folding = pars.folding; + + //////////////////////////////////////////// + // [START] GLOBAL OPTIONS + //////////////////////////////////////////// + + //Use only DTF, could be removed + opts.DTF = true; + + //SET OUTPUT DESIGN + reset_spdlog(); + set_spdlog_level(pars.verbosity); + + //Make ROOT shut up + gStyle -> SetOptStat(0); + gROOT->SetBatch(kTRUE); + gErrorIgnoreLevel = kWarning; + //gErrorIgnoreLevel = kError; + + opts.ncores = NCORES; + if(opts.ncores > 1) spdlog::info("[CPU]\tUse parallelisation on {0:d} CPU cores", opts.ncores); + + //FIXED to true, since we have flatQ2 phase-space MC + opts.IsFlatQ2 = true; + + //get individual angular acceptance corrections for every year + opts.angacccorrperyear = false; + //Decide in what format everything should be saved in + opts.write_eps = true; + opts.write_C = false; + opts.write_jpg = false; + opts.write_pdf = true; + + //Set the default path for plots_folder, somehow it doesn't want to accept PLOTS_PATH in the options constructor, possibly fix TODO + opts.plot_folder = PLOTS_PATH; + + //fit pdfs over complete phi range [-pi, +pi] + opts.full_angular = opts.folding == -1; + //use a two tailed CrystalBall function instead of a Gaussian + opts.twotailedcrystalball = DOUBLE_CB; + opts.crystalball = !DOUBLE_CB; + //No exponential, but flat background model + opts.flat_bkg = false; + + ////////////////////////// + // HARDCODED FUNCTIONS: // + ////////////////////////// + + //default is NOT Kshort channel: + opts.KS = false; + + //Set 'globally' fl and afb to (not) be used + opts.fit_fl = true; + opts.fit_afb = true; + + //Set 'globaly' to use lambda in the background fit + //fit exponential with exp(-lambda*x) instead of exp(-x/tau), it has better precision + opts.fit_lambda = true; + + //Assymetries to be included in the fit itself + opts.fit_asymmetries = false; //you don't have enough stats for this to be true + + ///////////////////////////////////// + // Set the order of the polynomial // + ///////////////////////////////////// + opts.bkg_order_costhetal = 2; //TODO: put as a const into constants.cc and modify it accordingly in options.cc + opts.bkg_order_costhetak = 5; + + //////////////////////// + // ANGULAR RESOLUTION // + //////////////////////// + + //Set the order of legendre polynomial + opts.eff_order_costhetal = ORDER_COSTHETAL; + opts.eff_order_costhetak = ORDER_COSTHETAK; + opts.eff_order_phi = ORDER_PHI; + opts.eff_order_q2 = ORDER_Q2; + + std::vector> resolution = get_resolution(); + + //Have angular correction per each Run (false) + opts.angacccorrbothruns = false; + + //Don't use angular acceptance convoluted in the likelihood (false) + opts.use_angular_acc = false; + + //////////////////////////////////////////// + // GLOBAL OPTIONS // + //////////////////////////////////////////// + + //TODO fix this (actually nice, but can be done elsewhere) + //maximum range of considered B mass: + opts.m_low = B_MASS_LOW; + opts.m_high = B_MASS_HIGH; + //signal window of B mass: + opts.m_min = PDGMASS_B-B_MASS_TIGHT_WINDOW; + opts.m_max = PDGMASS_B+B_MASS_TIGHT_WINDOW; + + //If MC, use MC weights//TODO: check for data + opts.multiply_eff = pars.dataset >0; + + //TODO move to paths + std::string angularsuffix = opts.full_angular ? "full_angular" : "folding"+std::to_string(opts.folding); + + + //generate vector with years for every run option, including just one year + std::vectoryears = (pars.Run == 0 ? std::vector{pars.year} : get_years(pars.Run, pars.dataset==1, pars.dataset==2)); + spdlog::debug("Using years: " + convert_vector_to_string(years)); + + //--------------------------------------------- + // Put stuff from pars and acts into opts + //--------------------------------------------- + //yes it is dumb but I cannot be bothered to change the whole options + opts.verbose = pars.verbosity; + opts.run = pars.Run; //This is not ideal when fitting per year, + //From now on passing the pars as well + opts.useMC = pars.dataset > 0; + opts.fit_pprimes = pars.usePprime; + + //------------------------------- + // Get corresponding Q2 bins + //------------------------------- + if (pars.reference) pars.nBins = 1; //For reference, always use 1 bin + opts.TheQ2binsmin = get_TheQ2binsmin(pars.nBins, pars.reference); + opts.TheQ2binsmax = get_TheQ2binsmax(pars.nBins, pars.reference); + + spdlog::debug("Using {0:d} q2 bins.", opts.TheQ2binsmax.size()); + + if (spdlog::default_logger_raw()->level()==spdlog::level::info){ + spdlog::info("Using the following binning scheme:"); + for(UInt_t b = 0; b < opts.TheQ2binsmin.size(); b++){ + assert(opts.TheQ2binsmin.at(b) != 0.0); + assert(opts.TheQ2binsmax.at(b) != 0.0); + assert(opts.TheQ2binsmin.at(b) < opts.TheQ2binsmax.at(b)); + std::cout << std::fixed << std::setprecision(2) << "\tbin" << b+1 << ": [" << opts.TheQ2binsmin.at(b) << "-" << opts.TheQ2binsmax.at(b) << "] GeV^2/c^4" << std::endl; + } + } + + //------------------------------- + // Set ranges of the angles + //------------------------------- + //Not ideal to have it as an opts and as a constant, but this is how it is going to be now + opts.reset_angle_ranges(); + //The ranges might change in the folding, hence I will keep the opts.angle_min/max for this case + + + //Check if something is wrong; if any task is assigned, raise this flag + bool isItDoingAnything_flag = false; + int returnCode = 0; + + //------------------------------- + // create branches for FCNCfitter + //------------------------------- + if(acts.convert){ //these booleans are only for running, used only here + //maybe put it into a new class //TODO + isItDoingAnything_flag = true; + return convert_tuples(pars.dataset, get_theFCNCpath(pars.dataset, opts.run), opts,years); + } + + //------------------------------- + // scan angular acceptance max. order of legendre + //------------------------------- + if(acts.angCorrScan){ + isItDoingAnything_flag = true; + bool quickTest = false; + bool test_4times1D = false; + bool checkSignificance = false; + bool runMinuit = false; + bool checkFactorization = false; + bool do3Dmoments = false; + const bool assumePhiEven = IS_PHI_EVEN; + spdlog::debug("Scanning angular acceptance corrections..."); + returnCode = scan_max_order_angular_ccorrection(opts, assumePhiEven, quickTest, test_4times1D, + checkSignificance, runMinuit, checkFactorization, do3Dmoments); + if (returnCode!=0) return returnCode; + } + + //------------------------------- + // fit angular acceptance + //------------------------------- + if (acts.angCorr){ + if (pars.testInt > -1) sanityCheck_MC(opts); + else{ + isItDoingAnything_flag = true; + bool testSaving = false; + spdlog::debug("Calculating angular acceptance correction parameters..."); + returnCode = get_angular_acceptance(opts, testSaving); + if (returnCode!=0) return returnCode; + } + } + + //-------------------------------- + // FIT MASS + //-------------------------------- + if(acts.fitType == 2){ + isItDoingAnything_flag = true; + bool splitRuns = true; + massfit(opts, pars.reference, splitRuns, pars); + } + + //-------------------------------- + // MC FIT + //-------------------------------- + if(acts.fitType == 4){ + isItDoingAnything_flag = true; + opts.only_angles = false;//(nBins == 8); //Do not fit the mass, just angles //Apply only when fitting B0 binning + //Reference MC is broken (K* is PHSP), so when fitting the reference, fit only mass + opts.only_Bmass = pars.reference; //Do not fit the angles, just mass + opts.initSM = !pars.reference; //Set to true only for reference + returnCode = mcfit_4D(opts, pars.reference, pars.dataset==3, pars); + //yes, fitRef could be included in params, but I like to keep my options open :) + if (returnCode!=0) return returnCode; + } + + //-------------------------------- + // COMPLETE FIT + //-------------------------------- + if(acts.fitType == 1){ + isItDoingAnything_flag = true; + bool fitToy = pars.testInt > -1; //If test, then do fit toys + if (pars.folding == 5){ //We do not need this here, we can run the code 5 times, no? + for (int f = 0; f < 5; f++){ + pars.folding = f; + opts.folding = f; + spdlog::debug("Fitting with folding={0:d}", pars.folding); + mainfit(opts, pars, pars.reference, fitToy, pars.likelyhood, pars.FeldCous); + } + } + else { + mainfit(opts, pars, pars.reference, fitToy, pars.likelyhood, pars.FeldCous); + } + } + + //-------------------------------- + // BACKGROUND ONLY FIT + //-------------------------------- + if(acts.fitType == 0){ + isItDoingAnything_flag = true; + + //Clear the bkgFit file + clear_Latex_noteFile("_bkgFit"); + + //Set options + //One can also fit only upper/lower mass sideband, to set this use -index + bool LowMassFit = (pars.index == 1); + bool HighMassFit = (pars.index == 2); + bool Use2DAngularBins = false; + bool fitKpiMass = true; + + //Run the background only fit + int bkgfit = 0; + if (pars.folding == 5){ //We do not need this here, we can run the code 5 times, no? + for (int f = 0; f < 5; f++){ + pars.folding = f; + opts.folding = f; + bkgfit =+ backgroundfit(opts, pars.reference, + LowMassFit, HighMassFit, fitKpiMass, + Use2DAngularBins, pars); + } + } + else bkgfit = backgroundfit(opts, pars.reference, + LowMassFit, HighMassFit, fitKpiMass, + Use2DAngularBins, pars); + if (bkgfit != 0) return bkgfit; + } + + //-------------------------------- + // start GENERATOR LEVEL MC FIT + //-------------------------------- + if(acts.fitType == 5){ + isItDoingAnything_flag = true; + opts.initSM = pars.nBins != 8; //SM for 8 bins not implemented + genlvlfit(opts, pars.dataset==4, pars); + } + + //-------------------------------- + // method of moment fit + //-------------------------------- + //TODO + if(acts.fitType == 3){ + isItDoingAnything_flag = true; + bool blind = true; + bool Fit2bins = false, Fit1bin = false, FitAllbins = false; //TODO: remove + momfit(opts, pars.nBins==0, pars.dataset==1, pars.dataset==0, blind, + Fit1bin, Fit2bins, FitAllbins); + } + + //-------------------------------- + // BEGIN angular resolution + //-------------------------------- + + if(acts.angRes){ + isItDoingAnything_flag = true; + get_angular_resolution(opts, get_years(opts.run, true, false)); + } + + //------------------------------- + // generate Toy events + //------------------------------- + + if (acts.genToys){ + isItDoingAnything_flag = true; + spdlog::debug("Generating and fitting toys"); + + bool onlySig = true; + bool onlyBkg = false; + if (pars.folding == 5){ //We do not need this here, we can run the code 5 times, no? + for (int f = 0; f < 5; f++){ + pars.folding = f; + opts.folding = f; + spdlog::debug("Generating and fitting a toy sample with folding={0:d}", pars.folding); + toysfit(opts, pars.nBins, pars.reference, pars, onlySig, onlyBkg); + } + } + else { + if (pars.testInt > -1)saveToys(pars, opts, pars.dataset>0, false); //if MC generate without bkg + else{ + if(pars.folding != -1)spdlog::debug("Generating and fitting a toy sample with folding={0:d}", pars.folding); + toysfit(opts, pars.nBins, pars.reference, pars, onlySig, onlyBkg); + } + } + } + + //------------------------------------------- + // Run whatever script you decide to run + //------------------------------------------- + //Yes, this is tedious, but I don't want to hardcode everything just so root is happy + //nor I wanna compile everything, so here we are + if(acts.script){ + isItDoingAnything_flag = true; + int status = runWhatever(pars, acts); //FILL IN RunningScripts.cc BY HAND + if(status)return status; + } + + + if (!isItDoingAnything_flag) spdlog::warn("Nothing to do! Exitting."); + else spdlog::info("Done with everything. Exit."); + return 0; +} diff --git a/Code/FCNCFitter/cmake.sh b/Code/FCNCFitter/cmake.sh new file mode 100644 index 0000000..258b57a --- /dev/null +++ b/Code/FCNCFitter/cmake.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +##export CMTCONFIG=x86_64-slc6-gcc49-opt +. /cvmfs/lhcb.cern.ch/lib/lcg/releases/LCG_84/ROOT/6.06.02/x86_64-slc6-gcc49-opt/bin/thisroot.sh +. /cvmfs/lhcb.cern.ch/lib/lcg/releases/gcc/4.9.3/x86_64-slc6/setup.sh +export GSL_DIR=/cvmfs/lhcb.cern.ch/lib/lcg/releases/GSL/2.1-36ee5/x86_64-slc6-gcc49-opt + +if [ "$1" == '--clear' ] || [ "$1" == '-clear' ]; then + echo "Cleaning up all cmake files to start over freshly" + if [ -e 'CMakeFiles/' ]; then + rm -r CMakeFiles/ + fi + if [ -e 'CMakeCache.txt' ]; then + rm CMakeCache.txt + fi +fi + +#build make files +cmake . +#using 4 cores. why not? +make -j8 +#make + +#export CMTCONFIG=x86_64-slc6-gcc49-opt +#. /cvmfs/lhcb.cern.ch/lib/lcg/releases/LCG_84/ROOT/6.06.02/x86_64-slc6-gcc49-opt/bin/thisroot.sh +#. /cvmfs/lhcb.cern.ch/lib/lcg/releases/gcc/4.9.3/x86_64-slc6/setup.sh +#export GSL_DIR=/cvmfs/lhcb.cern.ch/lib/lcg/releases/GSL/2.1-36ee5/x86_64-slc6-gcc49-opt + +#export CMTCONFIG=x86_64-centos7-gcc9-opt +#. /cvmfs/lhcb.cern.ch/lib/lcg/releases/LCG_97/ROOT/v6.20.02/x86_64-centos7-gcc9-opt/bin/thisroot.sh +#. /cvmfs/lhcb.cern.ch/lib/lcg/releases/gcc/9.2.0/x86_64-centos7/setup.sh +#export GSL_DIR=/cvmfs/lhcb.cern.ch/lib/lcg/releases/GSL/2.6-ecdfc/x86_64-centos7-gcc9-opt diff --git a/Code/FCNCFitter/condor/output/checkConvergence.py b/Code/FCNCFitter/condor/output/checkConvergence.py new file mode 100644 index 0000000..744e90e --- /dev/null +++ b/Code/FCNCFitter/condor/output/checkConvergence.py @@ -0,0 +1,37 @@ +from os import walk #Used to list all files in directory + +debug = False + +jobID = str(input("Enter the jobID:")) +PATH = "/home/lhcb/kopecna/B2KstarMuMu/code/ewp-Bplus2Kstmumu-AngAna/FCNCfitter/condor/output/" + +PATH = PATH + jobID +"/" + +_, _, fileList = next(walk(PATH), (None, None, [])) +#Walk returns dirpath, dirnames, filenames, so we don't care about the first two + +if (debug): print(fileList) + +nFiles = len(fileList) +if (nFiles==0): + raise ValueError('No files found.') + +if (debug): print(nFiles) + +nFailedHesse = 0 +nFailedSquaredHesse = 0 + +for outFile in fileList: + with open(PATH+outFile) as f: + #Read leaves a cursor at the end of the file, reading twice then is not an option + #Let's be safe here and instead of saving f.read in memore, let's call seek to return the cursor to the beginning + if '[warning] Hesse returns 2: Full, forced pos def' in f.read(): nFailedHesse+=1 + f.seek(0) + if "[warning] Squared Hesse returns 2: Full, forced pos def" in f.read(): nFailedSquaredHesse+=1 + +if (debug): + print ("Failed hesse: ",nFailedHesse) + print ("Failed sqaured hesse: ",nFailedSquaredHesse) + +print ("Failed hesse: {0:.1f}% ".format(nFailedHesse/nFiles*100.0)) +print ("Failed sqaured hesse: {0:.1f} %".format(nFailedSquaredHesse/nFiles*100.0)) \ No newline at end of file diff --git a/Code/FCNCFitter/condor/output/cleanup.sh b/Code/FCNCFitter/condor/output/cleanup.sh new file mode 100755 index 0000000..0ce9097 --- /dev/null +++ b/Code/FCNCFitter/condor/output/cleanup.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +#Set the main dir (no capital letters as it is best practice not to mess up with system variables +main_dir=/home/lhcb/kopecna/B2KstarMuMu/code/ewp-Bplus2Kstmumu-AngAna/FCNCfitter/condor + +# Used to clean up the mess condor created by default +for CondorID in {500..650} +do + mkdir $main_dir/error/$CondorID + mkdir $main_dir/output/$CondorID + + #Delete empty error messages + find $main_dir/error/toys_$CondorID* -size 0 -exec rm {} \; + find $main_dir/Folding0/error/toys_$CondorID* -size 0 -exec rm {} \; + find $main_dir/Folding1/error/toys_$CondorID* -size 0 -exec rm {} \; + find $main_dir/Folding2/error/toys_$CondorID* -size 0 -exec rm {} \; + find $main_dir/Folding3/error/toys_$CondorID* -size 0 -exec rm {} \; + find $main_dir/Folding4/error/toys_$CondorID* -size 0 -exec rm {} \; + + #Move the error messages into a subfolder + mv "$main_dir/error/toys_$CondorID"* "$main_dir/error/$CondorID/" + mv "$main_dir/Folding0/error/toys_$CondorID"* "$main_dir/error/$CondorID/" + mv "$main_dir/Folding1/error/toys_$CondorID"* "$main_dir/error/$CondorID/" + mv "$main_dir/Folding2/error/toys_$CondorID"* "$main_dir/error/$CondorID/" + mv "$main_dir/Folding3/error/toys_$CondorID"* "$main_dir/error/$CondorID/" + mv "$main_dir/Folding4/error/toys_$CondorID"* "$main_dir/error/$CondorID/" + #rm "$MAIN_DIR/error/toys_$CondorID"* + + #Move the output file into a subfodler + mv "$main_dir/output/toys_$CondorID"* "$main_dir/output/$CondorID/" + mv "$main_dir/Folding0/output/toys_$CondorID"* "$main_dir/output/$CondorID/" + mv "$main_dir/Folding1/output/toys_$CondorID"* "$main_dir/output/$CondorID/" + mv "$main_dir/Folding2/output/toys_$CondorID"* "$main_dir/output/$CondorID/" + mv "$main_dir/Folding3/output/toys_$CondorID"* "$main_dir/output/$CondorID/" + mv "$main_dir/Folding4/output/toys_$CondorID"* "$main_dir/output/$CondorID/" + + #Move the log from the folding folder + + mv "$main_dir/Folding0/log/toys_$CondorID"* "$main_dir/log/" + mv "$main_dir/Folding1/log/toys_$CondorID"* "$main_dir/log/" + mv "$main_dir/Folding2/log/toys_$CondorID"* "$main_dir/log/" + mv "$main_dir/Folding3/log/toys_$CondorID"* "$main_dir/log/" + mv "$main_dir/Folding4/log/toys_$CondorID"* "$main_dir/log/" + + #Echo we are done :) + echo "Cleaned." +done + diff --git a/Code/FCNCFitter/condor/output/condor.sh b/Code/FCNCFitter/condor/output/condor.sh new file mode 100644 index 0000000..ea151f5 --- /dev/null +++ b/Code/FCNCFitter/condor/output/condor.sh @@ -0,0 +1,31 @@ +#!/bin/bash +ProcID="$1" +ClusterID="$2" +# More or less gneric PI LHCb HTCondor script, to run something within singularity +# +# Where we should work +working_dir=/home/lhcb/kopecna/B2KstarMuMu/code/ewp-Bplus2Kstmumu-AngAna/FCNCfitter/condor +# What start in singularity (current directory will be current in singularity as well) +to_run="/home/lhcb/kopecna/B2KstarMuMu/code/ewp-Bplus2Kstmumu-AngAna/FCNCfitter/condor/job.sh" + + +# Singularity image to use (can point to CERN CVMFS...) +# Can be constructer by yourself... like +# OS_IMAGE=/work/zhelezov/singularity/CentOS7.simg +# Taken from "generic" CERN, unfortunately without graphic libraries... +#OS_IMAGE=/cvmfs/unpacked.cern.ch/registry.hub.docker.com/library/centos\:centos7 +# That seems like work for the perpose at the moment... Not perfect, I know. +OS_IMAGE=/cvmfs/unpacked.cern.ch/registry.hub.docker.com/cmssw/cc7\:amd64 + +# We will work here. Local Condor has no "shared filesystem" (yet, unclear if it should/will), +# so jobs start in a dedicated local directory on working nodes. +cd $working_dir || exit 1 +# That defines where is singularity +export PATH=/work/software/singularity/latest/`/work/software/os_version`/bin:$PATH +# Just for info under which OS we are running +echo "Batch execution OS: `/work/software/os_version`" +#In case cvmfs is not available for whatever reason +while [ ! -e "$OS_IMAGE" ]; do echo "Waiting for image..." >&1; /bin/sleep 300; done +# That starts singularity with image and final script +exec singularity exec --bind /cvmfs,/auto,/auto/home:/home,/auto/work:/work $OS_IMAGE $to_run "$@" + diff --git a/Code/FCNCFitter/condor/output/job.sh b/Code/FCNCFitter/condor/output/job.sh new file mode 100755 index 0000000..12bc7d8 --- /dev/null +++ b/Code/FCNCFitter/condor/output/job.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +# LHCb group_login.sh destroy arguments... +ProcID="$1" +ClusterID="$2" + +# If something from there is required... +source /cvmfs/lhcb.cern.ch/group_login.sh + +# real job (since I work in my directory, I have to set path explicity) +from_dir=/home/lhcb/kopecna/B2KstarMuMu/code/ewp-Bplus2Kstmumu-AngAna/FCNCfitter + +#That can work, with a bit of luck... +# source $FROM_DIR/SetPaths.sh +# +# But there are more standard and so stable way to setup CVMFS environment. +# For "generic CERN" (not LHCb specific): +# The list of possible views: +# source /cvmfs/sft.cern.ch/lcg/views/setupViews.sh gives the list.. +# The list of binary tags for views: +# source /cvmfs/sft.cern.ch/lcg/views/setupViews.sh +# And so, for LCG_84 and x86_64-slc6-gcc49-opt +source /cvmfs/sft.cern.ch/lcg/views/setupViews.sh LCG_84 x86_64-slc6-gcc49-opt +echo "Job execution OS: `/work/software/os_version`" +echo "Args: '$ProcID' '$ClusterID'" + +#$from_dir/bu2kstarmumu -r 12 -d 0 -u 1 -q -w -e 13000 -j $ProcID -i $ClusterID -v 3 +#$from_dir/bu2kstarmumu -r 12 -d 0 -u 1 -q -w -e 52000 -j $ProcID -i $ClusterID -v 3 +$from_dir/bu2kstarmumu -r 12 -d 0 -u 1 -q -w -e 65000 -j $ProcID -i $ClusterID -v 3 +#$from_dir/bu2kstarmumu -r 12 -d 0 -u 5 -w -e 8710 -j $ProcID -i $ClusterID -v 3 +#$from_dir/bu2kstarmumu -r 12 -d 0 -u 5 -w -e 871 -j $ProcID -i $ClusterID -v 3 + diff --git a/Code/FCNCFitter/condor/output/runToysHD.sub b/Code/FCNCFitter/condor/output/runToysHD.sub new file mode 100644 index 0000000..864c4e0 --- /dev/null +++ b/Code/FCNCFitter/condor/output/runToysHD.sub @@ -0,0 +1,19 @@ +executable = condor.sh +arguments = $(ProcId) $(ClusterId) +should_transfer_files = YES +output = output/toys_$(ClusterId)_$(ProcId).txt +error = error/toys_$(ClusterId)_$(ProcId).err +log = log/toys_$(ClusterId).log +#getenv = True #Alexey says this should be commented out +#requirements = (OpSysAndVer =?= "CentOS7") +transfer_executable = True +##+JobFlavour = "microcentury" + +# The following flag disable special job interpretation when you submit from CentOS7 container ++FromVIRTC = "" + +# The following flag can be used to exclude old server (which don't support some recent LHCb software) +# +WantCPUCap = 2020 + + +queue 500 diff --git a/Code/FCNCFitter/config/phspweightq2.root b/Code/FCNCFitter/config/phspweightq2.root new file mode 100644 index 0000000..ac9c875 Binary files /dev/null and b/Code/FCNCFitter/config/phspweightq2.root differ diff --git a/Code/FCNCFitter/dummy b/Code/FCNCFitter/dummy new file mode 100644 index 0000000..e69de29 diff --git a/Code/FCNCFitter/makefolders.sh b/Code/FCNCFitter/makefolders.sh new file mode 100644 index 0000000..c60bcca --- /dev/null +++ b/Code/FCNCFitter/makefolders.sh @@ -0,0 +1,15 @@ +#!/bin/sh +declare -a folders=(fitResults fitResults/angReso fitResults/angular fitResults/bkgFit fitResults/GenLvlFit fitResults/MainFit fitResults/MassFit fitResults/MCfit fitResults/Scans fitResults/ToysFit LaTeXfiles plots plots/angReso plots/angular plots/bkgFit plots/GenLvlFit plots/MainFit plots/MassFit plots/MCfit plots/MCfit/Signal plots/Scans plots/Toys log Toys) + + +#generate all folders in the array if they are not existing: +for folder in "${folders[@]}"; do + if [ -d $folder ]; then + echo "Folder '$folder' is already existing" + else + echo "Creating new folder: '$folder'" + mkdir $folder + fi +done + + diff --git a/Code/FCNCFitter/moveToys.sh b/Code/FCNCFitter/moveToys.sh new file mode 100755 index 0000000..18aca05 --- /dev/null +++ b/Code/FCNCFitter/moveToys.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +#Read the jobID +JobID="$1" + +#Set the main dir (no capital letters as it is best practice not to mess up with system variables +main_dir=/home/lhcb/kopecna/B2KstarMuMu/code/ewp-Bplus2Kstmumu-AngAna/FCNCfitter/plots/Toys + +mkdir "$main_dir/$JobID" + +#Move the files into a folder +#list=("$main_dir/*_${JobID}_*") +#echo ${list[@]} +mv $main_dir/*_${JobID}_*.eps $main_dir/${JobID}/ +mv $main_dir/*_${JobID}_*.root $main_dir/${JobID}/ + + +#Remove the Run1 and Run2 only plots +rm $main_dir/$JobID/*_Run1_* +rm $main_dir/$JobID/*_Run2_* + +#Echo we are done :) +echo "Cleaned." + diff --git a/Code/FCNCFitter/push.py b/Code/FCNCFitter/push.py new file mode 100644 index 0000000..10b1f93 --- /dev/null +++ b/Code/FCNCFitter/push.py @@ -0,0 +1,99 @@ +# Renata Kopecna + + +######################################################### +# # +# Script for easier pushing to git # +# # +######################################################### + +#Bash would work but this is nicer for the user to read + + +import sys +import subprocess + +tmp = subprocess.Popen(["git","branch","--show-current"], cwd = "./", stdout=subprocess.PIPE) +targetBranch = tmp.communicate()[0].decode("utf-8").strip("\n") +#print (targetBranch) + +if (len(sys.argv)!= 3): + print("Use it only with two arguments! python git.py fileToBePushed commitMessage") + print("Using " + str(len(sys.argv)) + " arguments") + exit() + +toBePushed = sys.argv[1] +commitMessage = sys.argv[2] + +class_dict = { + "generator": "sources/Core/bu2kstarmumu_generator", + "loader": "sources/Core/bu2kstarmumu_loader", + "parameters": "sources/Core/bu2kstarmumu_parameters", + "pdf": "sources/Core/bu2kstarmumu_pdf", + "plotter": "sources/Core/bu2kstarmumu_plotter", + "event": "sources/Core/event", + "folder": "sources/Core/folder", + "fitter": "sources/Core/fitter", + "funcs": "sources/Core/funcs", + "integrals": "sources/Core/integrals", + "options": "sources/Core/options", + "toystudy": "sources/Core/toystudy", + "design": "sources/Helpers/design", + "helpers": "sources/Helpers/helpers", + "constants": "sources/Params/constants", + "parameters.hh": "sources/Params/parameters", + "parameterscan": "sources/Params/parameterscan", + "angularcorr": "sources/Run/angularcorr", + "backgroundfit": "sources/Run/backgroundfit", + "feldman_cousins": "sources/Run/feldman_cousins", + "genlvlfit": "sources/Run/genlvlfit", + "generatetoys": "sources/Run/generatetoys", + "likelihoodscan": "sources/Run/likelihoodscan", + "mcfit": "sources/Run/mcfit", + "mainfit": "sources/Run/mainfit", + "massfit": "sources/Run/massfit", + "momfit": "sources/Run/momfit", + "multifit": "sources/Run/multifit", + "pulls": "sources/Run/pulls", + "toysfit": "sources/Run/toysfit", + "parse": "sources/parse", + "help": "sources/help", + "paths": "sources/paths" +} + +scripts_dict = { + "PlotMCfit": "sources/Scripts/PlotMCfit", + "GenLvlvsMC": "sources/Scripts/GenLvlvsMC", + "EvaluateToys": "sources/Scripts/EvaluateToys", + "ReferencePlots": "sources/Scripts/ReferencePlots", + "ScriptHelpers": "sources/Scripts/ScriptHelpers", + "RunningScripts": "sources/Scripts/RunningScripts" +} + +others_dict ={ + "main": "bu2kstarmumu.cc", + "plotter.hh": "sources/Core/plotter.hh", + "values": "sources/Params/values.hh", +} + + +mainPath = "/home/lhcb/kopecna/B2KstarMuMu/code/ewp-Bplus2Kstmumu-AngAna/FCNCfitter/" +if (toBePushed in class_dict): + add_cc = subprocess.run(["git","add",class_dict.get(toBePushed)+".cc"], cwd = "./", check = False) #Output into console + add_hh = subprocess.run(["git","add",class_dict.get(toBePushed)+".hh"], cwd = "./", check = False) #Output into console +elif (toBePushed in others_dict): + add = subprocess.run(["git","add",others_dict.get(toBePushed)], cwd = "./", check = False) #Output into console +elif (toBePushed in scripts_dict): + add_cc = subprocess.run(["git","add",scripts_dict.get(toBePushed)+".cc"], cwd = "./", check = False) #Output into console + add_hh = subprocess.run(["git","add",scripts_dict.get(toBePushed)+".hh"], cwd = "./", check = False) #Output into console +else: + print("Wrong file name! Use any of the following:") + print (class_dict.keys()) + print (others_dict.keys()) + +add = subprocess.run(["git","commit","-m",commitMessage], cwd = "./", check = True) #Output into console +add = subprocess.run(["git","push","origin",targetBranch], cwd = "./", check = True) #Output into console + +print ("\nDone pushing.\n") + + diff --git a/Code/FCNCFitter/rerunBasic.sh b/Code/FCNCFitter/rerunBasic.sh new file mode 100644 index 0000000..8fbc262 --- /dev/null +++ b/Code/FCNCFitter/rerunBasic.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +#Use as ./rerunBasic.sh RUN + +E_NO_ARGS=65 +if [ $# -eq 1 ] # Must have one command-line argument (run number) +then + run=$1 + echo "Rerruning everything for Run $run" +else + echo "Please invoke this script with one command-line argument in the following format:" + echo "./rerunBasic.sh RUN" + exit $E_NO_ARGS +fi + +if [ $run = 12 ] +then + python run.py -convert -all -Run 1 + python run.py -dontCompile -convert -all -Run 2 + python run.py -dontCompile -MC -angCorr -Run 1 -scan + python run.py -dontCompile -MC -angCorr -Run 2 -scan + python run.py -dontCompile -MC -angCorr -Run 1 + python run.py -dontCompile -MC -angCorr -Run 2 + python run.py -dontCompile -MC -angRes -Run 1 + python run.py -dontCompile -MC -angRes -Run 2 + python run.py -dontCompile -MC -Run 12 -fit -Ref -nBins 1; + python run.py -dontCompile -MC -Run 12 -fit -nBins 5; + python run.py -dontCompile -Data -Run 12 -fit -Ref -nBins 1 -massDim; + python run.py -dontCompile -Data -Run 12 -fit -nBins 5 -massDim; + python run.py -dontCompile -Data -Run 12 -fit -Ref -nBins 1 -bkgOnly -upper; + python run.py -dontCompile -Data -Run 12 -fit -nBins 5 -onlyBkg -upper; + python run.py -dontCompile -Run 12 -v 2 -fit -Ref -nBins 1 -genMC -Ref + python run.py -dontCompile -Run 12 -v 2 -fit -nBins 5 -genMC +else + python run.py -convert -all -Run $run + python run.py -dontCompile -MC -angCorr -Run $run -scan + python run.py -dontCompile -MC -angCorr -Run $run + python run.py -dontCompile -MC -angRes -Run $run + python run.py -dontCompile -MC -Run $run -fit -Ref -nBins 1; + python run.py -dontCompile -MC -Run $run -fit -nBins 5; + python run.py -dontCompile -Data -Run $run -fit -Ref -nBins 1 -massDim; + python run.py -dontCompile -Data -Run $run -fit -nBins 5 -massDim; + python run.py -dontCompile -Data -Run $run -fit -Ref -nBins 1 -bkgOnly -upper; + python run.py -dontCompile -Data -Run $run -fit -nBins 5 -onlyBkg -upper; + python run.py -dontCompile -Run $run -v 2 -fit -Ref -nBins 1 -genMC -Ref + python run.py -dontCompile -Run $run -v 2 -fit -nBins 5 -genMC +fi + +echo "All done" + diff --git a/Code/FCNCFitter/run.py b/Code/FCNCFitter/run.py new file mode 100644 index 0000000..dd33fde --- /dev/null +++ b/Code/FCNCFitter/run.py @@ -0,0 +1,70 @@ +# Renata Kopecna + +######################################################### +# # +# Set of functions used for running FCNC fitter # +# # +######################################################### +import sys +import os +import subprocess +from runUtils import * +from runArgs import * + +allYearsDict ={ 2011:1, + 2012:1, + 2015:2, + 2016:2, + 2017:2, + 2018:2, + } + +if '__main__' == __name__: + print ("") + + #Add and parse arguments + parser = ShowArgumentsParser( + formatter_class=argparse.RawTextHelpFormatter, + prog=os.path.basename(sys.argv[0]), + description=("""Do the comparison for: + + For a full list of arguments, do: 'python {0} -h' + """).format(os.path.basename(sys.argv[0])) + ) + addAllArgs(parser) + opts = parser.parse_args() + dir(opts) + + #check dir is the FCNC dir + print ("Starting program in directory: ") + os.system('pwd') + print ("\n") + + #Open output file; if none specified, print into console + if (opts.log!=""): logFile = open(opts.log,'w') + else: logFile = open("dummy",'w') #easiest is to create a dummy and then not save anything in it + + + #if (opts.compile): + #Just compile always, because you're a dumb dumb + if (not opts.dontCompile): + waitForCommand("bash",["cmake.sh"], logFile) + print ("\n\nCompiled.") + + cmd = './bu2kstarmumu' + + arg_list = [] + arg_list.append('-v ' + str(opts.verbosity)) + if (opts.hilfe): + arg_list.append("-h") + waitForCommand(cmd,arg_list,logFile) + else: + argListList= fullArgListPerRun(opts) + for arguments in argListList: + print("Runinng ./bu2kstarmumu ", arguments, "\n") + waitForCommand(cmd,arguments,logFile) + + + print ("\n\nDone running FCNC.\n") + + diff --git a/Code/FCNCFitter/runArgs.py b/Code/FCNCFitter/runArgs.py new file mode 100644 index 0000000..8fcb511 --- /dev/null +++ b/Code/FCNCFitter/runArgs.py @@ -0,0 +1,348 @@ +# Renata Kopecna + + +######################################################### +# # +# Define Parser and add all options # +# # +######################################################### +import sys +import argparse + +RunList = [1,2,12] + +class ShowArgumentsParser(argparse.ArgumentParser): + def error(self, message): + sys.stderr.write('error: %s\n\n' %message) + parser.print_usage(sys.stderr) + sys.stderr.write('\n'+self.description) + sys.exit(2) + +def addAllArgs(parser): + #Basic options + parser.add_argument("-v", "--verbosity", + metavar = '', + default = 2, + type = int, + help="Set verbosity level. Default is INFO.\n"+ + "Available levels are:\n"+ + "0: Trace\n"+ + "1: Debug\n"+ + "2: Info\n"+ + "3: Warn\n"+ + "4: Error\n"+ + "5: Critical\n\n") + parser.add_argument("-log", "--log", + metavar = '', + default = "", + type = str, + help="Set log file. Default is no log, streaming right into console.\n\n") + parser.add_argument("-hilfe", "--hilfe", + action="store_true", + help="Print full help.\n\n") + #Compile + parser.add_argument("-compile", "--compile", + action="store_true", + help="Compile the code before runing.\n\n") + parser.add_argument("-dontCompile", "--dontCompile", + action="store_true", + help="Don't compile the code before runing.\n\n") + # #Set dataset + parser.add_argument('-Run', '--Run', + metavar='', + default = 1, + type = int, + help="Set the Run number. Default is Run 1.\n\n") + parser.add_argument('-allRun', '--allRun', + action="store_true", + default = False, + help="Run on Runs 1, 2 and 12.\n\n") + parser.add_argument('-year', '--year', #TODO + metavar='', + default = -1, + type = int, + help="Run only on one year.\n\n") #TODO + parser.add_argument("-PHSP", "--PHSP", + action="store_true", + default = False, + help="Run on PHSP\n\n") + parser.add_argument("-Data", "--Data", + action="store_true", + default = False, + help="Run on Data\n\n") + parser.add_argument("-Ref", "--Ref", + action="store_true", + default = False, + help="Run on reference channel Jpsi\n\n") + parser.add_argument("-MC", "--MC", + action="store_true", + default = False, + help="Run on signal MC\n\n") + parser.add_argument("-all", "--all", + action="store_true", + default = False, + help = "Run on data, signal MC, reference MC and PHSP\n\n" ) + parser.add_argument("-allMC", "--allMC", + action="store_true", + default = False, + help = "Run on signal MC, reference MC and PHSP\n\n" ) + parser.add_argument("-genMC", "--genMC", + action="store_true", + default = False, + help="Run on generator level MC\n\n") + parser.add_argument("-boost", "--boost", + action="store_true", + default = False, + help="Run on boosted sample, turn on also generator level MC option!\n\n") + #Set tasks + parser.add_argument("-convert", "--convert", + action="store_true", + help="Convert selection tuples to FCNC tuples.\n\n") + parser.add_argument("-angCorr", "--angCorr", + action="store_true", + help="Obtain angular acceptance correction coefficients from PHSP Monte Carlo events.\n\n") + parser.add_argument("-scan", "--scan", + action="store_true", + help="Scan whatever you are doing :)\n\n") + parser.add_argument("-fit", "--fit", + action="store_true", + help="Run the main fit\n\n") + parser.add_argument("-angRes", "--angRes", + action="store_true", + help="Get angular resolution from signal MC.\n\n") + parser.add_argument('-toys', '--toys', #TODO + action="store_true", + help="Generate toys. Add -evts to generate custom number of events.\n\n") + parser.add_argument('-script', '--script', + action="store_true", + help="Run whatever script you decided.\n\n") + parser.add_argument('-job', '--job', + metavar='', + default = -1, + type = int, + help="Set the job number\n\n") + #Set toy options + parser.add_argument('-evts', '--evts', + metavar='', + default = -1, + type = int, + help="Set number of used/generated events\n\n") + + #Set fit options + parser.add_argument('-onlyBkg', '--onlyBkg', + action="store_true", + help="Fit only angular background.\n\n") + parser.add_argument('-upper', '--upper', + action="store_true", + help="Fit only upper-mass side-band.\n\n") + parser.add_argument('-lower', '--lower', + action="store_true", + help="Fit only lower-mass side-band.\n\n") + parser.add_argument('-bin', '--bin', + metavar='', + default = -1, + type = int, + help="Which angular bin would you like to fit?\n\n") + parser.add_argument('-nBins', '--nBins', + metavar='', + default = -1, + type = int, + help="Set total number q2 bins.\n\n") + parser.add_argument("-MagDown", "--MagDown", + action="store_true", + default = False, + help="Run only on MagDown\n\n") + parser.add_argument("-MagUp", "--MagUp", + action="store_true", + default = False, + help="Run only on MagUp\n\n") + parser.add_argument('-trueMC', '--trueMC', + action="store_true", + help="Use MC true information.\n\n") + parser.add_argument('-likelyhood', '--likelyhood', + action="store_true", + help="Likelihood profile scans.\n\n") + parser.add_argument('-massDim', '--massDim', + action="store_true", + help="Fit mass dimension\n\n") + parser.add_argument('-MoM', '--MoM', + action="store_true", + help="Use Method of Moments instead of the fit.\n\n") + parser.add_argument('-observeP', '--observeP', + action="store_true", + help="use P(') angular observables in the fit instead of the S(')\n\n") + parser.add_argument('-folding', '--folding', + metavar='', + default = -1, + type = int, + help="Set the folding of angles.\n" + +"Five possibilities use range [0-4]\n" + +"\t0: phi' = phi + pi for phi < 0\n" + +"\t1: phi' = -phi for phi < 0\n" + +"\t phi' = pi - phi for ctl < 0\n" + +"\t ctl' = -ctl for ctl < 0\n" + +"\t2: phi' = -phi for phi < 0\n" + +"\t ctl' = -ctl for ctl < 0\n" + +"\t3: phi' = pi - phi for phi > pi/2\n" + +"\t phi' = -pi - phi for phi < -pi/2\n" + +"\t ctl' = -ctl for ctl < 0\n" + +"\t4: phi' = pi - phi for phi > pi/2\n" + +"\t phi' = -pi - phi for phi < -pi/2\n" + +"\t ctk' = -ctk for ctk < 0\n" + +"\t ctl' = -ctl for ctl < 0\n" + +"Default is -1, meaning no folding.\n\n") + parser.add_argument('-loopFolds', '--loopFolds', + action="store_true", + help="Evaluate all five foldings\n\n") + # #Other options + + #parser.add_argument('-FC', '--FC', #TODO + # action="store_true", + # help="Run Feldman-Cousins: par=/8 and q2bin=%%8") #TODO + + #parser.add_argument('-pullsMC', '--pullsMC', #TODO + # action="store_true", + # help="Create -pullsMC pulls using specified signal MC events.") #TODO + parser.add_argument('-index', '--index', #TODO + metavar='', + default = -1, + type = int, + help="Set index, used for various checks.") + + #Systematics + #parser.add_argument('-systematics', '--systematics', #TODO "-s " + # metavar='', + # default = -1, + # type = int, + # help="Run a systematic study number:\n" + # +"\t1\t:Bootstrapping of PHSP MC\n" + # +"\t2\t:Perform fit with non-symmetric acceptance in ctl\n" + # +"\t3\t:Increase Legendre poly order by 2 for PHSP MC\n" + # +"\t4\t:Randomly change PHSP MC reweighting wihtin it's uncertainties\n" + # +"\t5\t:Check non-homogeneous FS distributions in q2\n" + # +"\t6\t:Vary angles (ctk, ctl and phi) within the angular resoluation\n" + # +"\t7\t:Generate toy events with double-gaussian profile and fit with CB\n" + # +"\t8\t:Systematic study on angular background model, add 10%% contribution of higher order\n" + # +"\t9\t:Investigate systematic effects due to trigger selection\n" + # +"\t10\t:Reweight PHSP MC according to pion PT disagreement in DD\n" + # +"\t11\t:Background systematic for mimicing the B0 -> KS mu mu veto\n") + #Test parameter + parser.add_argument('-test', '--test', #TODO + metavar='', + default = -1, + type = int, + help="Test parameter. When !=-1, verbosity automatically on debug.\n\n") #TODO + +def getDatasetCommands(opts): + arg_list = [] + if (opts.all): return ["-d 0", "-d 1", "-d 2", "-d 3", "-d 4"] + if (opts.allMC): return ["-d 1", "-d 2", "-d 3", "-d 4"] + + if (opts.Data): arg_list.append("-d 0") + if (opts.genMC): + if (opts.PHSP): arg_list.append("-d 4") + else: arg_list.append("-d 5") + else: + if (opts.MC): + if (opts.Ref): arg_list.append("-d 2") + else: arg_list.append("-d 1") + if (opts.PHSP): arg_list.append("-d 3") + return arg_list + +def setDataOpts(opts,arg): + if (arg == "-d 0"): + opts.Data = True + opts.MC = False + opts.PHSP = False + + elif (arg == "-d 1"): + opts.Data = False + opts.MC = True + opts.Ref = False + opts.PHSP = False + + if (arg == "-d 2"): + opts.Data = False + opts.MC = True + opts.Ref = True + opts.PHSP = False + + if (arg == "-d 3"): + opts.Data = False + opts.MC = True + opts.PHSP = True + +def getActionCommands(opts): + arg_list = [] + if (opts.test!=-1): + arg_list.append("-z " + str(opts.test)) + opts.verbosity = 1 + if (opts.angRes): arg_list.append("-a") + if (opts.angCorr): + arg_list.append("-c") + if (opts.scan): arg_list.append("-i 1") + + if (opts.fit): + if (opts.onlyBkg): + arg_list.append("-f 0") + if (opts.upper): arg_list.append("-i 2") + if (opts.lower): arg_list.append("-i 1") + elif (opts.massDim): arg_list.append("-f 2") + elif (opts.MoM): arg_list.append("-f 3") + elif (opts.MC or opts.PHSP): + arg_list.append("-f 4") #TODO: I'm working on this one + if (opts.MagDown): arg_list.append("-i 2") + if (opts.MagUp): arg_list.append("-i 1") + elif (opts.genMC): arg_list.append("-f 5") + else : arg_list.append("-f 1") + + if (opts.toys): arg_list.append("-w") + if (opts.convert): arg_list.append("-k") + #if (opts.pullsMC): arg_list.append("-m") #or -t when form toys TODO + #if (opts.systematics != -1): arg_list.append("-s " + str(opts.systematics)) TODO + if (opts.script): arg_list.append("-x") + + if (opts.upper): arg_list.append("") #TODO + if (opts.lower): arg_list.append("") #TODO + if (opts.trueMC): arg_list.append("") #TODO + return arg_list + + +def getParameterCommands(opts): + arg_list = [] + if (opts.bin!=-1): arg_list.append("-b " + str(opts.bin)) + if (opts.evts!=-1): arg_list.append("-e " + str(opts.evts)) + if (opts.folding!=-1): arg_list.append("-g " + str(opts.folding)) + if (opts.loopFolds): arg_list.append("-g 5") + if (opts.likelyhood): arg_list.append("-l") + if (opts.observeP): arg_list.append("-p") + #if (opts.FC): arg_list.append("-o") TODO + if (opts.nBins!=-1): arg_list.append("-u " + str(opts.nBins)) + if (opts.Ref): arg_list.append("-q") + if (opts.index !=-1): arg_list.append("-i " + str(opts.index)) + if (opts.job!=-1): arg_list.append("-j " + str(opts.job)) + + return arg_list + +def fullArgListPerRun(opts): + runs = [] + if (opts.allRun): runs = RunList + else: runs = [opts.Run] + + + argListList = [] + for dataArg in getDatasetCommands(opts): + for r in runs: + arg_list = [] + arg_list.append('-v ' + str(opts.verbosity)) + setDataOpts(opts,dataArg) + if (opts.Run!=-1): arg_list.append("-r " + str(r)) + if (opts.year!=-1): arg_list.append('-y' + str(opts.year)) + if (len(arg_list)==0): print ("The script needs at least run or year! Crashing now") + arg_list.extend([dataArg]) + arg_list.extend(getActionCommands(opts)) + arg_list.extend(getParameterCommands(opts)) + argListList.append(arg_list) + + return argListList + diff --git a/Code/FCNCFitter/runUtils.py b/Code/FCNCFitter/runUtils.py new file mode 100644 index 0000000..ec725b5 --- /dev/null +++ b/Code/FCNCFitter/runUtils.py @@ -0,0 +1,29 @@ +# Renata Kopecna + +import subprocess + +def parse_jobID(opts): + job_list = [] + if (opts.Data): job_list.append(0) + if (opts.MC): job_list.append(1) + if (opts.RefMC): job_list.append(2) + if (opts.PHSP): job_list.append(3) + if (opts.genMC): + if (opts.boost): job_list.append(5) + else: job_list.append(4) + return job_list + + +def waitForCommand(cmd, args, logFile): #args is a list + if (type(cmd) is not str): + raise TypeError("waitForCommand needs (str,list,str). Got ("+str(type(args))+",list,str) instead.") + + if (type(args) is not list): + raise TypeError("waitForCommand needs (str,list,str). Got (str," +type(args)+",str) instead.") + + if (logFile.name=="dummy"): + p = subprocess.run([cmd]+args, cwd = "./", check = True) #Output into console + else: + p = subprocess.run([cmd]+args, stdout=logFile, cwd = "./", check = True) #Output into a logFile + + print ("Return:", p.returncode) diff --git a/Code/FCNCFitter/sources/Core/bu2kstarmumu_generator.cc b/Code/FCNCFitter/sources/Core/bu2kstarmumu_generator.cc new file mode 100644 index 0000000..0e6df40 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/bu2kstarmumu_generator.cc @@ -0,0 +1,572 @@ +//Renata Kopecna + +#include +#include +#include +#include + +#include +#include + +#include + +//using namespace std; +using namespace fcnc; + +//boost::mutex generator_mutex; +std::mutex generator_mutex; + +//Function that returns a parameter with given range +double genValueFromRange(double min, double max, TRandom3* rnd){ + return min+rnd->Rndm()*(max-min); +} +double genValueFromPar(fcnc::parameter *par, TRandom3* rnd){ + return genValueFromRange(par->get_min(),par->get_max(),rnd); +} + + +std::vector bu2kstarmumu_generator::generate(unsigned int nevents, bu2kstarmumu_parameters* parameters, bu2kstarmumu_pdf* probability){ + prob = probability; + params = parameters; + + //even if folding (non-full-angular) is chosen, use full_angular mode to create events! + assert(opts->full_angular == prob->opts->full_angular); + assert(opts->always_generate_full_angular == prob->opts->always_generate_full_angular); + //always_generate_full_angular is true everywhere anyway + + bool only_generate_full_angular = prob->opts->always_generate_full_angular && !prob->opts->full_angular; + spdlog::debug("only_generate_full_angular: " + boolToString(only_generate_full_angular)); + if(only_generate_full_angular){ + prob->opts->full_angular = true; + opts->full_angular = true; + prob->opts->update_angle_ranges(); + opts->update_angle_ranges(); + if(opts->use_angular_acc){ + prob->load_coeffs_eff_phsp_4d(); + spdlog::debug("Loaded full angular coefficients."); + } + } + + prob->init(params); + + //account for the bias in f_sig by rescaling the f_sig for production, using efficiency corrected normalization and non-corrected normalization of background and signal PDF + //TODO: ask David wth this comment means + if((opts->weighted_fit || (opts->use_weighted_bkg && opts->use_angular_acc))){ + //Get normalizations + double bkg_norm = prob->angular_bkg_norm(params, false); + double bkg_eff_norm = prob->angular_bkg_norm(params, true); + double sig_norm = prob->angular_sig_norm(params, false); + double sig_eff_norm = prob->angular_sig_norm(params, true); + double f_sig_scale = (bkg_norm / bkg_eff_norm) / (sig_norm / sig_eff_norm); + + spdlog::info("BKG_NORM={0:f}", bkg_norm); + spdlog::info("BKG_NORM_EFF={0:f}", bkg_eff_norm); + + //make sure the scale is not too large, because this might lead to unwanted effects + if(f_sig_scale > 2.0){ + spdlog::error("The rescaling of the f_sig in toy generation is larger than 2.0 (value is: {0:f}), which seems very odd. Check your parameters!",f_sig_scale); + assert(f_sig_scale < 2.0); + } + if(f_sig_scale < 0.5){ + spdlog::error("The rescaling of the f_sig in toy generation is smaller 0.5 (value is: {0:f}), which seems very odd. Check your parameters!",f_sig_scale); + assert(f_sig_scale > 0.5); + } + + //set effective f_sig: + if(params->f_sig() != 0.0 && params->f_sig() != 1.0){ + effective_f_sig = params->f_sig() * f_sig_scale / (1 + params->f_sig() * (f_sig_scale - 1)); + } + else{ + effective_f_sig = params->f_sig(); + } + + //test if resulting 'effective' f_sig is out of the range [0.0, 1.0] + if(effective_f_sig > 1.0 || effective_f_sig < 0.0){ + spdlog::error("Rescaled f_sig in generation is out of the allowed range (0-1). Use either pure background or pure signal toys or a more equal mixture of both!"); + assert(0); + } + spdlog::debug("[INFO]\t\tSignal fraction: f_sig={0:0.4f} and eff_f_sig={1:f}", params->f_sig(), effective_f_sig); + } + else{ + effective_f_sig = params->f_sig(); + } + + prob->update_cached_normalization(params); + spdlog::info("Generating Toy MC"); + //Create empty space for the events + std::vector< std::vector > generated_events; + for (unsigned int i = 0; i < opts->ncores; i++) { + generated_events.push_back(std::vector()); + generated_events.at(i).reserve(nevents/opts->ncores); + } + + spdlog::info("Generation started"); + //Divide in threads if possible + std::vector threads; + if (opts->ncores > 1 && nevents > 1000) { + for (unsigned int i = 0; i < opts->ncores; i++) { + //boost::thread* t = new boost::thread(boost::bind(&bu2kstarmumu_generator::generation_thread, this, i, nevents/opts->ncores, &generated_events.at(i))); + std::thread* t = new std::thread(std::bind(&bu2kstarmumu_generator::generation_thread, this, i, nevents/opts->ncores, &generated_events.at(i))); + threads.push_back(t); + } + for (unsigned int i = 0; i < opts->ncores; i++) threads[i]->join(); + } + else generation_thread(0, nevents, &generated_events.at(0)); + + //Copy the generated events into the final vector + std::vector< event > evtVec; + for (unsigned int i = 0; i < opts->ncores; i++){ + copy(generated_events.at(i).begin(), generated_events.at(i).end(), back_inserter(evtVec)); + } + if (opts->ncores > 1 && nevents > 1000) { + for (unsigned int i = 0; i < opts->ncores; i++) delete threads[i]; + } + + //generate last events on single thread if number of requested event is not multiple of nCPUcores + //and add it to the final vector + if(evtVec.size() < nevents){ + std::vector last_events; + generation_thread(0, nevents - evtVec.size(), &last_events); + evtVec.insert(evtVec.end(), last_events.begin(), last_events.end()); + } + + if(evtVec.size() != nevents){ + spdlog::critical("Number of requested events not reached: {0:d}/{1:d} ({2:f}%) ", + evtVec.size(), nevents, 100. * evtVec.size() / nevents); + assert(0); + } + + //TODO: ask David what is this supposed to be + //opts->use_angular_res = angular_res; + spdlog::info("Generation of {0:d} pseudo-events completed", nevents); + + //reset full_angular to false, if it is only needed for the generation of events + //Aka when fititng and folding and you need a generator before that, restore the + //folding back to being used + if(only_generate_full_angular){ + prob->opts->full_angular = false; + opts->full_angular = false; + prob->opts->update_angle_ranges(); + opts->update_angle_ranges(); + } + + return evtVec; +}; + +void bu2kstarmumu_generator::generation_thread(unsigned int thread_id, unsigned long nevents, std::vector* eventVec){ + //nevents is a number of actually generated events + + //TRandom3 has an internal state! + //we therefore need one TRandom3 per thread + TRandom3* rnd = new TRandom3(); + if (opts->always_static_seed){//always use the same static seed + rnd->SetSeed(71598+thread_id*12); //TODO + } + else if (opts->static_seed){//this needs to be rerun dependent otherwise every rerun you get the same data! + spdlog::info("Thread={0:d}\tJobID={1:d}\tSeed={2:d}", thread_id, opts->get_job_id(), opts->get_job_id()*opts->ncores+thread_id+12345); + rnd->SetSeed(opts->get_job_id()*opts->ncores+thread_id+12345); + } + else rnd->SetSeed(0);//this is correct, see documentation //WHY IS THERE NO LINK AND ONE HAS TO GOOGLE?! + + spdlog::debug("Generator OK"); + + double mkpi_min = opts->mkpi_min/1.0e+3; + double mkpi_max = opts->mkpi_max/1.0e+3; + double asphase = params->asphase(); + double a = params->a(); + double r = params->r(); + double gammakstar = params->gammakstar(); + double mkstar = params->mkstar(); + double gammakstarplus = params->gammakstarplus(); + double mkstarplus = params->mkstarplus(); + double gammaf800 = params->gammaf800(); + double mf800 = params->mf800(); + double f800mag = params->f800mag(); + double f800phase = params->f800phase(); + double q2 = params->eff_q2(); + + double R = params->R(); + + bool swave = opts->swave; + + //integrate over mkpi + const double mk = PDGMASS_KST_KAON/1.0e+3; + const double mpi = PDGMASS_KST_PION/1.0e+3; + const double mb = PDGMASS_B/1.0e+3; + const double from = opts->mkpi_full_range_norm ? (mk+mpi) : mkpi_min; + const double to = opts->mkpi_full_range_norm ? mb : mkpi_max; + double mkpi_swave_2_norm=1.0, mkpi_pwave_2_norm=1.0; + double int_mkpi_re_swavepwave=1.0, int_mkpi_im_swavepwave=1.0; + //TODO: check whether I can turn off the mkpi generation all together + if(opts->generate_mkpi){ + spdlog::debug("Generating m(Kpi)!"); + if(opts->simple_mkpi){ + mkpi_swave_2_norm = fcnc::int_mkpi_simple_kstarzero_amp_squared(from, to, q2, f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus); + mkpi_pwave_2_norm = fcnc::int_mkpi_simple_bw_kstar_amp_squared(from, to, q2, gammakstar, mkstar); + int_mkpi_re_swavepwave = fcnc::int_mkpi_simple_bw_kstar_amp_bar_kstarzero_amp(from, to, q2, gammakstar, mkstar, asphase, f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus).real(); + int_mkpi_im_swavepwave = fcnc::int_mkpi_simple_bw_kstar_amp_bar_kstarzero_amp(from, to, q2, gammakstar, mkstar, asphase, f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus).imag(); + } + else if(opts->isobar){ + mkpi_swave_2_norm = fcnc::int_mkpi_kstarzero_isobar_amp_squared(from, to, q2, f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus, R); + mkpi_pwave_2_norm = fcnc::int_mkpi_bw_kstar_amp_squared(from, to, q2, gammakstar, mkstar, R); + int_mkpi_re_swavepwave = fcnc::int_mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(from, to, q2, gammakstar, mkstar, asphase, f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus, R).real(); + int_mkpi_im_swavepwave = fcnc::int_mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(from, to, q2, gammakstar, mkstar, asphase, f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus, R).imag(); + } + else{ + mkpi_swave_2_norm = fcnc::int_mkpi_kstarzero_lass_amp_squared(from, to, q2, asphase, a, r, gammakstarplus, mkstarplus, R); + mkpi_pwave_2_norm = fcnc::int_mkpi_bw_kstar_amp_squared(from, to, q2, gammakstar, mkstar, R); + int_mkpi_re_swavepwave = fcnc::int_mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(from, to, q2, gammakstar, mkstar, asphase, a, r, gammakstarplus, mkstarplus, R).real(); + int_mkpi_im_swavepwave = fcnc::int_mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(from, to, q2, gammakstar, mkstar, asphase, a, r, gammakstarplus, mkstarplus, R).imag(); + } + } + else spdlog::debug("Skipping generation of m(Kpi)!"); + + //get all P- and S-wave angular observables + const double j1s = params->J1s(); + const double j1c = params->J1c(); + const double j2s = params->J2s(); + const double j2c = params->J2c(); + const double j3 = params->J3(); + const double j4 = params->J4(); + const double j5 = params->J5(); + const double j6s = params->J6s(); + const double j6c = params->J6c(); + const double j7 = params->J7(); + const double j8 = params->J8(); + const double j9 = params->J9(); + const double fs = params->FS(); + const double js1 = params->SS1(); + const double js2 = params->SS2(); + const double js3 = params->SS3(); + const double js4 = params->SS4(); + const double js5 = params->SS5(); + + unsigned int n_gen = 0; //Number of generated events + unsigned int n_neg = 0; //Number of events with negative angular probability + unsigned int n_rej = 0; //Number of rejected events in the generation + unsigned int n_exc = 0; //Number of accepted events + + //main event loop + for (unsigned int ev = 0; ev < nevents; ev++){ + event meas; + meas.cp_conjugate = rnd->Rndm() < 0.5;//no overall cp asymmetry, so 50/50 chance of a 1 and 0 + + //give a progress report + if (ev % 1000 == 0 || ev == nevents - 1){ + std::lock_guard lock(generator_mutex); + spdlog::debug("\rThread {0:d} generating event no. {1:d} \r", thread_id , ev + 1 ); + spdlog::default_logger_raw()->flush(); + } + + //determine if event is signal or background + bool is_signal = (rnd->Rndm() < effective_f_sig); + if(opts->generate_only_bkg) is_signal = false; + if(is_signal) meas.event_type = 0; + else meas.event_type = 1; + + //m_res_1 should be the ratio between the two CBs + //In case of 2-tailed CB, m_res_1 is always 1 + if(rnd->Rndm() < params->m_res_1()) meas.sigma_m = params->m_sigma_1(); + else meas.sigma_m = params->m_sigma_2(); + + //generate mass (hit and miss), no real need to speed this up for now + bool finished_mass = false; //Means done with generating the mass + while(!finished_mass){ + //get a random mass value + meas.m = genValueFromPar(¶ms->m_b, rnd); //get random number between the range of B mass parameter + //determine probability from signal PDF + if(is_signal){ + event mmax; + mmax.m = params->m_b(); + //The probability is calculated in bu2kstarmumu_pdf, and it takes into account twotailedCB if opts.twotailedcrystalball is true + if(rnd->Rndm() < prob->m_sig_prob(params, meas)/prob->m_sig_prob(params, mmax)){ + finished_mass = true; + } + } + //or determine background probability + else{ + event mmax; + if(opts->fit_lambda){ + if (params->m_lambda() < 0.0) mmax.m = params->m_b.get_min(); + else assert(params->m_lambda() < 0.0); + } + else{ + if (params->m_tau() > 0.0) mmax.m = params->m_b.get_min(); + else mmax.m = params->m_b.get_max(); + } + double m_probmax = prob->m_bkg_prob(params, mmax); + //systematic 11: remove a gaussian shaped hole in the upper mass sideband: + if(opts->systematic == 11){ //TODO + double gaussian_width = 30.; + double gaussian_mean = 5520.; + double gaussian_frac = 0.02; + double gaussian_hole = TMath::Exp(-(meas.m - gaussian_mean)*(meas.m - gaussian_mean)/(2.*gaussian_width*gaussian_width))/TMath::Sqrt(2.*TMath::Pi()*gaussian_width*gaussian_width); + double exp_norm = 1./params->m_lambda()*(exp(opts->m_max*params->m_lambda()) - exp(opts->m_min*params->m_lambda())); + gaussian_hole *= gaussian_frac * exp_norm; + + if (rnd->Rndm()*m_probmax < prob->m_bkg_prob(params, meas) - gaussian_hole) finished_mass = true; + } + else{ + if (rnd->Rndm()*m_probmax < prob->m_bkg_prob(params, meas)) finished_mass = true; + //If your random shot on the y-axis is smaller than the wanted distribution/comparison function, keep the event! + } + } + }//mass loop end + + //generate angles + if(is_signal){//generate signal + double max_gen = opts->generate_mkpi ? 10.0 : 2.0; + //This is the 'upper limit' or 'comparison funcition', pretty much the top of your generation. It always has to be bigger than dGamma/d(ctl)d(ctk)d(phi)!!! + + bool finished = false; + while (!finished){ + + n_gen++; + double result = 1.0; + + //get q2 value + meas.q2 = params->eff_q2(); + if (opts->weighted_fit){ //TODO eh? + assert(opts->q2_min > 0.0); + assert(opts->q2_max > opts->q2_min); + meas.q2 = genValueFromRange(opts->q2_min, opts->q2_max, rnd); + } + + //get angles + meas.costhetak = genValueFromRange(opts->ctk_min, opts->ctk_max, rnd); + meas.costhetal = genValueFromRange(opts->ctl_min, opts->ctl_max, rnd); + meas.phi = genValueFromRange(opts->phi_min, opts->phi_max, rnd); + + double f1=0.0, f2=0.0, f3=0.0, f4 =0.0, f5 =0.0, f6 =0.0, + f7=0.0, f8=0.0, f9=0.0, f10=0.0, f11=0.0, f12=0.0; + if(opts->full_angular){ + prob->fj(meas.costhetal, meas.costhetak, meas.phi, + f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12); + } + else{ + prob->folded_fj(meas.costhetal, meas.costhetak, meas.phi, + f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12); + } + + //calculate P-wave probability + result = f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9; + + if(opts->fit_asymmetries && meas.cp_conjugate){ + result = f1*j1s + f2*j1c + f3*j2s + f4*j2c - f5*j3 - f6*j4 + - f7*j5 - f8*j6s - f9*j6c - f10*j7 - f11*j8 - f12*j9; + } + + //generate m(Kpi) + double prob_mkpi_pwave=0.0, prob_mkpi_swave=0.0; + std::complex prob_mkpi_swavepwave={0.0, 0.0}; + if (opts->generate_mkpi){ //TODO: here it is! + assert(mkpi_min > 0.0); + assert(mkpi_max > mkpi_min); + meas.mkpi = genValueFromRange(mkpi_min, mkpi_max, rnd)*1.0e+3; + if(opts->simple_mkpi) prob_mkpi_pwave = fcnc::mkpi_simple_bw_kstar_amp_squared(meas.mkpi/1.0e+3, meas.q2, gammakstar, mkstar); + else if(opts->isobar) prob_mkpi_pwave = fcnc::mkpi_bw_kstar_amp_squared(meas.mkpi/1.0e+3, meas.q2, gammakstar, mkstar, R); + else prob_mkpi_pwave = fcnc::mkpi_bw_kstar_amp_squared(meas.mkpi/1.0e+3, meas.q2, gammakstar, mkstar, R); + result *= prob_mkpi_pwave/mkpi_pwave_2_norm; + } + else{ + meas.mkpi = PDGMASS_K_STAR_PLUS; + } + + //calculate S-wave probability + double result_swave = 0.0; + if(swave){ + //P-wave gets factor (1-FS) + result *= (1.0-fs); + double fs1=0.0, fs2=0.0, fs3=0.0, fs4=0.0, fs5=0.0, fs6=0.0; + if(opts->full_angular){ + prob->swave_fj(meas.costhetal, meas.costhetak, meas.phi, + fs1, fs2, fs3, fs4, fs5, fs6); + } + else{ + prob->folded_swave_fj(meas.costhetal, meas.costhetak, meas.phi, + fs1, fs2, fs3, fs4, fs5, fs6); + } + + result_swave = fs*fs1 + js1*fs2 + js2*fs3 + js3*fs4 + js4*fs5 + js5*fs6; + if(opts->generate_mkpi){ + if(opts->simple_mkpi){ + prob_mkpi_swave = fcnc::mkpi_simple_kstarzero_amp_squared(meas.mkpi/1.0e+3, meas.q2, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus); + prob_mkpi_swavepwave = fcnc::mkpi_simple_bw_kstar_amp_bar_kstarzero_amp(meas.mkpi/1.0e+3, meas.q2, + gammakstar, mkstar, asphase, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus); + } + else if(opts->isobar){ + prob_mkpi_swave = fcnc::mkpi_kstarzero_isobar_amp_squared(meas.mkpi/1.0e+3, meas.q2, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus, R); + prob_mkpi_swavepwave = fcnc::mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(meas.mkpi/1.0e+3, meas.q2, + gammakstar, mkstar, asphase, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus, R); + } + else{ + prob_mkpi_swave = fcnc::mkpi_kstarzero_lass_amp_squared(meas.mkpi/1.0e+3, meas.q2, asphase, a, r, gammakstarplus, mkstarplus, R); + prob_mkpi_swavepwave = fcnc::mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(meas.mkpi/1.0e+3, meas.q2, gammakstar, mkstar, asphase, a, r, gammakstarplus, mkstarplus, R); + } + result_swave = fs*fs1*prob_mkpi_swave/mkpi_swave_2_norm + + (js1*fs2 + js2*fs3 + js3*fs4)*prob_mkpi_swavepwave.real()/int_mkpi_re_swavepwave + + (js4*fs5 + js5*fs6)*prob_mkpi_swavepwave.imag()/int_mkpi_im_swavepwave; + } + //add S-wave probability to P-wave probability + result += result_swave; + } + + //safety check on nan or inf + if(std::isnan(result) || std::isinf(result)){ + spdlog::critical("The calculated probability is = {0:f}", result); + assert(!std::isnan(result)); + assert(!std::isinf(result)); + } + + //safety check to avoid negative probabilities at toy generation + if(result < 0.0){ + n_neg++; + continue; + } + + //determine angular acceptance + if (opts->use_angular_acc || opts->weighted_fit){ + result *=prob->get_ang_eff(opts, meas, false); + } + + if (result > max_gen){ + double eff = prob->get_ang_eff(opts, meas, false); + //Yes, the eff is calculated again, but it doesn't cost any time as it crashes here anyway + spdlog::error("Determined probability is too large: {0:e}. With efficiency: {1:f}", result, eff); + spdlog::error("swave={0:f}\tpwave={1:f}", result_swave, result/eff - result_swave); + spdlog::critical("If you are seing this, increase the max_gen!!!"); + assert(0); + } + else if (rnd->Rndm() < result/max_gen){ //If your random shot on the y-axis is smaller than the wanted distribution/comparison function, keep the event! + finished = true; + n_exc++; + } + else{ + n_rej++; + } + }; + } + else{//generate bkg + bool finished = false; + double max_gen = 25.;//This is the 'upper limit' or 'comparison funcition', pretty much the top of your generation. It always has to be bigger than dGamma/d(ctl)d(ctk)d(phi)!!! + + while(!finished){ + + //generate angles + meas.costhetak = genValueFromRange(opts->ctk_min, opts->ctk_max, rnd); + meas.costhetal = genValueFromRange(opts->ctl_min, opts->ctl_max, rnd); + meas.phi = genValueFromRange(opts->phi_min, opts->phi_max, rnd); + + //generate q2 + meas.q2 = params->eff_q2(); + if(opts->weighted_fit){ + assert(opts->q2_min > 0.0); + assert(opts->q2_max > opts->q2_min); + meas.q2 = genValueFromRange(opts->q2_min, opts->q2_max, rnd); + } + + double result = 1.0; + if(!opts->flat_bkg){ + //use this (3 * 1D)*eff generation instead of 4D(Omega, eff) generation from prob->angular_bkg_prob + std::vector ch_ctl = init_ch_ctl(params); + std::vector ch_ctk = init_ch_ctk(params); + std::vector ch_phi = init_ch_phi(params); + + std::vector poly_ctl(ch_ctl.size(), 0.0); + std::vector poly_ctk(ch_ctk.size(), 0.0); + std::vector poly_phi(ch_phi.size(), 0.0); + + std::vector temp_ctl(ch_ctl.size(), 0.0); + std::vector temp_ctk(ch_ctk.size(), 0.0); + std::vector temp_phi(ch_phi.size(), 0.0); + + chebyshev_to_poly(ch_ctl, temp_ctl); + chebyshev_to_poly(ch_ctk, temp_ctk); + chebyshev_to_poly(ch_phi, temp_phi); + + for (unsigned int i=0; ifnorm_bkg; + } + + //efficiency correction in generation: + + if((opts->use_angular_acc && opts->use_weighted_bkg) || opts->weighted_fit){//applies efficiency to bkg for weighted fit + result *= prob->get_ang_eff(opts, meas, false); + } + + if(result > max_gen){ + spdlog::error("The probability is too large: {0:f}", result); + spdlog::error("It has to be smaller than: {0:f}", max_gen); + spdlog::error("The normalization of the PDF is: {0:f}", prob->fnorm_bkg); + spdlog::critical("If you are seing this, increase the max_gen!!!"); + assert(0); + } + else if(max_gen*rnd->Rndm() < result) finished = true; + }//end angular background generation + + finished = false; + if(opts->generate_mkpi){ + double mkpi_min = opts->mkpi_min/1.0e+3; + double mkpi_max = opts->mkpi_max/1.0e+3; + std::vector ch_mkpi(5, 0.0); + ch_mkpi.at(0) = params->cbkgmkpi0(); + ch_mkpi.at(1) = params->cbkgmkpi1(); + ch_mkpi.at(2) = params->cbkgmkpi2(); + ch_mkpi.at(3) = params->cbkgmkpi3(); + ch_mkpi.at(4) = params->cbkgmkpi4(); + std::vector poly_mkpi(ch_mkpi.size(), 0.0); + chebyshev_to_poly(ch_mkpi, poly_mkpi); + std::vector poly_corr_mkpi(ch_mkpi.size(), 0.0); + correct_poly(poly_mkpi, poly_corr_mkpi, mkpi_min, mkpi_max); + + while(!finished){ + double mkpi = mkpi_min+rnd->Rndm()*(mkpi_max-mkpi_min); + double probbkg = 0.0; + if (opts->mkpi_threshold){ + probbkg = fcnc::threshold(mkpi, 0.633, params->nthreshold()); + } + else{ + for(unsigned int i=0; iRndm()*probmax < probbkg){ + meas.mkpi = mkpi*1.0e+3; + finished = true; + } + } + }//end m(Kpi) background generation + else{ + meas.mkpi = PDGMASS_K_STAR_PLUS; + } + } + + //save angles also in backup/full angular variables: + meas.costhetal_fa = meas.costhetal; + meas.costhetak_fa = meas.costhetak; + meas.phi_fa = meas.phi; + meas.year = opts->year; + + eventVec->push_back(meas); + + }//end for all n events that are to be constructed + spdlog::debug("Thread #{0:d}: Angular signal events: n_gen={1:d}\tn_neg={2:d}\tn_rej={3:d}\tn_exc={4:d}", thread_id, n_gen, n_neg, n_rej, n_exc); + delete rnd; +} diff --git a/Code/FCNCFitter/sources/Core/bu2kstarmumu_generator.hh b/Code/FCNCFitter/sources/Core/bu2kstarmumu_generator.hh new file mode 100644 index 0000000..623f5b3 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/bu2kstarmumu_generator.hh @@ -0,0 +1,55 @@ +/** + * @file bu2kstarmumu_generator.hh + * @author Christoph Langenbruch, Renata Kopecna + * @date 2009-03-18 + * + */ + +#ifndef BU2KSTARMUMU_GENERATOR_H +#define BU2KSTARMUMU_GENERATOR_H + +#include +#include //Forward declaration is complainign due to dynamic_cast +#include +#include + +namespace fcnc { + class parameters; + class options; + class pdf; + +///Class to generate toy data for the decay Bs -> JPsi Phi. +class bu2kstarmumu_generator: public generator { +public: + ///constructor + bu2kstarmumu_generator(options* o): + opts(o) { + effective_f_sig = 0.5; +}; + /** + * generate Bs -> Phi gamma toy monte carlo and return a vector of the generated events + * @param nevents number of events to generate + * @param parameters parameter values to use in generation + * @param probability pdf to use in the generation. Some helper routines are used from here + */ + std::vector generate(unsigned int nevents, bu2kstarmumu_parameters* parameters, bu2kstarmumu_pdf* probability); + std::vector generate(unsigned int nevents, parameters* params, pdf* probability) { + return generate(nevents, dynamic_cast(params), dynamic_cast(probability)); + }; +private: + ///pointer to the pdf + bu2kstarmumu_pdf* prob; + ///pointer to the parameters to use in the generation + bu2kstarmumu_parameters* params; + ///pointer to options + options* opts; + ///used internally for threaded generation of the events + void generation_thread(unsigned int thread_id, unsigned long nevents, std::vector* eventVec); + ///background and signal weight correction for f_sig + double effective_f_sig; +}; + +} + +#endif + diff --git a/Code/FCNCFitter/sources/Core/bu2kstarmumu_loader.cc b/Code/FCNCFitter/sources/Core/bu2kstarmumu_loader.cc new file mode 100755 index 0000000..48e2039 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/bu2kstarmumu_loader.cc @@ -0,0 +1,659 @@ +//Renata Kopecna + +#include + +#include +#include +#include + +#include + +#include +#include + + +using namespace fcnc; + +///calculate decay angles according to theory convention http://arxiv.org/abs/0805.2525 +void bu2kstarmumu_loader::theory_angles(const TLorentzVector& muplus, const TLorentzVector& muminus, const TLorentzVector& kaon, const TLorentzVector& pion, double& costhetal, double& costhetak, double& phi) +{ + //set up boost vectors + TLorentzVector b = muplus + muminus + kaon + pion; + TLorentzVector mumu = muplus + muminus; + TLorentzVector kpi = kaon + pion; + TVector3 mumuboost(-mumu.BoostVector()); + TVector3 kpiboost(-kpi.BoostVector()); + TVector3 bboost(-b.BoostVector()); + + //determine costhetal + TLorentzVector muminusd(muminus); + muminusd.Boost(mumuboost); + TLorentzVector bd(b); + bd.Boost(mumuboost); + costhetal = cos(muminusd.Vect().Angle(bd.Vect())); + + //determine costhetak + TLorentzVector kaondd(kaon); + kaondd.Boost(kpiboost); + TLorentzVector bdd(b); + bdd.Boost(kpiboost); + costhetak = cos(kaondd.Vect().Angle(bdd.Vect())); + + //determine phi + TLorentzVector kaonddd(kaon); + kaonddd.Boost(bboost); + TLorentzVector pionddd(pion); + pionddd.Boost(bboost); + TLorentzVector muminusddd(muminus); + muminusddd.Boost(bboost); + TLorentzVector muplusddd(muplus); + muplusddd.Boost(bboost); + TVector3 normalkpi = kaonddd.Vect().Cross(pionddd.Vect()); + TVector3 normalmumu = muminusddd.Vect().Cross(muplusddd.Vect()); + + phi = normalkpi.Angle(normalmumu); + TLorentzVector kpiddd(kpi); + kpiddd.Boost(bboost); + if (normalkpi.Cross(normalmumu).Dot(kpiddd.Vect()) < 0.0) phi = -phi; + +} + +///calculate decay angles according to lhcb convention http://arxiv.org/abs/1304.6325, bzero is true for B0 and false for B0bar +void bu2kstarmumu_loader::lhcb_angles(bool bplus, const TLorentzVector& muplus, const TLorentzVector& muminus, const TLorentzVector& kaon, const TLorentzVector& pion, double& costhetal, double& costhetak, double& phi){ + + //set up boost vectors + TLorentzVector b = muplus + muminus + kaon + pion; + TLorentzVector mumu = muplus + muminus; + TLorentzVector kpi = kaon + pion; + TVector3 mumuboost(-mumu.BoostVector()); + TVector3 kpiboost(-kpi.BoostVector()); + TVector3 bboost(-b.BoostVector()); + + //determine costhetal + TLorentzVector muminusd(muminus); + muminusd.Boost(mumuboost); + TLorentzVector muplusd(muplus); + muplusd.Boost(mumuboost); + TLorentzVector bd(b); + bd.Boost(mumuboost); + if (bplus) costhetal = cos(muplusd.Vect().Angle(-bd.Vect())); + else costhetal = cos(muminusd.Vect().Angle(-bd.Vect())); + + //determine costhetak + TLorentzVector kaondd(kaon); + kaondd.Boost(kpiboost); + TLorentzVector bdd(b); + bdd.Boost(kpiboost); + costhetak = cos(kaondd.Vect().Angle(-bdd.Vect())); + + //determine phi + TLorentzVector kaonddd(kaon); + kaonddd.Boost(bboost); + TLorentzVector pionddd(pion); + pionddd.Boost(bboost); + TLorentzVector muminusddd(muminus); + muminusddd.Boost(bboost); + TLorentzVector muplusddd(muplus); + muplusddd.Boost(bboost); + TVector3 normalkpi = kaonddd.Vect().Cross(pionddd.Vect()); + TVector3 normalmumu = muplusddd.Vect().Cross(muminusddd.Vect()); + + TLorentzVector kpiddd(kpi); + kpiddd.Boost(bboost); + + if (bplus) { + phi = normalkpi.Angle(normalmumu); + if ((normalmumu.Cross(normalkpi)).Dot(kpiddd.Vect()) < 0.0) + phi = -phi; + } + else + { + phi = normalkpi.Angle(-normalmumu); + if ((normalmumu.Cross(normalkpi)).Dot(kpiddd.Vect()) < 0.0) + phi = -phi; + } + + spdlog::trace("Calculated angles: \t ctl= {0:0.2f},\t ctk = {1:0.2f}, \t phi = {1:0.2f}", costhetal, costhetak ,phi); + return; +} + +//calculate angles (Heidelberg2018). Should be 100% identical to LHCb convention +//definition as in LHCb-ANA-2013-097 page 23 +void bu2kstarmumu_loader::hd_angles(bool bplus, const TLorentzVector& muplus, const TLorentzVector& muminus, const TLorentzVector& kaon, const TLorentzVector& pion, double& costhetal_lhs, double& costhetal_rhs, double& costhetak_lhs, double& costhetak_rhs, double& phi){ + + //4D and boost vector of B system + TLorentzVector B = (muplus + muminus + kaon + pion); + TVector3 boost_B = B.BoostVector(); + + //ctk + TLorentzVector kaon_in_B = kaon; + kaon_in_B.Boost(-boost_B); + TLorentzVector pion_in_B = pion; + pion_in_B.Boost(-boost_B); + TLorentzVector kstar_in_B = kaon_in_B + pion_in_B; + + TLorentzVector kaon_in_kstar = kaon_in_B; + kaon_in_kstar.Boost(-kstar_in_B.BoostVector()); + + costhetak_lhs = kaon_in_kstar.Vect().Unit().Dot(kstar_in_B.Vect().Unit()); + + TLorentzVector B_in_kstar = B; + B_in_kstar.Boost(-boost_B); + B_in_kstar.Boost(-kstar_in_B.BoostVector()); + + costhetak_rhs = kaon_in_kstar.Vect().Unit().Dot(-B_in_kstar.Vect().Unit()); + + + //ctl + TLorentzVector muplus_in_B = bplus ? muplus : muminus; + muplus_in_B.Boost(-boost_B); + TLorentzVector muminus_in_B = bplus ? muminus : muplus; + muminus_in_B.Boost(-boost_B); + TLorentzVector dimuon_in_B = muplus_in_B + muminus_in_B; + + TLorentzVector muon_in_dimuon = muplus_in_B; + muon_in_dimuon.Boost(-dimuon_in_B.BoostVector()); + + costhetal_lhs = muon_in_dimuon.Vect().Unit().Dot(dimuon_in_B.Vect().Unit()); + + TLorentzVector B_in_dimuon = B; + B_in_dimuon.Boost(-boost_B); + B_in_dimuon.Boost(-dimuon_in_B.BoostVector()); + + costhetal_rhs = muon_in_dimuon.Vect().Unit().Dot(-B_in_dimuon.Vect().Unit()); + + //phi + TVector3 normalkpi = (kaon_in_B.Vect().Unit().Cross(pion_in_B.Vect().Unit())).Unit(); + TVector3 normalmumu = (muplus_in_B.Vect().Unit().Cross(muminus_in_B.Vect().Unit())).Unit(); + phi = normalkpi.Angle(normalmumu); + if ((bplus ? 1. : -1.)*(normalmumu.Cross(normalkpi)).Dot(kstar_in_B.Vect().Unit()) < 0.0) + phi = -phi; +} + +///B+ case: no further cuts in the tuple. Read (up to) all events without restrictions +std::vector bu2kstarmumu_loader::read_full_tuple(int year, std::string filename, std::string treename, bool isMC, bool mctruth, bool genLevelMC, int nevents) { + + //Set a year for gen lvl MC by hand + if(genLevelMC) year = 2017; + + check_year(year); + + //open the root file + TFile* root_file = new TFile(filename.c_str(), "READ"); + assert(root_file->IsOpen()); + + //Read the tree + TTree* tree = static_cast(root_file->Get(treename.c_str())); + if (!tree){ + //Check if the tree exists, if not, return an empty vector + spdlog::warn("Could not get tree {0:s} from file {1:s}", treename, filename); + std::vector blank_vector; + return blank_vector; + //assert(0); + } + + std::vector events; + event meas; + + Double_t mbu = PDGMASS_B; + Double_t sigma_mbu = 0.0; //TODO: mbu possibly from the fit? + Double_t mkstar = PDGMASS_K_STAR; + + Double_t + muplus_px, muplus_py, muplus_pz, muplus_pe, + muminus_px, muminus_py, muminus_pz, muminus_pe, + muplus_px_TRUE, muplus_py_TRUE, muplus_pz_TRUE, muplus_pe_TRUE, + muminus_px_TRUE, muminus_py_TRUE, muminus_pz_TRUE, muminus_pe_TRUE, + kaon_px, kaon_py, kaon_pz, kaon_pe, + pion_px, pion_py, pion_pz, pion_pe, + kaon_pt, pion_pt, muplus_pt, muminus_pt, + Ks_pi_plus_px, Ks_pi_plus_py, Ks_pi_plus_pz, Ks_pi_plus_pt, Ks_pi_plus_pe, + Ks_pi_minus_px, Ks_pi_minus_py, Ks_pi_minus_pz, Ks_pi_minus_pt, Ks_pi_minus_pe, + gamma1_px, gamma1_py, gamma1_pz, gamma1_pt, gamma1_pe, + gamma2_px, gamma2_py, gamma2_pz, gamma2_pt, gamma2_pe, + totalweight, delta_weight; + + Double_t ctl_TT, ctk_TT, phi_TT; + + Int_t b_id = 521, muplus_id = -13, muminus_id = +13;//, kaon_id, pion_id; + Int_t DDLL; + + UInt_t runno = 0; + ULong64_t gpstime = 0; + Short_t polarity = 0; + + if(!genLevelMC){ + tree->SetBranchAddress(opts->DTF ? "B_plus_M_DTF" : "B_plus_MM",&mbu); + tree->SetBranchAddress(opts->DTF ? "B_plus_MERR_DTF" : "B_plus_MMERR",&sigma_mbu); + tree->SetBranchAddress(opts->DTF ? "K_star_plus_M_scaled" : "K_star_plus_MM", &mkstar); + + tree->SetBranchAddress("Polarity", &polarity); + tree->SetBranchAddress("runNumber", &runno); + + tree->SetBranchAddress("B_plus_ThetaL", &ctl_TT); + tree->SetBranchAddress("B_plus_ThetaK", &ctk_TT); + tree->SetBranchAddress("B_plus_Phi", &phi_TT); + } + + if (!mctruth && !genLevelMC){ + tree->SetBranchAddress("GpsTime", &gpstime); + + tree->SetBranchAddress((opts->DTF ? "mu_plus_PX_DTF" : "mu_plus_PX"), &muplus_px); + tree->SetBranchAddress((opts->DTF ? "mu_plus_PY_DTF" : "mu_plus_PY"), &muplus_py); + tree->SetBranchAddress((opts->DTF ? "mu_plus_PZ_DTF" : "mu_plus_PZ"), &muplus_pz); + tree->SetBranchAddress((opts->DTF ? "mu_plus_PE_DTF" : "mu_plus_PE"), &muplus_pe); + tree->SetBranchAddress((opts->DTF ? "mu_plus_PT_DTF" : "mu_plus_PT"), &muplus_pt); + + tree->SetBranchAddress((opts->DTF ? "mu_minus_PX_DTF" : "mu_minus_PX"), &muminus_px); + tree->SetBranchAddress((opts->DTF ? "mu_minus_PY_DTF" : "mu_minus_PY"), &muminus_py); + tree->SetBranchAddress((opts->DTF ? "mu_minus_PZ_DTF" : "mu_minus_PZ"), &muminus_pz); + tree->SetBranchAddress((opts->DTF ? "mu_minus_PE_DTF" : "mu_minus_PE"), &muminus_pe); + tree->SetBranchAddress((opts->DTF ? "mu_minus_PT_DTF" : "mu_minus_PT"), &muminus_pt); + + if(opts->KS){ //K_S^0 pi^+ channel + + if(opts->DTF){ + tree->SetBranchAddress("Ks_pi_plus_PX_DTF", &Ks_pi_plus_px); + tree->SetBranchAddress("Ks_pi_plus_PY_DTF", &Ks_pi_plus_py); + tree->SetBranchAddress("Ks_pi_plus_PZ_DTF", &Ks_pi_plus_pz); + tree->SetBranchAddress("Ks_pi_plus_PT_DTF", &Ks_pi_plus_pt); + tree->SetBranchAddress("Ks_pi_plus_PE_DTF", &Ks_pi_plus_pe); + + tree->SetBranchAddress("Ks_pi_minus_PX_DTF", &Ks_pi_minus_px); + tree->SetBranchAddress("Ks_pi_minus_PY_DTF", &Ks_pi_minus_py); + tree->SetBranchAddress("Ks_pi_minus_PZ_DTF", &Ks_pi_minus_pz); + tree->SetBranchAddress("Ks_pi_minus_PT_DTF", &Ks_pi_minus_pt); + tree->SetBranchAddress("Ks_pi_minus_PE_DTF", &Ks_pi_minus_pe); + } + else{ + tree->SetBranchAddress("K_short_PX", &kaon_px); + tree->SetBranchAddress("K_short_PY", &kaon_py); + tree->SetBranchAddress("K_short_PZ", &kaon_pz); + tree->SetBranchAddress("K_short_PE", &kaon_pe); + tree->SetBranchAddress("K_short_PT", &kaon_pt); + } + + tree->SetBranchAddress((opts->DTF ? "pi_plus_PX_DTF" : "pi_plus_PX"), &pion_px); + tree->SetBranchAddress((opts->DTF ? "pi_plus_PY_DTF" : "pi_plus_PY"), &pion_py); + tree->SetBranchAddress((opts->DTF ? "pi_plus_PZ_DTF" : "pi_plus_PZ"), &pion_pz); + tree->SetBranchAddress((opts->DTF ? "pi_plus_PE_DTF" : "pi_plus_PE"), &pion_pe); + tree->SetBranchAddress((opts->DTF ? "pi_plus_PT_DTF" : "pi_plus_PT"), &pion_pt); + + } + else{ //K^+pi^0 channel + tree->SetBranchAddress((opts->DTF ? "K_plus_PX_DTF" : "K_short_PX"), &kaon_px); + tree->SetBranchAddress((opts->DTF ? "K_plus_PY_DTF" : "K_short_PY"), &kaon_py); + tree->SetBranchAddress((opts->DTF ? "K_plus_PZ_DTF" : "K_short_PZ"), &kaon_pz); + tree->SetBranchAddress((opts->DTF ? "K_plus_PE_DTF" : "K_short_PE"), &kaon_pe); + tree->SetBranchAddress((opts->DTF ? "K_plus_PT_DTF" : "K_short_PT"), &kaon_pt); + + if(opts->DTF){ + tree->SetBranchAddress("gamma1_PX_DTF", &gamma1_px); + tree->SetBranchAddress("gamma1_PY_DTF", &gamma1_py); + tree->SetBranchAddress("gamma1_PZ_DTF", &gamma1_pz); + tree->SetBranchAddress("gamma1_PE_DTF", &gamma1_pe); + tree->SetBranchAddress("gamma1_PT_DTF", &gamma1_pt); + + tree->SetBranchAddress("gamma2_PX_DTF", &gamma2_px); + tree->SetBranchAddress("gamma2_PY_DTF", &gamma2_py); + tree->SetBranchAddress("gamma2_PZ_DTF", &gamma2_pz); + tree->SetBranchAddress("gamma2_PE_DTF", &gamma2_pe); + tree->SetBranchAddress("gamma2_PT_DTF", &gamma2_pt); + } + else{ + tree->SetBranchAddress("pi_zero_resolved_PX", &pion_px); + tree->SetBranchAddress("pi_zero_resolved_PY", &pion_py); + tree->SetBranchAddress("pi_zero_resolved_PZ", &pion_pz); + tree->SetBranchAddress("pi_zero_resolved_PE", &pion_pe); + tree->SetBranchAddress("pi_zero_resolved_PT", &pion_pt); + } + } + } + else if(genLevelMC){ + if(opts->KS){ + tree->SetBranchAddress("KS0_TRUEP_X", &kaon_px); + tree->SetBranchAddress("KS0_TRUEP_Y", &kaon_py); + tree->SetBranchAddress("KS0_TRUEP_Z", &kaon_pz); + tree->SetBranchAddress("KS0_TRUEP_E", &kaon_pe); + + tree->SetBranchAddress("piplus0_TRUEP_X", &pion_px); + tree->SetBranchAddress("piplus0_TRUEP_Y", &pion_py); + tree->SetBranchAddress("piplus0_TRUEP_Z", &pion_pz); + tree->SetBranchAddress("piplus0_TRUEP_E", &pion_pe); + + tree->SetBranchAddress("piplus_TRUEP_X", &Ks_pi_plus_px); + tree->SetBranchAddress("piplus_TRUEP_Y", &Ks_pi_plus_py); + tree->SetBranchAddress("piplus_TRUEP_Z", &Ks_pi_plus_pz); + tree->SetBranchAddress("piplus_TRUEP_E", &Ks_pi_plus_pe); + + tree->SetBranchAddress("piminus_TRUEP_X", &Ks_pi_minus_px); + tree->SetBranchAddress("piminus_TRUEP_Y", &Ks_pi_minus_py); + tree->SetBranchAddress("piminus_TRUEP_Z", &Ks_pi_minus_pz); + tree->SetBranchAddress("piminus_TRUEP_E", &Ks_pi_minus_pe); + + } + else{ + tree->SetBranchAddress("Kplus_TRUEP_X", &kaon_px); + tree->SetBranchAddress("Kplus_TRUEP_Y", &kaon_py); + tree->SetBranchAddress("Kplus_TRUEP_Z", &kaon_pz); + tree->SetBranchAddress("Kplus_TRUEP_E", &kaon_pe); + + tree->SetBranchAddress("pi0_TRUEP_X", &pion_px); + tree->SetBranchAddress("pi0_TRUEP_Y", &pion_py); + tree->SetBranchAddress("pi0_TRUEP_Z", &pion_pz); + tree->SetBranchAddress("pi0_TRUEP_E", &pion_pe); + + tree->SetBranchAddress("muplus_TRUEP_X", &muplus_px_TRUE); + tree->SetBranchAddress("muplus_TRUEP_Y", &muplus_py_TRUE); + tree->SetBranchAddress("muplus_TRUEP_Z", &muplus_pz_TRUE); + tree->SetBranchAddress("muplus_TRUEP_E", &muplus_pe_TRUE); + + tree->SetBranchAddress("muminus_TRUEP_X", &muminus_px_TRUE); + tree->SetBranchAddress("muminus_TRUEP_Y", &muminus_py_TRUE); + tree->SetBranchAddress("muminus_TRUEP_Z", &muminus_pz_TRUE); + tree->SetBranchAddress("muminus_TRUEP_E", &muminus_pe_TRUE); + } + } + else{ //use MC true information + if(opts->KS){ + tree->SetBranchAddress("K_short_TRUEP_X", &kaon_px); + tree->SetBranchAddress("K_short_TRUEP_Y", &kaon_py); + tree->SetBranchAddress("K_short_TRUEP_Z", &kaon_pz); + tree->SetBranchAddress("K_short_TRUEP_E", &kaon_pe); + + tree->SetBranchAddress("pi_plus_TRUEP_X", &pion_px); + tree->SetBranchAddress("pi_plus_TRUEP_Y", &pion_py); + tree->SetBranchAddress("pi_plus_TRUEP_Z", &pion_pz); + tree->SetBranchAddress("pi_plus_TRUEP_E", &pion_pe); + } + else{ + tree->SetBranchAddress("K_plus_TRUEP_X", &kaon_px); + tree->SetBranchAddress("K_plus_TRUEP_Y", &kaon_py); + tree->SetBranchAddress("K_plus_TRUEP_Z", &kaon_pz); + tree->SetBranchAddress("K_plus_TRUEP_E", &kaon_pe); + + tree->SetBranchAddress("pi_zero_resolved_TRUEP_X", &pion_px); + tree->SetBranchAddress("pi_zero_resolved_TRUEP_Y", &pion_py); + tree->SetBranchAddress("pi_zero_resolved_TRUEP_Z", &pion_pz); + tree->SetBranchAddress("pi_zero_resolved_TRUEP_E", &pion_pe); + } + } + + //For any MC, always link the TRUE muon as well: + if(isMC || mctruth){ + tree->SetBranchAddress("mu_plus_TRUEP_X", &muplus_px_TRUE); + tree->SetBranchAddress("mu_plus_TRUEP_Y", &muplus_py_TRUE); + tree->SetBranchAddress("mu_plus_TRUEP_Z", &muplus_pz_TRUE); + tree->SetBranchAddress("mu_plus_TRUEP_E", &muplus_pe_TRUE); + + tree->SetBranchAddress("mu_minus_TRUEP_X", &muminus_px_TRUE); + tree->SetBranchAddress("mu_minus_TRUEP_Y", &muminus_py_TRUE); + tree->SetBranchAddress("mu_minus_TRUEP_Z", &muminus_pz_TRUE); + tree->SetBranchAddress("mu_minus_TRUEP_E", &muminus_pe_TRUE); + } + + //particle IDs: + if(genLevelMC){ + tree->SetBranchAddress("Kst_892_plus_MC_MOTHER_ID", &b_id); + } + else{ + tree->SetBranchAddress("B_plus_ID", &b_id); + tree->SetBranchAddress("mu_minus_ID", &muminus_id); + tree->SetBranchAddress("mu_plus_ID", &muplus_id); + } + + //for K_S^0 channel, get DD or LL track information + if(opts->KS && !genLevelMC)tree->SetBranchAddress("KshortDecayInVeLo", &DDLL); + + //load either sWeights (data) or MC reweights (signal, reference and phase-space MC) + if(!genLevelMC){ + if(isMC){ + if (opts->KS){ + tree->SetBranchAddress("weight2D_nLongTracks", &totalweight); + tree->SetBranchAddress("delta_weight2D_nLongTracks", &delta_weight); + } + else{ + tree->SetBranchAddress("weight2D_nLongTracks_TM_rndGamma", &totalweight); + tree->SetBranchAddress("delta_weight2D_nLongTracks_TM_rndGamma", &delta_weight); + } + } + else tree->SetBranchAddress("N_Bplus_sw", &totalweight); + } + + //determine number of events to load: + unsigned int nentries = tree->GetEntries(); + if (nevents > 0){ + unsigned int n = TMath::Abs(nevents); + if(n < nentries)nentries = n; + } + spdlog::info("Reading {0:d} events from file {1:s}", nentries ,filename); + + bool DDtracks = strcmp(opts->DDLL.c_str(), "DD") == 0; + + std::vectorvCorruptedEvents; + vCorruptedEvents.clear(); + + + //loop over input tree: + for(unsigned int j=0; j < nentries; j++){ + tree->GetEntry(j); + if (j % (tree->GetEntries()/10) == 0) std::cout << "\r[" << round(double(j*100)/tree->GetEntries()) << "%]" << std::flush; + + //Is it a B+ or a B-? + bool b_plus = b_id > 0; + + //for genLevelMonteCarlo: define muonID accordingly to B_id: + if(genLevelMC){ + muminus_id = b_plus ? +13 : -13; + muplus_id = b_plus ? -13 : +13; + } + + //skip events in K_S^0 sample that have incorrect tracktype + if(opts->KS && !genLevelMC){ + if( DDtracks && DDLL)continue; + if(!DDtracks && !DDLL)continue; + } + + if(genLevelMC || mctruth){ //MC TRUE samples and GenLevel samples use the MC true information: + muminus_px = muminus_px_TRUE; + muminus_py = muminus_py_TRUE; + muminus_pz = muminus_pz_TRUE; + muminus_pe = muminus_pe_TRUE; + muplus_px = muplus_px_TRUE; + muplus_py = muplus_py_TRUE; + muplus_pz = muplus_pz_TRUE; + muplus_pe = muplus_pe_TRUE; + } + + //initialize 4D vectors for angel calculations + TLorentzVector muplus, muminus, kaon, pion, muplus_TRUE, muminus_TRUE; + + if(muminus_id == muplus_id){ + spdlog::critical("Cannot have mu+ and mu- to have the same ID: {0:d}", muplus_id); + spdlog::critical("Event ID = {0:d}"); + assert(0); + } + + if (muminus_id == +13){ + muminus = TLorentzVector(muminus_px, muminus_py, muminus_pz, muminus_pe); + muminus_TRUE = TLorentzVector(muminus_px_TRUE, muminus_py_TRUE, muminus_pz_TRUE, muminus_pe_TRUE); + } + else if(muminus_id == -13){ + muplus = TLorentzVector(muminus_px, muminus_py, muminus_pz, muminus_pe); + muplus_TRUE = TLorentzVector(muminus_px_TRUE, muminus_py_TRUE, muminus_pz_TRUE, muminus_pe_TRUE); + } + else{ + spdlog::critical("Found invalid muon ID in mu-: {0:d}", muminus_id); + assert(0); + } + if (muplus_id == -13){ + muplus = TLorentzVector(muplus_px, muplus_py, muplus_pz, muplus_pe); + muplus_TRUE = TLorentzVector(muplus_px_TRUE, muplus_py_TRUE, muplus_pz_TRUE, muplus_pe_TRUE); + } + else if(muplus_id == +13){ + muminus = TLorentzVector(muplus_px, muplus_py, muplus_pz, muplus_pe); + muminus_TRUE = TLorentzVector(muplus_px_TRUE, muplus_py_TRUE, muplus_pz_TRUE, muplus_pe_TRUE); + } + else{ + spdlog::critical("Found invalid muon ID in mu-: {0:d}", muplus_id); + assert(0); + } + + if(opts->DTF && !mctruth && !genLevelMC){ + //If no true information, re-reconstruct the pion+kaon pair + if(opts->KS){ + pion = TLorentzVector(pion_px, pion_py, pion_pz, pion_pe); + kaon = TLorentzVector(Ks_pi_plus_px, Ks_pi_plus_py, Ks_pi_plus_pz, Ks_pi_plus_pe) + + TLorentzVector(Ks_pi_minus_px, Ks_pi_minus_py, Ks_pi_minus_pz, Ks_pi_minus_pe); + } + else{ + pion = TLorentzVector(gamma1_px, gamma1_py, gamma1_pz, gamma1_pe) + + TLorentzVector(gamma2_px, gamma2_py, gamma2_pz, gamma2_pe); + kaon = TLorentzVector(kaon_px, kaon_py, kaon_pz, kaon_pe); + } + } + else{ //in case of true info, read kaon and pion directly + pion = TLorentzVector(pion_px, pion_py, pion_pz, pion_pe); + kaon = TLorentzVector(kaon_px, kaon_py, kaon_pz, kaon_pe); + } + + + //In case of genLvl MC recalculate B mass + if(genLevelMC) mbu = (kaon+pion+muplus+muminus).M(); + + //de-bugging + if (opts->KS){ + spdlog::trace("KS_piplus_PX: {0:f}", Ks_pi_plus_px ); + spdlog::trace("KS_piplus_PY: {0:f}", Ks_pi_plus_py ); + spdlog::trace("KS_piplus_PZ: {0:f}", Ks_pi_plus_pz ); + spdlog::trace("KS_piplus_PE: {0:f}", Ks_pi_plus_pe ); + spdlog::trace("KS_piminus_PX: {0:f}", Ks_pi_minus_px); + spdlog::trace("KS_piminus_PY: {0:f}", Ks_pi_minus_py); + spdlog::trace("KS_piminus_PZ: {0:f}", Ks_pi_minus_pz); + spdlog::trace("KS_piminus_PE: {0:f}", Ks_pi_minus_pe); + } + + //print vectors + if(spdlog::default_logger_raw()->level()==spdlog::level::trace){ + spdlog::debug(b_plus ? "[B+]" : "[B-]"); + muplus.Print(); + muminus.Print(); + pion.Print(); + kaon.Print(); + } + + //make sure that the TRUE_P's of muons in MC are not identical + if(isMC && opts->reject_identical_muon_TRUEID){ + if(muplus_TRUE.X() == muminus_TRUE.X() && + muplus_TRUE.Y() == muminus_TRUE.Y() && + muplus_TRUE.Z() == muminus_TRUE.Z() && + muplus_TRUE.T() == muminus_TRUE.T()){ + vCorruptedEvents.push_back(j); + continue; + } + } + + //make sure that mup != mun + if(muplus.X() == muminus.X() && + muplus.Y() == muminus.Y() && + muplus.Z() == muminus.Z() && + muplus.T() == muminus.T()){ + vCorruptedEvents.push_back(j); + continue; + } + + //get pseudo_q2 from opening angle of leptons: + Double_t pseudo_q2 = muplus.Angle(muminus.Vect()); + // Double_t pseudo_q2 = std::max(muminus.Pt(), muplus.Pt()); + + //calculate angles + Double_t ctl_theory, ctk_theory, phi_theory; + Double_t ctl_lhcb, ctk_lhcb, phi_lhcb; + Double_t ctl_converted, ctk_converted, phi_converted; + Double_t ctl_hd_lhs, ctk_hd_lhs, phi_hd; + Double_t ctl_hd_rhs, ctk_hd_rhs; + + theory_angles( muplus, muminus, kaon, pion, ctl_theory, ctk_theory, phi_theory); + lhcb_angles (b_plus, muplus, muminus, kaon, pion, ctl_lhcb, ctk_lhcb, phi_lhcb); + hd_angles (b_plus, muplus, muminus, kaon, pion, ctl_hd_lhs, ctl_hd_rhs, ctk_hd_rhs, ctk_hd_lhs, phi_hd); + + //check and convert theory convention to LHCb convention + ctl_converted = b_plus ? ctl_theory : -ctl_theory; + ctk_converted = -ctk_theory; + if (b_plus) phi_converted = phi_theory > 0 ? TMath::Pi() - phi_theory : -TMath::Pi() - phi_theory; + else phi_converted = phi_theory; + + //convert tupletoolP2VV angles to cos() + ctl_TT = cos(ctl_TT); + ctk_TT = cos(ctk_TT); + + spdlog::trace("Event #{0:d}", j); + spdlog::trace("B" + std::string(b_plus ? "+" : "-") + "\t\t: Theory \tLHCb \t\tConverted \tHD(lhs) \tHD(rhs)\tTupleToolP2VV"); + spdlog::trace("cos(theta_L)\t:{0:0.4f}\t {0:0.4f}\t\t{0:0.4f}\t\t{0:0.4f}\t\t{0:0.4f}\t\t{0:0.4f}\t\t", ctl_theory, ctl_lhcb, ctl_converted, ctl_hd_lhs, ctl_hd_rhs, ctl_TT); + spdlog::trace("cos(theta_k)\t:{0:0.4f}\t {0:0.4f}\t\t{0:0.4f}\t\t{0:0.4f}\t\t{0:0.4f}\t\t{0:0.4f}\t\t", ctk_theory, ctk_lhcb , ctk_converted, ctk_hd_lhs, ctk_hd_rhs, ctk_TT); + spdlog::trace("phit:{0:0.4f}\t {0:0.4f}\t\t{0:0.4f}\t\t{0:0.4f}\t\t{0:0.4f}\t\t{0:0.4f}\t\t\n", phi_theory, phi_lhcb, phi_converted, phi_hd, phi_TT); + + + //test all angles to be identical: + assert(fabs(ctl_lhcb - ctl_converted) < 1.0e-8); + assert(fabs(ctk_lhcb - ctk_converted) < 1.0e-8); + assert(fabs(phi_lhcb - phi_converted) < 1.0e-8); + + assert(fabs(ctl_lhcb - ctl_hd_lhs) < 1.0e-8); + assert(fabs(ctl_lhcb - ctl_hd_rhs) < 1.0e-8); + assert(fabs(ctk_lhcb - ctk_hd_lhs) < 1.0e-8); + assert(fabs(ctk_lhcb - ctk_hd_rhs) < 1.0e-8); + assert(fabs(phi_lhcb - phi_hd) < 1.0e-8); + + + meas.year = year; + meas.m = mbu; + meas.sigma_m = sigma_mbu; + meas.costhetal = ctl_lhcb; + meas.costhetak = ctk_lhcb; + meas.phi = phi_lhcb; + meas.costhetal_fa = ctl_lhcb; + meas.costhetak_fa = ctk_lhcb; + meas.phi_fa = phi_lhcb; + meas.q2 = (muplus+muminus).Mag2()/1.0e+6;//in gev2 + meas.p2 = (kaon+pion).Mag2()/1.0e+6;//in gev2 + meas.weight = totalweight; + meas.delta_weight = delta_weight; + meas.mkpi = mkstar; + meas.cp_conjugate = b_plus;//this is B+ + meas.max_mu_pt = TMath::Max(muplus.Pt(), muminus.Pt()); + meas.kaon_pt = kaon.Pt(); + meas.pseudo_q2 = pseudo_q2; + meas.magnet = polarity; + + + bool ApplyGenLevelTightCuts = false; + if(genLevelMC && ApplyGenLevelTightCuts){ + if(muplus.Theta() < 0.005 || muplus.Theta() > 0.4)continue; + if(muminus.Theta() < 0.005 || muminus.Theta() > 0.4)continue; + if(pion.Theta() < 0.005 || pion.Theta() > 0.4)continue; + + TLorentzVector piplus(Ks_pi_plus_px, Ks_pi_plus_py, Ks_pi_plus_pz, Ks_pi_plus_pe); + TLorentzVector piminus(Ks_pi_minus_px, Ks_pi_minus_py, Ks_pi_minus_pz, Ks_pi_minus_pe); + if(piplus.P() <= 1800)continue; + if(piminus.P() <= 1800)continue; + if(piplus.Theta() < 0.005 || piplus.Theta() > 0.4)continue; + if(piminus.Theta() < 0.005 || piminus.Theta() > 0.4)continue; + } + + events.push_back(meas); + + } + if(vCorruptedEvents.size() > 0){ + spdlog::warn("Found {0:d} corrupted events with idendical muons: ",vCorruptedEvents.size()); + for(UInt_t c = 0; c < vCorruptedEvents.size(); c++) spdlog::warn("Events at: {0:d}",vCorruptedEvents.at(c)); + } + + root_file->Close(); + delete root_file; + spdlog::info("DONE reading {0:d} events from file " + filename,events.size()); + return events; + +} + + diff --git a/Code/FCNCFitter/sources/Core/bu2kstarmumu_loader.hh b/Code/FCNCFitter/sources/Core/bu2kstarmumu_loader.hh new file mode 100755 index 0000000..a2ad917 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/bu2kstarmumu_loader.hh @@ -0,0 +1,44 @@ +/** + * @file bu2kstarmumu_loader.hh + * @author Christoph Langenbruch, Renata Kopecna + * @date 2009-03-18 + * + */ + +#ifndef BU2KSTARMUMU_LOADER_H +#define BU2KSTARMUMU_LOADER_H + +#include "TLorentzVector.h" + +namespace fcnc { + class options; + class event; + +///class that implements the ability to load the Bs -> JPsi Phi signal decay from Zoo-ntuple root files. +class bu2kstarmumu_loader { +public: + ///constructor + bu2kstarmumu_loader(options* o): + opts(o) {}; + ///Read events from decaytree tuple + std::vector read_decaytree_tuple(std::string filename, std::string treename, bool mctruth=false, int nevents=1000000, int syst_variation=-1); + std::vector read_full_tuple(int year, std::string filename, std::string treename, bool isMC = false, bool mctruth=false, bool genLevelMC = false, int nevents=1000000); + + void test_angles(std::string filename, std::string treename, bool mctruth=false, int nevents=1000000); + + ///calculate decay angles according to theory convention http://arxiv.org/abs/0805.2525 + void theory_angles(const TLorentzVector& muplus, const TLorentzVector& muminus, const TLorentzVector& kaon, const TLorentzVector& pion, double& costhetal, double& costhetak, double& phi); + + ///calculate decay angles according to lhcb convention http://arxiv.org/abs/1304.6325 + void lhcb_angles(bool bplus, const TLorentzVector& muplus, const TLorentzVector& muminus, const TLorentzVector& kaon, const TLorentzVector& pion, double& costhetal, double& costhetak, double& phi); + + void hd_angles(bool bplus, const TLorentzVector& muplus, const TLorentzVector& muminus, const TLorentzVector& kaon, const TLorentzVector& pion, double& costhetal_lhs, double& costhetal_rhs, double& costhetak_lhs, double& costhetak_rhs, double& phi); + +private: + ///pointer to options + options* opts; +}; + +} + +#endif diff --git a/Code/FCNCFitter/sources/Core/bu2kstarmumu_parameters.cc b/Code/FCNCFitter/sources/Core/bu2kstarmumu_parameters.cc new file mode 100755 index 0000000..b08e869 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/bu2kstarmumu_parameters.cc @@ -0,0 +1,953 @@ +//Renata Kopecna + +#include +#include +#include // std::istringstream + +#include +#include +#include +#include + +#include +#include +#include + +#include + +//fixConstr constructor +fixConstr::fixConstr(bool b_fix,bool b_constr){ + if (b_fix && b_constr){ //Check if both constrain and fix are set to true + //If yes, set constrain to false without modifying the input bools + spdlog::warn("Cannot both fix and constrain a parameter.\n The parameter is fixed, setting constrain to false."); + spdlog::warn("Check your options."); + fix = true; + constrain = false; + return; + } + fix = b_fix; + constrain = b_constr; + return; +} + +using namespace fcnc; + +void bu2kstarmumu_parameters::use_default_bkg(){ + //Set all backgrounds to be flat + cbkgctl0.init(1.0, -1.0, 1.0, 0.0); + cbkgctl1.init(0.0, -1.0, 1.0, 0.0); + cbkgctl2.init(0.0, -1.0, 1.0, 0.0); + cbkgctl3.init(0.0, -1.0, 1.0, 0.0); + cbkgctl4.init(0.0, -1.0, 1.0, 0.0); + + cbkgctk0.init(1.0, -1.0, 1.0, 0.0); + cbkgctk1.init(0.0, -1.0, 1.0, 0.0); + cbkgctk2.init(0.0, -1.0, 1.0, 0.0); + cbkgctk3.init(0.0, -1.0, 1.0, 0.0); + cbkgctk4.init(0.0, -1.0, 1.0, 0.0); + cbkgctk5.init(0.0, -1.0, 1.0, 0.0); + cbkgctk6.init(0.0, -1.0, 1.0, 0.0); + + cbkgphi0.init(1.0, -1.0, 1.0, 0.0); + cbkgphi1.init(0.0, -1.0, 1.0, 0.0); + cbkgphi2.init(0.0, -1.0, 1.0, 0.0); + cbkgphi3.init(0.0, -1.0, 1.0, 0.0); + cbkgphi4.init(0.0, -1.0, 1.0, 0.0); + + cbkgmkpi0.init(1.0, -1.0, 1.0, 0.0); + cbkgmkpi1.init(0.0, -1.0, 1.0, 0.0); + cbkgmkpi2.init(0.0, -1.0, 1.0, 0.0); + cbkgmkpi3.init(0.0, -1.0, 1.0, 0.0); + cbkgmkpi4.init(0.0, -1.0, 1.0, 0.0); + + cswavemkpi0.init(1.0, -1.0, 1.0, 0.0); + cswavemkpi1.init(0.0, -1.0, 1.0, 0.0); + cswavemkpi2.init(0.0, -1.0, 1.0, 0.0); + cswavemkpi3.init(0.0, -1.0, 1.0, 0.0); + cswavemkpi4.init(0.0, -1.0, 1.0, 0.0); + + cbkgp20.init(1.0, -1.0, 1.0, 0.0); + cbkgp21.init(0.0, -1.0, 1.0, 0.0); + cbkgp22.init(0.0, -1.0, 1.0, 0.0); + cbkgp23.init(0.0, -1.0, 1.0, 0.0); + cbkgp24.init(0.0, -1.0, 1.0, 0.0); +} + +void bu2kstarmumu_parameters::use_default_observables(){ + if (opts->fit_pprimes){ + Fl.init (0.7, 0.0, 2.0*PAR_ANG_RANGE, 0.0); + P1.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + P2.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + P3.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + P4.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + P5.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + P6.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + P8.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + } + else{ + Fl.init (0.7, 0.0, 2.0*PAR_ANG_RANGE, 0.0); + S1s.init(0.7, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + S3.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + S4.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + S5.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + Afb.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + S6s.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + S7.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + S8.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + S9.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + } + return; +} +//This function is used in the parameters constructor! +void bu2kstarmumu_parameters::use_default(){ + Fl.init (0.7, 0.0, 2.0*PAR_ANG_RANGE, 0.0); + S1s.init(0.7, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + S3.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + S4.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + S5.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + Afb.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + S6s.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + S7.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + S8.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + S9.init (0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + + P1.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + P2.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + P3.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + P4.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + P5.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + P6.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + P8.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + + //S-wave parameters + FS.init (0.0, 0.0, 2*PAR_ANG_RANGE, 0.0); + SS1.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + SS2.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + SS3.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + SS4.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + SS5.init(0.0, -PAR_ANG_RANGE, PAR_ANG_RANGE, 0.0); + + //signal fraction + f_sig.init(PAR_N_SIG/(PAR_N_SIG+PAR_N_BKG), 0.0, 1.0, 0.0); + n_sig.init(PAR_N_SIG, 0.0, 1.0e+6, 0.0); + n_bkg.init(PAR_N_BKG, 0.0, 1.0e+6, 0.0); + //mass parameters + m_b.init (PDGMASS_B, B_MASS_LOW, B_MASS_HIGH, 0.0); + m_res_1.init (DOUBLE_CB ? 1.0 : 0.5, 0.0, 1.0, 0.0); + m_sigma_1.init(PAR_SIGMA, PAR_SIGMA_LOW, PAR_SIGMA_HIGH, 0.0); + m_sigma_2.init(DOUBLE_CB ? 0.0 : PAR_SIGMA, PAR_SIGMA_LOW, PAR_SIGMA_HIGH, 0.0); + //crystal ball + m_scale.init(1.0, 0.0, 2.0, 0.0); + alpha_1.init(1.0, 0.1, 10.0, 0.0); + n_1.init (1.0, 0.1, 10.0, 0.0); + alpha_2.init(1.0, 0.1, 10.0, 0.0); + n_2.init (1.0, 0.1, 10.0, 0.0); + + fm_tau.init(FIX_FM ? 1.0 : 0.5, 0.0, 1.0, 0.0); + m_tau.init(PAR_TAU, PAR_TAU/PAR_TAU_SCALE, PAR_TAU*PAR_TAU_SCALE, 0.0); + m_tau_2.init(PAR_TAU, PAR_TAU/PAR_TAU_SCALE, PAR_TAU*PAR_TAU_SCALE, 0.0); + m_lambda.init(PAR_LAMBDA, PAR_LAMBDA/PAR_LAMBDA_SCALE, PAR_LAMBDA*PAR_LAMBDA_SCALE, 0.0); + m_lambda_2.init(PAR_LAMBDA, PAR_LAMBDA/PAR_LAMBDA_SCALE, PAR_LAMBDA*PAR_LAMBDA_SCALE, 0.0); + + //Welp, this will end up in Jpsi, but whatever :) + eff_q2.init(bin_center(Q2_MIN_RANGE,Q2_MAX_RANGE), Q2_MIN_RANGE, Q2_MAX_RANGE, 0.0); + + //TODO: figure out what these are + asphase.init(MY_PI, 0.0, 2.0*MY_PI, 0.0); + a.init(1.0, 0.0, 10.0, 0.0); + r.init(1.0, 0.0, 10.0, 0.0); + gammakstar.init(PAR_KSTAR_WIDTH/1.0e3, 0.01, PAR_KSTAR_WIDTH/0.5e3, 0.0); //With of K* + mkstar.init(PDGMASS_K_STAR_PLUS/1.0e3, (K_ONE_PLUS-PAR_KSTAR_WIDTH)/1.0e3, (K_ONE_PLUS+PAR_KSTAR_WIDTH)/1.0e3, 0.0); + //This is a K1 or K something + mkstarplus.init(K_ONE_PLUS/1.0e3, (K_ONE_PLUS-PAR_K1_WIDTH)/1.0e3, (K_ONE_PLUS+PAR_K1_WIDTH)/1.0e3, 0.0); + gammakstarplus.init(PAR_K1_WIDTH/1.0e3, 0.01, PAR_K1_WIDTH/0.5e3, 0.0); //Width of K1 + + + nthreshold.init(PAR_NTRESHOLD, 1.0, 10.0, 0.0); + R.init(1.6, 0.0, 10.0, 0.0); + + //Some other fancy resonances //TODO ask Eluned + mf800.init(0.682, 0.1, 1.0, 0.0); + gammaf800.init(0.547, 0.1, 1.0, 0.0); + f800mag.init(0.1, 0.0, 1.0, 0.0); + f800phase.init(0.5*MY_PI, -2.0*MY_PI, +2.0*MY_PI, 0.0); + + //Set all backgrounds to be flat + use_default_bkg(); +} + +void bu2kstarmumu_parameters::load_param_values(std::string filename){ + + std::ifstream file(filename.c_str());; + std::string line = ""; + if (file.is_open()){ + spdlog::info("Parameter values are being read from file "+filename+"."); + } + else{ + spdlog::error("Could not load values from file " + filename);; + assert(0); + } + + UInt_t p_index; + std::string p_name; + Float_t p_value; + Float_t p_error; + //loop over lines in file and read values and errors of all parameters + while(true){ //Jesus christ, another while(true). Shoot me, please. + getline(file, line); + spdlog::debug("Line: "+line);; + if(file.eof()) break; + std::istringstream istr(line); + istr >> p_index; + istr >> p_name; + istr >> p_value; + istr >> p_error; + + //sanity check to make sure the parameter index fits to the parameter name: + if(p_name != this->get_parameter(p_index)->get_name()){ + spdlog::critical("Trying to assign values of var=" + p_name + " to parameter=" + this->get_parameter(p_index)->get_name());; + assert(p_name == this->get_parameter(p_index)->get_name()); + } + + //assign value and error from file to parameters + this->get_parameter(p_index)->set_values_n_errors(p_value, p_error); + } + file.close(); +} + +void bu2kstarmumu_parameters::load_param(std::string filename, std::string parname){ + + std::ifstream file(filename.c_str());; + std::string line = ""; + if (!file.is_open()){ + spdlog::error("\tCould not open file " + filename); + assert(0); + } + + UInt_t p_index; + std::string p_name; + Float_t p_value; + Float_t p_error; + //loop over lines in file and read values and errors of all parameters + while(true){ //Dear kids, + getline(file, line); + spdlog::debug("Line: " + line); + if(file.eof()) break; //never ever write code like this. Even at gunpoint. Don't. + std::istringstream istr(line); + istr >> p_index; + istr >> p_name; + istr >> p_value; + istr >> p_error; + + //continue if param name is identical + if(p_name != parname) continue; + + spdlog::debug("Load parameter: " + p_name + "={0:f}", p_value); + + //sanity check to make sure the parameter index fits to the parameter name: + assert(p_name == this->get_parameter(p_index)->get_name()); + + //assign value and error from file to parameters + this->get_parameter(p_index)->set_values_n_errors(p_value, p_error); + } + file.close(); + return; +} + +double get_param_valueError_from_rootfile(std::string fileName, std::string name, int PDF, int bin, bool getError){ + //Retuns a value for given parametr from a given rootfile + + //Open file + spdlog::info("Opening " + fileName); + TFile* file = new TFile(fileName.c_str(), "READ"); + + if (!file->GetListOfKeys()->Contains(name.c_str())){ + spdlog::critical("Wrong tree name " + name + "! Abort."); + assert(0); + } + + //Get the tree and set the branches to active + TTree* tree = (TTree*)file->Get(name.c_str()); + tree->SetBranchStatus("*",1); //Activate all branches + + //The root file is saved in a way that first bins in first pdf is saved + //then the next pdf is saved, bin by bin + //Meaning if I want to load event from bin 2 and pdf 1 + //tree->GetEntry(2) + //If I want to load event from bin 2 and pdf 2, one needs to do + //tree->GetEntry(totBins+2) + //PDFs are named according to the Run! So if only Run 2 is fitted, the returned pdf is 2 + //This implementation is actually useful for checks + //Therefore, starting entry is equal to int bin + int entry_position = bin; + + //Read the q2 bins + int totBins = DEFAULT_TREE_INT; + int pdf_idx = DEFAULT_TREE_INT; + int bin_idx = DEFAULT_TREE_INT; + double value = DEFAULT_TREE_VAL; + double error = DEFAULT_TREE_ERR; + int migrad = DEFAULT_TREE_INT; + + tree->SetBranchAddress("totBins", &totBins); + tree->SetBranchAddress("pdf", &pdf_idx); + tree->SetBranchAddress("bin", &bin_idx); + tree->SetBranchAddress("value",&value); + tree->SetBranchAddress("migrad",&migrad); + tree->SetBranchAddress("error",&error); + + tree->GetEntry(entry_position); + + //Check whether we got the right bin position + if (bin_idx != bin){ + spdlog::critical("Something went very wrong for "+name); + spdlog::critical("The read pdf {0:d} from position {1:d} doesn't agree with the wanted bin {2:d}", pdf_idx, entry_position, bin); + assert(0); + } + while (pdf_idx != PDF){ + entry_position += totBins; + if (entry_position >= tree->GetEntries()){ + spdlog::critical("Required PDF {0:d} for " + name + " not found!",PDF); + assert(0); + } + tree->GetEntry(entry_position); + } + + + //Check if migrad makes sense + if (migrad != 0){ + spdlog::warn("Careful! You are reading a fit that had failed migrad for " + name + "!"); + printMigradStatus(migrad); + } + + + + file->Close(); + spdlog::debug("Loaded " + name + " value is {0:f}", value); + + return getError ? error : value; +} + +double get_param_value_from_rootfile(std::string fileName, std::string name, int PDF, int bin){ + return get_param_valueError_from_rootfile(fileName, name, PDF, bin, false); +} +double get_param_error_from_rootfile(std::string fileName, std::string name, int PDF, int bin){ + return get_param_valueError_from_rootfile(fileName, name, PDF, bin, true); +} + +int bu2kstarmumu_parameters::get_param_from_rootfile(std::string fileName, std::vector names, int PDF, int bin, fixConstr FC){ + + //Open file + spdlog::info("Opening " + fileName); + TFile* file = new TFile(fileName.c_str(), "READ"); + + for (auto name: names){ + if (!file->GetListOfKeys()->Contains(name.c_str())){ + spdlog::critical("Wrong tree name " + name + "! Abort."); + assert(0); + } + + //Get the tree and set the branches to active + TTree* tree = (TTree*)file->Get(name.c_str()); + tree->SetBranchStatus("*",1); //Activate all branches + + //The root file is saved in a way that first bins in first pdf is saved + //then the next pdf is saved, bin by bin + //Meaning if I want to load event from bin 2 and pdf 1 + //tree->GetEntry(2) + //If I want to load event from bin 2 and pdf 2, one needs to do + //tree->GetEntry(totBins+2) + //PDFs are named according to the Run! So if only Run 2 is fitted, the returned pdf is 2 + //This implementation is actually useful for checks + //Therefore, starting entry is equal to int bin + int entry_position = bin; + + //Read the q2 bins + int totBins = DEFAULT_TREE_INT; + int pdf_idx = DEFAULT_TREE_INT; + int bin_idx = DEFAULT_TREE_INT; + tree->SetBranchAddress("totBins", &totBins); + tree->SetBranchAddress("pdf", &pdf_idx); + tree->SetBranchAddress("bin", &bin_idx); + + //Now get all the parameters + int migrad = DEFAULT_TREE_INT; + int param_index = DEFAULT_TREE_INT; + + double value = DEFAULT_TREE_VAL; + double error = DEFAULT_TREE_ERR; + double error_up = DEFAULT_TREE_ERR; + double error_down = DEFAULT_TREE_ERR; + double start_value = DEFAULT_TREE_VAL; + double prev_value = DEFAULT_TREE_VAL; + double prev_error = DEFAULT_TREE_ERR; + + tree->SetBranchAddress("value",&value); + tree->SetBranchAddress("error",&error); + tree->SetBranchAddress("error_up",&error_up); + tree->SetBranchAddress("error_down",&error_down); + + tree->SetBranchAddress("start_value",&start_value); //Not really used: TODO + tree->SetBranchAddress("prev_value",&prev_value); //Not really used: TODO + tree->SetBranchAddress("prev_error",&prev_error); //Not really used: TODO + + tree->SetBranchAddress("index",¶m_index); + tree->SetBranchAddress("migrad",&migrad); + + tree->GetEntry(entry_position); + + //Check whether the file contains correct numbers of bins + //If totBins are 1, let's assume this is fine and we are reading from ReferenceChannel + if (unsigned (totBins) != opts->TheQ2binsmin.size() && totBins != 1){ + spdlog::warn("Wrong number of bins for " + name + "!"); + spdlog::warn("totBins = {0:d}\tnQ2bins= {1:d}",totBins,opts->TheQ2binsmin.size()); + } + if (bin_idx != bin){ + spdlog::critical("Something went very wrong for "+name); + spdlog::critical("The read pdf {0:d} from position {1:d} doesn't agree with the wanted bin {2:d}", pdf_idx, entry_position, bin); + assert(0); + } + while (pdf_idx != PDF){ + entry_position += totBins; + if (entry_position >= tree->GetEntries()){ + spdlog::critical("Required PDF {0:d} for " + name + " not found!",PDF); + assert(0); + } + tree->GetEntry(entry_position); + } + + //Check if migrad makes sense + if (migrad != 0){ + spdlog::warn("Careful! You are reading a fit that had failed migrad for " + name + "!"); + printMigradStatus(migrad); + } + + //if opts->hesse is non-active, use error for both error_up and error_down + if(error_down == DEFAULT_TREE_ERR) error_down = error; + if(error_up == DEFAULT_TREE_ERR) error_up = error; + + //Init parameter + double stepsize = GetParamStepsize(name); //TODO check + if (FC.fix) stepsize = 0.0; + else if (stepsize < 0.001) stepsize = 0.01; //Protect zeroes //TODO: possibly add some protection against very very small numbers, but if it works as it is, no need to make it fancier + this->get_parameter(param_index)->set_previous_measurement(prev_value); + if (FC.constrain){ + if (error_down==0) error_down = 0.01; + if (error_up==0) error_up = 0.01; + } + std::vector param_range = GetParamRange(name); + this->get_parameter(param_index)->init(value, param_range.front(), param_range.back(), stepsize,error_down,error_up,FC.constrain); + } + + file->Close(); + + return 0; +} + +int bu2kstarmumu_parameters::fix_param_from_rootfile(std::string fileName,std::vector names, int PDF, int bin){ + return get_param_from_rootfile(fileName, names, PDF, bin, fixConstr(true,false)); +} + +int bu2kstarmumu_parameters::constrain_param_from_rootfile(std::string fileName,std::vector names, int PDF, int bin){ + return get_param_from_rootfile(fileName, names, PDF, bin, fixConstr(false,true)); +} + +int bu2kstarmumu_parameters::load_param_from_rootfile(std::string fileName,std::vector names, int PDF, int bin){ + return get_param_from_rootfile(fileName, names, PDF, bin, fixConstr(false, false)); +} + +//TODO: the following ones are not needed, as the string vector can be used instead.... +void bu2kstarmumu_parameters::load_only_bckgnd_param_values(std::string filename){ + this->load_param(filename, "cbkgmkpi0"); + this->load_param(filename, "cbkgmkpi1"); + this->load_param(filename, "cbkgmkpi2"); + this->load_param(filename, "cbkgmkpi3"); + this->load_param(filename, "cbkgmkpi4"); + this->load_param(filename, "cbkgctl0"); + this->load_param(filename, "cbkgctl1"); + this->load_param(filename, "cbkgctl2"); + this->load_param(filename, "cbkgctl3"); + this->load_param(filename, "cbkgctl4"); + this->load_param(filename, "cbkgctk0"); + this->load_param(filename, "cbkgctk1"); + this->load_param(filename, "cbkgctk2"); + this->load_param(filename, "cbkgctk3"); + this->load_param(filename, "cbkgctk4"); + this->load_param(filename, "cbkgctk5"); + this->load_param(filename, "cbkgctk6"); + this->load_param(filename, "cbkgphi0"); + this->load_param(filename, "cbkgphi1"); + this->load_param(filename, "cbkgphi2"); + this->load_param(filename, "cbkgphi3"); + this->load_param(filename, "cbkgphi4"); +} + +void bu2kstarmumu_parameters::load_only_Bmass_param_values(std::string filename){ + this->load_param(filename, "sigma_1"); + this->load_param(filename, "alpha_1"); + this->load_param(filename, "n_1"); + this->load_param(filename, "sigma_2"); + this->load_param(filename, "alpha_2"); + this->load_param(filename, "n_2"); +} + +void bu2kstarmumu_parameters::save_param_values(std::string filename){ + + std::ostringstream sout; + spdlog::info("Parameter values are being saved to file "+ filename);; + + //write all parameters to oss + for(UInt_t p = 0; p < this->nparameters(); p++){ + sout << std::endl; + sout << p; + sout << "\t" << this->get_parameter(p)->get_name(); + if (this->get_parameter(p)->get_error()==0) continue; //Print only not-fixed parameters + sout << "\t" << this->get_parameter(p)->get_value(); + sout << "\t" << this->get_parameter(p)->get_error(); + if (TMath::Abs(this->get_parameter(p)->get_error()/this->get_parameter(p)->get_value()) > 0.5){ + sout << "\tLARGE ERROR"; //c++s abs returned an int for whatever reason + spdlog::warn("Par " + this->get_parameter(p)->get_name() + " has a large error:\t {0:f} +- {1:f}", this->get_parameter(p)->get_value() ,this->get_parameter(p)->get_error() ); + } + else{ + spdlog::info("\tPar " + this->get_parameter(p)->get_name() + ":\t {0:f} +- {1:f}", this->get_parameter(p)->get_value() ,this->get_parameter(p)->get_error() ); + } + } + //save oss to file + std::ofstream file(filename.c_str()); + file << sout.str(); + file.close(); +} + +void bu2kstarmumu_parameters::add_parameters(){ + //physics parameters + add_parameter(&Fl); + add_parameter(&S1s); + add_parameter(&S3); + add_parameter(&S4); + add_parameter(&S5); + add_parameter(&Afb); + add_parameter(&S6s); + add_parameter(&S7); + add_parameter(&S8); + add_parameter(&S9); + add_parameter(&P1); + add_parameter(&P2); + add_parameter(&P3); + add_parameter(&P4); + add_parameter(&P5); + add_parameter(&P6); + add_parameter(&P8); + add_parameter(&FS); + add_parameter(&SS1); + add_parameter(&SS2); + add_parameter(&SS3); + add_parameter(&SS4); + add_parameter(&SS5); + + //had this at the start + //signal fraction + add_parameter(&f_sig); + add_parameter(&n_sig); + add_parameter(&n_bkg); + //mass parameters + add_parameter(&m_b); + add_parameter(&m_res_1); + add_parameter(&m_sigma_1); + add_parameter(&m_sigma_2); + add_parameter(&m_scale); + add_parameter(&alpha_1); + add_parameter(&alpha_2); + add_parameter(&n_1); + add_parameter(&n_2); + + add_parameter(&fm_tau); + add_parameter(&m_tau); + add_parameter(&m_tau_2); + add_parameter(&m_lambda); + add_parameter(&m_lambda_2); + add_parameter(&eff_q2); + + add_parameter(&asphase); + add_parameter(&a); + add_parameter(&r); + add_parameter(&gammakstar); + add_parameter(&mkstar); + add_parameter(&gammakstarplus); + add_parameter(&mkstarplus); + + add_parameter(&mf800); + add_parameter(&gammaf800); + add_parameter(&f800mag); + add_parameter(&f800phase); + + add_parameter(&cbkgctl0); + add_parameter(&cbkgctl1); + add_parameter(&cbkgctl2); + add_parameter(&cbkgctl3); + add_parameter(&cbkgctl4); + + add_parameter(&cbkgctk0); + add_parameter(&cbkgctk1); + add_parameter(&cbkgctk2); + add_parameter(&cbkgctk3); + add_parameter(&cbkgctk4); + add_parameter(&cbkgctk5); + add_parameter(&cbkgctk6); + + add_parameter(&cbkgphi0); + add_parameter(&cbkgphi1); + add_parameter(&cbkgphi2); + add_parameter(&cbkgphi3); + add_parameter(&cbkgphi4); + + add_parameter(&cbkgmkpi0); + add_parameter(&cbkgmkpi1); + add_parameter(&cbkgmkpi2); + add_parameter(&cbkgmkpi3); + add_parameter(&cbkgmkpi4); + + add_parameter(&cswavemkpi0); + add_parameter(&cswavemkpi1); + add_parameter(&cswavemkpi2); + add_parameter(&cswavemkpi3); + add_parameter(&cswavemkpi4); + + add_parameter(&cbkgp20); + add_parameter(&cbkgp21); + add_parameter(&cbkgp22); + add_parameter(&cbkgp23); + add_parameter(&cbkgp24); + + add_parameter(&nthreshold); + add_parameter(&R); +} + +void bu2kstarmumu_parameters::init_mass_parameters(int PDF, int nBins, int bin, double defaultStepSize){ + + //Initialize the mass fit parameters based on the bin, as pi0 screws everyhting up + std::vector> sMassPar = init_mass_params_MC(nBins,PDF); + //Not the most efficient to always get the full vector with all bins, but oh well + if(opts->twotailedcrystalball){ + m_res_1.init(1.0, 0.0, 1.0, 0.0); + m_sigma_1.init(sMassPar[0][bin],15.0, 50.0, defaultStepSize); + } + else{ + m_res_1.init(0.5, 0.0, 1.0, defaultStepSize); + m_sigma_1.init(sMassPar[0][bin],15.0, 40.0, defaultStepSize); + m_sigma_2.init(sMassPar[1][bin],15.0, 40.0, defaultStepSize); + } + + alpha_1.init(sMassPar[2][bin], 0.5, 3.0, defaultStepSize); + alpha_2.init(sMassPar[3][bin], 0.5, 3.0, defaultStepSize); + n_1.init(sMassPar[4][bin], 2.0, 10.0, defaultStepSize); + n_2.init(sMassPar[5][bin], 2.0, 10.0, defaultStepSize); + + return; +} + +void bu2kstarmumu_parameters::init_Bmass(std::string fileName, int PDF, double stepSize, fixConstr FC){ + double massInit = get_param_value_from_rootfile(fileName,"m_b", PDF, 0); + //fixing the Bmass outweights constraining it: + if (FC.fix) m_b.init(massInit,B_MASS_LOW,B_MASS_HIGH, 0.0); + else if (FC.constrain) m_b.init(massInit,B_MASS_LOW,B_MASS_HIGH, stepSize, 1.0, true); + else m_b.init(massInit,B_MASS_LOW,B_MASS_HIGH, stepSize); + return; +} + +void bu2kstarmumu_parameters::init_angular_background_parameters(bool fitReference, double stepsize){ + //Order of the polynomial is 0-6, each parameter represents x^n + //TODO: CHECK THE FOLDINGS + + //fitReference is not used, but in case this needs to be different for signal/reference! + //First set everything to be flat so one can only change the parameters that actually vary + use_default_bkg(); + + std::vector init_values = init_bkg(opts->folding, opts->bkg_order_costhetal,opts->bkg_order_costhetak); + for_indexed(auto name: PAR_BKG_STRING(opts->folding, opts->bkg_order_costhetal,opts->bkg_order_costhetak)){ + std::vector range = GetParamRange(name); + this->get_parameter(name)->init(init_values[i],range.front(), range.back(),stepsize); + spdlog::trace("Initialized " + this->get_parameter(name)->get_name()); + } + + return; +} + +void bu2kstarmumu_parameters::init_mass_background_parameters(int nBins, int bin, bool useLambda){ + std::vector f_lambda = init_f_lambda(nBins); + if(useLambda){ + m_lambda.init(f_lambda.at(bin), PAR_LAMBDA*PAR_LAMBDA_SCALE, PAR_LAMBDA/PAR_LAMBDA_SCALE, 1.0e-5); + //Turn on/off second exponential possibly + m_lambda_2.init(f_lambda.at(bin), PAR_LAMBDA*PAR_LAMBDA_SCALE, PAR_LAMBDA/PAR_LAMBDA_SCALE, FIX_FM ? 0.0 : 1.0e-5); + m_tau.init_fixed(0.0); + m_tau_2.init_fixed(0.0); + } + else{ + //Not really used, so if someone ever needs this, modify yourselves!!! + m_tau.init(-1.0/f_lambda.at(bin), 100, 100000, FIX_FM ? 0.0 : 10.0); + //Turn on/off second exponential possibly + m_tau_2.init(-1.0/f_lambda.at(bin), 100, 100000, FIX_FM ? 0.0 : 10.0); + m_lambda.init_fixed(0.0); + m_lambda_2.init_fixed(0.0); + } + return; +} + +void bu2kstarmumu_parameters::init_mkpi_pWave_parameters(bool fitReference, double stepsize){ + //fitReference is not used, but in case this needs to be different for signal/reference! + gammakstar.init(0.065, 0.055, 0.07, stepsize); + mkstar.init(PDGMASS_K_STAR_PLUS / 1000., 0.882, 0.902, 0.0); //PDG value + R.init(1.6, 0.0, 10.0, 0.00); + return; +} + +void bu2kstarmumu_parameters::init_mkpi_sWave_parameters(bool fitReference, double stepsize){ + //fitReference is not used, but in case this needs to be different for signal/reference! + gammakstarplus.init(0.236, 0.1, 0.5, stepsize); //PDG value is 0.236 + mkstarplus.init(1.41,1.2,1.6, 0.00); //PDG value is 1.41 + asphase.init(TMath::Pi(), 0.0, 2.0*TMath::Pi(), 0.0); + a.init(1.95, 0.0, 20.0, 0.0); + r.init(1.78, 0.0, 10.0, 0.0); + return; +} + +void bu2kstarmumu_parameters::init_kpi_background_parameters(bool fitReference, double stepsize){ + //fitReference is not used, but in case this needs to be different for signal/reference! + cbkgmkpi1.init(-0.99, -1.25, 0.25, stepsize); + //cbkgmkpi2.init(0.3, -1.0, 1.0, stepsize); + return; + +} + +void bu2kstarmumu_parameters::init_angular_parameters(int nBins, int bin, double stepsize, double scale, bool blind){ + //Scale sets the range + + //First, make sure everything is at the starting point + use_default_observables(); + + //Initialize angular parameters from constants + //s1s //s3 //s4 //s5 //s6s //s7 //s8 //s9 + std::vector> sParameters; + + if (opts->initSM){ + spdlog::debug("Loading angular parameters from flavio SM preditions"); + sParameters = init_angular_params(nBins,false,false); + } + else{ + spdlog::debug("Loading angular parameters from MC result file"); + sParameters = init_angular_params_MC(nBins); + } + + double blind_scale = 1.0; //Don't know what it does, but it is set to 1.0 everywhere + + if (!opts->fit_pprimes){ + + if(opts->fit_fl) Fl.init(1.0-4.0/3.0*sParameters.at(0).at(bin), 0.0, 2.0*scale, stepsize); + else S1s.init(sParameters.at(0).at(bin), -scale, scale, stepsize); + + S3.init(sParameters.at(1).at(bin), -scale, scale, stepsize); + S4.init(sParameters.at(2).at(bin), -scale, scale, (opts->full_angular || opts->folding == 1 ? stepsize : 0.0)); + S5.init(sParameters.at(3).at(bin), -scale, scale, (opts->full_angular || opts->folding == 2 ? stepsize : 0.0)); + + if(opts->fit_afb) Afb.init(3.0/4.0*sParameters.at(4).at(bin), -0.75*scale, 0.75*scale, (opts->full_angular || opts->folding == 0 ? stepsize : 0.0)); + else S6s.init(sParameters.at(4).at(bin), -scale, scale, (opts->full_angular || opts->folding == 0 ? stepsize : 0.0)); + + S7.init(sParameters.at(5).at(bin), -scale, scale, (opts->full_angular || opts->folding == 3 ? stepsize : 0.0)); + S8.init(sParameters.at(6).at(bin), -scale, scale, (opts->full_angular || opts->folding == 4 ? stepsize : 0.0)); + S9.init(sParameters.at(7).at(bin), -scale, scale, (opts->full_angular || opts->folding == 0 ? stepsize : 0.0)); + if(blind){ + Fl.set_blinding(true, blind_scale, true); + P1.set_blinding(true, blind_scale, true); + P2.set_blinding(true, blind_scale, true); + P3.set_blinding(true, blind_scale, true); + P4.set_blinding(true, blind_scale, true); + P5.set_blinding(true, blind_scale, true); + P6.set_blinding(true, blind_scale, true); + P8.set_blinding(true, blind_scale, true); + } + } + else{ + double fl = 1.0-4.0/3.0*sParameters.at(0).at(bin); + Fl.init(fl, 0.0, 2.0*scale, stepsize); + P1.init(2*sParameters.at(0).at(bin)/(1.-fl) , -scale, scale, stepsize); + P2.init(sParameters.at(4).at(bin)/2/(1.-fl) , -scale, scale, (opts->full_angular || opts->folding == 0 ? stepsize : 0.0)); + P3.init(-sParameters.at(1).at(bin)/(1.-fl) , -scale, scale, (opts->full_angular || opts->folding == 0 ? stepsize : 0.0)); + P4.init(sParameters.at(2).at(bin)/sqrt(fl*(1.-fl)), -scale, scale, (opts->full_angular || opts->folding == 1 ? stepsize : 0.0)); + P5.init(sParameters.at(3).at(bin)/sqrt(fl*(1.-fl)), -scale, scale, (opts->full_angular || opts->folding == 2 ? stepsize : 0.0)); + P6.init(sParameters.at(5).at(bin)/sqrt(fl*(1.-fl)), -scale, scale, (opts->full_angular || opts->folding == 3 ? stepsize : 0.0)); + P8.init(sParameters.at(6).at(bin)/sqrt(fl*(1.-fl)), -scale, scale, (opts->full_angular || opts->folding == 4 ? stepsize : 0.0)); + + if(blind){ + if(opts->fit_fl) Fl.set_blinding(true, blind_scale, true); + else S1s.set_blinding(true, blind_scale, true); + S3.set_blinding(true, blind_scale, true); + S4.set_blinding(true, blind_scale, true); + S5.set_blinding(true, blind_scale, true); + if(opts->fit_afb) Afb.set_blinding(true, blind_scale, true); + else S6s.set_blinding(true, blind_scale, true); + S7.set_blinding(true, blind_scale, true); + S8.set_blinding(true, blind_scale, true); + S9.set_blinding(true, blind_scale, true); + } + } + return; +} + +void bu2kstarmumu_parameters::init_ang_parameters_fromRefDavid(double stepsize, double scale, bool blind){ + + std::vector angPars = init_angular_params_RefFromDavid(); + //Not the most efficient to always get the full vector, but oh well + + if (opts->fit_pprimes){ + spdlog::critical("init_ang_parameters_fromRefDavid not implemented yet for Pprimes!"); + assert(0); + } + + if(opts->fit_fl) Fl.init(1.0-4.0/3.0*angPars.at(0), 0.0, 2.0*scale, stepsize); + else S1s.init(angPars.at(0), -scale, scale, stepsize); + + S3.init(angPars.at(1), -scale, scale, stepsize); + S4.init(angPars.at(2), -scale, scale, (opts->full_angular || opts->folding == 1 ? stepsize : 0.0)); + S5.init(angPars.at(3), -scale, scale, (opts->full_angular || opts->folding == 2 ? stepsize : 0.0)); + + if(opts->fit_afb) Afb.init(3.0/4.0*angPars.at(4), -0.75*scale, 0.75*scale, (opts->full_angular || opts->folding == 0 ? stepsize : 0.0)); + else S6s.init(angPars.at(4), -scale, scale, (opts->full_angular || opts->folding == 0 ? stepsize : 0.0)); + + S7.init(angPars.at(5), -scale, scale, (opts->full_angular || opts->folding == 3 ? stepsize : 0.0)); + S8.init(angPars.at(6), -scale, scale, (opts->full_angular || opts->folding == 4 ? stepsize : 0.0)); + S9.init(angPars.at(7), -scale, scale, (opts->full_angular || opts->folding == 0 ? stepsize : 0.0)); + + int blind_scale = 1.0; //No clue what this is good for, but it is 1.0 everywhere, so + if(blind){ + if(opts->fit_fl) Fl.set_blinding(true, blind_scale, true); + else S1s.set_blinding(true, blind_scale, true); + S3.set_blinding(true, blind_scale, true); + S4.set_blinding(true, blind_scale, true); + S5.set_blinding(true, blind_scale, true); + if(opts->fit_afb) Afb.set_blinding(true, blind_scale, true); + else S6s.set_blinding(true, blind_scale, true); + S7.set_blinding(true, blind_scale, true); + S8.set_blinding(true, blind_scale, true); + S9.set_blinding(true, blind_scale, true); + } + + return; +} + +void bu2kstarmumu_parameters::init_sWave_parameters(double stepsize){ + //TODO: very basic for now + double scale = 1.0; + SS1.init( -0.153, -scale, scale, opts->full_angular || opts->folding != 4 ? stepsize : 0.0); + SS2.init( 0.032, -scale, scale, opts->full_angular || opts->folding == 1 ? stepsize : 0.0); + SS3.init( -0.001, -scale, scale, opts->full_angular || opts->folding == 2 ? stepsize : 0.0); + SS4.init( 0.001, -scale, scale, opts->full_angular || opts->folding > 2 ? stepsize : 0.0); + SS5.init( -0.070, -scale, scale, opts->full_angular ? stepsize : 0.0); + return; +} + +bu2kstarmumu_parameters::bu2kstarmumu_parameters(options* o): + opts(o) +{ + use_default(); + add_parameters(); +} + + +double eventsInBin_fraction(int bin, int run, int nBins, bool fromRef){ + //From the requested total number of events, get the number of events in the given bin for given pdf + //Get the number of events from the dataFile and from the fraction of nSig/(nSig+nBkg) + + assert(bin >= 0 && bin < nBins); + assert(run == 1 || run == 2 || run == 12); + + TChain * chain = new TChain("Events"); + spdlog::trace("Run 1 data file ='" + get_theFCNCpath(0,1) + "'"); + chain->Add(get_theFCNCpath(0,1).c_str()); + spdlog::trace("Run 2 data file ='" + get_theFCNCpath(0,2) + "'"); + chain->Add(get_theFCNCpath(0,2).c_str()); + spdlog::debug("Chain entries: {0:d}", chain->GetEntries()); + + //cut on the q2 + std::vector q2BinsMin = get_TheQ2binsmin(nBins, fromRef); //No need to have specifically 1 for Ref + std::vector q2BinsMax = get_TheQ2binsmax(nBins, fromRef); //as if reference, always returns one bin + std::string whichYear = ""; + switch(run){ + case 1: whichYear = "(year<2013) &&"; break; + case 2: whichYear = "(year>2013) &&"; break; + case 12: whichYear = "(year<2020) &&"; break; + } + std::string cutOnQ2 = " "; + for (unsigned int b = 0; b < q2BinsMin.size(); b++){ + cutOnQ2.append( "(" + std::to_string(q2BinsMin[b]) + " < q2 && q2 < "+ std::to_string(q2BinsMax[b]) +") || "); + } + cutOnQ2.erase(cutOnQ2.length()-3); + spdlog::debug("Using cut: '" + cutOnQ2 + "'"); + int n_all = chain->GetEntries(cutOnQ2.c_str()); //number of events in the rare q2 region + if(n_all == -1) spdlog::debug("Getting number of all entries from TChain failed. Using hardcoded numbers."); + spdlog::debug("All entries: {0:d}", n_all); + + cutOnQ2 = whichYear + std::to_string(q2BinsMin[bin]) + " < q2 && q2 < "+ std::to_string(q2BinsMax[bin]); + spdlog::debug("Using cut: '" + cutOnQ2 + "'"); + int n_bin = chain->GetEntries(cutOnQ2.c_str()); //number of events in the desired q2 bin + if(n_bin == -1)spdlog::debug("Getting number of entries for bin {0:d} from TChain failed. Using hardcoded numbers.", bin); + spdlog::debug("Entries in bin: {0:d}", n_bin); + + //Running on Condor does not allow usage of TTreePlayer, which is needed for the GetEntries with selection cut + //In that case, -1 is returned. If so, use hardcoded fractions for the 4 or 5 q2 binning scheme. + if(n_all == -1 || n_bin == -1){ + spdlog::warn("Could not determine event fraction in bin={0:d} for run={1:d} from TChain. Use hardcoded numbers.", bin, run); + if(nBins == 4 || nBins == 5){ + std::vector > frac = fracs(nBins); + if(run == 12)return frac.at(0).at(bin)+frac.at(1).at(bin); + else return frac.at(run-1).at(bin); + } + spdlog::error("No hardcoded numbers available for {0:d} q2 bins.", nBins); + return 0.0; + } + double fraction = double(n_bin)/double(n_all); + spdlog::debug("Returning fraction of {0:f}", fraction); + chain->Clear(); + return fraction; +} + +void EventNumbers(unsigned int bin, unsigned int pdf, double & fraction, unsigned int & eventnumbers, + unsigned int TotalEvents, unsigned int bins, unsigned int pdfs){ + + bool use_unblinded_values = false;//TODO + + //return the fraction of nSig/(nSig+nBkg) *** in the requested q2bin *** + //return the number of events (nSig+nBkg) *** in this q2bin *** and in this sub-set given a total number of events (all sub-sets and all q2bins) + fraction = 0; + eventnumbers = 0; + + std::vector f_signal = init_n_signal(bins); + std::vector f_bckgnd = init_n_bckgnd(bins); + std::vector f_subset = get_f_subset(pdfs); + + assert(f_signal.size() == bins); + assert(f_bckgnd.size() == bins); + assert(f_subset.size() == pdfs); + + //assign signal fraction + fraction = f_signal.at(bin) / (f_signal.at(bin) + f_bckgnd.at(bin)); + + //get total event number in this bin and for this sub-set: + double f_sig_norm = sum_vector(f_signal) + sum_vector(f_bckgnd); + double f_event_norm = sum_vector(f_subset); + + for(auto sig: f_signal) sig /= f_sig_norm; + for(auto bkg: f_bckgnd) bkg /= f_sig_norm; + for(auto f_sub: f_subset) f_sub /= f_event_norm; + + eventnumbers = (unsigned int) (0.5 + TotalEvents * (f_signal.at(bin) + f_bckgnd.at(bin)) * f_subset.at(pdf)); + + if(use_unblinded_values){ //Number of signal and background events for each PDF //TODO: de-hardcode this one + fraction = sig_unblinded.at(bin).at(pdf) / (sig_unblinded.at(bin).at(pdf) + bkg_unblinded.at(bin).at(pdf)); + eventnumbers = (unsigned int) (0.5 + sig_unblinded.at(bin).at(pdf) + bkg_unblinded.at(bin).at(pdf)); + } + + return; +} + + + + diff --git a/Code/FCNCFitter/sources/Core/bu2kstarmumu_parameters.hh b/Code/FCNCFitter/sources/Core/bu2kstarmumu_parameters.hh new file mode 100755 index 0000000..9dcbabf --- /dev/null +++ b/Code/FCNCFitter/sources/Core/bu2kstarmumu_parameters.hh @@ -0,0 +1,282 @@ +/** + * @file bu2kstarmumu_parameters.hh + * @author Christoph Langenbruch, Renata Kopecna + * @date 2009-03-18 + * + */ + +#ifndef BU2KSTARMUMU_PARAMETERS_H +#define BU2KSTARMUMU_PARAMETERS_H + +#include +#include +#include + +//Simple struct to see whether fix or constrain a parameter +struct fixConstr{ + bool fix = false; + bool constrain = false; + //Constructor + fixConstr(bool b_fix, bool b_constr); +}; + +namespace fcnc { + +///class that implements the different parameter sets for Bd -> Kstar mu mu +class bu2kstarmumu_parameters: public parameters { +private: + ///adds all parameters to the params vector + void add_parameters(); + options* opts; + +public: + ///constructor uses toy challenge version 1 data as default + bu2kstarmumu_parameters(options* o); + + ///use default B+ values + /// //THIS IS SOMETHING EVERY ANALYSIS HAS TO CHANGE ON THEIR OWN! + void use_default_bkg(); //Just reset bkg, useful in the code down the line + void use_default_observables(); //Reset S-wave observables, useful in the code down the line + void use_default(); + + //simple and quick loading and saving of parameters to/from txt file + void load_param_values(std::string filename); + void load_param(std::string filename, std::string parname); + + int get_param_from_rootfile(std::string fileName, std::vector names, int PDF, int bin, fixConstr FC); + + //Fix parameter to a value from a root file + int fix_param_from_rootfile(std::string fileName, std::vector names, int PDF, int bin); + //Constrain parameter to a value from a root file + int constrain_param_from_rootfile(std::string fileName, std::vectornames, int PDF, int bin); + //Initialize parameter from a root file and let if float as it wishes + int load_param_from_rootfile(std::string fileName,std::vector names, int PDF, int bin); + + //TODO: remove as it is obsolete when done with pulls.cc + void load_only_bckgnd_param_values(std::string filename); + void load_only_Bmass_param_values(std::string filename); + + //Initialize parameters in the fit + void init_mass_parameters(int PDF, int nBins, int bin, double defaultStepSize); + void init_angular_background_parameters(bool fitReference, double stepsize); + void init_kpi_background_parameters(bool fitReference, double stepsize); + void init_mkpi_pWave_parameters(bool fitReference, double stepsize); + void init_mkpi_sWave_parameters(bool fitReference, double stepsize); + void init_mass_background_parameters(int nBins, int bin, bool useLambda); + void init_angular_parameters(int nBins, int bin, double stepsize, double scale, bool blind); + void init_Bmass(std::string fileName, int PDF, double stepSize, fixConstr FC); + void init_ang_parameters_fromRefDavid(double stepsize, double scale, bool blind); + void init_sWave_parameters(double stepsize); + + void save_param_values(std::string filename); + + //Effective q2 + parameter eff_q2 = parameter("eff_q2", "{q^{2}}_eff"); + + //Number of signal/background events + parameter n_sig = parameter("n_sig", "N_\\mathrm{sig}"); + parameter n_bkg = parameter("n_bkg", "N_\\mathrm{bkg}"); + + //Fraction of signal events, effectivelly (nsig/(nsig+nbkg))) + parameter f_sig = parameter("f_sig", "f_\\mathrm{sig}"); + + //The B massneeds the full range of the B-mass fit, + //as it decides the range of the data used in the fit + parameter m_b = parameter("m_b", "m_{B^{+}}"); + + //All mass parameters + parameter m_res_1 = parameter("m_res_1", "f_{CB}"); + parameter m_scale = parameter("m_scale", "s_\\mathrm{m}"); + parameter m_sigma_1 = parameter("m_sigma_1", "#sigma_{1}^{CB}"); + parameter m_sigma_2 = parameter("m_sigma_2", "#sigma_{2}^{CB}"); + parameter alpha_1 = parameter("alpha_1", "#alpha_{1}^{CB}"); + parameter alpha_2 = parameter("alpha_2", "#alpha_{2}^{CB}"); + parameter n_1 = parameter("n_1", "n_{1}^{CB}"); + parameter n_2 = parameter("n_2", "n_{2}^{CB}"); + + //These are for exponential background, either exp(-lambda*x) or exp(x/tau)  + parameter fm_tau = parameter("fm_tau", "f_{m,#tau}"); + parameter m_lambda = parameter("m_lambda", "\\lambda_\\mathrm{m}"); + parameter m_lambda_2 = parameter("m_lambda_2", "\\lambda_\\mathrm{m,2}"); + parameter m_tau = parameter("m_tau", "#tau_{m,1}"); + parameter m_tau_2 = parameter("m_tau_2", "#tau_{m,2}"); + + //Kstar related parameters / + + parameter mkstar = parameter("mkst","m(K^{*+})"); + parameter mkstarplus = parameter("mkstz","m(K^{*+}_{x})"); //K1+ resonances + parameter mkstp = parameter("mkstp", "m(K^+\\pi^0)"); //TODO + + parameter gammakstar = parameter("gammakstar", "\\Gamma(K^{*+})"); //Width of K* + parameter gammakstarplus = parameter("gamkstp", "\\Gamma(K^+\\pi^0)"); //Width of K1 + //parameter gamkstp = parameter("gamkstp", "\\Gamma(K^+\\pi^0)"); + + + //Afb and FL, S- and P- parameters are in S_pars(int) and P_pars(int) + parameter fl = parameter("Fl", "F_{L}"); + parameter afb = parameter("Afb", "A_{FB}"); + + //double exponential bkg + parameter Fl = parameter("Fl", "F_{L}"); + parameter S1s = parameter("S1s", "S_{1s}"); + parameter S3 = parameter("S3", "S_{3}"); + parameter S4 = parameter("S4", "S_{4}"); + parameter S5 = parameter("S5", "S_{5}"); + parameter Afb = parameter("Afb", "A_{FB}"); + parameter S6s = parameter("S6s", "S_{6s}"); + parameter S7 = parameter("S7", "S_{7}"); + parameter S8 = parameter("S8", "S_{8}"); + parameter S9 = parameter("S9", "S_{9}"); + + //less FF dependent variables P_i + parameter P1 = parameter("P1", "P_{1}");//=2*S3/(1-Fl) + parameter P2 = parameter("P2", "P_{2}");//=0.5*S6/(1-Fl) + parameter P3 = parameter("P3", "P_{3}");//=-S9/(1-Fl) + parameter P4 = parameter("P4", "P_{4}^{\\prime}");//=S4/sqrt(Fl Ft) + parameter P5 = parameter("P5", "P_{5}^{\\prime}");//=S5/sqrt(Fl Ft) + parameter P6 = parameter("P6", "P_{6}^{\\prime}");//=S7/sqrt(Fl Ft) + parameter P8 = parameter("P8", "P_{8}^{\\prime}");//=S8/sqrt(Fl Ft) + + //S-wave parameters + parameter FS = parameter("FS" ,"F_{S}"); + parameter SS1 = parameter("SS1","S_{S1}"); + parameter SS2 = parameter("SS2","S_{S2}"); + parameter SS3 = parameter("SS3","S_{S3}"); + parameter SS4 = parameter("SS4","S_{S4}"); + parameter SS5 = parameter("SS5","S_{S5}"); + + //More Kstar related parameters + parameter asphase = parameter("asphase", "arg(A_{S})"); + //Control the K* shape; one is ~p(K*) and one is ~1/p(K*), + parameter a = parameter("a", "a"); + parameter r = parameter("r", "r"); + + //Related to kappa(800), or f(800), it changed name apparently + //Essentially a wide resonance + parameter mf800 = parameter("mf800","m(f_{800})"); + parameter gammaf800 = parameter("gamf800","\\Gamma(f_{800})"); + parameter f800mag = parameter("f800mag","|f_{800}|"); + parameter f800phase = parameter("f800phase","arg(f_{800})"); + + //R (also refered to as d in the literature) + //is a parameter in the mkpi parameterisation. + //It refers to the effective hadronic size + //See L861f (page 66) of https://cds.cern.ch/record/2318554/files/LHCb-ANA-2018-022.pdf + parameter R = parameter("R", "R"); + //As a standard this is the radius of a B messon + + //Background parameters + //Polynomial of maximal order of four + //Each parameter correspons to x^n + //Eg cbkgctl1 and cbkgctl3 are non-zero, rest is zero means polynomial + // x^1 + x^3 + + //ctl + parameter cbkgctl0 = parameter("cbkgctl0", "c_{bkg}^{0}(cos#Theta_{L})"); + parameter cbkgctl1 = parameter("cbkgctl1", "c_{bkg}^{1}(cos#Theta_{L})"); + parameter cbkgctl2 = parameter("cbkgctl2", "c_{bkg}^{2}(cos#Theta_{L})"); + parameter cbkgctl3 = parameter("cbkgctl3", "c_{bkg}^{3}(cos#Theta_{L})"); + parameter cbkgctl4 = parameter("cbkgctl4", "c_{bkg}^{4}(cos#Theta_{L})"); + //ctk + parameter cbkgctk0 = parameter("cbkgctk0", "c_{bkg}^{0}(cos#Theta_{K})"); + parameter cbkgctk1 = parameter("cbkgctk1", "c_{bkg}^{1}(cos#Theta_{K})"); + parameter cbkgctk2 = parameter("cbkgctk2", "c_{bkg}^{2}(cos#Theta_{K})"); + parameter cbkgctk3 = parameter("cbkgctk3", "c_{bkg}^{3}(cos#Theta_{K})"); + parameter cbkgctk4 = parameter("cbkgctk4", "c_{bkg}^{4}(cos#Theta_{K})"); + parameter cbkgctk5 = parameter("cbkgctk5", "c_{bkg}^{5}(cos#Theta_{K})"); + parameter cbkgctk6 = parameter("cbkgctk6", "c_{bkg}^{6}(cos#Theta_{K})"); + //phi + parameter cbkgphi0 = parameter("cbkgphi0", "c_{bkg}^{0}(#phi)"); + parameter cbkgphi1 = parameter("cbkgphi1", "c_{bkg}^{0}(#phi)"); + parameter cbkgphi2 = parameter("cbkgphi2", "c_{bkg}^{0}(#phi)"); + parameter cbkgphi3 = parameter("cbkgphi3", "c_{bkg}^{0}(#phi)"); + parameter cbkgphi4 = parameter("cbkgphi4", "c_{bkg}^{0}(#phi)"); + + //mkpi + parameter cbkgmkpi0 = parameter("cbkgmkpi0", "c_{bkg}^{0}(m_{K#pi})"); + parameter cbkgmkpi1 = parameter("cbkgmkpi1", "c_{bkg}^{1}(m_{K#pi})"); + parameter cbkgmkpi2 = parameter("cbkgmkpi2", "c_{bkg}^{2}(m_{K#pi})"); + parameter cbkgmkpi3 = parameter("cbkgmkpi3", "c_{bkg}^{3}(m_{K#pi})"); + parameter cbkgmkpi4 = parameter("cbkgmkpi4", "c_{bkg}^{4}(m_{K#pi})"); + + //Fancy background to mkpi in the p^2 dimension + parameter cswavemkpi0 = parameter("cswavemkpi0", "c_{S}^{0}(m_{K#pi})"); + parameter cswavemkpi1 = parameter("cswavemkpi1", "c_{S}^{1}(m_{K#pi})"); + parameter cswavemkpi2 = parameter("cswavemkpi2", "c_{S}^{2}(m_{K#pi})"); + parameter cswavemkpi3 = parameter("cswavemkpi3", "c_{S}^{3}(m_{K#pi})"); + parameter cswavemkpi4 = parameter("cswavemkpi4", "c_{S}^{4}(m_{K#pi})"); + + parameter cbkgp20 = parameter("cbkgp20", "c_{bkg}^{0}(p^{2})"); + parameter cbkgp21 = parameter("cbkgp21", "c_{bkg}^{1}(p^{2})"); + parameter cbkgp22 = parameter("cbkgp22", "c_{bkg}^{2}(p^{2})"); + parameter cbkgp23 = parameter("cbkgp23", "c_{bkg}^{3}(p^{2})"); + parameter cbkgp24 = parameter("cbkgp24", "c_{bkg}^{4}(p^{2})"); + + //Nobody used this ever, probably not even in the PDF + parameter nthreshold = parameter("nthreshold", "n_{thr.}"); + + double J1s() const { + return 3.0/4.0*(1.0-J1c()); // 3/4*(1-F_L) + }; + double J1c() const { + if (opts->fit_pprimes) assert(opts->fit_fl); + if (opts->fit_fl) return Fl(); + else return 1.0-4.0/3.0*S1s(); + }; + double J2s() const { + return J1s()/3.0; //1/4(1-F_L) + }; + double J2c() const { + return -J1c(); //-F_L + }; + double J3() const {//P1;//=S3/(1-Fl) correction P1=2S3/(1-FL) + if (opts->fit_pprimes) return 0.5*P1()*(1.0-J1c()); + else return S3(); + }; + double J4() const {//P4;//=S4/sqrt(Fl Ft) + if (opts->fit_pprimes) return P4()*sqrt(J1c()*(1.0-J1c())); + else return S4(); + }; + double J5() const {//P5;//=S5/sqrt(Fl Ft) + if (opts->fit_pprimes) return P5()*sqrt(J1c()*(1.0-J1c())); + else return S5(); + }; + double J6s() const {//P2;//=S6/(1-Fl) correction P2=0.5*S6s/(1-FL) + if (opts->fit_pprimes) return 2.0*P2()*(1.0-J1c()); + else if (opts->fit_afb) return 4.0/3.0*Afb(); + else return S6s(); + }; + double J6c() const { + return 0.0; + }; + double J7() const {//P6;//=S7/sqrt(Fl Ft) + if (opts->fit_pprimes) return P6()*sqrt(J1c()*(1.0-J1c())); + else return S7(); + }; + double J8() const {//P8;//=S8/sqrt(Fl Ft) + if (opts->fit_pprimes) return P8()*sqrt(J1c()*(1.0-J1c())); + else return S8(); + }; + double J9() const {//P3;//=S9/(1-Fl) correction P3=-S9/(1-FL) + if (opts->fit_pprimes) return -P3()*(1.0-J1c()); + else return S9(); + }; +}; + + +} + +//Returns value or error of a parameter from a rootFile +double get_param_value_from_rootfile(std::string fileName, std::string names, int PDF, int bin); +double get_param_error_from_rootfile(std::string fileName, std::string names, int PDF, int bin); + +//Returns a scaled number of events in given bin from total number of events in data +double eventsInBin_fraction(int bin, int run, int nBins, bool fromRef); + +//Returns a scaled number of events in given bin from total number of events +//Eg I want to have 1000 events in 4 bins and 2 pdfs, it generates 155 signal + 100 bkg events in bin1, 125+120 in bin2, 180 + 50 in bin3 and 200+70 in bin4 as random example +void EventNumbers(unsigned int bin, unsigned int pdf, + double & fraction, unsigned int & eventnumbers,unsigned int TotalEvents, + unsigned int bins, unsigned int pdfs); + +#endif diff --git a/Code/FCNCFitter/sources/Core/bu2kstarmumu_pdf.cc b/Code/FCNCFitter/sources/Core/bu2kstarmumu_pdf.cc new file mode 100644 index 0000000..d93f830 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/bu2kstarmumu_pdf.cc @@ -0,0 +1,5380 @@ +//Renata Kopecna + +#include + +#include "folder.hh" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + + +//Helper function to create a polynomial for the background + +std::vector init_ch_ctl(const fcnc::bu2kstarmumu_parameters* params){ + std::vector bkg_ctl; + bkg_ctl.push_back(params->cbkgctl0()); + bkg_ctl.push_back(params->cbkgctl1()); + bkg_ctl.push_back(params->cbkgctl2()); + bkg_ctl.push_back(params->cbkgctl3()); + bkg_ctl.push_back(params->cbkgctl4()); + return bkg_ctl; +} +std::vector init_ch_ctk(const fcnc::bu2kstarmumu_parameters* params){ + std::vector bkg_ctk; + bkg_ctk.push_back(params->cbkgctk0()); + bkg_ctk.push_back(params->cbkgctk1()); + bkg_ctk.push_back(params->cbkgctk2()); + bkg_ctk.push_back(params->cbkgctk3()); + bkg_ctk.push_back(params->cbkgctk4()); + bkg_ctk.push_back(params->cbkgctk5()); + bkg_ctk.push_back(params->cbkgctk6()); + return bkg_ctk; +} +std::vector init_ch_phi(const fcnc::bu2kstarmumu_parameters* params){ + std::vector bkg_phi; + bkg_phi.push_back(params->cbkgphi0()); + bkg_phi.push_back(params->cbkgphi1()); + bkg_phi.push_back(params->cbkgphi2()); + bkg_phi.push_back(params->cbkgphi3()); + bkg_phi.push_back(params->cbkgphi4()); + return bkg_phi; +} + + +//using namespace std; +using namespace fcnc; + +//this is a wrapper for the complex error function +//which is needed for a gaussian convolution of exp*cos/sin +//this fortran implementation however is not thread safe! +extern "C" void wwerfwrap_(double *zr, double *zi, double *wr, double* wi); +//boost::mutex global_mutex_2; +std::mutex global_mutex_2; + +bu2kstarmumu_pdf* bu2kstarmumu_pdf::current_pdf; + +bu2kstarmumu_pdf::bu2kstarmumu_pdf(options* o, const bu2kstarmumu_parameters* params): + opts(o) +{ + + //vector of efficiency coefficients containing 1260 elements, coefficients stored in bu2kstarmumu_coefficients.cc + //coeffs_eff_4d = fcnc::coefficients_nominal; + //load_coeffs_eff_phsp_4d(); + fldr = new fcnc::folder(opts); +}; + +bu2kstarmumu_pdf::~bu2kstarmumu_pdf() +{ +}; + +void bu2kstarmumu_pdf::get_moments(std::vector events, std::vector& moments, std::vector& covariance) const +{ + + if(!opts->full_angular){ + spdlog::error("No folding implemented for moments. Debug: 1"); + assert(0); + } + + std::vector cov(NTERMS*NTERMS, 0.0);//the actual covariance matrix for the moments + std::vector m(NTERMS, 0.0);//need to first calculate the mean + + double nweight = 0.0; //sum of weights + double nweightsquared = 0.0; //sum of weights squared, not used anywhere + + for (auto meas: events){ + double weight = meas.weight*meas.sweight; + nweight += weight; + nweightsquared += weight*weight; + } + for (auto meas: events){ + double weight = meas.weight*meas.sweight; + weight /= nweight;//nominal + //Calculate the angular terms for each parameter + double f1=0.0, f2=0.0, f3=0.0, f4=0.0, f5=0.0, f6=0.0, + f7=0.0, f8=0.0, f9=0.0, f10=0.0, f11=0.0, f12=0.0; + fj(meas.costhetal, meas.costhetak, meas.phi, + f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12); + double ffs=0.0, fs1=0.0, fs2=0.0, fs3=0.0, fs4=0.0, fs5=0.0; + if(opts->swave){ + swave_fj(meas.costhetal, meas.costhetak, meas.phi, + ffs, fs1, fs2, fs3, fs4, fs5); + } + //TODO when bored: this is very annoying and f_whatever should be a struct or so and one should loop + m.at(0) += f1*weight; + m.at(1) += f2*weight; + m.at(2) += f3*weight; + m.at(3) += f4*weight; + m.at(4) += f5*weight; + m.at(5) += f6*weight; + m.at(6) += f7*weight; + m.at(7) += f8*weight; + m.at(8) += f9*weight; + m.at(9) += f10*weight; + m.at(10) += f11*weight; + m.at(11) += f12*weight; + if(opts->swave){ + m.at(12) += ffs*weight; + m.at(13) += fs1*weight; + m.at(14) += fs2*weight; + m.at(15) += fs3*weight; + m.at(16) += fs4*weight; + m.at(17) += fs5*weight; + } + } + + //calculate rms + for (auto meas: events){ + double weight = meas.weight*meas.sweight;//dangerous? + weight /= nweight;//nominal + double f1=0.0, f2=0.0, f3=0.0, f4=0.0, f5=0.0, f6=0.0, + f7=0.0, f8=0.0, f9=0.0, f10=0.0, f11=0.0, f12=0.0; + fj(meas.costhetal, meas.costhetak, meas.phi, + f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12); + double ffs=0.0, fs1=0.0, fs2=0.0, fs3=0.0, fs4=0.0, fs5=0.0; + if(opts->swave){ + swave_fj(meas.costhetal, meas.costhetak, meas.phi, + ffs, fs1, fs2, fs3, fs4, fs5); + } + std::vector diff(NTERMS*NTERMS, 0.0); + diff.at(0) = f1 - m.at(0); //aaaaaaaarrrrggghhh + diff.at(1) = f2 - m.at(1); + diff.at(2) = f3 - m.at(2); + diff.at(3) = f4 - m.at(3); + diff.at(4) = f5 - m.at(4); + diff.at(5) = f6 - m.at(5); + diff.at(6) = f7 - m.at(6); + diff.at(7) = f8 - m.at(7); + diff.at(8) = f9 - m.at(8); + diff.at(9) = f10 - m.at(9); + diff.at(10) = f11 - m.at(10); + diff.at(11) = f12 - m.at(11); + if(opts->swave){ + diff.at(12) = ffs - m.at(12); + diff.at(13) = fs1 - m.at(13); + diff.at(14) = fs2 - m.at(14); + diff.at(15) = fs3 - m.at(15); + diff.at(16) = fs4 - m.at(16); + diff.at(17) = fs5 - m.at(17); + } + //for swave==false, only loop over the first 12x12 elements + //the matrix however stays in the 18x18 format, with 0.0 for all j > 11 || k > 11 + UInt_t mm = opts->swave ? NTERMS : NTERMS_P; + for (unsigned int j = 0; j obs, std::vector obscov, int i, int k){ + return obscov.at(i+NTERMS*k)/sqrt(obscov.at(k+NTERMS*k))/sqrt(obscov.at(i+NTERMS*i)); +} + +void bu2kstarmumu_pdf::save_moments_to_obs(bu2kstarmumu_parameters* params, + std::vector obs, + std::vector obscov) const +{ + assert(obs.size() == NTERMS); + assert(obscov.size() == NTERMS*NTERMS); + + //**** Fl ****// + params->Fl.set_value(1.0-4.0/3.0*obs.at(0)); + params->Fl.set_error(4.0/3.0*sqrt(obscov.at(0+NTERMS*0))); + if(opts->fit_fl) params->Fl.set_step_size(0.0001); + + for(unsigned int i = 0; i < NTERMS; i++){ + if(i == 0) params->Fl.set_correlation(1.0, 0); //self correlation is one by definition + else if(i == 7 && opts->fit_afb){ + //correlation to Afb is equal to correlation of S1s and S6s + params->Fl.set_correlation(corr_from_obs(obs,obscov,7,0), 7); + } + else{ + params->Fl.set_correlation(corr_from_obs(obs,obscov,i,0)/sqrt(3.0/4.0), i); + } + } + + //**** S1s ****// + params->S1s.set_value(obs.at(0)); + params->S1s.set_error(sqrt(obscov.at(0+NTERMS*0))); + if(!opts->fit_fl) params->S1s.set_step_size(0.0001); + for(unsigned int i = 0; i < NTERMS; i++){ + params->S1s.set_correlation(corr_from_obs(obs,obscov,i,0), i); + } + //**** S3 ****// + params->S3.set_value(obs.at(4)); + params->S3.set_error(sqrt(obscov.at(4+NTERMS*4))); + params->S3.set_step_size(0.0001); + for(unsigned int i = 0; i < NTERMS; i++){ + params->S3.set_correlation(corr_from_obs(obs,obscov,i,4), i); + } + //**** S4 ****// + params->S4.set_value(obs.at(5)); + params->S4.set_error(sqrt(obscov.at(5+NTERMS*5))); + params->S4.set_step_size(0.0001); + for(unsigned int i = 0; i < NTERMS; i++) + params->S4.set_correlation(corr_from_obs(obs,obscov,i,5), i); + + //**** S5 ****// + params->S5.set_value(obs.at(6)); + params->S5.set_error(sqrt(obscov.at(6+NTERMS*6))); + params->S5.set_step_size(0.0001); + for(unsigned int i = 0; i < NTERMS; i++) + params->S5.set_correlation(corr_from_obs(obs,obscov,i,6), i); + + //**** Afb ****// + params->Afb.set_value(3.0/4.0*obs.at(7)); + params->Afb.set_error(3.0/4.0*sqrt(obscov.at(7+NTERMS*7))); + if(opts->fit_afb) + params->Afb.set_step_size(0.0001); + for(unsigned int i = 0; i < NTERMS; i++){ + if(i == 7) params->Afb.set_correlation(1.0, 7);//self correlation is not scaled + else if(i == 0 && opts->fit_afb){ + //correlation to Fl is equal to correlation of S1s and S6s + params->Afb.set_correlation(corr_from_obs(obs,obscov,0,7), 0); + } + else params->Afb.set_correlation(corr_from_obs(obs,obscov,i,7)/sqrt(4.0/3.0), i); + } + + //**** S6s ****// + params->S6s.set_value(obs.at(7)); + params->S6s.set_error(sqrt(obscov.at(7+NTERMS*7))); + if(!opts->fit_afb) params->S6s.set_step_size(0.0001); + for(unsigned int i = 0; i < NTERMS; i++) params->S6s.set_correlation(corr_from_obs(obs,obscov,i,7), i); + + //**** S7 ****// + params->S7.set_value(obs.at(9)); + params->S7.set_error(sqrt(obscov.at(9+NTERMS*9))); + params->S7.set_step_size(0.0001); + for(unsigned int i = 0; i < NTERMS; i++) params->S7.set_correlation(corr_from_obs(obs,obscov,i,9), i); + + //**** S8 ****// + params->S8.set_value(obs.at(10)); + params->S8.set_error(sqrt(obscov.at(10+NTERMS*10))); + params->S8.set_step_size(0.0001); + for(unsigned int i = 0; i < NTERMS; i++) params->S8.set_correlation(corr_from_obs(obs,obscov,i,10), i); + + //**** S9 ****// + params->S9.set_value(obs.at(11)); + params->S9.set_error(sqrt(obscov.at(11+NTERMS*11))); + params->S9.set_step_size(0.0001); + for(unsigned int i = 0; i < NTERMS; i++) params->S9.set_correlation(corr_from_obs(obs,obscov,i,11), i); + + //**** FS ****// + params->FS.set_value(obs.at(12)); + params->FS.set_error(sqrt(obscov.at(12+NTERMS*12))); + if(opts->swave) params->FS.set_step_size(0.0001); + for(unsigned int i = 0; i < NTERMS; i++) params->FS.set_correlation(corr_from_obs(obs,obscov,i,12), i); + + //**** SS1 ****// + params->SS1.set_value(obs.at(13)); + params->SS1.set_error(sqrt(obscov.at(13+NTERMS*13))); + if(opts->swave) params->SS1.set_step_size(0.0001); + for(unsigned int i = 0; i < NTERMS; i++) params->SS1.set_correlation(corr_from_obs(obs,obscov,i,13), i); + + //**** SS2 ****// + params->SS2.set_value(obs.at(14)); + params->SS2.set_error(sqrt(obscov.at(14+NTERMS*14))); + if(opts->swave) params->SS2.set_step_size(0.0001); + for(unsigned int i = 0; i < NTERMS; i++) params->SS2.set_correlation(corr_from_obs(obs,obscov,i,14), i); + + //**** SS3 ****// + params->SS3.set_value(obs.at(15)); + params->SS3.set_error(sqrt(obscov.at(15+NTERMS*15))); + if(opts->swave) params->SS3.set_step_size(0.0001); + for(unsigned int i = 0; i < NTERMS; i++) params->SS3.set_correlation(corr_from_obs(obs,obscov,i,15), i); + + //**** SS4 ****// + params->SS4.set_value(obs.at(16)); + params->SS4.set_error(sqrt(obscov.at(16+NTERMS*16))); + if(opts->swave)params->SS4.set_step_size(0.0001); + for(unsigned int i = 0; i < NTERMS; i++) params->SS4.set_correlation(corr_from_obs(obs,obscov,i,16), i); + + //**** SS5 ****// + params->SS5.set_value(obs.at(17)); + params->SS5.set_error(sqrt(obscov.at(17+NTERMS*17))); + if(opts->swave) params->SS5.set_step_size(0.0001); + for(unsigned int i = 0; i < NTERMS; i++) params->SS5.set_correlation(corr_from_obs(obs,obscov,i,17), i); + + +} + +double bu2kstarmumu_pdf::prob(const bu2kstarmumu_parameters* params, const event& meas) const +{ + + //safety checks: + if(opts->fit_mkpi && opts->use_mkpi){ + spdlog::critical("Do not use the direct fit of m(Kpi) and the included fit of m(Kpi) in the angular s-Wave at the same time!"); + spdlog::critical("5D fit:\t'use_mkpi'"); + spdlog::critical("4D+1D fit:\t'fit_mkpi'"); + assert(0); + } + if(opts->only_mass2DFit && opts->only_Bmass){ + spdlog::critical("Cannot fit m(Kpi) and m(B) with option 'only_Bmass'!"); + assert(0); + } + if(opts->only_mass2DFit && !opts->fit_mkpi){ + spdlog::critical("When using the 2D mass fit, enable 'fit_mkpi' as well!"); + assert(0); + } + if(opts->only_mkpi && !opts->fit_mkpi){ + spdlog::critical("When using the m(Kpi) mass fit, enable 'fit_mkpi' as well!"); + assert(0); + } + if((opts->only_angles && opts->only_Bmass) || (opts->only_mkpi && opts->only_Bmass) || (opts->only_angles && opts->only_mkpi)){ + spdlog::critical("Do not use two or more of 'only_Bmass', 'only_mkpi' and 'only_angles' at the same time!"); + spdlog::critical("only_Bmass = " + boolToString(opts->only_Bmass)); + spdlog::critical("only_mkpi = " + boolToString(opts->only_mkpi)); + spdlog::critical("only_angles = " + boolToString(opts->only_angles)); + assert(0); + } + + if(opts->use_angular_acc && opts->weighted_fit){ + spdlog::critical("Do not use 'use_angular_acc' and 'weighted_fit' at the same time!"); + spdlog::critical("'use_angular_acc'\tConvolute acceptance function into fit pdf"); + spdlog::critical("'weighted_fit'\tAssign per event weight according to acceptance"); + assert(0); + } + if(opts->twotailedcrystalball && opts->crystalball){ + spdlog::critical("Cannot use CB and two-tailed CB option. Choose only one and chose wisely:"); + spdlog::critical("Either 'twotailedcrystalball' or 'crystalball'"); + assert(0); + } + + if(opts->full_angular && opts->folding > -1){ + spdlog::critical("Cannot run full angular fit and folding at the same time"); + assert(0); + } + + //determine signal and background probability + double fsig = (opts->extended_ml ? params->n_sig()/(params->n_sig()+params->n_bkg()) : params->f_sig()); + double sig_part = 0.0; + double bkg_part = 0.0; + + if(fsig != 0.0)//signal part: + sig_part += fsig + * angular_sig_prob(params, meas) + * m_sig_prob(params, meas) + * mkpi_sig_prob(params, meas); + + if(fsig != 1.0)//background part: + bkg_part += (1.0-fsig) + * angular_bkg_prob(params, meas) + * m_bkg_prob(params, meas) + * mkpi_bkg_prob(params, meas); + + //force individual probabilities for signal and background to be positive + if(opts->individual_penalties){ + if(sig_part < 0.0){ + sig_part = 1.0e-12; + bkg_part = 0.0; + } + if(bkg_part < 0.0){ + bkg_part = 1.0e-12; + sig_part = 0.0; + } + } + + //add background and signal parts: + double result = sig_part + bkg_part; + + //check final probability + if(result < 0.0){ + std::lock_guard lock(global_mutex_2); + spdlog::debug("Event has negative probability {0:e}", result); + spdlog::debug("Signal_part:\t{0:e}", sig_part); + spdlog::debug("m(B):\t\t{0:e}",m_sig_prob(params, meas)); //THIS one crashes and idk why + spdlog::debug("m(Kpi):\t{0:e}",mkpi_sig_prob(params, meas)); + spdlog::debug("angles:\t{0:e}",angular_sig_prob(params, meas)); + spdlog::debug("FS:\t\t{0:e}", params->FS.get_value()); + spdlog::debug("Backgrnd_part:\t{0:e}", bkg_part); + if (fsig != 1.0){ + spdlog::debug("m(B):\t{0:e}",m_bkg_prob(params, meas)); + spdlog::debug("m(Kpi):\t{0:e}",mkpi_bkg_prob(params, meas)); + spdlog::debug("angles:\t{0:e}",angular_bkg_prob(params, meas)); + } + + const bool variablepushback = false; //OMFG + if(variablepushback){ + double baseline = 1.0e-12; + double absres = fabs(result) > 1.0e-6 ? fabs(result) : 1.0e-6; + double logres = log10(absres)+6.0; + double factor = pow(10.0, -logres); + result = baseline*factor; + } + else{ + result = 1.0e-12; + } + } + else if(std::isinf(result) || std::isnan(result)){ + std::lock_guard lock(global_mutex_2); + params->print_parameters(false); + spdlog::error("Event has probability {0:f}", result); + spdlog::error("Signal_part:\t{0:f}", sig_part); + spdlog::error("fsig:\t\t{0:f}", fsig); + spdlog::error("m(B):\t\t{0:f}", m_sig_prob(params, meas)); + spdlog::error("m(Kpi):\t{0:e}", mkpi_sig_prob(params, meas)); + spdlog::error("angles:\t{0:e}",angular_sig_prob(params, meas)); + spdlog::error("FS:\t\t{0:f}", params->FS.get_value()); + spdlog::error("m(K*+) s-Wave NORM:\t{0:f}", mkpi_swave_2_norm); + spdlog::error("m(K*+) p-Wave NORM:\t{0:f}", mkpi_pwave_2_norm); + spdlog::error("Backgrnd_part:\t{0:f}", bkg_part); + assert(0); + } + return result; +}; + +void bu2kstarmumu_pdf::init(parameters* params) { + init(dynamic_cast(params)); + //update_cached_normalization(params); +}; + + +struct bin_edges{ //This could've been a class in case someone is bored in the future + + //limits for all variable (range) (4D): + double q2min, q2max; + double ctkmin, ctkmax; + double ctlmin, ctlmax; + double phimin, phimax; + + unsigned int nq2bins, nctlbins, nctkbins, nphibins; + + //keep this as functions in case of modyfing the ranges during running the code! + + //range of each dimension (4D): + double range_q2(){ + return q2max - q2min; + } + double range_ctk(){ + return ctkmax - ctkmin; + } + double range_ctl(){ + return ctlmax - ctlmin; + } + double range_phi(){ + return phimax - phimin; + } + + //bin width for each variable + double binWidth_q2(){ + return range_q2()/nq2bins; + } + double binWidth_ctl(){ + return range_ctl()/nctlbins; + } + double binWidth_ctk(){ + return range_ctk()/nctkbins; + } + double binWidth_phi(){ + return range_phi()/nphibins; + } + + //bin edges for each variable + std::vector edges_q2(){ + std::vector tmp; + for (unsigned int h = 0; h<=nq2bins; h++){ + tmp.push_back(q2min + h * binWidth_q2()); + } + return tmp; + } + std::vector edges_ctl(){ + std::vector tmp; + for (unsigned int h = 0; h<=nctlbins; h++){ + tmp.push_back(ctlmin + h * binWidth_ctl()); + } + return tmp; + } + std::vector edges_ctk(){ + std::vector tmp; + for (unsigned int h = 0; h<=nctkbins; h++){ + tmp.push_back(ctkmin + h * binWidth_ctk()); + } + return tmp; + } + std::vector edges_phi(){ + std::vector tmp; + for (unsigned int h = 0; h<=nphibins; h++){ + tmp.push_back(phimin + h * binWidth_phi()); + } + return tmp; + } + + //Total number of bins in 4D + unsigned int getNbins(){ + return nq2bins*nctlbins*nctkbins*nphibins; + } + + //constructor + bin_edges(fcnc::options *opts, unsigned int nq2,unsigned int nctl,unsigned int nctk,unsigned int nphi){ + + //get the limits for all variables (4D): + q2min = opts->TheQ2binsmin.front(); q2max = opts->TheQ2binsmax.back(); + ctkmin = opts->ctk_min; ctkmax = opts->ctk_max; + ctlmin = opts->ctl_min; ctlmax = opts->ctl_max; + phimin = opts->phi_min; phimax = opts->phi_max; + + nq2bins = nq2; + nctlbins = nctl; + nctkbins = nctk; + nphibins = nphi; + } + +}; + +unsigned int get_bin_in4D(int h, int i, int j, int k, bin_edges edges){ + /// h = q2, i = ctl, j = ctk, k = phi + + //Return the bin number for given event evt in 4D (q2, thetal, thetak, phi) + //Starting from 0! + unsigned int bin = edges.nctlbins*edges.nctkbins*edges.nphibins*h //q2 + +edges.nctkbins*edges.nphibins*i //thetaL + +edges.nphibins*j //thetaK + +k; //phi + if (bin >= edges.getNbins()){ + spdlog::critical("Bin {0:d} is larger than the dimension of {1:d}!",bin,edges.getNbins()); + spdlog::error("h {0:d},\ti {1:d},\tj {2:d},\tk {3:d}", h, i, j, k); + spdlog::error("q2 {0:d},\tctl {1:d},\tctk {2:d},\tphi {3:d}", + edges.nq2bins, edges.nctlbins, edges.nctkbins, edges.nphibins); + assert(0); + } + else return bin; +} + +unsigned int get_bin_in4D(event evt, bin_edges edges ){ + //Return the bin number for given event evt in 4D (q2, thetal, thetak, phi) + //Starting from 0! + unsigned int h = (evt.q2 - edges.q2min ) / edges.binWidth_q2(); //division here truncates the result"chi + unsigned int i = (evt.costhetal - edges.ctlmin) / edges.binWidth_ctl();//eg 18/10 = 1 + unsigned int j = (evt.costhetak - edges.ctkmin) / edges.binWidth_ctk(); + unsigned int k = (evt.phi - edges.phimin) / edges.binWidth_phi(); + + return get_bin_in4D(h,i,j,k, edges); +} + +unsigned int npolynom::get_bin_in4D(int h, int i, int j, int k){ + /// h = q2, i = ctl, j = ctk, k = phi + + //Return the bin number for given event evt in 4D (q2, thetal, thetak, phi) + //Starting from 0! + return ctl*ctk*phi*h //q2 + +ctk*phi*i //thetaL + +phi*j //thetaK + +k; //phi +} + +unsigned int get_bin_in3D(int i, int j, int k, npolynom npol){ + /// h = q2, i = ctl, j = ctk, k = phi + + //Return the bin number for given event evt in 4D (q2, thetal, thetak, phi) + //Starting from 0! + return npol.ctk*npol.phi*i //thetaL + +npol.phi*j //thetaK + +k; //phi +} + +unsigned int get_bin_in3D(int i, int j, int k, bin_edges edges){ + /// h = q2, i = ctl, j = ctk, k = phi + + //Return the bin number for given event evt in 4D (q2, thetal, thetak, phi) + //Starting from 0! + return edges.nctkbins*edges.nphibins*i //thetaL + +edges.nphibins*j //thetaK + +k; //phi +} + +void get_chi2(bin_edges edges, npolynom npol, + std::vector eventsInQ2bin, std::vector coeffs_moments, + values* globalvalues, + bool assumectleven, bool assumePhiEven, bool write_eps, + std::string subfolder, std::string appendix){ + + spdlog::info( "Starting chi2 calculation" ); + std::vector nsel_hist(edges.getNbins(), 0.0); + std::vector nsel_hist_errsq(edges.getNbins(), 0.0); + + //this is actually not the correct error here, due to the weights! + //should be sqrt(sum_i weights_i^2) + + double nsel = 0.0; + int nEvents = eventsInQ2bin.size(); + for (auto &meas: eventsInQ2bin) { + unsigned int bin = get_bin_in4D(meas,edges); + nsel_hist.at(bin) += meas.weight; + nsel += meas.weight; + nsel_hist_errsq.at(bin) += sqr(meas.weight); + } + //Set errors + for (auto err: nsel_hist_errsq){ + if (err == 0.0) err = 1.0; + } + + //compare with prediction + double neps = 0.0; + std::vector neps_hist(edges.getNbins(), 0.0); + std::vector q2_edges = edges.edges_q2(); + std::vector ctl_edges = edges.edges_ctl(); + std::vector ctk_edges = edges.edges_ctk(); + std::vector phi_edges = edges.edges_phi(); + + for (unsigned int h = 0; hFill((nsel_hist.at(bin)-neps_hist.at(bin))/sqrt(fabs(neps_hist.at(bin)))); + spdlog::trace("nsel_hist.at({0:d})\t{1:f}",bin,nsel_hist.at(bin)); + spdlog::trace("neps_hist.at({0:d})\t{1:f}",bin,neps_hist.at(bin)); + hnsel->Fill(nsel_hist.at(bin)); + hnfit->Fill(neps_hist.at(bin)); + } + } + } + } + spdlog::debug( "chi2\t {0:f}", chi2 ); + + //Calculate the number of parameters + int nparams = npol.q2*npol.ctl*npol.ctk*npol.phi-1; + spdlog::debug( "Nparams\t {0:d}", nparams ); + + if (assumectleven && assumePhiEven){ + nparams = npol.q2*((npol.ctl+1)/2)*npol.ctk*((npol.phi+1)/2)-1; + } + else{ + if (assumectleven) nparams = npol.q2*((npol.ctl+1)/2)*npol.ctk*npol.phi-1; + if (assumePhiEven) nparams = npol.q2*npol.ctl*npol.ctk*((npol.phi+1)/2)-1; + } + spdlog::debug( "Nparams (accounting for even ctl and phi)\t {0:d}", nparams ); + + //Get degrees of freedom + int nbins = edges.getNbins(); + spdlog::debug( "Nbins\t {0:d}", nbins); + + int ndof = nbins - nparams - 1; + spdlog::debug( "ndof\t {0:d}", ndof ); + + spdlog::debug( "chi2/ndof (accounting for even ctl and phi)\t {0:f}",chi2/ndof ); + spdlog::debug( "chi2/Nbins\t\t {0:f}",chi2/nbins ); + spdlog::debug( "pvalue using ndof\t {0:f}",TMath::Prob(chi2, ndof) ); + spdlog::debug( "pvalue using nbins\t {0:f}", TMath::Prob(chi2, nbins) ); + + //========================================= + // + // save chi2 to global values: + // + //========================================= + + globalvalues->angacccorr_chi2 = chi2; + globalvalues->angacccorr_ndof = ndof; + + //recount of nparams + int ncount = 0; + for (unsigned int l = 0; l eventsInQ2bin, double nWeightedEvents, + std::vector &poly_moments, + bool fejerkernel, bool assumectleven, bool assumePhiEven, + bool checkSignificance, bool calculateCovariance){ + //use Legendre polynomials + spdlog::info("DOLEGENDRE start"); + + //should def use this: + //calculates all legendre polynomials up to including degree n + //void fcnc::legendre(double x, int n, std::vector& results) + + //this is not the best way to do things + //should rather + //loop over events + //determine, for every event the legendre polynomials order 0 to nq2/nctl/nctk/nphi + //loop over all orders + //add weight*leg_q2.at(h)*leg_ctl.at(i)*leg_ctk.at(j)*leg_phi.at(k) in correct bin + + //optimized version + std::vector chijk_moments = std::vector(npol.getSize(), 0.0); + for (auto & meas: eventsInQ2bin){ //This is all computed then in the range of -1 to +1 + double q2 = 2.0 * (meas.q2 - edges.q2min ) / edges.range_q2() - 1.0; + double ctl = 2.0 * (meas.costhetal - edges.ctlmin) / edges.range_ctl()- 1.0; + double ctk = 2.0 * (meas.costhetak - edges.ctkmin) / edges.range_ctk()- 1.0; + double phi = 2.0 * (meas.phi - edges.phimin) / edges.range_phi()- 1.0; + + double weight = meas.weight; + //calculates all legendre polynomials up to including degree n + std::vector leg_q2(npol.q2, 0.0); + fcnc::legendre(q2, npol.q2, leg_q2); + std::vector leg_ctl(npol.ctl, 0.0); + fcnc::legendre(ctl, npol.ctl, leg_ctl); + std::vector leg_ctk(npol.ctk, 0.0); + fcnc::legendre(ctk, npol.ctk, leg_ctk); + std::vector leg_phi(npol.phi, 0.0); + fcnc::legendre(phi, npol.phi, leg_phi); + + double result = 0.0; + for (unsigned int h = 0; h covariance(nsize*nsize, 0.0); + //startB = clock(); + for (unsigned int e=0; e leg_q2(npol.q2, 0.0); + legendre(q2, npol.q2, leg_q2); + std::vector leg_ctl(npol.ctl, 0.0); + legendre(ctl, npol.ctl, leg_ctl); + std::vector leg_ctk(npol.ctk, 0.0); + legendre(ctk, npol.ctk, leg_ctk); + std::vector leg_phi(npol.phi, 0.0); + legendre(phi, npol.phi, leg_phi); + double wfactor = weight*weight/(nWeightedEvents*nWeightedEvents); + double resulti=0.0, resultj=0.0, cov=0.0; + unsigned int bini=0, binj=0; + + int hfactor=0, ifactor=0, jfactor=0, kfactor=0, + lfactor=0, mfactor=0, nfactor=0, ofactor=0, + hifactor=0, hijfactor=0, hijkfactor=0, + lmfactor=0, lmnfactor=0, lmnofactor=0; + double aq2=0.0,aq2ctl=0.0,aq2ctlctk=0.0,aq2ctlctkphi=0.0; + double bq2=0.0,bq2ctl=0.0,bq2ctlctk=0.0,bq2ctlctkphi=0.0; + for (unsigned int h = 0; h fabs(correlation) && i != j) correlation = corr; + } + } + spdlog::info("Largest correlation found is {0:f}", correlation ); + } + + spdlog::debug("start CONVERT legendre to monomial coefficients" ); + //transform legendre coefficients to monomial coefficients + + + for (unsigned int h = 0; h leg_coeffs_q2(npol.q2, 0.0); + std::vector leg_coeffs_ctl(npol.ctl, 0.0); + std::vector leg_coeffs_ctk(npol.ctk, 0.0); + std::vector leg_coeffs_phi(npol.phi, 0.0); + + std::vector poly_coeffs_q2(npol.q2, 0.0); + std::vector poly_coeffs_ctl(npol.ctl, 0.0); + std::vector poly_coeffs_ctk(npol.ctk, 0.0); + std::vector poly_coeffs_phi(npol.phi, 0.0); + + leg_coeffs_q2.at(h) = 1.0; + leg_coeffs_ctl.at(i) = 1.0; + leg_coeffs_ctk.at(j) = 1.0; + leg_coeffs_phi.at(k) = 1.0; + + legendre_to_poly(leg_coeffs_q2, poly_coeffs_q2); + legendre_to_poly(leg_coeffs_ctl, poly_coeffs_ctl); + legendre_to_poly(leg_coeffs_ctk, poly_coeffs_ctk); + legendre_to_poly(leg_coeffs_phi, poly_coeffs_phi); + + for (unsigned int l = 0; l<=h; l++) + for (unsigned int m = 0; m<=i; m++) + for (unsigned int n = 0; n<=j; n++) + for (unsigned int o = 0; o<=k; o++){ + unsigned int bin = npol.get_bin_in4D(l,m,n,o); + poly_moments.at(bin) += tmp*poly_coeffs_q2.at(l)*poly_coeffs_ctl.at(m)*poly_coeffs_ctk.at(n)*poly_coeffs_phi.at(o); + } + }//tested, works + spdlog::debug( "end CONVERT legendre to monomial coefficients" ); + spdlog::debug( "poly_moments size: {0:d}", poly_moments.size() ); + + spdlog::info( "DOLEGENDRE end" ); + +} + +void get_chebyschev(bin_edges edges, npolynom npol, + std::vector eventsInQ2bin, double nWeightedEvents, + std::vector &poly_moments, + bool fejerkernel, bool assumectleven, bool assumePhiEven, + bool checkSignificance, bool calculateCovariance + ){ + //use Legendre polynomials + spdlog::info("CHEBYSCHEV start"); + std::vector chijk_moments = std::vector(npol.getSize(), 0.0); + + for (unsigned int h = 0; h covariance(npol.getSize2(), 0.0); + for (unsigned int h = 0; h bini) continue;//covariance matrix is symmetric + double resultj = chijk_moments.at(binj); + if (((bini*npol.getSize()+binj) * 100) % (npol.getSize2()) == 0) + spdlog::debug( "covariance matrix calculation {0:f}%", ((bini*npol.getSize()+binj) * 100) / (npol.getSize2())); + if (resultj != 0.0){ + double cov = 0.0; + for (auto &meas : eventsInQ2bin){ + double q2 = 2.0 * (meas.q2 - edges.q2min ) / edges.range_q2() - 1.0; + double ctl = 2.0 * (meas.costhetal - edges.ctlmin) / edges.range_ctl()- 1.0; + double ctk = 2.0 * (meas.costhetak - edges.ctkmin) / edges.range_ctk()- 1.0; + double phi = 2.0 * (meas.phi - edges.phimin) / edges.range_phi()- 1.0; + + + cov += ((resulti - meas.weight + *fcnc::chebyshev(q2, h)/sqrt(1-q2*q2)*(h == 0 ? 1.0/MY_PI : 2.0/MY_PI) + *fcnc::chebyshev(ctl, i)/sqrt(1-ctl*ctl)*(i == 0 ? 1.0/MY_PI : 2.0/MY_PI) + *fcnc::chebyshev(ctk, j)/sqrt(1-ctk*ctk)*(j == 0 ? 1.0/MY_PI : 2.0/MY_PI) + *fcnc::chebyshev(phi, k)/sqrt(1-phi*phi)*(k == 0 ? 1.0/MY_PI : 2.0/MY_PI)) + *(resultj - meas.weight + *fcnc::chebyshev(q2, l)/sqrt(1-q2*q2)*(l == 0 ? 1.0/MY_PI : 2.0/MY_PI) + *fcnc::chebyshev(ctl, m)/sqrt(1-ctl*ctl)*(m == 0 ? 1.0/MY_PI : 2.0/MY_PI) + *fcnc::chebyshev(ctk, n)/sqrt(1-ctk*ctk)*(n == 0 ? 1.0/MY_PI : 2.0/MY_PI) + *fcnc::chebyshev(phi, o)/sqrt(1-phi*phi)*(o == 0 ? 1.0/MY_PI : 2.0/MY_PI)) + ); + } + //cov = sqrt(cov); //to get sigma on diagonal + cov /= sqr(nWeightedEvents); + covariance.at(npol.getSize()*bini+binj) = cov; + covariance.at(npol.getSize()*binj+bini) = cov; + } + } + } + } + } + } + } + } + } + } + + + spdlog::info("uncertainties[{0:0.8e}]", npol.getSize()); + if (spdlog_info()){ + for (unsigned int i =0; i fabs(correlation) && i != j) + correlation = corr; + } + spdlog::info( "Largest correlation found is {0:f}", correlation ); + } + //transform chebyshev coefficients to monomial coefficients + + + for (unsigned int h = 0; h ch_coeffs_q2(npol.q2, 0.0); + std::vector ch_coeffs_ctl(npol.ctl, 0.0); + std::vector ch_coeffs_ctk(npol.ctk, 0.0); + std::vector ch_coeffs_phi(npol.phi, 0.0); + + std::vector poly_coeffs_q2(npol.q2, 0.0); + std::vector poly_coeffs_ctl(npol.ctl, 0.0); + std::vector poly_coeffs_ctk(npol.ctk, 0.0); + std::vector poly_coeffs_phi(npol.phi, 0.0); + + ch_coeffs_q2.at(h) = 1.0; + ch_coeffs_ctl.at(i) = 1.0; + ch_coeffs_ctk.at(j) = 1.0; + ch_coeffs_phi.at(k) = 1.0; + + chebyshev_to_poly(ch_coeffs_q2, poly_coeffs_q2); + chebyshev_to_poly(ch_coeffs_ctl, poly_coeffs_ctl); + chebyshev_to_poly(ch_coeffs_ctk, poly_coeffs_ctk); + chebyshev_to_poly(ch_coeffs_phi, poly_coeffs_phi); + + for (unsigned int l = 0; l<=h; l++){ + for (unsigned int m = 0; m<=i; m++){ + for (unsigned int n = 0; n<=j; n++){ + for (unsigned int o = 0; o<=k; o++){ + unsigned int bin = npol.get_bin_in4D(l,m,n,o); + poly_moments.at(bin) += c*poly_coeffs_q2.at(l)*poly_coeffs_ctl.at(m)*poly_coeffs_ctk.at(n)*poly_coeffs_phi.at(o); + } + } + } + } + } + } + } + } + +} + + +double integrate_4D(bin_edges edges, int h, int i, int j, int k){ + return integrate_x_to_n(edges.q2min, edges.q2max,h)//careful with q2max + *integrate_x_to_n(edges.ctlmin, edges.ctlmax,i) + *integrate_x_to_n(edges.ctkmin, edges.ctkmax,j) + *integrate_x_to_n(edges.phimin, edges.phimax,k); +} + +double integrate_3D(bin_edges edges, int i, int j, int k){ + return integrate_x_to_n(edges.ctlmin, edges.ctlmax,i) + *integrate_x_to_n(edges.ctkmin, edges.ctkmax,j) + *integrate_x_to_n(edges.phimin, edges.phimax,k); +} + +void fill_moments_hist_1D(TH1D *hist_moments, std::vector coeffs_moments, + bin_edges edges, npolynom npol, double q2low, double q2high){ + + bool do_ctl = (std::string(hist_moments->GetName()).find("ctl") != std::string::npos); + bool do_ctk = (std::string(hist_moments->GetName()).find("ctk") != std::string::npos); + bool do_phi = (std::string(hist_moments->GetName()).find("phi") != std::string::npos); + bool do_q2 = (std::string(hist_moments->GetName()).find("q2") != std::string::npos); + + for (int l=1; l<=hist_moments->GetNbinsX(); l++){ + double a = hist_moments->GetBinLowEdge(l); + double b = hist_moments->GetBinLowEdge(l+1); + double integral = 0.0; + for (unsigned int h = 0; hSetBinContent(l, integral); + } + return; + +} + + +void fill_moments_hist_2D(TH2D *hist_moments, std::vector coeffs_moments, + bin_edges edges, npolynom npol, double q2low, double q2high){ + + bool do_ctl = (std::string(hist_moments->GetName()).find("ctl") != std::string::npos); + bool do_ctk = (std::string(hist_moments->GetName()).find("ctk") != std::string::npos); + bool do_phi = (std::string(hist_moments->GetName()).find("phi") != std::string::npos); + bool do_q2 = (std::string(hist_moments->GetName()).find("q2") != std::string::npos); + + spdlog::trace("do_ctl\t"+boolToString(do_ctl)); + spdlog::trace("do_ctk\t"+boolToString(do_ctk)); + spdlog::trace("do_phi\t"+boolToString(do_phi)); + spdlog::trace("do_q2\t"+boolToString(do_q2)); + bool is_ctl_First = !do_q2; //ctl is second if q2 + bool is_ctk_First = !(do_q2 || do_ctl); //ctk is second if ctl or q2 + //phi is always second and q2 always first + spdlog::trace("is_ctl_First\t"+boolToString(is_ctl_First)); + spdlog::trace("is_ctk_First\t"+boolToString(is_ctk_First)); + + for (int l=1; l<=hist_moments->GetNbinsX(); l++){ + double a = hist_moments->GetXaxis()->GetBinLowEdge(l); + double b = hist_moments->GetXaxis()->GetBinLowEdge(l+1); + for (int m=1; m<=hist_moments->GetNbinsY(); m++){ + double c = hist_moments->GetYaxis()->GetBinLowEdge(m); + double d = hist_moments->GetYaxis()->GetBinLowEdge(m+1); + double integral = 0.0; + for (unsigned int h = 0; hSetBinContent(l, m, integral); + } + } + return; + +} + + +int get_correct_index(std::string whichVar, int l, int m, int n, int o){ + if (whichVar == "q2") return l; + if (whichVar == "ctl") return m; + if (whichVar == "ctk") return n; + if (whichVar == "phi") return o; + return -1; +} +int change_index(std::string whichVar, npolynom npol, int p, int l, int m, int n, int o){ + if (whichVar == "q2") return npol.get_bin_in4D(p,m,n,o); + if (whichVar == "ctl") return npol.get_bin_in4D(l,p,n,o); + if (whichVar == "ctk") return npol.get_bin_in4D(l,m,p,o); + if (whichVar == "phi") return npol.get_bin_in4D(l,m,n,p); + return -1; +} +void correct_coefficients(npolynom npol, bin_edges edges, std::vector &out_poly_moments, std::vector in_poly_moments, std::string whichVar){ + //Just rebin + unsigned int npol_var; + double intvar_min; + double intvar_max; + if (whichVar == "q2"){ //If this would be na efin array, my life would be orders of magnitute easier + npol_var = npol.q2; + intvar_min = edges.q2min; + intvar_max = edges.q2max; + } + else if (whichVar == "ctl") { + npol_var = npol.ctl; + intvar_min = edges.ctlmin; + intvar_max = edges.ctlmax; + } + else if (whichVar == "ctk") { + npol_var = npol.ctk; + intvar_min = edges.ctkmin; + intvar_max = edges.ctkmax; + } + else if (whichVar == "phi") { + npol_var = npol.phi; + intvar_min = edges.phimin; + intvar_max = edges.phimax; + } + else{ + spdlog::error("Wrong index name! Either q2, ctl, ctk or phi!"); + assert (0); + } + spdlog::debug("npol_var = {0:d}\tintvar_min = {1:f}\tintvar_max = {2:f}", npol_var, intvar_min, intvar_max); + for (unsigned int l = 0; l poly(npol_var, 0.0); + poly.at(get_correct_index(whichVar,l,m,n,o)) = in_poly_moments.at(bin); + std::vector correct(npol_var, 0.0); + correct_poly(poly, correct, intvar_min, intvar_max); + for (unsigned int p = 0; p& events, values* globalvalues, int tagNumber, bool assumePhiEven, bool checkSignificance, bool runMinuit, bool checkFactorization, bool do3Dmoments){ + + spdlog::debug("----> start parametrization of angular acceptance correction coefficients with {0:d} events.", events.size()); + + const UInt_t nBinsQ2 = 40; + const UInt_t nBinsAngles = 40; + + bool ignore_q2weights = false; + if (ignore_q2weights) spdlog::warn("Not using weights from genLvl PHSP to flatten the q2 distribution!!!"); + + //Get the pointer to this class of bu2kstarmumu_pdf + current_pdf = this; + + std::vector q2binsmin = opts->TheQ2binsmin; //Check TheQ2binsmax and q2binsmin + std::vector q2binsmax = opts->TheQ2binsmax; + spdlog::debug("Vector q2binsmin:\t"+convert_vector_to_string(q2binsmin)); + spdlog::debug("Vector q2binsmax:\t"+convert_vector_to_string(q2binsmax)); + + //name tag for all plots: + std::string appendix = "_"+DECAY_NAME + + (opts->KS ? opts->DDLL+"_" : "_") + + "Run" + std::to_string(opts->run) + + ((opts->angacccorrperyear && opts->year != -1) ? "_"+std::to_string(opts->year) : "") + + ((opts->folding != -1) ? "_folding"+std::to_string(opts->folding) : "") + + ((opts->systematic == 3) ? "_"+std::to_string(opts->orderincrease)+"moreOrders" : "") + + std::string(tagNumber != 0 ? "_"+std::to_string(tagNumber) : ""); + std::string subfolder = "plots/angular/" + std::string(tagNumber != 0 ? "test/" : ""); + spdlog::debug("Saving all plots into folder " + subfolder); + + //Set orders of chebyshev/legendre polynomials + npolynom npol(opts); //Should be a const, but then all the future shuffling gets difficult + + //fold the events if needed: + spdlog::debug("Init folder...."); +//TODO remove fcnc::folder fldr(opts); + //only accept events inside q2min and q2max + std::vector filtered_events; + //std::vector fullrange_events; + unsigned int ee; + unsigned int N = events.size(); + TRandom3 * rnd = new TRandom3(15*opts->job_id); + + spdlog::debug("Filtering events..."); + for (unsigned int e=0; esystematic == 1) ee = int(rnd->Rndm() * N); + else ee = e; //or the correct, nominal order + fcnc::event evt = events.at(ee); + if (!isEvtInAngleRange(&(evt), opts)) continue; + filtered_events.push_back(evt); + if(!opts->full_angular) fldr->fold(&filtered_events.back()); + } + + if (!ignore_q2weights){ + spdlog::debug("Getting q2 weights..."); + //weight for all events, reweight from PHSP q2 model to flat q2 distribution using histogram + TFile* fphspweightq2 = new TFile(CONFIG_PHSP_WEIGHT.c_str()); + TH1D* phspweightq2 = dynamic_cast(fphspweightq2->Get(opts->IsFlatQ2 ? "flatq2weights" : "phspweightq2")); + + bool keep_weights = opts->systematic != 2; + bool vary_weights = opts->systematic == 4; + + //reweight filtered events + for (auto evt: filtered_events){ + double q2 = evt.q2; + + if(vary_weights){ + evt.weight += evt.delta_weight * rnd->Gaus(0., 1.); + } + + if (q2 < 0.2){ + if(keep_weights) evt.weight *= phspweightq2->GetBinContent(2);//keep loaded totalweight! + else evt.weight = phspweightq2->GetBinContent(2); + } + else{ + int bin = phspweightq2->FindFixBin(q2); + if (bin >=1 && bin <= phspweightq2->GetNbinsX()){ + if(keep_weights) evt.weight *= phspweightq2->GetBinContent(bin);//keep loaded totalweight! + else evt.weight = phspweightq2->GetBinContent(bin); + } + } + } + + delete phspweightq2; + fphspweightq2->Close(); + delete fphspweightq2; + } + + //for systematic 9: trigger weights, multiply existing weights by 1/L0Muon_eff + if(opts->systematic == 9){ + spdlog::debug("Getting systematic 9"); + //get years from current data-set: + std::vector years; //empty vector + for (auto event: filtered_events){ + bool year_found = false; + for(auto yr: years){ + if(yr == event.year){ + year_found = true; + break; + } + } + if(!year_found) years.push_back(event.year); //First event always gets filled + //Technically one should make an if to check it is all years, but given the size of the event sample this is okayish + } + assert(years.size()); + std::sort(years.begin(), years.end()); + + //get L0Muon efficiency histo(s) + TFile * f_L0_w[years.size()]; + TH1D * h_L0_w[years.size()]; + for(unsigned int y = 0; y < years.size(); y++){ + f_L0_w[y] = new TFile((std::string("config/")+(opts->KS?"KshortPiplus":"KplusPi0Resolved")+"_L0MuonEfficiency_"+std::to_string(years.at(y))+".root").c_str(), "READ"); + if(!f_L0_w[y]->IsOpen()){ + spdlog::critical( "Could not find file with L0Muon efficiencies: 'config/" + std::string(opts->KS ? "KshortPiplus" : "KplusPi0Resolved") + "_L0MuonEfficiency_{0:d}.root'", years.at(y) ); + assert(0); + } + h_L0_w[y] = dynamic_cast(f_L0_w[y]->Get("L0MuonEffRatioPHSP")); + spdlog::info("Succesfully loaded L0Muon efficiency reweighting histogram for year={0:d}", years.at(y)); + } + + for (unsigned int i=0; i 20000.){ + filtered_events.at(i).weight *= h_L0_w[year_idx]->GetBinContent(h_L0_w[year_idx]->GetNbinsX()); + } + else{ + int bin = h_L0_w[year_idx]->FindFixBin(max_mu_pt); + filtered_events.at(i).weight *= h_L0_w[year_idx]->GetBinContent(bin); + } + } + + for(unsigned int y = 0; y < years.size(); y++){ + delete h_L0_w[y]; + f_L0_w[y]->Close(); + delete f_L0_w[y]; + } + } + + //set the pointer that is accessible from the minuit fcn + eff_events = filtered_events; + + //make plot to check weight distribution if running a test + if(tagNumber >0){ + spdlog::debug("Plotting weights"); + TH1D* hweight = new TH1D("hweight", ";w;", 100, 0.0, 1.0/EFF_CUTOFF); + for (unsigned int i=0; iFill(filtered_events.at(i).weight); + } + TCanvas * cweights = new TCanvas(); + cweights->cd(); + hweight->Draw(""); + if(opts->write_eps)cweights->Print((subfolder + "weights"+appendix+".eps").c_str(), "eps"); + if(opts->write_eps)cweights->Print((subfolder + "weights"+appendix+".root").c_str(), "root"); + + delete hweight; + delete cweights; + } + + //--------------------------------------- + //DETERMINATION FROM ACCEPTANCE HISTOGRAM + //--------------------------------------- + unsigned int nq2bins = 18; + unsigned int nctlbins = 10; + unsigned int nctkbins = 10; + unsigned int nphibins = 5; + + bool adapt_bins_to_folding = false; + if(adapt_bins_to_folding){ + nphibins /= 2; + if(opts->folding > 0)nctlbins /= 2; + } + + spdlog::debug("Options: "); + spdlog::debug("q2min={0:f}\tq2max={1:f}", opts->TheQ2binsmin.front(),opts->TheQ2binsmax.back()); + spdlog::debug("ctkmin={0:f}\tctkmax={1:f}", opts->ctk_min, opts->ctk_max); + spdlog::debug("ctlmin={0:f}\tctlmax={1:f}", opts->ctl_min, opts->ctl_max); + spdlog::debug("phimin={0:f}\tphimax={1:f}", opts->phi_min, opts->phi_max); + bin_edges edges (opts, nq2bins, nctlbins, nctkbins, nphibins); + const std::vector q2_edges = edges.edges_q2(); + const std::vector ctl_edges = edges.edges_ctl(); + const std::vector ctk_edges = edges.edges_ctk(); + const std::vector phi_edges = edges.edges_phi(); //This could've been a struct/class + + spdlog::trace("q2 edges: " + convert_vector_to_string(q2_edges)); + spdlog::trace("ctl edges: " + convert_vector_to_string(ctl_edges)); + spdlog::trace("ctk edges: " + convert_vector_to_string(ctk_edges)); + spdlog::trace("phi edges: " + convert_vector_to_string(phi_edges)); + + + //should compare full 4D with + //3D in q2 bins + //3D factorizing in bins of q2 + + spdlog::debug("Getting number of weighted events..."); + std::vector eps_hist(edges.getNbins(), 0.0); + double nWeightedEvents = 0.0; + for (auto &meas: filtered_events){ + unsigned int bin = get_bin_in4D(meas,edges); + eps_hist.at(bin) += meas.weight; + nWeightedEvents += meas.weight; + } + + //rescale efficiency + spdlog::debug("Rescaling efficiency..."); + for (unsigned int h = 0; h hxi_hist; + for (auto angObs: get_angObser_withTeX_vec()){ + hxi_hist.push_back(new TH1D(("hxi"+angObs[0]+"hist").c_str(), (";q^{2};"+angObs[1]).c_str(), + edges.nq2bins, edges.q2min, edges.q2max)); + } + + std::vectorint_xi(hxi_hist.size(),0); + for (unsigned int h = 0; hfull_angular){ + integrated_fj_noacc(ctl_edges[i], ctl_edges[i+1], + ctk_edges[j], ctk_edges[j+1], + phi_edges[k], phi_edges[k+1], + f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12); + } + else{ + folded_integrated_fj_noacc(ctl_edges[i], ctl_edges[i+1], + ctk_edges[j], ctk_edges[j+1], + phi_edges[k], phi_edges[k+1], + f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12); + } + int_xi[0] += eps*f1; //KILL ME + int_xi[1] += eps*f2; + int_xi[2] += eps*f3; + int_xi[3] += eps*f4; + int_xi[4] += eps*f5; + int_xi[5] += eps*f6; + int_xi[6] += eps*f7; + int_xi[7] += eps*f8; + int_xi[8] += eps*f9; + int_xi[9] += eps*f10; + int_xi[10] += eps*f11; + int_xi[11] += eps*f12; + } + for_indexed(auto hist: hxi_hist) hist->SetBinContent(h+1,int_xi[i]); + } + + //----------------------------------- + //DETERMINE XIS USING UNBINNED METHOD + //----------------------------------- + + spdlog::debug("Getting xis using unbinned method..."); + std::vector hxi_ub; + for (auto angObs: get_angObser_withTeX_vec()){ + hxi_ub.push_back(new TH1D(("hxi"+angObs[0]+"ub").c_str(), (";q^{2};"+angObs[1]).c_str(), + edges.nq2bins, edges.q2min, edges.q2max)); + } + + //make it pretty + for (auto hist: hxi_ub) hist->SetLineColor(4); + + for (unsigned int h = 0; hGetBinLowEdge(h); //check this is the same as q2_edges!!!!! should be, but to be sure + //double q2b = hxi_ub[0]->GetBinLowEdge(h+1); + for (auto &&meas: filtered_events){ + if (meas.q2 < q2_edges[h] || meas.q2 > q2_edges[h]) continue; + double f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12; + if(opts->full_angular){ + fj(meas.costhetal, meas.costhetak, meas.phi, + f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12); + } + else{ + folded_fj(meas.costhetal, meas.costhetak, meas.phi, + f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12); + } + + double weight = meas.weight/nWeightedEvents*edges.nq2bins*(edges.range_ctl()*edges.range_ctk()*edges.range_phi()); + int_xi[0] += f1*weight; //KILL ME + int_xi[1] += f2*weight; + int_xi[2] += f3*weight; + int_xi[3] += f4*weight; + int_xi[4] += f5*weight; + int_xi[5] += f6*weight; + int_xi[6] += f7*weight; + int_xi[7] += f8*weight; + int_xi[8] += f9*weight; + int_xi[9] += f10*weight; + int_xi[10] += f11*weight; + int_xi[11] += f12*weight; + } + + for_indexed(auto hist: hxi_ub) hist->SetBinContent(h,int_xi[i]); + + } + + //------------------------------------------------------ + //DETERMINE POLYNOMIAL ACCEPTANCE WITH METHOD OF MOMENTS + //------------------------------------------------------ + const bool calculateCovariance = false; + const bool assumectleven = opts->systematic == 2; + const bool fejerkernel = false; //see Alexander Weisse, Holger Feshke, Chebyshev expansion techniques + const bool doLegendre = true; //somehow, chebyshev is broken now, great job me + + std::vector poly_moments(npol.getSize(), 0.0); + + if (doLegendre){ + get_legendre(edges, npol, + filtered_events, nWeightedEvents, + poly_moments, + fejerkernel, assumectleven, assumePhiEven, + checkSignificance, calculateCovariance); + } + else{ + get_chebyschev(edges, npol, + filtered_events, nWeightedEvents, + poly_moments, + fejerkernel, assumectleven, assumePhiEven, + checkSignificance, calculateCovariance); + + } + + spdlog::debug("Getting correct polynomial coefficients in cos(thetak) and cos(thetal)"); + spdlog::debug("poly_moments size:{0:d}", poly_moments.size()); + //correct coefficients from -1 +1 to ctlmin .. ctlmax for ctl, bit difficult, requires binomial coefficients + std::vector poly_moments_ctl(npol.getSize(), 0.0); + std::vector poly_moments_ctk(npol.getSize(), 0.0); + std::vector poly_moments_phi(npol.getSize(), 0.0); + std::vector poly_moments_q2(npol.getSize(), 0.0); + + correct_coefficients(npol,edges,poly_moments_ctl,poly_moments, "ctl"); + correct_coefficients(npol,edges,poly_moments_ctk,poly_moments_ctl, "ctk"); + correct_coefficients(npol,edges,poly_moments_phi,poly_moments_ctk, "phi"); + correct_coefficients(npol,edges,poly_moments_q2, poly_moments_phi, "q2"); + + spdlog::debug("Getting moments...."); + + std::vector coeffs_moments(poly_moments_q2); + //calculate norm after full integration + double full_norm = 0.0; + for (unsigned int h = 0; h scale by edges.range_q2()*RANGE_3D()/full_norm + for (unsigned int h = 0; h hxi_moments; + for (auto &angObs: get_angObser_withTeX_vec()){ + hxi_moments.push_back(new TH1D(("hxi"+angObs[0]+"_moments").c_str(), (";q^{2};"+angObs[1]).c_str(), + edges.nq2bins, edges.q2min, edges.q2max)); + } + + for (int l=1; l<=hxi_moments[0]->GetNbinsX(); l++) { + double a = hxi_moments[0]->GetXaxis()->GetBinLowEdge(l); + double b = hxi_moments[0]->GetXaxis()->GetBinLowEdge(l+1); + std::vector integral_xi(hxi_moments.size(),0.0); + + for (unsigned int h = 0; hSetBinContent(l, is_param_folded(i,opts) ? 0.0 : integral_xi[i]); + } + + + //----------------------------------------------------- + //DETERMINE POLYNOMIAL ACCEPTANCE USING UNBINNED ML FIT + //----------------------------------------------------- + std::vector hxi_ml_hist; + for (auto &angObs: get_angObser_withTeX_vec()){ + hxi_ml_hist.push_back(new TH1D(("hxi"+angObs[0]+"_ml").c_str(), (";q^{2};"+angObs[1]).c_str(), + nBinsQ2, edges.q2min, edges.q2max)); + } + for (auto &hist: hxi_ml_hist){ + hist->SetLineColor(3); + } + + //possible TODO for when you're bored: move into it's own function + //Running minuit is expensive, use only if necesary! + if (runMinuit){ + spdlog::info("Running Minuit...."); + //setup minuit + TMinuit* minuit_eff = new TMinuit(10000); + int errorcode; + minuit_eff->SetFCN(&(eff_fcn_phsp_4d)); + double strategy_list[1] = {2.0}; + minuit_eff->mnexcm("SET STR", strategy_list, 1, errorcode); + minuit_eff->SetMaxIterations(1000000); + minuit_eff->SetErrorDef(1.0); + const bool second_run = false; + //define params (could also feed with starting values from method of moments) + unsigned int q2_limit = 6; + unsigned int ctl_limit = 3; + unsigned int ctk_limit = 4; + unsigned int phi_limit = 1; + for (unsigned int h = 0; hDefineParameter(npol.get_bin_in4D(h,i,j,k), sout.str().c_str(), 1.0, 0.0, 0.0, 0.0); + } + else if (h >= q2_limit || i >= ctl_limit || j >= ctk_limit || k >= phi_limit){ + //this is to be able to do higher orders with the moments method and lower ones with minuit + minuit_eff->DefineParameter(npol.get_bin_in4D(h,i,j,k), sout.str().c_str(), 0.0, 0.0, 0.0, 0.0); + } + else if ((second_run && i == 0 && k == 0)|| (!second_run && i % 2 == 0 && k % 2 == 0)){ + minuit_eff->DefineParameter(npol.get_bin_in4D(h,i,j,k), sout.str().c_str(), 0.0, 0.001, 0.0, 0.0); + } + else{ + minuit_eff->DefineParameter(npol.get_bin_in4D(h,i,j,k), sout.str().c_str(), 0.0, 0.0, 0.0, 0.0); + } + } + } + } + } + double migrad_options[2] = {100000000.0, 0.1}; //{max calls, tolerance} + spdlog::info( "Running Migrad to determine eff shape" ); + minuit_eff->mnset(); + minuit_eff->mnexcm("MIG", migrad_options, 2, errorcode); + + if (second_run){ + spdlog::info( "Running Migrad a second time releasing parameters" ); + //second run releasing some parameters + for (unsigned int h = 0; h 0 || k > 0) && i % 2 == 0 && k % 2 == 0 + && h < q2_limit && i < ctl_limit && j < ctk_limit && k < phi_limit + )// && (i+j+k)<=4) + minuit_eff->DefineParameter(npol.get_bin_in4D(h,i,j,k), sout.str().c_str(), 0.0, 0.001, 0.0, 0.0); + } + spdlog::info( "Running Migrad to determine eff shape" ); + minuit_eff->mnexcm("MIG", migrad_options, 2, errorcode); + } + //extract fitted parameters + spdlog::debug("Extracting fitted parameters."); + std::vector chijk_ml; + for (unsigned int h = 0; hGetParameter(npol.get_bin_in4D(h,i,j,k), v, e); + chijk_ml.push_back(v); + } + delete minuit_eff; + spdlog::info( "Minuit finished" ); + + //transform chebyshev coefficients to monomial coefficients + std::vector poly_ml(npol.getSize(), 0.0); + for (unsigned int h = 0; h ch_coeffs_q2(npol.q2, 0.0); + std::vector ch_coeffs_ctl(npol.ctl, 0.0); + std::vector ch_coeffs_ctk(npol.ctk, 0.0); + std::vector ch_coeffs_phi(npol.phi,0.0); + ch_coeffs_q2.at(h) = 1.0; + ch_coeffs_ctl.at(i) = 1.0; + ch_coeffs_ctk.at(j) = 1.0; + ch_coeffs_phi.at(k) = 1.0; + std::vector poly_coeffs_q2(npol.q2, 0.0); + std::vector poly_coeffs_ctl(npol.ctl, 0.0); + std::vector poly_coeffs_ctk(npol.ctk, 0.0); + std::vector poly_coeffs_phi(npol.phi,0.0); + chebyshev_to_poly(ch_coeffs_q2, poly_coeffs_q2); + chebyshev_to_poly(ch_coeffs_ctl, poly_coeffs_ctl); + chebyshev_to_poly(ch_coeffs_ctk, poly_coeffs_ctk); + chebyshev_to_poly(ch_coeffs_phi, poly_coeffs_phi); + for (unsigned int l = 0; l<=h; l++) + for (unsigned int m = 0; m<=i; m++) + for (unsigned int n = 0; n<=j; n++) + for (unsigned int o = 0; o<=k; o++){ + unsigned int bin = npol.get_bin_in4D(l,m,n,o); + poly_ml.at(bin) += c*poly_coeffs_q2.at(l)*poly_coeffs_ctl.at(m)*poly_coeffs_ctk.at(n)*poly_coeffs_phi.at(o); + } + }//tested, works + + //correct coefficients from -1 +1 to ctlmin .. ctlmax for ctl, bit difficult, requires binomial coefficients + std::vector poly_ml_ctl(npol.getSize(), 0.0); + std::vector poly_ml_ctk(npol.getSize(), 0.0); + std::vector poly_ml_phi(npol.getSize(), 0.0); + std::vector poly_ml_q2(npol.getSize(), 0.0); + correct_coefficients(npol, edges, poly_ml_ctl, poly_ml, "ctl"); + correct_coefficients(npol, edges, poly_ml_ctk, poly_ml_ctl, "ctk"); + correct_coefficients(npol, edges, poly_ml_phi, poly_ml_ctk, "phi"); + correct_coefficients(npol, edges, poly_ml_q2, poly_ml_phi, "q2"); + + + std::vector coeffs_ml(poly_ml_q2); + //calculate norm after full integration + double full_norm = 0.0; + for (unsigned int h = 0; h scale by edges.range_q2()*RANGE_3D()/full_norm + for (unsigned int h = 0; hGetNbinsX(); l++){ + double a = hxi_ml_hist[0]->GetXaxis()->GetBinLowEdge(l); + double b = hxi_ml_hist[0]->GetXaxis()->GetBinLowEdge(l+1); + std::vector integral_xi(hxi_ml_hist.size(), 0.0); + + for (unsigned int h = 0; hSetBinContent(l, is_param_folded(i,opts) ? 0.0 : integral_xi[i]); + } + } + + //----------------------- + // Factorization in q2 bins + //----------------------- + //std::vector nfact(); + if (checkFactorization){ //possible TODO for when you're bored: move into it's own function + spdlog::info( "CHECKFACTORIZATION start " ); + //fill histo for comparison + std::vector nsel_hist(edges.getNbins(), 0.0); + std::vector nsel_hist_errsq(edges.getNbins(), 0.0); + for (auto &meas: filtered_events){ + unsigned int h = (meas.q2 - edges.q2min ) / edges.binWidth_q2(); + unsigned int i = (meas.costhetal - edges.ctlmin ) / edges.binWidth_ctl(); + unsigned int j = (meas.costhetak - edges.ctkmin ) / edges.binWidth_ctk(); + unsigned int k = (meas.phi - edges.phimin ) / edges.binWidth_phi(); + + unsigned int bin = get_bin_in4D(h,i,j,k,edges); + nsel_hist.at(bin) += meas.weight; + nsel_hist_errsq.at(bin) += sqr(meas.weight); + } + for (unsigned int i=0; i ctl_moments(npol.ctl, 0.0); + std::vector ctk_moments(npol.ctk, 0.0); + std::vector phi_moments(npol.phi,0.0); + double nfactweighted = 0.0; + //determine weighted number of events in this bin and fill control histos + std::ostringstream sout; + sout << h; + sout << "_" << DECAY_NAME << (opts->KS ? opts->DDLL+"_" : "_") + << "Run" << opts->run + << ((opts->angacccorrperyear && opts->year != -1) ? "_"+std::to_string(opts->year) : "") + << "_" << tagNumber; + TH1D* hctl = new TH1D("hctl", ";cos#Theta_{L};", nBinsAngles, edges.ctlmin, edges.ctlmax); + TH1D* hctk = new TH1D("hctk", ";cos#Theta_{K};", nBinsAngles, edges.ctkmin, edges.ctkmax); + TH1D* hphi = new TH1D("hphi", ";#phi [rad];" , nBinsAngles, edges.phimin, edges.phimax); + for (auto &meas : filtered_events){ + if (meas.q2 > q2a && meas.q2 < q2b){ + nfactweighted += meas.weight; + hctl->Fill(meas.costhetal, meas.weight); + hctk->Fill(meas.costhetak, meas.weight); + hphi->Fill(meas.phi, meas.weight); + } + } + //loop over events in this bin, determine factorizing moments + for (auto & meas: filtered_events){ + if (meas.q2 > q2a && meas.q2 < q2b){ + double weight = meas.weight; + double ctl = 2.0 * (meas.costhetal - edges.ctlmin ) / edges.range_ctl() - 1.0; + double ctk = 2.0 * (meas.costhetak - edges.ctkmin ) / edges.range_ctk() - 1.0; + double phi = 2.0 * (meas.phi - edges.phimin ) / edges.range_phi() - 1.0; + + for (unsigned int i = 0; i ctl_polys(npol.ctl, 0.0); + std::vector ctk_polys(npol.ctk, 0.0); + std::vector phi_polys(npol.phi,0.0); + if (doLegendre){ + legendre_to_poly(ctl_moments, ctl_polys); + legendre_to_poly(ctk_moments, ctk_polys); + legendre_to_poly(phi_moments, phi_polys); + } + else{ + chebyshev_to_poly(ctl_moments, ctl_polys); + chebyshev_to_poly(ctk_moments, ctk_polys); + chebyshev_to_poly(phi_moments, phi_polys); + } + + //transform angles from -1 +1 to angle_min angle_max + std::vector ctl_correct(npol.ctl, 0.0); + std::vector ctk_correct(npol.ctk, 0.0); + std::vector phi_correct(npol.phi,0.0); + + for (unsigned int i=0; i neps_hist(nctlbins*nctkbins*nphibins, 0.0); + for (unsigned int i = 0; iFill((nsel_hist.at(bin)-neps_hist.at(get_bin_in3D(i,j,k,edges)))/sqrt(fabs(neps_hist.at(get_bin_in3D(i,j,k,edges)))));//TODO: h is a wrong bin! + } + } + } + //do plots + TH1D* ectl = new TH1D("ectl", ";cos#Theta_{L};", nBinsAngles, edges.ctlmin, edges.ctlmax); + TH1D* ectk = new TH1D("ectk", ";cos#Theta_{K};", nBinsAngles, edges.ctkmin, edges.ctkmax); + TH1D* ephi = new TH1D("ephi", ";#phi [rad];" , nBinsAngles, edges.phimin, edges.phimax); + for (int l=1; l<=ectl->GetNbinsX(); l++){ + double integral = 0.0; + for (unsigned int i = 0; iGetBinLowEdge(l),ectl->GetBinLowEdge(l+1),i); + } + ectl->SetBinContent(l, integral); + } + for (int l=1; l<=ectk->GetNbinsX(); l++){ + double integral = 0.0; + for (unsigned int j = 0; jGetBinLowEdge(l),ectl->GetBinLowEdge(l+1),j); + } + ectk->SetBinContent(l, integral); + } + for (int l=1; l<=ephi->GetNbinsX(); l++){ + double integral = 0.0; + for (unsigned int k = 0; kGetBinLowEdge(l),ectl->GetBinLowEdge(l+1),k); + } + ephi->SetBinContent(l, integral); + } + TLatex *tex = getPrettyTex(0.06,31); + + std::ostringstream sregion; + sregion << std::fixed << std::setprecision(2) << q2a << "cd(); + hpull->Draw(); + tex->DrawLatex(0.85, 0.15, sregion.str().c_str()); + if(opts->write_eps)c_pull->Print((std::string(subfolder + "fact_pull")+sout.str()+std::string(".eps")).c_str(),"eps"); + + plotAngular(hctl,ectl,opts->write_eps,"fact_ctleff",sout.str(),sregion.str(),tex,subfolder); + plotAngular(hctk,ectk,opts->write_eps,"fact_ctkeff",sout.str(),sregion.str(),tex,subfolder); + plotAngular(hphi,ephi,opts->write_eps,"fact_phieff",sout.str(),sregion.str(),tex,subfolder); + + delete hpull; + delete ectl; + delete ectk; + delete ephi; + delete hctl; + delete hctk; + delete hphi; + + delete c_pull; + + spdlog::debug( "fact chi2 in bin {0:d}: {1:f}", h, curr_chi2 ); + chi2 += curr_chi2; + } + spdlog::info( "fact total chi2: {0:f}",chi2 ); + spdlog::info( "uses {0:d}*{1:d}*{2:d}*{3:d}={4:d} bins",edges.nq2bins, edges.nctlbins, edges.nctkbins, edges.nphibins, edges.getNbins()); + spdlog::info( "Chi2/Nbins = {0:f}", chi2/(edges.getNbins()) ); + spdlog::info( "CHECKFACTORIZATION end " ); + } + //----------------------- + // 3D MOMENTS in q2 bins + //----------------------- + if (do3Dmoments){ + spdlog::info("DOTHREEDMOMENTS start "); + //fill histo for comparison + std::vector nsel_hist(edges.getNbins(), 0.0); + std::vector nsel_hist_errsq(edges.getNbins(), 0.0); + for (unsigned int e=0; eKS ? opts->DDLL+"_" : "_") + << "Run" << opts->run + << ((opts->angacccorrperyear && opts->year != -1) ? "_"+std::to_string(opts->year) : ""); + TH1D* hctl = new TH1D("hctl", ";cos#Theta_{L};", nBinsAngles, edges.ctlmin, edges.ctlmax); + TH1D* hctk = new TH1D("hctk", ";cos#Theta_{K};", nBinsAngles, edges.ctkmin, edges.ctkmax); + TH1D* hphi = new TH1D("hphi", ";#phi [rad];" , nBinsAngles, edges.phimin, edges.phimax); + for (auto &meas: filtered_events){ + if (meas.q2 > q2a && meas.q2 < q2b){ + nthreedweighted += meas.weight; + hctl->Fill(meas.costhetal, meas.weight); + hctk->Fill(meas.costhetak, meas.weight); + hphi->Fill(meas.phi, meas.weight); + } + } + //loop over events in this bin, determine factorizing moments + spdlog::debug("Getting factorizing moments"); + std::vector threed_moments(npol.ctl*npol.ctk*npol.phi,0.0); + for (unsigned int i = 0; i q2a && meas.q2 < q2b){ + double weight = meas.weight; + double ctl = 2.0 * (meas.costhetal - edges.ctlmin ) / edges.range_ctl() - 1.0; + double ctk = 2.0 * (meas.costhetak - edges.ctkmin ) / edges.range_ctk() - 1.0; + double phi = 2.0 * (meas.phi - edges.phimin ) / edges.range_phi() - 1.0; + + double result = 0.0; + if (assumectleven && i%2 != 0) result = 0.0; + else if (assumePhiEven && k%2 != 0) result = 0.0; + else { + if (doLegendre){ + result = weight + *fcnc::legendre(ctl, i)*(2.0*i+1.0)/2.0 + *fcnc::legendre(ctk, j)*(2.0*j+1.0)/2.0 + *fcnc::legendre(phi, k)*(2.0*k+1.0)/2.0 + /nthreedweighted;// /filtered_events.size(); + } + else{ + result = weight + *fcnc::chebyshev(ctl, i)/sqrt(1-ctl*ctl)*(i==0 ? 1.0/MY_PI : 2.0/MY_PI) + *fcnc::chebyshev(ctk, j)/sqrt(1-ctk*ctk)*(j==0 ? 1.0/MY_PI : 2.0/MY_PI) + *fcnc::chebyshev(phi, k)/sqrt(1-phi*phi)*(k==0 ? 1.0/MY_PI : 2.0/MY_PI) + /nthreedweighted;// /filtered_events.size(); + } + } + threed_moments.at( get_bin_in3D(i,j,k,npol)) += result; + } + } + } + } + } + //make polynomial + + //transform legendre coefficients to monomial coefficients + spdlog::debug("Transforming legendre coefficients to monomial coefficients...."); + std::vector threedpoly_moments(npol.ctl*npol.ctk*npol.phi,0.0); + for (unsigned int i = 0; i leg_coeffs_ctl(npol.ctl, 0.0); + std::vector leg_coeffs_ctk(npol.ctk, 0.0); + std::vector leg_coeffs_phi(npol.phi,0.0); + leg_coeffs_ctl.at(i) = 1.0; + leg_coeffs_ctk.at(j) = 1.0; + leg_coeffs_phi.at(k) = 1.0; + std::vector poly_coeffs_ctl(npol.ctl, 0.0); + std::vector poly_coeffs_ctk(npol.ctk, 0.0); + std::vector poly_coeffs_phi(npol.phi,0.0); + legendre_to_poly(leg_coeffs_ctl, poly_coeffs_ctl); + legendre_to_poly(leg_coeffs_ctk, poly_coeffs_ctk); + legendre_to_poly(leg_coeffs_phi, poly_coeffs_phi); + + for (unsigned int m = 0; m<=i; m++){ + for (unsigned int n = 0; n<=j; n++){ + for (unsigned int o = 0; o<=k; o++){ + unsigned int bin = get_bin_in3D(m,n,o,npol); + threedpoly_moments.at(bin) += tmp*poly_coeffs_ctl.at(m)*poly_coeffs_ctk.at(n)*poly_coeffs_phi.at(o); + } + } + } + } + } + } + + //correct coefficients from -1 +1 to -pi .. +pi for phi, this is easy + std::vector threedpoly_moments_phi(threedpoly_moments); + for (unsigned int m = 0; m neps_hist(nctlbins*nctkbins*nphibins, 0.0); + for (unsigned int i = 0; iFill((nsel_hist.at(bin)-neps_hist.at(get_bin_in3D(i,j,k,edges)))/sqrt(fabs(neps_hist.at(get_bin_in3D(i,j,k,edges))))); + } + //spdlog::debug( "ok" ); + //do plots + TH1D* ectl = new TH1D("ectl", ";cos#Theta_{L};", nBinsAngles, edges.ctlmin, edges.ctlmax); + TH1D* ectk = new TH1D("ectk", ";cos#Theta_{K};", nBinsAngles, edges.ctkmin, edges.ctkmax); + TH1D* ephi = new TH1D("ephi", ";#phi [rad];" , nBinsAngles, edges.phimin, edges.phimax); + for (int l=1; l<=ectl->GetNbinsX(); l++){ + double a = ectl->GetBinLowEdge(l); + double b = ectl->GetBinLowEdge(l+1); + double integral = 0.0; + for (unsigned int i = 0; iSetBinContent(l, integral); + } + for (int l=1; l<=ectk->GetNbinsX(); l++){ + double a = ectk->GetBinLowEdge(l); + double b = ectk->GetBinLowEdge(l+1); + double integral = 0.0; + for (unsigned int i = 0; iSetBinContent(l, integral); + } + for (int l=1; l<=ephi->GetNbinsX(); l++){ + double a = ephi->GetBinLowEdge(l); + double b = ephi->GetBinLowEdge(l+1); + double integral = 0.0; + for (unsigned int i = 0; iSetBinContent(l, integral); + } + + spdlog::debug("Plotting..."); + TLatex *tex = getPrettyTex(0.06,31); + std::ostringstream sregion; + sregion << std::fixed << std::setprecision(2) << q2a << "cd(); + hpull->Draw(); + tex->DrawLatex(0.85, 0.15, sregion.str().c_str()); + if(opts->write_eps)c_zero->Print((std::string(subfolder + "3d_pull")+sout.str()+std::string(".eps")).c_str(),"eps"); + + plotAngular(hctl,ectl,opts->write_eps,"3d_ctleff", sout.str(), sregion.str(),tex,subfolder); + plotAngular(hctk,ectk,opts->write_eps,"3d_ctkeff", sout.str(), sregion.str(),tex,subfolder); + plotAngular(hphi,ephi,opts->write_eps,"3d_phieff", sout.str(), sregion.str(),tex,subfolder); + + delete hpull; + delete ectl; + delete ectk; + delete ephi; + delete hctl; + delete hctk; + delete hphi; + + delete c_zero; + + spdlog::debug( "3d chi2 in bin {0:d}: {1:f}", h, curr_chi2 ); + chi2 += curr_chi2; + } + spdlog::debug( "3d total chi2: {0:f}",chi2 ); + spdlog::debug( "3d uses {0:d}*{1:d}*{2:d}*{3:d}={4_d} bins",edges.nq2bins, edges.nctlbins, edges.nctkbins, edges.nphibins, edges.getNbins()); + spdlog::debug( "3d chi2/Nbins = {0:f}", chi2/(edges.getNbins()) ); + spdlog::info( "DOTHREEDMOMENTS end " ); + + } + //----------------------- + // CHI2 TEST FOR MOMENTS + //----------------------- + bool dochi2test = true; + if(opts->only_4_1D_chi2)dochi2test = false; + spdlog::debug("dochi2: "+boolToString(dochi2test)); + if (dochi2test) { + get_chi2(edges, npol, filtered_events, coeffs_moments, globalvalues, + assumectleven, assumePhiEven, opts->write_eps, subfolder, appendix); + } + + //----------------------- + //MAKE NICE CONTROL PLOTS + //----------------------- + const bool do_plots = opts->write_eps || opts->only_4_1D_chi2; + if (do_plots){ + + spdlog::info( "Start PLOTS.." ); + + gROOT->SetStyle("Plain"); + TPad foo; + const int NRGBs = 5; + const int NCont = 250; + double stops[NRGBs] = { 0.00, 0.34, 0.61, 0.84, 1.00 }; + double red[NRGBs] = { 0.00, 0.00, 0.87, 1.00, 0.51 }; + double green[NRGBs] = { 0.00, 0.81, 1.00, 0.20, 0.00 }; + double blue[NRGBs] = { 0.51, 1.00, 0.12, 0.00, 0.00 }; + TColor::CreateGradientColorTable(NRGBs, stops, red, green, blue, NCont); + gStyle->SetNumberContours(NCont); + gStyle->SetLabelFont(132, "xyz"); + gStyle->SetTitleFont(132, "xyz"); + gStyle->SetLegendFont(132); + gStyle->SetStatFont(132); + //new histograms binned in q2 + //compare the three angular projections for data and moments + + for (unsigned int u=0; u q2a && meas.q2 < q2b){ + hctl->Fill(meas.costhetal, meas.weight); + hctk->Fill(meas.costhetak, meas.weight); + hphi->Fill(meas.phi, meas.weight); + + hctlctk->Fill(meas.costhetal, meas.costhetak, meas.weight); + hctlphi->Fill(meas.costhetal, meas.phi, meas.weight); + hctkphi->Fill(meas.costhetak, meas.phi, meas.weight); + } + } + + TH1D* hctl_moments = new TH1D("hctl_moments", ";cos#Theta_{L};", nBinsAngles, edges.ctlmin, edges.ctlmax); + TH1D* hctk_moments = new TH1D("hctk_moments", ";cos#Theta_{K};", nBinsAngles, edges.ctkmin, edges.ctkmax); + TH1D* hphi_moments = new TH1D("hphi_moments", ";#phi [rad];" , nBinsAngles, edges.phimin, edges.phimax); + TH2D* hctlctk_moments = new TH2D("hctlctk_moments", ";cos#Theta_{L};cos#Theta_{K}", nBinsAngles, edges.ctlmin, edges.ctlmax, nBinsAngles, edges.ctkmin, edges.ctkmax); + TH2D* hctlphi_moments = new TH2D("hctlphi_moments", ";cos#Theta_{L};#phi [rad]" , nBinsAngles, edges.ctlmin, edges.ctlmax, nBinsAngles, edges.phimin, edges.phimax); + TH2D* hctkphi_moments = new TH2D("hctkphi_moments", ";cos#Theta_{K};#phi [rad]" , nBinsAngles, edges.ctkmin, edges.ctkmax, nBinsAngles, edges.phimin, edges.phimax); + + //1d plots + fill_moments_hist_1D(hctl_moments, coeffs_moments, edges, npol, q2a, q2b); + fill_moments_hist_1D(hctk_moments, coeffs_moments, edges, npol, q2a, q2b); + fill_moments_hist_1D(hphi_moments, coeffs_moments, edges, npol, q2a, q2b); + + //2d plots + fill_moments_hist_2D(hctlctk_moments, coeffs_moments, edges, npol, q2a, q2b); + fill_moments_hist_2D(hctlphi_moments, coeffs_moments, edges, npol, q2a, q2b); + fill_moments_hist_2D(hctkphi_moments, coeffs_moments, edges, npol, q2a, q2b); + + + TLatex *tex = getPrettyTex(0.06,31); + std::ostringstream sregion; + sregion << std::fixed << std::setprecision(2) << q2a << "write_eps,"ctleff",binno+appendix,sregion.str(), tex, subfolder); + plotAngular(hctk,hctk_moments,opts->write_eps,"ctkeff",binno+appendix,sregion.str(), tex, subfolder); + plotAngular(hphi,hphi_moments,opts->write_eps,"phieff",binno+appendix,sregion.str(), tex, subfolder); + + if (tagNumber < 0){ //Do not plot when testing quickly + plotAngular(hctlctk,hctlctk_moments,opts->write_eps,"ctlctkeff",binno+appendix, + sregion.str(), tex, subfolder); + plotAngular(hctlphi,hctlphi_moments,opts->write_eps,"ctlphieff",binno+appendix, + sregion.str(), tex, subfolder); + plotAngular(hctkphi,hctkphi_moments,opts->write_eps,"ctkphieff",binno+appendix, + sregion.str(), tex, subfolder); + } + + delete hctl; delete hctl_moments; + delete hctk; delete hctk_moments; + delete hphi; delete hphi_moments; + delete hctlctk; delete hctlctk_moments; + delete hctkphi; delete hctkphi_moments; + delete hctlphi; delete hctlphi_moments; + + }//end extra plots in bins of q2 + + //data histograms + TH1D* hq2 = new TH1D("hq2" , ";q^{2} [GeV^{2}];" , nBinsQ2 ,edges.q2min, edges.q2max); + TH1D* hctl = new TH1D("hctl", ";cos(#Theta_{L});", nBinsAngles, edges.ctlmin, edges.ctlmax); + TH1D* hctk = new TH1D("hctk", ";cos(#Theta_{K});", nBinsAngles, edges.ctkmin, edges.ctkmax); + TH1D* hphi = new TH1D("hphi", ";#phi [rad];" , nBinsAngles, edges.phimin, edges.phimax); + TH2D* hctlctk = new TH2D("hctlctk", ";cos#Theta_{L};cos#Theta_{K}", nBinsAngles, edges.ctlmin, edges.ctlmax, nBinsAngles, edges.ctkmin, edges.ctkmax); + TH2D* hctlphi = new TH2D("hctlphi", ";cos#Theta_{L};#phi [rad]" , nBinsAngles, edges.ctlmin, edges.ctlmax, nBinsAngles, edges.phimin, edges.phimax); + TH2D* hctkphi = new TH2D("hctkphi", ";cos#Theta_{K};#phi [rad]" , nBinsAngles, edges.ctkmin, edges.ctkmax, nBinsAngles, edges.phimin, edges.phimax); + TH2D* hq2ctl = new TH2D("hq2ctl", ";q^{2};cos#Theta_{L}", nBinsQ2, edges.q2min, edges.q2max, nBinsAngles, edges.ctlmin, edges.ctlmax); + TH2D* hq2ctk = new TH2D("hq2ctk", ";q^{2};cos#Theta_{K}", nBinsQ2, edges.q2min, edges.q2max, nBinsAngles, edges.ctkmin, edges.ctkmax); + TH2D* hq2phi = new TH2D("hq2phi", ";q^{2};#phi [rad]" , nBinsQ2, edges.q2min, edges.q2max, nBinsAngles, edges.phimin, edges.phimax); + hq2->Sumw2(); + hctl->Sumw2(); + hctk->Sumw2(); + hphi->Sumw2(); + for (unsigned int i=0; iFill(meas.q2, meas.weight); + hctl->Fill(meas.costhetal, meas.weight); + hctk->Fill(meas.costhetak, meas.weight); + hphi->Fill(meas.phi, meas.weight); + + hctlctk->Fill(meas.costhetal, meas.costhetak, meas.weight); + hctlphi->Fill(meas.costhetal, meas.phi, meas.weight); + hctkphi->Fill(meas.costhetak, meas.phi, meas.weight); + hq2ctl->Fill(meas.q2, meas.costhetal, meas.weight); + hq2ctk->Fill(meas.q2, meas.costhetak, meas.weight); + hq2phi->Fill(meas.q2, meas.phi, meas.weight); + } + //fitted histograms, moments method + TH1D* hq2_moments = new TH1D("hq2_moments" , ";q^{2} [GeV^{2}];" , nBinsQ2, edges.q2min, edges.q2max); + TH1D* hctl_moments = new TH1D("hctl_moments", ";cos(#Theta_{L});", nBinsAngles, edges.ctlmin, edges.ctlmax); + TH1D* hctk_moments = new TH1D("hctk_moments", ";cos(#Theta_{K});", nBinsAngles, edges.ctkmin, edges.ctkmax); + TH1D* hphi_moments = new TH1D("hphi_moments", ";#phi [rad];" , nBinsAngles, edges.phimin, edges.phimax); + TH2D* hctlctk_moments = new TH2D("hctlctk_moments", ";cos#Theta_{L};cos#Theta_{K}", nBinsAngles, edges.ctlmin, edges.ctlmax, nBinsAngles, edges.ctkmin, edges.ctkmax); + TH2D* hctlphi_moments = new TH2D("hctlphi_moments", ";cos#Theta_{L};#phi [rad]" , nBinsAngles, edges.ctlmin, edges.ctlmax, nBinsAngles, edges.phimin, edges.phimax); + TH2D* hctkphi_moments = new TH2D("hctkphi_moments", ";cos#Theta_{K};#phi [rad]" , nBinsAngles, edges.ctkmin, edges.ctkmax, nBinsAngles, edges.phimin, edges.phimax); + TH2D* hq2ctl_moments = new TH2D("hq2ctl_moments", ";q^{2};cos#Theta_{L}", nBinsQ2, edges.q2min, edges.q2max, nBinsAngles, edges.ctlmin, edges.ctlmax); + TH2D* hq2ctk_moments = new TH2D("hq2ctk_moments", ";q^{2};cos#Theta_{K}", nBinsQ2, edges.q2min, edges.q2max, nBinsAngles, edges.ctkmin, edges.ctkmax); + TH2D* hq2phi_moments = new TH2D("hq2phi_moments", ";q^{2};#phi [rad]" , nBinsQ2, edges.q2min, edges.q2max, nBinsAngles, edges.phimin, edges.phimax); + + //1d plots + fill_moments_hist_1D(hq2_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max); + fill_moments_hist_1D(hctl_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max); + fill_moments_hist_1D(hctk_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max); + fill_moments_hist_1D(hphi_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max); + + //2d plots + fill_moments_hist_2D(hctlctk_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max); + fill_moments_hist_2D(hctlphi_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max); + fill_moments_hist_2D(hctkphi_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max); + fill_moments_hist_2D(hq2ctl_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max); + fill_moments_hist_2D(hq2ctk_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max); + fill_moments_hist_2D(hq2phi_moments,coeffs_moments,edges,npol,edges.q2min,edges.q2max); + + if(opts->only_4_1D_chi2){ + //reset globalvalues + globalvalues->chi2_4_1D = 0.0; + globalvalues->chi2_4_1D_ctk = 0.0; + globalvalues->chi2_4_1D_ctl = 0.0; + globalvalues->chi2_4_1D_phi = 0.0; + globalvalues->chi2_4_1D_q2 = 0.0; + globalvalues->ndof_4_1D = 0; + globalvalues->ndof_4_1D_ctk = 0; + globalvalues->ndof_4_1D_ctl = 0; + globalvalues->ndof_4_1D_phi = 0; + globalvalues->ndof_4_1D_q2 = 0; + + //first scale moments to match integral of event histograms + hctk_moments->Scale(hctk->Integral()/hctk_moments->Integral()); + hctl_moments->Scale(hctl->Integral()/hctl_moments->Integral()); + hphi_moments->Scale(hphi->Integral()/hphi_moments->Integral()); + hq2_moments ->Scale(hq2->Integral()/hq2_moments->Integral()); + + //get chi2 from all 4 variables + for(UInt_t b = 1; b <= nBinsAngles; b++){ + globalvalues->chi2_4_1D_ctk += sqr((hctk->GetBinContent(b) - hctk_moments->GetBinContent(b))) / fabs(hctk_moments->GetBinContent(b)); + globalvalues->chi2_4_1D_ctl += sqr((hctl->GetBinContent(b) - hctl_moments->GetBinContent(b))) / fabs(hctl_moments->GetBinContent(b)); + globalvalues->chi2_4_1D_phi += sqr((hphi->GetBinContent(b) - hphi_moments->GetBinContent(b))) / fabs(hphi_moments->GetBinContent(b)); + } + for(UInt_t b = 1; b <= nBinsQ2; b++){ + globalvalues->chi2_4_1D_q2 += sqr((hq2->GetBinContent(b) - hq2_moments->GetBinContent(b))) / fabs(hq2_moments->GetBinContent(b)); + } + //sum of all four 1D histograms + globalvalues->chi2_4_1D = globalvalues->chi2_4_1D_ctk + globalvalues->chi2_4_1D_ctl + globalvalues->chi2_4_1D_phi + globalvalues->chi2_4_1D_q2; + + //determine ndof for all angles and q2 + //NOT sure if these ndofs are 100% correct, but good enough for a relative measure + globalvalues->ndof_4_1D_ctk = nBinsAngles - (npol.ctk-1) - 1; + globalvalues->ndof_4_1D_ctl = nBinsAngles - (npol.ctl-1) - 1; + globalvalues->ndof_4_1D_phi = nBinsAngles - (npol.phi-1) - 1; + globalvalues->ndof_4_1D_q2 = nBinsQ2 - (npol.q2-1) - 1; + globalvalues->ndof_4_1D = 3*nBinsAngles + nBinsQ2 - 1 - (npol.ctk + npol.ctl + npol.phi + npol.q2 - 1); + + } + + //plot + plotAngular(hq2,hq2_moments,opts->write_eps,"q2eff",appendix, subfolder); + plotAngular(hctl,hctl_moments,opts->write_eps,"ctleff",appendix, subfolder); + plotAngular(hctk,hctk_moments,opts->write_eps,"ctkeff",appendix, subfolder); + plotAngular(hphi,hphi_moments,opts->write_eps,"phieff",appendix, subfolder); + + if (tagNumber < 0){ //do not plot when testing + plotAngular(hctlctk,hctlctk_moments,opts->write_eps,"ctlctkeff",appendix, subfolder); + plotAngular(hctlphi,hctlphi_moments,opts->write_eps,"ctlphieff",appendix, subfolder); + plotAngular(hctkphi,hctkphi_moments,opts->write_eps,"ctkphieff",appendix, subfolder); + plotAngular(hq2ctl,hq2ctl_moments,opts->write_eps,"q2ctleff",appendix, subfolder); + plotAngular(hq2ctk,hq2ctk_moments,opts->write_eps,"q2ctkeff",appendix, subfolder); + plotAngular(hq2phi,hq2phi_moments,opts->write_eps,"q2phieff",appendix, subfolder); + } + + delete hq2; delete hq2_moments; + delete hctl; delete hctl_moments; + delete hctk; delete hctk_moments; + delete hphi; delete hphi_moments; + delete hctlctk; delete hctlctk_moments; + delete hctkphi; delete hctkphi_moments; + delete hctlphi; delete hctlphi_moments; + delete hq2ctl; delete hq2ctl_moments; + delete hq2ctk; delete hq2ctk_moments; + delete hq2phi; delete hq2phi_moments; + + + hxi_moments[0]->SetMinimum(1.0); hxi_moments[0]->SetMaximum(+2.0); + hxi_moments[1]->SetMinimum(0.25); hxi_moments[1]->SetMaximum(+1.25); + hxi_moments[2]->SetMinimum(-1.0); hxi_moments[2]->SetMaximum(+0.0); + hxi_moments[3]->SetMinimum(-0.75); hxi_moments[3]->SetMaximum(+0.25); + + for (int i = 4; i<12; i++){ + hxi_moments[i]->SetMinimum(-0.5); + hxi_moments[i]->SetMaximum(+0.5); + } + + for (auto hist: hxi_moments) hist->GetYaxis()->SetTitleOffset(1.4); + + TCanvas* c10 = new TCanvas("c10", "c10", 1600, 1200); + c10->Divide(4,3); + plotAngularInOne(c10,1,hxi_moments[0],hxi_ub[0],hxi_hist[0],hxi_ml_hist[0],runMinuit,edges.q2min,edges.q2max,1.5,false); + plotAngularInOne(c10,2,hxi_moments[1],hxi_ub[1],hxi_hist[1],hxi_ml_hist[1],runMinuit,edges.q2min,edges.q2max,0.75,false); + plotAngularInOne(c10,3,hxi_moments[2],hxi_ub[2],hxi_hist[2],hxi_ml_hist[2],runMinuit,edges.q2min,edges.q2max,-0.5,false); + plotAngularInOne(c10,4,hxi_moments[3],hxi_ub[3],hxi_hist[3],hxi_ml_hist[3],runMinuit,edges.q2min,edges.q2max,-0.25,false); + for (int i = 4; i<12; i++){ + plotAngularInOne(c10,i+1,hxi_moments[i],hxi_ub[i],hxi_hist[i],hxi_ml_hist[i],runMinuit, + edges.q2min,edges.q2max,0.0,is_param_folded(i,opts)); + } + + if(opts->write_eps)c10->Print((subfolder + "/xis"+appendix+".eps").c_str(),"eps"); + + delete c10; + + spdlog::info( "end PLOTS" ); + + }//end make plots + + //delete histograms + for (auto hist: hxi_moments) delete hist; + for (auto hist: hxi_ml_hist) delete hist; + for (auto hist: hxi_hist) delete hist; + for (auto hist: hxi_ub) delete hist; + + +}; //end parametrize_eff_phsp_4d() + +double bu2kstarmumu_pdf::get_ang_eff(fcnc::options *opts, + double q2, double ctl, double ctk, double phi) const{ + npolynom npol(opts); + assert(coeffs_eff_4d.size() == npol.getSize()); + + //Posibly can be faster, but with more memory consumption and unless I calculate this for like a million events it doesn't make a difference. This way the code is readable and usable at many places + double eff = 0.0; + + for(unsigned int h = 0; hopts); + + std::vector chebyshev_costhetal(npol.ctl, 0.0); + std::vector chebyshev_costhetak(npol.ctk, 0.0); + std::vector chebyshev_phi(npol.phi, 0.0); + + for (unsigned int j = 0; j coeffs_costhetal(npol.ctl, 0.0); + std::vector coeffs_costhetak(npol.ctk, 0.0); + std::vector coeffs_phi(npol.phi, 0.0); + + std::vector temp_ctl(npol.ctl, 0.0); + std::vector temp_ctk(npol.ctk, 0.0); + std::vector temp_phi(npol.phi, 0.0); + + chebyshev_to_poly(chebyshev_costhetal, temp_ctl); + chebyshev_to_poly(chebyshev_costhetak, temp_ctk); + chebyshev_to_poly(chebyshev_phi, temp_phi); + + for (unsigned int i=0; iopts->full_angular)c *= 2.0; //folding in phi + + if (current_pdf->opts->full_angular) + { + for (unsigned int i = 0; i ch_costhetal; + std::vector ch_costhetak; + std::vector ch_phi; + double lh_costhetal = 0.0; + double lh_costhetak = 0.0; + double lh_phi = 0.0; + unsigned int nsize = current_pdf->eff_events.size(); + for (unsigned int i=0; ieff_events.at(i); + chebyshev(meas.costhetal, npol.ctl, ch_costhetal); + chebyshev(meas.costhetak, npol.ctk, ch_costhetak); + + if (current_pdf->opts->full_angular) + chebyshev(meas.phi/MY_PI, npol.phi, ch_phi); + else + chebyshev(2.0*meas.phi/MY_PI-1.0, npol.phi, ch_phi); + //double result = 0.0; + double result_costhetal = 0.0; + for (unsigned int j = 0; jeff_params->J1s(); + const double j1c = current_pdf->eff_params->J1c(); + const double j2s = current_pdf->eff_params->J2s(); + const double j2c = current_pdf->eff_params->J2c(); + const double j3 = current_pdf->eff_params->J3(); + const double j4 = current_pdf->eff_params->J4(); + const double j5 = current_pdf->eff_params->J5(); + const double j6s = current_pdf->eff_params->J6s(); + const double j6c = current_pdf->eff_params->J6c(); + const double j7 = current_pdf->eff_params->J7(); + const double j8 = current_pdf->eff_params->J8(); + const double j9 = current_pdf->eff_params->J9(); + + double sig_norm = 0.0; + sig_norm = (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9); + double lh_sig = 0.0, prob = 0.0; + + for (unsigned int i=0; ieff_events.at(i); + if (current_pdf->opts->full_angular) + { + current_pdf->fj(meas.costhetal, meas.costhetak, meas.phi, + f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12); + prob = (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9)/sig_norm; + } + else + { + current_pdf->folded_fj(meas.costhetal, meas.costhetak, meas.phi, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12); + /* + prob = 9.0/16.0/MY_PI * (fl * f1 + +ft * f2 + +s3 * f3 + +afb * f4 + +aim * f5 + )/sig_norm; + */ + prob = (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9)/sig_norm; + } + lh_sig += -2.0*TMath::Log(prob); + } + //is the integral correct here? + //need to do a nice integration over pdf_sig(costhetal,costhetak,phi)*eps(costhetal,costhetak,phi) + lh = lh_sig + lh_costhetal + lh_costhetak + lh_phi; +}; + +//this does not assume factorisation of the three dependencies, but assumes phsp MC in 3D +void bu2kstarmumu_pdf::eff_fcn_phsp(Int_t &npar, Double_t *grad, Double_t &lh, Double_t *params, Int_t iflag) +{ + //TODO + unsigned int ncosthetal = 5; + unsigned int ncosthetak = 5; + unsigned int nphi = 5; + + //make sure we are doing full angular acceptance, no phi folding + assert(current_pdf->opts->full_angular); + + //need to account for the norm given the current parameters + double norm = 0.0; + for (unsigned int i = 0; ieff_events.size(); + //loop over all events + for (unsigned int l=0; leff_events.at(l); + std::vector ch_costhetal; + std::vector ch_costhetak; + std::vector ch_phi; + chebyshev(meas.costhetal, ncosthetal, ch_costhetal); + chebyshev(meas.costhetak, ncosthetak, ch_costhetak); + chebyshev(meas.phi/MY_PI, nphi, ch_phi); + + double result = 0.0; + for (unsigned int i = 0; i 0.0 && !std::isnan(result) && !std::isinf(result)) + lh += -2.0*TMath::Log(result/norm) - (-2.0*TMath::Log(1.0/8.0));//can subtract + else + lh += (-100.0*2.0*TMath::Log(1.0/8.0)); + } + spdlog::debug( "eff_fcn_phsp lh {0:f}\t npar {1:d}\tiflag {2:d}\tnorm {3:f}", lh, npar, iflag, norm); +}; + +void bu2kstarmumu_pdf::eff_fcn_phsp_4d(Int_t &npar, Double_t *grad, Double_t &lh, Double_t *params, Int_t iflag) +{ + npolynom npol(current_pdf->opts); + + double q2min = current_pdf->opts->TheQ2binsmin.front(), q2max = current_pdf->opts->TheQ2binsmax.back(); + double ctkmin = current_pdf->opts->ctk_min, ctkmax = current_pdf->opts->ctk_max; + double ctlmin = current_pdf->opts->ctl_min, ctlmax = current_pdf->opts->ctl_max; + double phimin = current_pdf->opts->phi_min, phimax = current_pdf->opts->phi_max; + + spdlog::warn("The TMinuit version was not yet tested for folded analysis!"); + assert(current_pdf->opts->full_angular); + + //need to account for the norm given the current parameters + double norm = 0.0; + for (unsigned int h = 0; heff_events.size(); + //loop over all events + for (unsigned int l=0; leff_events.at(l); + if (meas.q2 < q2min || meas.q2 > q2max) continue; + + std::vector ch_q2; + std::vector ch_costhetal; + std::vector ch_costhetak; + std::vector ch_phi; + chebyshev(2.0*(meas.q2 - q2min ) / (q2max - q2min ) - 1.0, npol.q2, ch_q2); + chebyshev(2.0*(meas.costhetal - ctlmin) / (ctlmax - ctlmin) - 1.0, npol.ctl, ch_costhetal); + chebyshev(2.0*(meas.costhetak - ctkmin) / (ctkmax - ctkmin) - 1.0, npol.ctk, ch_costhetak); + chebyshev(2.0*(meas.phi - phimin) / (phimax - phimin) - 1.0, npol.phi, ch_phi); + /* + chebyshev(meas.costhetal, ncosthetal, ch_costhetal); + chebyshev(meas.costhetak, ncosthetak, ch_costhetak); + chebyshev(meas.phi/pi, nphi, ch_phi); +*/ + double result = 0.0; + for (unsigned int h = 0; h 0.0 && !std::isnan(result) && !std::isinf(result)){ + lh += -2.0*meas.weight*TMath::Log(result/norm) - (-2.0*TMath::Log(1.0/16.0)); + } + else{ + lh += (-100.0*2.0*TMath::Log(1.0/8.0)); + } + } + + spdlog::debug( "eff_fcn_phsp_4d lh {0:f}\t npar {1:d}\tiflag {2:d}\tnorm {3:f}", lh, npar, iflag, norm); +}; + +void bu2kstarmumu_pdf::update_cached_normalization(const bu2kstarmumu_parameters* params) +{ + spdlog::trace("updating cached normalisation"); + //this caches the overall normalisation for both signal and background + double q2 = params->eff_q2(); + //swave norm + if (opts->use_mkpi || opts->fit_mkpi){ + double mkpi_min = opts->mkpi_min/1.0e+3; + double mkpi_max = opts->mkpi_max/1.0e+3; + //double q2 = params->eff_q2(); + double asphase = params->asphase(); + double a = params->a(); + double r = params->r(); + double gammakstar = params->gammakstar(); + double mkstar = params->mkstar(); + double gammakstarplus = params->gammakstarplus(); + double mkstarplus = params->mkstarplus(); + double R = params->R(); + + double gammaf800 = params->gammaf800(); + double mf800 = params->mf800(); + double f800mag = params->f800mag(); + double f800phase = params->f800phase(); + //integrate over mkpi2 + const double mk = PDGMASS_KST_KAON/1.0e+3; + const double mpi = PDGMASS_KST_PION/1.0e+3; + const double mb = PDGMASS_B/1.0e+3; + const double from = opts->mkpi_full_range_norm ? (mk+mpi) : mkpi_min; + const double to = opts->mkpi_full_range_norm ? mb : mkpi_max; + std::complex mkpi_swavepwave_norm; + if (opts->simple_mkpi){ + mkpi_swave_2_norm = int_mkpi_simple_kstarzero_amp_squared(from, to, q2, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus); + mkpi_pwave_2_norm = int_mkpi_simple_bw_kstar_amp_squared(from, to, q2, gammakstar, mkstar); + mkpi_swavepwave_norm = int_mkpi_simple_bw_kstar_amp_bar_kstarzero_amp(from, to, q2, + gammakstar, mkstar, asphase, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus); + mkpi_re_swavepwave_norm = mkpi_swavepwave_norm.real(); + mkpi_im_swavepwave_norm = mkpi_swavepwave_norm.imag(); + } + else if (opts->isobar){ + mkpi_swave_2_norm = int_mkpi_kstarzero_isobar_amp_squared(from, to, q2, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus, R); + mkpi_pwave_2_norm = int_mkpi_bw_kstar_amp_squared(from, to, q2, gammakstar, mkstar, R); + mkpi_swavepwave_norm = int_mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(from, to, q2, + gammakstar, mkstar, asphase, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus, R); + mkpi_re_swavepwave_norm = mkpi_swavepwave_norm.real(); + mkpi_im_swavepwave_norm = mkpi_swavepwave_norm.imag(); + } + else{//nominal lass + mkpi_swave_2_norm = int_mkpi_kstarzero_lass_amp_squared(from, to, q2, asphase, a, r, gammakstarplus, mkstarplus, R); + mkpi_pwave_2_norm = int_mkpi_bw_kstar_amp_squared(from, to, q2, gammakstar, mkstar, R); + mkpi_swavepwave_norm = int_mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(from, to, q2, + gammakstar, mkstar, + asphase, a, r, gammakstarplus, mkstarplus, R); + mkpi_re_swavepwave_norm = mkpi_swavepwave_norm.real(); + mkpi_im_swavepwave_norm = mkpi_swavepwave_norm.imag(); + } + + if (opts->use_p2){ + //mkpi_bkg( + std::vector ch_p2(5, 0.0); + ch_p2.at(0) = params->cbkgp20(); + ch_p2.at(1) = params->cbkgp21(); + ch_p2.at(2) = params->cbkgp22(); + ch_p2.at(3) = params->cbkgp23(); + ch_p2.at(4) = params->cbkgp24(); + std::vector poly_p2(ch_p2.size(), 0.0); + chebyshev_to_poly(ch_p2, poly_p2); + std::vector poly_corr_p2(ch_p2.size(), 0.0); + correct_poly(poly_p2, poly_corr_p2, mkpi_min*mkpi_min, mkpi_max*mkpi_max); + + mkpi_bkg_norm = 0.0; + for (unsigned int i=0; i ch_mkpi(5, 0.0); + ch_mkpi.at(0) = params->cbkgmkpi0(); + ch_mkpi.at(1) = params->cbkgmkpi1(); + ch_mkpi.at(2) = params->cbkgmkpi2(); + ch_mkpi.at(3) = params->cbkgmkpi3(); + ch_mkpi.at(4) = params->cbkgmkpi4(); + std::vector poly_mkpi(ch_mkpi.size(), 0.0); + chebyshev_to_poly(ch_mkpi, poly_mkpi); + std::vector poly_corr_mkpi(ch_mkpi.size(), 0.0); + correct_poly(poly_mkpi, poly_corr_mkpi, mkpi_min, mkpi_max); + + mkpi_bkg_norm = 0.0; + if (opts->mkpi_threshold){ + mkpi_bkg_norm = fcnc::int_threshold(mkpi_min, mkpi_max, 0.633, params->nthreshold()); + } + else{ + for(unsigned int i=0; iJ1s(); + const double j1c = params->J1c(); + const double j2s = params->J2s(); + const double j2c = params->J2c(); + const double j3 = params->J3(); + const double j4 = params->J4(); + const double j5 = params->J5(); + const double j6s = params->J6s(); + const double j6c = params->J6c(); + const double j7 = params->J7(); + const double j8 = params->J8(); + const double j9 = params->J9(); + + const double fs = params->FS(); + const double js1 = params->SS1(); + const double js2 = params->SS2(); + const double js3 = params->SS3(); + const double js4 = params->SS4(); + const double js5 = params->SS5(); + + if(spdlog_trace()){ //print out the integrated angular moments. with and without weights, as well as their ratios + + load_coeffs_eff_phsp_4d(); + + integrated_fj_chebyshev(f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12, q2); + double pwave_weighted = (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9); + + integrated_fj_noacc(f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12); + double pwave_noweights = (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9); + + swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2); + + swave_integrated_fj_noacc(fs1, fs2, fs3, fs4, fs5, fs6); + + spdlog::trace("Integrated P-wave:"); + spdlog::trace("P-wave no weights: {0:0.5f}",pwave_noweights); + spdlog::trace("P-wave weighted: {0:0.5f}",pwave_weighted); + spdlog::trace("P-wave ratio: {0:0.5f}\n",pwave_weighted / pwave_noweights); + + if (opts->swave){ + double swave_noweights = (fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5); + double swave_weighted = (fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5); + spdlog::trace("Integrated S-wave:"); + spdlog::trace("S-wave weighted: {0:0.5f}{0:0.5f}",swave_weighted); + spdlog::trace("S-wave no weights: {0:0.5f}",swave_noweights); + spdlog::trace("S-wave ratio: {0:0.5f}\n",swave_weighted / swave_noweights); + spdlog::trace("Double ratio (s/p):{0:0.5f}",(swave_weighted / swave_noweights) / (pwave_weighted / pwave_noweights)); + } + + //assert(0); + + } + + if(opts->full_angular){ + if(!opts->cache_fis){ + if(opts->use_angular_acc){ + integrated_fj_chebyshev(f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12, q2); + } + else{//this is also what the weighted fit uses! + integrated_fj_noacc(f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12); + } + fbuffer_f1 = f1; + fbuffer_f2 = f2; + fbuffer_f3 = f3; + fbuffer_f4 = f4; + fbuffer_f5 = f5; + fbuffer_f6 = f6; + fbuffer_f7 = f7; + fbuffer_f8 = f8; + fbuffer_f9 = f9; + fbuffer_f10 = f10; + fbuffer_f11 = f11; + fbuffer_f12 = f12; + } + else{ + f1 = fbuffer_f1; + f2 = fbuffer_f2; + f3 = fbuffer_f3; + f4 = fbuffer_f4; + f5 = fbuffer_f5; + f6 = fbuffer_f6; + f7 = fbuffer_f7; + f8 = fbuffer_f8; + f9 = fbuffer_f9; + f10 = fbuffer_f10; + f11 = fbuffer_f11; + f12 = fbuffer_f12; + } + fnorm_sig = (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9); + if (opts->fit_asymmetries){ + fnorm_sig = (f1*j1s + f2*j1c + f3*j2s + f4*j2c); + } + + bool swave = opts->swave; + if (swave){ + if (!opts->cache_fis){ + if (opts->use_angular_acc){ + swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2); + } + else{//weighted fit and fit without acceptance + swave_integrated_fj_noacc(fs1, fs2, fs3, fs4, fs5, fs6); + } + + fbuffer_fs1 = fs1; + fbuffer_fs2 = fs2; + fbuffer_fs3 = fs3; + fbuffer_fs4 = fs4; + fbuffer_fs5 = fs5; + fbuffer_fs6 = fs6; + } + else{ + fs1 = fbuffer_fs1; + fs2 = fbuffer_fs2; + fs3 = fbuffer_fs3; + fs4 = fbuffer_fs4; + fs5 = fbuffer_fs5; + fs6 = fbuffer_fs6; + } + fnorm_sig = (1.0-fs) * (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9) + + (fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5); + if (opts->fit_asymmetries){ + fnorm_sig = (1.0-fs)*(f1*j1s + f2*j1c + f3*j2s + f4*j2c) + + (fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5); + } + } + + spdlog::trace("Fnormsig (full_angular) {0:f}",fnorm_sig ); + spdlog::trace("Normalization integrals P-wave"); + spdlog::trace("\tj1s {0:0.4f}",f1/fnorm_sig); + spdlog::trace("\tj1c {0:0.4f}",f2/fnorm_sig); + spdlog::trace("\tj2s {0:0.4f}",f3/fnorm_sig); + spdlog::trace("\tj2c {0:0.4f}",f4/fnorm_sig); + spdlog::trace("\tj3 {0:0.4f}",f5/fnorm_sig); + spdlog::trace("\tj4 {0:0.4f}",f6/fnorm_sig); + spdlog::trace("\tj5 {0:0.4f}",f7/fnorm_sig); + spdlog::trace("\tj6s {0:0.4f}",f8/fnorm_sig); + spdlog::trace("\tj6c {0:0.4f}",f9/fnorm_sig); + spdlog::trace("\tj7 {0:0.4f}",f10/fnorm_sig); + spdlog::trace("\tj8 {0:0.4f}",f11/fnorm_sig); + spdlog::trace("\tj9 {0:0.4f}",f12/fnorm_sig); + if(opts->swave){ + spdlog::trace("Normalization integrals S-wave"); + spdlog::trace("fs {0:0.4f}",fs1/fnorm_sig); + spdlog::trace("\tas1 {0:0.4f}",fs2/fnorm_sig); + spdlog::trace("\tas2 {0:0.4f}",fs3/fnorm_sig); + spdlog::trace("\tas3 {0:0.4f}",fs4/fnorm_sig); + spdlog::trace("\tas4 {0:0.4f}",fs5/fnorm_sig); + spdlog::trace("\tas5 {0:0.4f}",fs6/fnorm_sig); + } + + spdlog::trace("Angular amplitudes: "); + spdlog::trace("\tj1s {0:0.4f}",j1s); + spdlog::trace("\tj1c {0:0.4f}",j1c); + spdlog::trace("\tj2s {0:0.4f}",j2s); + spdlog::trace("\tj2c {0:0.4f}",j2c); + spdlog::trace("\tj3 {0:0.4f}",j3); + spdlog::trace("\tj4 {0:0.4f}",j4); + spdlog::trace("\tj5 {0:0.4f}",j5); + spdlog::trace("\tj6s {0:0.4f}",j6s); + spdlog::trace("\tj6c {0:0.4f}",j6c); + spdlog::trace("\tj7 {0:0.4f}",j7); + spdlog::trace("\tj8 {0:0.4f}",j8); + spdlog::trace("\tj9 {0:0.4f}",j9); + + } + else //folded normalization! + { + if (!opts->cache_fis) { + if (opts->use_angular_acc){ + folded_integrated_fj_chebyshev(f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12, q2); + } + else{//this is also what the weighted fit uses! + folded_integrated_fj_noacc(f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12); + } + fbuffer_f1 = f1; + fbuffer_f2 = f2; + fbuffer_f3 = f3; + fbuffer_f4 = f4; + fbuffer_f5 = f5; + fbuffer_f6 = f6; + fbuffer_f7 = f7; + fbuffer_f8 = f8; + fbuffer_f9 = f9; + fbuffer_f10 = f10; + fbuffer_f11 = f11; + fbuffer_f12 = f12; + } + else{ + f1 = fbuffer_f1; + f2 = fbuffer_f2; + f3 = fbuffer_f3; + f4 = fbuffer_f4; + f5 = fbuffer_f5; + f6 = fbuffer_f6; + f7 = fbuffer_f7; + f8 = fbuffer_f8; + f9 = fbuffer_f9; + f10 = fbuffer_f10; + f11 = fbuffer_f11; + f12 = fbuffer_f12; + } + + fnorm_sig = (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9); + if (opts->fit_asymmetries){ + fnorm_sig = (f1*j1s + f2*j1c + f3*j2s + f4*j2c); + } + bool swave = opts->swave; + if (swave){ + if (!opts->cache_fis) { + if (opts->use_angular_acc ){ + folded_swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2); + } + else{//weighted fit and fit without acceptance + folded_swave_integrated_fj_noacc(fs1, fs2, fs3, fs4, fs5, fs6); + } + + fbuffer_fs1 = fs1; + fbuffer_fs2 = fs2; + fbuffer_fs3 = fs3; + fbuffer_fs4 = fs4; + fbuffer_fs5 = fs5; + fbuffer_fs6 = fs6; + } + else { + fs1 = fbuffer_fs1; + fs2 = fbuffer_fs2; + fs3 = fbuffer_fs3; + fs4 = fbuffer_fs4; + fs5 = fbuffer_fs5; + fs6 = fbuffer_fs6; + } + fnorm_sig = (1-fs) * (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9) + + (fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5); + if (opts->fit_asymmetries) + fnorm_sig = (1-fs)*(f1*j1s + f2*j1c + f3*j2s + f4*j2c) + +(fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5); + } + + spdlog::trace("Fnormsig (folding {0:d}) {1:f}", opts->folding, fnorm_sig ); + spdlog::trace("Normalization integrals P-wave"); + spdlog::trace("\tj1s {0:0.4f}",f1/fnorm_sig); + spdlog::trace("\tj1c {0:0.4f}",f2/fnorm_sig); + spdlog::trace("\tj2s {0:0.4f}",f3/fnorm_sig); + spdlog::trace("\tj2c {0:0.4f}",f4/fnorm_sig); + spdlog::trace("\tj3 {0:0.4f}",f5/fnorm_sig); + spdlog::trace("\tj4 {0:0.4f}",f6/fnorm_sig); + spdlog::trace("\tj5 {0:0.4f}",f7/fnorm_sig); + spdlog::trace("\tj6s {0:0.4f}",f8/fnorm_sig); + spdlog::trace("\tj6c {0:0.4f}",f9/fnorm_sig); + spdlog::trace("\tj7 {0:0.4f}",f10/fnorm_sig); + spdlog::trace("\tj8 {0:0.4f}",f11/fnorm_sig); + spdlog::trace("\tj9 {0:0.4f}",f12/fnorm_sig); + + if(opts->swave){ + spdlog::trace("Normalization integrals S-wave"); + spdlog::trace("fs {0:0.4f}",fs1/fnorm_sig); + spdlog::trace("\tas1 {0:0.4f}",fs2/fnorm_sig); + spdlog::trace("\tas2 {0:0.4f}",fs3/fnorm_sig); + spdlog::trace("\tas3 {0:0.4f}",fs4/fnorm_sig); + spdlog::trace("\tas4 {0:0.4f}",fs5/fnorm_sig); + spdlog::trace("\tas5 {0:0.4f}",fs6/fnorm_sig); + } + + spdlog::trace("Angular amplitudes: "); + spdlog::trace("\tj1s {0:0.4f}",j1s); + spdlog::trace("\tj1c {0:0.4f}",j1c); + spdlog::trace("\tj2s {0:0.4f}",j2s); + spdlog::trace("\tj2c {0:0.4f}",j2c); + spdlog::trace("\tj3 {0:0.4f}",j3); + spdlog::trace("\tj4 {0:0.4f}",j4); + spdlog::trace("\tj5 {0:0.4f}",j5); + spdlog::trace("\tj6s {0:0.4f}",j6s); + spdlog::trace("\tj6c {0:0.4f}",j6c); + spdlog::trace("\tj7 {0:0.4f}",j7); + spdlog::trace("\tj8 {0:0.4f}",j8); + spdlog::trace("\tj9 {0:0.4f}",j9); + + + } + + //bkg norm + //this is used to convolute the acceptance into the pdf + if(opts->use_angular_acc && opts->use_weighted_bkg){ //weighted background pdf + if (opts->full_angular){ + fnorm_bkg = integral_bkg_chebyshev(params, CTL_MIN, CTL_MAX, CTK_MIN, CTK_MAX, PHI_MIN, PHI_MAX, q2); + } + else if(opts->fit_full_angular_bkg){ + + fnorm_bkg = integral_bkg_chebyshev(params, CTL_MIN, CTL_MAX, opts->ctk_min, opts->ctk_max, PHI_MIN, PHI_MAX, q2); //TODO: check here whether this makes any sense (https://gitlab.cern.ch/LHCb-RD/ewp-Bplus2Kstmumu-AngAna/-/merge_requests/21) + } + else{ + fnorm_bkg = integral_bkg_chebyshev(params, opts->ctl_min, opts->ctl_max, opts->ctk_min, opts->ctk_max, opts->phi_min, opts->phi_max, q2); + } + } + else{ //non weighted background pdf + if (opts->full_angular){ + if (opts->flat_bkg) fnorm_bkg = RANGE_3D(); + else fnorm_bkg = integral_bkg(params, opts->ctl_min, opts->ctl_max, + opts->ctk_min, opts->ctk_max, + opts->phi_min, opts->phi_max); + } + else{ //folded angles + if (opts->flat_bkg){ + fnorm_bkg = (opts->ctk_max - opts->ctk_min) * (opts->ctl_max - opts->ctl_min) * (opts->phi_max - opts->phi_min); + } + else{ + if(opts->fit_full_angular_bkg){ + fnorm_bkg = integral_bkg(params, CTL_MIN, CTL_MAX, CTK_MIN, CTK_MAX, PHI_MIN, PHI_MAX); + } + else{ + fnorm_bkg = integral_bkg(params, opts->ctl_min, opts->ctl_max, opts->ctk_min, opts->ctk_max, opts->phi_min, opts->phi_max); + } + } + } + } +} + +void bu2kstarmumu_pdf::update_cached_integrated_fis(const bu2kstarmumu_parameters* params) +{ + if(opts->cache_fis){ + double q2 = params->eff_q2(); + if(opts->full_angular){ + if(opts->use_angular_acc){ + integrated_fj_chebyshev(fbuffer_f1, fbuffer_f2, fbuffer_f3, fbuffer_f4, fbuffer_f5, fbuffer_f6, + fbuffer_f7, fbuffer_f8, fbuffer_f9, fbuffer_f10, fbuffer_f11, fbuffer_f12, q2); + swave_integrated_fj_chebyshev(fbuffer_fs1, fbuffer_fs2, fbuffer_fs3, fbuffer_fs4, fbuffer_fs5, fbuffer_fs6, q2); + } + else{//this is also what the weighted fit uses! + integrated_fj_noacc(fbuffer_f1, fbuffer_f2, fbuffer_f3, fbuffer_f4, fbuffer_f5, fbuffer_f6, + fbuffer_f7, fbuffer_f8, fbuffer_f9, fbuffer_f10, fbuffer_f11, fbuffer_f12); + swave_integrated_fj_noacc(fbuffer_fs1, fbuffer_fs2, fbuffer_fs3, fbuffer_fs4, fbuffer_fs5, fbuffer_fs6); + } + } + else{ //folded + if(opts->use_angular_acc){ + folded_integrated_fj_chebyshev(fbuffer_f1, fbuffer_f2, fbuffer_f3, fbuffer_f4, fbuffer_f5, fbuffer_f6, + fbuffer_f7, fbuffer_f8, fbuffer_f9, fbuffer_f10, fbuffer_f11, fbuffer_f12, q2); + folded_swave_integrated_fj_chebyshev(fbuffer_fs1, fbuffer_fs2, fbuffer_fs3, fbuffer_fs4, fbuffer_fs5, fbuffer_fs6, q2); + } + else{//this is also what the weighted fit uses! + folded_integrated_fj_noacc(fbuffer_f1, fbuffer_f2, fbuffer_f3, fbuffer_f4, fbuffer_f5, fbuffer_f6, + fbuffer_f7, fbuffer_f8, fbuffer_f9, fbuffer_f10, fbuffer_f11, fbuffer_f12); + folded_swave_integrated_fj_noacc(fbuffer_fs1, fbuffer_fs2, fbuffer_fs3, fbuffer_fs4, fbuffer_fs5, fbuffer_fs6); + } + } + } +} + +double bu2kstarmumu_pdf::mkpi_pwave_2(const bu2kstarmumu_parameters* params, const event& meas) const +{ + double mkpi = meas.mkpi/1.0e+3; + double q2 = params->eff_q2(); + //if (opts->weighted_fit) TODO + // q2 = meas.q2; + double gammakstar = params->gammakstar(); + double mkstar = params->mkstar(); + double R = params->R(); + if (opts->simple_mkpi) return mkpi_simple_bw_kstar_amp_squared(mkpi, q2, gammakstar, mkstar); + else return mkpi_bw_kstar_amp_squared(mkpi, q2, gammakstar, mkstar, R); +} + +double bu2kstarmumu_pdf::mkpi_swave_2(const bu2kstarmumu_parameters* params, const event& meas) const +{ + double mkpi = meas.mkpi/1.0e+3; + double q2 = params->eff_q2(); + //if (opts->weighted_fit) TODO + // q2 = meas.q2; + double asphase = params->asphase(); + double a = params->a(); + double r = params->r(); + double R = params->R(); + double gammakstarplus = params->gammakstarplus(); + double mkstarplus = params->mkstarplus(); + + double gammaf800 = params->gammaf800(); + double mf800 = params->mf800(); + double f800mag = params->f800mag(); + double f800phase = params->f800phase(); + if (opts->simple_mkpi){ + return mkpi_simple_kstarzero_amp_squared(mkpi, q2, + f800mag, f800phase, gammaf800, mf800, + gammakstarplus, mkstarplus); + } + else if (opts->isobar){ + return mkpi_kstarzero_isobar_amp_squared(mkpi, q2, + f800mag, f800phase, gammaf800, mf800, + gammakstarplus, mkstarplus, R); + } + else{//LASS + return mkpi_kstarzero_lass_amp_squared(mkpi, q2, asphase, a, r, gammakstarplus, mkstarplus, R); + } +} + +double bu2kstarmumu_pdf::mkpi_re_swavepwave(const bu2kstarmumu_parameters* params, const event& meas) const +{ + double mkpi = meas.mkpi/1.0e+3; + double q2 = params->eff_q2(); + // if (opts->weighted_fit) //TODO + // q2 = meas.q2; + double gammakstar = params->gammakstar(); + double mkstar = params->mkstar(); + double asphase = params->asphase(); + double a = params->a(); + double r = params->r(); + double gammakstarplus = params->gammakstarplus(); + double mkstarplus = params->mkstarplus(); + double R = params->R(); + + double gammaf800 = params->gammaf800(); + double mf800 = params->mf800(); + double f800mag = params->f800mag(); + double f800phase = params->f800phase(); + + std::complex swavepwave; + if (opts->simple_mkpi){ + swavepwave = mkpi_simple_bw_kstar_amp_bar_kstarzero_amp(mkpi, q2, + gammakstar, mkstar, asphase, + f800mag, f800phase, gammaf800, mf800, + gammakstarplus, mkstarplus); + } + else if (opts->isobar){ + swavepwave = mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(mkpi, q2, + gammakstar, mkstar, asphase, + f800mag, f800phase, gammaf800, mf800, + gammakstarplus, mkstarplus, R); + } + else{//LASS + swavepwave = mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(mkpi, q2, gammakstar, mkstar, asphase, + a, r, gammakstarplus, mkstarplus, R); + } + return swavepwave.real(); +} + +double bu2kstarmumu_pdf::mkpi_im_swavepwave(const bu2kstarmumu_parameters* params, const event& meas) const +{ + double mkpi = meas.mkpi/1.0e+3; + double q2 = params->eff_q2(); + //if (opts->weighted_fit) //TODO + // q2 = meas.q2; + double gammakstar = params->gammakstar(); + double mkstar = params->mkstar(); + double asphase = params->asphase(); + double a = params->a(); + double r = params->r(); + double gammakstarplus = params->gammakstarplus(); + double mkstarplus = params->mkstarplus(); + double R = params->R(); + + double gammaf800 = params->gammaf800(); + double mf800 = params->mf800(); + double f800mag = params->f800mag(); + double f800phase = params->f800phase(); + + std::complex swavepwave; + if (opts->simple_mkpi){ + swavepwave = mkpi_simple_bw_kstar_amp_bar_kstarzero_amp(mkpi, q2, + gammakstar, mkstar, asphase, + f800mag, f800phase, gammaf800, mf800, + gammakstarplus, mkstarplus); + } + else if (opts->isobar){ + swavepwave = mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(mkpi, q2, + gammakstar, mkstar, asphase, + f800mag, f800phase, gammaf800, mf800, + gammakstarplus, mkstarplus, R); + } + else{//LASS + swavepwave = mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(mkpi, q2, gammakstar, mkstar, asphase, + a, r, gammakstarplus, mkstarplus, R); + } + + return swavepwave.imag(); +} + +double bu2kstarmumu_pdf::mkpi_bkg(const bu2kstarmumu_parameters* params, const event& meas) const +{ + double mkpi = meas.mkpi/1.0e+3; + double mkpi_min = opts->mkpi_min/1.0e+3; + double mkpi_max = opts->mkpi_max/1.0e+3; + double probbkg = 0.0; + if (opts->use_p2) { + std::vector ch_p2(5, 0.0); + ch_p2.at(0) = params->cbkgp20(); + ch_p2.at(1) = params->cbkgp21(); + ch_p2.at(2) = params->cbkgp22(); + ch_p2.at(3) = params->cbkgp23(); + ch_p2.at(4) = params->cbkgp24(); + std::vector poly_p2(ch_p2.size(), 0.0); + chebyshev_to_poly(ch_p2, poly_p2); + std::vector poly_corr_p2(ch_p2.size(), 0.0); + correct_poly(poly_p2, poly_corr_p2, mkpi_min*mkpi_min, mkpi_max*mkpi_max); + + for (unsigned int i=0; i ch_mkpi(5, 0.0); + ch_mkpi.at(0) = params->cbkgmkpi0(); + ch_mkpi.at(1) = params->cbkgmkpi1(); + ch_mkpi.at(2) = params->cbkgmkpi2(); + ch_mkpi.at(3) = params->cbkgmkpi3(); + ch_mkpi.at(4) = params->cbkgmkpi4(); + std::vector poly_mkpi(ch_mkpi.size(), 0.0); + chebyshev_to_poly(ch_mkpi, poly_mkpi); + std::vector poly_corr_mkpi(ch_mkpi.size(), 0.0); + correct_poly(poly_mkpi, poly_corr_mkpi, mkpi_min, mkpi_max); + + if (opts->mkpi_threshold){ + //threshold(double x, double thr, double n); + probbkg = fcnc::threshold(mkpi, 0.633, params->nthreshold()); + } + else{ + for (unsigned int i=0; i* events) +{ + spdlog::info("Updating cached xis"); + //this is used if per_event_norm is on + //it stores the 18 xis for every event + //otherwise using a different norm per event is computationally not possible + //double q2 = params->eff_q2(); + assert(opts->use_event_norm); + /* + for (unsigned int e=0; esize(); e++) + { + if ((e*100) % events->size() == 0) + std::cout << (e*100)/events->size() << "% " << std::endl; + event& meas = events->at(e);D + double q2 = meas.q2; + double f1=0.0, f2=0.0, f3=0.0, f4=0.0, f5=0.0, f6=0.0, + f7=0.0, f8=0.0, f9=0.0, f10=0.0, f11=0.0, f12=0.0; + integrated_fj_chebyshev(f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12, q2); + meas.xis[0] = f1; + meas.xis[1] = f2; + meas.xis[2] = f3; + meas.xis[3] = f4; + meas.xis[4] = f5; + meas.xis[5] = f6; + meas.xis[6] = f7; + meas.xis[7] = f8; + meas.xis[8] = f9; + meas.xis[9] = f10; + meas.xis[10] = f11; + meas.xis[11] = f12; + bool swave = opts->swave; + if (swave) + { + double fs1=0.0, fs2=0.0, fs3=0.0, fs4=0.0, fs5=0.0, fs6=0.0; + swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2); + meas.xis[12] = fs1; + meas.xis[13] = fs2; + meas.xis[14] = fs3; + meas.xis[15] = fs4; + meas.xis[16] = fs5; + meas.xis[17] = fs6; + } + } + */ + /* + for (unsigned int e=0; esize(); e++) + { + event& meas = events->at(e); + std::cout << meas.xis[0] << " " + << meas.xis[1] << " " + << meas.xis[2] << " " + << meas.xis[3] << " " + << meas.xis[4] << " " + << meas.xis[5] << " " + << meas.xis[6] << " " + << meas.xis[7] << " " + << meas.xis[8] << " " + << meas.xis[9] << " " + << meas.xis[10] << " " + << meas.xis[11] << " " + << meas.xis[12] << " " + << meas.xis[13] << " " + << meas.xis[14] << " " + << meas.xis[15] << " " + << meas.xis[16] << " " + << meas.xis[17] << " q2 " << meas.q2 << std::endl; + } + */ + //std::cout << std::endl; +} + +void bu2kstarmumu_pdf::update_cached_normalization(const parameters* params){ + update_cached_normalization(static_cast(params)); +} + +void bu2kstarmumu_pdf::update_cached_integrated_fis(const parameters* params){ + update_cached_integrated_fis(static_cast(params)); +} + + +void bu2kstarmumu_pdf::update_cached_efficiencies(const parameters* params, std::vector* events) +{ + update_cached_efficiencies(static_cast(params), events); +} + +void bu2kstarmumu_pdf::update_cached_xis(const parameters* params, std::vector* events) +{ + update_cached_xis(static_cast(params), events); +} + + +double bu2kstarmumu_pdf::m_sig_prob(const bu2kstarmumu_parameters* params, const event& meas) const{ + if (opts->only_angles || opts->only_mkpi) return 1.0; + + double mmin=params->m_b.get_min(); + double mmax=params->m_b.get_max(); + + if(meas.m > mmax || meas.m < mmin){ + spdlog::error("m(B) outside of allowed range: mmin={0:f}, mmax={1:f} m={2:f}", mmin, mmax, meas.m); + assert(0); + } + + double result = 0.0; + if(opts->crystalball){ + result = params->m_res_1() + * crystalball(meas.m, params->m_b(), params->m_scale()*params->m_sigma_1(), params->alpha_1(), params->n_1()) + / integrate_crystalball(params->m_b(), params->m_scale()*params->m_sigma_1(), params->alpha_1(), params->n_1(), mmin, mmax); + if(params->m_res_1() != 1.0) + result += (1.0-params->m_res_1()) + * crystalball(meas.m, params->m_b(), params->m_scale()*params->m_sigma_2(), params->alpha_2(), params->n_2()) + / integrate_crystalball(params->m_b(), params->m_scale()*params->m_sigma_2(), params->alpha_2(), params->n_2(), mmin, mmax); + } + else if(opts->twotailedcrystalball){ + result = twotailedcrystalball(meas.m, params->m_b(), params->m_scale()*params->m_sigma_1(), params->alpha_1(), params->alpha_2(), params->n_1(), params->n_2()) + / integrate_twotailedcrystalball(params->m_b(), params->m_scale()*params->m_sigma_1(), params->alpha_1(), params->alpha_2(), params->n_1(), params->n_2(), mmin, mmax); + } + else{ + result = params->m_res_1() + * normed_gauss(meas.m, params->m_scale()*params->m_sigma_1(), params->m_b(), mmin, mmax); + if(params->m_res_1() != 1.0) + result += (1.0-params->m_res_1()) + * normed_gauss(meas.m, params->m_scale()*params->m_sigma_2(), params->m_b(), mmin, mmax); + } + return result; + +}; + +double bu2kstarmumu_pdf::mkpi_sig_prob(const bu2kstarmumu_parameters* params, const event& meas) const +{ + if(!opts->fit_mkpi || opts->only_angles || opts->only_Bmass) return 1.0; + + assert(meas.mkpi <= opts->mkpi_max); + assert(meas.mkpi >= opts->mkpi_min); + + double result = 0.0; + + double prob_mkpi_pwave = mkpi_pwave_2(params, meas); + double prob_mkpi_swave = mkpi_swave_2(params, meas); + double prob_mkpi_pwaveswave_re = mkpi_re_swavepwave(params, meas); + double prob_mkpi_pwaveswave_im = mkpi_im_swavepwave(params, meas); + double fs = params->FS(); + + //only m(B) and m(K*+) fitted + if(opts->only_mass2DFit){ + if(opts->swave){ + result = (1.0-fs) + * prob_mkpi_pwave/mkpi_pwave_2_norm + + fs + * prob_mkpi_swave/mkpi_swave_2_norm; + } + else{ + result = prob_mkpi_pwave/mkpi_pwave_2_norm; + } + }//end only m(B) and m(K*+) + else{//angular dimensions included in the fit + + double q2 = meas.q2; + + //integrated S_i + double xi1, xi2, xi3, xi4, xi5, xi6, xi7, xi8, xi9, xi10, xi11, xi12; + if(opts->use_angular_acc) integrated_fj_chebyshev(xi1, xi2, xi3, xi4, xi5, xi6, xi7, xi8, xi9, xi10, xi11, xi12, q2); + else integrated_fj_noacc(xi1, xi2, xi3, xi4, xi5, xi6, xi7, xi8, xi9, xi10, xi11, xi12); + + //integrated SS_i + double sxi1, sxi2, sxi3, sxi4, sxi5, sxi6; + if(opts->use_angular_acc) swave_integrated_fj_chebyshev(sxi1, sxi2, sxi3, sxi4, sxi5, sxi6, q2); + else swave_integrated_fj_noacc(sxi1, sxi2, sxi3, sxi4, sxi5, sxi6); + + //load values for required parameters: + const double s1s = params->S1s(); + const double s2s = s1s/3.0; + const double s1c = 1.0 - 4.0/3.0 * s1s; + const double s2c = -s1c; + const double s3 = params->S3(); + const double s4 = params->S4(); + const double s5 = params->S5(); + const double s6s = params->S6s(); + const double s6c = 0.; + const double s7 = params->S7(); + const double s8 = params->S8(); + const double s9 = params->S9(); + + const double ss1 = params->SS1(); + const double ss2 = params->SS2(); + const double ss3 = params->SS3(); + const double ss4 = params->SS4(); + const double ss5 = params->SS5(); + + double norm = (1 - fs) * (xi1*s1s + xi2*s1c + xi3*s2s + xi4*s2c + xi5*s3 + xi6*s4 + + xi7*s5 + xi8*s6s + xi9*s6c + xi10*s7 + xi11*s8 + xi12*s9) + + (sxi1*fs) + + (sxi2*ss1 + sxi3*ss2 + sxi4*ss3) + + (sxi5*ss4 + sxi6*ss5); + + double A = (xi1*s1s + xi2*s1c + xi3*s2s + xi4*s2c + xi5*s3 + xi6*s4 + + xi7*s5 + xi8*s6s + xi9*s6c + xi10*s7 + xi11*s8 + xi12*s9)/norm; + double B = sxi1/norm; + double C = (sxi2*ss1 + sxi3*ss2 + sxi4*ss3)/norm; + double D = (sxi5*ss4 + sxi6*ss5)/norm; + + result = (1.0-fs) * A * prob_mkpi_pwave/mkpi_pwave_2_norm + + fs * B * prob_mkpi_swave/mkpi_swave_2_norm + + C * prob_mkpi_pwaveswave_re/mkpi_re_swavepwave_norm + + D * prob_mkpi_pwaveswave_im/mkpi_im_swavepwave_norm; + }//end of prob with angular parts included + return result; +}; + +double bu2kstarmumu_pdf::integral_m_sig_prob(const bu2kstarmumu_parameters* params, double ma, double mb) const +{ + + double result = 0.0; + if (opts->crystalball){ + double mmin=params->m_b.get_min(), mmax=params->m_b.get_max(); + result = params->m_res_1()*integrate_crystalball(params->m_b(), params->m_scale()*params->m_sigma_1(), params->alpha_1(), params->n_1(), ma, mb) + / integrate_crystalball(params->m_b(), params->m_scale()*params->m_sigma_1(), params->alpha_1(), params->n_1(), mmin, mmax); + if (params->m_res_1() != 1.0) + result += (1.0-params->m_res_1()) * integrate_crystalball(params->m_b(), params->m_scale()*params->m_sigma_2(), params->alpha_2(), params->n_2(), ma, mb) + / integrate_crystalball(params->m_b(), params->m_scale()*params->m_sigma_2(), params->alpha_2(), params->n_2(), mmin, mmax); + } + else if(opts->twotailedcrystalball){ + double mmin=params->m_b.get_min(), mmax=params->m_b.get_max(); + result = integrate_twotailedcrystalball(params->m_b(), params->m_scale()*params->m_sigma_1(), params->alpha_1(), params->alpha_2(), params->n_1(), params->n_2(), ma, mb) + / integrate_twotailedcrystalball(params->m_b(), params->m_scale()*params->m_sigma_1(), params->alpha_1(), params->alpha_2(), params->n_1(), params->n_2(), mmin, mmax); + } + else{ + double mean = params->m_b(); + double min = params->m_b.get_min(); + double max = params->m_b.get_max(); + double sigma1 = params->m_scale()*params->m_sigma_1(); + double sigma2 = params->m_scale()*params->m_sigma_2(); + double fres = params->m_res_1(); + double fullrange = (fres)*1.0/2.0*(TMath::Erf((max-mean)/(sqrt(2.0)*sigma1))-TMath::Erf((min-mean)/(sqrt(2.0)*sigma1))); + if (params->m_res_1() != 1.0) + fullrange += (1.0-fres)*1.0/2.0*(TMath::Erf((max-mean)/(sqrt(2.0)*sigma2))-TMath::Erf((min-mean)/(sqrt(2.0)*sigma2))); + double integral = (fres)*1.0/2.0*(TMath::Erf((mb-mean)/(sqrt(2.0)*sigma1))-TMath::Erf((ma-mean)/(sqrt(2.0)*sigma1))); + if (params->m_res_1() != 1.0) + integral += (1.0-fres)*1.0/2.0*(TMath::Erf((mb-mean)/(sqrt(2.0)*sigma2))-TMath::Erf((ma-mean)/(sqrt(2.0)*sigma2))); + result = integral/fullrange; + } + return result; + +}; + + +double bu2kstarmumu_pdf::m_bkg_prob(const bu2kstarmumu_parameters* params, const event& meas) const +{ + if (opts->only_angles || opts->only_mkpi) return 1.0; + + double mmin=params->m_b.get_min(), mmax=params->m_b.get_max(); + assert(meas.m <= mmax); + assert(meas.m >= mmin); + + if(opts->cutsignalwindow){ + assert(meas.m <= opts->m_min || meas.m >= opts->m_max); + } + + double fm1 = params->fm_tau(); + double tau1 = params->m_tau(); + double tau2 = params->m_tau_2(); + double lambda1 = params->m_lambda(); + double lambda2 = params->m_lambda_2(); + + double result = 0.; + + if(opts->fit_lambda){ + if(lambda1 == 0.0) return 1.0; + double norm1 = 1.0/lambda1*(exp(mmax*lambda1) - exp(mmin*lambda1)); + if(opts->cutsignalwindow){ + norm1 -= 1.0/lambda1*(exp(opts->m_max*lambda1) - exp(opts->m_min*lambda1)); + } + result = exp(meas.m*lambda1)/norm1; + if (fm1 != 1.0){ + if(lambda2 == 0.0) return result; + result *= fm1; + double norm2 = 1.0/lambda2*(exp(mmax*lambda2) - exp(mmin*lambda2)); + if(opts->cutsignalwindow) + norm2 -= 1.0/lambda2*(exp(opts->m_max*lambda2) - exp(opts->m_min*lambda2)); + result += (1.0-fm1)*exp(meas.m*lambda2)/norm2; + } + } + else{ + double norm1 = tau1*(exp(-mmin/tau1) - exp(-mmax/tau1)); + if(opts->cutsignalwindow) + norm1 -= tau1*(exp(-opts->m_min/tau1) - exp(-opts->m_max/tau1)); + result = exp(-meas.m/tau1)/norm1; + if (fm1 != 1.0){ + result *= fm1; + double norm2 = tau2*(exp(-mmin/tau2) - exp(-mmax/tau2)); + if(opts->cutsignalwindow) + norm2 -= tau2*(exp(-opts->m_min/tau2) - exp(-opts->m_max/tau2)); + result += (1.0-fm1)*exp(-meas.m/tau2)/norm2; + } + } + return result; +}; + +double bu2kstarmumu_pdf::mkpi_bkg_prob(const bu2kstarmumu_parameters* params, const event& meas) const +{ + if(!(opts->fit_mkpi || opts->use_mkpi) || opts->only_angles || opts->only_Bmass) + return 1.0; + + assert(meas.mkpi <= opts->mkpi_max); + assert(meas.mkpi >= opts->mkpi_min); + + double result = 0.0; + + double mkpi_min = opts->mkpi_min/1.0e+3; + double mkpi_max = opts->mkpi_max/1.0e+3; + double mkpi = meas.mkpi/1.0e+3; + + double normbkg=0.0; + std::vector ch_mkpi(5, 0.0); + ch_mkpi.at(0) = params->cbkgmkpi0(); + ch_mkpi.at(1) = params->cbkgmkpi1(); + ch_mkpi.at(2) = params->cbkgmkpi2(); + ch_mkpi.at(3) = params->cbkgmkpi3(); + ch_mkpi.at(4) = params->cbkgmkpi4(); + std::vector poly_mkpi(ch_mkpi.size(), 0.0); + chebyshev_to_poly(ch_mkpi, poly_mkpi); + std::vector poly_corr_mkpi(ch_mkpi.size(), 0.0); + correct_poly(poly_mkpi, poly_corr_mkpi, mkpi_min, mkpi_max); + for(unsigned int i=0; im_b.get_min(), mmax=params->m_b.get_max(); + + double bkg_frac = params->fm_tau(); + double tau1 = params->m_tau(); + double tau2 = params->m_tau_2(); + double lambda1 = params->m_lambda(); + double lambda2 = params->m_lambda_2(); + + double result = 0.0; + + if(opts->fit_lambda){ + assert(lambda1 <= 0.); + double fullrange1 = 1.0/lambda1*(exp(mmax*lambda1) - exp(mmin*lambda1)); + if(opts->cutsignalwindow){ + fullrange1 -= 1.0/lambda1*(exp(opts->m_max*lambda1) - exp(opts->m_min*lambda1)); + } + double integral1 = 1.0/lambda1*(exp(mb*lambda1) - exp(ma*lambda1)); + result = integral1/fullrange1; + if (bkg_frac != 1.0){ + assert(lambda2 <= 0.); + result *= bkg_frac; + double fullrange2 = 1.0/lambda2*(exp(mmax*lambda2) - exp(mmin*lambda2)); + if(opts->cutsignalwindow){ + fullrange2 -= 1.0/lambda2*(exp(opts->m_max*lambda2) - exp(opts->m_min*lambda2)); + } + double integral2 = 1.0/lambda2*(exp(mb*lambda2) - exp(ma*lambda2)); + result += (1.0-bkg_frac)*integral2/fullrange2; + } + } + else{ + double fullrange1 = tau1*(exp(-mmin/tau1) - exp(-mmax/tau1)); + if(opts->cutsignalwindow){ + fullrange1 -= tau1*(exp(opts->m_max/tau1) - exp(opts->m_min/tau1)); + } + double integral1 = tau1*(exp(-ma/tau1) - exp(-mb/tau1)); + result = integral1/fullrange1; + if (bkg_frac != 1.0){ + result *= bkg_frac; + double fullrange2 = tau2*(exp(-mmin/tau2) - exp(-mmax/tau2)); + if(opts->cutsignalwindow){ + fullrange2 -= tau2*(exp(opts->m_max/tau2) - exp(opts->m_min/tau2)); + } + double integral2 = tau2*(exp(-ma/tau2) - exp(-mb/tau2)); + result += (1.0-bkg_frac)*integral2/fullrange2; + } + } + return result; +}; + +double bu2kstarmumu_pdf::angular_sig_prob(const bu2kstarmumu_parameters* params, const event& meas) const +{ + //Don't when only fitting the mass + if (opts->only_Bmass || opts->only_mass2DFit || opts->only_mkpi) return 1.0; + + double ctl = meas.costhetal; + double ctk = meas.costhetak; + double phi = meas.phi; + + double result_swave = 0.0, result_pwave = 0.0; + double result = 0.0; + + double f1=0.0, f2=0.0, f3=0.0, f4=0.0, f5=0.0, f6=0.0, + f7=0.0, f8=0.0, f9=0.0, f10=0.0, f11=0.0, f12=0.0; + const double j1s = params->J1s(); + const double j1c = params->J1c(); + const double j2s = params->J2s(); + const double j2c = params->J2c(); + const double j3 = params->J3(); + const double j4 = params->J4(); + const double j5 = params->J5(); + const double j6s = params->J6s(); + const double j6c = params->J6c(); + const double j7 = params->J7(); + const double j8 = params->J8(); + const double j9 = params->J9(); + + if (opts->full_angular) fj(ctl, ctk, phi, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12); + else folded_fj(ctl, ctk, phi, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12); + + if (opts->fit_asymmetries && meas.cp_conjugate){ + result_pwave += (f1*j1s + f2*j1c + f3*j2s + f4*j2c - f5*j3 - f6*j4 + - f7*j5 - f8*j6s - f9*j6c - f10*j7 - f11*j8 - f12*j9); + } + else{ + result_pwave += (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9); + } + + if (opts->swave){ + double f1=0.0, f2=0.0, f3=0.0, f4=0.0, f5=0.0, f6=0.0; + if(opts->full_angular) swave_fj(ctl, ctk, phi, f1, f2, f3, f4, f5, f6); + else folded_swave_fj(ctl, ctk, phi, f1, f2, f3, f4, f5, f6); + const double fs = params->FS(); + const double js1 = params->SS1(); + const double js2 = params->SS2(); + const double js3 = params->SS3(); + const double js4 = params->SS4(); + const double js5 = params->SS5(); + result_pwave *= (1.0 - fs); + result_swave += (fs*f1 + js1*f2 + js2*f3 + js3*f4 + js4*f5 + js5*f6); + if (opts->use_mkpi){ + double prob_mkpi_pwave = mkpi_pwave_2(params, meas); + double prob_mkpi_swave = mkpi_swave_2(params, meas); + double prob_mkpi_re_swavepwave = mkpi_re_swavepwave(params, meas); + double prob_mkpi_im_swavepwave = mkpi_im_swavepwave(params, meas); + + result_pwave *= prob_mkpi_pwave/mkpi_pwave_2_norm; + if (std::isnan(result_pwave)) spdlog::warn("prob_mkpi_pwave {0:f}",prob_mkpi_pwave ); + + result_swave = (fs*f1*prob_mkpi_swave/mkpi_swave_2_norm + + (js1*f2 + js2*f3 + js3*f4)*prob_mkpi_re_swavepwave/mkpi_re_swavepwave_norm + + (js4*f5 + js5*f6)*prob_mkpi_im_swavepwave/mkpi_im_swavepwave_norm); + } + if (std::isnan(result_swave) || std::isinf(result_swave)){ + spdlog::warn("\tresult_swave {0:0.6f}",result_swave); + spdlog::warn("\t mkpi_swave_2_norm {0:0.6f}",mkpi_swave_2_norm); + spdlog::warn("\t mkpi_pwave_2_norm {0:0.6f}",mkpi_pwave_2_norm); + spdlog::warn("\t prob_mkpi_swave {0:0.6f}",mkpi_swave_2(params, meas)); + spdlog::warn("\t prob_mkpi_re_swavepwave {0:0.6f}",mkpi_re_swavepwave(params, meas)); + spdlog::warn("\t prob_mkpi_im_swavepwave {0:0.6f}",mkpi_im_swavepwave(params, meas)); + result_swave = 1.0e-12; + } + } + + result = result_pwave + result_swave; + + if(std::isnan(result) || std::isinf(result)){ + spdlog::error("result={0:0f}",result ); + spdlog::error("pwave={0:0f}",result_pwave ); + spdlog::error("swave={0:0f}",result_swave ); + assert(0); + } + + //spdlog::trace("result={0:0f}",result ); + //spdlog::trace("pwave={0:0f}",result_pwave ); + //spdlog::trace("swave={0:0f}",result_swave ); + + + double eff = 1.0; + if (opts->use_angular_acc){ + //for fixed effq2 the efficiency should have been calculated beforehand + //for floating q2 should recalculate as done below + //for event_norm, the efficiency should also have been calculated before + bool q2fixed = (params->eff_q2.get_step_size() == 0.0); + if ((q2fixed || opts->use_event_norm) && (!opts->mcweight)) { //use event norm is only used when convoluting the acceptance into the pdf + if (meas.weight > 0.0) eff = 1.0/meas.weight; + spdlog::trace("eff={0:f}",eff); + } + else{ + double q2 = params->eff_q2(); + eff = this->get_ang_eff(opts,q2,meas.costhetal_fa, meas.costhetal_fa,meas.phi_fa); + spdlog::trace("eff={0:f}",eff); + spdlog::trace("q2={0:f}",q2); + } + } + if(std::isnan(eff) || std::isinf(eff)){ + spdlog::error("eff={0:f}",eff ); + assert(0); + } + + if(eff/fnorm_sig < 0.0){ + spdlog::info("negative acc corr and/or normalizing"); + spdlog::info("eff={0:f}",eff ); + spdlog::info("norm={0:f}",fnorm_sig ); + assert(eff > 0.0); + assert(fnorm_sig > 0.0); + } + //spdlog::trace("eff={0:f},\t fnorm_sig={1:f}",eff, fnorm_sig); + + result *= eff/fnorm_sig; + + return result; +}; + +double bu2kstarmumu_pdf::angular_bkg_prob(const bu2kstarmumu_parameters* params, const event& meas) const{ + + //Don't when only fitting the mass + if (opts->only_Bmass || opts->only_mass2DFit || opts->only_mkpi) return 1.0; + + //calculate bkg prob for all 2(4) possible inversed folding angles: + if(opts->fit_full_angular_bkg && !opts->flat_bkg && !opts->full_angular){ + fcnc::event e[3]; + + fldr->invers_fold(&meas, &e[0], &e[1], &e[2]); + + double p1, p2, p3, p4; + + p1 = simple_angular_bkg_prob(params, meas); + p4 = simple_angular_bkg_prob(params, e[2]); + + if(opts->folding > 0){ + p2 = simple_angular_bkg_prob(params, e[0]); + p3 = simple_angular_bkg_prob(params, e[1]); + return p1+p2+p3+p4; + } + else{ + return p1+p4; + } + } + else{ + return simple_angular_bkg_prob(params, meas); + } +} + +double bu2kstarmumu_pdf::simple_angular_bkg_prob(const bu2kstarmumu_parameters* params, const event& meas) const{ + + if (opts->only_Bmass) return 1.0; + if (opts->only_mass2DFit) return 1.0; //Don't when fitting only mass + + double result = 1.0; + + double costhetal = meas.costhetal; + double costhetak = meas.costhetak; + double phi = meas.phi; + + npolynom npol(opts); + assert(coeffs_eff_4d.size() == npol.getSize()); + + //determine weight/efficiency for this event + double eff = 1.0; + if(opts->use_angular_acc && opts->use_weighted_bkg){ + //for fixed effq2 the efficiency should have been calculated beforehand + //for floating q2 should recalculate as done below + //for event_norm, the efficiency should also have been calculated before + bool q2fixed = (params->eff_q2.get_step_size() == 0.0); + if ((q2fixed || opts->use_event_norm) && (!opts->mcweight)){//use event norm is only used when convoluting the acceptance into the pdf + if (meas.weight > 0.0) eff = 1.0/meas.weight; + } + else eff = this->get_ang_eff(opts,meas,true); + } + + if (opts->flat_bkg){ //for a flat background, only - if at all - the angular acceptance correction is needed + result *= eff/fnorm_bkg; + } + else{ //Chebyshev background + + //read angular bkg coefficients from parameter object + std::vector ch_ctl = init_ch_ctl(params); + std::vector ch_ctk = init_ch_ctk(params); + std::vector ch_phi = init_ch_phi(params); + + //reserve vectors for the (non-)Chebyshev polynomial coefficients + std::vector poly_ctl(ch_ctl.size(), 0.0); + std::vector poly_ctk(ch_ctk.size(), 0.0); + std::vector poly_phi(ch_phi.size(), 0.0); + + //these temporary coefficients are defined in the range from -1 to +1 + std::vector temp_ctl(ch_ctl.size(), 0.0); + std::vector temp_ctk(ch_ctk.size(), 0.0); + std::vector temp_phi(ch_phi.size(), 0.0); + + //transform chebyshev polynomial coefficients to Standard Form polynomials + chebyshev_to_poly(ch_ctl, temp_ctl); + chebyshev_to_poly(ch_ctk, temp_ctk); + chebyshev_to_poly(ch_phi, temp_phi); + + //stretch or squeeze the definition of the polynomials in phi + //for (unsigned int i=0; iflat_bkg){ + return (ctl_b-ctl_a)*(ctk_b-ctk_a)*(phi_b-phi_a); // RANGE_3D() for non-folded + } + else{ + + std::vector ch_ctl = init_ch_ctl(params); + std::vector ch_ctk = init_ch_ctk(params); + std::vector ch_phi = init_ch_phi(params); + + std::vector poly_ctl(ch_ctl.size(), 0.0); + std::vector poly_ctk(ch_ctk.size(), 0.0); + std::vector poly_phi(ch_phi.size(), 0.0); + + std::vector temp_ctl(ch_ctl.size(), 0.0); + std::vector temp_ctk(ch_ctk.size(), 0.0); + std::vector temp_phi(ch_phi.size(), 0.0); + + chebyshev_to_poly(ch_ctl, temp_ctl); + chebyshev_to_poly(ch_ctk, temp_ctk); + chebyshev_to_poly(ch_phi, temp_phi); + + for (unsigned int i=0; iflat_bkg){ + + double c = 1.0; + + //new improved non-factorizing acceptance + + npolynom npol = npolynom(opts); + assert(coeffs_eff_4d.size() == npol.getSize()); + double chijk = 0.0; + for (unsigned int h = 0; h ch_ctl = init_ch_ctl(params); + std::vector ch_ctk = init_ch_ctk(params); + std::vector ch_phi = init_ch_phi(params); + + std::vector poly_ctl(ch_ctl.size(), 0.0); + std::vector poly_ctk(ch_ctk.size(), 0.0); + std::vector poly_phi(ch_phi.size(), 0.0); + + std::vector temp_ctl(ch_ctl.size(), 0.0); + std::vector temp_ctk(ch_ctk.size(), 0.0); + std::vector temp_phi(ch_phi.size(), 0.0); + + chebyshev_to_poly(ch_ctl, temp_ctl); + chebyshev_to_poly(ch_ctk, temp_ctk); + chebyshev_to_poly(ch_phi, temp_phi); + + for (unsigned int i=0; ieff_q2(); + npolynom npol(opts); + assert(coeffs_eff_4d.size() == npol.getSize()); + double chijk = 0.0; + + for (unsigned int h = 0; heff_q2(); + if (opts->full_angular){ + if (opts->flat_bkg){ + double integral = 0.0; + for (unsigned int h = 0; hflat_bkg){ + double integral = 0.0; + for (unsigned int h = 0; hctl_min,opts->ctl_max,i) + * integrate_x_to_n(opts->ctk_min,opts->ctk_max,j) + * integrate_x_to_n(opts->phi_min,opts->phi_max,k); + } + } + } + } + return integral; + } + else{ + if(opts->fit_full_angular_bkg){ + return integral_bkg_chebyshev(params, CTL_MIN, CTL_MAX, opts->ctk_min, opts->ctk_max, PHI_MIN, PHI_MAX, q2); //TODO: check if that makes sense (https://gitlab.cern.ch/LHCb-RD/ewp-Bplus2Kstmumu-AngAna/-/merge_requests/21) + } + else{ + return integral_bkg_chebyshev(params, opts->ctl_min, opts->ctl_max, opts->ctk_min, opts->ctk_max, opts->phi_min, opts->phi_max, q2); + } + } + } + } + else{ //non weighted background pdf + if (opts->full_angular){ + if (opts->flat_bkg) return RANGE_3D(); + else return integral_bkg(params, CTL_MIN, CTL_MAX, CTK_MIN, CTK_MAX, PHI_MIN, PHI_MAX); + } + else{ //folded angles + if (opts->flat_bkg){ + return (opts->ctk_max - opts->ctk_min) * (opts->ctl_max - opts->ctl_min) * (opts->phi_max - opts->phi_min); + } + else{ + if(opts->fit_full_angular_bkg){ + return integral_bkg(params, CTL_MIN, CTL_MAX, CTK_MIN, CTK_MAX, PHI_MIN, PHI_MAX); + } + else{ + return integral_bkg(params, opts->ctl_min, opts->ctl_max, opts->ctk_min, opts->ctk_max, opts->phi_min, opts->phi_max); + } + } + } + } +} + +double bu2kstarmumu_pdf::angular_sig_norm(const bu2kstarmumu_parameters* params, bool weighted){ + + double f1=0.0, f2=0.0, f3=0.0, f4=0.0, f5=0.0, f6=0.0, + f7=0.0, f8=0.0, f9=0.0, f10=0.0, f11=0.0, f12=0.0; + + double fs1=0.0, fs2=0.0, fs3=0.0, fs4=0.0, fs5=0.0, fs6=0.0; + + const double j1s = params->J1s(); + const double j1c = params->J1c(); + const double j2s = params->J2s(); + const double j2c = params->J2c(); + const double j3 = params->J3(); + const double j4 = params->J4(); + const double j5 = params->J5(); + const double j6s = params->J6s(); + const double j6c = params->J6c(); + const double j7 = params->J7(); + const double j8 = params->J8(); + const double j9 = params->J9(); + + const double fs = params->FS(); + const double js1 = params->SS1(); + const double js2 = params->SS2(); + const double js3 = params->SS3(); + const double js4 = params->SS4(); + const double js5 = params->SS5(); + + //sig norm + double q2 = params->eff_q2(); + if (opts->full_angular){ + //get signal pdf + if (weighted) integrated_fj_chebyshev(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, q2); + else integrated_fj_noacc(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12); + + //swave + if(opts->swave){ + if (weighted) swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2); + else swave_integrated_fj_noacc(fs1, fs2, fs3, fs4, fs5, fs6); + } + + //if asymmetries are fitted: + if(opts->fit_asymmetries){ + if(opts->swave) return (1.0-fs) * (f1*j1s + f2*j1c + f3*j2s + f4*j2c) + (fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5); + else return f1*j1s + f2*j1c + f3*j2s + f4*j2c; + } + + if (opts->swave){ + return (1.0-fs) * (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9) + + (fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5); + } + + //signal pdf without swave, without asymmetries and without m(Kpi) + return f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9; + } + else{ //folded angles + if (weighted) folded_integrated_fj_chebyshev(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, q2); + else folded_integrated_fj_noacc(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12); + + if(opts->swave){ + if (weighted) folded_swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2); + else folded_swave_integrated_fj_noacc(fs1, fs2, fs3, fs4, fs5, fs6); + } + + if(opts->fit_asymmetries){ + if(opts->swave) return (1-fs) * (f1*j1s + f2*j1c + f3*j2s + f4*j2c) + (fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5); + else return (f1*j1s + f2*j1c + f3*j2s + f4*j2c); + } + + if(opts->swave){ + return (1-fs) * (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9) + + (fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5); + } + + //signal pdf without swave, without asymmetries and without m(Kpi) + return f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9; + } +} + +double bu2kstarmumu_pdf::angular_swave_norm(const bu2kstarmumu_parameters* params, bool weighted){ + + double fs1=0.0, fs2=0.0, fs3=0.0, fs4=0.0, fs5=0.0, fs6=0.0; + const double fs = params->FS(); + + //sig norm + double q2 = params->eff_q2(); + if (opts->full_angular){ + if (weighted) swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2); + else swave_integrated_fj_noacc(fs1, fs2, fs3, fs4, fs5, fs6); + } + else{ //folded angles + if (weighted) folded_swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2); + else folded_swave_integrated_fj_noacc(fs1, fs2, fs3, fs4, fs5, fs6); + } + return fs1*fs; +} + +double bu2kstarmumu_pdf::angular_pwave_norm(const bu2kstarmumu_parameters* params, bool weighted){ + + double f1=0.0, f2=0.0, f3=0.0, f4=0.0, f5=0.0, f6=0.0, + f7=0.0, f8=0.0, f9=0.0, f10=0.0, f11=0.0, f12=0.0; + + const double j1s = params->J1s(); + const double j1c = params->J1c(); + const double j2s = params->J2s(); + const double j2c = params->J2c(); + const double j3 = params->J3(); + const double j4 = params->J4(); + const double j5 = params->J5(); + const double j6s = params->J6s(); + const double j6c = params->J6c(); + const double j7 = params->J7(); + const double j8 = params->J8(); + const double j9 = params->J9(); + + //sig norm + double q2 = params->eff_q2(); + if (opts->full_angular){ + if (weighted) integrated_fj_chebyshev(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, q2); + else integrated_fj_noacc(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12); + } + else{ //folded angles + if (weighted) folded_integrated_fj_chebyshev(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, q2); + else folded_integrated_fj_noacc(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12); + } + //if asymmetries are fitted: + if(opts->fit_asymmetries)return f1*j1s + f2*j1c + f3*j2s + f4*j2c; + else return f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9; +} + +double bu2kstarmumu_pdf::angular_pswave_norm(const bu2kstarmumu_parameters* params, bool weighted){ + + double fs1=0.0, fs2=0.0, fs3=0.0, fs4=0.0, fs5=0.0, fs6=0.0; + + const double js1 = params->SS1(); + const double js2 = params->SS2(); + const double js3 = params->SS3(); + const double js4 = params->SS4(); + const double js5 = params->SS5(); + + //sig norm + double q2 = params->eff_q2(); + if (opts->full_angular){ + if (weighted) swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2); + else swave_integrated_fj_noacc(fs1, fs2, fs3, fs4, fs5, fs6); + } + else{ //folded angles + if (weighted) folded_swave_integrated_fj_chebyshev(fs1, fs2, fs3, fs4, fs5, fs6, q2); + else folded_swave_integrated_fj_noacc(fs1, fs2, fs3, fs4, fs5, fs6); + } + return fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5; +} + +void bu2kstarmumu_pdf::update_cached_efficiencies(const bu2kstarmumu_parameters* params, std::vector* events) +{ + if (opts->update_efficiencies){ + spdlog::info("Updating cached efficiencies"); + //assert(0); + //three ways this is usefull + //-q2_eff is fixed and you want to avoid recalculating this every time + //-weighted fit to determine the event weight that needs to be used + //-when using per event norm this can also be cached + npolynom npol(opts); + assert(coeffs_eff_4d.size() == npol.getSize()); + double q2 = params->eff_q2(); + + unsigned int N = events->size(); + for (unsigned int e=0; eat(e); + if (opts->weighted_fit || (opts->use_angular_acc && opts->use_event_norm)){ + q2 = meas.q2; + } + eff = this->get_ang_eff(opts,q2, meas.costhetal_fa, meas.costhetak_fa, meas.phi_fa); + + if (eff > EFF_CUTOFF){ + if (opts->multiply_eff) meas.weight *= 1.0/eff; + else meas.weight = 1.0/eff; + } + else{ + spdlog::warn("Event with too low efficiency: {0:f}", eff); + spdlog::warn("\t q2: {0:f} \tq2_eff {1:f} \tctl: {2:f} \tctk: {3:f} \tphi: {4:f} ", + meas.q2, q2, meas.costhetal_fa, meas.costhetak_fa , meas.phi_fa); + if (opts->multiply_eff) meas.weight *= 1.0; + else meas.weight = 1.0; + } + } + return; + } + else return; +} + +//////////////////////// +/// Full angular /// +//////////////////////// + +//--------------------// +// S-wave +//--------------------// + +void bu2kstarmumu_pdf::swave_fj(double ctl, double ctk, double phi, + double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const{ + f1 = C_SWAVE * sintheta2(ctl); + f2 = C_SWAVE * sintheta2(ctl)*ctk; + f3 = C_SWAVE * sin2theta(ctl)*sintheta_abs(ctk)*cos(phi); + f4 = C_SWAVE * sintheta_abs(ctl)*sintheta_abs(ctk)*cos(phi); + f5 = C_SWAVE * sintheta_abs(ctl)*sintheta_abs(ctk)*sin(phi); + f6 = C_SWAVE * sin2theta(ctl)*sintheta_abs(ctk)*sin(phi); +} + +void bu2kstarmumu_pdf::swave_integrated_fj_noacc(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const{ + f1 = 1.0; + f2 = 0.0; + f3 = 0.0; + f4 = 0.0; + f5 = 0.0; + f6 = 0.0; + + swave_integrated_fj_noacc(opts->ctl_min, opts->ctl_max, opts->ctk_min, opts->ctk_max, opts->phi_min, opts->phi_max, + f1, f2, f3, f4, f5, f6); +} + +void bu2kstarmumu_pdf::swave_integrated_fj_noacc(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, + double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const{ + f1 = C_SWAVE * integrate_s_f1(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + f2 = C_SWAVE * integrate_s_f2(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + f3 = C_SWAVE * integrate_s_f3(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + f4 = C_SWAVE * integrate_s_f4(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + f5 = C_SWAVE * integrate_s_f5(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + f6 = C_SWAVE * integrate_s_f6(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + return; +} + +void bu2kstarmumu_pdf::swave_integrated_fj_chebyshev(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, + double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double q2) const //TODO: modify this according to the normDebug branch +{ + + f1 = 0.0; f2 = 0.0; f3 = 0.0; f4 = 0.0; f5 = 0.0; f6 = 0.0; + + npolynom npol(opts); + assert(coeffs_eff_4d.size() == npol.getSize()); + double chijk = 0.0; + for (unsigned int h = 0; hfolding > 0) c *= 2.0; //folding in cos(thetaL) + + f2 = 0.0; f3 = 0.0; f4 = 0.0; f5 = 0.0; f6 = 0.0; + + f1 = c * sintheta2(ctl); + if(opts->folding != 4) f2 = c * sintheta2(ctl)*(ctk); + if(opts->folding == 1) f3 = c * sintheta_abs(ctk)*sin2theta(ctl)*cos(phi); + if(opts->folding == 2) f4 = c * sintheta_abs(ctk)*sintheta_abs(ctl)*cos(phi); + if(opts->folding > 2) f5 = c * sintheta_abs(ctk)*sintheta_abs(ctl)*sin(phi); + //f6 always zero no matter what folding +} + +void bu2kstarmumu_pdf::folded_swave_integrated_fj_noacc(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const +{ + f1 = 1.0; + f2 = 0.0; + f3 = 0.0; + f4 = 0.0; + f5 = 0.0; + f6 = 0.0; + + folded_swave_integrated_fj_noacc(opts->ctl_min, opts->ctl_max, opts->ctk_min, opts->ctk_max, opts->phi_min, opts->phi_max, + f1, f2, f3, f4, f5, f6); + +} + +void bu2kstarmumu_pdf::folded_swave_integrated_fj_noacc(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, + double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const{ + double c = C_SWAVE*2.0; // folding in phi + if(opts->folding > 0) c *= 2.0; //folding in cos(thetaL) + + f2 = 0.0; f3 = 0.0; f4 = 0.0; f5 = 0.0; + f1 = c * integrate_s_f1(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + if(opts->folding != 4) f2 = c * integrate_s_f2(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + if(opts->folding == 1) f3 = c * integrate_s_f3(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + if(opts->folding == 2) f4 = c * integrate_s_f4(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + if(opts->folding > 2) f5 = c * integrate_s_f5(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + f6 = 0.0; + + return; +} + +void bu2kstarmumu_pdf::folded_swave_integrated_fj_chebyshev(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, + double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double q2) const{ + double c = C_SWAVE*2.0; // folding in phi + if(opts->folding > 0) c *= 2.0; //folding in cos(thetaL) + + f1 = 0.0; f2 = 0.0; f3 = 0.0; f4 = 0.0; f5 = 0.0; f6 = 0.0; + + npolynom npol = npolynom(opts); + assert(coeffs_eff_4d.size() == npol.getSize()); + + double chijk = 0.0; + for (unsigned int h = 0; hfolding != 4) f2 += chijk * integrate_s_f2(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k); + if(opts->folding == 1) f3 += chijk * integrate_s_f3(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k); + if(opts->folding == 2) f4 += chijk * integrate_s_f4(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k); + if(opts->folding > 2) f5 += chijk * integrate_s_f5(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k); + f6 = 0.0; + + } + } + } + } +} + +void bu2kstarmumu_pdf::folded_swave_integrated_fj_chebyshev(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double q2) const{ + + folded_swave_integrated_fj_chebyshev(opts->ctl_min, opts->ctl_max, opts->ctk_min, opts->ctk_max, opts->phi_min, opts->phi_max, + f1, f2, f3, f4, f5, f6, q2); + return; +} + +//P-wave + +void bu2kstarmumu_pdf::folded_fj(double ctl, double ctk, double phi, double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double& f7, double& f8, double& f9, double& f10, double& f11, double& f12) const +{ + //reset all coefficients that might not be calculated due to folding! + f6 = 0.; + f7 = 0.; + f8 = 0.; + f9 = 0.; + f10 = 0.; + f11 = 0.; + f12 = 0.; + + //constant coefficient + double c = 2.0*C_PWAVE; //multiply by 2 due to folding in phi + if(opts->folding > 0) c *= 2.0; //folding in cos(thetaL) + + f1 = c * sintheta2(ctk); //j1s = 3/4*(1-FL) + f2 = c * costheta2(ctk); //j1c = FL + f3 = c * sintheta2(ctk)*cos2theta(ctl); //j2s = 1/4*(1-FL) + f4 = c * costheta2(ctk)*cos2theta(ctl); //j2c = -FL + f5 = c * sintheta2(ctk)*sintheta2(ctl)*cos(2.0*phi); //j3 + if(opts->folding == 1) f6 = c * sin2theta(ctk)*sin2theta(ctl)*cos(phi); //j4 + if(opts->folding == 2) f7 = c * sin2theta(ctk)*sintheta_abs(ctl)*cos(phi); //j5 + if(opts->folding == 0){ + f8 = c * sintheta2(ctk)*ctl; //j6s + f9 = c * costheta2(ctk)*ctl; //j6c + } + if(opts->folding == 3) f10 = c * sin2theta(ctk)*sintheta_abs(ctl)*sin(phi); //j7 + if(opts->folding == 4) f11 = c * sin2theta(ctk)*sin2theta(ctl)*sin(phi); //j8 + if(opts->folding == 0) f12 = c * sintheta2(ctk)*sintheta2(ctl)*sin(2.0*phi); //j9 +}; + + +void bu2kstarmumu_pdf::folded_integrated_fj_noacc(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double& f7, double& f8, double& f9, double& f10, double& f11, double& f12) const +{ + folded_integrated_fj_noacc(opts->ctl_min, opts->ctl_max, opts->ctk_min, opts->ctk_max, opts->phi_min, opts->phi_max, + f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12); +}; + +void bu2kstarmumu_pdf::folded_integrated_fj_noacc(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, + double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double& f7, double& f8, double& f9, double& f10, double& f11, double& f12) const +{ + + if(opts->full_angular){ + spdlog::error("Cannot use folded integrals for full angular fit"); + assert(0); + } + + f1 = 0.0; + f2 = 0.0; + f3 = 0.0; + f4 = 0.0; + f5 = 0.0; + f6 = 0.0; + f7 = 0.0; + f8 = 0.0; + f9 = 0.0; + f10 = 0.0; + f11 = 0.0; + f12 = 0.0; + + //copied from full angular integral: + double c = C_PWAVE*2.; //folding in phi + if(opts->folding > 0)c *= 2.; //folding in cos(theta_L) + + f1 = c * integrate_f1(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + f2 = c * integrate_f2(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + f3 = c * integrate_f3(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + f4 = c * integrate_f4(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + f5 = c * integrate_f5(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + if(opts->folding == 0){ + f8 = c * integrate_f8(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + f9 = c * integrate_f9(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + f12 = c * integrate_f12(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + } + else if(opts->folding == 1) f6 = c * integrate_f6(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + else if(opts->folding == 2) f7 = c * integrate_f7(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + else if(opts->folding == 3) f10 = c * integrate_f10(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + else if(opts->folding == 4) f11 = c * integrate_f11(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, 0, 0, 0); + + return; + +}; + + +void bu2kstarmumu_pdf::folded_integrated_fj_chebyshev(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, + double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double& f7, double& f8, double& f9, double& f10, double& f11, double& f12, double q2) const{ + + if(opts->full_angular){ + spdlog::error("Cannot use folded integrals for full angular fit"); + assert(0); + } + + double c = C_PWAVE* 2.; //folding in phi + if(opts->folding > 0)c *= 2.; //folding in cos(theta_L) + + f1 = 0.0; + f2 = 0.0; + f3 = 0.0; + f4 = 0.0; + f5 = 0.0; + f6 = 0.0; + f7 = 0.0; + f8 = 0.0; + f9 = 0.0; + f10 = 0.0; + f11 = 0.0; + f12 = 0.0; + + //new improved non-factorizing acceptance + + npolynom npol = npolynom(opts); + assert(coeffs_eff_4d.size() == npol.getSize()); + double chijk = 0.0; + for (unsigned int h = 0; hfolding == 0){ + f8 += chijk*integrate_f8(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k); + f9 += chijk*integrate_f9(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k); + f12 += chijk*integrate_f12(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k); + } + else if(opts->folding == 1) f6 += chijk*integrate_f6(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k); + else if(opts->folding == 2) f7 += chijk*integrate_f7(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k); + else if(opts->folding == 3) f10 += chijk*integrate_f10(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k); + else if(opts->folding == 4) f11 += chijk*integrate_f11(ctl_a, ctl_b, ctk_a, ctk_b, phi_a, phi_b, i, j, k); + + } + +}; + +void bu2kstarmumu_pdf::folded_integrated_fj_chebyshev(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double& f7, double& f8, double& f9, double& f10, double& f11, double& f12, double q2) const{ + folded_integrated_fj_chebyshev(opts->ctl_min, opts->ctl_max, opts->ctk_min, opts->ctk_max, opts->phi_min, opts->phi_max, + f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, q2); + return; +}; + + + +void bu2kstarmumu_pdf::calculate_sweights(const bu2kstarmumu_parameters* parms, std::vector* ev) const +{ + assert(opts->extended_ml); + parameter* psig = parms->get_parameter("n_sig"); + parameter* pbkg = parms->get_parameter("n_bkg"); + if (psig != 0 && pbkg != 0){ + double nsig = psig->get_value(); + double nbkg = pbkg->get_value(); + + double sweight = 0.0, prob_sig_m = 0.0, prob_bkg_m = 0.0; + + //obtain inverse variant matrix (V_{nj}^{-1}) + double inv_cov_matrix[2*2] = {0.0, 0.0, 0.0, 0.0}; + for (unsigned int i = 0; isize(); i++){ + const event& meas = ev->at(i); + prob_sig_m = m_sig_prob(parms, meas); + prob_bkg_m = m_bkg_prob(parms, meas); + + inv_cov_matrix[0] += prob_sig_m*prob_sig_m/sqr(nsig*prob_sig_m + nbkg*prob_bkg_m); + inv_cov_matrix[1] += prob_sig_m*prob_bkg_m/sqr(nsig*prob_sig_m + nbkg*prob_bkg_m); + inv_cov_matrix[2] += prob_bkg_m*prob_sig_m/sqr(nsig*prob_sig_m + nbkg*prob_bkg_m); + inv_cov_matrix[3] += prob_bkg_m*prob_bkg_m/sqr(nsig*prob_sig_m + nbkg*prob_bkg_m); + } + spdlog::info("Inverse covariance matrix"); + spdlog::info("{0:0.8f} {1:.8f}", inv_cov_matrix[0],inv_cov_matrix[1] ); + spdlog::info("{0:0.8f} {1:.8f}", inv_cov_matrix[2],inv_cov_matrix[3] ); + + //invert inserve matrix to get V_{nj} + double cov_matrix[2*2] = {0.0, 0.0, 0.0, 0.0}; + cov_matrix[0] = +inv_cov_matrix[3]/(inv_cov_matrix[0]*inv_cov_matrix[3]-inv_cov_matrix[1]*inv_cov_matrix[2]); + cov_matrix[1] = -inv_cov_matrix[1]/(inv_cov_matrix[0]*inv_cov_matrix[3]-inv_cov_matrix[1]*inv_cov_matrix[2]); + cov_matrix[2] = -inv_cov_matrix[2]/(inv_cov_matrix[0]*inv_cov_matrix[3]-inv_cov_matrix[1]*inv_cov_matrix[2]); + cov_matrix[3] = +inv_cov_matrix[0]/(inv_cov_matrix[0]*inv_cov_matrix[3]-inv_cov_matrix[1]*inv_cov_matrix[2]); + spdlog::info("Covariance matrix"); + spdlog::info("{0:0.8f} {1:.8f}", cov_matrix[0], cov_matrix[1] ); + spdlog::info("{0:0.8f} {1:.8f}", cov_matrix[2], cov_matrix[3] ); + + //get sWeights for all events + for (unsigned int i = 0; isize(); i++){ + const event& meas = ev->at(i); + prob_sig_m = m_sig_prob(parms, meas); + prob_bkg_m = m_bkg_prob(parms, meas); + sweight = (prob_sig_m * cov_matrix[0] + prob_bkg_m * cov_matrix[1]) / ( prob_sig_m * nsig + prob_bkg_m * nbkg ); + ev->at(i).sweight = sweight; + } + } +}; + +void bu2kstarmumu_pdf::save_coeffs_eff_phsp_4d(){ + std::ofstream ostr(coeffs_eff_phsp_4D(opts)); + for(unsigned int c = 0; c < this->coeffs_eff_4d.size(); c++){ + ostr << std::setprecision(15) << std::scientific << this->coeffs_eff_4d.at(c) << "\n"; + } + spdlog::info("[SAVE]\t\tSaved a total of {0:d} angular acceptance correction coefficients",this->coeffs_eff_4d.size()); +} + +std::vector bu2kstarmumu_pdf::read_coeffs_eff_phsp_4d(){ + + unsigned int nCoeffs = opts->eff_order_q2 * opts->eff_order_costhetal * opts->eff_order_costhetak * opts->eff_order_phi; + + std::string filename = coeffs_eff_phsp_4D(opts); + std::ifstream file(filename); + if(!file.is_open())spdlog::error("File " + filename + " not found to load coefficients!"); + else spdlog::info("Loading a total of {0:d} coefficients from file " + filename + ".",nCoeffs); + std::string line; + + double coeff; + std::vectorcoeffs; + + assert(file.is_open()); + + while(1){ + getline(file, line); + if(file.eof())break; + std::istringstream istr(line); + istr >> coeff; + coeffs.push_back(coeff); + } + + if(coeffs.size() != nCoeffs){ + spdlog::critical("Number of coefficients loaded from file ({0:d}) does not match the number of configurated coefficients ({1:d}). Abort", coeffs.size(), nCoeffs); + assert(0); + } + + + return coeffs; +} + +void bu2kstarmumu_pdf::load_coeffs_eff_phsp_4d(){ + this->coeffs_eff_4d = read_coeffs_eff_phsp_4d(); +} + diff --git a/Code/FCNCFitter/sources/Core/bu2kstarmumu_pdf.hh b/Code/FCNCFitter/sources/Core/bu2kstarmumu_pdf.hh new file mode 100644 index 0000000..0e4ca56 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/bu2kstarmumu_pdf.hh @@ -0,0 +1,275 @@ +/** + * @file bu2kstarmumu_pdf.hh + * @author Christoph Langenbruch, Renata Kopecna + * @date 2009-03-18 + * + */ + +#ifndef BU2KSTARMUMU_PDF_H +#define BU2KSTARMUMU_PDF_H + +#include +#include +#include +#include + +//Create vectors with the values of the polynomials +std::vector init_ch_ctl(const fcnc::bu2kstarmumu_parameters* params); +std::vector init_ch_ctk(const fcnc::bu2kstarmumu_parameters* params); +std::vector init_ch_phi(const fcnc::bu2kstarmumu_parameters* params); + +namespace fcnc { + + struct q2bin { + double min; + double max; + q2bin(double a, double b): min(a), max(b) {}; + }; + + class options; + class event; + class values; + + static const double mumass = 105.6583668; //TODO: OMFG + + class bu2kstarmumu_pdf; + + ///class that implements the pdf ot the signal decay Bs -> JPsi Phi + class bu2kstarmumu_pdf: public pdf { + ///These encapsulation functions used by ROOT/Minuit need access to class internals. + friend class bu2kstarmumu_plotter; + friend class bu2kstarmumu_generator; + private: + folder* fldr; + public: + static bu2kstarmumu_pdf* current_pdf; + //double shift_lh; + bu2kstarmumu_pdf(options* o, const bu2kstarmumu_parameters* params); + virtual ~bu2kstarmumu_pdf(); + void init(bu2kstarmumu_parameters* params) + { + }; + void init(parameters* params); + void update_cached_normalization(const bu2kstarmumu_parameters* params); + void update_cached_normalization(const parameters* params); + void update_cached_integrated_fis(const bu2kstarmumu_parameters* params); + void update_cached_integrated_fis(const parameters* params); + //void update_cached_normalization(const bu2kstarmumu_parameters* params, std::vector* events); + //void update_cached_normalization(const parameters* params, std::vector* events); + void update_cached_efficiencies(const bu2kstarmumu_parameters* params, std::vector* events); + void update_cached_efficiencies(const parameters* params, std::vector* events); + void update_cached_xis(const bu2kstarmumu_parameters* params, std::vector* events); + void update_cached_xis(const parameters* params, std::vector* events); + public: + ///normalization + double fnorm_sig; + //double fnorm_sig_swave; + double fnorm_bkg; + double fbuffer_f1, fbuffer_f2, fbuffer_f3, fbuffer_f4, fbuffer_f5, fbuffer_f6, fbuffer_f7, fbuffer_f8, fbuffer_f9, fbuffer_f10, fbuffer_f11, fbuffer_f12; + double fbuffer_fs1, fbuffer_fs2, fbuffer_fs3, fbuffer_fs4, fbuffer_fs5, fbuffer_fs6; + virtual void get_swave_integrated_fj(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const { + f1 = fbuffer_fs1; + f2 = fbuffer_fs2; + f3 = fbuffer_fs3; + f4 = fbuffer_fs4; + f5 = fbuffer_fs5; + f6 = fbuffer_fs6; + return; + }; + virtual void get_integrated_fj(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, + double& f7, double& f8, double& f9, double& f10, double& f11, double& f12) const { + f1 = fbuffer_f1; + f2 = fbuffer_f2; + f3 = fbuffer_f3; + f4 = fbuffer_f4; + f5 = fbuffer_f5; + f6 = fbuffer_f6; + f7 = fbuffer_f7; + f8 = fbuffer_f8; + f9 = fbuffer_f9; + f10 = fbuffer_f10; + f11 = fbuffer_f11; + f12 = fbuffer_f12; + return; + }; + /* + unsigned int neff_costhetal; + unsigned int neff_costhetak; + unsigned int neff_phi; + + unsigned int nbkg_costhetal; + unsigned int nbkg_costhetak; + unsigned int nbkg_phi; + */ + ///coefficients for 4D angular acceptance (Sliding acceptance which is controlled by a parameter eff_q2range in the parameter set) + std::vector coeffs_eff_4d; + + ///chebyshev coefficients for factorizing bkg modeling + //std::vector coeffs_bkg_costhetal; + //std::vector coeffs_bkg_costhetak; + //std::vector coeffs_bkg_phi; + + //std::vector bkg_events; + std::vector eff_events; + const bu2kstarmumu_parameters* eff_params; + + //static void bkg_fcn(Int_t &npar, Double_t *grad, Double_t &lh, Double_t *params, Int_t iflag); + static void eff_fcn(Int_t &npar, Double_t *grad, Double_t &lh, Double_t *params, Int_t iflag); + static void eff_fcn_phsp(Int_t &npar, Double_t *grad, Double_t &lh, Double_t *params, Int_t iflag); + static void eff_fcn_phsp_4d(Int_t &npar, Double_t *grad, Double_t &lh, Double_t *params, Int_t iflag); + + ////////////////// + ///Full angular/// + ////////////////// + + //Angular correction polynomials are converted into Sum (c_ijkl * ctk^i * ctl^j * phi^k * q2^l) + //S-wave + void swave_fj(double ctl, double ctk, double phi, + double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const; + void swave_integrated_fj_noacc(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const; + void swave_integrated_fj_noacc(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, + double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const; + void swave_integrated_fj_chebyshev(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, + double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double q2) const; + void swave_integrated_fj_chebyshev(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double q2) const; + + //P-wave + void fj(double ctl, double ctk, double phi, + double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, + double& f7, double& f8, double& f9, double& f10, double& f11, double& f12) const; + void integrated_fj_noacc(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, + double& f7, double& f8, double& f9, double& f10, double& f11, double& f12) const; + void integrated_fj_noacc(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, + double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, + double& f7, double& f8, double& f9, double& f10, double& f11, double& f12) const; + void integrated_fj_chebyshev(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, + double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, + double& f7, double& f8, double& f9, double& f10, double& f11, double& f12, double q2) const; + void integrated_fj_chebyshev(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, + double& f7, double& f8, double& f9, double& f10, double& f11, double& f12, double q2) const; + + ///////////////////// + ///Angular folding/// + ///////////////////// + + //S-wave + void folded_swave_fj(double ctl, double ctk, double phi, double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const; + void folded_swave_integrated_fj_noacc(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const; + void folded_swave_integrated_fj_noacc(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, + double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const; + void folded_swave_integrated_fj_chebyshev(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, + double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double q2) const; + void folded_swave_integrated_fj_chebyshev(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double q2) const; + + //P-wave + void folded_fj(double ctl, double ctk, double phi, double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double& f7, double& f8, double& f9, double& f10, double& f11, double& f12) const; + void folded_integrated_fj_noacc(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double& f7, double& f8, double& f9, double& f10, double& f11, double& f12) const; + void folded_integrated_fj_noacc(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, + double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double& f7, double& f8, double& f9, double& f10, double& f11, double& f12) const; + void folded_integrated_fj_chebyshev(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double& f7, double& f8, double& f9, double& f10, double& f11, double& f12, double q2) const; + void folded_integrated_fj_chebyshev(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, + double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double& f7, double& f8, double& f9, double& f10, double& f11, double& f12, double q2) const; + + //background + double integral_bkg(const bu2kstarmumu_parameters* params, double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b) const; + double integral_bkg_chebyshev(const bu2kstarmumu_parameters* params, double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, double q2) const; + + //moments + void get_moments(std::vector events, std::vector& moments, std::vector& covariance) const; + void save_moments_to_obs(bu2kstarmumu_parameters* params, std::vector obs, std::vector obscov) const; + + //mkpi dependencies + double mkpi_pwave_2(const bu2kstarmumu_parameters* params, const event& meas) const; + double mkpi_swave_2(const bu2kstarmumu_parameters* params, const event& meas) const; + double mkpi_re_swavepwave(const bu2kstarmumu_parameters* params, const event& meas) const; + double mkpi_im_swavepwave(const bu2kstarmumu_parameters* params, const event& meas) const; + double mkpi_bkg(const bu2kstarmumu_parameters* params, const event& meas) const; + double mkpi_swave_2_norm; + double mkpi_pwave_2_norm; + double mkpi_re_swavepwave_norm; + double mkpi_im_swavepwave_norm; + double mkpi_bkg_norm; + + ///determine parametrization for efficiencies in angles and q2, needs reconstructed phsp MC events, needs to change weights so non-const + void parametrize_eff_phsp_4d(const std::vector& events, values* globalvalues, int tagNumber, bool assumePhiEven, bool checkSignifcance, bool runMinuit, bool checkFactorization, bool do3Dmoments); + + //Get the efficiency from the angular corrections + double get_ang_eff(fcnc::options *opts, double q2, double ctl, double ctk, double phi) const; + double get_ang_eff(fcnc::options *opts, fcnc::event evt, bool fa) const; //TBH, no clue why there has to be the const, but it compiles, so I'll take it + + //save and load the 4d coefficients to a file + void save_coeffs_eff_phsp_4d(); + void load_coeffs_eff_phsp_4d(); + std::vectorread_coeffs_eff_phsp_4d(); + ///determine parametrization for efficiencies, needs the reconstructed (MC) events and the set of theory paramters + void parametrize_eff(const std::vector& events, const bu2kstarmumu_parameters* theory_params); + ///parametrize the angular background distribution from the bd mass sidebands + //void parametrize_bkg(const std::vector& events); + //can do this unbinned in principle ? + //yes, do not forget that normalization is not free -> -1 parameter + + ///the options used for this pdf e.g. per event resolution or not etc. + options* opts; + ///The signal mass probability (Currently double gaussian). //TODO: check + double m_sig_prob(const bu2kstarmumu_parameters* params, const event& meas) const; + double integral_m_sig_prob(const bu2kstarmumu_parameters* params, double ma, double mb) const; + ///The prompt background mass probability (Currently exponential). + double m_bkg_prob(const bu2kstarmumu_parameters* params, const event& meas) const; + double integral_m_bkg_prob(const bu2kstarmumu_parameters* params, double ma, double mb) const; + ///The signal m(Kpi) mass probability + double mkpi_sig_prob(const bu2kstarmumu_parameters* params, const event& meas) const; + ///The prompt background in m(Kpi) spectrum probability //TODO: normalization? + double mkpi_bkg_prob(const bu2kstarmumu_parameters* params, const event& meas) const; + ///The signal angular probability + double angular_sig_prob(const bu2kstarmumu_parameters* params, const event& meas) const; + ///The prompt background angular probability (flat or Chebyshev) + double angular_bkg_prob(const bu2kstarmumu_parameters* params, const event& meas) const; + ///Simple background probabilily: + double simple_angular_bkg_prob(const bu2kstarmumu_parameters* params, const event& meas) const; + + ///The total probability f_sig*p_sig + (1-f_sig)*p_bkg for event meas. + virtual double prob(const parameters* params, const event& meas) const{ + return prob(static_cast(params), meas);//still have the initialization as safety, this is faster + }; + ///The total probability f_sig*p_sig + (1-f_sig)*p_bkg for event meas. + double prob(const bu2kstarmumu_parameters* params, const event& meas) const; + void calculate_sweights(const bu2kstarmumu_parameters* parms, std::vector* ev) const; + + double angular_bkg_norm(const bu2kstarmumu_parameters* params, bool weighted); + double angular_sig_norm(const bu2kstarmumu_parameters* params, bool weighted); + double angular_swave_norm(const bu2kstarmumu_parameters* params, bool weighted); + double angular_pwave_norm(const bu2kstarmumu_parameters* params, bool weighted); + double angular_pswave_norm(const bu2kstarmumu_parameters* params, bool weighted); + }; + + +} + +struct npolynom{ + unsigned int ctl; + unsigned int ctk; + unsigned int phi; + unsigned int q2; + + unsigned int getSize(){ + return q2*ctl*ctk*phi; + } + + unsigned int getSize2(){ + return getSize()*getSize(); + } + + npolynom(fcnc::options *opts){ + //Set orders of chebyshev polynomials + ctl = opts->eff_order_costhetal; + ctk = opts->eff_order_costhetak; + phi = opts->eff_order_phi; + q2 = opts->eff_order_q2; + //spdlog::trace("phi: {0:d}", phi); + //spdlog::trace("opts->eff_order_phi: {0:d}", opts->eff_order_phi); + } + unsigned int get_bin_in4D(int h, int i, int j, int k); +}; + + +#endif diff --git a/Code/FCNCFitter/sources/Core/bu2kstarmumu_plotter.cc b/Code/FCNCFitter/sources/Core/bu2kstarmumu_plotter.cc new file mode 100755 index 0000000..b021306 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/bu2kstarmumu_plotter.cc @@ -0,0 +1,2625 @@ +//Renata Kopecna + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +//possible TODO when bored: This could be shortened even further, but I cannot be bothered at the moment + +//Bkg plots were very flat resulting in the plots sometimes having too large minimum, so set manualy now +const double minBkg = 0.0; + +using namespace fcnc; + +bu2kstarmumu_plotter::bu2kstarmumu_plotter(options* o): + opts(o) +{ + gROOT->SetStyle("Plain"); + + TPad foo; + const int NRGBs = 5; + const int NCont = 250; + + double stops[NRGBs] = { 0.00, 0.45, 0.60, 0.74, 1.00 }; + double red[NRGBs] = { 0.00, 0.00, 0.52, 1.00, 0.41 }; + double green[NRGBs] = { 0.00, 0.61, 1.00, 0.35, 0.00 }; + double blue[NRGBs] = { 0.68, 1.00, 0.12, 0.00, 0.00 }; + + TColor::CreateGradientColorTable(NRGBs, stops, red, green, blue, NCont); + gStyle->SetNumberContours(NCont); + gStyle->SetLabelFont(132, "xyz"); + gStyle->SetTitleFont(132, "xyz"); + gStyle->SetLegendFont(132); + gStyle->SetStatFont(132); + gStyle->SetEndErrorSize(10.0); //Sets the lenght of the tiny bars at the end of error bars + + //by default draw pulls underneath the 1D projections: + this->pulls = true; + +}; + +bu2kstarmumu_plotter::~bu2kstarmumu_plotter() +{ +}; + + +int bu2kstarmumu_plotter::plot_data(bu2kstarmumu_pdf* prob, bu2kstarmumu_parameters* params, std::vector* events, std::string prefix, std::string postfix, bool signalregion){ + //Calls plot_m, plot_mkpi and plot_angle + if(events->size() == 0){ + spdlog::error("Cannot plot empty event histograms!"); + return 404; + } + + spdlog::debug("Plotting of projections started."); + prob->update_cached_normalization(params); + spdlog::trace("Normalization updated."); + output = new TFile((opts->plot_folder+"projections_" + opts->name + ".root").c_str(), "UPDATE"); + spdlog::debug("Created file " + std::string(output->GetPath())); + std::string logstr = std::string("log_")+postfix; + spdlog::trace("TFile created."); + + //m(B) + if(!opts->only_angles && !opts->only_mkpi){ + spdlog::debug("Plotting B mass."); + plot_m(prob, params, events, prefix, postfix, false, false); + plot_m(prob, params, events, prefix, logstr , true, false); + } + + //m(Kpi) + if (opts->fit_mkpi || opts->use_mkpi){ + plot_mkpi(prob, params, events, prefix, postfix, signalregion, false, false); + } + + //angles + if(!opts->only_Bmass && !opts->only_mass2DFit && !opts->only_mkpi){ + spdlog::debug("Plotting angles."); + plot_angle(prob, params, events, prefix, postfix, signalregion, "ctl", false); + plot_angle(prob, params, events, prefix, postfix, signalregion, "ctk", false); + plot_angle(prob, params, events, prefix, postfix, signalregion, "phi", false); + } + output->Close(); + delete output; + return 0; +}; + + +//Few functions making pretty TH1Ds + +int design_pdfLine(TH1D *pdf, Color_t lineColor, Style_t lineStyle){ + pdf->SetLineWidth(2.0); + pdf->SetLineColor(lineColor); + pdf->SetLineStyle(lineStyle); + pdf->GetXaxis()->SetNoExponent(kTRUE); + return 0; +} + +int design_pdfLine(TH1D *pdf, Color_t lineColor, Style_t lineStyle, int lineWidth){ + pdf->SetLineWidth(lineWidth); + pdf->SetLineColor(lineColor); + pdf->SetLineStyle(lineStyle); + pdf->GetXaxis()->SetNoExponent(kTRUE); + return 0; +} + +int design_plot(TH1D *plot, int markerStyle, bool printC){ + plot->SetMarkerStyle(markerStyle); + plot->SetMarkerSize(printC ? 1.0 : 2.0); + plot->GetXaxis()->SetNoExponent(kTRUE); + return 0; +} + +TLatex *design_TLatex(double texsizelarge, double texsizesmall, double pullHeight, double pos, + bool pulls, std::string plot_label, std::string q2_label){ + + TLatex *tex = getPrettyTex(texsizelarge,11); + + + if(pulls) tex->SetTextSize(texsizelarge/(1 - pullHeight)); + tex->DrawLatexNDC(pos,(pulls ? (0.8 - pullHeight)/(1 - pullHeight) : 0.8),plot_label.c_str()); + + if(PLOT_THISTHESIS_TAG){ + tex->DrawLatexNDC(0.7,(pulls ? (0.82 - pullHeight)/(1 - pullHeight) : 0.82),THISTHESIS_TAG.c_str()); + } + + tex->SetTextSize(texsizesmall); + if(pulls) tex->SetTextSize(texsizesmall/(1 - pullHeight)); + tex->DrawLatexNDC(pos,(pulls ? (0.74 - pullHeight)/(1 - pullHeight) : 0.74),q2_label.c_str()); + + return tex; +} + +int bu2kstarmumu_plotter::design_pdf(TH1D *pdf, Color_t lineColor, Color_t fillColor, + int fillStyle, double eff_pullHeight, bool doPull){ + pdf->SetLineWidth(2.0); + pdf->SetLineColor(lineColor); + pdf->SetFillStyle(fillStyle); + pdf->SetFillColor(fillColor); + pdf->GetXaxis()->SetNoExponent(kTRUE); + if(doPull){ + Float_t textsize = gStyle->GetTextSize(); + design_pull_basic(pdf, textsize, eff_pullHeight); + pdf->GetXaxis()->SetTickLength(pdf->GetXaxis()->GetTickLength()/eff_pullHeight); + + pdf->GetXaxis()->SetTitle(""); + pdf->GetXaxis()->SetLabelSize(0.0);//don't print labels + pdf->GetYaxis()->SetNdivisions(gStyle->GetNdivisions("Y")); + } + return 0; +} + + +//Plot (log) mass +void bu2kstarmumu_plotter::plot_m(bu2kstarmumu_pdf* prob, bu2kstarmumu_parameters* params, std::vector* events, std::string prefix, std::string postfix, bool logarithmic, bool printC) +{ + unsigned int m_bins = opts->plots_m_bins; + double m_min = params->m_b.get_min(); + double m_max = params->m_b.get_max(); + double fsig = params->f_sig(); + if (opts->extended_ml){ + fsig = params->n_sig()/(params->n_sig()+params->n_bkg()); + } + + TCanvas *m_canvas = nullptr; + std::string m_canvas_name = "Bplus Likelihood Analysis: #it{m}(#it" +latex_decay(opts->DTF) +") mass projection"; + if(printC) m_canvas = new TCanvas(("m_"+postfix).c_str(), m_canvas_name.c_str()) ; + else m_canvas = new TCanvas(("m_"+postfix).c_str(), m_canvas_name.c_str(),1600,1200); + + const double pullHeight = 0.27; + const double pullFrameRange = 6.5; + TPad *pad1 = new TPad("pad1", "plot",0.0,pullHeight,1.0,1.0,0); + TPad *pad2 = new TPad("pad2", "pull",0.0,0.0,1.0,pullHeight,0); + if(this->pulls){ + pad1->Draw(); + pad2->Draw(); + pad1->SetLogy(logarithmic); + pad1->SetBorderSize (0); + pad1->SetMargin(0.125,0.1,1e-6,0.1/ (1 - pullHeight)); + pad1->SetTickx(); + pad1->SetTicky(); + pad1->cd(); + } + else{ + m_canvas->cd()->SetMargin(0.125,0.1,0.125,0.1); + m_canvas->SetLogy(logarithmic); + m_canvas->SetTickx(); + m_canvas->SetTicky(); + } + + std::ostringstream sout; + sout << ";#it{m}(" + latex_decay(opts->DTF) + ") ["+MeVc()+"];" << EVENTS_TAG << " / " << std::setprecision(2) << (m_max-m_min)/m_bins << " "+MeVc()+""; + + TH1D* m_plot_sig = new TH1D("msig", sout.str().c_str(), m_bins, m_min, m_max); + TH1D* m_plot_bkg = new TH1D("mbkg", sout.str().c_str(), m_bins, m_min, m_max); + TH1D* m_plot = new TH1D("m", sout.str().c_str(), m_bins, m_min, m_max); + m_plot->Sumw2(); + std::ostringstream spulls; + spulls << ";#it{m}(" + latex_decay(opts->DTF) + ") ["+MeVc()+"];" + latex_pull(); + + + TH1D* m_pulls = new TH1D("mpulls", spulls.str().c_str(), m_bins, m_min, m_max); + spdlog::trace("Filling the histograms with {0:d} events.", events->size()); + double nevents = 0.0; + for (auto evt: *events){ + double weight = 1.0; + if(opts->weighted_fit) weight = evt.weight; + if(evt.event_type == 0) m_plot_sig->Fill(evt.m, weight); + else m_plot_bkg->Fill(evt.m, weight); + m_plot->Fill(evt.m, weight); + nevents += weight; + } + spdlog::trace("Filled."); + const int bin_ratio = 20; + unsigned int pdf_bins = m_bins*bin_ratio; + if (pdf_bins == 0) spdlog::critical("No PDF bins!"); + double dm = (m_max-m_min)/pdf_bins; + TH1D* pdf_sig = new TH1D("pdf_sig", sout.str().c_str(), pdf_bins, m_min, m_max); + TH1D* pdf_bkg = new TH1D("pdf_bkg", sout.str().c_str(), pdf_bins, m_min, m_max); + TH1D* pdf_tot = new TH1D("pdf_tot", sout.str().c_str(), pdf_bins, m_min, m_max); + + spdlog::trace("Getting parameter values..."); + double m_b = params->m_b(); + double m_scale = params->m_scale(); + double f_res = params->m_res_1(); + double sigma_1 = params->m_sigma_1(); + double sigma_2 = params->m_sigma_2(); + double alpha_1 = opts->crystalball || opts->twotailedcrystalball ? params->alpha_1() : 0.; + double alpha_2 = opts->crystalball || opts->twotailedcrystalball ? params->alpha_2() : 0.; + double n_1 = opts->crystalball || opts->twotailedcrystalball ? params->n_1() : 0.; + double n_2 = opts->crystalball || opts->twotailedcrystalball ? params->n_2() : 0.; + + double prob_sig = 0.0, prob_bkg = 0.0, from = 0.0, to = 0.0; + + double integral1 = 1.0, integral2 = 1.0; + spdlog::trace("Integrating..."); + if(opts->crystalball){ + integral1 = integrate_crystalball(m_b, m_scale*sigma_1, alpha_1, n_1, m_min, m_max); + integral2 = integrate_crystalball(m_b, m_scale*sigma_2, alpha_2, n_2, m_min, m_max); + } + else if(opts->twotailedcrystalball){ + integral1 = integrate_twotailedcrystalball(m_b, m_scale*sigma_1, alpha_1, alpha_2, n_1, n_2, m_min, m_max); + } + else{ + integral1 = integrate_gauss(m_scale*sigma_1, m_b, m_min, m_max); + integral2 = integrate_gauss(m_scale*sigma_2, m_b, m_min, m_max); + } + if (isnan(integral1) || isnan(integral2)){ + spdlog::critical("integral1 is NaN"); + return; + } + + spdlog::trace("Getting signal prob..."); + for (unsigned int i = 0; i < pdf_bins; i++){ + from = m_min + i*dm; + to = m_min + (i+1)*dm; + prob_sig = 0.0; + if (opts->crystalball){ + prob_sig = integrate_crystalball(m_b, m_scale*sigma_1, alpha_1, n_1, from, to) / integral1; + if (f_res != 1.0){ + prob_sig *= f_res; + prob_sig += (1.0-f_res) + * integrate_crystalball(m_b, m_scale*sigma_2, alpha_2, n_2, from, to) / integral2; + } + } + else if(opts->twotailedcrystalball){ + prob_sig = integrate_twotailedcrystalball(m_b, m_scale*sigma_1, alpha_1, alpha_2, n_1, n_2, from, to) / integral1; + } + else{ + prob_sig = integrate_gauss(m_scale*sigma_1, m_b, from, to) / integral1; + if (f_res != 1.0){ + prob_sig *= f_res; + prob_sig += (1.0 - f_res) + * integrate_gauss(m_scale*sigma_2, m_b, from, to) / integral2; + } + } + if (isnan(prob_sig)){ + spdlog::critical("prob_sig is nan"); + spdlog::critical("pdf bin {0:d}, edges: {1:f}-{2:f}", i, pdf_sig->GetBinLowEdge(i+1), pdf_sig->GetBinLowEdge(i+2)); + return; + } + + pdf_sig->SetBinContent(i+1, prob_sig); + prob_bkg = prob->integral_m_bkg_prob(params, from, to); + if (isnan(prob_bkg)){ + spdlog::error("prob_bkg is nan"); + spdlog::error("pdf bin {0:d}, edges: {1:f}-{2:f}", i, from, to); + spdlog::error("Setting prob_bkg to ZERO!"); + prob_bkg = 0; + } + pdf_bkg->SetBinContent(i+1, prob_bkg); + } + + pdf_sig->Scale(nevents * fsig * double(pdf_bins) / double(m_bins)); + pdf_bkg->Scale(nevents * (1.0-fsig) * double(pdf_bins) / double(m_bins)); + pdf_tot->Add(pdf_sig, pdf_bkg); + + spdlog::trace("Making the plots pretty..."); + double maxpdf = (pdf_tot->GetMaximum() > m_plot->GetMaximum() ? pdf_tot->GetMaximum() : m_plot->GetMaximum()); + if(this->pulls){ + if (logarithmic) pdf_sig->SetMinimum(0.1001); + else pdf_sig->SetMinimum(0.001); + } + else{ //no pull distributions + if (logarithmic) pdf_sig->SetMinimum(0.1); + else pdf_sig->SetMinimum(0.0); + } + pdf_sig->SetMaximum(1.45*maxpdf); + + pdf_bkg->SetTitleSize(0.06, "XY"); + pdf_bkg->SetLabelSize(0.05, "XY"); + pdf_bkg->SetTitleOffset(0.9, "XY"); + pdf_bkg->GetXaxis()->SetNoExponent(kTRUE); + TGaxis::SetMaxDigits(3); + + design_pdf(pdf_sig, kAzure, kAzure-5, 1001, 1-pullHeight, this->pulls); + if(pdf_sig->Integral() > 0.0) pdf_sig->Draw("hist C"); + + design_pdf(pdf_bkg, kOrange+10, kOrange+8, 3354, 1-pullHeight, pdf_sig->Integral() <= 0.0 ); + if(pdf_sig->Integral() > 0.0){ + pdf_bkg->Draw("hist same C"); + } + else{ + pdf_bkg->SetMaximum(1.45*maxpdf); + pdf_bkg->SetMinimum(minBkg); + pdf_bkg->Draw("hist C"); + } + + design_pdfLine(pdf_tot,kBlack,2.0); + pdf_tot->Draw("hist same C"); + + design_plot(m_plot,20,printC); + m_plot->Draw("same e1"); + if (m_plot_bkg->Integral() != 0){ + design_pdfLine(m_plot_sig,4,kSolid); + m_plot_sig->Draw("esame"); + design_pdfLine(m_plot_bkg,2,kSolid); + if (params->f_sig() != 1.0) m_plot_bkg->Draw("esame"); + } + + //draw legend + spdlog::trace("Drawing legend..."); + TLegend* m_leg = new TLegend(0.675,0.45,0.875,0.65); + m_leg->SetBorderSize(0); + m_leg->SetTextFont(132); + m_leg->SetFillColor(0); + m_leg->AddEntry(m_plot, "data", "le"); + m_leg->AddEntry(pdf_tot, "total PDF", "l"); + m_leg->AddEntry(pdf_sig, "signal PDF", "l"); + m_leg->AddEntry(pdf_bkg, "bkg PDF", "l"); + //m_leg->Draw(); + TLatex *tex = design_TLatex(texsizelarge,texsizesmall, pullHeight, 0.47, + this->pulls, opts->plot_label, opts->q2_label); + if(this->pulls){ + spdlog::trace("Drawing pulls..."); + assert(pdf_bins == m_bins*bin_ratio); + + //calculate pulls from fit and data points: + for(UInt_t b = 1; b <= m_bins; b++){ + double p; + if(m_plot->GetBinError(b) == 0) p = 0.; + else{ + if(bin_ratio == 1){ + p = (m_plot->GetBinContent(b) - pdf_tot->GetBinContent(b))/m_plot->GetBinError(b); + } + //for odd ratio, take central bin from pdf w.r.t to m_bin: + else if(bin_ratio%2 != 0){ + p = (m_plot->GetBinContent(b) - pdf_tot->GetBinContent(b*bin_ratio - bin_ratio/2))/m_plot->GetBinError(b); + } + //else, average the two central bins from pdf w.r.t. to angle_bin: + else{ + p = (m_plot->GetBinContent(b) - (pdf_tot->GetBinContent(b*bin_ratio - bin_ratio/2)+pdf_tot->GetBinContent(b*bin_ratio - bin_ratio/2 + 1))/2. ) / m_plot->GetBinError(b); //take central of 10 pdfbins + } + } + m_pulls->SetBinContent(b, p); + } + pad2->Clear(); + pad2->SetMargin(0.125,0.1,0.125/ pullHeight, 1e-6); + pad2->SetTickx(); + pad2->cd(); + + design_pull(m_pulls, kBlack,kGray+2,pullHeight,pullFrameRange); + m_pulls->Draw(); + + //add two 3-sigma lines: + TLine * lUp = threeSigmaLine(m_min, m_max, true); + TLine * lLow = threeSigmaLine(m_min, m_max, false); + lUp->Draw("same"); + lLow->Draw("same"); + } + + std::string mname = prefix + "m_" + postfix; + spdlog::debug("Writting into " + mname); + saveTCanvas(m_canvas,mname,opts->getAllPlotTypes()); + + output->cd(); + m_canvas->Write(); + + delete m_plot; + delete m_plot_sig; + delete m_plot_bkg; + delete pdf_sig; + delete pdf_bkg; + delete pdf_tot; + delete m_pulls; + delete m_canvas; + delete tex; +}; + +void bu2kstarmumu_plotter::plot_mkpi(bu2kstarmumu_pdf* prob, bu2kstarmumu_parameters* params, std::vector* events, std::string prefix, std::string postfix, bool signalregion, bool logarithmic, bool printC) +{ + double ma = params->m_b() - B_MASS_TIGHT_WINDOW; + double mb = params->m_b() + B_MASS_TIGHT_WINDOW; + double fsig = params->f_sig(); + if(opts->extended_ml){ + fsig = params->n_sig() / (params->n_sig()+params->n_bkg()); + } + if(signalregion){ + double rsig = prob->integral_m_sig_prob(params, ma, mb); + double rbkg = prob->integral_m_bkg_prob(params, ma, mb); + fsig = fsig*rsig/(fsig*rsig + (1.0-fsig)*rbkg); + } + + unsigned int mkpi_bins = opts->plots_mkpi_bins; + double mkpi_min = opts->mkpi_min/1.0e+3; + double mkpi_max = opts->mkpi_max/1.0e+3; + + TCanvas *mkpi_canvas = nullptr; + std::string mkpi_canvas_name = "B plus Likelihood Analysis: #it{m}(#it"+ latex_Kst_decay(opts->DTF) +") ["+GeVc()+"]"; + if(printC){ + mkpi_canvas = new TCanvas(("mkpi_"+postfix).c_str(), mkpi_canvas_name.c_str()); + } + else{ + mkpi_canvas = new TCanvas(("mkpi_"+postfix).c_str(), mkpi_canvas_name.c_str(),1600,1200) ; + } + const double pullHeight = 0.27; + const double pullFrameRange = 6.5; + TPad *pad1 = new TPad("pad1", "plot",0.0,pullHeight,1.0,1.0,0); + TPad *pad2 = new TPad("pad2", "pull",0.0,0.0,1.0,pullHeight,0); + if(this->pulls){ + pad1->Draw(); + pad2->Draw(); + pad1->SetLogy(logarithmic); + pad1->SetBorderSize (0); + pad1->SetMargin(0.125,0.1,1e-6,0.1/ (1 - pullHeight)); + pad1->SetTickx(); + pad1->SetTicky(); + pad1->cd(); + } + else{ + mkpi_canvas->cd()->SetMargin(0.125,0.1,0.125,0.1); + mkpi_canvas->SetTickx(); + mkpi_canvas->SetTicky(); + } + + std::ostringstream sout; + sout << ";#it{m}(#it{K}^{+}#pi^{-}) ["+GeVc()+"];" << EVENTS_TAG << " / " << std::setprecision(2) << (mkpi_max-mkpi_min)/mkpi_bins << " GeV^{2}/#it{c}^{4}"; + TH1D* mkpi_plot_sig = new TH1D("mkpi_sig", sout.str().c_str(), mkpi_bins, mkpi_min, mkpi_max); + TH1D* mkpi_plot_bkg = new TH1D("mkpi_bkg", sout.str().c_str(), mkpi_bins, mkpi_min, mkpi_max); + TH1D* mkpi_plot = new TH1D("mkpi", sout.str().c_str(), mkpi_bins, mkpi_min, mkpi_max); + + mkpi_plot->Sumw2(); + std::string spulls = ";#it{m}("+ latex_Kst_decay(opts->DTF) +") ["+GeVc()+"];" + latex_pull(); + + TH1D* mkpi_pulls = new TH1D("mkpipulls", spulls.c_str(), mkpi_bins, mkpi_min, mkpi_max); + double nevents = 0.0; + + for (auto evt: *events){ + if (!signalregion || (evt.m > ma && evt.m < mb)){ + double weight = 1.0; + double mkpi = evt.mkpi/1.0e+3; + if (opts->weighted_fit){ + weight = evt.weight; + mkpi_plot->Fill(mkpi, weight); + } + else mkpi_plot->Fill(mkpi); + + if(evt.event_type == 0) mkpi_plot_sig->Fill(mkpi, weight); + else mkpi_plot_bkg->Fill(mkpi, weight); + nevents += weight; + } + } + + const UInt_t bin_ratio = PLOT_NBINS_RATIO; + unsigned int pdf_bins = mkpi_bins*bin_ratio; + double dm = (mkpi_max-mkpi_min)/pdf_bins; + TH1D* pdf_sig = new TH1D("pdf_sig", sout.str().c_str(), pdf_bins, mkpi_min, mkpi_max); + TH1D* pdf_swave = new TH1D("pdf_swave", sout.str().c_str(), pdf_bins, mkpi_min, mkpi_max); + TH1D* pdf_pwave = new TH1D("pdf_pwave", sout.str().c_str(), pdf_bins, mkpi_min, mkpi_max); + TH1D* pdf_interference = new TH1D("pdf_interference", sout.str().c_str(), pdf_bins, mkpi_min, mkpi_max); + TH1D* pdf_bkg = new TH1D("pdf_bkg", sout.str().c_str(), pdf_bins, mkpi_min, mkpi_max); + TH1D* pdf_tot = new TH1D("pdf_tot", sout.str().c_str(), pdf_bins, mkpi_min, mkpi_max); + + double gammakstar = params->gammakstar(); + double mkstar = params->mkstar(); + double asphase = params->asphase(); + double a = params->a(); + double r = params->r(); + double R = params->R(); + + double gammakstarplus = params->gammakstarplus(); + double mkstarplus = params->mkstarplus(); + double gammaf800 = params->gammaf800(); + double mf800 = params->mf800(); + double f800mag = params->f800mag(); + double f800phase = params->f800phase(); + + double normbkg=0.0; + std::vector ch_mkpi(5, 0.0); + ch_mkpi.at(0) = params->cbkgmkpi0(); + ch_mkpi.at(1) = params->cbkgmkpi1(); + ch_mkpi.at(2) = params->cbkgmkpi2(); + ch_mkpi.at(3) = params->cbkgmkpi3(); + ch_mkpi.at(4) = params->cbkgmkpi4(); + std::vector poly_mkpi(ch_mkpi.size(), 0.0); + chebyshev_to_poly(ch_mkpi, poly_mkpi); + std::vector poly_corr_mkpi(ch_mkpi.size(), 0.0); + correct_poly(poly_mkpi, poly_corr_mkpi, mkpi_min, mkpi_max); + + if (opts->mkpi_threshold){ + normbkg = fcnc::int_threshold(mkpi_min, mkpi_max, 0.633, params->nthreshold()); + } + else{ + for (unsigned int i=0; ieff_q2(); + double rangednormkstarplus, rangednormkstar; + + if (opts->simple_mkpi){ + rangednormkstarplus = int_mkpi_simple_kstarzero_amp_squared(mkpi_min, mkpi_max, q2, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus); + rangednormkstar = int_mkpi_simple_bw_kstar_amp_squared(mkpi_min, mkpi_max, q2, gammakstar, mkstar); + } + else if(opts->isobar){ + rangednormkstarplus = int_mkpi_kstarzero_isobar_amp_squared(mkpi_min, mkpi_max, q2, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus, R); + rangednormkstar = int_mkpi_bw_kstar_amp_squared(mkpi_min, mkpi_max, q2, gammakstar, mkstar, R); + } + else{ + rangednormkstarplus = int_mkpi_kstarzero_lass_amp_squared(mkpi_min, mkpi_max, q2, asphase, a, r, gammakstarplus, mkstarplus, R); + rangednormkstar = int_mkpi_bw_kstar_amp_squared(mkpi_min, mkpi_max, q2, gammakstar, mkstar, R); + } + + double sxi1, sxi2, sxi3, sxi4, sxi5, sxi6; + + //weighted fit and fit without acceptance + if (opts->use_angular_acc)prob->swave_integrated_fj_chebyshev(sxi1, sxi2, sxi3, sxi4, sxi5, sxi6, q2); + else prob->swave_integrated_fj_noacc(sxi1, sxi2, sxi3, sxi4, sxi5, sxi6); + + double xi1, xi2, xi3, xi4, xi5, xi6, xi7, xi8, xi9, xi10, xi11, xi12; + if (opts->use_angular_acc){ + prob->integrated_fj_chebyshev(xi1, xi2, xi3, xi4, xi5, xi6, + xi7, xi8, xi9, xi10, xi11, xi12, q2); + } + else{//weighted fit and fit without acceptance + prob->integrated_fj_noacc(xi1, xi2, xi3, xi4, xi5, xi6, + xi7, xi8, xi9, xi10, xi11, xi12); + } + + double s1s = params->J1s(); + double s1c = params->J1c(); + double s2s = params->J2s(); + double s2c = params->J2c(); + double s3 = params->J3(); + double s4 = params->J4(); + double s5 = params->J5(); + double s6s = params->J6s(); + double s6c = params->J6c(); + double s7 = params->J7(); + double s8 = params->J8(); + double s9 = params->J9(); + double fs = params->FS(); + double ss1 = params->SS1(); + double ss2 = params->SS2(); + double ss3 = params->SS3(); + double ss4 = params->SS4(); + double ss5 = params->SS5(); + + double norm = + (1-fs)*(xi1*s1s + xi2*s1c + xi3*s2s + xi4*s2c + xi5*s3 + xi6*s4 + + xi7*s5 + xi8*s6s + xi9*s6c + xi10*s7 + xi11*s8 + xi12*s9) + +(sxi1*fs + sxi2*ss1 + sxi3*ss2 + sxi4*ss3 + sxi5*ss4 + sxi6*ss5); + double A = (xi1*s1s + xi2*s1c + xi3*s2s + xi4*s2c + xi5*s3 + xi6*s4 + + xi7*s5 + xi8*s6s + xi9*s6c + xi10*s7 + xi11*s8 + xi12*s9)/norm; + double B = sxi1/norm; + double C = (sxi2*ss1 + sxi3*ss2 + sxi4*ss3)/norm; + double D = (sxi5*ss4 + sxi6*ss5)/norm; + + double prob_bkg = 0.0, from = 0.0, to = 0.0; + for (unsigned int i = 0; i < pdf_bins; i++){ + + from = mkpi_min + i*dm; + to = mkpi_min + (i+1)*dm; + + double swavesq, pwavesq; + std::complex stimespwave; + + if (opts->simple_mkpi){ + swavesq = fcnc::int_mkpi_simple_kstarzero_amp_squared(from, to, q2, + f800mag, f800phase, gammaf800, mf800, + gammakstarplus, mkstarplus); + pwavesq = fcnc::int_mkpi_simple_bw_kstar_amp_squared(from, to, q2, gammakstar, mkstar); + stimespwave = fcnc::int_mkpi_simple_bw_kstar_amp_bar_kstarzero_amp(from, to, q2, + gammakstar, mkstar, asphase, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus); + } + else if (opts->isobar){ + swavesq = fcnc::int_mkpi_kstarzero_isobar_amp_squared(from, to, q2, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus, R); + pwavesq = fcnc::int_mkpi_bw_kstar_amp_squared(from, to, q2, gammakstar, mkstar, R); + stimespwave = fcnc::int_mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(from, to, q2, + gammakstar, mkstar, asphase, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus, R); + } + else{//nominal lass + swavesq = fcnc::int_mkpi_kstarzero_lass_amp_squared(from, to, q2, asphase, a, r, gammakstarplus, mkstarplus, R); + pwavesq = fcnc::int_mkpi_bw_kstar_amp_squared(from, to, q2, gammakstar, mkstar, R); + stimespwave = fcnc::int_mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(from, to, q2, + gammakstar, mkstar, + asphase, a, r, gammakstarplus, mkstarplus, R); + } + + prob_bkg = 0.0; + if (opts->mkpi_threshold){ + prob_bkg = fcnc::int_threshold(from, to, 0.633, params->nthreshold()); + } + else{ + for (unsigned int i=0; iSetBinContent(i+1, (1.0-fs)*pwave + fs*swave + interference); + pdf_bkg->SetBinContent(i+1, prob_bkg); + pdf_swave->SetBinContent(i+1, swave); + pdf_pwave->SetBinContent(i+1, pwave); + pdf_interference->SetBinContent(i+1, interference); + pdf_tot->SetBinContent(i+1, + fsig*((1.0-fs)*pwave + fs*swave + interference) + + (1.0-fsig)*prob_bkg); + } + + pdf_sig ->Scale(nevents * fsig * double(pdf_bins) / double(mkpi_bins)); + pdf_swave->Scale(nevents * fs*fsig * double(pdf_bins) / double(mkpi_bins)); + pdf_pwave->Scale(nevents * (1.0-fs)*fsig * double(pdf_bins) / double(mkpi_bins)); + pdf_interference->Scale(nevents * fsig * double(pdf_bins) / double(mkpi_bins)); + pdf_bkg ->Scale(nevents * (1.0-fsig) * double(pdf_bins) / double(mkpi_bins)); + pdf_tot ->Scale(nevents * double(pdf_bins) / double(mkpi_bins)); + + double maxpdf = (pdf_tot->GetMaximum() > mkpi_plot->GetMaximum() ? pdf_tot->GetMaximum() : mkpi_plot->GetMaximum()); + if(this->pulls){ + if (logarithmic) pdf_sig->SetMinimum(0.1001); + else pdf_sig->SetMinimum(0.001); + } + else{ //no pull distributions + if (logarithmic) pdf_sig->SetMinimum(0.1); + else pdf_sig->SetMinimum(0.0); + } + + pdf_sig->SetMaximum(1.45*maxpdf); + design_pdf(pdf_sig,kAzure, kAzure-5, 1001, 1-pullHeight, this->pulls); + if(pdf_sig->Integral() > 0.0) pdf_sig->Draw("hist C"); + + design_pdf(pdf_bkg,kOrange+10,kOrange+8, 3354, 1-pullHeight,pdf_sig->Integral() <= 0.0 ); + + if(pdf_sig->Integral() > 0.0){ + pdf_bkg->Draw("hist same C"); + } + else{ + pdf_bkg->SetMaximum(1.45*maxpdf); + pdf_bkg->SetMinimum(0.5); + pdf_bkg->Draw("hist C"); + } + + design_pdfLine(pdf_pwave, pWaveColor, kDashed); + if(opts->swave) pdf_pwave->Draw("hist same C"); + + design_pdfLine(pdf_swave, sWaveColor, kDotted); + if(opts->swave) pdf_swave->Draw("hist same C"); + + design_pdfLine(pdf_interference, psInterferenceColor, kDashDotted); + if(opts->swave) pdf_interference->Draw("hist same C"); + + design_pdfLine(pdf_tot, kBlack, kSolid); + pdf_tot->Draw("hist same C"); + + design_plot(mkpi_plot, 20, printC); + design_pdfLine(mkpi_plot, kBlack, kSolid, 1.0); + mkpi_plot->Draw("same e1"); + + //draw legend + TLegend* mkpi_leg = new TLegend(0.675,0.45,0.875,0.65); + mkpi_leg->SetBorderSize(0); + mkpi_leg->SetTextFont(132); + mkpi_leg->SetFillColor(0); + mkpi_leg->AddEntry(mkpi_plot, "data", "le"); + mkpi_leg->AddEntry(pdf_tot, "total PDF", "l"); + mkpi_leg->AddEntry(pdf_sig, "signal PDF", "l"); + mkpi_leg->AddEntry(pdf_bkg, "bkg PDF", "l"); + if(opts->swave){ + mkpi_leg->AddEntry(pdf_pwave, "P-wave PDF", "l"); + mkpi_leg->AddEntry(pdf_swave, "S-wave PDF", "l"); + mkpi_leg->AddEntry(pdf_interference, "interference PDF", "l"); + } + + TLatex *tex = design_TLatex(texsizelarge,texsizesmall, pullHeight, 0.67, + this->pulls, opts->plot_label,opts->q2_label); + + if(this->pulls){ + assert(pdf_bins == mkpi_bins*bin_ratio); + + //calculate pulls from fit and data points: + for(UInt_t b = 1; b <= mkpi_bins; b++){ + double p; + if(mkpi_plot->GetBinError(b) == 0){ + p = 0.; + } + else{ + if(bin_ratio == 1){ + p = (mkpi_plot->GetBinContent(b) - pdf_tot->GetBinContent(b))/mkpi_plot->GetBinError(b); + } + //for odd ratio, take central bin from pdf w.r.t to m_bin: + else if(bin_ratio%2 != 0){ + p = (mkpi_plot->GetBinContent(b) - pdf_tot->GetBinContent(b*bin_ratio - bin_ratio/2))/mkpi_plot->GetBinError(b); + } + //else, average the two central bins from pdf w.r.t. to angle_bin: + else{ + p = (mkpi_plot->GetBinContent(b) - (pdf_tot->GetBinContent(b*bin_ratio - bin_ratio/2)+pdf_tot->GetBinContent(b*bin_ratio - bin_ratio/2 + 1))/2. ) / mkpi_plot->GetBinError(b); //take central of 10 pdfbins + } + } + mkpi_pulls->SetBinContent(b, p); + } + pad2->Clear(); + pad2->SetMargin(0.125,0.1,0.125/ pullHeight, 1e-6); + pad2->SetTickx(); + pad2->cd(); + + design_pull(mkpi_pulls, kBlack,kGray+2,pullHeight,pullFrameRange); + mkpi_pulls->Draw(); + + //add two 3-sigma lines: + TLine * lUp = threeSigmaLine(mkpi_min, mkpi_max, true); + TLine * lLow = threeSigmaLine(mkpi_min, mkpi_max, false); + lUp->Draw("same"); + lLow->Draw("same"); + } + + std::string mkpiname = prefix + "mkpi_" + postfix; + saveTCanvas(mkpi_canvas, mkpiname, opts->getAllPlotTypes()); + + output->cd(); + mkpi_canvas->Write(); + + delete mkpi_plot; + delete mkpi_plot_sig; + delete mkpi_plot_bkg; + delete pdf_sig; + delete pdf_swave; + delete pdf_pwave; + delete pdf_interference; + delete pdf_bkg; + delete pdf_tot; + delete mkpi_pulls; + delete mkpi_canvas; + delete tex; +}; + +void bu2kstarmumu_plotter::plot_angle(bu2kstarmumu_pdf* prob, bu2kstarmumu_parameters* params, std::vector* events, std::string prefix, std::string postfix, bool signalregion, std::string angle, bool printC){ //signal region: plots only stuff within B_MASS_TIGHT_WINDOW MeV B mass window + + bool is_ctl = false, is_ctk = false, is_phi = false; + std::string angle_name = latex_angle(angle, is_ctl, is_ctk, is_phi); + spdlog::debug("angle:{0:s}\tctl:{1:d}\tctk:{2:d}\tphi:{3:d}",angle, is_ctl, is_ctk, is_phi); + if(!is_ctl && !is_ctk && !is_phi)spdlog::error("Invalid angle name is given: " + angle); + assert(is_ctl || is_ctk || is_phi); + + double ma = params->m_b() - B_MASS_TIGHT_WINDOW; + double mb = params->m_b() + B_MASS_TIGHT_WINDOW; + double fsig = params->f_sig(); + if(opts->extended_ml) fsig = params->n_sig() / (params->n_sig()+params->n_bkg()); + + if (signalregion){ + double rsig = prob->integral_m_sig_prob(params, ma, mb); + double rbkg = prob->integral_m_bkg_prob(params, ma, mb); + fsig = fsig*rsig/(fsig*rsig + (1.0-fsig)*rbkg); + } + unsigned int angle_bins = 0; + double angle_min = 0.; + double angle_max = 0.; + + if(is_ctl){ + angle_bins = opts->plots_costhetal_bins; + angle_min = opts->ctl_min; + angle_max = opts->ctl_max; + if(!opts->full_angular && opts->folding != 0) angle_bins /= 2; + } + else if(is_ctk){ + angle_bins = opts->plots_costhetak_bins; + angle_min = opts->ctk_min; + angle_max = opts->ctk_max; + } + else if(is_phi){ + angle_bins = opts->plots_phi_bins; + angle_min = opts->phi_min; + angle_max = opts->phi_max; + if(!opts->full_angular) angle_bins /= 2; + } + + assert(angle_min != 0. || angle_max != 0.); + + TCanvas *angle_canvas = nullptr; + if(printC) angle_canvas = new TCanvas((angle+"_"+postfix).c_str(), ("B+ Likelihood Analysis: "+angle_name+" projection").c_str()); + else angle_canvas = new TCanvas((angle+"_"+postfix).c_str(), ("B+ Likelihood Analysis: "+angle_name+" projection").c_str(),1600,1200); + const double pullHeight = 0.27; + const double pullFrameRange = 6.5; + TPad *pad1 = new TPad(("pad1_"+angle).c_str(), "plot",0.0,pullHeight,1.0,1.0,0); + TPad *pad2 = new TPad(("pad2_"+angle).c_str(), "pull",0.0,0.0,1.0,pullHeight,0); + if(this->pulls){ + pad1->Draw(); + pad2->Draw(); + pad1->SetBorderSize (0); + pad1->SetMargin(0.125,0.1,1e-6,0.1/ (1 - pullHeight)); + pad1->SetTickx(); + pad1->SetTicky(); + pad1->cd(); + } + else{ + angle_canvas->cd()->SetMargin(0.125,0.1,0.125,0.1); + angle_canvas->SetTickx(); + angle_canvas->SetTicky(); + } + std::ostringstream sout; + sout << ";" << angle_name << ";" << EVENTS_TAG << " / " << std::setprecision(2) << (angle_max-angle_min)/angle_bins; + TH1D* angle_plot_sig = new TH1D((angle+"_sig").c_str(), sout.str().c_str(), angle_bins, angle_min, angle_max); + TH1D* angle_plot_bkg = new TH1D((angle+"_bkg").c_str(), sout.str().c_str(), angle_bins, angle_min, angle_max); + TH1D* angle_plot = new TH1D((angle+"_plot").c_str(), sout.str().c_str(), angle_bins, angle_min, angle_max); + angle_plot->Sumw2(); + std::ostringstream spulls; + spulls << ";" << angle_name << ";" + latex_pull(); + TH1D* angle_pulls = new TH1D((angle+"_pulls").c_str(), spulls.str().c_str(), angle_bins, angle_min, angle_max); + TH1D* angle_averaged = new TH1D((angle+"_averaged").c_str(), (angle+"_averaged").c_str(), angle_bins, angle_min, angle_max); + + bool sWeighted = false; + double nevents = 0.0; + for (auto evt: *events){ + if (!signalregion || (evt.m > ma && evt.m < mb)){ + double weight = 1.0, value = -100.0; + if (opts->weighted_fit){ + weight = evt.weight; + } + if(evt.sweight != 1.0){ + sWeighted = true; + weight *= evt.sweight; + } + + if (is_phi)value = evt.phi; + else if (is_ctk)value = evt.costhetak; + else if (is_ctl)value = evt.costhetal; + else return; + + if (evt.event_type == 0) angle_plot_sig->Fill(value, weight); + else angle_plot_bkg->Fill(value, weight); + + angle_plot->Fill(value, weight); + nevents += weight; + } + } + if(sWeighted) fsig = 1.0; + + const UInt_t bin_ratio = PLOT_NBINS_RATIO/2; + unsigned int pdf_bins = angle_bins * bin_ratio; + double dangle = (angle_max-angle_min)/pdf_bins; + TH1D* pdf_sig = new TH1D((angle+"_pdf_sig").c_str(), sout.str().c_str(), pdf_bins, angle_min, angle_max); + TH1D* pdf_swave = new TH1D((angle+"_pdf_swave").c_str(), sout.str().c_str(), pdf_bins, angle_min, angle_max); + TH1D* pdf_pwave = new TH1D((angle+"_pdf_pwave").c_str(), sout.str().c_str(), pdf_bins, angle_min, angle_max); + TH1D* pdf_interference = new TH1D((angle+"_pdf_interference").c_str(), sout.str().c_str(), pdf_bins, angle_min, angle_max); + TH1D* pdf_bkg = new TH1D((angle+"_pdf_bkg").c_str(), sout.str().c_str(), pdf_bins, angle_min, angle_max); + TH1D* pdf_tot = new TH1D((angle+"_pdf_tot").c_str(), sout.str().c_str(), pdf_bins, angle_min, angle_max); + double prob_sig=0.0, prob_bkg=0.0, prob_pwave=0.0, prob_swave=0.0, prob_interference=0.0; + double ctk_from = 0.0, ctk_to = 0.0, ctl_from=0.0, ctl_to=0.0, phi_from=0.0, phi_to=0.0; + + const double q2 = params->eff_q2(); + const double j1s = params->J1s(); + const double j1c = params->J1c(); + const double j2s = params->J2s(); + const double j2c = params->J2c(); + const double j3 = params->J3(); + const double j4 = params->J4(); + const double j5 = params->J5(); + const double j6s = params->J6s(); + const double j6c = params->J6c(); + const double j7 = params->J7(); + const double j8 = params->J8(); + const double j9 = params->J9(); + + double f1=0.0, f2=0.0, f3=0.0, f4=0.0, f5=0.0, f6=0.0, + f7=0.0, f8=0.0, f9=0.0, f10=0.0, f11=0.0, f12=0.0; + + for (unsigned int i = 0; i < pdf_bins; i++){ + if(is_ctk){ + ctk_from = angle_min + i*dangle; + ctk_to = angle_min + (i+1)*dangle; + ctl_from = opts->ctl_min; + ctl_to = opts->ctl_max; + phi_from = opts->phi_min; + phi_to = opts->phi_max; + } + else if(is_ctl){ + ctk_from = opts->ctk_min; + ctk_to = opts->ctk_max; + ctl_from = angle_min + i*dangle; + ctl_to = angle_min + (i+1)*dangle; + phi_from = opts->phi_min; + phi_to = opts->phi_max; + } + else if(is_phi){ + ctk_from = opts->ctk_min; + ctk_to = opts->ctk_max; + ctl_from = opts->ctl_min; + ctl_to = opts->ctl_max; + phi_from = angle_min + i*dangle; + phi_to = angle_min + (i+1)*dangle; + } + else return; + + if (opts->full_angular){ + if (opts->use_angular_acc){ + prob->integrated_fj_chebyshev(ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, + f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12, q2); + } + else{ + prob->integrated_fj_noacc(ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, + f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12); + } + prob_sig = (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9)/prob->fnorm_sig; + prob_pwave = prob_sig; + if (opts->swave){ + const double fs = params->FS(); + const double js1 = params->SS1(); + const double js2 = params->SS2(); + const double js3 = params->SS3(); + const double js4 = params->SS4(); + const double js5 = params->SS5(); + + double fs1=0.0, fs2=0.0, fs3=0.0, fs4=0.0, fs5=0.0, fs6=0.0; + + if (opts->use_angular_acc) + prob->swave_integrated_fj_chebyshev(ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, + fs1, fs2, fs3, fs4, fs5, fs6, q2); + else + prob->swave_integrated_fj_noacc(ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, + fs1, fs2, fs3, fs4, fs5, fs6); + + prob_sig = ((1-fs)*(f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9) + +(fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5))/prob->fnorm_sig; + prob_pwave = ((1-fs)*(f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9))/prob->fnorm_sig; + prob_swave = fs1*fs/prob->fnorm_sig; + prob_interference = (fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5)/prob->fnorm_sig; + } + } + else { + if (opts->use_angular_acc){ + prob->folded_integrated_fj_chebyshev(ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, + f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12, q2); + } + else{ + prob->folded_integrated_fj_noacc(ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, + f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12); + } + //Calculated probability for all foldings + //non-active coefficients are return 0 by 'folded'-functions in the lines above! + prob_sig = (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9)/prob->fnorm_sig; + prob_pwave = prob_sig; + if(opts->swave){ + const double fs = params->FS(); + const double js1 = params->SS1(); + const double js2 = params->SS2(); + const double js3 = params->SS3(); + const double js4 = params->SS4(); + const double js5 = params->SS5(); + + double fs1=0.0, fs2=0.0, fs3=0.0, fs4=0.0, fs5=0.0, fs6=0.0; + + if (opts->use_angular_acc){ + prob->folded_swave_integrated_fj_chebyshev(ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, + fs1, fs2, fs3, fs4, fs5, fs6, q2); + } + else{ + prob->folded_swave_integrated_fj_noacc(ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, + fs1, fs2, fs3, fs4, fs5, fs6); + } + + prob_sig = ((1-fs)*(f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9) + +(fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5))/prob->fnorm_sig; + prob_pwave = ((1-fs)*(f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9))/prob->fnorm_sig; + prob_swave = fs1*fs/prob->fnorm_sig; + prob_interference = (fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5)/prob->fnorm_sig; + } + } + pdf_sig->SetBinContent(i+1, prob_sig); + pdf_interference->SetBinContent(i+1, prob_interference); + pdf_pwave->SetBinContent(i+1, prob_pwave); + pdf_swave->SetBinContent(i+1, prob_swave); + + if(opts->use_angular_acc && opts->use_weighted_bkg){ + if(opts->fit_full_angular_bkg && !opts->flat_bkg && !opts->full_angular){ + double pi = TMath::Pi(); + if(opts->folding == 0){ + prob_bkg = (prob->integral_bkg_chebyshev(params, ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, q2) + + prob->integral_bkg_chebyshev(params, ctl_from, ctl_to, ctk_from, ctk_to, phi_from-pi, phi_to-pi, q2)) /prob->fnorm_bkg; + } + else if(opts->folding == 1){ + prob_bkg = (prob->integral_bkg_chebyshev(params, ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, q2) + + prob->integral_bkg_chebyshev(params, ctl_from, ctl_to, ctk_from, ctk_to, -phi_to, -phi_from, q2) + + prob->integral_bkg_chebyshev(params, -ctl_to, -ctl_from, ctk_from, ctk_to, pi-phi_to, pi-phi_from, q2) + + prob->integral_bkg_chebyshev(params, -ctl_to, -ctl_from, ctk_from, ctk_to, -pi+phi_from, -pi+phi_to, q2)) /prob->fnorm_bkg; + } + else if(opts->folding == 2){ + prob_bkg = (prob->integral_bkg_chebyshev(params, ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, q2) + + prob->integral_bkg_chebyshev(params, ctl_from, ctl_to, ctk_from, ctk_to, -phi_to, -phi_from, q2) + + prob->integral_bkg_chebyshev(params, -ctl_to, -ctl_from, ctk_from, ctk_to, phi_from, phi_to, q2) + + prob->integral_bkg_chebyshev(params, -ctl_to, -ctl_from, ctk_from, ctk_to, -phi_to, -phi_from, q2)) /prob->fnorm_bkg; + } + else if(opts->folding == 3){ + if((phi_from <= 0.0 && phi_to <= 0.0) || (phi_from >= 0.0 && phi_to >= 0.0)){ + prob_bkg = (prob->integral_bkg_chebyshev(params, ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, q2) + + prob->integral_bkg_chebyshev(params, ctl_from, ctl_to, ctk_from, ctk_to, (phi_from < 0.0 ? -pi - phi_to : pi - phi_to), (phi_to < 0.0 ? -pi - phi_from : pi - phi_from), q2) + + prob->integral_bkg_chebyshev(params, -ctl_to, -ctl_from, ctk_from, ctk_to, phi_from, phi_to, q2) + + prob->integral_bkg_chebyshev(params, -ctl_to, -ctl_from, ctk_from, ctk_to, (phi_from < 0.0 ? -pi - phi_to : pi - phi_to), (phi_to < 0.0 ? -pi - phi_from : pi - phi_from), q2)) /prob->fnorm_bkg; + } + else{ //when phi_from < 0.0 and phi_to > 0.0: + assert(phi_to > phi_from); + prob_bkg = (prob->integral_bkg_chebyshev(params, ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, q2) + + prob->integral_bkg_chebyshev(params, ctl_from, ctl_to, ctk_from, ctk_to, -pi, -pi - phi_from, q2) + + prob->integral_bkg_chebyshev(params, ctl_from, ctl_to, ctk_from, ctk_to, pi - phi_to, pi, q2) + + prob->integral_bkg_chebyshev(params, -ctl_to, -ctl_from, ctk_from, ctk_to, phi_from, phi_to, q2) + + prob->integral_bkg_chebyshev(params, -ctl_to, -ctl_from, ctk_from, ctk_to, -pi, -pi - phi_from, q2) + + prob->integral_bkg_chebyshev(params, -ctl_to, -ctl_from, ctk_from, ctk_to, pi - phi_to, pi, q2)) /prob->fnorm_bkg; + } + } + else if(opts->folding == 4){ + if((phi_from <= 0.0 && phi_to <= 0.0) || (phi_from >= 0.0 && phi_to >= 0.0)){ + prob_bkg = (prob->integral_bkg_chebyshev(params, ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, q2) + + prob->integral_bkg_chebyshev(params, ctl_from, ctl_to, ctk_from, ctk_to, (phi_from < 0.0 ? -pi - phi_to : pi - phi_to), (phi_to < 0.0 ? -pi - phi_from : pi - phi_from), q2) + + prob->integral_bkg_chebyshev(params, -ctl_to, -ctl_from, -ctk_to, -ctk_from, phi_from, phi_to, q2) + + prob->integral_bkg_chebyshev(params, -ctl_to, -ctl_from, -ctk_to, -ctk_from, (phi_from < 0.0 ? -pi - phi_to : pi - phi_to), (phi_to < 0.0 ? -pi - phi_from : pi - phi_from), q2)) /prob->fnorm_bkg; + } + else{ //when phi_from < 0.0 and phi_to > 0.0: + assert(phi_to > phi_from); + prob_bkg = (prob->integral_bkg_chebyshev(params, ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, q2) + + prob->integral_bkg_chebyshev(params, ctl_from, ctl_to, ctk_from, ctk_to, -pi, -pi - phi_from, q2) + + prob->integral_bkg_chebyshev(params, ctl_from, ctl_to, ctk_from, ctk_to, pi - phi_to, pi, q2) + + prob->integral_bkg_chebyshev(params, -ctl_to, -ctl_from, -ctk_to, -ctk_from, phi_from, phi_to, q2) + + prob->integral_bkg_chebyshev(params, -ctl_to, -ctl_from, -ctk_to, -ctk_from, -pi, -pi - phi_from, q2) + + prob->integral_bkg_chebyshev(params, -ctl_to, -ctl_from, -ctk_to, -ctk_from, pi - phi_to, pi, q2)) /prob->fnorm_bkg; + } + } + } + else{ + prob_bkg = prob->integral_bkg_chebyshev(params, ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, q2) /prob->fnorm_bkg; + } + } + else{ + if(opts->fit_full_angular_bkg && !opts->flat_bkg && !opts->full_angular){ + if(opts->folding == 0){ + prob_bkg = (prob->integral_bkg(params, ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to) + + prob->integral_bkg(params, ctl_from, ctl_to, ctk_from, ctk_to, phi_from-MY_PI, phi_to-MY_PI)) /prob->fnorm_bkg; + } + else if(opts->folding == 1){ + prob_bkg = (prob->integral_bkg(params, ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to) + + prob->integral_bkg(params, ctl_from, ctl_to, ctk_from, ctk_to, -phi_to, -phi_from) + + prob->integral_bkg(params, -ctl_to, -ctl_from, ctk_from, ctk_to, MY_PI-phi_to, MY_PI-phi_from) + + prob->integral_bkg(params, -ctl_to, -ctl_from, ctk_from, ctk_to, -MY_PI+phi_from, -MY_PI+phi_to)) /prob->fnorm_bkg; + } + else if(opts->folding == 2){ + prob_bkg = (prob->integral_bkg(params, ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to) + + prob->integral_bkg(params, ctl_from, ctl_to, ctk_from, ctk_to, -phi_to, -phi_from) + + prob->integral_bkg(params, -ctl_to, -ctl_from, ctk_from, ctk_to, phi_from, phi_to) + + prob->integral_bkg(params, -ctl_to, -ctl_from, ctk_from, ctk_to, -phi_to, -phi_from)) /prob->fnorm_bkg; + } + else if(opts->folding == 3){ + if((phi_from <= 0.0 && phi_to <= 0.0) || (phi_from >= 0.0 && phi_to >= 0.0)){ + prob_bkg = (prob->integral_bkg(params, ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to) + + prob->integral_bkg(params, ctl_from, ctl_to, ctk_from, ctk_to, (phi_from < 0.0 ? -MY_PI - phi_to : MY_PI - phi_to), (phi_to < 0.0 ? -MY_PI - phi_from : MY_PI - phi_from)) + + prob->integral_bkg(params, -ctl_to, -ctl_from, ctk_from, ctk_to, phi_from, phi_to) + + prob->integral_bkg(params, -ctl_to, -ctl_from, ctk_from, ctk_to, (phi_from < 0.0 ? -MY_PI - phi_to : MY_PI - phi_to), (phi_to < 0.0 ? -MY_PI - phi_from : MY_PI - phi_from))) /prob->fnorm_bkg; + } + else{ //when phi_from < 0.0 and phi_to > 0.0: + assert(phi_to > phi_from); + prob_bkg = (prob->integral_bkg(params, ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to) + + prob->integral_bkg(params, ctl_from, ctl_to, ctk_from, ctk_to, -MY_PI, -MY_PI - phi_from) + + prob->integral_bkg(params, ctl_from, ctl_to, ctk_from, ctk_to, MY_PI - phi_to, MY_PI) + + prob->integral_bkg(params, -ctl_to, -ctl_from, ctk_from, ctk_to, phi_from, phi_to) + + prob->integral_bkg(params, -ctl_to, -ctl_from, ctk_from, ctk_to, -MY_PI, -MY_PI - phi_from) + + prob->integral_bkg(params, -ctl_to, -ctl_from, ctk_from, ctk_to, MY_PI - phi_to, MY_PI)) /prob->fnorm_bkg; + } + } + else if(opts->folding == 4){ + if((phi_from <= 0.0 && phi_to <= 0.0) || (phi_from >= 0.0 && phi_to >= 0.0)){ + prob_bkg = (prob->integral_bkg(params, ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to) + + prob->integral_bkg(params, ctl_from, ctl_to, ctk_from, ctk_to, (phi_from < 0.0 ? -MY_PI - phi_to : MY_PI - phi_to), (phi_to < 0.0 ? -MY_PI - phi_from : MY_PI - phi_from)) + + prob->integral_bkg(params, -ctl_to, -ctl_from, -ctk_to, -ctk_from, phi_from, phi_to) + + prob->integral_bkg(params, -ctl_to, -ctl_from, -ctk_to, -ctk_from, (phi_from < 0.0 ? -MY_PI - phi_to : MY_PI - phi_to), (phi_to < 0.0 ? -MY_PI - phi_from : MY_PI - phi_from))) /prob->fnorm_bkg; + } + else{ //when phi_from < 0.0 and phi_to > 0.0: + assert(phi_to > phi_from); + prob_bkg = (prob->integral_bkg(params, ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to) + + prob->integral_bkg(params, ctl_from, ctl_to, ctk_from, ctk_to, -MY_PI, -MY_PI - phi_from) + + prob->integral_bkg(params, ctl_from, ctl_to, ctk_from, ctk_to, MY_PI - phi_to, MY_PI) + + prob->integral_bkg(params, -ctl_to, -ctl_from, -ctk_to, -ctk_from, phi_from, phi_to) + + prob->integral_bkg(params, -ctl_to, -ctl_from, -ctk_to, -ctk_from, -MY_PI, -MY_PI - phi_from) + + prob->integral_bkg(params, -ctl_to, -ctl_from, -ctk_to, -ctk_from, MY_PI - phi_to, MY_PI)) /prob->fnorm_bkg; + } + } + } + else{ + prob_bkg = prob->integral_bkg(params, ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to) /prob->fnorm_bkg; + } + } + pdf_bkg->SetBinContent(i+1, prob_bkg); + } + + pdf_sig->Scale(nevents * fsig * double(pdf_bins) / double(angle_bins)); + pdf_pwave->Scale(nevents * fsig * double(pdf_bins) / double(angle_bins)); + pdf_swave->Scale(nevents * fsig * double(pdf_bins) / double(angle_bins)); + pdf_interference->Scale(nevents * fsig * double(pdf_bins) / double(angle_bins)); + + pdf_bkg->Scale(nevents * (1.0-fsig) * double(pdf_bins) / double(angle_bins)); + + pdf_tot->Add(pdf_sig, pdf_bkg); + + double maxpdf = (pdf_tot->GetMaximum() > angle_plot->GetMaximum() ? pdf_tot->GetMaximum() : angle_plot->GetMaximum()); + if(this->pulls) pdf_sig->SetMinimum(0.1001); + else pdf_sig->SetMinimum(0.0); + + pdf_sig->SetMaximum(1.45*maxpdf); + pdf_sig->SetTitleSize(0.06, "XY"); + pdf_sig->SetLabelSize(0.05, "XY"); + pdf_sig->SetTitleOffset(0.9, "XY"); + pdf_sig->GetXaxis()->SetNoExponent(kTRUE); + TGaxis::SetMaxDigits(3); + spdlog::debug("Designing PDF..."); + design_pdf(pdf_sig, kAzure, kAzure-5, 1001, 1-pullHeight, this->pulls); + if(pdf_sig->Integral() > 0.0) pdf_sig->Draw("hist C"); + + design_pdf(pdf_bkg,kOrange+10,kOrange+8, 3354, 1-pullHeight,pdf_sig->Integral() <= 0.0 ); + + if(pdf_sig->Integral() > 0.0){ + pdf_bkg->Draw("hist same C"); + } + else{ + pdf_bkg->SetMinimum(minBkg); + pdf_bkg->SetMaximum(1.45*maxpdf); + pdf_bkg->Draw("hist C"); + } + ///// + + spdlog::debug("Designing PDF lines..."); + design_pdfLine(pdf_pwave, pWaveColor, kDashed); + if(opts->swave) pdf_pwave->Draw("hist same C"); + + design_pdfLine(pdf_swave, sWaveColor, kDotted); + if(opts->swave) pdf_swave->Draw("hist same C"); + + design_pdfLine(pdf_interference, psInterferenceColor, kDashDotted); + if(opts->swave) pdf_interference->Draw("hist same C"); + + design_pdfLine(pdf_tot, kBlack, kSolid); + pdf_tot->Draw("hist same C"); + + design_plot(angle_plot,20,printC); + design_pdfLine(angle_plot,kBlack,kSolid,1.0); + angle_plot->Draw("same e1"); + if (false && angle_plot_bkg->Integral() != 0){ + angle_plot_sig->SetLineColor(4); + angle_plot_sig->GetXaxis()->SetNoExponent(kTRUE); + angle_plot_sig->Draw("esame"); + angle_plot_bkg->SetLineColor(2); + angle_plot_bkg->GetXaxis()->SetNoExponent(kTRUE); + if (params->f_sig() != 1.0) + angle_plot_bkg->Draw("esame"); + } + + TLegend* angle_leg = new TLegend(0.675,0.45,0.875,0.65); + angle_leg->SetBorderSize(0); + angle_leg->SetTextFont(132); + angle_leg->SetFillColor(0); + angle_leg->AddEntry(angle_plot, "data", "le"); + angle_leg->AddEntry(pdf_tot, "total PDF", "l"); + angle_leg->AddEntry(pdf_sig, "signal PDF", "l"); + angle_leg->AddEntry(pdf_bkg, "bkg PDF", "l"); + if(opts->swave){ + angle_leg->AddEntry(pdf_pwave, "P-wave PDF", "l"); + angle_leg->AddEntry(pdf_swave, "S-wave PDF", "l"); + angle_leg->AddEntry(pdf_interference, "interference PDF", "l"); + } + //angle_leg->Draw("same"); + + spdlog::debug("plotter: getting a TLatex..."); + TLatex *tex = design_TLatex(texsizelarge,texsizesmall, pullHeight, 0.47, + this->pulls, opts->plot_label,opts->q2_label); + assert(pdf_bins == angle_bins*bin_ratio); + assert(bin_ratio >= 1); + + //calculate pulls from fit and data points: + + spdlog::debug("plotter: calculate pulls from fit and data points"); + for(UInt_t b = 1; b <= angle_bins; b++){ + double p; + if(bin_ratio == 1){ + p = pdf_tot->GetBinContent(b); + } + //for odd ratio, take central bin from pdf w.r.t to angle_bin: + else if(bin_ratio%2 != 0){ + p = pdf_tot->GetBinContent(b*bin_ratio - bin_ratio/2); + } + //else, average the two central bins from pdf w.r.t. to angle_bin: + else{ + p = (pdf_tot->GetBinContent(b*bin_ratio - bin_ratio/2)+pdf_tot->GetBinContent(b*bin_ratio - bin_ratio/2 + 1))/2.; //take central of 10 pdfbins + } + + angle_averaged->SetBinContent(b, p); + + if(angle_plot->GetBinError(b) == 0){ + angle_pulls->SetBinContent(b, 0.0); + } + else{ + angle_pulls->SetBinContent(b, (angle_plot->GetBinContent(b) - p)/angle_plot->GetBinError(b)); + } + } + + Double_t angle_chi2 = 0.0; + Int_t angle_ndf = 0, angle_Good = 0; + + spdlog::debug("plotter: plotting chi2"); + if(opts->plot_chi2){ + angle_averaged->Chi2TestX(angle_plot, angle_chi2, angle_ndf, angle_Good, "WW"); + tex->SetTextColor(kBlack); + tex->DrawLatexNDC(0.5,(this->pulls ? (0.85 - pullHeight)/(1 - pullHeight) : 0.85),("#chi^{2}: "+std::to_string(angle_chi2 / angle_ndf)).c_str()); + } + + if(this->pulls){ + spdlog::debug("plotter: Designing pulls..."); + + pad2->Clear(); + pad2->SetMargin(0.125,0.1,0.125/ pullHeight, 1e-6); + pad2->SetTickx(); + pad2->cd(); + + design_pull(angle_pulls, kBlack,kGray+2,pullHeight,pullFrameRange); + angle_pulls->Draw(); + + //add two 3-sigma lines: + TLine * lUp = threeSigmaLine(angle_min, angle_max, true); + TLine * lLow = threeSigmaLine(angle_min, angle_max, false); + lUp->Draw("same"); + lLow->Draw("same"); + } + spdlog::debug("plotter: Saving..."); + + std::string anglename = prefix + angle + "_" + postfix; + saveTCanvas(angle_canvas,anglename,opts->getAllPlotTypes()); + + output->cd(); + angle_canvas->Write(); + + spdlog::debug("plotter: Deleting stuff"); + delete angle_plot; + delete angle_plot_sig; + delete angle_plot_bkg; + delete angle_pulls; + delete angle_averaged; + delete pdf_sig; + delete pdf_pwave; + delete pdf_swave; + delete pdf_interference; + delete pdf_bkg; + delete pdf_tot; + delete angle_canvas; +}; + +void bu2kstarmumu_plotter::plot_added_pdfs(std::vector * probs, + std::vector * params, + std::vector* > * events, + std::string prefix, std::string postfix, + bool signalregion){ + + if (probs->size() != params->size()){ + spdlog::critical("probs size != params size!\t {0:d} \t != \t {1:d}", probs->size(), params->size()); + assert(0); + } + if (probs->size() != events->size()){ + spdlog::critical("probs size != events size!\t {0:d} \t != \t {1:d}", probs->size(), events->size()); + assert(0); + } + + for(UInt_t e = 0; e < events->size(); e++){ + if(events->at(e)->size() == 0){ + spdlog::error("Cannot plot empty event histograms! Events for PDF {0:d} are empty!", e); + return; + } + probs->at(e)->update_cached_normalization(params->at(e)); + } + + output = new TFile((prefix +"projections_addedPDFS" + opts->name + ".root").c_str(), "UPDATE"); + std::string logstr = std::string("log_")+postfix; + + //m(B) + if(!opts->only_angles && !opts->only_mkpi){ + plot_m_added_pdfs(probs, params, events, prefix, postfix, false, false); + plot_m_added_pdfs(probs, params, events, prefix, logstr , true, false); + } + + //m(Kpi) + if (opts->fit_mkpi || opts->use_mkpi){ + plot_mkpi_added_pdfs(probs, params, events, prefix, postfix, signalregion, false, false); + } + + //angles + if(!opts->only_Bmass && !opts->only_mass2DFit && !opts->only_mkpi){ + plot_angle_added_pdfs(probs, params, events, prefix, postfix, signalregion, "ctl", false); + plot_angle_added_pdfs(probs, params, events, prefix, postfix, signalregion, "ctk", false); + plot_angle_added_pdfs(probs, params, events, prefix, postfix, signalregion, "phi", false); + } + output->Close(); + delete output; +}; + +void bu2kstarmumu_plotter::plot_m_added_pdfs(std::vector * probs, std::vector * params, std::vector*> * events, std::string prefix, std::string postfix, bool logarithmic, bool printC){ + + unsigned int m_bins = opts->plots_m_bins; + double m_min = params->at(0)->m_b.get_min(); + double m_max = params->at(0)->m_b.get_max(); + spdlog::debug("Mass range: {0:f} - {1:f}", m_min, m_max); + + //create canvas + TCanvas *m_canvas = nullptr; + std::string m_canvas_name = "Bplus Likelihood Analysis: #it{m}(#it" +latex_decay(opts->DTF) +") mass projection"; + if(printC) m_canvas = new TCanvas(("m_"+postfix).c_str(), m_canvas_name.c_str()); + else m_canvas = new TCanvas(("m_"+postfix).c_str(), m_canvas_name.c_str(),1600,1200); + + const double pullHeight = 0.27; + const double pullFrameRange = 6.5; + TPad *pad1 = new TPad("pad1", "plot",0.0,pullHeight,1.0,1.0,0); + TPad *pad2 = new TPad("pad2", "pull",0.0,0.0,1.0,pullHeight,0); + if(this->pulls){ + pad1->Draw(); + pad2->Draw(); + pad1->SetLogy(logarithmic); + pad1->SetBorderSize (0); + pad1->SetMargin(0.125,0.1,1e-6,0.1/ (1 - pullHeight)); + pad1->SetTickx(); + pad1->SetTicky(); + pad1->cd(); + } + else{ + m_canvas->cd()->SetMargin(0.125,0.1,0.125,0.1); + m_canvas->SetLogy(logarithmic); + m_canvas->SetTickx(); + m_canvas->SetTicky(); + } + + //create histograms + std::ostringstream sout; + sout << ";#it{m}(" + latex_decay(opts->DTF) + ") ["+MeVc()+"];" << EVENTS_TAG << " / " << std::setprecision(2) << (m_max-m_min)/m_bins << " "+MeVc()+""; + + std::string spulls = ";#it{m}(" + latex_decay(opts->DTF) + ") ["+MeVc()+"];" + latex_pull(); + + const UInt_t bin_ratio = PLOT_NBINS_RATIO; + unsigned int pdf_bins = m_bins*bin_ratio; + double dm = (m_max-m_min)/pdf_bins; + + TH1D* m_plot = new TH1D("m", sout.str().c_str(), m_bins, m_min, m_max); + TH1D* m_pulls = new TH1D("mpulls", spulls.c_str(), m_bins, m_min, m_max); + TH1D* pdf_sig = new TH1D("pdf_sig", sout.str().c_str(), pdf_bins, m_min, m_max); + TH1D* pdf_bkg = new TH1D("pdf_bkg", sout.str().c_str(), pdf_bins, m_min, m_max); + TH1D* pdf_tot = new TH1D("pdf_tot", sout.str().c_str(), pdf_bins, m_min, m_max); + + m_plot->Sumw2(); + + //loop over all PDFs + for(UInt_t k = 0; k < params->size(); k++){ + + double fsig = params->at(k)->f_sig(); + if (opts->extended_ml){ + fsig = params->at(k)->n_sig()/(params->at(k)->n_sig()+params->at(k)->n_bkg()); + } + + TH1D* tmp_m = new TH1D(("tmp_m"+std::to_string(k)).c_str(), sout.str().c_str(), m_bins, m_min, m_max); + TH1D* tmp_sig = new TH1D(("tmp_sig"+std::to_string(k)).c_str(), sout.str().c_str(), pdf_bins, m_min, m_max); + TH1D* tmp_bkg = new TH1D(("tmp_bkg"+std::to_string(k)).c_str(), sout.str().c_str(), pdf_bins, m_min, m_max); + TH1D* tmp_tot = new TH1D(("tmp_tot"+std::to_string(k)).c_str(), sout.str().c_str(), pdf_bins, m_min, m_max); + + double nevents = 0.0; + for (unsigned int i = 0; i < events->at(k)->size(); i++) + { + double weight = 1.0; + if (opts->weighted_fit) weight = events->at(k)->at(i).weight; + tmp_m->Fill(events->at(k)->at(i).m, weight); + nevents += weight; + } + double m_b = params->at(k)->m_b(); + double m_scale = params->at(k)->m_scale(); + double f_res = params->at(k)->m_res_1(); + double sigma_1 = params->at(k)->m_sigma_1(); + double sigma_2 = params->at(k)->m_sigma_2(); + double alpha_1 = opts->crystalball || opts->twotailedcrystalball ? params->at(k)->alpha_1() : 0.; + double alpha_2 = opts->crystalball || opts->twotailedcrystalball ? params->at(k)->alpha_2() : 0.; + double n_1 = opts->crystalball || opts->twotailedcrystalball ? params->at(k)->n_1() : 0.; + double n_2 = opts->crystalball || opts->twotailedcrystalball ? params->at(k)->n_2() : 0.; + + double prob_sig = 0.0, prob_bkg = 0.0, from = 0.0, to = 0.0; + + double integral1 = 1.0, integral2 = 2.0; + if(opts->crystalball){ + integral1 = integrate_crystalball(m_b, m_scale*sigma_1, alpha_1, n_1, m_min, m_max); + integral2 = integrate_crystalball(m_b, m_scale*sigma_2, alpha_2, n_2, m_min, m_max); + } + else if(opts->twotailedcrystalball){ + integral1 = integrate_twotailedcrystalball(m_b, m_scale*sigma_1, alpha_1, alpha_2, n_1, n_2, m_min, m_max); + } + else{ + integral1 = integrate_gauss(m_scale*sigma_1, m_b, m_min, m_max); + integral2 = integrate_gauss(m_scale*sigma_2, m_b, m_min, m_max); + } + + for (unsigned int i = 0; i < pdf_bins; i++){ + from = m_min + i*dm; + to = m_min + (i+1)*dm; + prob_sig = 0.0; + if (opts->crystalball){ + prob_sig = integrate_crystalball(m_b, m_scale*sigma_1, alpha_1, n_1, from, to) / integral1; + if (f_res != 1.0){ + prob_sig *= f_res; + prob_sig += (1.0-f_res) + * integrate_crystalball(m_b, m_scale*sigma_2, alpha_2, n_2, from, to) / integral2; + } + } + else if(opts->twotailedcrystalball){ + prob_sig = integrate_twotailedcrystalball(m_b, m_scale*sigma_1, alpha_1, alpha_2, n_1, n_2, from, to) / integral1; + } + else{ + prob_sig = integrate_gauss(m_scale*sigma_1, m_b, from, to) / integral1; + if (f_res != 1.0){ + prob_sig *= f_res; + prob_sig += (1.0 - f_res) + * integrate_gauss(m_scale*sigma_2, m_b, from, to) / integral2; + } + } + + tmp_sig->SetBinContent(i+1, prob_sig); + + prob_bkg = probs->at(k)->integral_m_bkg_prob(params->at(k), from, to); + + tmp_bkg->SetBinContent(i+1, prob_bkg); + } + + tmp_sig->Scale(nevents * fsig * double(pdf_bins) / double(m_bins)); + tmp_bkg->Scale(nevents * (1.0-fsig) * double(pdf_bins) / double(m_bins)); + tmp_tot->Add(tmp_sig, tmp_bkg); + + m_plot->Add(tmp_m); + pdf_sig->Add(tmp_sig); + pdf_bkg->Add(tmp_bkg); + pdf_tot->Add(tmp_tot); + + delete tmp_m; + delete tmp_sig; + delete tmp_bkg; + delete tmp_tot; + + } + + double maxpdf= (pdf_tot->GetMaximum() > m_plot->GetMaximum() ? pdf_tot->GetMaximum() : m_plot->GetMaximum()); + if(this->pulls){ + if (logarithmic) pdf_sig->SetMinimum(0.1001); + else pdf_sig->SetMinimum(0.001); + } + else{ //no pull distributions + if (logarithmic) pdf_sig->SetMinimum(0.1); + else pdf_sig->SetMinimum(0.0); + } + pdf_sig->SetMaximum(1.45*maxpdf); + + + pdf_bkg->SetTitleSize(0.06, "XY"); + pdf_bkg->SetLabelSize(0.05, "XY"); + pdf_bkg->SetTitleOffset(0.9, "XY"); + pdf_bkg->GetXaxis()->SetNoExponent(kTRUE); + TGaxis::SetMaxDigits(3); //TODO: check + + design_pdf(pdf_sig,kAzure, kAzure-5, 1001, 1-pullHeight, this->pulls); + if(pdf_sig->Integral() > 0.0) pdf_sig->Draw("hist C"); + design_pdf(pdf_bkg,kOrange+10,kOrange+8, 3354, 1-pullHeight,pdf_sig->Integral() <= 0.0 ); + + if(pdf_sig->Integral() > 0.0){ + pdf_bkg->Draw("hist same C"); + } + else{ + pdf_bkg->SetMaximum(1.45*maxpdf); + pdf_bkg->SetMinimum(minBkg); + pdf_bkg->Draw("hist C"); + } + + pdf_tot->SetFillStyle(0); + design_pdfLine(pdf_tot,kBlack,kSolid,2.0); + pdf_tot->Draw("hist same C"); + + design_plot(m_plot, 20, printC); + design_pdfLine(m_plot,kBlack,kSolid,1.0); + m_plot->Draw("same e1"); + + //draw legend + TLegend* m_leg = new TLegend(0.675,0.45,0.875,0.65); + m_leg->SetBorderSize(0); + m_leg->SetTextFont(132); + m_leg->SetFillColor(0); + m_leg->AddEntry(m_plot, "data", "le"); + m_leg->AddEntry(pdf_tot, "total PDF", "l"); + m_leg->AddEntry(pdf_sig, "signal PDF", "l"); + m_leg->AddEntry(pdf_bkg, "bkg PDF", "l"); + //m_leg->Draw(); + + TLatex *tex = design_TLatex(texsizelarge,texsizesmall, pullHeight, 0.47, + this->pulls, opts->plot_label,opts->q2_label); + + assert(pdf_bins == m_bins*bin_ratio); + assert(bin_ratio >= 1); + + if(this->pulls){ + + //calculate pulls from fit and data points: + for(UInt_t b = 1; b <= m_bins; b++){ + double p; + if(bin_ratio == 1){ + p = pdf_tot->GetBinContent(b); + } + //for odd ratio, take central bin from pdf w.r.t to m_bin: + else if(bin_ratio%2 != 0){ + p = pdf_tot->GetBinContent(b*bin_ratio - bin_ratio/2); + } + //else, average the two central bins from pdf w.r.t. to angle_bin: + else{ + p = (pdf_tot->GetBinContent(b*bin_ratio - bin_ratio/2)+pdf_tot->GetBinContent(b*bin_ratio - bin_ratio/2 + 1))/2.; //take central of 10 pdfbins + } + + if(m_plot->GetBinError(b) == 0) m_pulls->SetBinContent(b, 0.0); + else m_pulls->SetBinContent(b, (m_plot->GetBinContent(b) - p)/m_plot->GetBinError(b)); + } + + pad2->Clear(); + pad2->SetMargin(0.125,0.1,0.125/ pullHeight, 1e-6); + pad2->SetTickx(); + pad2->cd(); + + design_pull(m_pulls, kBlack,kGray+2,pullHeight,pullFrameRange); + m_pulls->Draw(); + + //add two 3-sigma lines: + TLine * lUp = threeSigmaLine(m_min, m_max, true); + TLine * lLow = threeSigmaLine(m_min, m_max, false); + lUp->Draw("same"); + lLow->Draw("same"); + } + + std::string mname = prefix + "m_" + postfix + "_AllPDFs"; + saveTCanvas(m_canvas,mname,opts->getAllPlotTypes()); + + output->cd(); + m_canvas->Write(); + + delete m_plot; + delete pdf_sig; + delete pdf_bkg; + delete pdf_tot; + delete m_pulls; + delete m_canvas; + delete tex; + +} + +void bu2kstarmumu_plotter::plot_mkpi_added_pdfs(std::vector * probs, std::vector * params, std::vector*> * events, std::string prefix, std::string postfix, bool signalregion, bool logarithmic, bool printC){ + + unsigned int mkpi_bins = opts->plots_m_bins; + double mkpi_min = opts->mkpi_min/1.0e+3;//0.7959*0.7959;//(0.892-0.100)*(0.892-0.100);//opts->m_min; + double mkpi_max = opts->mkpi_max/1.0e+3;//0.9959*0.9959;//(0.892+0.100)*(0.892+0.100);//opts->m_max; + + TCanvas *mkpi_canvas = nullptr; + std::string mpki_canvas_name = "B plus Likelihood Analysis: #it{m}(#it"+ latex_Kst_decay(opts->DTF) +") ["+GeVc()+"]"; + if(printC)mkpi_canvas = new TCanvas(("mkpi_"+postfix).c_str(), mpki_canvas_name.c_str()); + else mkpi_canvas = new TCanvas(("mkpi_"+postfix).c_str(), mpki_canvas_name.c_str(),1600,1200); + + + const double pullHeight = 0.27; + const double pullFrameRange = 6.5; + TPad *pad1 = new TPad("pad1", "plot",0.0,pullHeight,1.0,1.0,0); + TPad *pad2 = new TPad("pad2", "pull",0.0,0.0,1.0,pullHeight,0); + if(this->pulls){ + pad1->Draw(); + pad2->Draw(); + pad1->SetLogy(logarithmic); + pad1->SetBorderSize (0); + pad1->SetMargin(0.125,0.1,1e-6,0.1/ (1 - pullHeight)); + pad1->SetTickx(); + pad1->SetTicky(); + pad1->cd(); + } + else{ + mkpi_canvas->cd()->SetMargin(0.125,0.1,0.125,0.1); + mkpi_canvas->SetTickx(); + mkpi_canvas->SetTicky(); + } + + std::ostringstream sout; + sout << ";#it{m}(#it{K}^{+}#pi^{-}) ["+GeVc()+"];" << EVENTS_TAG << " / " << std::setprecision(2) << (mkpi_max-mkpi_min)/mkpi_bins << " GeV^{2}/#it{c}^{4}"; + std::string spulls = ";#it{m}("+ latex_Kst_decay(opts->DTF) +") ["+MeVc()+"];" + latex_pull(); + + const UInt_t bin_ratio = PLOT_NBINS_RATIO; + unsigned int pdf_bins = mkpi_bins*bin_ratio; + double dm = (mkpi_max-mkpi_min)/pdf_bins; + + TH1D* mkpi_plot = new TH1D("m", sout.str().c_str(), mkpi_bins, mkpi_min, mkpi_max); + TH1D* mkpi_pulls= new TH1D("mkpipulls", spulls.c_str(), mkpi_bins, mkpi_min, mkpi_max); + TH1D* pdf_sig = new TH1D("pdf_sig", sout.str().c_str(), pdf_bins, mkpi_min, mkpi_max); + TH1D* pdf_swave = new TH1D("pdf_swave", sout.str().c_str(), pdf_bins, mkpi_min, mkpi_max); + TH1D* pdf_pwave = new TH1D("pdf_pwave", sout.str().c_str(), pdf_bins, mkpi_min, mkpi_max); + TH1D* pdf_interference = new TH1D("pdf_interference", sout.str().c_str(), pdf_bins, mkpi_min, mkpi_max); + TH1D* pdf_bkg = new TH1D("pdf_bkg", sout.str().c_str(), pdf_bins, mkpi_min, mkpi_max); + TH1D* pdf_tot = new TH1D("pdf_tot", sout.str().c_str(), pdf_bins, mkpi_min, mkpi_max); + + mkpi_plot->Sumw2(); + + for(UInt_t k = 0; k < params->size(); k++){ + + double ma = params->at(k)->m_b() - B_MASS_TIGHT_WINDOW; + double mb = params->at(k)->m_b() + B_MASS_TIGHT_WINDOW; + + double fsig = params->at(k)->f_sig(); + if(opts->extended_ml){ + fsig = params->at(k)->n_sig() / (params->at(k)->n_sig()+params->at(k)->n_bkg()); + } + if(signalregion){ + double rsig = probs->at(k)->integral_m_sig_prob(params->at(k), ma, mb); + double rbkg = probs->at(k)->integral_m_bkg_prob(params->at(k), ma, mb); + fsig = fsig*rsig/(fsig*rsig + (1.0-fsig)*rbkg); + } + + TH1D* tmp_mkpi = new TH1D(("tmp_mkpi"+std::to_string(k)).c_str(), sout.str().c_str(), mkpi_bins, mkpi_min, mkpi_max); + TH1D* tmp_sig = new TH1D(("tmp_sig"+std::to_string(k)).c_str(), sout.str().c_str(), pdf_bins, mkpi_min, mkpi_max); + TH1D* tmp_swave = new TH1D(("tmp_swave"+std::to_string(k)).c_str(), sout.str().c_str(), pdf_bins, mkpi_min, mkpi_max); + TH1D* tmp_pwave = new TH1D(("tmp_pwave"+std::to_string(k)).c_str(), sout.str().c_str(), pdf_bins, mkpi_min, mkpi_max); + TH1D* tmp_interference = new TH1D(("tmp_interference"+std::to_string(k)).c_str(), sout.str().c_str(), pdf_bins, mkpi_min, mkpi_max); + TH1D* tmp_bkg = new TH1D(("tmp_bkg"+std::to_string(k)).c_str(), sout.str().c_str(), pdf_bins, mkpi_min, mkpi_max); + TH1D* tmp_tot = new TH1D(("tmp_tot"+std::to_string(k)).c_str(), sout.str().c_str(), pdf_bins, mkpi_min, mkpi_max); + + double nevents = 0.0; + + for (unsigned int i = 0; i < events->at(k)->size(); i++){ + if (!signalregion || (events->at(k)->at(i).m > ma && events->at(k)->at(i).m < mb)){ + double weight = 1.0; + double mkpi = events->at(k)->at(i).mkpi/1.0e+3; + if (opts->weighted_fit) weight = events->at(k)->at(i).weight; + tmp_mkpi->Fill(mkpi, weight); + nevents += weight; + } + } + + double gammakstar = params->at(k)->gammakstar(); + double mkstar = params->at(k)->mkstar(); + double asphase = params->at(k)->asphase(); + double a = params->at(k)->a(); + double r = params->at(k)->r(); + double R = params->at(k)->R(); + + double gammakstarplus = params->at(k)->gammakstarplus(); + double mkstarplus = params->at(k)->mkstarplus(); + double gammaf800 = params->at(k)->gammaf800(); + double mf800 = params->at(k)->mf800(); + double f800mag = params->at(k)->f800mag(); + double f800phase = params->at(k)->f800phase(); + + double normbkg=0.0; + std::vector ch_mkpi(5, 0.0); + ch_mkpi.at(0) = params->at(k)->cbkgmkpi0(); + ch_mkpi.at(1) = params->at(k)->cbkgmkpi1(); + ch_mkpi.at(2) = params->at(k)->cbkgmkpi2(); + ch_mkpi.at(3) = params->at(k)->cbkgmkpi3(); + ch_mkpi.at(4) = params->at(k)->cbkgmkpi4(); + std::vector poly_mkpi(ch_mkpi.size(), 0.0); + chebyshev_to_poly(ch_mkpi, poly_mkpi); + std::vector poly_corr_mkpi(ch_mkpi.size(), 0.0); + correct_poly(poly_mkpi, poly_corr_mkpi, mkpi_min, mkpi_max); + + if (opts->mkpi_threshold){ + normbkg = fcnc::int_threshold(mkpi_min, mkpi_max, 0.633, params->at(k)->nthreshold()); + } + else{ + for (unsigned int i=0; iat(k)->eff_q2(); + double rangednormkstarplus, rangednormkstar; + + if (opts->simple_mkpi){ + rangednormkstarplus = int_mkpi_simple_kstarzero_amp_squared(mkpi_min, mkpi_max, q2, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus); + rangednormkstar = int_mkpi_simple_bw_kstar_amp_squared(mkpi_min, mkpi_max, q2, gammakstar, mkstar); + } + else if(opts->isobar){ + rangednormkstarplus = int_mkpi_kstarzero_isobar_amp_squared(mkpi_min, mkpi_max, q2, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus, R); + rangednormkstar = int_mkpi_bw_kstar_amp_squared(mkpi_min, mkpi_max, q2, gammakstar, mkstar, R); + } + else{ + rangednormkstarplus = int_mkpi_kstarzero_lass_amp_squared(mkpi_min, mkpi_max, q2, asphase, a, r, gammakstarplus, mkstarplus, R); + rangednormkstar = int_mkpi_bw_kstar_amp_squared(mkpi_min, mkpi_max, q2, gammakstar, mkstar, R); + } + + double sxi1, sxi2, sxi3, sxi4, sxi5, sxi6; + if (opts->use_angular_acc){ + probs->at(k)->swave_integrated_fj_chebyshev(sxi1, sxi2, sxi3, sxi4, sxi5, sxi6, q2); + } + else{//weighted fit and fit without acceptance + probs->at(k)->swave_integrated_fj_noacc(sxi1, sxi2, sxi3, sxi4, sxi5, sxi6); + } + double xi1, xi2, xi3, xi4, xi5, xi6, + xi7, xi8, xi9, xi10, xi11, xi12; + //double q2 = peffq2->get_value(); + if (opts->use_angular_acc){ + probs->at(k)->integrated_fj_chebyshev(xi1, xi2, xi3, xi4, xi5, xi6, + xi7, xi8, xi9, xi10, xi11, xi12, q2); + } + else{//weighted fit and fit without acceptance + probs->at(k)->integrated_fj_noacc(xi1, xi2, xi3, xi4, xi5, xi6, + xi7, xi8, xi9, xi10, xi11, xi12); + } + + double s1s = params->at(k)->J1s(); + double s1c = params->at(k)->J1c(); + double s2s = params->at(k)->J2s(); + double s2c = params->at(k)->J2c(); + double s3 = params->at(k)->J3(); + double s4 = params->at(k)->J4(); + double s5 = params->at(k)->J5(); + double s6s = params->at(k)->J6s(); + double s6c = params->at(k)->J6c(); + double s7 = params->at(k)->J7(); + double s8 = params->at(k)->J8(); + double s9 = params->at(k)->J9(); + double fs = params->at(k)->FS(); + double ss1 = params->at(k)->SS1(); + double ss2 = params->at(k)->SS2(); + double ss3 = params->at(k)->SS3(); + double ss4 = params->at(k)->SS4(); + double ss5 = params->at(k)->SS5(); + + double norm = + (1-fs)*(xi1*s1s + xi2*s1c + xi3*s2s + xi4*s2c + xi5*s3 + xi6*s4 + + xi7*s5 + xi8*s6s + xi9*s6c + xi10*s7 + xi11*s8 + xi12*s9) + +(sxi1*fs + sxi2*ss1 + sxi3*ss2 + sxi4*ss3 + sxi5*ss4 + sxi6*ss5); + double A = (xi1*s1s + xi2*s1c + xi3*s2s + xi4*s2c + xi5*s3 + xi6*s4 + + xi7*s5 + xi8*s6s + xi9*s6c + xi10*s7 + xi11*s8 + xi12*s9)/norm; + double B = sxi1/norm; + double C = (sxi2*ss1 + sxi3*ss2 + sxi4*ss3)/norm; + double D = (sxi5*ss4 + sxi6*ss5)/norm; + + + double prob_bkg = 0.0, from = 0.0, to = 0.0; + for (unsigned int i = 0; i < pdf_bins; i++){ + + from = mkpi_min + i*dm; + to = mkpi_min + (i+1)*dm; + + double swavesq, pwavesq; + std::complex stimespwave; + + if (opts->simple_mkpi){ + swavesq = fcnc::int_mkpi_simple_kstarzero_amp_squared(from, to, q2, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus); + pwavesq = fcnc::int_mkpi_simple_bw_kstar_amp_squared(from, to, q2, gammakstar, mkstar); + stimespwave = fcnc::int_mkpi_simple_bw_kstar_amp_bar_kstarzero_amp(from, to, q2, + gammakstar, mkstar, asphase, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus); + } + else if (opts->isobar){ + swavesq = fcnc::int_mkpi_kstarzero_isobar_amp_squared(from, to, q2, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus, R); + pwavesq = fcnc::int_mkpi_bw_kstar_amp_squared(from, to, q2, gammakstar, mkstar, R); + stimespwave = fcnc::int_mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(from, to, q2, + gammakstar, mkstar, asphase, + f800mag, f800phase, gammaf800, mf800, gammakstarplus, mkstarplus, R); + } + else{//nominal lass + swavesq = fcnc::int_mkpi_kstarzero_lass_amp_squared(from, to, q2, asphase, a, r, gammakstarplus, mkstarplus, R); + pwavesq = fcnc::int_mkpi_bw_kstar_amp_squared(from, to, q2, gammakstar, mkstar, R); + stimespwave = fcnc::int_mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(from, to, q2, + gammakstar, mkstar, + asphase, a, r, gammakstarplus, mkstarplus, R); + } + + prob_bkg = 0.0; + if (opts->mkpi_threshold){ + prob_bkg = fcnc::int_threshold(from, to, 0.633, params->at(k)->nthreshold()); + } + else{ + for (unsigned int i=0; iSetBinContent(i+1, (1.0-fs)*pwave + fs*swave + interference); + tmp_bkg->SetBinContent(i+1, prob_bkg); + tmp_swave->SetBinContent(i+1, swave); + tmp_pwave->SetBinContent(i+1, pwave); + tmp_interference->SetBinContent(i+1, interference); + tmp_tot->SetBinContent(i+1, + fsig*((1.0-fs)*pwave + fs*swave + interference) + + (1.0-fsig)*prob_bkg); + } + + tmp_sig->Scale(nevents * fsig * double(pdf_bins) / double(mkpi_bins)); + tmp_swave->Scale(nevents * fs*fsig * double(pdf_bins) / double(mkpi_bins)); + tmp_pwave->Scale(nevents * (1.0-fs)*fsig * double(pdf_bins) / double(mkpi_bins)); + tmp_interference->Scale(nevents * fsig * double(pdf_bins) / double(mkpi_bins)); + tmp_bkg->Scale(nevents * (1.0-fsig) * double(pdf_bins) / double(mkpi_bins)); + tmp_tot->Scale(nevents * double(pdf_bins) / double(mkpi_bins)); + + mkpi_plot->Add(tmp_mkpi); + pdf_sig->Add(tmp_sig); + pdf_swave->Add(tmp_swave); + pdf_pwave->Add(tmp_pwave); + pdf_interference->Add(tmp_interference); + pdf_bkg->Add(tmp_bkg); + pdf_tot->Add(tmp_tot); + + delete tmp_mkpi; + delete tmp_sig; + delete tmp_swave; + delete tmp_pwave; + delete tmp_interference; + delete tmp_bkg; + delete tmp_tot; + + } + + double maxpdf = (pdf_tot->GetMaximum() > mkpi_plot->GetMaximum() ? pdf_tot->GetMaximum() : mkpi_plot->GetMaximum()); + if(this->pulls){ + if (logarithmic) pdf_sig->SetMinimum(0.1001); + else pdf_sig->SetMinimum(0.001); + } + else{ //no pull distributions + if (logarithmic) pdf_sig->SetMinimum(0.1); + else pdf_sig->SetMinimum(0.0); + } + + pdf_sig->SetMaximum(1.45*maxpdf); + + design_pdf(pdf_sig,kAzure, kAzure-5, 1001, 1-pullHeight, this->pulls); + if(pdf_sig->Integral() > 0.0) pdf_sig->Draw("hist C"); + + design_pdf(pdf_bkg,kOrange+10,kOrange+8, 3354, 1-pullHeight,pdf_sig->Integral() <= 0.0 ); + + if(pdf_sig->Integral() > 0.0){ + pdf_bkg->Draw("hist same C"); + } + else{ + pdf_bkg->SetMaximum(1.45*maxpdf); + pdf_bkg->SetMinimum(minBkg); + pdf_bkg->Draw("hist C"); + } + + + if(opts->swave){ + design_pdfLine(pdf_pwave, pWaveColor, kDashed); + pdf_pwave->Draw("hist same C"); + design_pdfLine(pdf_swave, sWaveColor, kDotted); + pdf_swave->Draw("hist same C"); + design_pdfLine(pdf_interference, psInterferenceColor, kDashDotted); + pdf_interference->Draw("hist same C"); + } + + + design_pdfLine(pdf_tot, kBlack, kSolid); + pdf_tot->Draw("hist same C"); + design_plot(mkpi_plot, 20, printC); + mkpi_plot->Draw("same e1"); + + //draw legend + TLegend* mkpi_leg = new TLegend(0.675,0.45,0.875,0.65); + mkpi_leg->SetBorderSize(0); + mkpi_leg->SetTextFont(132); + mkpi_leg->SetFillColor(0); + mkpi_leg->AddEntry(mkpi_plot, "data", "le"); + mkpi_leg->AddEntry(pdf_tot, "total PDF", "l"); + mkpi_leg->AddEntry(pdf_sig, "signal PDF", "l"); + mkpi_leg->AddEntry(pdf_bkg, "bkg PDF", "l"); + if(opts->swave){ + mkpi_leg->AddEntry(pdf_pwave, "P-wave PDF", "l"); + mkpi_leg->AddEntry(pdf_swave, "S-wave PDF", "l"); + mkpi_leg->AddEntry(pdf_interference, "interference PDF", "l"); + } + //mkpi_leg->Draw(); + + TLatex *tex = design_TLatex(texsizelarge,texsizesmall, pullHeight, 0.47, + this->pulls, opts->plot_label,opts->q2_label); + + if(this->pulls){ + assert(pdf_bins == mkpi_bins*bin_ratio); + + //calculate pulls from fit and data points: + for(UInt_t b = 1; b <= mkpi_bins; b++){ + double p; + if(mkpi_plot->GetBinError(b) == 0){ + p = 0.; + } + else{ + if(bin_ratio == 1){ + p = (mkpi_plot->GetBinContent(b) - pdf_tot->GetBinContent(b))/mkpi_plot->GetBinError(b); + } + //for odd ratio, take central bin from pdf w.r.t to m_bin: + else if(bin_ratio%2 != 0){ + p = (mkpi_plot->GetBinContent(b) - pdf_tot->GetBinContent(b*bin_ratio - bin_ratio/2))/mkpi_plot->GetBinError(b); + } + //else, average the two central bins from pdf w.r.t. to angle_bin: + else{ + p = (mkpi_plot->GetBinContent(b) - (pdf_tot->GetBinContent(b*bin_ratio - bin_ratio/2)+pdf_tot->GetBinContent(b*bin_ratio - bin_ratio/2 + 1))/2. ) / mkpi_plot->GetBinError(b); //take central of 10 pdfbins + } + } + mkpi_pulls->SetBinContent(b, p); + } + pad2->Clear(); + pad2->SetMargin(0.125,0.1,0.125/ pullHeight, 1e-6); + pad2->SetTickx(); + pad2->cd(); + + design_pull(mkpi_pulls, kBlack,kGray+2,pullHeight,pullFrameRange); + mkpi_pulls->Draw(); + + //add two 3-sigma lines: + TLine * lUp = threeSigmaLine(mkpi_min, mkpi_max, true); + TLine * lLow = threeSigmaLine(mkpi_min, mkpi_max, false); + lUp->Draw("same"); + lLow->Draw("same"); + } + + std::string mkpiname = prefix + "mkpi_" + postfix + "_AllPDFs"; + saveTCanvas(mkpi_canvas, mkpiname, opts->getAllPlotTypes()); + + output->cd(); + mkpi_canvas->Write(); + + delete mkpi_plot; + delete pdf_sig; + delete pdf_swave; + delete pdf_pwave; + delete pdf_interference; + delete pdf_bkg; + delete pdf_tot; + delete mkpi_pulls; + delete mkpi_canvas; + delete tex; + +} + +void bu2kstarmumu_plotter::plot_angle_added_pdfs(std::vector * probs, std::vector * params, std::vector*> * events, std::string prefix, std::string postfix, bool signalregion, std::string angle, bool printC){ + + bool is_ctl = false, is_ctk = false, is_phi = false; + std::string angle_name = latex_angle(angle, is_ctl, is_ctk, is_phi); + if(!is_ctl && !is_ctk && !is_phi) spdlog::error("Invalid angle name is given: " + angle ); + assert(is_ctl || is_ctk || is_phi); + + + unsigned int angle_bins = 0; + double angle_min = 0.; + double angle_max = 0.; + + if(is_ctl){ + angle_bins = opts->plots_costhetal_bins; + angle_min = opts->ctl_min; + angle_max = opts->ctl_max; + if(!opts->full_angular && opts->folding != 0) + angle_bins /= 2; + } + else if(is_ctk){ + angle_bins = opts->plots_costhetak_bins; + angle_min = opts->ctk_min; + angle_max = opts->ctk_max; + } + else if(is_phi){ + angle_bins = opts->plots_phi_bins; + angle_min = opts->phi_min; + angle_max = opts->phi_max; + if(!opts->full_angular) + angle_bins /= 2; + } + + assert(angle_min != 0. || angle_max != 0.); + + TCanvas *angle_canvas = nullptr; + if(printC){ + angle_canvas = new TCanvas((angle+"_"+postfix).c_str(), ("B+ Likelihood Analysis: "+angle_name+" projection").c_str()); + } + else{ + angle_canvas = new TCanvas((angle+"_"+postfix).c_str(), ("B+ Likelihood Analysis: "+angle_name+" projection").c_str(),1600,1200); + } + + const double pullHeight = 0.27; + const double pullFrameRange = 6.5; + TPad *pad1 = new TPad(("pad1_"+angle).c_str(), "plot",0.0,pullHeight,1.0,1.0,0); + TPad *pad2 = new TPad(("pad2_"+angle).c_str(), "pull",0.0,0.0,1.0,pullHeight,0); + if(this->pulls){ + pad1->Draw(); + pad2->Draw(); + pad1->SetBorderSize (0); + pad1->SetMargin(0.125,0.1,1e-6,0.1/ (1 - pullHeight)); + pad1->SetTickx(); + pad1->SetTicky(); + pad1->cd(); + } + else{ + angle_canvas->cd()->SetMargin(0.125,0.1,0.125,0.1); + angle_canvas->SetTickx(); + angle_canvas->SetTicky(); + } + std::ostringstream sout; + sout << ";" << angle_name << ";" << EVENTS_TAG << " / " << std::setprecision(2) << (angle_max-angle_min)/angle_bins; + std::ostringstream spulls; + spulls << ";" << angle_name << ";" + latex_pull(); + TH1D* angle_pulls = new TH1D("angle_pulls", spulls.str().c_str(), angle_bins, angle_min, angle_max); + + + const UInt_t bin_ratio = PLOT_NBINS_RATIO/2; + unsigned int pdf_bins = angle_bins * bin_ratio; + double dangle = (angle_max-angle_min)/pdf_bins; + + TH1D* angle_plot = new TH1D("m", sout.str().c_str(), angle_bins, angle_min, angle_max); + TH1D* pdf_sig = new TH1D("pdf_sig", sout.str().c_str(), pdf_bins, angle_min, angle_max); + TH1D* pdf_swave = new TH1D("pdf_swave", sout.str().c_str(), pdf_bins, angle_min, angle_max); + TH1D* pdf_pwave = new TH1D("pdf_pwave", sout.str().c_str(), pdf_bins, angle_min, angle_max); + TH1D* pdf_interference = new TH1D("pdf_interference", sout.str().c_str(), pdf_bins, angle_min, angle_max); + TH1D* pdf_bkg = new TH1D("pdf_bkg", sout.str().c_str(), pdf_bins, angle_min, angle_max); + TH1D* pdf_tot = new TH1D("pdf_tot", sout.str().c_str(), pdf_bins, angle_min, angle_max); + double prob_sig=0.0, prob_bkg=0.0, prob_pwave=0.0, prob_swave=0.0, prob_interference=0.0; + double ctk_from = 0.0, ctk_to = 0.0, ctl_from=0.0, ctl_to=0.0, phi_from=0.0, phi_to=0.0; + + angle_plot->Sumw2(); + + for(UInt_t k = 0; k < params->size(); k++){ + + TH1D* tmp_angle = new TH1D(("tmp_angle"+std::to_string(k)).c_str(), sout.str().c_str(), angle_bins, angle_min, angle_max); + TH1D* tmp_sig = new TH1D(("tmp_sig"+std::to_string(k)).c_str(), sout.str().c_str(), pdf_bins, angle_min, angle_max); + TH1D* tmp_swave = new TH1D(("tmp_swave"+std::to_string(k)).c_str(), sout.str().c_str(), pdf_bins, angle_min, angle_max); + TH1D* tmp_pwave = new TH1D(("tmp_pwave"+std::to_string(k)).c_str(), sout.str().c_str(), pdf_bins, angle_min, angle_max); + TH1D* tmp_interference = new TH1D(("tmp_interference"+std::to_string(k)).c_str(), sout.str().c_str(), pdf_bins, angle_min, angle_max); + TH1D* tmp_bkg = new TH1D(("tmp_bkg"+std::to_string(k)).c_str(), sout.str().c_str(), pdf_bins, angle_min, angle_max); + TH1D* tmp_tot = new TH1D(("tmp_tot"+std::to_string(k)).c_str(), sout.str().c_str(), pdf_bins, angle_min, angle_max); + + double ma = params->at(k)->m_b() - B_MASS_TIGHT_WINDOW; + double mb = params->at(k)->m_b() + B_MASS_TIGHT_WINDOW; + + double fsig = params->at(k)->f_sig(); + if(opts->extended_ml){ + fsig = params->at(k)->n_sig() / (params->at(k)->n_sig()+params->at(k)->n_bkg()); + } + if (signalregion){ + double rsig = probs->at(k)->integral_m_sig_prob(params->at(k), ma, mb); + double rbkg = probs->at(k)->integral_m_bkg_prob(params->at(k), ma, mb); + fsig = fsig*rsig/(fsig*rsig + (1.0-fsig)*rbkg); + } + + double nevents = 0.0; + for (unsigned int i = 0; i < events->at(k)->size(); i++){ + if (!signalregion || (events->at(k)->at(i).m > ma && events->at(k)->at(i).m < mb)){ + double weight = 1.0, value = -100.0; + if (opts->weighted_fit) + weight = events->at(k)->at(i).weight; + if(is_phi)value = events->at(k)->at(i).phi; + else if (is_ctk)value = events->at(k)->at(i).costhetak; + else if (is_ctl)value = events->at(k)->at(i).costhetal; + else return; + tmp_angle->Fill(value, weight); + nevents += weight; + } + } + + const double q2 = params->at(k)->eff_q2(); + const double j1s = params->at(k)->J1s(); + const double j1c = params->at(k)->J1c(); + const double j2s = params->at(k)->J2s(); + const double j2c = params->at(k)->J2c(); + const double j3 = params->at(k)->J3(); + const double j4 = params->at(k)->J4(); + const double j5 = params->at(k)->J5(); + const double j6s = params->at(k)->J6s(); + const double j6c = params->at(k)->J6c(); + const double j7 = params->at(k)->J7(); + const double j8 = params->at(k)->J8(); + const double j9 = params->at(k)->J9(); + + double f1=0.0, f2=0.0, f3=0.0, f4=0.0, f5=0.0, f6=0.0, + f7=0.0, f8=0.0, f9=0.0, f10=0.0, f11=0.0, f12=0.0; + + for (unsigned int i = 0; i < pdf_bins; i++){ + if(is_ctk){ + ctk_from = angle_min + i*dangle; + ctk_to = angle_min + (i+1)*dangle; + ctl_from = opts->ctl_min; + ctl_to = opts->ctl_max; + phi_from = opts->phi_min; + phi_to = opts->phi_max; + } + else if(is_ctl){ + ctk_from = opts->ctk_min; + ctk_to = opts->ctk_max; + ctl_from = angle_min + i*dangle; + ctl_to = angle_min + (i+1)*dangle; + phi_from = opts->phi_min; + phi_to = opts->phi_max; + } + else if(is_phi){ + ctk_from = opts->ctk_min; + ctk_to = opts->ctk_max; + ctl_from = opts->ctl_min; + ctl_to = opts->ctl_max; + phi_from = angle_min + i*dangle; + phi_to = angle_min + (i+1)*dangle; + } + else return; + + if (opts->full_angular){ + + if (opts->use_angular_acc){ + probs->at(k)->integrated_fj_chebyshev(ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, + f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12, q2); + } + else{ + probs->at(k)->integrated_fj_noacc(ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, + f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12); + } + prob_sig = (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9)/probs->at(k)->fnorm_sig; + prob_pwave = prob_sig; + if (opts->swave){ + const double fs = params->at(k)->FS(); + const double js1 = params->at(k)->SS1(); + const double js2 = params->at(k)->SS2(); + const double js3 = params->at(k)->SS3(); + const double js4 = params->at(k)->SS4(); + const double js5 = params->at(k)->SS5(); + + double fs1=0.0, fs2=0.0, fs3=0.0, fs4=0.0, fs5=0.0, fs6=0.0; + + if (opts->use_angular_acc) + probs->at(k)->swave_integrated_fj_chebyshev(ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, + fs1, fs2, fs3, fs4, fs5, fs6, q2); + else + probs->at(k)->swave_integrated_fj_noacc(ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, + fs1, fs2, fs3, fs4, fs5, fs6); + + prob_sig = ((1-fs)*(f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9) + +(fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5))/probs->at(k)->fnorm_sig; + prob_pwave = ((1-fs)*(f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9))/probs->at(k)->fnorm_sig; + prob_swave = fs1*fs/probs->at(k)->fnorm_sig; + prob_interference = (fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5)/probs->at(k)->fnorm_sig; + } + } + else { //folding + if (opts->use_angular_acc) probs->at(k)->folded_integrated_fj_chebyshev(ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, + f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12, q2); + else probs->at(k)->folded_integrated_fj_noacc(ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, + f1, f2, f3, f4, f5, f6, + f7, f8, f9, f10, f11, f12); + //Calculated probability for all foldings + //non-active coefficients are return 0 by 'folded'-functions in the lines above! + prob_sig = (f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9)/probs->at(k)->fnorm_sig; + prob_pwave = prob_sig; + if(opts->swave){ + const double fs = params->at(k)->FS(); + const double js1 = params->at(k)->SS1(); + const double js2 = params->at(k)->SS2(); + const double js3 = params->at(k)->SS3(); + const double js4 = params->at(k)->SS4(); + const double js5 = params->at(k)->SS5(); + + double fs1=0.0, fs2=0.0, fs3=0.0, fs4=0.0, fs5=0.0, fs6=0.0; + + if (opts->use_angular_acc) + probs->at(k)->folded_swave_integrated_fj_chebyshev(ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, + fs1, fs2, fs3, fs4, fs5, fs6, q2); + else + probs->at(k)->folded_swave_integrated_fj_noacc(ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, + fs1, fs2, fs3, fs4, fs5, fs6); + + prob_sig = ((1-fs)*(f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9) + +(fs1*fs + fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5))/probs->at(k)->fnorm_sig; + prob_pwave = ((1-fs)*(f1*j1s + f2*j1c + f3*j2s + f4*j2c + f5*j3 + f6*j4 + + f7*j5 + f8*j6s + f9*j6c + f10*j7 + f11*j8 + f12*j9))/probs->at(k)->fnorm_sig; + prob_swave = fs1*fs/probs->at(k)->fnorm_sig; + prob_interference = (fs2*js1 + fs3*js2 + fs4*js3 + fs5*js4 + fs6*js5)/probs->at(k)->fnorm_sig; + } + } + tmp_sig->SetBinContent(i+1, prob_sig); + tmp_interference->SetBinContent(i+1, prob_interference); + tmp_pwave->SetBinContent(i+1, prob_pwave); + if (opts->swave) tmp_swave->SetBinContent(i+1, prob_swave); + + if(opts->use_angular_acc && opts->use_weighted_bkg){ + if(opts->fit_full_angular_bkg && !opts->flat_bkg && !opts->full_angular){ + double pi = TMath::Pi(); + if(opts->folding == 0){ + prob_bkg = (probs->at(k)->integral_bkg_chebyshev(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, phi_from-pi, phi_to-pi, q2)) /probs->at(k)->fnorm_bkg; + } + else if(opts->folding == 1){ + prob_bkg = (probs->at(k)->integral_bkg_chebyshev(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, -phi_to, -phi_from, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), -ctl_to, -ctl_from, ctk_from, ctk_to, pi-phi_to, pi-phi_from, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), -ctl_to, -ctl_from, ctk_from, ctk_to, -pi+phi_from, -pi+phi_to, q2)) /probs->at(k)->fnorm_bkg; + } + else if(opts->folding == 2){ + prob_bkg = (probs->at(k)->integral_bkg_chebyshev(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, -phi_to, -phi_from, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), -ctl_to, -ctl_from, ctk_from, ctk_to, phi_from, phi_to, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), -ctl_to, -ctl_from, ctk_from, ctk_to, -phi_to, -phi_from, q2)) /probs->at(k)->fnorm_bkg; + } + else if(opts->folding == 3){ + if((phi_from <= 0.0 && phi_to <= 0.0) || (phi_from >= 0.0 && phi_to >= 0.0)){ + prob_bkg = (probs->at(k)->integral_bkg_chebyshev(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, (phi_from < 0.0 ? -pi - phi_to : pi - phi_to), (phi_to < 0.0 ? -pi - phi_from : pi - phi_from), q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), -ctl_to, -ctl_from, ctk_from, ctk_to, phi_from, phi_to, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), -ctl_to, -ctl_from, ctk_from, ctk_to, (phi_from < 0.0 ? -pi - phi_to : pi - phi_to), (phi_to < 0.0 ? -pi - phi_from : pi - phi_from), q2)) /probs->at(k)->fnorm_bkg; + } + else{ //when phi_from < 0.0 and phi_to > 0.0: + assert(phi_to > phi_from); + prob_bkg = (probs->at(k)->integral_bkg_chebyshev(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, -pi, -pi - phi_from, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, pi - phi_to, pi, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), -ctl_to, -ctl_from, ctk_from, ctk_to, phi_from, phi_to, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), -ctl_to, -ctl_from, ctk_from, ctk_to, -pi, -pi - phi_from, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), -ctl_to, -ctl_from, ctk_from, ctk_to, pi - phi_to, pi, q2)) /probs->at(k)->fnorm_bkg; + } + } + else if(opts->folding == 4){ + if((phi_from <= 0.0 && phi_to <= 0.0) || (phi_from >= 0.0 && phi_to >= 0.0)){ + prob_bkg = (probs->at(k)->integral_bkg_chebyshev(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, (phi_from < 0.0 ? -pi - phi_to : pi - phi_to), (phi_to < 0.0 ? -pi - phi_from : pi - phi_from), q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), -ctl_to, -ctl_from, -ctk_to, -ctk_from, phi_from, phi_to, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), -ctl_to, -ctl_from, -ctk_to, -ctk_from, (phi_from < 0.0 ? -pi - phi_to : pi - phi_to), (phi_to < 0.0 ? -pi - phi_from : pi - phi_from), q2)) /probs->at(k)->fnorm_bkg; + } + else{ //when phi_from < 0.0 and phi_to > 0.0: + assert(phi_to > phi_from); + prob_bkg = (probs->at(k)->integral_bkg_chebyshev(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, -pi, -pi - phi_from, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, pi - phi_to, pi, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), -ctl_to, -ctl_from, -ctk_to, -ctk_from, phi_from, phi_to, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), -ctl_to, -ctl_from, -ctk_to, -ctk_from, -pi, -pi - phi_from, q2) + + probs->at(k)->integral_bkg_chebyshev(params->at(k), -ctl_to, -ctl_from, -ctk_to, -ctk_from, pi - phi_to, pi, q2)) /probs->at(k)->fnorm_bkg; + } + } + } + else{ + prob_bkg = probs->at(k)->integral_bkg_chebyshev(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to, q2) /probs->at(k)->fnorm_bkg; + } + } + else{ + if(opts->fit_full_angular_bkg && !opts->flat_bkg && !opts->full_angular){ + double pi = TMath::Pi(); + if(opts->folding == 0){ + prob_bkg = (probs->at(k)->integral_bkg(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to) + + probs->at(k)->integral_bkg(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, phi_from-pi, phi_to-pi)) /probs->at(k)->fnorm_bkg; + } + else if(opts->folding == 1){ + prob_bkg = (probs->at(k)->integral_bkg(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to) + + probs->at(k)->integral_bkg(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, -phi_to, -phi_from) + + probs->at(k)->integral_bkg(params->at(k), -ctl_to, -ctl_from, ctk_from, ctk_to, pi-phi_to, pi-phi_from) + + probs->at(k)->integral_bkg(params->at(k), -ctl_to, -ctl_from, ctk_from, ctk_to, -pi+phi_from, -pi+phi_to)) /probs->at(k)->fnorm_bkg; + } + else if(opts->folding == 2){ + prob_bkg = (probs->at(k)->integral_bkg(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to) + + probs->at(k)->integral_bkg(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, -phi_to, -phi_from) + + probs->at(k)->integral_bkg(params->at(k), -ctl_to, -ctl_from, ctk_from, ctk_to, phi_from, phi_to) + + probs->at(k)->integral_bkg(params->at(k), -ctl_to, -ctl_from, ctk_from, ctk_to, -phi_to, -phi_from)) /probs->at(k)->fnorm_bkg; + } + else if(opts->folding == 3){ + if((phi_from <= 0.0 && phi_to <= 0.0) || (phi_from >= 0.0 && phi_to >= 0.0)){ + prob_bkg = (probs->at(k)->integral_bkg(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to) + + probs->at(k)->integral_bkg(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, (phi_from < 0.0 ? -pi - phi_to : pi - phi_to), (phi_to < 0.0 ? -pi - phi_from : pi - phi_from)) + + probs->at(k)->integral_bkg(params->at(k), -ctl_to, -ctl_from, ctk_from, ctk_to, phi_from, phi_to) + + probs->at(k)->integral_bkg(params->at(k), -ctl_to, -ctl_from, ctk_from, ctk_to, (phi_from < 0.0 ? -pi - phi_to : pi - phi_to), (phi_to < 0.0 ? -pi - phi_from : pi - phi_from))) /probs->at(k)->fnorm_bkg; + } + else{ //when phi_from < 0.0 and phi_to > 0.0: + assert(phi_to > phi_from); + prob_bkg = (probs->at(k)->integral_bkg(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to) + + probs->at(k)->integral_bkg(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, -pi, -pi - phi_from) + + probs->at(k)->integral_bkg(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, pi - phi_to, pi) + + probs->at(k)->integral_bkg(params->at(k), -ctl_to, -ctl_from, ctk_from, ctk_to, phi_from, phi_to) + + probs->at(k)->integral_bkg(params->at(k), -ctl_to, -ctl_from, ctk_from, ctk_to, -pi, -pi - phi_from) + + probs->at(k)->integral_bkg(params->at(k), -ctl_to, -ctl_from, ctk_from, ctk_to, pi - phi_to, pi)) /probs->at(k)->fnorm_bkg; + } + } + else if(opts->folding == 4){ + if((phi_from <= 0.0 && phi_to <= 0.0) || (phi_from >= 0.0 && phi_to >= 0.0)){ + prob_bkg = (probs->at(k)->integral_bkg(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to) + + probs->at(k)->integral_bkg(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, (phi_from < 0.0 ? -pi - phi_to : pi - phi_to), (phi_to < 0.0 ? -pi - phi_from : pi - phi_from)) + + probs->at(k)->integral_bkg(params->at(k), -ctl_to, -ctl_from, -ctk_to, -ctk_from, phi_from, phi_to) + + probs->at(k)->integral_bkg(params->at(k), -ctl_to, -ctl_from, -ctk_to, -ctk_from, (phi_from < 0.0 ? -pi - phi_to : pi - phi_to), (phi_to < 0.0 ? -pi - phi_from : pi - phi_from))) /probs->at(k)->fnorm_bkg; + } + else{ //when phi_from < 0.0 and phi_to > 0.0: + assert(phi_to > phi_from); + prob_bkg = (probs->at(k)->integral_bkg(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to) + + probs->at(k)->integral_bkg(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, -pi, -pi - phi_from) + + probs->at(k)->integral_bkg(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, pi - phi_to, pi) + + probs->at(k)->integral_bkg(params->at(k), -ctl_to, -ctl_from, -ctk_to, -ctk_from, phi_from, phi_to) + + probs->at(k)->integral_bkg(params->at(k), -ctl_to, -ctl_from, -ctk_to, -ctk_from, -pi, -pi - phi_from) + + probs->at(k)->integral_bkg(params->at(k), -ctl_to, -ctl_from, -ctk_to, -ctk_from, pi - phi_to, pi)) /probs->at(k)->fnorm_bkg; + } + } + } + else{ + prob_bkg = probs->at(k)->integral_bkg(params->at(k), ctl_from, ctl_to, ctk_from, ctk_to, phi_from, phi_to) /probs->at(k)->fnorm_bkg; + } + } + tmp_bkg->SetBinContent(i+1, prob_bkg); + } + + tmp_sig->Scale(nevents * fsig * double(pdf_bins) / double(angle_bins)); + tmp_pwave->Scale(nevents * fsig * double(pdf_bins) / double(angle_bins)); + if (opts->swave) tmp_swave->Scale(nevents * fsig * double(pdf_bins) / double(angle_bins)); + tmp_interference->Scale(nevents * fsig * double(pdf_bins) / double(angle_bins)); + + tmp_bkg->Scale(nevents * (1.0-fsig) * double(pdf_bins) / double(angle_bins)); + + tmp_tot->Add(tmp_sig, tmp_bkg); + + angle_plot->Add(tmp_angle); + pdf_sig->Add(tmp_sig); + if (opts->swave) pdf_swave->Add(tmp_swave); + pdf_pwave->Add(tmp_pwave); + pdf_interference->Add(tmp_interference); + pdf_bkg->Add(tmp_bkg); + pdf_tot->Add(tmp_tot); + + delete tmp_angle; + delete tmp_sig; + delete tmp_swave; + delete tmp_pwave; + delete tmp_interference; + delete tmp_bkg; + delete tmp_tot; + + } + + double maxpdf = (pdf_tot->GetMaximum() > angle_plot->GetMaximum() ? pdf_tot->GetMaximum() : angle_plot->GetMaximum()); + if(this->pulls) pdf_sig->SetMinimum(0.1001); + else pdf_sig->SetMinimum(0.0); + + pdf_sig->SetMaximum(1.45*maxpdf); + pdf_sig->SetTitleSize(0.06, "XY"); + pdf_sig->SetLabelSize(0.05, "XY"); + pdf_sig->SetTitleOffset(0.9, "XY"); + pdf_sig->GetXaxis()->SetNoExponent(kTRUE); + TGaxis::SetMaxDigits(3); + design_pdf(pdf_sig,kAzure, kAzure-5, 1001, 1-pullHeight, this->pulls); + if(pdf_sig->Integral() > 0.0) pdf_sig->Draw("hist C"); + + design_pdf(pdf_bkg,kOrange+10,kOrange+8, 3354, 1-pullHeight,pdf_sig->Integral() <= 0.0 ); + + if(pdf_sig->Integral() > 0.0){ + pdf_bkg->Draw("hist same C"); + } + else{ + pdf_bkg->SetMaximum(1.45*maxpdf); + pdf_bkg->SetMinimum(minBkg); + pdf_bkg->Draw("hist C"); + } + + ///// + + design_pdfLine(pdf_pwave, pWaveColor, kDashed); + if(opts->swave) pdf_pwave->Draw("hist same C"); + + design_pdfLine(pdf_swave, sWaveColor, kDotted); + if(opts->swave) pdf_swave->Draw("hist same C"); + + design_pdfLine(pdf_interference, psInterferenceColor, kDashDotted); + if(opts->swave) pdf_interference->Draw("hist same C"); + + design_pdfLine(pdf_tot, kBlack, kSolid); + pdf_tot->Draw("hist same C"); + + design_plot(angle_plot, 20, printC); + angle_plot->Draw("same e1"); + + TLegend* angle_leg = new TLegend(0.675,0.45,0.875,0.65); + angle_leg->SetBorderSize(0); + angle_leg->SetTextFont(132); + angle_leg->SetFillColor(0); + angle_leg->AddEntry(angle_plot, "data", "le"); + angle_leg->AddEntry(pdf_tot, "total PDF", "l"); + angle_leg->AddEntry(pdf_sig, "signal PDF", "l"); + angle_leg->AddEntry(pdf_bkg, "bkg PDF", "l"); + if(opts->swave){ + angle_leg->AddEntry(pdf_pwave, "P-wave PDF", "l"); + angle_leg->AddEntry(pdf_swave, "S-wave PDF", "l"); + angle_leg->AddEntry(pdf_interference, "interference PDF", "l"); + } + //angle_leg->Draw("same"); + + TLatex *tex = design_TLatex(texsizelarge,texsizesmall, pullHeight, 0.47, + this->pulls, opts->plot_label,opts->q2_label); + + if(this->pulls){ + assert(pdf_bins == angle_bins*bin_ratio); + + //calculate pulls from fit and data points: + for(UInt_t b = 1; b <= angle_bins; b++){ + double p; + if(angle_plot->GetBinError(b) == 0) + p = 0.; + else{ + if(bin_ratio == 1){ + p = (angle_plot->GetBinContent(b) - pdf_tot->GetBinContent(b))/angle_plot->GetBinError(b); + } + //for odd ratio, take central bin from pdf w.r.t to angle_bin: + else if(bin_ratio%2 != 0){ + p = (angle_plot->GetBinContent(b) - pdf_tot->GetBinContent(b*bin_ratio - bin_ratio/2))/angle_plot->GetBinError(b); + } + //else, average the two central bins from pdf w.r.t. to angle_bin: + else{ + p = (angle_plot->GetBinContent(b) - (pdf_tot->GetBinContent(b*bin_ratio - bin_ratio/2)+pdf_tot->GetBinContent(b*bin_ratio - bin_ratio/2 + 1))/2. ) / angle_plot->GetBinError(b); //take central of 10 pdfbins + } + } + angle_pulls->SetBinContent(b, p); + } + pad2->Clear(); + pad2->SetMargin(0.125,0.1,0.125/ pullHeight, 1e-6); + pad2->SetTickx(); + pad2->cd(); + + design_pull(angle_pulls, kBlack,kGray+2,pullHeight,pullFrameRange); + angle_pulls->Draw(); + + //add two 3-sigma lines: + TLine * lUp = threeSigmaLine(angle_min, angle_max, true); + TLine * lLow = threeSigmaLine(angle_min, angle_max, false); + lUp->Draw("same"); + lLow->Draw("same"); + } + + std::string anglename = prefix + angle + "_" + postfix+ "_AllPDFs"; + saveTCanvas(angle_canvas, anglename, opts->getAllPlotTypes()); + + output->cd(); + angle_canvas->Write(); + + delete angle_plot; + delete angle_pulls; + delete pdf_sig; + delete pdf_pwave; + delete pdf_swave; + delete pdf_interference; + delete pdf_bkg; + delete pdf_tot; + delete angle_canvas; + delete tex; +} + +void bu2kstarmumu_plotter::SetPulls(bool drawpulls){ + this->pulls = drawpulls; +} + +int bu2kstarmumu_plotter::plotYieldInQ2(bool fixRange, std::vector fitParams[], std::vector pdf[], int nPDFs, std::vectornEvts[], std::string prefix, std::string plotName){ + + // CMS [1 - 8.68], [10.09 - 12.86], [14.18 - 19.00] + double CMS_X[3] = {4.84, 11.475, 16.59}; + double CMS_EX[3] = {3.84, 1.385, 2.41}; + double CMS_Y[3] = {2.7, 4.1, 5.6}; + double CMS_EY[3] = {0.0, 0.0, 0.0}; + double CMS_sig[3] = {22.1,25.9,45.1}; + double CMS_sig_E[3] = {8.1,6.3,8.0}; + double CMS_bkg[3] = {49.0,14.0,20.0}; + double CMS_bkg_E[3] = {0.0,0.0,0.0}; + + TGraphErrors *graphSignificanceCMS = new TGraphErrors(3,CMS_X,CMS_Y,CMS_EX,CMS_EY); + //Not used, but keep it in case + TGraphErrors *graphSigCMS = new TGraphErrors(3,CMS_X,CMS_sig,CMS_EX,CMS_sig_E); + TGraphErrors *graphBkgCMS = new TGraphErrors(3,CMS_X,CMS_bkg,CMS_EX,CMS_bkg_E); + graphSigCMS->SetTitle("SigCMS"); + graphBkgCMS->SetTitle("BkgCMS"); + + //Protection against the 1.1-6.0 bin + const int nBins = opts->get_nQ2bins()==5 ? 4 : opts->get_nQ2bins(); + + double bkg_yield_tot[nBins]; + double sig_yield_tot[nBins]; + for (int n = 0; n < nPDFs; n++){ + TGraphErrors *tmpSig = new TGraphErrors(); + TGraphErrors *tmpBkg = new TGraphErrors(); + TGraphErrors *tmpSignificance = new TGraphErrors(); + + for (int b = 0; b < nBins; b++){ + + double binCenter = bin_center_q2(opts,b); + double binError = bin_halfWidth_q2(opts,b); + + //TODO: add couts + //First get the measured mean + double measured_m =((fcnc::bu2kstarmumu_parameters *)fitParams[b].at(n))->m_b.get_value(); + //Then get the fraction of signal + double f_sig =((fcnc::bu2kstarmumu_parameters *)fitParams[b].at(n))->f_sig.get_value(); + + //If fixed window, use B_MASS_TIGHT_WINDOW + //Otherwise use 2*sigma //TODO: for now only one sigma + double window = 0.0; + if (fixRange) window = B_MASS_TIGHT_WINDOW; + else window = 2*((fcnc::bu2kstarmumu_parameters *)fitParams[b].at(n))->m_sigma_1.get_value(); + + //Get the probabilities + double sig_prob = ((fcnc::bu2kstarmumu_pdf*) pdf[b].at(n))->integral_m_sig_prob((fcnc::bu2kstarmumu_parameters*)fitParams[b].at(n),measured_m-window, measured_m+window); + + double bkg_prob = ((fcnc::bu2kstarmumu_pdf*) pdf[b].at(n))->integral_m_bkg_prob((fcnc::bu2kstarmumu_parameters*)fitParams[b].at(n),measured_m-window, measured_m+window); + + double bkg_yield = bkg_prob * nEvts[b].at(n)*(1.0-f_sig); + double sig_yield = sig_prob * nEvts[b].at(n)*f_sig; + bkg_yield_tot[b] += bkg_yield; + sig_yield_tot[b] += sig_yield; + + spdlog::debug("Bkg yield: {0:f}", bkg_yield); + spdlog::debug("Sig yield: {0:f}", sig_yield); + //TODO: add yield errors! + double significance = sig_yield/sqrt(sig_yield+bkg_yield); + + //Signal + tmpSig->SetPoint(tmpSig->GetN(), binCenter, sig_yield); + tmpSig->SetPointError(tmpSig->GetN()-1, binError, 0.0); + //Background + tmpBkg->SetPoint(tmpBkg->GetN(), binCenter, bkg_yield); + tmpBkg->SetPointError(tmpBkg->GetN()-1, binError, 0.0); + //Significance + tmpSignificance->SetPoint(tmpSignificance->GetN(), binCenter, significance); + tmpSignificance->SetPointError(tmpSignificance->GetN()-1,binError,0.0); + } + std::string tmpPlotName = prefix+ plotName + "_significance_Run" + std::to_string(n+1); + //TODO: n+1 is run, so this should be fixed to pdf_idx + design_YieldInQ2(n+1, tmpSig, tmpBkg, tmpSignificance, graphSignificanceCMS, fixRange, tmpPlotName,opts->getAllPlotTypes()); + design_SignificanceInQ2(n+1,tmpSignificance,graphSignificanceCMS,fixRange, std::string(tmpPlotName+"_noYields"),opts->getAllPlotTypes()); + + } + + //Make a Run 1+2 plot + TGraphErrors *totSig = new TGraphErrors(); + TGraphErrors *totBkg = new TGraphErrors(); + TGraphErrors *totSignificance = new TGraphErrors(); + + for (int b = 0; b < nBins; b++){ + double significance = sig_yield_tot[b]/sqrt( sig_yield_tot[b]+ bkg_yield_tot[b]); + + double binCenter = bin_center_q2(opts,b); + double binError = bin_halfWidth_q2(opts,b); + + //Signal + totSig->SetPoint(totSig->GetN(), binCenter, sig_yield_tot[b]); + totSig->SetPointError(totSig->GetN()-1, binError, 0.0); + //Background + totBkg->SetPoint(totBkg->GetN(), binCenter, bkg_yield_tot[b]); + totBkg->SetPointError(totBkg->GetN()-1, binError, 0.0); + //Significance + totSignificance->SetPoint(totSignificance->GetN(), binCenter, significance); + totSignificance->SetPointError(totSignificance->GetN()-1,binError,0.0); + + } + std::string tmpPlotName = prefix+ plotName + "_significance_Run" + std::to_string(12); + design_YieldInQ2(12, totSig, totBkg, totSignificance, graphSignificanceCMS, fixRange, tmpPlotName,opts->getAllPlotTypes()); + design_SignificanceInQ2(12, graphSignificanceCMS, graphSignificanceCMS, fixRange, std::string(tmpPlotName+"_noYields"),opts->getAllPlotTypes()); + + return 0; +} + + diff --git a/Code/FCNCFitter/sources/Core/bu2kstarmumu_plotter.hh b/Code/FCNCFitter/sources/Core/bu2kstarmumu_plotter.hh new file mode 100755 index 0000000..1f53301 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/bu2kstarmumu_plotter.hh @@ -0,0 +1,66 @@ +/** + * @file bu2kstarmumu_plotter.hh + * @author Christoph Langenbruch, Renata Kopecna + * @date 2009-03-18 + * + */ + +#ifndef BU2KSTARMUMU_PLOTTER_H +#define BU2KSTARMUMU_PLOTTER_H + +#include +#include + +#include +#include + +namespace fcnc { + +///class to plots the data and the fitted pdf, also plots the efficiencies +class bu2kstarmumu_plotter: public plotter {//was derived from plotter +public: + ///constructor + bu2kstarmumu_plotter(options* o); + ///destructor + ~bu2kstarmumu_plotter(); + ///plots all projections + /// + int design_pdf(TH1D *pdf, Color_t lineColor, Color_t fillColor, int fillStyle, double eff_pullHeight, bool doPull); + + int plot_data(bu2kstarmumu_pdf* prob, bu2kstarmumu_parameters* params, std::vector* events, std::string prefix, std::string postfix="", bool signalregion=false); + + int plot_data(pdf* prob, parameters* params, std::vector* ev, std::string index) { + return plot_data(dynamic_cast(prob), dynamic_cast(params), ev, index); + }; + void plot_pdfs(std::vector * probs, std::vector * params, std::string postfix, bool signalregion=false); + void plot_added_pdfs(std::vector * probs, std::vector * params, std::vector*> * events, std::string prefix, std::string postfix, bool signalregion=false); + void SetPulls(bool drawpulls=true); + + //Plot yields of sig and bkg in one go together with significance and the CMS measurement + //Technically this could be in the scritps, but whatever at this point //TODO + int plotYieldInQ2(bool fixRange, std::vector fitParams[], std::vector pdf[], int nPDFs, std::vectornEvts[], std::string prefix, std::string plotName); +private: + ///pointer to options object + options* opts; + ///draw pull distribuions under plots? + bool pulls; + ///root output file + TFile* output; + ///tex sizes + double texsizelarge=0.06, texsizesmall=0.04; + ///plots the mass projection. + void plot_m(bu2kstarmumu_pdf* prob, bu2kstarmumu_parameters* params, std::vector* events, std::string prefix, std::string postfix, bool logarithmic=false, bool printC=false); + void plot_mkpi(bu2kstarmumu_pdf* prob, bu2kstarmumu_parameters* params, std::vector* events, std::string prefix, std::string postfix, bool signalregion=false, bool logarithmic=false, bool printC=false); + ///plots a given angle projection + void plot_angle(bu2kstarmumu_pdf* prob, bu2kstarmumu_parameters* params, std::vector* events, std::string prefix, std::string postfix, bool signalregion=false, std::string angle = "ctl", bool printC=false); + ///plots of pdfs added into one signal histogram! + void plot_m_added_pdfs(std::vector * probs, std::vector * params, std::vector*> * events, std::string prefix, std::string postfix, bool logarithmic=false, bool printC=false); + void plot_mkpi_added_pdfs(std::vector * probs, std::vector * params, std::vector*> * events, std::string prefix, std::string postfix, bool signalregion=false, bool logarithmic=false, bool printC=false); + void plot_angle_added_pdfs(std::vector * probs, std::vector * params, std::vector*> * events, std::string prefix, std::string postfix, bool signalregion=false, std::string angle = "ctl", bool printC=false); + + +}; + +} + +#endif diff --git a/Code/FCNCFitter/sources/Core/event.cc b/Code/FCNCFitter/sources/Core/event.cc new file mode 100755 index 0000000..c4c7071 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/event.cc @@ -0,0 +1,287 @@ +//Renata Kopecna + +#include + +#include +#include +#include + +#include "TFile.h" +#include "TTree.h" +#include "TMath.h" + +#include +#include +#include +#include + +#include + +void fcnc::print_event(const event& meas) +{ + spdlog::info("Event has" ); + spdlog::info( " m: {0:f}", meas.m); + spdlog::info( " sigma_m: {0:f}", meas.sigma_m); + spdlog::info( " weight: {0:f}", meas.weight); + spdlog::info( " delta_weight: {0:f}", meas.delta_weight); + spdlog::info( " max_mu_pt: {0:f}", meas.max_mu_pt); + spdlog::info( " kaon_pt: {0:f}", meas.kaon_pt); + spdlog::info( " event_type: {0:d}", meas.event_type); + spdlog::info( " Magnet polarity: {0:d}", meas.magnet ); + spdlog::info( " cos(thetal): {0:f}", meas.costhetal ); + spdlog::info( " cos(thetak): {0:f}", meas.costhetak ); + spdlog::info( " phi: {0:f}", meas.phi ); + + spdlog::info( " q2: {0:f}", meas.q2 ); + spdlog::info( " p2: {0:f}", meas.p2 ); + spdlog::info( " cp conjugate: " +(meas.cp_conjugate) ); + + //spdlog::trace( " tagging_decision: {0:f}", meas.tagging_decision ); + //spdlog::trace( " tagging_dilution: {0:f}", meas.tagging_dilution ); + //spdlog::trace( " efficiency: {0:f}", meas.efficiency ); +} + +void fcnc::save_events(std::string filename, const std::vector& events){ + TFile* output = new TFile(filename.c_str(), "RECREATE"); + output->cd(); + TTree* tree = new TTree("Events", "Events"); + //init and link parameters + bool cp_conjugate; + int year, magnet, event_type; + double m, mkpi, sigma_m, costhetal, costhetak, phi, q2, p2, weight, delta_weight, kaon_pt, max_mu_pt, pseudo_q2; + tree->Branch("year",&year,"year/I"); + tree->Branch("m",&m,"m/D"); + tree->Branch("mkpi",&mkpi,"mkpi/D"); + tree->Branch("sigma_m",&sigma_m,"sigma_m/D"); + tree->Branch("costhetal",&costhetal,"costhetal/D"); + tree->Branch("costhetak",&costhetak,"costhetak/D"); + tree->Branch("phi",&phi,"phi/D"); + tree->Branch("magnet", &magnet, "magnet/I"); + tree->Branch("q2",&q2,"q2/D"); + tree->Branch("p2",&p2,"p2/D"); + tree->Branch("cp_conjugate",&cp_conjugate,"cp_conjugate/O"); + tree->Branch("weight", &weight, "weight/D"); + tree->Branch("delta_weight", &delta_weight, "delta_weight/D"); + tree->Branch("kaon_pt", &kaon_pt, "kaon_pt/D"); + tree->Branch("max_mu_pt", &max_mu_pt, "max_mu_pt/D"); + tree->Branch("pseudo_q2", &pseudo_q2, "pseudo_q2/D"); + tree->Branch("event_type", &event_type, "event_type/I"); //TODO + spdlog::info( "START to fill events into TTree and save to file!" ); + + for (unsigned int i=0; i< events.size(); i++){ + //get event from vector + fcnc::event meas = events.at(i); + //copy all values to the linked objects to save in TBranches + year = meas.year; + m = meas.m; + mkpi = meas.mkpi; + sigma_m = meas.sigma_m; + costhetal = meas.costhetal; + costhetak = meas.costhetak; + phi = meas.phi; + magnet = meas.magnet; + q2 = meas.q2; + p2 = meas.p2; + cp_conjugate = meas.cp_conjugate; + weight = meas.weight; + delta_weight = meas.delta_weight; + kaon_pt = meas.kaon_pt; + max_mu_pt = meas.max_mu_pt; + pseudo_q2 = meas.pseudo_q2; + event_type = meas.event_type; + //write to TTree + tree->Fill(); + } + Int_t N = tree->GetEntries(); + tree->Write(); + output->Write(); + output->Close(); + spdlog::info("DONE: Successfully saved {0:d} (out of {1:d}) events to file {2:s}", N, events.size(), filename); + return; + +} + +void fcnc::lhcbtotheory(const bool b_plus, const double ctl_lhcb, const double ctk_lhcb, const double phi_lhcb, double& ctl_th, double& ctk_th, double& phi_th) +{ + ctl_th = b_plus ? ctl_lhcb : -ctl_lhcb; + ctk_th = -ctk_lhcb; + if (b_plus) + phi_th = phi_lhcb > 0 ? TMath::Pi() - phi_lhcb : -TMath::Pi() - phi_lhcb; + else + phi_th = phi_lhcb; +} + +void fcnc::theorytolhcb(const bool b_plus, const double ctl_th, const double ctk_th, const double phi_th, double& ctl_lhcb, double& ctk_lhcb, double& phi_lhcb) +{ + ctl_lhcb = b_plus ? ctl_th : -ctl_th; + ctk_lhcb = -ctk_th; + if (b_plus) + phi_lhcb = phi_th > 0 ? TMath::Pi() - phi_th : -TMath::Pi() - phi_th; + else + phi_lhcb = phi_th; +} + +void fcnc::save_eos_events(std::string filename, const std::vector& events) +{ + TFile* output = new TFile(filename.c_str(), "RECREATE"); + output->cd(); + TTree* tree = new TTree("Events", "Events"); + fcnc::event meas; + tree->Branch("m",&meas.m,"m/D"); + tree->Branch("mkpi",&meas.mkpi,"mkpi/D"); + //double costhetal_lhcb, costhetak_lhcb, phi_lhcb; + double costhetal_th, costhetak_th, phi_th; + + // tree->Branch("costhetal",&costhetal_lhcb,"costhetal/D"); + // tree->Branch("costhetak",&costhetak_lhcb,"costhetak/D"); + // tree->Branch("phi",&phi_lhcb,"phi/D"); + + // tree->Branch("costhetal_theory",&meas.costhetal,"costhetal_theory/D"); + // tree->Branch("costhetak_theory",&meas.costhetak,"costhetak_theory/D"); + // tree->Branch("phi_theory",&meas.phi,"phi_theory/D"); + + tree->Branch("costhetal",&meas.costhetal,"costhetal/D"); + tree->Branch("costhetak",&meas.costhetak,"costhetak/D"); + tree->Branch("phi",&meas.phi,"phi/D"); + + tree->Branch("costhetal_theory",&costhetal_th,"costhetal_theory/D"); + tree->Branch("costhetak_theory",&costhetak_th,"costhetak_theory/D"); + tree->Branch("phi_theory",&phi_th,"phi_theory/D"); + + tree->Branch("q2",&meas.q2,"q2/D"); + tree->Branch("p2",&meas.p2,"p2/D"); + tree->Branch("cp_conjugate",&meas.cp_conjugate,"cp_conjugate/O"); + int bid; + tree->Branch("bid",&bid,"bid/I"); + tree->Branch("bkgcat", &meas.event_type, "bkgcat/I"); + + for (unsigned int i=0; i< events.size(); i++) + { + meas = events.at(i); + bid = meas.cp_conjugate ? +511 : -511; + + //convert from theory convention to lhcb convention + lhcbtotheory(bid > 0, meas.costhetal, meas.costhetak, meas.phi, costhetal_th, costhetak_th, phi_th); + tree->Fill(); + } + tree->Write(); + output->Write(); + output->Close(); + delete output; +} + +//Removes the resonances from the data sample +bool isResonance(double q2){ + for (auto bin: EXCLUDED_Q2){ + if (bin[0] fcnc::filterResonances(std::vector events){ + std::vector filtered; + for (auto evt: events){ + if (isResonance(evt.q2)) continue; + filtered.push_back(evt); + } + return filtered; +} + +std::vector fcnc::load_events(std::string filename, std::string treename, int neventsmax) +{ + spdlog::info("Reading " + filename + " into fcnc event vector."); + TFile* input = new TFile(filename.c_str(), "READ"); + TTree* tree = dynamic_cast(input->Get(treename.c_str())); + spdlog::debug("Treename: " + std::string(tree->GetName())); + fcnc::event meas; + + tree->SetBranchAddress("year", &meas.year); + tree->SetBranchAddress("m",&meas.m); + tree->SetBranchAddress("mkpi",&meas.mkpi); + tree->SetBranchAddress("sigma_m",&meas.sigma_m); + + tree->SetBranchAddress("costhetal",&meas.costhetal); + tree->SetBranchAddress("costhetak",&meas.costhetak); + tree->SetBranchAddress("phi",&meas.phi); + + tree->SetBranchAddress("q2",&meas.q2); + tree->SetBranchAddress("p2",&meas.p2); + tree->SetBranchAddress("cp_conjugate",&meas.cp_conjugate); + //tree->SetBranchAddress("bkgcat",&meas.event_type); //ONLY USED IN TOYS + tree->SetBranchAddress("magnet", &meas.magnet); + tree->SetBranchAddress("weight", &meas.weight); + tree->SetBranchAddress("delta_weight", &meas.delta_weight); + tree->SetBranchAddress("kaon_pt", &meas.kaon_pt); + tree->SetBranchAddress("max_mu_pt", &meas.max_mu_pt); + + std::vector result; + unsigned int nmax = tree->GetEntries(); + if (neventsmax > 0){ + unsigned int n = TMath::Abs(neventsmax); + if(n < nmax)nmax = n; + } + for (unsigned int i=0; i< nmax; i++){ + tree->GetEntry(i); + if (!isEvtInAngleRange(&meas)) continue; + meas.costhetal_fa = meas.costhetal; + meas.costhetak_fa = meas.costhetak; + meas.phi_fa = meas.phi; + result.push_back(meas); + } + spdlog::debug("Read events: {0:d}",result.size()); + input->Close(); + //delete tree; + delete input; + return result; +}; + +std::vector merge_two_evtVecs(std::vector one, std::vector two){ + std::vector merged_vec; + merged_vec.insert(merged_vec.end(), one.begin(), one.end()); + merged_vec.insert(merged_vec.end(), two.begin(), two.end()); + return merged_vec; +} + +//run over the complete tree and create a tree with only the branches needed for FCNC in the correct nomenclature of the FCNCfitter +//the data and MC samples are divided into 6 sub-samples: 2 per Run, 3 per sub-decay (K+pi0, KS0pi+(DD) and KS0pi-(LL)) +int convert_tuples(int job_id, std::string theFCNCpath, fcnc::options opts,std::vector years){ + + spdlog::info( "Converting "+get_sample_from_jobID(job_id)+" tuples of Run {0:d} to FCNC format",opts.run); + + reset_spdlog(); // back to default format + + //load the options + fcnc::bu2kstarmumu_loader loader(&opts); + + //initialize a vector of this special class of events + std::vector theEvents; + + if(job_id==4 || job_id ==5) years={2017}; //Only one year available for GenLvl + //read the full tuple for each year + std::string treePath; + for(auto yr: years){ + //Set the tree name + treePath = getSelectedTuplePath(job_id,opts.run,yr); + spdlog::debug("Processing " +treePath); + //Load the event vector + std::vector Events = loader.read_full_tuple(yr, treePath, get_inputTree_name(job_id), + job_id>0, job_id>0 && opts.useMC, job_id>=4, -1); + spdlog::debug("Inserting the vector into theEvents..."); + //Add + theEvents.insert(theEvents.end(), Events.begin(), Events.end()); + } + + //Some log messages + spdlog::debug("Event vector lenght: {0:d}",theEvents.size()); + if (theEvents.size()==0){ + spdlog::error("Empty event vector! Abort."); + assert(0); + } + spdlog::info("Completed loading sample: Run {0:d} with years {1:s}", opts.run, convert_vector_to_string(years)); + + //save events to standardised output filepath + fcnc::save_events(theFCNCpath, theEvents); + spdlog::info( "Completed saving sample: Run {0:d}.", opts.run ); + + return 0; +} diff --git a/Code/FCNCFitter/sources/Core/event.hh b/Code/FCNCFitter/sources/Core/event.hh new file mode 100755 index 0000000..9dbf013 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/event.hh @@ -0,0 +1,134 @@ +/** + * @file event.hh + * @author Christoph Langenbruch, Renata Kopecna + * @date 2009-03-18 + * + */ + +#ifndef EVENT_H +#define EVENT_H + +#include +#include + +namespace fcnc { //Forward declaration, fully defined in options.hh + class options; +} + +namespace fcnc { + + // typedef event_type enum {}; +///The event class stores the different event quantities needed to extract the physically interesting parametes in the likelihood fit. +class event { +public: + //save the year into each event + int year; + ///the mass used to separate signal and background + double m; + ///the error on the measured mass + double sigma_m; + //the reconstructed mass of the K*+ + double mkpi; + ///set in the toy data generation to distinguish background from signal in the plots + int event_type; + /// magnet polarity (down = -1 and up = +1) + int magnet; + ///costhetal + double costhetal; + ///costhetak + double costhetak; + ///phi + double phi; + //full angular angles that are saved even after folding + double costhetal_fa; + double costhetak_fa; + double phi_fa; + ///weight + double weight; + double delta_weight; + double max_mu_pt; + double kaon_pt; + ///xis + //double xis[18]; + //float xis[18]; + ///q2 + double q2; + ///from opening angle of leptons: + double pseudo_q2; + ///p2 + double p2; + ///cp_conjugate (B) or not (Bbar) + bool cp_conjugate; + double sweight; + double mjpsipi; + event(): + year(2000), + m(0.0), + sigma_m(0.0), + mkpi(892.0), + event_type(0), + magnet(0), + costhetal(0.0), + costhetak(0.0), + phi(0.0), + costhetal_fa(0.0), + costhetak_fa(0.0), + phi_fa(0.0), + weight(1.0), + delta_weight(0.0), + max_mu_pt(0.0), + kaon_pt(0.0), + //norm(1.0), + q2(0.0), + pseudo_q2(0.0), + cp_conjugate(false), + sweight(1.0) + { + // xis[0] = 3.0/2.0; + // xis[1] = 3.0/4.0; + // xis[2] = -1.0/2.0; + // xis[3] = -1.0/4.0; + // xis[4] = 0.0; + // xis[5] = 0.0; + // xis[6] = 0.0; + // xis[7] = 0.0; + // xis[8] = 0.0; + // xis[9] = 0.0; + // xis[10] = 0.0; + // xis[11] = 0.0; + // xis[12] = 1.0; + // xis[13] = 0.0; + // xis[14] = 0.0; + // xis[15] = 0.0; + // xis[16] = 0.0; + // xis[17] = 0.0; + }; + + //reset folded angles back to full angular + void reset_angles() + { + costhetal = costhetal_fa; + costhetak = costhetak_fa; + phi = phi_fa; + }; + +}; + +///print the quantities of event meas + void print_event(const event& meas); + void save_events(std::string filename, const std::vector& events); + void save_eos_events(std::string filename, const std::vector& events); + std::vector filterResonances(std::vector events); + std::vector load_events(std::string filename, std::string treename="Events", int neventsmax = -1); + + ///convert between different angular conventions + void lhcbtotheory(const bool bzero, const double ctl_lhcb, const double ctk_lhcb, const double phi_lhcb, double& ctl_th, double& ctk_th, double& phi_th); + void theorytolhcb(const bool bzero, const double ctl_th, const double ctk_th, const double phi_th, double& ctl_lhcb, double& ctk_lhcb, double& phi_lhcb); +}; + + +int convert_tuples(int job_id, std::string theFCNCpath, fcnc::options opts, std::vector years); + +std::vector merge_two_evtVecs(std::vector one, std::vector two); + +#endif diff --git a/Code/FCNCFitter/sources/Core/fitter.cc b/Code/FCNCFitter/sources/Core/fitter.cc new file mode 100644 index 0000000..ab7059c --- /dev/null +++ b/Code/FCNCFitter/sources/Core/fitter.cc @@ -0,0 +1,1260 @@ +//Renata Kopecna + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +//Log of the covariance matrix status +void printCovMatrixStatus(int status, bool squared){ + std::string hesse = "Hesse"; + if (squared) hesse = "Squared Hesse"; + if (status==0) spdlog::warn(hesse + " returns 0: Hesse not calculated."); + else if (status==1) spdlog::warn(hesse + " returns 1: Approximation only."); + else if (status==2) spdlog::warn(hesse + " returns 2: Full, forced pos def"); + else if (status==3) spdlog::info(hesse + " returns 3: ALL GOOD"); + else spdlog::warn(hesse + " returns {0:d} -> SOMETHING VERY WRONG", status); + return; +} + +//Migrad status log so one doesn't have to look it up all the time +void printMigradStatus(int status){ + if (status==0) spdlog::info("MIGRAD returns 0: ALL GOOD"); + else if (status==1) spdlog::warn("MIGRAD returns 1: Blank command, ignored."); + else if (status==2) spdlog::warn("MIGRAD returns 2: Command line unreadable, ignored."); + else if (status==3) spdlog::warn("MIGRAD returns 3: Unknown command, ignored"); + else if (status==4) spdlog::warn("MIGRAD returns 4: Abnormal termination, MIGRAD not converged or something."); + else if (status==9) spdlog::warn("MIGRAD returns 9: Reserved."); + else if (status==10) spdlog::warn("MIGRAD returns 10: End command."); + else if (status==11) spdlog::warn("MIGRAD returns 11: Exit/Stop command."); + else if (status==12) spdlog::warn("MIGRAD returns 12: Return command."); + else spdlog::warn("MIGRAD returns {0:d} -> SOMETHING VERY WRONG", status); + return; +} + + +//set plotter +void fcnc::fitter::set_plotters(plotter* plot) { + std::vector p; + p.push_back(plot); + plots = p; + return; +} + +///set plotters +void fcnc::fitter::set_plotters(std::vector plotters) { + plots = plotters; + return; +} +///define common parameters for all pdfs +void fcnc::fitter::set_common_parameters(std::vector common_pars) { + common_params = common_pars; + return; +} +///is the parameter with name one of the common parameters +bool fcnc::fitter::is_common(std::string name) { + for (unsigned int i=0; inparameters(); j++){ + if (name == params.at(i)->get_parameter(j)->get_name()){ + if (i==idx_i && j==idx_j) return true; + else return false; + } + } + } + spdlog::critical("[FATAL]\t\tThe parameter '"+name+"' was not found!"); + assert(0); + return true; +} + +///returns the nth minuit index for parameter with name +int fcnc::fitter::nth_minuit_index(std::string name, unsigned int n) { + assert(n); + assert(n <= params.size()); + unsigned int start_param = 0; + for (unsigned int i = 0; i < params.size(); i++){ + for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){ + if (name == params.at(i)->get_parameter(j)->get_name()){ + if (n == 1) return start_param+j; + else n--; + } + } + start_param += minuit_one_fitter->params.at(i)->nparameters(); + } + return -1; +} + +///returns the first minuit index for parameter with name +int fcnc::fitter::first_minuit_index(std::string name) { + return nth_minuit_index(name, 1); +} + +///returns wether this is an analysis with blinded parameters +bool fcnc::fitter::is_blind() { + for (unsigned int i = 0; i < params.size(); i++){ + for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){ + if (params.at(i)->get_parameter(j)->is_blind()){ + return true; + } + } + } + return false; +} + +//WHAT THE FUCK IS THIS DOING HERE? +int fcnc::fitter::fit(pdf* probs, parameters* parms, std::vector* ev, std::string index){ + std::vector the_probs; + the_probs.push_back(probs); + + std::vector the_params; + the_params.push_back(parms); + + std::vector* > the_events; + the_events.push_back(ev); + + return fit(the_probs, the_params, the_events, index); +} + +void fcnc::fitter::init(pdf* probs, parameters* parms, std::vector* ev, std::string index){ + std::vector the_probs; + the_probs.push_back(probs); + + std::vector the_params; + the_params.push_back(parms); + + std::vector* > the_events; + the_events.push_back(ev); + + return init(the_probs, the_params, the_events, index); +} + +void fcnc::fitter::minuit_one_fcn(Int_t &npar, Double_t *grad, Double_t &lh, Double_t *parameters, Int_t iflag){ + //set the parameter sets according to minuits current parameter values stored in the params pointer + //do not forget to set common parameters correctly. these have no directly corresponding minuit index, use first_index instead + unsigned int start_param = 0; + for (unsigned int i = 0; i < minuit_one_fitter->params.size(); i++){ + for (unsigned int j = 0; j < minuit_one_fitter->params.at(i)->nparameters(); j++){ + unsigned int index = start_param + j; + std::string par_name = minuit_one_fitter->params.at(i)->get_parameter(j)->get_name(); + if (minuit_one_fitter->is_common(par_name)) + minuit_one_fitter->params.at(i)->get_parameter(j)->set_value(parameters[minuit_one_fitter->first_minuit_index(par_name)]); + else + minuit_one_fitter->params.at(i)->get_parameter(j)->set_value(parameters[index]); + } + start_param += minuit_one_fitter->params.at(i)->nparameters(); + } + lh = minuit_one_fitter->likelihood(); + return; +} + +fcnc::fitter::fitter(options* o): + opts(o) +{ + minuit_one = new TMinuit(1000);//params->nparameters()); + minuit_one->SetFCN(&(minuit_one_fcn)); + //this makes minuit use highest precision + int errorcode; + double strategy_list[1];// = {2.0} + strategy_list[0] = opts->minuit_strategy; + minuit_one->mnexcm("SET STR", strategy_list, 1, errorcode); + minuit_one->SetMaxIterations(40000); + //need to set this value to 0.5 if you do not use -2*ln(LH) + minuit_one->SetErrorDef(1.0);//default + spdlog::info("Machine precision: {0:f}", minuit_one->fEpsmac); //8.88178e-16 + //verbose minuit + //minuit_one->SetPrintLevel(o->print_level); + //minuit_one->SetPrintLevel(-1); + empirical_constant = 0.0; +} + +fcnc::fitter::~fitter(){ + delete minuit_one; +} + +void fcnc::fitter::init(std::vector probs, std::vector parms, std::vector< std::vector * > ev, std::string index){ + square_weights = false; + //set all important pointers and initialize + minuit_one_fitter = this; + //this could be different for every fit (feldman-cousins) + int errorcode; + double strategy_list[1];// = {2.0} + strategy_list[0] = opts->minuit_strategy; + minuit_one->mnexcm("SET STR", strategy_list, 1, errorcode); + + //prob = probability; + pdfs = probs; + params = parms; + events = ev; + + reset_param_values(); + //this was originally before the reset... put here to catch reset of swave + for (unsigned int i=0; iinit(params.at(i)); + + //update cached efficiencies in three situations + //1. q2 fixed and regular acceptance + //2. unfolded fit to determine the weight=1/eff + //3. per event norm + //cache fis + if (opts->cache_fis){ + spdlog::info("Caching fis"); + for (unsigned int i = 0; i < pdfs.size(); i++) + pdfs.at(i)->update_cached_integrated_fis(params.at(i)); + } + for (unsigned int i = 0; i < pdfs.size(); i++){ + parameter* effq2 = params.at(i)->get_parameter("eff_q2"); + bool q2fixed = false; + if (effq2) q2fixed = (effq2->get_step_size() == 0.0); + if ((q2fixed && opts->use_angular_acc) || opts->weighted_fit || opts->use_event_norm){ + pdfs.at(i)->update_cached_efficiencies(params.at(i), events.at(i)); + } + } + //per event xis + if (opts->use_event_norm){ + for (unsigned int i = 0; i < pdfs.size(); i++){ + pdfs.at(i)->update_cached_xis(params.at(i), events.at(i)); + } + } + +} + +int fcnc::fitter::fit(std::vector probs, std::vector parms, std::vector< std::vector * > ev, std::string index){ + //can only use either squared hesse or minos + if(opts->minos_errors && opts->squared_hesse){ + spdlog::critical("Cannot use both MINOS and squared HESSE for uncertainty deterimination. Choose one!"); + assert(0); + } + square_weights = false; + //set all important pointers and initialize + minuit_one_fitter = this; + //this could be different for every fit (feldman-cousins) + int errorcode; + double strategy_list[1];// = {2.0} + strategy_list[0] = opts->minuit_strategy; + minuit_one->mnexcm("SET STR", strategy_list, 1, errorcode); + + //prob = probability; + pdfs = probs; + params = parms; + events = ev; + + //make sure to reduce output for blind analysis + if (is_blind()) minuit_one->SetPrintLevel(-1); + else if (spdlog_debug()) minuit_one->SetPrintLevel(0); + else minuit_one->SetPrintLevel(-1); + + reset_param_values(); + //this was originally before the reset... put here to catch reset of swave + for (unsigned int i=0; iinit(params.at(i)); + } + + //update cached efficiencies in three situations + //1. q2 fixed and regular acceptance + //2. unfolded fit to determine the weight=1/eff + //3. per event norm + //cache fis + if (opts->cache_fis){ + spdlog::info("Caching fis"); + for (unsigned int i = 0; i < pdfs.size(); i++){ + pdfs.at(i)->update_cached_integrated_fis(params.at(i)); + } + } + for (unsigned int i = 0; i < pdfs.size(); i++){ + parameter* effq2 = params.at(i)->get_parameter("eff_q2"); + bool q2fixed = false; + if (effq2) q2fixed = (effq2->get_step_size() == 0.0); + if ((q2fixed && opts->use_angular_acc) || opts->weighted_fit || opts->use_event_norm){ + pdfs.at(i)->update_cached_efficiencies(params.at(i), events.at(i)); + } + } + //per event xis + if (opts->use_event_norm){ + for (unsigned int i = 0; i < pdfs.size(); i++){ + pdfs.at(i)->update_cached_xis(params.at(i), events.at(i)); + } + } + + //get empirical factor + empirical_constant = 0.0; + if (opts->shift_lh){ + unsigned int the_size=0; + for (unsigned int i=0; isize(); + empirical_constant = likelihood()/the_size; + } + + spdlog::debug("Determined empirical constant of: {0:f}", empirical_constant); + + int result = 0; + unsigned int varied_params = 0; + //determine the number of varied parameters + //count only parameters that are not common among the PDFs! + for (unsigned int i = 0; i < params.size(); i++){ + for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){ + if (params.at(i)->get_parameter(j)->get_step_size() != 0.0 && !is_common(params.at(i)->get_parameter(j)->get_name())){ + varied_params++; + spdlog::debug("[PDF{0:d}]\tPAR='"+params.at(i)->get_parameter(j)->get_name()+"'\trange=[{1:f} - {2:f}]", i+1, params.at(i)->get_parameter(j)->get_min(), params.at(i)->get_parameter(j)->get_max()); + } + } + } + + spdlog::debug("Count number of varied parameters: {0:d} PDF(s)", params.size()); + spdlog::debug("Number of varied, non-common parameters: {0:d}", varied_params); + //assert(!(varied_params % params.size())); + + //add the parameters to the counter, that are common AND varied + for (unsigned int i = 0; i < common_params.size(); i++){ + bool is_varied = false; + for (unsigned int j = 0; j < params.size(); j++){ + for (unsigned int k = 0; k < params.at(j)->nparameters(); k++){ + if (common_params.at(i) == params.at(j)->get_parameter(k)->get_name() && params.at(j)->get_parameter(k)->get_step_size() != 0.0){ + is_varied = true; + spdlog::debug("[COMMON]\tPAR='"+params.at(j)->get_parameter(k)->get_name()+"'\trange=[{0:f} - {1:f}]", params.at(j)->get_parameter(k)->get_min(), params.at(j)->get_parameter(k)->get_max()); + break; + } + } + if(is_varied)break; + } + if (is_varied){ + varied_params++; + } + } + + spdlog::info("Including common parameters, number of varied parameters is: {0:d}", varied_params); + + //open texFile + std::ofstream myFile; + if (index != ""){ + open_Latex_noteFile(latex_fitterFile(index), myFile); + } + + + //Use Markov Chain Monte Carlo //TODO when bored, move this to a separate function + if (opts->use_mcmc){ + unsigned int nlength = 10000; + //just run a single chain + std::vector chain;//(nlength); + for (unsigned int i=0; inparameters(); j++){ + if (params.at(i)->get_parameter(j)->get_step_size() != 0.0 && !is_common(params.at(i)->get_parameter(j)->get_name())){ + current[idx] = params.at(i)->get_parameter(j)->get_value(); + SNminusone(idx, idx) = params.at(i)->get_parameter(j)->get_step_size();//this is actually quite clever + idx++; + } + } + } + spdlog::debug("nrows {0:d}\tvaried_params {1:d}", current.GetNrows(), varied_params); + for(int i=0; iGaus(0.0, 1.0);//could also use students t distribution + } + //shift depends on SNminusone + TVectorD SW(SNminusone*WN); + current = last + SW; + finished = true; + //this will disallow parameters outside the allowed range + const bool constrain_parameters = true; + if (constrain_parameters){ + idx = 0; + for (unsigned int j = 0; j < params.size(); j++){ + for (unsigned int k = 0; k < params.at(j)->nparameters(); k++){ + if (params.at(j)->get_parameter(k)->get_step_size() != 0.0 && !is_common(params.at(j)->get_parameter(k)->get_name())){ + if (current[idx] > params.at(j)->get_parameter(k)->get_max() || current[idx] < params.at(j)->get_parameter(k)->get_min()){ + finished = false; + } + idx++; + } + } + } + } + } + spdlog::debug("event {0:d}", i); + //convert index back to parameter* and set to current point + idx = 0; + for (unsigned int j = 0; j < params.size(); j++){ + for (unsigned int k = 0; k < params.at(j)->nparameters(); k++){ + if (params.at(j)->get_parameter(k)->get_step_size() != 0.0 && !is_common(params.at(j)->get_parameter(k)->get_name())){ + params.at(j)->get_parameter(k)->set_value(current[idx]); + idx++; + } + } + } + for (unsigned int j=0; jinit(params.at(j)); + } + //compute likelihood of current point + double current_llh = likelihood(); + double r = rnd->Rndm(); + double alpha = std::min(1.0, exp(0.5*(last_llh-current_llh)));//llhs are in fact Sum_i -2*log(P_i) + //debug output + if (spdlog_debug()){ + for (int i=0; inparameters(); k++){ + if (params.at(j)->get_parameter(k)->get_step_size() != 0.0 && !is_common(params.at(j)->get_parameter(k)->get_name())){ + std::ostringstream hname; + hname << "hist" << idx; + histos[idx] = new TH1D(hname.str().c_str(), ";;", nbins, + params.at(j)->get_parameter(k)->get_min(), + params.at(j)->get_parameter(k)->get_max()); + idx++; + } + } + } + //loop over chain and fill histos + for (unsigned int i=0; iFill(v[row]); + } + if (true){//smooth all histos + const unsigned int ntimes = 1; + for (unsigned int i=0; iSmooth(ntimes); + } + if (spdlog_debug()){ //If in debug mode, just save the histos for now + for (unsigned int i=0; iGetName()),"eps"); + } + } + //get maximum from histos (for now no smoothing) and add up highes bins until 1 sigma + //probably want to add from highest bin, no? + TVectorD max(varied_params); + TVectorD eup(varied_params); + TVectorD edown(varied_params); + for (unsigned int i=0; iGetMaximumBin(); + double x = histos[i]->GetBinCenter(maxbin); + double left = histos[i]->GetBinLowEdge(maxbin); + double right = histos[i]->GetBinLowEdge(maxbin+1); + double sum = histos[i]->GetBinContent(maxbin); + histos[i]->SetBinContent(maxbin, 0.0); + bool finished = sum/nlength > ONE_SIGMA; + while (!finished){ + maxbin = histos[i]->GetMaximumBin(); + double nx = histos[i]->GetBinCenter(maxbin); + sum += histos[i]->GetBinContent(maxbin); + histos[i]->SetBinContent(maxbin, 0.0); + if (nx > right) right = histos[i]->GetBinLowEdge(maxbin+1); + if (nx < left) left = histos[i]->GetBinLowEdge(maxbin); + finished = sum/nlength > ONE_SIGMA; + } + max[i] = x; + eup[i] = right-x; + edown[i] = left-x; + delete histos[i]; + } + //output of the newly determined mean and errors + + if (spdlog_info()){ + spdlog::info("max"); + for (int i=0; inparameters(); k++){ + if (params.at(j)->get_parameter(k)->get_step_size() != 0.0 && !is_common(params.at(j)->get_parameter(k)->get_name())){ + params.at(j)->get_parameter(k)->set_value(max[idx]); + params.at(j)->get_parameter(k)->set_error(0.5*(fabs(eup[idx])+fabs(edown[idx]))); + params.at(j)->get_parameter(k)->set_error_up(eup[idx]); + params.at(j)->get_parameter(k)->set_error_down(edown[idx]); + //params.at(j)->get_parameter(k)->set_value(mean[idx]); + //params.at(j)->get_parameter(k)->set_error(sqrt(cov(idx,idx))); + idx++; + } + } + } + //MCMC always returns status OK + return 300;//this means all ok + } + //When using no Markov Chain MC: Nominal fit procedure + else{ //TODO when bored, move this to a separate function + spdlog::debug("Starting Fit Procedure"); + int errorcode; + //double eps[1] = {1.0e-10}; + //minuit_one->mnexcm("SET EPS", eps, 1, errorcode); + //double strategy_list[2] = {0,0.1}; + + double migrad_options[2] = {MIG_MAX_CALLS, MIG_TOLERANCE}; //Maxcalls and tolerance + // The default tolerance is 0.1, and the minimization will stop when the estimated vertical distance to the minimum (EDM) is less than 0.001*[tolerance]*UP(see SET ERR) + if (opts->simplex_prerun){ + spdlog::info("Running Simplex"); + minuit_one->mnexcm("SIM", migrad_options, 2, errorcode); + } + minuit_one->mnexcm("MIG", migrad_options, 2, errorcode); + result = errorcode; + printMigradStatus(result); + spdlog::warn("EDM: {0:f}", minuit_one->fEDM); + if (opts->hesse_postrun){ + spdlog::info("Starting hesse"); + minuit_one->mnhess(); + if (spdlog_debug()) minuit_one->mnmatu(1); //Print the correlation matrix, they are annoying so turned off for now + } + int nfree, ntot, status_cov; + double m_fcn, m_edm, up; + minuit_one->mnstat(m_fcn, m_edm, up, nfree, ntot, status_cov); + //status_cov 0=not calculated, 1=approximation, 2=full but forced pos. def., 3=full accurate + result += 100*status_cov; + if (opts->hesse_postrun){ //Hesse calculates the 2nd derivative of the likelihood profile to assign the correct systematics + printCovMatrixStatus(status_cov,false); + } + double tmp_cov[varied_params * varied_params]; + //spdlog::info("nvaried params = " << varied_params);; + minuit_one->mnemat(tmp_cov, varied_params); + if (opts->weighted_fit && opts->asymptotic){//perform correction according to 1911.01303 Eq. 18 + spdlog::debug("Starting an assymptotic treatment."); + assert(!(opts->squared_hesse));//TODOCL i think hesse_postrun is fine (and will lead to better estimate for the weighted Hessian) + + //weighted hesse matrix is available as tmp_cov + //need to iterate over all events + //need to evaluate first derivatives at central values + //events in different pdfs are independently distributed + //just should count every event separately + TMatrixDSym V(varied_params, tmp_cov);//weighted covariance matrix + TMatrixDSym C(varied_params);//, 0.0);//tmp_cov_sq); + for (unsigned int k=0; k param_names; + std::vector param_values; + std::vector eps(varied_params, 1.0e-5); + for (unsigned int i = 0; i < params.size(); i++){ + for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){ + if (params.at(i)->get_parameter(j)->get_step_size() != 0.0){ + //if the parameter is common, only add name once + if (!is_common(params.at(i)->get_parameter(j)->get_name()) || is_first(params.at(i)->get_parameter(j)->get_name(), i, j)){ + double v,e; + std::string par_name = params.at(i)->get_parameter(j)->get_name(); + unsigned int idx = first_minuit_index(par_name); + minuit_one->GetParameter(idx, v, e); + param_names.push_back(par_name); + param_values.push_back(v); + spdlog::debug(par_name+": {0:f}", v); + } + } + } + } + //the optimized version varies the parameter in the outer loop and performs the update_cached_normalisation only once for + and - + //loop over data samples + + spdlog::debug("Looping over data samples."); + + std::vector lh_extended_nsig(events.size(),0.0); + std::vector lh_extended_nbkg(events.size(),0.0); + std::vector lh_extended_nsigbar(events.size(),0.0); + std::vector lh_extended_nbkgbar(events.size(),0.0); + for (unsigned int i = 0; i > derivs; //first idx varied param, second index event + for (unsigned int k=0; kget_parameter(param_names.at(k)); + if (!varied){ + std::vector derivs_k(events.at(i)->size(),0.0); + derivs.push_back(derivs_k); + continue; + } + //set varied parameter + everywhere + varied->set_value(param_values.at(k)+eps.at(k)); + //cache integrals + pdfs.at(i)->update_cached_normalization(params.at(i)); + if (opts->use_event_norm) pdfs.at(i)->update_cached_normalization(params.at(i), events.at(i)); + + //TODOCL + + spdlog::debug("Getting likelihood."); + likelihood();//this is supposed to only get the extended term, for the + varied parameters, should be fast enough //This doesn't do anything! + //loop over lh_plus events + std::vector loglh_plus_k(events.at(i)->size(),0.0); + for (unsigned int j = 0; j < events.at(i)->size(); j++){ + //for every event do finite differences + const fcnc::event meas = events.at(i)->at(j); + double probability = 0.0; + probability = pdfs.at(i)->prob(params.at(i), meas); + if (probability > 0.0) loglh_plus_k.at(j) = -TMath::Log(probability); + //TODOCL + if (meas.cp_conjugate){ //TODOCL CHECK!! //LEONS COMMENT meas.cp_conjugate corresponds to n_sig !!!!!!! + loglh_plus_k.at(j) += -TMath::Log(lh_extended_nsig.at(i)+lh_extended_nbkg.at(i)); + } + else{ + loglh_plus_k.at(j) += -TMath::Log(lh_extended_nsigbar.at(i)+lh_extended_nbkgbar.at(i)); + } + } + + //set varied parameter - everywhere + varied->set_value(param_values.at(k)-eps.at(k)); + //cache integrals + pdfs.at(i)->update_cached_normalization(params.at(i)); + if (opts->use_event_norm) pdfs.at(i)->update_cached_normalization(params.at(i), events.at(i)); + + //TODOCL + likelihood();//this is supposed to only get the extended term, for the - varied parameters, should be fast enough + + //loop over lh_minus events + std::vector loglh_minus_k(events.at(i)->size(),0.0); +// for (unsigned int j = 0; j < events.at(i)->size(); j++){ +// //for every event do finite differences +// const fcnc::event meas = events.at(i)->at(j); +// double probability = 0.0; +// probability = pdfs.at(i)->prob(params.at(i), meas); +// if (probability > 0.0) loglh_minus_k.at(j) = -TMath::Log(probability); + +// //TODOCL +// if (meas.cp_conjugate){ //TODOCL CHECK!! //LEONS COMMENT meas.cp_conjugate corresponds to n_sig !!!!!!! +// loglh_minus_k.at(j) += -TMath::Log(lh_extended_nsig.at(i)+lh_extended_nbkg.at(i)); +// } +// else{ +// loglh_minus_k.at(j) += -TMath::Log(lh_extended_nsigbar.at(i)+lh_extended_nbkgbar.at(i)); +// } +// } + + //calculate derivatives for all events + spdlog::debug("Calculating derivatives for all events"); + std::vector derivs_k(events.at(i)->size(),0.0); + for (unsigned int j = 0; j < events.at(i)->size(); j++){ + derivs_k.at(j) = (loglh_plus_k.at(j)-loglh_minus_k.at(j))/(2.0*eps.at(k)); + } + spdlog::trace("Derivatives:+ "+convert_vector_to_string(derivs_k)); + derivs.push_back(derivs_k); + + //reset varied parameter everywhere + varied->set_value(param_values.at(k)); + //cache integrals + pdfs.at(i)->update_cached_normalization(params.at(i)); + if (opts->use_event_norm){ + pdfs.at(i)->update_cached_normalization(params.at(i), events.at(i)); + } + + } + + //afterwards determine derivative via finite differences + + spdlog::debug("Calculating derivatives for finite differences"); + //and save matrix of squared first derivatives + for (unsigned int j = 0; j < events.at(i)->size(); j++){ + //for every event do finite differences + const fcnc::event meas = events.at(i)->at(j); + for (unsigned int k=0; kweighted_fit && opts->squared_hesse){ + square_weights = true; + spdlog::info("Starting hesse with squared weights"); + minuit_one->mnhess(); + //check that this went fine + double m_sq_fcn, m_sq_edm, sq_up; + int status_sq_cov; + minuit_one->mnstat(m_sq_fcn, m_sq_edm, sq_up, nfree, ntot, status_sq_cov); + printCovMatrixStatus(status_sq_cov,true); + //change status to invalied if squared weighted fit failed + if (status_cov != status_sq_cov){ + result -= 100*status_cov; + result += 100*((status_cov < status_sq_cov) ? status_cov : status_sq_cov); + } + // minuit_one->mnmatu(1);//this also sets something internal in minuit! getparameter seems to get its error from here! + double tmp_cov_sq[varied_params * varied_params]; + minuit_one->mnemat(tmp_cov_sq, varied_params); + //lets use root classes for the matrix inversion + TMatrixDSym V(varied_params, tmp_cov);//tmp_cov + TMatrixDSym C(varied_params, tmp_cov_sq); + double det=0.0; + C.Invert(&det); + TMatrixD VCV(V,TMatrixD::kMult,TMatrixD(C,TMatrixD::kMult,V)); + TMatrixDSym VCVsym(varied_params); + spdlog::info("printing corrected covariance matrix"); + for (unsigned int i=0; i varied_names; + for (unsigned int i = 0; i < params.size(); i++){ + for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){ + if (params.at(i)->get_parameter(j)->get_step_size() != 0.0){//if the parameter is common, only add name once + if (!is_common(params.at(i)->get_parameter(j)->get_name()) || is_first(params.at(i)->get_parameter(j)->get_name(), i, j)){ + varied_names.push_back(params.at(i)->get_parameter(j)->get_description()); + } + } + } + } + + //printing error matrix + if (spdlog_debug()){ + spdlog::debug("printing error matrix"); + for (unsigned int x = 0; x < varied_params; x++) std::cout << "\tvar" << x << " "; + std::cout << std::endl; + for (unsigned int y = 0; y < varied_params; y++){ + std::cout << "var" << y; + for (unsigned int x = 0; x < varied_params; x++){ + std::cout << " " << std::scientific << std::setw(9) << std::setprecision(2) << tmp_cov[varied_params*y + x]; + } + std::cout << std::endl; + } + } + //calculating correlation matrix from error matrix + double cor[varied_params*varied_params]; + for (unsigned int x = 0; x < varied_params; x++){ + for (unsigned int y = 0; y < varied_params; y++){ + cor[varied_params*y + x] = tmp_cov[varied_params*y + x] + /(sqrt(fabs(tmp_cov[varied_params*x + x]))*sqrt(fabs(tmp_cov[varied_params*y + y]))); + } + } + //printing correlation matrix + + if (index != ""){ + spdlog::info("printing correlation matrix"); + myFile << "Run: " << opts->run << std::endl; + myFile << "\\begin{tabular}{c"; + for (unsigned int x = 0; x < varied_params; x++){ + myFile << "c"; + } + myFile << "} \\hline" << std::endl; + myFile << " "; + for (unsigned int x = 0; x < varied_params; x++){ + myFile << " & $" << varied_names.at(x) << "$"; + } + myFile << "\\\\ \\hline" << std::endl; + + bool upper_half = true; + for (unsigned int y = 0; y < varied_params; y++){ + myFile << std::setw(20) << "$" << varied_names.at(y) << "$"; + for (unsigned int x = 0; x < varied_params; x++){ + if (x >= y || !upper_half){ + if (fabs(cor[varied_params*y + x]) >= 0.005){ + myFile << " & " << std::fixed << std::setw(5) << std::setprecision(2) << cor[varied_params*y + x]; + } + else myFile << " & " << std::setw(5) << "-"; + } + else myFile << " & " << std::setw(5) << " "; + } + myFile << " \\\\ " << std::endl; + } + myFile <<"\\hline \\end{tabular}" << std::endl; + } + + + //saves correlations for all parameters + for (unsigned int i = 0; i < params.size(); i++){ + for (unsigned int j=0; j < params.at(i)->nparameters(); j++){ + if (params.at(i)->get_parameter(j)->get_step_size() != 0.0){ + params.at(i)->get_parameter(j)->correlations.clear(); + unsigned int apary = 0; + for (unsigned int y=0; y < varied_params; y++){ + if (varied_names.at(y) == params.at(i)->get_parameter(j)->get_description()){ + apary = y; + break; + } + } + for (unsigned int x=0; x < varied_params; x++) + params.at(i)->get_parameter(j)->correlations.push_back(cor[varied_params*apary + x]); + } + } + } + + //minos error analysis + if (opts->minos_errors && (result%100) == 0){//migrad is successfull + spdlog::info("Starting Minos error analysis"); + std::vector indices; + for (unsigned int i = 0; i < params.size(); i++){ + for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){ + if (params.at(i)->get_parameter(j)->get_step_size() != 0.0 && params.at(i)->get_parameter(j)->get_minos()){ + std::string par_name = params.at(i)->get_parameter(j)->get_name(); + unsigned int idx = 0; + if(is_common(par_name) || opts->use_individual_param_names) idx = first_minuit_index(par_name); + else idx = nth_minuit_index(par_name, i+1); + indices.push_back(idx); + } + } + } + if (indices.size() > 0){//run minos just for subset of parameters + spdlog::info("MINOS SUBSET"); + int errorcode; + /* + double migrad_options[indices.size()+1]; + migrad_options[0] = 100000000.0; + for (unsigned int i = 0; i < indices.size(); i++) + //migrad_options[i+1] = indices.at(i); + migrad_options[i+1] = indices.at(i)+1; + minuit_one->mnexcm("MINO", migrad_options, indices.size()+1, errorcode); + */ + for (unsigned int i = 0; i < indices.size(); i++){ + double migrad_options[2]; + migrad_options[0] = 100000000.0; + migrad_options[1] = indices.at(i)+1; + minuit_one->mnexcm("MINO", migrad_options, 2, errorcode); + } + } + else minuit_one->mnmnos();//do minos error analysis on all parameters + + //write MINOS errors to parameters + for (unsigned int i = 0; i < params.size(); i++){ + for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){ + double e_up, e_down, parab, gcc; + if (params.at(i)->get_parameter(j)->get_step_size() != 0.0){ + std::string par_name = params.at(i)->get_parameter(j)->get_name(); + unsigned int idx = 0; + if(is_common(par_name) || opts->use_individual_param_names) idx = first_minuit_index(par_name); + else idx = nth_minuit_index(par_name, i+1); + minuit_one->mnerrs(idx, e_up, e_down, parab, gcc); + params.at(i)->get_parameter(j)->set_error_up(e_up); + params.at(i)->get_parameter(j)->set_error_down(e_down); + } + } + } + } + + //finally extract fitted parameters from minuit + for (unsigned int i = 0; i < params.size(); i++){ + for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){ + double v,e; + std::string par_name = params.at(i)->get_parameter(j)->get_name(); + unsigned int idx; + if(is_common(par_name) || opts->use_individual_param_names) idx = first_minuit_index(par_name); + else idx = nth_minuit_index(par_name, i + 1); + + spdlog::trace("[PDF{0:d}]\tPAR{1:d}:\t{2:s}\tTMinuit_idx: {3:d}", i, j, par_name, idx); + + minuit_one->GetParameter(idx, v, e); + params.at(i)->get_parameter(j)->set_value(v); + params.at(i)->get_parameter(j)->set_error(e); + + + if (opts->weighted_fit){ + //this method is approximate for parameters with limited range! + int iidx = minuit_one->fNiofex[idx] - 1; + if (iidx>=0){ + e = sqrt(fabs(tmp_cov[iidx*varied_params+iidx])); + params.at(i)->get_parameter(j)->set_error(e); + } + } + } + } + + if (spdlog_trace()){ + for (unsigned int i = 0; i < params.size(); i++){ + params.at(i)->print_parameters(); + } + } + + if (opts->project){ + for (unsigned int i = 0; iplot_data(pdfs.at(i), params.at(i), events.at(i), index); + } + spdlog::info("Fit procedure finished"); + } + + //Close Latex file + if (index != "") myFile.close(); + + return result; +} + +void fcnc::fitter::define_parameter(int i, const parameter & p){ + if (p.get_unlimited()){ + minuit_one->DefineParameter(i, p.get_mn_name(), p(), p.get_step_size(), 0.0, 0.0); + } + else{ + minuit_one->DefineParameter(i, p.get_mn_name(), p(), p.get_step_size(), p.get_min(), p.get_max()); + } +} + +void fcnc::fitter::reset_param_values(){ + spdlog::debug("Resetting parameter values"); + minuit_one->mncler(); + + unsigned int start_param = 0; + for (unsigned int i = 0; i < params.size(); i++){ + for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){ + if (opts->reset_start){ + params.at(i)->get_parameter(j)->reset_start(); + } + std::string par_name = params.at(i)->get_parameter(j)->get_name(); + if (!is_common(par_name) || is_first(par_name, i, j)){ + define_parameter(start_param+j, *(params.at(i)->get_parameter(j))); + } + } + start_param += params.at(i)->nparameters(); + } +} + +double fcnc::fitter::likelihood(){ + lh_tot = 0.0; + //this is called on every parameter change + //this can never hurt, also needed in case of weighted/unfolded fit + for (unsigned int i = 0; i < pdfs.size(); i++){ + pdfs.at(i)->update_cached_normalization(params.at(i));//should do this, but should buffer f1, update f1 on fit command + if(opts->use_event_norm){ + pdfs.at(i)->update_cached_normalization(params.at(i), events.at(i)); + } + } + + //threading the likelihood determination on multiple CPU cores + if(opts->ncores > 1){ + std::vector threads; + for(unsigned int i = 0; i < opts->ncores; i++){ + std::thread* t = new std::thread(std::bind( &fitter::likelihood_thread, this, i)); + threads.push_back(t); + } + for(unsigned int i = 0; i < opts->ncores; i++) threads[i]->join(); + for(unsigned int i = 0; i < opts->ncores; i++) delete threads[i]; + } + else{ + likelihood_thread(0); + } + + if (spdlog_trace()){ + unsigned int start_param = 0; + for(unsigned int i = 0; i < params.size(); i++){ + for(unsigned int j = 0; j < params.at(i)->nparameters(); j++){ + if(params.at(i)->get_parameter(j)->get_step_size() != 0.0){ + std::string par_name = params.at(i)->get_parameter(j)->get_name(); + if(!is_common(par_name) || is_first(par_name, i, j)){ + if(!params.at(i)->get_parameter(j)->is_blind()) std::cout << par_name << ":" << params.at(i)->get_parameter(j)->get_value() << " "; + else std::cout << par_name << ":" << "XXX" << " "; + } + } + } + start_param += params.at(i)->nparameters(); + } + std::cout << std::endl; + } + + //there is an additional term for parameters which have been measured previously + for (unsigned int i = 0; i < params.size(); i++){ + for (unsigned int j = 0; j < params.at(i)->nparameters(); j++){ + const parameter* param = params.at(i)->get_parameter(j); + if (param->get_gaussian_constraint()){ + if (!is_common(param->get_name()) || is_first(param->get_name(), i, j)){ + double mean = param->get_previous_measurement(); + double x = param->get_value(); + double dup = fabs(param->get_previous_error_high()); + double ddown = fabs(param->get_previous_error_low()); + double sigma = (x>mean ? dup : ddown); + //spdlog::trace("mean {0:f}\tx {1:f}\tdup {2:f}\tddown {3:f}\tsigma {4:f}",mean,x,dup,ddown,sigma); + + if (x>mean+dup) sigma = dup; + else if (xchisquaredstudy){ + double chi2 = 0.0; + for (unsigned int i = 0; i < pdfs.size(); i++) chi2 += pdfs.at(i)->chi2(params.at(i)); + lh_tot += chi2; + } + if (opts->extended_ml){ + double lh_ext = 0.0; + for(unsigned int i = 0; i < params.size(); i++){ + double nobs = 0.0; + parameter* pnsig = params.at(i)->get_parameter("n_sig"); + parameter* pnbkg = params.at(i)->get_parameter("n_bkg"); + assert(pnsig && pnbkg); + double nsig = pnsig->get_value(); + double nbkg = pnbkg->get_value(); + if(opts->weighted_fit){ + for(unsigned int j = 0; jsize(); j++){ + nobs += events.at(i)->at(j).weight; + } + } + else{ + nobs = events.at(i)->size(); + } + double prob = TMath::Poisson(nsig+nbkg, nobs); + if(prob == 0.0) prob = 1e-100; + lh_ext += -2.0*TMath::Log( prob ); + if (std::isinf(lh_ext) || std::isnan(lh_ext)){ + std::cout << "[PDF" << i << "]\t\tlh_ext = " << lh_ext << "\t prob = " << prob << "\t -2log(prob) = " << -2.0*TMath::Log( prob ) << std::endl; + std::cout << "[PDF" << i << "]\t\tnsig = " << nsig << "\t n_bkg = " << nbkg << "\t nobs = " << nobs << std::endl; + assert(0); + } + } + if (std::isinf(lh_ext)){ + spdlog::error("{0:0.16f}", lh_ext); + spdlog::error("lh (w/o lh_ext) = {0:0.16f}", lh_tot); + assert(0); + } + lh_tot += lh_ext; + } + + if (std::isinf(lh_tot || std::isnan(lh_tot))){ + spdlog::error("lh = {0:0.16f}", lh_tot); + assert(0); + } + if (spdlog_trace()) std::cout << "[debug]\t" << std::setprecision(16) << "lh = " << lh_tot << "\r" << std::flush; + return lh_tot; +} + +void fcnc::fitter::likelihood_thread(int thread_id){ + + double probability = 0.0; + event meas; + long double result = 0.0; + + for (unsigned int i = 0; isize()/opts->ncores; + //is too small for last vector! + min = evts_per_thread * thread_id; + max = evts_per_thread * (thread_id+1); + int last_thread = opts->ncores - 1; + if (thread_id == last_thread){//last thread needs to take all posibly remaining events + max = events.at(i)->size(); + } + std::vector vec; + vec.reserve(max - min); + for (unsigned int j = min; j < max; j++){ + meas = events.at(i)->at(j); + probability = pdfs.at(i)->prob(params.at(i), meas); + if (probability < 0.0 || std::isnan(probability) || std::isinf(probability)){ + std::lock_guard lock(fitter_mutex); + spdlog::info("Event probability is {0:d}", probability); + print_event(meas); + params.at(i)->print_parameters(); + assert(0); + } + if (probability == 0.0){ + probability = 1.0;//ignore event + } + if (probability != 0.0){ + if (opts->weighted_fit){ + if (square_weights) vec.push_back(-2.0 * meas.weight * meas.weight * TMath::Log(probability) - empirical_constant);//todo: does the empirical constant pose a problem here? + else vec.push_back(-2.0 * meas.weight * TMath::Log(probability) - empirical_constant); + } + else vec.push_back(-2.0 * TMath::Log(probability) - empirical_constant); + } + else if (!std::isnan(probability)){ + spdlog::error("Event probability is {0:d}", probability); + print_event(meas); + assert(0); + } + else{//is inf? + vec.push_back(8.0);//is inf?//use something like prob max? log(p_min) + } + } + result += add_results::iterator>(vec.begin(), vec.end()); + } + if (opts->ncores > 1){ + std::lock_guard lock(fitter_mutex); + lh_tot += result; + } + else{ + lh_tot += result; + } +} + +//boost::mutex fitter::fitter_mutex; +std::mutex fcnc::fitter::fitter_mutex; + +fcnc::fitter* fcnc::fitter::minuit_one_fitter; diff --git a/Code/FCNCFitter/sources/Core/fitter.hh b/Code/FCNCFitter/sources/Core/fitter.hh new file mode 100644 index 0000000..0ab89c5 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/fitter.hh @@ -0,0 +1,135 @@ +/** + * @file fitter.hh + * @author Christoph Langenbruch, Renata Kopecna + * @date 2010-10-13 + * + */ + +#ifndef FITTER_H +#define FITTER_H + +#include +#include +#include + +#include + +namespace fcnc { + class event; + class parameter; + class parameters; + class pdf; + class plotter; + class options; +class fitter; + +///gives wether a i (absolutely) larger than b +template struct GreaterThan{ + bool operator()(const T a, const T b) const + { return std::abs(a) > std::abs(b); } +}; + +///adds up all probability values in an efficient and numerically optimal manner +template typename iterator::value_type add_results(iterator begin, iterator end){ + typedef typename iterator::value_type T; + if (end == begin) return 0.; + std::make_heap(begin, end, GreaterThan()); + + for (; begin + 1 < end; ) { + T x = *begin; + std::pop_heap(begin, end--, GreaterThan()); + do { + x += *begin; + std::pop_heap(begin, end--, GreaterThan()); + } while (std::abs(*begin) >= std::abs(x) && begin < end); + *end++ = x; + std::push_heap(begin, end, GreaterThan()); + } + return *begin; +} + +///The fitter class implements an unbinned multithreaded maximum likelihood fit +class fitter { +public: + ///global mutex for use of threads + //static boost::mutex fitter_mutex; + static std::mutex fitter_mutex; + ///global fitter object for minuit + static fitter* minuit_one_fitter; + ///empirical constant which is subtracted to improve the numerical stability of the fit + double empirical_constant; + ///the minuit 1 minimizer object + TMinuit* minuit_one; + ///pointer to events to fit + std::vector< std::vector* > events; + ///pointer to parameter sets to fit + std::vector< parameters* > params; + ///common parameters in different parameter sets + std::vector< std::string > common_params; + //plotters + std::vector< plotter* > plots; + ///pointer to the pdf(s) + std::vector pdfs; + ///pointer to the options object + options* opts; + ///if true, this fitter has already been initialized + bool initialized; + ///every thread adds the result of their likelihood calculation to this + long double lh_tot; + ///use square of weights for error correction in weighted fits + bool square_weights; +public: + ///minuit one FCN + static void minuit_one_fcn(Int_t &npar, Double_t *grad, Double_t &lh, Double_t *params, Int_t iflag); + ///constructor + fitter(options* o); + ///destructor + ~fitter(); + /** fit the parameter set to the events using the pdf + * @param probability pointer to pdf to use in the likelihood fit + * @param parameters pointer to parameterset to use in the likelihood fit + * @param events pointer to a vector of events for which to maximise the likelihood + * @param index optional parameter to give the current run of a toystudy **/ + int fit(std::vector probs, std::vector parms, std::vector< std::vector * > ev, std::string index=""); + /** fit the parameter set to the events using the pdf + * @param vector of probability pointers to pdfs to use in the likelihood fit + * @param vector of pointers to parametersets to use in the likelihood fit + * @param vector of pointers to vector of events for which to maximise the likelihood + * @param index optional parameter to give the current run of a toystudy **/ + int fit(pdf* probs, parameters* parms, std::vector* ev, std::string index=""); + //set pdfs, parameters and events to extract likelihoods manually: + void init(std::vector probs, std::vector parms, std::vector< std::vector * > ev, std::string index=""); + void init(pdf* probs, parameters* parms, std::vector* ev, std::string index=""); + ///add a parameter to minuit + void define_parameter(int i, const parameter & p); + ///reset all parameters to the start values + void reset_param_values(); + ///calculates log (prod(p_i)) = sum lh(p_i), calls likelihood_thread for every thread + double likelihood(); + ///calculates the log pdf for a single thread + void likelihood_thread(int thread_id); + //set plotter + void set_plotters(plotter* plot); + ///set plotters + void set_plotters(std::vector plotters); + ///define common parameters for all pdfs + void set_common_parameters(std::vector common_pars); + ///is the parameter with name one of the common parameters + bool is_common(std::string name); + ///is this the first occurence of the parameter? + bool is_first(std::string name, unsigned int idx_i, unsigned int idx_j); + ///returns the nth minuit index for parameter with name + int nth_minuit_index(std::string name, unsigned int n); + ///returns the first minuit index for parameter with name + int first_minuit_index(std::string name); + + ///returns wether this is an analysis with blinded parameters + bool is_blind(); +}; + + +}//end namespace + +//Print migrad status with explanation +void printMigradStatus(int status); +#endif diff --git a/Code/FCNCFitter/sources/Core/folder.cc b/Code/FCNCFitter/sources/Core/folder.cc new file mode 100644 index 0000000..d7fbd5d --- /dev/null +++ b/Code/FCNCFitter/sources/Core/folder.cc @@ -0,0 +1,201 @@ +//Renata Kopecna + +#include +#include +#include +#include + +#include +///fold the set of angles according to the chosen folding scheme +void fcnc::folder::fold(event* e){ + //make sure, that the full angular information was saved before into the correct parameters: + assert(e->costhetal == e->costhetal_fa); + assert(e->costhetak == e->costhetak_fa); + assert(e->phi == e->phi_fa); + + double pi = TMath::Pi(); + switch(this->scheme){ + case -1: + return; + case 0: + if(e->phi < 0)e->phi = e->phi + pi; + break; + case 1: + if(e->phi < 0){ + e->phi = -e->phi; + } + if(e->costhetal < 0){ + e->phi = pi - e->phi; + e->costhetal = -e->costhetal; + } + break; + case 2: + if(e->phi < 0) e->phi = -e->phi; + + if(e->costhetal < 0) e->costhetal = -e->costhetal; + break; + case 3: + if(e->phi > pi/2.) e->phi = pi - e->phi; + if(e->phi < -pi/2.) e->phi = -pi - e->phi; + + if(e->costhetal < 0) e->costhetal = -e->costhetal; + break; + case 4: + if(e->phi > pi/2.) e->phi = pi - e->phi; + if(e->phi < -pi/2.) e->phi = -pi - e->phi; + + if(e->costhetal < 0){ + e->costhetal = -e->costhetal; + e->costhetak = -e->costhetak; + } + + break; + } + return; +} + +///inverse fold the set of angles according to the chosen folding scheme +void fcnc::folder::invers_fold(const event* e, event *u_phi, event *u_ctl, event *u_full){ + + /* + phi /^\ + | : + | (2) : (4) + | : + |---------+-------- + | : + | (1) : (3) + |_________________> + cos(theta) + + (1): original event (e) + (2): unfolded in phi (u_phi) + (3): unfolded in ctl (u_ctl) + (4): twice unfolded (u_full) + + */ + *u_phi = *e; //only inversly folded in dependence of phi + *u_ctl = *e; //only inversly folded in dependence of ctl + *u_full = *e; //full inversly folded + + double pi = TMath::Pi(); + switch(this->scheme){ + case -1: + return; + case 0: + assert(e->phi > 0.0); + + u_phi->phi = u_phi->phi - pi; + u_full->phi = u_full->phi - pi; + + break; + case 1: + assert(e->phi > 0.0); + assert(e->costhetal > 0.0); + + u_ctl->phi = pi - u_ctl->phi; + u_full->phi = pi - u_full->phi; + u_ctl->costhetal = -u_ctl->costhetal; + u_full->costhetal = -u_full->costhetal; + + u_phi->phi = -u_phi->phi; + u_full->phi = -u_full->phi; + + break; + case 2: + assert(e->phi > 0.0); + assert(e->costhetal > 0.0); + + u_phi->phi = -u_phi->phi; + u_full->phi = -u_full->phi; + + u_ctl->costhetal = -u_ctl->costhetal; + u_full->costhetal = -u_full->costhetal; + + break; + case 3: + assert(e->phi < pi/2.); + assert(e->phi > -pi/2.); + assert(e->costhetal > 0.0); + + if(e->phi > 0.0){ + u_phi->phi = pi - u_phi->phi; + u_full->phi = pi - u_full->phi; + } + else{ + u_phi->phi = -pi - u_phi->phi; + u_full->phi = -pi - u_full->phi; + } + + u_ctl->costhetal = -u_ctl->costhetal; + u_full->costhetal = -u_full->costhetal; + + break; + case 4: + assert(e->phi < pi/2.); + assert(e->phi > -pi/2.); + assert(e->costhetal > 0.0); + + if(e->phi > 0.0){ + u_phi->phi = pi - u_phi->phi; + u_full->phi = pi - u_full->phi; + } + else{ + u_phi->phi = -pi - u_phi->phi; + u_full->phi = -pi - u_full->phi; + } + + u_ctl->costhetal = -u_ctl->costhetal; + u_ctl->costhetak = -u_ctl->costhetak; + u_full->costhetal = -u_full->costhetal; + u_full->costhetak = -u_full->costhetak; + + break; + } +} + +void fcnc::folder::test_inv_folding(){ + + fcnc::event e; + e.m = 5286.0; + TRandom3 * r = new TRandom3(0); + for(int i = 0; i < 10000; i++){ + + if(i % 100 == 0 && spdlog_info())std::cout << i / 100. << "%" << std::endl; + + //generate a folded event: + e.costhetal = r->Rndm() * 2. - 1.; + e.costhetak = r->Rndm() * 2. - 1.; + e.phi = (r->Rndm() * 2. - 1.) * TMath::Pi(); + e.costhetal_fa = e.costhetal; + e.costhetak_fa = e.costhetak; + e.phi_fa = e.phi; + + this->fold(&e); + + //get 3 events for (partial-)inverse folding: + fcnc::event inv_e[3]; + + this->invers_fold(&e, &inv_e[0], &inv_e[1], &inv_e[2]); + + for(int j = 0; j < 3; j++){ + inv_e[j].costhetal_fa = inv_e[j].costhetal; + inv_e[j].costhetak_fa = inv_e[j].costhetak; + inv_e[j].phi_fa = inv_e[j].phi; + this->fold(&inv_e[j]); + + assert(abs(e.phi - inv_e[j].phi ) < 1e-7); + assert(abs(e.costhetal - inv_e[j].costhetal) < 1e-7); + assert(abs(e.costhetak - inv_e[j].costhetak) < 1e-7); + } + } + spdlog::info("[DONE]\t\tInverse folding #{0:d} works!", this->scheme); +} + +int fcnc::folder::get_scheme(){ + return this->scheme; +} + +void fcnc::folder::set_scheme(int s){ + this->scheme = s; +} diff --git a/Code/FCNCFitter/sources/Core/folder.hh b/Code/FCNCFitter/sources/Core/folder.hh new file mode 100644 index 0000000..0ef80b1 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/folder.hh @@ -0,0 +1,66 @@ +/** + * @file folder.hh + * @author David Gerick, Renata Kopecna + * @date 2018-04-24 + * + */ + +#ifndef FOLDER_H +#define FOLDER_H + +#include +#include + +namespace fcnc { + class event; + +///An abstract base class to fold angles accordingly +class folder { +public: + int scheme; + ///constructor + folder(options *o): + scheme(o->folding) + { + + if(!o->full_angular){ + assert(scheme >= 0); + assert(scheme <= 4); + } + o->update_angle_ranges(); + }; + + ///fold the set of angles according to the chosen folding scheme + void fold(event* e); + + ///inverse fold the set of angles according to the chosen folding scheme + void invers_fold(const event* e, event *u_phi, event *u_ctl, event *u_full); + + /* + phi /^\ + | : + | (2) : (4) + | : + |---------+-------- + | : + | (1) : (3) + |_________________> + cos(theta) + + (1): original event (e) + (2): unfolded in phi (u_phi) + (3): unfolded in ctl (u_ctl) + (4): twice unfolded (u_full) + + */ + + void test_inv_folding(); + + int get_scheme(); + void set_scheme(int s); + +}; +} + +#endif + diff --git a/Code/FCNCFitter/sources/Core/funcs.cc b/Code/FCNCFitter/sources/Core/funcs.cc new file mode 100755 index 0000000..a314cfb --- /dev/null +++ b/Code/FCNCFitter/sources/Core/funcs.cc @@ -0,0 +1,2561 @@ +//Renata Kopecna + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +namespace fcnc +{ + + +TMatrixD get_bsz_mu_invcov(){ //Used one in toystudy.hh + TMatrixDSym bsz_cov(21); + bsz_cov = get_bsz_cov(); + + //need to do cholesky decomposition, use root functionality for this + //TMatrixDSym mcoeffs_sym(21, &coeffs_sym[0]); + TDecompChol chol(bsz_cov); + bool success = chol.Decompose(); + assert(success); + TMatrixD mU = chol.GetU();//gets upper triangular matrix + + if (spdlog_debug()){ + for (unsigned int i =0; i<21; i++){//column + std::cout << i << std::endl; + for (unsigned int j =0; j<21; j++){//row + std::cout << mU(j,i) << " "; + } + std::cout << std::endl; + } + } + + return mU; +} + +TMatrixDSym get_bsz_invcov() +{ + TMatrixDSym covariance_sym = TMatrixDSym(21); + covariance_sym = get_bsz_cov(); + bool success = false; + TDecompBK decompbk(covariance_sym); + TMatrixDSym bsz_invcov = TMatrixDSym(decompbk.Invert(success)); + assert(success); + return bsz_invcov; +} + +TMatrixDSym get_bsz_cov() +{ + + //current covariance matrix + double covariance_raw[21*21] = {0.000837635, 0.00471065, 0.00272131, 0.00471065, 0.0659712, 0.204148, 0.00272131, 0.204148, 2.67119, 4.69403e-5, 0.000919267, 0.00714105, 0.0020347, 0.022787, 0.0846849, 0.0222044, 0.228333, 1.10882, 0.000602086, 0.00227154, 0.000674336, 0.00331857, 0.0250234, 0.079078, 0.00187104, 0.0687236, 0.713438, 3.79001e-5, 0.00134723, 0.00865921, 0.00239851, 0.0371657, 0.029583, 0.0296877, 0.312199, 0.0215381, 1.31212e-5, 0.000248351, -0.00751951, 0.00170386, 0.0218497, -0.0768858, 0.021364, 0.208973, -0.336619, 1.73162e-5, 0.000722872, 0.00072477, 0.00172356, 0.0211513, 0.0374082, 0.0213424, 0.190446, 0.359855, 0.000826815, 0.000674452, -0.022157, 0.00932974, 0.0304414, -0.109803, 0.0686369, 0.154917, -1.14562, 4.69403e-5, 0.0020347, 0.0222044, 0.000919267, 0.022787, 0.228333, 0.00714105, 0.0846849, 1.10882, 0.000694641, 0.00347885, 0.00415084, 0.00347885, 0.0353042, 0.144041, 0.00415084, 0.144041, 1.05126, 3.04401e-5, 3.57306e-5, 0.00355147, 0.000650453, 0.00688257, 0.0593046, 0.00522776, 0.0417512, 0.36039, 0.000809924, 0.00503414, -0.0144592, 0.00424412, 0.0423395, -0.0182202, 0.00664211, 0.138549, 0.397771, 0.000652147, 0.00340264, -0.0202476, 0.00325978, 0.0270724, -0.114933, 0.00381811, 0.0778571, -0.214537, 0.00065194, 0.00303435, -0.00428123, 0.00327701, 0.028583, 0.0341862, 0.00394892, 0.10177, 0.331577, 0.000942311, 0.00179228, -0.0210447, 0.0082808, 0.0190827, -0.18232, 0.0359498, 0.0574551, -0.914838, 0.000602086, 0.00331857, 0.00187104, 0.00227154, 0.0250234, 0.0687236, 0.000674336, 0.079078, 0.713438, 3.04401e-5, 0.000650453, 0.00522776, 3.57306e-5, 0.00688257, 0.0417512, 0.00355147, 0.0593046, 0.36039, 0.000432775, 0.00165482, 0.000605487, 0.00165482, 0.0165823, 0.059165, 0.000605487, 0.059165, 0.430695, 2.32114e-5, 0.000937822, 0.00645455, -6.04184e-5, 0.0117957, 0.0462642, 0.0042958, 0.0833038, 0.140056, 6.01978e-6, 0.000154238, -0.0052701, -8.61667e-5, 0.00572307, -0.0128712, 0.00312849, 0.0501177, -0.083906, 9.00023e-6, 0.000503353, 0.000573722, -7.58925e-5, 0.00611674, 0.0257193, 0.00313087, 0.0460709, 0.133667, 0.000590954, 0.000464079, -0.0159601, 0.00315256, 0.0153668, -0.0107164, 0.0167505, 0.083256, -0.0400335, 3.79001e-5, 0.00239851, 0.0296877, 0.00134723, 0.0371657, 0.312199, 0.00865921, 0.029583, 0.0215381, 0.000809924, 0.00424412, 0.00664211, 0.00503414, 0.0423395, 0.138549, -0.0144592, -0.0182202, 0.397771, 2.32114e-5, -6.04184e-5, 0.0042958, 0.000937822, 0.0117957, 0.0833038, 0.00645455, 0.0462642, 0.140056, 0.00110852, 0.00658825, -0.0202371, 0.00658825, 0.0682608, 0.0138459, -0.0202371, 0.0138459, 2.34402, 0.000825342, 0.004522, -0.0218767, 0.00509604, 0.0448809, -0.101388, -0.0149136, -0.0227422, 0.849315, 0.000823664, 0.00388965, -0.00393922, 0.00509672, 0.0397888, 0.0548511, -0.0148331, -0.0137692, 0.473698, 0.00120989, 0.00205499, -0.0264334, 0.0116269, 0.0278953, -0.204925, 0.00157102, 2.28401e-5, 0.19199, 1.31212e-5, 0.00170386, 0.021364, 0.000248351, 0.0218497, 0.208973, -0.00751951, -0.0768858, -0.336619, 0.000652147, 0.00325978, 0.00381811, 0.00340264, 0.0270724, 0.0778571, -0.0202476, -0.114933, -0.214537, 6.01978e-6, -8.61667e-5, 0.00312849, 0.000154238, 0.00572307, 0.0501177, -0.0052701, -0.0128712, -0.083906, 0.000825342, 0.00509604, -0.0149136, 0.004522, 0.0448809, -0.0227422, -0.0218767, -0.101388, 0.849315, 0.000756032, 0.00372113, -0.0213639, 0.00372113, 0.0359388, 0.00028928, -0.0213639, 0.00028928, 2.68844, 0.000756032, 0.00313686, -0.00507995, 0.0036848, 0.0277685, 0.0556352, -0.0217047, -0.0652209, 0.825691, 0.00089759, 0.00144256, -0.0188003, 0.0072161, 0.0179819, -0.0877721, -0.0281293, -0.0385387, 1.61537, 1.73162e-5, 0.00172356, 0.0213424, 0.000722872, 0.0211513, 0.190446, 0.00072477, 0.0374082, 0.359855, 0.00065194, 0.00327701, 0.00394892, 0.00303435, 0.028583, 0.10177, -0.00428123, 0.0341862, 0.331577, 9.00023e-6, -7.58925e-5, 0.00313087, 0.000503353, 0.00611674, 0.0460709, 0.000573722, 0.0257193, 0.133667, 0.000823664, 0.00509672, -0.0148331, 0.00388965, 0.0397888, -0.0137692, -0.00393922, 0.0548511, 0.473698, 0.000756032, 0.0036848, -0.0217047, 0.00313686, 0.0277685, -0.0652209, -0.00507995, 0.0556352, 0.825691, 0.000756032, 0.00316639, -0.00503577, 0.00316639, 0.0276287, 0.0511444, -0.00503577, 0.0511444, 0.646067, 0.000900667, 0.00145139, -0.0189859, 0.00693449, 0.0173072, -0.119675, 0.00493465, 0.0386434, 0.478871, 0.000826815, 0.00932974, 0.0686369, 0.000674452, 0.0304414, 0.154917, -0.022157, -0.109803, -1.14562, 0.000942311, 0.0082808, 0.0359498, 0.00179228, 0.0190827, 0.0574551, -0.0210447, -0.18232, -0.914838, 0.000590954, 0.00315256, 0.0167505, 0.000464079, 0.0153668, 0.083256, -0.0159601, -0.0107164, -0.0400335, 0.00120989, 0.0116269, 0.00157102, 0.00205499, 0.0278953, 2.28401e-5, -0.0264334, -0.204925, 0.19199, 0.00089759, 0.0072161, -0.0281293, 0.00144256, 0.0179819, -0.0385387, -0.0188003, -0.0877721, 1.61537, 0.000900667, 0.00693449, 0.00493465, 0.00145139, 0.0173072, 0.0386434, -0.0189859, -0.119675, 0.478871, 0.0040111, 0.00460369, -0.0993374, 0.00460369, 0.0493411, 0.140689, -0.0993374, 0.140689, 4.85487 }; + + //spdlog::info("chi2 start"std::endl; + + double covariance_reordered[21*21]; + //double covariance_reordered_old[21*21]; + //want to reorder covariances into proper matrix A0a0 A0a1 A0a2 A1a0 A1a1 A1a2 A12a0 and so on + for (unsigned int i =0; i<21; i++)//column + for (unsigned int j =0; j<21; j++)//row + { + int to = 21*j+i; + int parcol = (to%21); + int parrow = to / 21; + int ffcol = parcol/3; + int ffrow = parrow/3; + int alphacol = parcol%3; + int alpharow = parrow%3; + int from = 9*(7*ffrow+ffcol) + 3*alpharow + alphacol; + covariance_reordered[to] = covariance_raw[from]; + //covariance_reordered_old[to] = covariance_old[from]; + } + + //for (unsigned int i=0; i<21; i++) + // spdlog::info("COVCOMP new ",sqrt(covariance_reordered[i*21+i])" old ",sqrt(covariance_reordered_old[i*21+i]) << ); + //now need to remove 100% correlated obs + //a12_0 = (mB^2-mK*^2)/(8mBmK*)A3(0) = (mB^2-mK*^2)/(8mBmK*)A0(0) B6 in BSZ paper + //t2_0 = t1_0 + double covariance_final[21*21]; + for (unsigned int i =0; i<21; i++)//column + for (unsigned int j =0; j<21; j++)//row + { + covariance_final[j*21+i] = covariance_reordered[j*21+i]; + if ((i==6 || j==6) || (i==15 || j==15)) + covariance_final[j*21+i] = 0.0; + if ((i==6 && j==6) || (i==15 && j==15)) + covariance_final[j*21+i] = 0.1; + } + //test output + //for (unsigned int i =0; i<21; i++)//column + // { + // std::cout << i << std::endl; + // for (unsigned int j =0; j<21; j++)//row + // std::cout << covariance_final[21*j+i] << " "; + // std::cout << std::endl << std::endl; + // }//seems to be ok + // spdlog::info("BSZ correlations",std::endl << " "; + // for (unsigned int i =0; i<21; i++) + // std::cout << std::fixed << std::setw(5) << i << " "; + // std::cout << std::endl; + // for (unsigned int i =0; i<21; i++)//column + // { + // std::cout << i << (i<10 ? " " : " "); + // for (unsigned int j =0; j<21; j++)//row + // std::cout << std::fixed << std::setprecision(2) << std::setw(5) << covariance_final[21*j+i]/sqrt(covariance_final[21*i+i]*covariance_final[21*j+j]) << " "; + // std::cout << std::endl; + // }//seems to be ok + + + //we should be able to invert this now + TMatrixDSym covariance_sym(21, &covariance_final[0]); + return covariance_sym; +} + +double crystalball(double m, double mean, double sigma, double alpha, double n){ + + //implementation taken from RooFit: https://root.cern.ch/doc/master/RooCBShape_8cxx_source.html#l00056 + + double t = (m-mean)/sigma; + if (alpha < 0) t = -t; + + double absAlpha = fabs(alpha); + + if (t >= -absAlpha) { + return exp(-0.5*t*t); + } + else { + double a = TMath::Power(n/absAlpha,n)*exp(-0.5*absAlpha*absAlpha); + double b= n/absAlpha - absAlpha; + return a/TMath::Power(b - t, n); + } +} + +double twotailedcrystalball(double m, double mean, double sigma, double alpha1, double alpha2, double n1, double n2){ + + double result = 0.0; + if (alpha1 < 0.0 || alpha2 < 0.0 || isnan(alpha1) || isnan(alpha2)){ + spdlog::critical("sigma {0:f}\talpha1 {1:f}\talpha2 {2:f}\tn1 {3:f}\tn2 {4:f}",sigma,alpha1,alpha2,n1,n2); + assert(0); + } + + //implementation taken from RooFit: RooDoubleCB.cxx + double t = (m-mean)/sigma; + if(t>-alpha1 && t=alpha2){ + double alpha2invn2 = alpha2/n2; + result = TMath::Exp(-0.5*alpha2*alpha2)*TMath::Power(1. - alpha2invn2*(alpha2-t), -n2); + } + else{ + spdlog::critical("Cannot sort t={0:f} in range with alphas: alpha1={1:f}, alpha2={2:f}", + t, alpha1, alpha2); + assert(0); + } + + if(std::isnan(result) || std::isinf(result)){ + spdlog::critical("Calculation of twotailed CB failed: {0:f}", result); + spdlog::critical("m(B): {0:f}\tmean: {1:f}\tsigma: {2:f}\talpha1: {3:f}\talpha2: {4:f}\tn1: {5:f}\tn2: {6:f}",m, mean, sigma, alpha1, alpha2, n1, n2); + assert(0); + } + + return result; +} + +double sqr(double x) +{ + return x*x; +} + +//basic trigonometric functions +double costheta2(double costheta){ + return costheta*costheta; //cos^2(x) +} +double cos2theta(double costheta){ + return 2.0*costheta2(costheta) - 1.0; //cos(2x) = 2cos^2(x)-1 +} +double sintheta2(double costheta){ + return 1.0-costheta2(costheta); //sin^2 = 1-cos^2 +} +double sintheta_abs(double costheta){ //TODO: check if this is fine as sin(x) != |sin(x)| + return sqrt(sintheta2(costheta)); +} +double sin2theta(double costheta){ //TODO: check if this is fine as sin(x) != |sin(x)| + return 2.0 * sintheta_abs(costheta) * costheta; +} + + +//calculates all chebyshev polynomials up to including degree n +void chebyshev(double x, int n, std::vector& results) +{ + assert(n >= 0); + results.clear(); + results.reserve(n+1); + results.push_back(1.0); + results.push_back(x); + for (int i=2; i& chebychev, std::vector& poly) +{ + poly.clear(); + poly.resize(chebychev.size(), 0.0); + if (chebychev.size() > 0) poly.at(0) = chebychev.at(0); + if (chebychev.size() > 1) poly.at(1) = chebychev.at(1); + for (unsigned int n =2; n& poly, std::vector& correct, double min, double max){ + correct.clear(); + + double c = 2.0/(max-min); //What idiot names stuff like c, d and e without explanations + double d = -2.0*min/(max-min)-1.0; + double e = d/c; //e = -min ?! + + unsigned int order = poly.size(); + correct.resize(order, 0.0); + for (unsigned int i = 0; i= 0); + if (n == 0) return 1; + else if (n == 1) return x; + else return ((2.0*n-1.0)*x*legendre(x, n-1) - (n-1.0)*legendre(x, n-2))/double(n); +} + +//calculates all legendre polynomials up to including degree n +void legendre(double x, int n, std::vector& results){ + //optimized + assert(n > 0); + //results = std::vector(n+1,1.0); + results.resize(n+1); + results[0] = 1.0; + results[1] = x; + for (int i=2; i& results){ + legendre(x, n, results); + for (unsigned int i=0; i& legendre, std::vector& poly){ + poly.clear(); + poly.resize(legendre.size(), 0.0); + if (legendre.size() > 0){//constant + poly.at(0) = legendre.at(0); + } + if (legendre.size() > 1){//linear + poly.at(1) = legendre.at(1); + } + for (unsigned int i=2; i quadratic + //i = 2 and 2 only + //k=0 + //k=1 + //as it should be + //poly(2) += + //poly(0) += + { + for (unsigned int k=0; k<=i/2; k++) + poly.at(i-2*k) += legendre.at(i) + * pow(-1.0, k)/pow(2.0, i)*TMath::Binomial(i, k)*TMath::Binomial(2*i-2*k, i); + } + +} + +//calculates chebyshev polynomial of order n +double chebyshev(double x, int n){ + assert(n >= 0); + if (n == 0) return 1; + else if (n == 1) return x; + else return 2.0*x*chebyshev(x, n-1) - chebyshev(x, n-2); +} + + +double legendre_poly(unsigned int l, double x){ + return ROOT::Math::legendre(l, x); +} + +double assoc_legendre(unsigned int l, unsigned int m, double x){ + return ROOT::Math::assoc_legendre(l, m, x); +} + +double spherical_harmonic_re(unsigned int l, unsigned int m, double cos_theta, double phi){ + return sqrt((2*l+1.0)/(4.0*TMath::Pi()))*sqrt(TMath::Factorial(l-m)/TMath::Factorial(l+m)) + *assoc_legendre(l, m, cos_theta) + *cos(m*phi); +} + +double spherical_harmonic_im(unsigned int l, unsigned int m, double cos_theta, double phi){ + return sqrt((2*l+1.0)/(4.0*TMath::Pi()))*sqrt(TMath::Factorial(l-m)/double(TMath::Factorial(l+m))) + *assoc_legendre(l, m, cos_theta) + *sin(m*phi); +} + +void calculate_transversity_angles(const LorentzVector& mu_minus, + const LorentzVector& mu_plus, + const LorentzVector& k_minus, + const LorentzVector& k_plus, + double & cos_theta, double & angle_phi, double & cos_psi){ + //LorentzVector bs = mu_plus + mu_minus + k_plus + k_minus; + LorentzVector jpsi = mu_plus + mu_minus; + LorentzVector phi = k_plus + k_minus; + LorentzBoost jpsiboost(jpsi.BoostToCM());//boosttocm actually gives beta vector + LorentzBoost phiboost(phi.BoostToCM());//pxyzm has boost to cm pxyzm not? + //boosted quantities in jpsi system + //LorentzVector mu_minus_d = jpsiboost(mu_minus); + LorentzVector mu_plus_d = jpsiboost(mu_plus); + LorentzVector k_minus_d = jpsiboost(k_minus); + LorentzVector k_plus_d = jpsiboost(k_plus); + LorentzVector phi_d = jpsiboost(phi); + //boosted quantities in phi system + LorentzVector k_plus_dd = phiboost(k_plus); + LorentzVector jpsi_dd = phiboost(jpsi); + + //cos theta is calculated in the cms of the jpsi + //cos theta + Vector3 normalxy = k_minus_d.Vect().Cross(k_plus_d.Vect()); + normalxy = normalxy.Unit();//normals should be normalized + cos_theta = (normalxy.Dot(mu_plus_d.Vect()) + / sqrt(normalxy.Mag2()) + / sqrt(mu_plus_d.Vect().Mag2())); + //phi is calculated in the cms of the jpsi + //cos phi + Vector3 mu_perp = normalxy * mu_plus_d.Vect().Dot(normalxy); + Vector3 mu_parallel = mu_plus_d.Vect() - mu_perp; + angle_phi = acos(mu_parallel.Dot(phi_d.Vect()) + / sqrt(mu_parallel.Mag2()) + / sqrt(phi_d.Vect().Mag2())); + //now get orientation + Vector3 checknormal = phi_d.Vect().Cross(mu_parallel); + bool samedirection = (checknormal.Dot(normalxy) > 0.0); + if (!samedirection) + angle_phi = -angle_phi; + + //cos psi is calculated in the cms of the phi + //cos psi + cos_psi = k_plus_dd.Vect().Dot(-jpsi_dd.Vect()) + /sqrt(k_plus_dd.Vect().Mag2()) + /sqrt(jpsi_dd.Vect().Mag2()); + +} + +//this is not normalized! +double convoluted_exp(double ct, double sigma_ct, double ctau){ + //use error function instead of numeric integration, should be a lot faster + if (ct > -6.0*sigma_ct)//this safety is important for the plotting + { + const double sqrt2 = TMath::Sqrt(2.0); + // const double norm_factor = 2.0/TMath::Sqrt(TMath::Pi()); + // Erf(x) = (2/sqrt(pi)) Integral(exp(-t^2))dt between 0 and x, already taken into account? + double exp_part = exp(-ct/ctau + sigma_ct*sigma_ct/(2.0*ctau*ctau)); + double erfc = TMath::Erfc(sigma_ct/ctau/sqrt2 - ct/sigma_ct/sqrt2); + // / norm_factor; the normalization here is already done? + //the expression below was normalized, but it shouldnt have been + //double prob = 0.5/ctau * exp * erfc;//is the factor 2 correct? yes. + double prob = 0.5 * exp_part * erfc;//is the factor 2 correct? yes. + if (std::isnan(prob) || prob <= 0.0) + { + spdlog::warn("CONVEXP gives prob: {0:f}; ct/sigma_ct/ctau/exp/erfc/exparg/erfarg: {1:f} {2:f}", + prob, ct,sigma_ct ); + spdlog::warn("ctau/exp{0:f} {1:f}",ctau,exp_part); + spdlog::warn("erfc/exparg/erfarg {0:f} {1:f} {2:f}",erfc, + -ct/ctau + sigma_ct*sigma_ct/(2.0*ctau*ctau), + sigma_ct/ctau/sqrt2 - ct/sigma_ct/sqrt2 ); + prob = 0.0; + } + return prob; + } + else return 0.0;//safety added +} + + +//may be needed later... +double expdecay(double t, double tau, bool normalized){ + if (t >= 0.0) { + if (normalized) return 1.0/tau*exp(-t/tau); + else return exp(-t/tau); + } + else{ + return 0.0; + } +} + +double gauss(double x, double sigma, double mean){ + //what do we have libraries for... + //this one is normalised + return TMath::Gaus(x, mean, sigma, kTRUE); +} + +double normed_gauss(double x, double sigma, double mean, double min, double max){ + //corrected error + double norm = 1.0/2.0 + *(TMath::Erf((max-mean)/(TMath::Sqrt(2.0)*sigma)) + -TMath::Erf((min-mean)/(TMath::Sqrt(2.0)*sigma))); + return 1.0/(TMath::Sqrt(2.0*TMath::Pi())*sigma)*exp(-(mean-x)*(mean-x)/(2*sigma*sigma))/norm; +} + +double linear(double x, double min, double max, double slope){ + //have corrected the slope (parameter needs to be big enough for minuit -> divide by width = 500^2) + double width = max - min; + double ymin = 1.0/width - 0.5*slope/(width*width)*width;//corrected the 0.5 factor + return ymin + slope/(width*width) * (x - min); +} + + +//computes erfc, because erfc(x)=exp(-x^2)*w(i*x) +std::complex cErrF(const std::complex& x){ + const std::complex i(0.0,1.0); + std::complex z(i*x); + //std::complex z(-x.imag(), x.real()); + std::complex result = exp(-x*x)*wErrF(z); + return result; +} + +//computes erfc, because erfc(x)=exp(-x^2)*w(i*x) +std::complex cErrF_2(const std::complex& x){ + const std::complex i(0.0,1.0); + std::complex z(i*x); + std::complex result = exp(-x*x)*Faddeeva_2(z); + + if (x.real() > 20.0) result = 0.0; + if (x.real() < -20.0) result = 2.0; + + return result; +} + +std::complex ErrF_2(const std::complex& x){ + return 1.0 - cErrF_2(x); +} + +//computes erfc, because erfc(x)=exp(-x^2)*w(i*x) +std::complex cErrF_3(const std::complex& x){ + const std::complex i(0.0,1.0); + std::complex z(i*x); + std::complex result = exp(-x*x)*nwwerf(z); + return result; + //careful! the fortran version is apparently not thread safe //TODO +} + +//from matpack +//precision 1e-14 +std::complex Faddeeva_2 (const std::complex& z) +{ + // table 1: coefficients for h = 0.5 + static double n1[12] = + { 0.25, 1.0, 2.25, 4.0, 6.25, 9.0, 12.25, 16.0, + 20.25, 25.0, 30.25, 36.0 }; + static double e1[12] = + { 0.7788007830714049, 0.3678794411714423, + 1.053992245618643e-1, 1.831563888873418e-2, + 1.930454136227709e-3, 1.234098040866795e-4, + 4.785117392129009e-6, 1.125351747192591e-7, + 1.605228055185612e-9, 1.388794386496402e-11, + 7.287724095819692e-14, 2.319522830243569e-16 }; + + // table 2: coefficients for h = 0.53 + static double n2[12] = + { 0.2809, 1.1236, 2.5281, 4.4944, 7.0225, 10.1124, + 13.7641, 17.9776, 22.7529, 28.09, 33.9889, 40.4496 }; + static double e2[12] = + { 0.7551038420890235, 0.3251072991205958, + 7.981051630007964e-2, 1.117138143353082e-2, + 0.891593719995219e-3, 4.057331392320188e-5, + 1.052755021528803e-6, 1.557498087816203e-8, + 1.313835773243312e-10, 6.319285885175346e-13, + 1.733038792213266e-15, 2.709954036083074e-18 }; + + // tables for Pade approximation + static double C[7] = + { 65536.0, -2885792.0, 69973904.0, -791494704.0, + 8962513560.0, -32794651890.0, 175685635125.0 }; + static double D[7] = + { 192192.0, 8648640.0, 183783600.0, 2329725600.0, + 18332414100.0, 84329104860.0, 175685635125.0 }; + + double *n,*e,t,u,r,s,d,f,g,h; + std::complex c,d2,v,w,zz; + int i; + + // use Pade approximation + s = norm(z); + if (s < 1e-7) { + zz = z*z; + v = exp(zz); + c = C[0]; + d2 = D[0]; + for (i = 1; i <= 6; i++) { + c = c * zz + C[i]; + d2 = d2 * zz + D[i]; + } + w = 1.0 / v + std::complex(0.0,m_2_SQRTPI) * c/d2 * z * v; + return w; + + // use trapezoid rule + } + else { + // select default table 1 + n = n1; + e = e1; + r = M_1_PI * 0.5; + + // if z is too close to a pole select table 2 + if (fabs(imag(z)) < 0.01 && fabs(real(z)) < 6.01) { + h = modf(2*fabs(real(z)),&g); + if (h < 0.02 || h > 0.98) { + n = n2; + e = e2; + r = M_1_PI * 0.53; + } + } + + d = (imag(z) - real(z)) * (imag(z) + real(z)); + f = 4 * real(z) * real(z) * imag(z) * imag(z); + + g = h = 0.0; + for (i = 0; i < 12; i++) { + t = d + n[i]; + u = e[i] / (t * t + f); + g += (s + n[i]) * u; + h += (s - n[i]) * u; + } + u = 1 / s; + c = r * std::complex(imag(z) * (u + 2.0 * g), + real(z) * (u + 2.0 * h) ); + + if (imag(z) < M_2PI) { + s = 2.0 / r; + t = s * real(z); + u = s * imag(z); + s = sin(t); + h = cos(t); + f = exp(- u) - h; + g = 2.0 * exp(d-u) / (s * s + f * f); + u = 2.0 * real(z) * imag(z); + h = cos(u); + t = sin(u); + c += g * std::complex( (h * f - t * s), -(h * s + t * f)); + } + return c; + } +} + +//this is the complex error function w(z) +std::complex wErrF(const std::complex& arg){ + const double c1 = 7.4; + const double c2 = 8.3; + const double c3 = 0.3125; + const double c4 = 1.6; + + const double p = 46768052394588893.38251791464692105662; + + //---------------------------------------------------------------------------- + std::complex r[37]; + std::complex zh, s, t, v; + std::complex hh, den; + + double xl = p; + + double x = arg.real(); + double y = arg.imag(); + double xa = fabs(x); + double ya = fabs(y); + + if (ya < c1 && xa < c2) { + zh = std::complex(ya+c4, xa); + + for (int n=35; n>-1; n--) { + t = zh + std::conj(double(n+1)*r[n+1]); + r[n] = 0.5 / (t.real()*t.real() + t.imag()*t.imag()) * t; + } + + for (int n=32; n>-1; n--) { + xl = xl*c3; + s = (xl+s)*r[n]; + } + + v = m_2_SQRTPI * s; + } + else { + zh = std::complex(ya, xa); + + for (int n=8; n>-1; n--) { + t = zh + std::conj(double(n+1)*r[0]); + r[0] = 0.5 / (t.real()*t.real() + t.imag()*t.imag()) * t; + } + + v = m_2_SQRTPI * r[0]; + } + + if (ya == 0){ + v = std::complex(exp(-xa*xa), v.imag()); + } + + if (y < 0) { + hh = std::complex(xa, ya); + std::complex hprod = -hh*hh; + std::complex anexp(exp(hprod.real())*cos(hprod.imag()),exp(hprod.real())*sin(hprod.imag())); + v = 2.0 * anexp - v; + } + else if (x < 0){ + v = conj(v); + } + + if(std::isnan(v.real())) spdlog::warn("wErrF: the result is NaN, do not trust anything!"); + + return v; + +} + +std::complex nwwerf(const std::complex z) { + std::complex zh,r[38],s,t,v; + + const double z1 = 1; + const double hf = z1/2; + const double z10 = 10; + const double c1 = 74/z10; + const double c2 = 83/z10; + const double c3 = z10/32; + const double c4 = 16/z10; + const double p = pow(2.0*c4,33); + + double x=z.real(); + double y=z.imag(); + double xa=(x >= 0) ? x : -x; + double ya=(y >= 0) ? y : -y; + if(ya < c1 && xa < c2){ + zh = std::complex(ya+c4,xa); + r[37]= std::complex(0,0); + // do 1 n = 36,1,-1 + for(int n = 36; n>0; n--){ + t=zh+double(n)*std::conj(r[n+1]); + r[n]=hf*t/std::norm(t); + } + double xl=p; + s=std::complex(0,0); + // do 2 n = 33,1,-1 + for(int k=33; k>0; k--){ + xl=c3*xl; + s=r[k]*(s+xl); + } + v=m_2_SQRTPI*s; + } + else{ + zh=std::complex(ya,xa); + r[1]=std::complex(0,0); + // do 3 n = 9,1,-1 + for(int n=9;n>0;n--){ + t=zh+double(n)*std::conj(r[1]); + r[1]=hf*t/std::norm(t); + } + v=m_2_SQRTPI*r[1]; + } + if(ya == 0) v= std::complex(exp(-xa*xa),v.imag()); + if(y < 0) { + v=2.0*std::exp(std::complex(-xa,-ya)*std::complex(xa,ya))-v; + if(x > 0) v=std::conj(v); + } + else{ + if(x < 0) v=std::conj(v); + } + return v; +} + +void norm_convoluted_exp_sincos(double tau, double deltam, double& one, double& two){ + //double tau = 1.0/gamma();//0.5*(ctau_l() + ctau_h());//is this correct? 1/(0.5(gammal + gammah)) + double tau_2 = tau*tau; + double deltam_2 = deltam*deltam; + one = tau_2 * deltam / (tau_2 * deltam_2 + 1.0);//sin + two = tau / (tau_2 * deltam_2 + 1.0);//cos +} + +//calculates the gaussian convolution sin(angle) from 0 to pi +double convoluted_sin(double angle, double sigma){ + double b = -angle/sqrt(2.0)/sigma + TMath::Pi()/sqrt(2.0)/sigma; + double c = angle/sqrt(2.0)/sigma; + double a = sigma/sqrt(2.0); + double sigma_2 = sigma*sigma; + double result = 0.0; + std::complex arg1(b, a); + std::complex arg2(c, a); + std::complex erf1 = 1.0-cErrF_2(arg1); + std::complex erf2 = 1.0-cErrF_2(arg2); + result = 0.5*sin(angle)*exp(-0.5*sigma_2) + *(erf1.real()+erf2.real()) + +0.5*cos(angle)*exp(-0.5*sigma_2) + *(-erf1.imag()+erf2.imag()); + spdlog::trace("convoluted sin:\t{0:f}", result); + return result; +} + +double convoluted_cos_sin(double angle, double sigma){ + return 0.5*convoluted_2_sin(angle, sigma); +} + +//calculates the gaussian convolution sin(angle) from 0 to pi +double convoluted_cos(double angle, double sigma) +{ + double b = -angle/sqrt(2.0)/sigma + TMath::Pi()/sqrt(2.0)/sigma; + double c = -angle/sqrt(2.0)/sigma;//also changed sign here + double a = sigma/sqrt(2.0); + double sigma_2 = sigma*sigma; + double result = 0.0; + std::complex arg1(b, a); + std::complex arg2(c, a); + std::complex erf1 = 1.0-cErrF_2(arg1); + std::complex erf2 = 1.0-cErrF_2(arg2); + result = 0.5*sin(angle)*exp(-0.5*sigma_2) + *(erf1.imag()-erf2.imag()) + +0.5*cos(angle)*exp(-0.5*sigma_2) + *(erf1.real()-erf2.real()); + return result; +} + +//calculates the gaussian convolution cos(angle)^2 from 0 to pi +double convoluted_cos_2(double angle, double sigma){ + double b = -angle/sqrt(2.0)/sigma + TMath::Pi()/sqrt(2.0)/sigma; + double c = -angle/sqrt(2.0)/sigma;//changed the sign here, more consistent + double a = sigma*sqrt(2.0);//!!! + double sigma_2 = sigma*sigma; + double result = 0.0; + std::complex arg1(b, a); + std::complex arg2(c, a); + std::complex erf1 = 1.0-cErrF_2(arg1); + std::complex erf2 = 1.0-cErrF_2(arg2); + result = 0.25*sin(2.0*angle)*exp(-2.0*sigma_2) + *(erf1.imag()-erf2.imag()) + +0.25*cos(2.0*angle)*exp(-2.0*sigma_2) + *(erf1.real()-erf2.real()) + -0.25*erf(-b) + +0.25*erf(-c); + return result; +} + +//calculates the gaussian convolution cos(angle)^2*sin(angle) from 0 to pi +double convoluted_cos_2_sin(double angle, double sigma){ + double b = -angle/sqrt(2.0)/sigma + TMath::Pi()/sqrt(2.0)/sigma; + double c = -angle/sqrt(2.0)/sigma;//changed the sign here, more consistent + + double a = 3.0*sigma/sqrt(2.0); + double sigma_2 = sigma*sigma; + double result = 0.0; + std::complex arg1(b, a); + std::complex arg2(c, a); + std::complex erf1 = 1.0-cErrF_2(arg1); + std::complex erf2 = 1.0-cErrF_2(arg2); + + result = 1.0/8.0*sin(3.0*angle)*exp(-4.5*sigma_2) + *(erf1.real()-erf2.real()) + +1.0/8.0*cos(3.0*angle)*exp(-4.5*sigma_2) + *(-erf1.imag()+erf2.imag()); + + a = sigma/sqrt(2.0); + arg1 = std::complex(b, a); + arg2 = std::complex(c, a); + + erf1 = 1.0-cErrF_2(arg1); + erf2 = 1.0-cErrF_2(arg2); + + result += 1.0/8.0*sin(angle)*exp(-0.5*sigma_2) + *(erf1.real()-erf2.real()) + +1.0/8.0*cos(angle)*exp(-0.5*sigma_2) + *(-erf1.imag()+erf2.imag()); + return result; +} + +//gaussian convolution sin(angle)*sin(2*angle) from 0 to pi +double convoluted_2_sin_sin(double angle, double sigma){ + double b = -angle/(sqrt(2.0)*sigma) + MY_PI/(sqrt(2.0)*sigma); + double c = -angle/(sqrt(2.0)*sigma); + double a = 3.0*sigma/sqrt(2.0); + double sigma_2 = sigma*sigma; + double result = 0.0; + std::complex arg1(b, a); + std::complex arg2(c, a); + std::complex erf1 = 1.0-cErrF_2(arg1); + std::complex erf2 = 1.0-cErrF_2(arg2); + result = 1.0/4.0*sin(3.0*angle)*exp(-4.5*sigma_2) + *(-erf1.imag()+erf2.imag()) + +1.0/4.0*cos(3.0*angle)*exp(-4.5*sigma_2) + *(-erf1.real()+erf2.real()); + + a = sigma/sqrt(2.0); + arg1 = std::complex(b, a); + arg2 = std::complex(c, a); + + erf1 = 1.0-cErrF_2(arg1); + erf2 = 1.0-cErrF_2(arg2); + + result += 1.0/4.0*sin(angle)*exp(-0.5*sigma_2) + *(+erf1.imag()-erf2.imag()) + +1.0/4.0*cos(angle)*exp(-0.5*sigma_2) + *(+erf1.real()-erf2.real()); + return result;//please recheck //I tried but gave up quickly as there is NOT A SINGLE COMMENT ANYHWERE + //TODO +} + +//gaussian convolution sin(angle)^3 from 0 to pi +double convoluted_sin_3(double angle, double sigma){ + double b = -angle/sqrt(2.0)/sigma + TMath::Pi()/sqrt(2.0)/sigma; + double c = -angle/sqrt(2.0)/sigma;//changed the sign here, more consistent + double a = 3.0*sigma/sqrt(2.0); + double sigma_2 = sigma*sigma; + double result = 0.0; + std::complex arg1(b, a); + std::complex arg2(c, a); + + std::complex erf1 = 1.0-cErrF_2(arg1); + std::complex erf2 = 1.0-cErrF_2(arg2); + + result = 1.0/8.0*sin(3.0*angle)*exp(-4.5*sigma_2) + *(-erf1.real()+erf2.real()) + +1.0/8.0*cos(3.0*angle)*exp(-4.5*sigma_2) + *(erf1.imag()-erf2.imag()); + + a = sigma/sqrt(2.0); + arg1 = std::complex(b, a); + arg2 = std::complex(c, a); + + erf1 = 1.0-cErrF_2(arg1); + erf2 = 1.0-cErrF_2(arg2); + + result += 3.0/8.0*sin(angle)*exp(-0.5*sigma_2) + *(erf1.real()-erf2.real()) + +3.0/8.0*cos(angle)*exp(-0.5*sigma_2) + *(-erf1.imag()+erf2.imag()); + return result;//this should be correct now->recheck //TODO//I tried but gave up quickly as there is NOT A SINGLE COMMENT ANYHWERE + //Also it is not used anywhere, so why bother + +} + +//calculates the gaussian convolution sin(angle)^2 from 0 to pi +double convoluted_sin_2(double angle, double sigma){ + double b = -angle/sqrt(2.0)/sigma + TMath::Pi()/sqrt(2.0)/sigma; + double c = -angle/sqrt(2.0)/sigma;//changed the sign here, more consistent + double a = sigma*sqrt(2.0);//!!! + double sigma_2 = sigma*sigma; + double result = 0.0; + std::complex arg1(b, a); + std::complex arg2(c, a); + std::complex erf1 = 1.0-cErrF_2(arg1); + std::complex erf2 = 1.0-cErrF_2(arg2); + result = 0.25*sin(2.0*angle)*exp(-2.0*sigma_2) + *(-erf1.imag()+erf2.imag()) + +0.25*cos(2.0*angle)*exp(-2.0*sigma_2) + *(-erf1.real()+erf2.real()) + -0.25*erf(-b) + +0.25*erf(-c); + return result; +} + +//calculates the gaussian convolution cos(2*angle) from 0 to pi +double convoluted_2_cos(double angle, double sigma){ + double b = -angle/sqrt(2.0)/sigma + TMath::Pi()/sqrt(2.0)/sigma; + double c = -angle/sqrt(2.0)/sigma;//changed the sign here, more consistent + double a = sigma*sqrt(2.0);//!!! + double sigma_2 = sigma*sigma; + double result = 0.0; + std::complex arg1(b, a); + std::complex arg2(c, a); + std::complex erf1 = 1.0-cErrF_2(arg1); + std::complex erf2 = 1.0-cErrF_2(arg2); + result = + 0.5*sin(2.0*angle)*exp(-2.0*sigma_2) + *(erf1.imag()-erf2.imag()) + +0.5*cos(2.0*angle)*exp(-2.0*sigma_2) + *(erf1.real()-erf2.real()); + return result; +} + +//calculates the gaussian convolution sin(2*angle) from 0 to pi +double convoluted_2_sin(double angle, double sigma){ + double b = -angle/sqrt(2.0)/sigma + TMath::Pi()/sqrt(2.0)/sigma; + double c = -angle/sqrt(2.0)/sigma;//changed the sign here, more consistent + double a = sigma*sqrt(2.0);//rechcek this for all other convs! + double sigma_2 = sigma*sigma; + double result = 0.0; + std::complex arg1(b, a); + std::complex arg2(c, a); + std::complex erf1 = 1.0-cErrF_2(arg1); + std::complex erf2 = 1.0-cErrF_2(arg2); + result = 0.5*sin(2.0*angle)*exp(-2.0*sigma_2) + *(erf1.real()-erf2.real())//ok + +0.5*cos(2.0*angle)*exp(-2.0*sigma_2) + *(-erf1.imag()+erf2.imag()); + + return result; +} + +//integrate(sqrt(alpha/%pi)*sin(d)*exp(-alpha*(t-d)^2),d,-inf,inf); +//integrate(1/sqrt(2*%pi)/sigma*sin(d)*exp(-(t-d)^2/2/sigma^2),d,-inf,inf); why does this not work? +double inf_convoluted_sin(double angle, double sigma){ + //%e^-(1/(4*alpha))*sin(t) + return exp(-0.5*sigma*sigma)*sin(angle); +} + +//integrate(sqrt(alpha/%pi)*cos(d)*exp(-alpha*(t-d)^2),d,-inf,inf); +double inf_convoluted_cos(double angle, double sigma){ + // %e^-(1/(4*alpha))*cos(t) + return exp(-0.5*sigma*sigma)*cos(angle); +} + +//integrate(sqrt(alpha/%pi)*cos(d)^2*exp(-alpha*(t-d)^2),d,-inf,inf); +double inf_convoluted_cos_2(double angle, double sigma){ + //%e^-(1/alpha)*cos(2*t)/2+1/2 + return 0.5*exp(-2.0*sigma*sigma)*cos(2.0*angle)+0.5; +} + +//integrate(sqrt(alpha/%pi)*sin(d)^2*exp(-alpha*(t-d)^2),d,-inf,inf); +double inf_convoluted_sin_2(double angle, double sigma){ + // 1/2-%e^-(1/alpha)*cos(2*t)/2 + return 0.5-0.5*exp(-2.0*sigma*sigma)*cos(2.0*angle); +} + +//integrate(sqrt(alpha/%pi)*sin(2*d)*exp(-alpha*(t-d)^2),d,-inf,inf); +double inf_convoluted_2_sin(double angle, double sigma){ + //%e^-(1/alpha)*sin(2*t) + return exp(-2.0*sigma*sigma)*sin(2.0*angle); +} + +//string(expand(integrate(integrate(sqrt(alpha/%pi)*exp(-alpha*(t-d)^2),d,-inf,inf),t))); +double int_inf_convoluted_const(double angle, double sigma){ + return angle; +} + +//string(expand(integrate(integrate(sqrt(alpha/%pi)*sin(d)*exp(-alpha*(t-d)^2),d,-inf,inf),t))); +double int_inf_convoluted_sin(double angle, double sigma){ + //-%e^-(1/(4*alpha))*cos(t) + return -exp(-0.5*sigma*sigma)*cos(angle); +} + +//string(expand(integrate(integrate(sqrt(alpha/%pi)*cos(d)*exp(-alpha*(t-d)^2),d,-inf,inf),t))); +double int_inf_convoluted_cos(double angle, double sigma){ + //%e^-(1/(4*alpha))*sin(t) + return exp(-0.5*sigma*sigma)*sin(angle); +} + +//string(expand(integrate(integrate(sqrt(alpha/%pi)*cos(d)^2*exp(-alpha*(t-d)^2),d,-inf,inf),t))); +double int_inf_convoluted_cos_2(double angle, double sigma){ + //%e^-(1/alpha)*sin(2*t)/4+t/2 + return 0.25*exp(-2.0*sigma*sigma)*sin(2.0*angle)+0.5*angle; +} + +//string(expand(integrate(integrate(sqrt(alpha/%pi)*sin(d)^2*exp(-alpha*(t-d)^2),d,-inf,inf),t))); +double int_inf_convoluted_sin_2(double angle, double sigma){ + //t/2-%e^-(1/alpha)*sin(2*t)/4 + return 0.5*angle-0.25*exp(-2.0*sigma*sigma)*sin(2.0*angle); +} + +//string(expand(integrate(integrate(sqrt(alpha/%pi)*sin(2*d)*exp(-alpha*(t-d)^2),d,-inf,inf),t))); +double int_inf_convoluted_2_sin(double angle, double sigma){ + // -%e^-(1/alpha)*cos(2*t)/2 + return -0.5*exp(-2.0*sigma*sigma)*cos(2.0*angle); +} + +//expand(integrate(integrate(sqrt(alpha/%pi)*sin(d)*exp(-alpha*(t-d)^2),d,0,%pi), t)); +double int_convoluted_sin(double angle, double sigma){ + double alpha = 1.0/(2.0*sigma*sigma); + double sa = sqrt(alpha); + double sat = sa*angle; + double sapi = sa*TMath::Pi(); + double overtwosa = 1.0/(2.0*sa); + double expa = exp(-1.0/(4.0*alpha)); + double cost = cos(angle); + double sint = sin(angle); + double result = 0.0; + result += 0.5*expa*cost*ErrF_2(std::complex(sat - sapi, overtwosa)).real(); + result += -0.5*expa*sint*ErrF_2(std::complex(sat - sapi, overtwosa)).imag(); + result += -0.5*expa*cost*ErrF_2(std::complex(sat, overtwosa)).real(); + result += 0.5*expa*sint*ErrF_2(std::complex(sat, overtwosa)).imag(); + result += 0.5*erf(sat - sapi); + result += 0.5*erf(sat); + return result; +} + +double int_convoluted_cos_sin(double angle, double sigma){ + return 0.5*int_convoluted_2_sin(angle, sigma); +} + +//expand(integrate(integrate(sqrt(alpha/%pi)*cos(d)^2*sin(d)*exp(-alpha*(t-d)^2),d,0,%pi), t)); +double int_convoluted_cos_2_sin(double angle, double sigma){ + double alpha = 1.0/(2.0*sigma*sigma); + double sa = sqrt(alpha); + double sat = sa*angle; + double sapi = sa*TMath::Pi(); + double overtwosa = 1.0/(2.0*sa); + double threeovertwosa = 3.0/(2.0*sa); + double expa = exp(-1.0/(4.0*alpha)); + double expninea = exp(-9.0/(4.0*alpha)); + double cost = cos(angle); + double sint = sin(angle); + double costhreet = cos(3.0*angle); + double sinthreet = sin(3.0*angle); + double result = 0.0; + + result += -(1.0/24.0)*expninea*sinthreet*ErrF_2(std::complex(sat - sapi, threeovertwosa)).imag(); + result += (1.0/24.0)*expninea*costhreet*ErrF_2(std::complex(sat - sapi, threeovertwosa)).real(); + + result += -(1.0/8.0)*expa*sint*ErrF_2(std::complex(sat - sapi, overtwosa)).imag(); + result += (1.0/8.0)*expa*cost*ErrF_2(std::complex(sat - sapi, overtwosa)).real(); + + result += (1.0/24.0)*expninea*sinthreet*ErrF_2(std::complex(sat, threeovertwosa)).imag(); + result += -(1.0/24.0)*expninea*costhreet*ErrF_2(std::complex(sat, threeovertwosa)).real(); + + result += (1.0/8.0)*expa*sint*ErrF_2(std::complex(sat, overtwosa)).imag(); + result += -(1.0/8.0)*expa*cost*ErrF_2(std::complex(sat, overtwosa)).real(); + + result += (1.0/6.0)*erf(sat-sapi); + result += (1.0/6.0)*erf(sat); + + return result; + +} + +//expand(integrate(integrate(sqrt(alpha/%pi)*sin(d)*sin(2*d)*exp(-alpha*(t-d)^2),d,0,%pi), t)); +double int_convoluted_2_sin_sin(double angle, double sigma){ + double alpha = 1.0/(2.0*sigma*sigma); + double sa = sqrt(alpha); + double sat = sa*angle; + double sapi = sa*TMath::Pi(); + double overtwosa = 1.0/(2.0*sa); + double threeovertwosa = 3.0/(2.0*sa); + double expa = exp(-1.0/(4.0*alpha)); + double expninea = exp(-9.0/(4.0*alpha)); + double cost = cos(angle); + double sint = sin(angle); + double costhreet = cos(3.0*angle); + double sinthreet = sin(3.0*angle); + double result = 0.0; + + result += (1.0/12.0)*expninea*sinthreet*ErrF_2(std::complex(sat - sapi, threeovertwosa)).real(); + result += (1.0/12.0)*expninea*costhreet*ErrF_2(std::complex(sat - sapi, threeovertwosa)).imag(); + + result += -(1.0/4.0)*expa*sint*ErrF_2(std::complex(sat - sapi, overtwosa)).real(); + result += -(1.0/4.0)*expa*cost*ErrF_2(std::complex(sat - sapi, overtwosa)).imag(); + + result += -(1.0/12.0)*expninea*sinthreet*ErrF_2(std::complex(sat, threeovertwosa)).real(); + result += -(1.0/12.0)*expninea*costhreet*ErrF_2(std::complex(sat, threeovertwosa)).imag(); + + result += (1.0/4.0)*expa*sint*ErrF_2(std::complex(sat, overtwosa)).real(); + result += (1.0/4.0)*expa*cost*ErrF_2(std::complex(sat, overtwosa)).imag(); + + return result; +} + +//expand(integrate(integrate(sqrt(alpha/%pi)*sin(d)^3*exp(-alpha*(t-d)^2),d,0,%pi), t)); +double int_convoluted_sin_3(double angle, double sigma){ + double alpha = 1.0/(2.0*sigma*sigma); + double sa = sqrt(alpha); + double sat = sa*angle; + double sapi = sa*TMath::Pi(); + double overtwosa = 1.0/(2.0*sa); + double threeovertwosa = 3.0/(2.0*sa); + double expa = exp(-1.0/(4.0*alpha)); + double expninea = exp(-9.0/(4.0*alpha)); + double cost = cos(angle); + double sint = sin(angle); + double costhreet = cos(3.0*angle); + double sinthreet = sin(3.0*angle); + double result = 0.0; + result += (1.0/24.0)*expninea*sinthreet*ErrF_2(std::complex(sat - sapi, threeovertwosa)).imag(); + result += -(1.0/24.0)*expninea*costhreet*ErrF_2(std::complex(sat - sapi, threeovertwosa)).real(); + result += -(3.0/8.0)*expa*sint*ErrF_2(std::complex(sat - sapi, overtwosa)).imag(); + result += (3.0/8.0)*expa*cost*ErrF_2(std::complex(sat - sapi, overtwosa)).real(); + + result += -(1.0/24.0)*expninea*sinthreet*ErrF_2(std::complex(sat, threeovertwosa)).imag(); + result += (1.0/24.0)*expninea*costhreet*ErrF_2(std::complex(sat, threeovertwosa)).real(); + result += +(3.0/8.0)*expa*sint*ErrF_2(std::complex(sat, overtwosa)).imag(); + result += -(3.0/8.0)*expa*cost*ErrF_2(std::complex(sat, overtwosa)).real(); + + result += 1.0/3.0*erf(sat-sapi); + result += 1.0/3.0*erf(sat); + + return result; +} + +//expand(integrate(integrate(sqrt(alpha/%pi)*sin(d)^2*exp(-alpha*(t-d)^2),d,0,%pi), t)); +double int_convoluted_sin_2(double angle, double sigma){//used by s wave + + double t = angle; + double alpha = 1.0/(2.0*sigma*sigma); + double sa = sqrt(alpha); + double sat = sa*angle; + double sapi = sa*TMath::Pi(); + double oversa = 1.0/(sa); + double expa = exp(-1.0/(alpha)); + double costwot = cos(2.0*angle); + double sintwot = sin(2.0*angle); + double pi = TMath::Pi(); + double spi = sqrt(pi); + double result = 0.0; + result += (1.0/8.0)*expa*sintwot*ErrF_2(std::complex(sat - sapi, oversa)).real(); + result += (1.0/8.0)*expa*costwot*ErrF_2(std::complex(sat - sapi, oversa)).imag(); + + result += -(1.0/8.0)*expa*sintwot*ErrF_2(std::complex(sat, oversa)).real(); + result += -(1.0/8.0)*expa*costwot*ErrF_2(std::complex(sat, oversa)).imag(); + + result += -(t/4.0)*erf(sat-sapi); + result += (pi/4.0)*erf(sat-sapi); + result += (t/4.0)*erf(sat); + + result += -(1.0/(4.0*sa*spi))*exp(-alpha*t*t+2.0*pi*alpha*t-pi*pi*alpha); + result += (1.0/(4.0*sa*spi))*exp(-alpha*t*t); + + return result; + +} + +//expand(integrate(integrate(sqrt(alpha/%pi)*sin(2*d)*exp(-alpha*(t-d)^2),d,0,%pi), t)); +double int_convoluted_2_sin(double angle, double sigma){//used by s wave + + double alpha = 1.0/(2.0*sigma*sigma); + double sa = sqrt(alpha); + double sat = sa*angle; + double sapi = sa*TMath::Pi(); + double oversa = 1.0/(sa); + double expa = exp(-1.0/(alpha)); + double costwot = cos(2.0*angle); + double sintwot = sin(2.0*angle); + double result = 0.0; + result += -(1.0/4.0)*expa*sintwot*ErrF_2(std::complex(sat - sapi, oversa)).imag(); + result += (1.0/4.0)*expa*costwot*ErrF_2(std::complex(sat - sapi, oversa)).real(); + + result += (1.0/4.0)*expa*sintwot*ErrF_2(std::complex(sat, oversa)).imag(); + result += -(1.0/4.0)*expa*costwot*ErrF_2(std::complex(sat, oversa)).real(); + + result += -(1.0/4.0)*erf(sat-sapi); + result += (1.0/4.0)*erf(sat); + + return result; + +} + +//for n:0 thru 8 do print("n=",n,": ",expand(integrate(sqrt(alpha/%pi)*exp(-alpha*(t-d)^2)*cos(t)^n, t, -inf, inf))); +//for k:0 thru n/2 do print(expand(1/2^(n-1)*binomial(n,k)*exp(-1/4/alpha*(n-2*k)^2)*cos((n-2*k)*t))); +//for k:0 thru 8/2 do print(expand(1/(2^(8-1))*binomial(8,k)*exp(-1/4/alpha*(8-2*k)^2)*cos((8-2*k)*t))); +//for k:0 thru 8/2 do print(expand(1/(2^(8))*binomial(8,k)*exp(-1/4/alpha*(8-2*k)^2)*cos((8-2*k)*t))); + +//for k:0 thru 8/2 do print(expand(1/2^(8)*binomial(8-1,k)*exp(-1/4/alpha*(8-2*k)^2)*cos((8-2*k)*t))); + +//for n:0 thru 20 do print("n=",n,": ",string(expand(integrate(integrate(sqrt(alpha/%pi)*exp(-alpha*(t)^2)*cos(t+d)^n*sin(d), t, -inf, inf), d, 0, %pi)))); +double int_convoluted_sin_cos_n(int n, double sigma){ + assert(n >= 0); + assert(n <= 20); + double alpha = 1.0/(2.0*sigma*sigma); + if (n % 2 == 1) + return 0.0; + switch (n) { + case 0: return 2; + break; + case 2: return 1-exp(-1/alpha)/3; + break; + case 4: return -exp(-1/alpha)/3-exp(-4/alpha)/60+3.0/4.0; + break; + case 6: return -5*exp(-1/alpha)/16-exp(-4/alpha)/40-exp(-9/alpha)/560+5.0/8.0; + break; + case 8: return -7*exp(-1/alpha)/24-7*exp(-4/alpha)/240-exp(-9/alpha)/280-exp(-16/alpha)/4032+35.0/64.0; + break; + case 10: return -35*exp(-1/alpha)/128-exp(-4/alpha)/32-9*exp(-9/alpha)/1792-5*exp(-16/alpha)/8064-exp(-25/alpha)/25344+63.0/128.0; + break; + case 12: return -33*exp(-1/alpha)/128-33*exp(-4/alpha)/1024-11*exp(-9/alpha)/1792-11*exp(-16/alpha)/10752-exp(-25/alpha)/8448-exp(-36/alpha)/146432+231.0/512.0; + break; + case 14: return -1001*exp(-1/alpha)/4096-1001*exp(-4/alpha)/30720-143*exp(-9/alpha)/20480-13*exp(-16/alpha)/9216-91*exp(-25/alpha)/405504-7*exp(-36/alpha)/292864-exp(-49/alpha)/798720+429.0/1024.0; + break; + case 16: return -715*exp(-1/alpha)/3072-1001*exp(-4/alpha)/30720-39*exp(-9/alpha)/5120-65*exp(-16/alpha)/36864-35*exp(-25/alpha)/101376-15*exp(-36/alpha)/292864-exp(-49/alpha)/199680-exp(-64/alpha)/4177920+6435.0/16384.0; + break; + case 18: return -7293*exp(-1/alpha)/32768-663*exp(-4/alpha)/20480-663*exp(-9/alpha)/81920-17*exp(-16/alpha)/8192-85*exp(-25/alpha)/180224-51*exp(-36/alpha)/585728-51*exp(-49/alpha)/4259840-3*exp(-64/alpha)/2785280-exp(-81/alpha)/21168128+12155.0/32768.0; + break; + case 20: return -20995*exp(-1/alpha)/98304-4199*exp(-4/alpha)/131072-969*exp(-9/alpha)/114688-1615*exp(-16/alpha)/688128-323*exp(-25/alpha)/540672-4845*exp(-36/alpha)/37486592-19*exp(-49/alpha)/851968-19*exp(-64/alpha)/6684672-5*exp(-81/alpha)/21168128-exp(-100/alpha)/104595456+46189.0/131072.0; + break; + } + return 0.0; +} + +//for n:0 thru 20 do print("n=",n,": ",string(expand(integrate(integrate(sqrt(alpha/%pi)*exp(-alpha*(t)^2)*cos(t+d)^n*sin(d)^3, t, -inf, inf), d, 0, %pi)))); +double int_convoluted_sin_3_cos_n(int n, double sigma){ + assert(n >= 0); + assert(n <= 20); + double alpha = 1.0/(2.0*sigma*sigma); + if (n % 2 == 1) + return 0.0; + switch (n) { + case 0: return 4.0/3.0 ; + break; + case 2: return 2.0/3.0-2*exp(-1/alpha)/5 ; + break; + case 4: return -2*exp(-1/alpha)/5+exp(-4/alpha)/70+1.0/2.0 ; + break; + case 6: return -3*exp(-1/alpha)/8+3*exp(-4/alpha)/140+exp(-9/alpha)/2520+5.0/12.0 ; + break; + case 8: return -7*exp(-1/alpha)/20+exp(-4/alpha)/40+exp(-9/alpha)/1260+exp(-16/alpha)/36960+35.0/96.0 ; + break; + case 10: return -21*exp(-1/alpha)/64+3*exp(-4/alpha)/112+exp(-9/alpha)/896+exp(-16/alpha)/14784+exp(-25/alpha)/384384+21.0/64.0 ; + break; + case 12: return -99*exp(-1/alpha)/320+99*exp(-4/alpha)/3584+11*exp(-9/alpha)/8064+exp(-16/alpha)/8960+exp(-25/alpha)/128128+exp(-36/alpha)/3294720+77.0/256.0 ; + break; + case 14: return -3003*exp(-1/alpha)/10240+143*exp(-4/alpha)/5120+143*exp(-9/alpha)/92160+13*exp(-16/alpha)/84480+exp(-25/alpha)/67584+7*exp(-36/alpha)/6589440+exp(-49/alpha)/24893440+143.0/512.0 ; + break; + case 16: return -143*exp(-1/alpha)/512+143*exp(-4/alpha)/5120+13*exp(-9/alpha)/7680+13*exp(-16/alpha)/67584+5*exp(-25/alpha)/219648+exp(-36/alpha)/439296+exp(-49/alpha)/6223360+exp(-64/alpha)/171991040+2145.0/8192.0 ; + break; + case 18: return -21879*exp(-1/alpha)/81920+1989*exp(-4/alpha)/71680+221*exp(-9/alpha)/122880+51*exp(-16/alpha)/225280+255*exp(-25/alpha)/8200192+17*exp(-36/alpha)/4392960+9*exp(-49/alpha)/23429120+9*exp(-64/alpha)/343982080+exp(-81/alpha)/1111326720+12155.0/49152.0 ; + break; + case 20: return -4199*exp(-1/alpha)/16384+12597*exp(-4/alpha)/458752+323*exp(-9/alpha)/172032+323*exp(-16/alpha)/1261568+323*exp(-25/alpha)/8200192+323*exp(-36/alpha)/56229888+57*exp(-49/alpha)/79659008.0+exp(-64/alpha)/14483456.0+exp(-81/alpha)/222265344.0+exp(-100/alpha)/6816137216.0+46189.0/196608.0 ; + break; + } + return 0.0; +} + +//for n:0 thru 20 do print("n=",n,": ",string(expand(integrate(integrate(sqrt(alpha/%pi)*exp(-alpha*(t)^2)*cos(t+d)^n*sin(d)*cos(d)^2, t, -inf, inf), d, 0, %pi)))); +double int_convoluted_cos_2_sin_cos_n(int n, double sigma){ + assert(n >= 0); + assert(n <= 20); + double alpha = 1.0/(2.0*sigma*sigma); + if (n % 2 == 1) + return 0.0; + switch (n) { + case 0: return 2.0/3.0 ; + break; + case 2: return exp(-1/alpha)/15+1.0/3.0 ; + break; + case 4: return exp(-1/alpha)/15-13*exp(-4/alpha)/420+1.0/4.0 ; + break; + case 6: return exp(-1/alpha)/16-13*exp(-4/alpha)/280-11*exp(-9/alpha)/5040+5.0/24.0 ; + break; + case 8: return 7*exp(-1/alpha)/120-13*exp(-4/alpha)/240-11*exp(-9/alpha)/2520-61*exp(-16/alpha)/221760+35.0/192.0 ; + break; + case 10: return 7*exp(-1/alpha)/128-13*exp(-4/alpha)/224-11*exp(-9/alpha)/1792-61*exp(-16/alpha)/88704-97*exp(-25/alpha)/2306304+21.0/128.0 ; + break; + case 12: return 33*exp(-1/alpha)/640-429*exp(-4/alpha)/7168-121*exp(-9/alpha)/16128-61*exp(-16/alpha)/53760-97*exp(-25/alpha)/768768-47*exp(-36/alpha)/6589440+77.0/512.0 ; + break; + case 14: return 1001*exp(-1/alpha)/20480-1859*exp(-4/alpha)/30720-1573*exp(-9/alpha)/184320-793*exp(-16/alpha)/506880-97*exp(-25/alpha)/405504-329*exp(-36/alpha)/13178880-193*exp(-49/alpha)/149360640+143.0/1024.0 ; + break; + case 16: return 143*exp(-1/alpha)/3072-1859*exp(-4/alpha)/30720-143*exp(-9/alpha)/15360-793*exp(-16/alpha)/405504-485*exp(-25/alpha)/1317888-47*exp(-36/alpha)/878592-193*exp(-49/alpha)/37340160-253*exp(-64/alpha)/1031946240+2145.0/16384.0 ; + break; + case 18: return 7293*exp(-1/alpha)/163840-8619*exp(-4/alpha)/143360-2431*exp(-9/alpha)/245760-1037*exp(-16/alpha)/450560-8245*exp(-25/alpha)/16400384-799*exp(-36/alpha)/8785920.0-579*exp(-49/alpha)/46858240.0-759*exp(-64/alpha)/687964160.0-107*exp(-81/alpha)/2222653440.0+12155.0/98304.0 ; + break; + case 20: return 4199*exp(-1/alpha)/98304-54587*exp(-4/alpha)/917504-3553*exp(-9/alpha)/344064-19703*exp(-16/alpha)/7569408-31331*exp(-25/alpha)/49201152-15181*exp(-36/alpha)/112459776.0-3667*exp(-49/alpha)/159318016.0-253*exp(-64/alpha)/86900736.0-107*exp(-81/alpha)/444530688.0-397*exp(-100/alpha)/40896823296.0+46189.0/393216.0 ; + break; + } + return 0.0; +} + +//for n:0 thru 20 do print("n=",n,": ",string(expand(integrate(integrate(sqrt(alpha/%pi)*exp(-alpha*(t)^2)*cos(t+d)^n*sin(2*d)*sin(d), t, -inf, inf), d, 0, %pi)))); +double int_convoluted_2_sin_sin_cos_n(int n, double sigma){ + assert(n >= 0); + assert(n <= 20); + double pi = TMath::Pi(); + double alpha = 1.0/(2.0*sigma*sigma); + if (n % 2 == 0) + return 0.0; + switch (n) { + case 1: return pi*exp(-1/(4*alpha))/4 ; + break; + case 3: return 3*pi*exp(-1/(4*alpha))/16-pi*exp(-9/(4*alpha))/16 ; + break; + case 5: return 5*pi*exp(-1/(4*alpha))/32-5*pi*exp(-9/(4*alpha))/64 ; + break; + case 7: return 35*pi*exp(-1/(4*alpha))/256-21*pi*exp(-9/(4*alpha))/256 ; + break; + case 9: return 63*pi*exp(-1/(4*alpha))/512-21*pi*exp(-9/(4*alpha))/256 ; + break; + case 11: return 231*pi*exp(-1/(4*alpha))/2048-165*pi*exp(-9/(4*alpha))/2048 ; + break; + case 13: return 429*pi*exp(-1/(4*alpha))/4096-1287*pi*exp(-9/(4*alpha))/16384 ; + break; + case 15: return 6435*pi*exp(-1/(4*alpha))/65536-5005*pi*exp(-9/(4*alpha))/65536 ; + break; + case 17: return 12155*pi*exp(-1/(4*alpha))/131072-2431*pi*exp(-9/(4*alpha))/32768 ; + break; + case 19: return 46189*pi*exp(-1/(4*alpha))/524288-37791*pi*exp(-9/(4*alpha))/524288 ; + break; + } + return 0.0; +} + +//for n:0 thru 20 do print("n=",n,": ",string(expand(integrate(integrate(sqrt(alpha/%pi)*exp(-alpha*(t)^2)*cos(t+d)^n*sin(d)*cos(d), t, -inf, inf), d, 0, %pi)))); +double int_convoluted_cos_sin_cos_n(int n, double sigma){ + assert(n >= 0); + assert(n <= 20); + double alpha = 1.0/(2.0*sigma*sigma); + if (n % 2 == 0) + return 0.0; + switch (n) { + case 1: return 2*exp(-1/(4*alpha))/3 ; + break; + case 3: return exp(-1/(4*alpha))/2-exp(-9/(4*alpha))/10 ; + break; + case 5: return 5*exp(-1/(4*alpha))/12-exp(-9/(4*alpha))/8-exp(-25/(4*alpha))/168 ; + break; + case 7: return 35*exp(-1/(4*alpha))/96-21*exp(-9/(4*alpha))/160-exp(-25/(4*alpha))/96-exp(-49/(4*alpha))/1440 ; + break; + case 9: return 21*exp(-1/(4*alpha))/64-21*exp(-9/(4*alpha))/160-3*exp(-25/(4*alpha))/224-exp(-49/(4*alpha))/640-exp(-81/(4*alpha))/9856 ; + break; + case 11: return 77*exp(-1/(4*alpha))/256-33*exp(-9/(4*alpha))/256-55*exp(-25/(4*alpha))/3584-11*exp(-49/(4*alpha))/4608-exp(-81/(4*alpha))/3584-exp(-121/(4*alpha))/59904 ; + break; + case 13: return 143*exp(-1/(4*alpha))/512-1287*exp(-9/(4*alpha))/10240-715*exp(-25/(4*alpha))/43008-143*exp(-49/(4*alpha))/46080-39*exp(-81/(4*alpha))/78848-exp(-121/(4*alpha))/18432-exp(-169/(4*alpha))/337920 ; + break; + case 15: return 2145*exp(-1/(4*alpha))/8192-1001*exp(-9/(4*alpha))/8192-143*exp(-25/(4*alpha))/8192-91*exp(-49/(4*alpha))/24576-65*exp(-81/(4*alpha))/90112-35*exp(-121/(4*alpha))/319488-exp(-169/(4*alpha))/90112-exp(-225/(4*alpha))/1810432 ; + break; + case 17: return 12155*exp(-1/(4*alpha))/49152-2431*exp(-9/(4*alpha))/20480-221*exp(-25/(4*alpha))/12288-1547*exp(-49/(4*alpha))/368640-85*exp(-81/(4*alpha))/90112-85*exp(-121/(4*alpha))/479232-17*exp(-169/(4*alpha))/675840-exp(-225/(4*alpha))/425984-exp(-289/(4*alpha))/9338880 ; + break; + case 19: return 46189*exp(-1/(4*alpha))/196608-37791*exp(-9/(4*alpha))/327680-4199*exp(-25/(4*alpha))/229376-2261*exp(-49/(4*alpha))/491520-2907*exp(-81/(4*alpha))/2523136-323*exp(-121/(4*alpha))/1277952-323*exp(-169/(4*alpha))/7208960-171*exp(-225/(4*alpha))/28966912-exp(-289/(4*alpha))/1966080-exp(-361/(4*alpha))/46792704 ; + break; + } + return 0.0; +} + +//for n:0 thru 20 do print("n=",n,": ",string(expand(integrate(integrate(sqrt(alpha/%pi)*exp(-alpha*(t)^2)*cos(t+d)^n*sin(d)^2, t, -inf, inf), d, 0, %pi)))); +double int_convoluted_sin_2_cos_n(int n, double sigma){ + assert(n >= 0); + assert(n <= 20); + double pi = TMath::Pi(); + double alpha = 1.0/(2.0*sigma*sigma); + if (n % 2 == 1) + return 0.0; + switch (n) { + case 0: return pi/2 ; + break; + case 2: return pi/4-pi*exp(-1/alpha)/8 ; + break; + case 4: return 3*pi/16-pi*exp(-1/alpha)/8 ; + break; + case 6: return 5*pi/32-15*pi*exp(-1/alpha)/128 ; + break; + case 8: return 35*pi/256-7*pi*exp(-1/alpha)/64 ; + break; + case 10: return 63*pi/512-105*pi*exp(-1/alpha)/1024 ; + break; + case 12: return 231*pi/2048-99*pi*exp(-1/alpha)/1024 ; + break; + case 14: return 429*pi/4096-3003*pi*exp(-1/alpha)/32768 ; + break; + case 16: return 6435*pi/65536-715*pi*exp(-1/alpha)/8192 ; + break; + case 18: return 12155*pi/131072-21879*pi*exp(-1/alpha)/262144 ; + break; + case 20: return 46189*pi/524288-20995*pi*exp(-1/alpha)/262144 ; + break; + } + return 0.0; +} + +//for n:0 thru 20 do print("case ",n,": return ",string(float(expand(integrate(integrate(sqrt(alpha/%pi)*(phi+d)^n*exp(-alpha*phi^2), phi, -inf, inf), d, -%pi, %pi)))), "; break;"); +double int_inf_convoluted_const_x_n(int n, double sigma){ + assert(n >= 0); + assert(n <= 20); + double alpha = 1.0/(2.0*sigma*sigma); + if (n % 2 == 1) + return 0.0; + switch (n) { + case 0 : return 6.283185307179586 ; break; + case 2 : return 3.141592653589793/alpha+20.67085112019988 ; break; + case 4 : return 62.01255336059963/alpha+4.71238898038469/pow(alpha,2)+122.4078739141126 ; break; + case 6 : return 918.0590543558442/alpha+232.5470751022486/pow(alpha,2)+11.78097245096172/pow(alpha,3)+862.9409222219404 ; break; + case 8 : return 12081.17291110717/alpha+6426.41338049091/pow(alpha,2)+1085.219683810494/pow(alpha,3)+41.23340357836604/pow(alpha,4)+6624.244296321378 ; break; + case 10 : return 149045.496667231/alpha+135913.1952499556/pow(alpha,2)+48198.10035368182/pow(alpha,3)+6104.360721434026/pow(alpha,4)+185.5503161026471/pow(alpha,5)+53491.63963161646 ; break; + case 12 : return + 1765224.107843343/alpha+2459250.695009312/pow(alpha,2)+1495045.147749512/pow(alpha,3)+397634.327917875/pow(alpha,4)+40288.78076146457/pow(alpha,5)+1020.526738564559/pow(alpha,6)+446719.5800943512 + ; break; + case 14 : return 2.0325740894292977E+7/alpha+4.0158848453436054E+7/pow(alpha,2)+3.7298635540974565E+7/pow(alpha,3)+1.7006138555650696E+7/pow(alpha,4)+3618472.384052663/pow(alpha,5)+305523.254107773/pow(alpha,6)+6633.423800669636/pow(alpha,7)+3821086.129251732 ; break; + case 16 : return 2.2926516775510389E+8/alpha+6.0977222682878935E+8/pow(alpha,2)+8.0317696906872118E+8/pow(alpha,3)+5.5947953311461842E+8/pow(alpha,4)+2.0407366266780835E+8/pow(alpha,5)+3.6184723840526626E+7/pow(alpha,6)+2618770.749495197/pow(alpha,7)+49750.67850502227/pow(alpha,8)+3.3275831010180339E+7 ; break; + case 18 : return 2.5456010722787962E+9/alpha+8.7693926666327229E+9/pow(alpha,2)+1.5549191784134127E+10/pow(alpha,3)+1.5360759533439291E+10/pow(alpha,4)+8.5600368566536617E+9/pow(alpha,5)+2.6019391990145564E+9/pow(alpha,6)+3.9544733911432672E+8/pow(alpha,7)+2.5041995292047825E+7/pow(alpha,8)+422880.7672926893/pow(alpha,9)+2.9384883679977304E+8 ; break; + case 20 : return 2.7915639495978439E+10/alpha+1.2091605093324281E+11/pow(alpha,2)+2.7769743444336957E+11/pow(alpha,3)+3.6929330487318555E+11/pow(alpha,4)+2.9185443113534656E+11/pow(alpha,5)+1.3553391689701631E+11/pow(alpha,6)+3.5312031986626122E+10/pow(alpha,7)+4.6959371519826298E+9/pow(alpha,8)+2.6433217252717146E+8/pow(alpha,9)+4017367.289280548/pow(alpha,10)+2.623964937416502E+9 + ; break; + } + return 0.0; +} + +//for n:0 thru 20 do print("case ",n,": return ",string(float(expand(integrate(integrate(sqrt(alpha/%pi)*(phi+d)^n*exp(-alpha*phi^2)*cos(d)^2, phi, -inf, inf), d, -%pi, %pi)))), "; break;"); +double int_inf_convoluted_cos_2_x_n(int n, double sigma) +{ + assert(n >= 0); + assert(n <= 20); + double alpha = 1.0/(2.0*sigma*sigma); + if (n % 2 == 1) + return 0.0; + switch (n) { + case 0 : return 3.141592653589793 ; break; + case 2 : return 1.570796326794897/alpha+11.90622188689484 ; break; + case 4 : return 35.71866566068451/alpha+2.356194490192345/pow(alpha,2)+87.4978246569714 ; break; + case 6 : return 656.2336849272856/alpha+133.9449962275669/pow(alpha,2)+5.890486225480862/pow(alpha,3)+693.2958305395289 ; break; + case 8 : return 9706.141627553405/alpha+4593.635794490999/pow(alpha,2)+625.0766490619789/pow(alpha,3)+20.61670178918302/pow(alpha,4)+5687.153431714451 ; break; + case 10 : return 127960.9522135751/alpha+109194.0933099758/pow(alpha,2)+34452.26845868249/pow(alpha,3)+3516.056150973631/pow(alpha,4)+92.77515805132357/pow(alpha,5)+47830.36426946412 ; break; + case 12 : return 1578402.020892315/alpha+2111355.71152399/pow(alpha,2)+1201135.026409734/pow(alpha,3)+284231.2147841306/pow(alpha,4)+23205.97059642596/pow(alpha,5)+510.2633692822797/pow(alpha,6)+410181.8769982042 + ; break; + case 14 : return 1.8663275403418235E+7/alpha+3.5908645975300178E+7/pow(alpha,2)+3.2022228291447181E+7/pow(alpha,3)+1.3662910925410721E+7/pow(alpha,4)+2586504.054535588/pow(alpha,5)+175978.6103562302/pow(alpha,6)+3316.711900334818/pow(alpha,7)+3573008.555500609 ; break; + case 16 : return 2.1438051333003667E+8/alpha+5.5989826210254693E+8/pow(alpha,2)+7.1817291950600362E+8/pow(alpha,3)+4.8033342437170768E+8/pow(alpha,4)+1.6395493110492867E+8/pow(alpha,5)+2.5865040545355879E+7/pow(alpha,6)+1508388.088767688/pow(alpha,7)+24875.33925251113/pow(alpha,8)+3.1522569930157386E+7 ; break; + case 18 : return 2.4114765996571231E+9/alpha+8.2000546348738604E+9/pow(alpha,2)+1.4277405683614956E+10/pow(alpha,3)+1.3735057085552319E+10/pow(alpha,4)+7.3491013928871279E+9/pow(alpha,5)+2.0904253715878406E+9/pow(alpha,6)+2.8266794310281783E+8/pow(alpha,7)+1.4423961098841013E+7/pow(alpha,8)+211440.3836463447/pow(alpha,9)+2.810488910215596E+8 ; break; + case 20 : return 2.6699644647049049E+10/alpha+1.1454513848371289E+11/pow(alpha,2)+2.5966839677100656E+11/pow(alpha,3)+3.390883849858551E+11/pow(alpha,4)+2.6096608462549408E+11/pow(alpha,5)+1.1636077205404617E+11/pow(alpha,6)+2.8370058614406403E+10/pow(alpha,7)+3.3566818243459616E+9/pow(alpha,8)+1.5225292270998847E+8/pow(alpha,9)+2008683.644640274/pow(alpha,10)+2.527977317637641E+9 + ; break; + } + return 0.0; +} + +//for n:0 thru 20 do print("case ",n,": return ",string(float(expand(integrate(integrate(sqrt(alpha/%pi)*(phi+d)^n*exp(-alpha*phi^2)*sin(d)^2, phi, -inf, inf), d, -%pi, %pi)))), "; break;"); +double int_inf_convoluted_sin_2_x_n(int n, double sigma){ + assert(n >= 0); + assert(n <= 20); + double alpha = 1.0/(2.0*sigma*sigma); + if (n % 2 == 1) + return 0.0; + switch (n) { + case 0 : return 3.141592653589793 ; break; + case 2 : return 1.570796326794897/alpha+8.764629233305042 ; break; + case 4 : return 26.29388769991513/alpha+2.356194490192345/pow(alpha,2)+34.91004925714116 ; break; + case 6 : return 261.8253694285586/alpha+98.60207887468172/pow(alpha,2)+5.890486225480862/pow(alpha,3)+169.6450916824115 ; break; + case 8 : return 2375.031283553761/alpha+1832.777585999911/pow(alpha,2)+460.1430347485147/pow(alpha,3)+20.61670178918302/pow(alpha,4)+937.0908646069279 ; break; + case 10 : return 21084.54445365589/alpha+26719.10193997981/pow(alpha,2)+13745.83189499933/pow(alpha,3)+2588.304570460395/pow(alpha,4)+92.77515805132357/pow(alpha,5)+5661.275362152337 ; break; + case 12 : return + 186822.0869510286/alpha+347894.9834853215/pow(alpha,2)+293910.121339778/pow(alpha,3)+113403.1131337445/pow(alpha,4)+17082.81016503861/pow(alpha,5)+510.2633692822797/pow(alpha,6)+36537.70309614705 + ; break; + case 14 : return 1662465.490874743/alpha+4250202.478135873/pow(alpha,2)+5276407.249527384/pow(alpha,3)+3343227.630239975/pow(alpha,4)+1031968.329517075/pow(alpha,5)+129544.6437515428/pow(alpha,6)+3316.711900334818/pow(alpha,7)+248077.5737511227 ; break; + case 16 : return 1.4884654425067216E+7/alpha+4.9873964726242363E+7/pow(alpha,2)+8.5004049562717617E+7/pow(alpha,3)+7.9146108742910743E+7/pow(alpha,4)+4.0118731562879689E+7/pow(alpha,5)+1.0319683295170747E+7/pow(alpha,6)+1110382.66072751/pow(alpha,7)+24875.33925251113/pow(alpha,8)+1753261.080022954 ; break; + case 18 : return 1.3412447262167311E+8/alpha+5.693380317588625E+8/pow(alpha,2)+1.2717861005191698E+9/pow(alpha,3)+1.6257024478869734E+9/pow(alpha,4)+1.2109354637665339E+9/pow(alpha,5)+5.1151382742671597E+8/pow(alpha,6)+1.1277939601150887E+8/pow(alpha,7)+1.0618034193206811E+7/pow(alpha,8)+211440.3836463447/pow(alpha,9)+1.2799945778213412E+7 ; break; + case 20 : return 1.21599484892939E+9/alpha+6.3709124495299149E+9/pow(alpha,2)+1.8029037672363007E+10/pow(alpha,3)+3.0204919887330444E+10/pow(alpha,4)+3.0888346509852478E+10/pow(alpha,5)+1.9173144842970131E+10/pow(alpha,6)+6.941973372219717E+9/pow(alpha,7)+1.339255327636668E+9/pow(alpha,8)+1.1207924981718299E+8/pow(alpha,9)+2008683.644640274/pow(alpha,10)+9.5987619778861046E+7 ; break; + } + return 0.0; +} + +//for n:0 thru 20 do print("case ",n,": return ",string(float(expand(integrate(integrate(sqrt(alpha/%pi)*(phi+d)^n*exp(-alpha*phi^2)*sin(d), phi, -inf, inf), d, -%pi, %pi)))), "; break;"); +double int_inf_convoluted_sin_x_n(int n, double sigma){ + assert(n >= 0); + assert(n <= 20); + double alpha = 1.0/(2.0*sigma*sigma); + if (n % 2 == 0) + return 0.0; + switch (n) { + case 1 : return 6.283185307179586 ; break; + case 3 : return 9.424777960769379/alpha+24.31344151752212 ; break; + case 5 : return 121.5672075876106/alpha+23.56194490192345/pow(alpha,2)+125.7705392201204 ; break; + case 7 : return 1320.590661811266/alpha+638.2278398349555/pow(alpha,2)+82.46680715673207/pow(alpha,3)+758.2238083085194 ; break; + case 9 : return 13648.02854955342/alpha+11885.31595630138/pow(alpha,2)+3829.367039009733/pow(alpha,3)+371.1006322052943/pow(alpha,4)+5026.084468678731 ; break; + case 11 : return 138217.3228886668/alpha+187660.3925563593/pow(alpha,2)+108948.7295994294/pow(alpha,3)+26326.89839319191/pow(alpha,4)+2041.053477129119/pow(alpha,5)+35538.744393114 ; break; + case 13 : return + 1386011.031330336/alpha+2695237.796329141/pow(alpha,2)+2439585.103232659/pow(alpha,3)+1062250.113594437/pow(alpha,4)+205349.807466897/pow(alpha,5)+13266.84760133927/pow(alpha,6)+263310.4159052214 + ; break; + case 15 : return 1.3823796834663689E+7/alpha+3.6382789572466373E+7/pow(alpha,2)+4.7166661435754895E+7/pow(alpha,3)+3.201955447992897E+7/pow(alpha,4)+1.1153626192741588E+7/pow(alpha,5)+1796810.815335348/pow(alpha,6)+99501.35701004454/pow(alpha,7)+2021104.600121215 ; break; + case 17 : return 1.3743511271761036E+8/alpha+4.7000909238989449E+8/pow(alpha,2)+8.2467656364292908E+8/pow(alpha,3)+8.018332444078331E+8/pow(alpha,4)+4.3546594092703295E+8/pow(alpha,5)+1.2640776351773798E+8/pow(alpha,6)+1.7454733634686239E+7/pow(alpha,7)+845761.5345853786/pow(alpha,8)+1.5948676302624345E+7 ; break; + case 19 : return 1.363611830458992E+9/alpha+5.8753510678547668E+9/pow(alpha,2)+1.3395259133206604E+10/pow(alpha,3)+1.7627461547833862E+10/pow(alpha,4)+1.3711348479374664E+10/pow(alpha,5)+6.2053896582101974E+9/pow(alpha,6)+1.5439805401095133E+9/pow(alpha,7)+1.865474657207092E+8/pow(alpha,8)+8034734.578561097/pow(alpha,9)+1.2868057735972023E+8 ; break; + } + return 0.0; +} + +//for n:0 thru 20 do print("case ",n,": return ",string(float(expand(integrate(integrate(sqrt(alpha/%pi)*(phi+d)^n*exp(-alpha*phi^2)*sin(2*d), phi, -inf, inf), d, -%pi, %pi)))), "; break;"); +double int_inf_convoluted_2_sin_x_n(int n, double sigma){ + assert(n >= 0); + assert(n <= 20); + double alpha = 1.0/(2.0*sigma*sigma); + if (n % 2 == 0) + return 0.0; + switch (n) { + case 1 : return -3.141592653589793 ; break; + case 3 : return -4.71238898038469/alpha-26.29388769991513 ; break; + case 5 : return -131.4694384995756/alpha-11.78097245096172/pow(alpha,2)-174.5502462857058 ; break; + case 7 : return -1832.777585999911/alpha-690.214552122772/pow(alpha,2)-41.23340357836604/pow(alpha,3)-1187.515641776881 ; break; + case 9 : return -21375.28155198386/alpha-16494.99827399919/pow(alpha,2)-4141.287312736632/pow(alpha,3)-185.5503161026471/pow(alpha,4)-8433.817781462349 ; break; + case 11 : return -231929.9889902145/alpha-293910.121339778/pow(alpha,2)-151204.1508449926/pow(alpha,3)-28471.35027506435/pow(alpha,4)-1020.526738564559/pow(alpha,5)-62274.02898367599 ; break; + case 13 : return -2428687.130363355/alpha-4522634.785309188/pow(alpha,2)-3820831.577417114/pow(alpha,3)-1474240.470738678/pow(alpha,4)-222076.5321455019/pow(alpha,5)-6633.423800669636/pow(alpha,6)-474990.140249928 + ; break; + case 15 : return -2.4936982363121182E+7/alpha-6.3753037172038078E+7/pow(alpha,2)-7.9146108742910743E+7/pow(alpha,3)-5.0148414453599617E+7/pow(alpha,4)-1.5479524942756122E+7/pow(alpha,5)-1943169.656273142/pow(alpha,6)-49750.67850502227/pow(alpha,7)-3721163.606266804 ; break; + case 17 : return -2.5303912522615099E+8/alpha-8.4785740034611607E+8/pow(alpha,2)-1.4450688425662041E+9/pow(alpha,3)-1.3454838486294813E+9/pow(alpha,4)-6.8201843656895471E+8/pow(alpha,5)-1.7543461601790273E+8/pow(alpha,6)-1.8876505232367665E+7/pow(alpha,7)-422880.7672926893/pow(alpha,8)-2.9805438360381901E+7 ; break; + case 19 : return -2.5483649798125954E+9/alpha-1.0817422603417984E+10/pow(alpha,2)-2.4163935909864288E+10/pow(alpha,3)-3.0888346509852478E+10/pow(alpha,4)-2.3007773811564163E+10/pow(alpha,5)-9.7187627211076069E+9/pow(alpha,6)-2.1428085242186687E+9/pow(alpha,7)-2.017426496709294E+8/pow(alpha,8)-4017367.289280548/pow(alpha,9)-2.4319896978524876E+8 ; break; + } + return 0.0; +} + +//for n:0 thru 20 do print("case ",n,": return ",string(float(expand(integrate(integrate(sqrt(alpha/%pi)*(phi+d)^n*exp(-alpha*phi^2)*cos(d), phi, -inf, inf), d, -%pi, %pi)))), "; break;"); +double int_inf_convoluted_cos_x_n(int n, double sigma){ + assert(n >= 0); + assert(n <= 20); + double alpha = 1.0/(2.0*sigma*sigma); + if (n % 2 == 1) + return 0.0; + switch (n) { + case 0 : return 0.0 ; break; + case 2 : return -12.56637061435917 ; break; + case 4 : return -37.69911184307752/alpha-97.25376607008846 ; break; + case 6 : return -729.4032455256634/alpha-141.3716694115407/pow(alpha,2)-754.6232353207233 ; break; + case 8 : return -10564.72529449013/alpha-5105.822718679644/pow(alpha,2)-659.7344572538566/pow(alpha,3)-6065.790466468156 ; break; + case 10 : return -136480.2854955334/alpha-118853.1595630139/pow(alpha,2)-38293.67039009733/pow(alpha,3)-3711.006322052943/pow(alpha,4)-50260.8446867906 ; break; + case 12 : return -1658607.874663904/alpha-2251924.710676324/pow(alpha,2)-1307384.755193153/pow(alpha,3)-315922.780718303/pow(alpha,4)-24492.64172554942/pow(alpha,5)-426464.9327177554 ; break; + case 14 : return -1.9404154438628018E+7/alpha-3.7733329148607552E+7/pow(alpha,2)-3.4154191445257187E+7/pow(alpha,3)-1.4871501590322122E+7/pow(alpha,4)-2874897.304536558/pow(alpha,5)-185735.8664187498/pow(alpha,6)-3686345.822659835 ; break; + case 16 : return -2.2118074935461903E+8/alpha-5.8212463315946198E+8/pow(alpha,2)-7.5466658297207832E+8/pow(alpha,3)-5.1231287167886353E+8/pow(alpha,4)-1.784580190838654E+8/pow(alpha,5)-2.8748973045365565E+7/pow(alpha,6)-1592021.712160713/pow(alpha,7)-3.233767360193944E+7 ; break; + case 18 : return -2.4738320296894684E+9/alpha-8.4601636629215393E+9/pow(alpha,2)-1.4844178145556E+10/pow(alpha,3)-1.4432998399342041E+10/pow(alpha,4)-7.8383869366865463E+9/pow(alpha,5)-2.2753397433192844E+9/pow(alpha,6)-3.1418520542435235E+8/pow(alpha,7)-1.5223707622536814E+7/pow(alpha,8)-2.8707617035731125E+8 ; break; + case 20 : return -2.7272236397462036E+10/alpha-1.1750702138356006E+11/pow(alpha,2)-2.6790518266332812E+11/pow(alpha,3)-3.5254923095672754E+11/pow(alpha,4)-2.742269695875127E+11/pow(alpha,5)-1.2410779316420337E+11/pow(alpha,6)-3.0879610802190308E+10/pow(alpha,7)-3.7309493144141827E+9/pow(alpha,8)-1.6069469157122192E+8/pow(alpha,9)-2.5736123940656128E+9 ; break; + } + return 0.0; +} + +//void fitter::ct_tagging_part(measurement* meas, double& one, double& two) +//this function calculates the convolution of the product exp(-t/tau) * sin(deltam*t) and exp(-t/tau) * cos(deltam*t) +void convoluted_exp_sincos(double ct, double sigma, double tau, double deltam, double& one, double& two){ + double sigma_2 = sigma*sigma; + double tau_2 = tau*tau; + double deltam_2 = deltam*deltam; + const double sqrt2 = TMath::Sqrt(2.0); + + const bool cdf_way = false; + if (!cdf_way){ + //safety for large negative decay times + if (ct < - 6.0*sigma){ + one = 0.0; + two = 0.0; + return; + } + double c1 = 0.5; + // double exp1arg = 0.5*sigma_2/tau_2 - 0.5*deltam_2*sigma_2 - ct/tau; + double exp1arg = 0.5*sigma_2*(1.0/tau_2 - deltam_2) - ct/tau; + double exp1 = exp(exp1arg); + double exp2arg = -deltam*(ct - sigma_2/tau); + std::complex exp2(cos(exp2arg), sin(exp2arg)); + std::complex cerfarg(sigma/(tau*sqrt2) - ct/(sigma*sqrt2), +deltam*sigma/sqrt2); + std::complex cerf; + if (cerfarg.real() < -20.0) cerf = std::complex(2.0,0.0); + else cerf = cErrF_2(cerfarg);//best std::complex error function + std::complex c2(exp2*cerf); + double im = -c2.imag();//exp*sin + double re = +c2.real();//exp*cos + one = c1*exp1*im ; + two = c1*exp1*re ; + } + else{ //all three methods are analytically the same. There might be numerical differences, though + if (ct < -6.0*sigma) { + one = 0.0; + two = 0.0; + return; + } + + //current cdf + std::complex z(deltam*sigma/sqrt2, (sigma/tau-ct/sigma)/sqrt2); + if (ct<0) {//i do not quite get this part. the calculation should also be corerct for ct < 0, right? + one= 2.0*nwwerf(z).real()/4.0*exp(-ct*ct/2.0/sigma/sigma); + two= 2.0*nwwerf(z).imag()/4.0*exp(-ct*ct/2.0/sigma/sigma); + } + else { + one= -2.0*nwwerf(std::conj(z)).real()/tau/4*exp(-ct*ct/2.0/sigma/sigma) + + exp(sigma*sigma/2 *(1/tau/tau - deltam*deltam) - ct/tau)*cos(deltam*ct - deltam/tau*sigma*sigma); + two= +2.0*nwwerf(std::conj(z)).imag()/tau/4*exp(-ct*ct/2.0/sigma/sigma) + + exp(sigma*sigma/2 *(1/tau/tau - deltam*deltam) - ct/tau)*sin(deltam*ct - deltam/tau*sigma*sigma); + } + + } + + if (std::isnan(one) || std::isnan(two)) { + //void convoluted_exp_sincos(double ct, double sigma, double tau, double deltam, double& one, double& two) + spdlog::error("ct= {0:f} sigma={1:f} tau={2:f} deltam={3:f} one={4:f} two={5:f}", + ct, sigma, tau, deltam, one, two); + spdlog::error("Error: NaN"); + assert(0); + + } + return; +} + + +double daughtermom(double m, double m1, double m2){ + //E1+E2 = sqrt(m1*m1+p1*p1)+sqrt(m2*m2+p2*p2), where p1=-p2 + //=> p= sqrt(m*m-(m1+m2)*(m1+m2))*(m*m-(m1-m2)*(m1-m2))/(2.0*m) + //E1 = (m*m+m1*m1-m2*m2)/(2.0*M) + //E2 = (m*m-m1*m1+m2*m2)/(2.0*M) + //So this returns daughter momentum and has nothing to do with the mother (=mom) + + double arg = (m*m-(m1+m2)*(m1+m2))*(m*m-(m1-m2)*(m1-m2));//original, reactivate + + if (arg < 0.0 || m1+m2>m) return 0.0; + + return sqrt(arg)/(2.0*m); + //all ok, confirmed that it gives breakup momentum +} + + +std::complex mkpi_simple_bw_kstar_amp(double mkpi, double qsquared, double gammakstar, double mkstar){ + double gamma = gammakstar; + std::complex bwamp = 1.0/std::complex(mkstar*mkstar-mkpi*mkpi,-mkstar*gamma); + //combine everything, eq 28-30 in LHCb-ANA-2013-053 + return sqrt(mkstar*gamma/TMath::Pi()) * bwamp; +} + +double mkpi_simple_bw_kstar_amp_squared(double mkpi, double qsquared, double gammakstar, double mkstar){ + std::complex result = mkpi_simple_bw_kstar_amp(mkpi, qsquared, gammakstar, mkstar); + return norm(result); +} + +double gsl_mkpi_simple_bw_kstar_amp_squared(double x, void* par){ + double* v = (double*)par; + return mkpi_simple_bw_kstar_amp_squared(sqrt(x), v[0], v[1], v[2]); +} + +double int_mkpi_simple_bw_kstar_amp_squared(const double& mkpia, const double& mkpib, const double& qsquared, const double& gammakstar, const double& mkstar){ + double pars[3] = {qsquared, gammakstar, mkstar}; + ROOT::Math::GSLIntegrator gslint; + gslint.SetFunction(gsl_mkpi_simple_bw_kstar_amp_squared, pars); + return gslint.Integral(mkpia*mkpia, mkpib*mkpib); +} + + +std::complex mkpi_simple_kstarzero_amp(double mkpi, double qsquared, double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero){ + std::complex gk(f800mag*cos(f800phase),f800mag*sin(f800phase)); + std::complex denomkappa(mf800,-0.5*gammaf800); + std::complex denomkstar(mkstarzero,-0.5*gammakstarzero); + + std::complex result = (-gk/(denomkappa*denomkappa-mkpi*mkpi) + +1.0/(denomkstar*denomkstar-mkpi*mkpi)); + return result; +} + +double mkpi_simple_kstarzero_amp_squared(double mkpi, double qsquared, double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero) +{ + std::complex result = mkpi_simple_kstarzero_amp(mkpi, qsquared, f800mag, f800phase, gammaf800, mf800, gammakstarzero, mkstarzero); + return norm(result); +} + +double gsl_mkpi_simple_kstarzero_amp_squared(double x, void* par) +{ + double* v = (double*)par; + return mkpi_simple_kstarzero_amp_squared(sqrt(x), v[0], v[1], v[2], v[3], v[4], v[5], v[6]);//this is for integrating over mkpi^2, only then is the norm 1 +} + +double gsl_mkpi_simple_re_bw_kstar_amp_kstarzero_amp_bar(double x, void* par) +{ + double* v = (double*)par; + std::complex result = mkpi_simple_bw_kstar_amp_kstarzero_amp_bar(x, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]); + return result.real(); +} + +double gsl_mkpi_simple_im_bw_kstar_amp_kstarzero_amp_bar(double x, void* par) +{ + double* v = (double*)par; + std::complex result = mkpi_simple_bw_kstar_amp_kstarzero_amp_bar(x, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]); + return result.imag(); +} + +double gsl_mkpi_simple_re_bw_kstar_amp_bar_kstarzero_amp(double x, void* par) +{ + double* v = (double*)par; + std::complex result = mkpi_simple_bw_kstar_amp_bar_kstarzero_amp(x, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]); + return result.real(); +} + +double gsl_mkpi_simple_im_bw_kstar_amp_bar_kstarzero_amp(double x, void* par) +{ + double* v = (double*)par; + std::complex result = mkpi_simple_bw_kstar_amp_bar_kstarzero_amp(x, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9]); + return result.imag(); +} + + + +double int_mkpi_simple_kstarzero_amp_squared(const double& mkpia, const double& mkpib, const double& qsquared, const double& f800mag, const double& f800phase, const double& gammaf800, const double& mf800, const double& gammakstarzero, const double& mkstarzero){ + double pars[7] = {qsquared, f800mag, f800phase, gammaf800, mf800, gammakstarzero, mkstarzero}; + ROOT::Math::GSLIntegrator gslint;//(1.0e-10, 1.0e-8, 10000); + gslint.SetFunction(gsl_mkpi_simple_kstarzero_amp_squared, pars); + return gslint.Integral(mkpia*mkpia, mkpib*mkpib); +} + +std::complex mkpi_simple_bw_kstar_amp_kstarzero_amp_bar(double mkpi, double qsquared, + double gammakstar, double mkstar, double asphase, + double f800mag, double f800phase, double gammaf800, double mf800, + double gammakstarzero, double mkstarzero){ + std::complex A = mkpi_simple_bw_kstar_amp(mkpi, qsquared, gammakstar, mkstar); + std::complex B = std::complex(cos(asphase),sin(asphase)) + *mkpi_simple_kstarzero_amp(mkpi, qsquared, f800mag, f800phase, gammaf800, mf800, gammakstarzero, mkstarzero); + return A*conj(B); +} + +std::complex mkpi_simple_bw_kstar_amp_bar_kstarzero_amp(double mkpi, double qsquared, + double gammakstar, double mkstar, double asphase, + double f800mag, double f800phase, double gammaf800, double mf800, + double gammakstarzero, double mkstarzero){ + std::complex A = mkpi_simple_bw_kstar_amp(mkpi, qsquared, gammakstar, mkstar); + std::complex B = std::complex(cos(asphase),sin(asphase)) + *mkpi_simple_kstarzero_amp(mkpi, qsquared, f800mag, f800phase, gammaf800, mf800, gammakstarzero, mkstarzero); + return conj(A)*B; +} + +std::complex int_mkpi_simple_bw_kstar_amp_kstarzero_amp_bar(const double& mkpia, const double& mkpib, const double& qsquared, + const double& gammakstar, const double& mkstar, const double& asphase, + const double& f800mag, const double& f800phase, + const double& gammaf800, const double& mf800, + const double& gammakstarzero, const double& mkstarzero){ + double pars[10] = {qsquared, gammakstar, mkstar, asphase, + f800mag, f800phase, gammaf800, mf800, gammakstarzero, mkstarzero}; + ROOT::Math::GSLIntegrator gslintre; + gslintre.SetFunction(gsl_mkpi_simple_re_bw_kstar_amp_kstarzero_amp_bar, pars); + double result_re = gslintre.Integral(mkpia, mkpib); + ROOT::Math::GSLIntegrator gslintim; + gslintim.SetFunction(gsl_mkpi_simple_im_bw_kstar_amp_kstarzero_amp_bar, pars); + double result_im = gslintim.Integral(mkpia, mkpib); + return std::complex(result_re, result_im); +} + +std::complex int_mkpi_simple_bw_kstar_amp_bar_kstarzero_amp(const double& mkpia, const double& mkpib, const double& qsquared, + const double& gammakstar, const double& mkstar, const double& asphase, + const double& f800mag, const double& f800phase, + const double& gammaf800, const double& mf800, + const double& gammakstarzero, const double& mkstarzero){ + double pars[10] = {qsquared, gammakstar, mkstar, asphase, + f800mag, f800phase, gammaf800, mf800, gammakstarzero, mkstarzero}; + //double pars[8] = {qsquared, gammakstar, mkstar, asphase, a, r, gammakstarzero, mkstarzero}; + ROOT::Math::GSLIntegrator gslintre; + gslintre.SetFunction(gsl_mkpi_simple_re_bw_kstar_amp_bar_kstarzero_amp, pars); + double result_re = gslintre.Integral(mkpia, mkpib); + ROOT::Math::GSLIntegrator gslintim; + gslintim.SetFunction(gsl_mkpi_simple_im_bw_kstar_amp_bar_kstarzero_amp, pars); + double result_im = gslintim.Integral(mkpia, mkpib); + return std::complex(result_re, result_im); +} + +//the kstar amplitude +std::complex mkpi_bw_kstar_amp(double mkpi, double qsquared, double gammakstar, double mkstar, double R){ + const double mk = PDGMASS_KST_KAON/1000.0; + const double mpi = PDGMASS_KST_PION/1000.0; + const double mb = PDGMASS_B/1000.0; + double p = daughtermom(mkpi, mk, mpi); + double pzero = daughtermom(mkstar, mk, mpi); + double k = daughtermom(mb, mkpi, sqrt(qsquared)); + double phsp = sqrt(k*p); + //double gamma = gammakstar*pow(p/pzero, 3.0)*mkstar/mkpi*sqrt((1.0+R*R*pzero*pzero)/(1.0+R*R*p*p));//nominal + double gamma = gammakstar*pow(p/pzero, 3.0)*mkstar/mkpi*((1.0+R*R*pzero*pzero)/(1.0+R*R*p*p));//squared??? !!! + std::complex bwamp = 1.0/std::complex(mkstar*mkstar-mkpi*mkpi,-mkstar*gamma); + //combine everything, eq 28-30 in LHCb-ANA-2013-053 + return phsp * bwamp + * sqrt((1.0+R*R*pzero*pzero)/(1.0+R*R*p*p)) + * p/mkstar; +} + +double mkpi_bw_kstar_amp_squared(double mkpi, double qsquared, double gammakstar, double mkstar, double R){ + std::complex result = mkpi_bw_kstar_amp(mkpi, qsquared, gammakstar, mkstar, R); + return norm(result); +} + +double mkpi_kstarzero_lass_amp_squared(double mkpi, double qsquared, double asphase, double a, double r, double gammakstarzero, double mkstarzero, double R){ + std::complex result = mkpi_kstarzero_lass_amp(mkpi, qsquared, asphase, a, r, gammakstarzero, mkstarzero, R); + return norm(result); +} + +//the combined s-wave amplitude +std::complex mkpi_kstarzero_lass_amp(double mkpi, double qsquared, double asphase, double a, double r, double gammakstarzero, double mkstarzero, double R){ + const double mk = PDGMASS_KST_KAON/1000.0; + const double mpi = PDGMASS_KST_PION/1000.0; + const double mb = PDGMASS_B/1000.0; + double p = daughtermom(mkpi, mk, mpi); + double pzero = daughtermom(mkstarzero, mk, mpi); + double k = daughtermom(mb, mkpi, sqrt(qsquared)); + double kzero = daughtermom(mb, mkstarzero, sqrt(qsquared)); + double phsp = sqrt(k*p); + // const double R = 1.6;//[GeV^-1] from Belle, see Z paper LHCb-ANA-2013-053 + //as amplitude + double asmag = 1.0; + std::complex as(asmag*cos(asphase),asmag*sin(asphase)); + //LASS shape + double cotdeltaB = 1.0/(a*p) + 0.5*r*p; + double deltaB = atan(1.0/cotdeltaB); + double gamma = gammakstarzero*p/pzero*mkstarzero/mkpi; + double cotdeltaR = (mkstarzero*mkstarzero - mkpi*mkpi)/(mkstarzero*gamma); + std::complex A = 1.0/std::complex(cotdeltaB, -1.0); + std::complex B = 1.0/std::complex(cotdeltaR, -1.0); + std::complex factor(cos(2.0*deltaB),sin(2.0*deltaB)); + std::complex lass = A+factor*B; + //combine everything, eq 52-53 in LHCb-ANA-2013-053 + return phsp * as * lass + //* mkpi/p ///David: this is not derivable from given formulas, but somehow appears in eq 52 of LHCb-ANA-2013-053 + * k/mb + * sqrt((1.0+R*R*kzero*kzero)/(1.0+R*R*k*k)); +} + + +std::complex mkpi_kstarzero_isobar_amp(double mkpi, double qsquared, double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero, double R){ + const double mk = PDGMASS_KST_KAON/1000.0; + const double mpi = PDGMASS_KST_PION/1000.0; + const double mb = PDGMASS_B/1000.0; + //const double R = 1.6;//[GeV^-1] from Belle, see Z paper LHCb-ANA-2013-053 + + double p = daughtermom(mkpi, mk, mpi); + double pzero = daughtermom(mf800, mk, mpi); + double k = daughtermom(mb, mkpi, sqrt(qsquared)); + double kzero = daughtermom(mb, mf800, sqrt(qsquared)); + double phsp = sqrt(k*p); + double gamma = gammaf800*pow(p/pzero, 1.0)*mf800/mkpi; + std::complex f800amp = + phsp + *k/mb*sqrt((1.0+R*R*kzero*kzero)/(1.0+R*R*k*k)) + *1.0/std::complex(mf800*mf800-mkpi*mkpi,-mf800*gamma); + + p = daughtermom(mkpi, mk, mpi); + pzero = daughtermom(mkstarzero, mk, mpi); + k = daughtermom(mb, mkpi, sqrt(qsquared)); + kzero = daughtermom(mb, mkstarzero, sqrt(qsquared)); + phsp = sqrt(k*p); + gamma = gammakstarzero*pow(p/pzero, 1.0)*mkstarzero/mkpi; + std::complex kstarzeroamp = + phsp + *k/mb*sqrt((1.0+R*R*kzero*kzero)/(1.0+R*R*k*k)) + *1.0/std::complex(mkstarzero*mkstarzero-mkpi*mkpi,-mkstarzero*gamma); + + return f800mag*std::complex(cos(f800phase),sin(f800phase))*f800amp + (1.0-f800mag)*kstarzeroamp; +} + +double mkpi_kstarzero_isobar_amp_squared(double mkpi, double qsquared, double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero, double R){ + std::complex result = mkpi_kstarzero_isobar_amp(mkpi, qsquared, f800mag, f800phase, gammaf800, mf800, gammakstarzero, mkstarzero, R); + return norm(result); +} + + +std::complex mkpi_bw_kstar_amp_kstarzero_isobar_amp_bar(double mkpi, double qsquared, + double gammakstar, double mkstar, double asphase, + double f800mag, double f800phase, + double gammaf800, double mf800, + double gammakstarzero, double mkstarzero, double R){ + std::complex A = mkpi_bw_kstar_amp(mkpi, qsquared, gammakstar, mkstar, R); + std::complex B = std::complex(cos(asphase),sin(asphase)) + *mkpi_kstarzero_isobar_amp(mkpi, qsquared, f800mag, f800phase, gammaf800, mf800, gammakstarzero, mkstarzero, R); + return A*conj(B); +} + +std::complex mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(double mkpi, double qsquared, + double gammakstar, double mkstar, double asphase, + double f800mag, double f800phase, + double gammaf800, double mf800, + double gammakstarzero, double mkstarzero, double R){ + std::complex A = mkpi_bw_kstar_amp(mkpi, qsquared, gammakstar, mkstar, R); + std::complex B = std::complex(cos(asphase),sin(asphase)) + *mkpi_kstarzero_isobar_amp(mkpi, qsquared, f800mag, f800phase, gammaf800, mf800, gammakstarzero, mkstarzero, R); + return conj(A)*B; +} + +std::complex mkpi_bw_kstar_amp_kstarzero_lass_amp_bar(double mkpi, double qsquared, + double gammakstar, double mkstar, + double asphase, double a, double r, + double gammakstarzero, double mkstarzero, double R){ + std::complex A = mkpi_bw_kstar_amp(mkpi, qsquared, gammakstar, mkstar, R); + std::complex B = mkpi_kstarzero_lass_amp(mkpi, qsquared, asphase, a, r, gammakstarzero, mkstarzero, R); + return A*conj(B); +} + +std::complex mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(double mkpi, double qsquared, + double gammakstar, double mkstar, + double asphase, double a, double r, + double gammakstarzero, double mkstarzero, double R){ + std::complex A = mkpi_bw_kstar_amp(mkpi, qsquared, gammakstar, mkstar, R); + std::complex B = mkpi_kstarzero_lass_amp(mkpi, qsquared, asphase, a, r, gammakstarzero, mkstarzero, R); + return conj(A)*B; +} + +double gsl_mkpi_bw_kstar_amp_squared(double x, void* par){ + double* v = (double*)par; + return mkpi_bw_kstar_amp_squared(x, v[0], v[1], v[2], v[3]); +} + +double gsl_mkpi_kstarzero_lass_amp_squared(double x, void* par){ + double* v = (double*)par; + return mkpi_kstarzero_lass_amp_squared(x, v[0], v[1], v[2], v[3], v[4], v[5], v[6]); +} + +double gsl_mkpi_re_bw_kstar_amp_kstarzero_lass_amp_bar(double x, void* par){ + double* v = (double*)par; + std::complex result = mkpi_bw_kstar_amp_kstarzero_lass_amp_bar(x, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]); + return result.real(); +} + +double gsl_mkpi_im_bw_kstar_amp_kstarzero_lass_amp_bar(double x, void* par){ + double* v = (double*)par; + std::complex result = mkpi_bw_kstar_amp_kstarzero_lass_amp_bar(x, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]); + return result.imag(); +} + +double gsl_mkpi_re_bw_kstar_amp_bar_kstarzero_lass_amp(double x, void* par){ + double* v = (double*)par; + std::complex result = mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(x, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]); + return result.real(); +} + +double gsl_mkpi_im_bw_kstar_amp_bar_kstarzero_lass_amp(double x, void* par){ + double* v = (double*)par; + std::complex result = mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(x, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]); + return result.imag(); +} + +double gsl_mkpi_kstarzero_isobar_amp_squared(double x, void* par){ + double* v = (double*)par; + return mkpi_kstarzero_isobar_amp_squared(x, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]); +} + +double gsl_mkpi_re_bw_kstar_amp_kstarzero_isobar_amp_bar(double x, void* par){ + double* v = (double*)par; + std::complex result = mkpi_bw_kstar_amp_kstarzero_isobar_amp_bar(x, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10]); + return result.real(); +} + +double gsl_mkpi_im_bw_kstar_amp_kstarzero_isobar_amp_bar(double x, void* par){ + double* v = (double*)par; + std::complex result = mkpi_bw_kstar_amp_kstarzero_isobar_amp_bar(x, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10]); + return result.imag(); +} + +double gsl_mkpi_re_bw_kstar_amp_bar_kstarzero_isobar_amp(double x, void* par){ + double* v = (double*)par; + std::complex result = mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(x, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10]); + return result.real(); +} + +double gsl_mkpi_im_bw_kstar_amp_bar_kstarzero_isobar_amp(double x, void* par){ + double* v = (double*)par; + std::complex result = mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(x, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9], v[10]); + return result.imag(); +} + +double int_mkpi_bw_kstar_amp_squared(double mkpia, double mkpib, double qsquared, double gammakstar, + double mkstar, double R){ + double pars[4] = {qsquared, gammakstar, mkstar, R}; + ROOT::Math::GSLIntegrator gslint; + gslint.SetFunction(gsl_mkpi_bw_kstar_amp_squared, pars); + return gslint.Integral(mkpia, mkpib); +} + +double int_mkpi_bw_kstar_amp_squared(double qsquared, double gammakstar, double mkstar, double R){ + double pars[4] = {qsquared, gammakstar, mkstar, R}; + ROOT::Math::GSLIntegrator gslint;//(1.0e-9, 1.0e-8, 100000); + gslint.SetFunction(gsl_mkpi_bw_kstar_amp_squared, pars); + return gslint.Integral(); +} + +double int_mkpi_kstarzero_lass_amp_squared(double mkpia, double mkpib, double qsquared, double asphase, double a, double r, double gammakstarzero, double mkstarzero, double R) +{ + double pars[7] = {qsquared, asphase, a, r, gammakstarzero, mkstarzero, R}; + ROOT::Math::GSLIntegrator gslint; + gslint.SetFunction(gsl_mkpi_kstarzero_lass_amp_squared, pars); + return gslint.Integral(mkpia, mkpib); +} + +double int_mkpi_kstarzero_lass_amp_squared(double qsquared, double asphase, double a, double r, double gammakstarzero, double mkstarzero, double R) +{ + double pars[7] = {qsquared, asphase, a, r, gammakstarzero, mkstarzero, R}; + ROOT::Math::GSLIntegrator gslint;//(1.0e-9, 1.0e-8, 100000); + gslint.SetFunction(gsl_mkpi_kstarzero_lass_amp_squared, pars); + return gslint.Integral(); +} + +double int_mkpi_kstarzero_isobar_amp_squared(double mkpia, double mkpib, double qsquared, double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero, double R) +{ + double pars[8] = {qsquared, f800mag, f800phase, gammaf800, mf800, gammakstarzero, mkstarzero, R}; + ROOT::Math::GSLIntegrator gslint; + gslint.SetFunction(gsl_mkpi_kstarzero_isobar_amp_squared, pars); + return gslint.Integral(mkpia, mkpib); +} + +double int_mkpi_kstarzero_isobar_amp_squared(double qsquared, double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero, double R) +{ + double pars[8] = {qsquared, f800mag, f800phase, gammaf800, mf800, gammakstarzero, mkstarzero, R}; + ROOT::Math::GSLIntegrator gslint;//(1.0e-9, 1.0e-8, 100000); + gslint.SetFunction(gsl_mkpi_kstarzero_isobar_amp_squared, pars); + return gslint.Integral(); +} + +std::complex int_mkpi_bw_kstar_amp_kstarzero_lass_amp_bar(double mkpia, double mkpib, double qsquared, double gammakstar, double mkstar, double asphase, double a, double r, double gammakstarzero, double mkstarzero, double R) +{ + double pars[9] = {qsquared, gammakstar, mkstar, asphase, a, r, gammakstarzero, mkstarzero, R}; + ROOT::Math::GSLIntegrator gslintre; + gslintre.SetFunction(gsl_mkpi_re_bw_kstar_amp_kstarzero_lass_amp_bar, pars); + double result_re = gslintre.Integral(mkpia, mkpib); + ROOT::Math::GSLIntegrator gslintim; + gslintim.SetFunction(gsl_mkpi_im_bw_kstar_amp_kstarzero_lass_amp_bar, pars); + double result_im = gslintim.Integral(mkpia, mkpib); + return std::complex(result_re, result_im); +} + +std::complex int_mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(double mkpia, double mkpib, double qsquared, double gammakstar, double mkstar, double asphase, double a, double r, double gammakstarzero, double mkstarzero, double R) +{ + double pars[9] = {qsquared, gammakstar, mkstar, asphase, a, r, gammakstarzero, mkstarzero, R}; + ROOT::Math::GSLIntegrator gslintre; + gslintre.SetFunction(gsl_mkpi_re_bw_kstar_amp_bar_kstarzero_lass_amp, pars); + double result_re = gslintre.Integral(mkpia, mkpib); + ROOT::Math::GSLIntegrator gslintim; + gslintim.SetFunction(gsl_mkpi_im_bw_kstar_amp_bar_kstarzero_lass_amp, pars); + double result_im = gslintim.Integral(mkpia, mkpib); + return std::complex(result_re, result_im); +} + + +std::complex int_mkpi_bw_kstar_amp_kstarzero_lass_amp_bar(double qsquared, double gammakstar, double mkstar, double asphase, double a, double r, double gammakstarzero, double mkstarzero, double R) +{ + double pars[9] = {qsquared, gammakstar, mkstar, asphase, a, r, gammakstarzero, mkstarzero, R}; + ROOT::Math::GSLIntegrator gslintre;//(1.0e-9, 1.0e-8, 100000); + gslintre.SetFunction(gsl_mkpi_re_bw_kstar_amp_kstarzero_lass_amp_bar, pars); + double result_re = gslintre.Integral();//mkpisquareda, mkpisquaredb); + ROOT::Math::GSLIntegrator gslintim;//(1.0e-9, 1.0e-8, 100000); + gslintim.SetFunction(gsl_mkpi_im_bw_kstar_amp_kstarzero_lass_amp_bar, pars); + double result_im = gslintim.Integral();//mkpisquareda, mkpisquaredb); + return std::complex(result_re, result_im); +} + +std::complex int_mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(double qsquared, double gammakstar, double mkstar, double asphase, double a, double r, double gammakstarzero, double mkstarzero, double R) +{ + double pars[9] = {qsquared, gammakstar, mkstar, asphase, a, r, gammakstarzero, mkstarzero, R}; + ROOT::Math::GSLIntegrator gslintre;//(1.0e-9, 1.0e-8, 100000); + gslintre.SetFunction(gsl_mkpi_re_bw_kstar_amp_bar_kstarzero_lass_amp, pars); + double result_re = gslintre.Integral();//mkpisquareda, mkpisquaredb); + ROOT::Math::GSLIntegrator gslintim;//(1.0e-9, 1.0e-8, 100000); + gslintim.SetFunction(gsl_mkpi_im_bw_kstar_amp_bar_kstarzero_lass_amp, pars); + double result_im = gslintim.Integral();//mkpisquareda, mkpisquaredb); + return std::complex(result_re, result_im); +} + +/////////////// +std::complex int_mkpi_bw_kstar_amp_kstarzero_isobar_amp_bar(double mkpia, double mkpib, double qsquared, + double gammakstar, double mkstar, double asphase, + double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero, double R) +{ + double pars[11] = {qsquared, gammakstar, mkstar, asphase, + f800mag, f800phase, gammaf800, mf800, gammakstarzero, mkstarzero, R}; + ROOT::Math::GSLIntegrator gslintre; + gslintre.SetFunction(gsl_mkpi_re_bw_kstar_amp_kstarzero_isobar_amp_bar, pars); + double result_re = gslintre.Integral(mkpia, mkpib); + ROOT::Math::GSLIntegrator gslintim; + gslintim.SetFunction(gsl_mkpi_im_bw_kstar_amp_kstarzero_isobar_amp_bar, pars); + double result_im = gslintim.Integral(mkpia, mkpib); + return std::complex(result_re, result_im); +} + +std::complex int_mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(double mkpia, double mkpib, double qsquared, + double gammakstar, double mkstar, double asphase, + double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero, double R) +{ + double pars[11] = {qsquared, gammakstar, mkstar, asphase, + f800mag, f800phase, gammaf800, mf800, gammakstarzero, mkstarzero, R}; + //double pars[8] = {qsquared, gammakstar, mkstar, asphase, a, r, gammakstarzero, mkstarzero}; + ROOT::Math::GSLIntegrator gslintre; + gslintre.SetFunction(gsl_mkpi_re_bw_kstar_amp_bar_kstarzero_isobar_amp, pars); + double result_re = gslintre.Integral(mkpia, mkpib); + ROOT::Math::GSLIntegrator gslintim; + gslintim.SetFunction(gsl_mkpi_im_bw_kstar_amp_bar_kstarzero_isobar_amp, pars); + double result_im = gslintim.Integral(mkpia, mkpib); + return std::complex(result_re, result_im); +} + + +std::complex int_mkpi_bw_kstar_amp_kstarzero_isobar_amp_bar(double qsquared, + double gammakstar, double mkstar, double asphase, + double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero, double R) +{ + double pars[11] = {qsquared, gammakstar, mkstar, asphase, + f800mag, f800phase, gammaf800, mf800, gammakstarzero, mkstarzero, R}; + //double pars[8] = {qsquared, gammakstar, mkstar, asphase, a, r, gammakstarzero, mkstarzero}; + ROOT::Math::GSLIntegrator gslintre;//(1.0e-9, 1.0e-8, 100000); + gslintre.SetFunction(gsl_mkpi_re_bw_kstar_amp_kstarzero_isobar_amp_bar, pars); + double result_re = gslintre.Integral();//mkpisquareda, mkpisquaredb); + ROOT::Math::GSLIntegrator gslintim;//(1.0e-9, 1.0e-8, 100000); + gslintim.SetFunction(gsl_mkpi_im_bw_kstar_amp_kstarzero_isobar_amp_bar, pars); + double result_im = gslintim.Integral();//mkpisquareda, mkpisquaredb); + return std::complex(result_re, result_im); +} + +std::complex int_mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(double qsquared, + double gammakstar, double mkstar, double asphase, + double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero, double R) +{ + double pars[11] = {qsquared, gammakstar, mkstar, asphase, + f800mag, f800phase, gammaf800, mf800, gammakstarzero, mkstarzero, R}; + ROOT::Math::GSLIntegrator gslintre;//(1.0e-9, 1.0e-8, 100000); + gslintre.SetFunction(gsl_mkpi_re_bw_kstar_amp_bar_kstarzero_isobar_amp, pars); + double result_re = gslintre.Integral();//mkpisquareda, mkpisquaredb); + ROOT::Math::GSLIntegrator gslintim;//(1.0e-9, 1.0e-8, 100000); + gslintim.SetFunction(gsl_mkpi_im_bw_kstar_amp_bar_kstarzero_isobar_amp, pars); + double result_im = gslintim.Integral();//mkpisquareda, mkpisquaredb); + return std::complex(result_re, result_im); +} + +void moments_to_observables(TRandom3* rnd, + std::vector mom, + std::vector momcov, + double fsext, + double dfsext, + std::vector& obs, + std::vector& obscov, + bool usefsext + ){ + + assert(mom.size() == 18); + assert(momcov.size() == 18*18); + + if(spdlog_debug()){ + std::cout << std::setw(10) << std::setprecision(6); + for(UInt_t j = 0; j < 18; j++){ + for(UInt_t k = 0; k < 18; k++){ + std::cout << momcov.at(j*18+k); + } + std::cout << std::endl; + } + } + + //without s-waves, the matrix only comprises of 12 elements: + bool swave = true; + if(momcov.at(12) == 0.0 && momcov.at(13) == 0.0 && momcov.at(14) == 0.0 && momcov.at(15) == 0.0 && momcov.at(16) == 0.0 && momcov.at(17) == 0.0){ + swave = false; + } + spdlog::info("[MoM]\tSwave is "+std::string(swave ? "ON" : "OFF")+"!"); + const UInt_t N = swave ? 18 : 12; + + //convert 18x18 matrix to 12x12 matrix + if(!swave){ + std::vector momcov_tmp; + for(UInt_t i = 0; i < 12; i++){ + for(UInt_t j = 0; j < 12; j++){ + momcov_tmp.push_back(momcov.at(i*18+j)); + } + } + momcov.clear(); + momcov = momcov_tmp; + } + + assert(momcov.size() == N*N); + + //all off-diagonal matrix elements for S1c, S2s, S2c are forced to zero + //all digaonal covariant elements are set equal to the one of S1s + for (unsigned int i=0; i > randomizedobs; + for (unsigned int l=0; l rndobs(N, 0.0); + + //generate 10000 random moments according to covariance matrix + //rndm gaussian(0,1) vector + std::vector rndvec(N, 0.0); + for (unsigned int i=0;iGaus(0.0, 1.0); + } + + //random gaussian vector times upper triangular matrix + std::vector murndvec(N, 0.0); + for (unsigned int i=0; i result(N, 0.0); + for (unsigned int i=0; i(N, 0.0); + double j6c = 0.0; + double pi = TMath::Pi(); + + bool useLinearCombinationForS1s = false; + bool useLinearCombinationForS6s = true; + + if(swave){ + + double fl = (80.0*pi*result.at(0)+80.0*pi*result.at(12)-27.0)/(80.0*pi*result.at(0)+240.0*pi*result.at(12)-51.0); + double fs = (80.0*pi*result.at(0)+240.0*pi*result.at(12)-45.0)/6.0; + if (usefsext){ + fs = fsext+rnd->Gaus(0.0,dfsext); + } + rndobs.at(0) = 3.0/4.0*(1.0-fl); //S_1s + rndobs.at(1) = 0.0; //S_1c + rndobs.at(2) = 0.0; //S_2s + rndobs.at(3) = 0.0; //S_2c + rndobs.at(4) = -100.0*pi*result.at(4)/(9.0*fs-9.0); //S_3 + rndobs.at(5) = -100.0*pi*result.at(5)/(9.0*fs-9.0); //S_4 + rndobs.at(6) = -80*pi*result.at(6)/(9.0*fs-9.0); //S_5 + if(useLinearCombinationForS6s){ + rndobs.at(7) = -32.0*pi*(3.0*result.at(7) - 2.0*result.at(8))/(9.0*fs-9.0); //S_6s + rndobs.at(8) = -32.0*pi*(8.0*result.at(8) - 2.0*result.at(7))/(9.0*fs-9.0); //S_6c + } + else{ + rndobs.at(7) = -(9.0*j6c*fs+320.0*pi*result.at(7)-9*j6c)/(36.0*fs-36.0); //S_6s + double j6s = rndobs.at(7); + rndobs.at(8) = -(18.0*j6s*fs+640.0*pi*result.at(8)-18.0*j6s)/(27.0*fs-27.0); //S_6c + //no strange usage of S_6c: + rndobs.at(7) = -80.0*pi*result.at(7)/(9.0*fs-9.0); //S_6s + rndobs.at(8) = 0.0; //S_6c + } + rndobs.at(9) = -80.0*pi*result.at(9)/(9.0*fs-9.0);//S_7 + rndobs.at(10) = -100.0*pi*result.at(10)/(9.0*fs-9.0);//S_8 + rndobs.at(11) = -100.0*pi*result.at(11)/(9.0*fs-9.0);//S_9 + rndobs.at(12) = fs;//rnd->Gaus(); + rndobs.at(13) = 20.0*pi*result.at(13);//S_S1 + rndobs.at(14) = 20.0*pi*result.at(14);//S_S2 + rndobs.at(15) = 16.0*pi*result.at(15);//S_S3 + rndobs.at(16) = 16.0*pi*result.at(16);//S_S4 + rndobs.at(17) = 20.0*pi*result.at(17);//S_S5 + } + else{ + if(useLinearCombinationForS1s){ + rndobs.at(0) = 32.0/9.0*pi*(21.0/16.0*result.at(0)-7.0/8.0*result.at(1)+1125.0/1184.0*result.at(2)-25.0/37.0*result.at(3)); //David recalculation + } + else{ + rndobs.at(0) = 15.0/8.0*(32.0/9.0*pi*result.at(0) - 2.0/5.0); //Thommis thesis + } + rndobs.at(1) = 0.0; //S_1c + rndobs.at(2) = 0.0; //S_2s + rndobs.at(3) = 0.0; //S_2c + rndobs.at(4) = 100.0/9.0*pi*result.at(4); //S_3 + rndobs.at(5) = 100.0/9.0*pi*result.at(5); //S_4 + rndobs.at(6) = 80.0/9.0*pi*result.at(6); //S_5 + if(useLinearCombinationForS6s){ + rndobs.at(7) = 32.0/9.0*pi*(3.0*result.at(7) - 2.0*result.at(8)); //S_6s + rndobs.at(8) = 32.0/9.0*pi*(8.0*result.at(8) - 2.0*result.at(7)); //S_6c + } + else{ + rndobs.at(7) = 80.0/9.0*pi*result.at(7); + rndobs.at(8) = 0.0; + } + rndobs.at(9) = 80.0/9.0*pi*result.at(9); //S_7 + rndobs.at(10) = 100.0/9.0*pi*result.at(10); //S_8 + rndobs.at(11) = 100.0/9.0*pi*result.at(11); //S_9 + } + randomizedobs.push_back(rndobs); + } + std::vector res(18,0.0); + std::vector rescov(18*18,0.0); + + //determine mean value of moments M_i + for (unsigned int i=0; i xi, std::vector cov, std::vector > results) +int throw_multivariate_normal(const unsigned int ndim, const unsigned int ntoys, const std::vector& xi, const std::vector& cov, std::vector >& results){ + assert(xi.size() == ndim); + assert(cov.size() == ndim*ndim); + results.clear(); + TRandom3* rnd = new TRandom3(); + + TMatrixDSym cov_sym(ndim, &cov[0]); + TDecompChol chol(cov_sym); + bool success = chol.Decompose(); + + assert(success); + TMatrixD mU = chol.GetU();//gets upper triangular matrix + + for (unsigned int l=0;l result(ndim, 0.0); + + std::vector rndvec(ndim, 0.0); + for (unsigned int i=0;iGaus(0.0, 1.0); + } + //random gaussian vector times upper triangular matrix + std::vector murndvec(ndim, 0.0); + for (unsigned int i=0; i >& meas, std::vector& mean, std::vector& cov){ + assert(meas.size() > 0); + unsigned int ndim = meas.at(0).size(); + unsigned int ntoys = meas.size(); + + std::vector m(ndim, 0.0); + + for (unsigned int l=0; l c(ndim*ndim, 0.0); + for (unsigned int l=0; l sis, + std::vector sicov, + std::vector& pis, + std::vector& picov){ + assert(sis.size()==8); + assert(sicov.size()==8*8); + + //cholesky decomposition of covariance matrix + TMatrixDSym cov_sym(8, &sicov[0]); + TDecompChol chol(cov_sym); + bool success = chol.Decompose(); + assert(success); + TMatrixD mU = chol.GetU();//gets upper triangular matrix + //decomposition check + //determine mean and rms (or rather confidence interval) from toys according to cov matrix + unsigned int nruns = 50000; + std::vector > randomizedpis; + for (unsigned int l=0; l rndvec(8, 0.0); + for (unsigned int i=0;i<8;i++){ + rndvec.at(i) = rnd->Gaus(0.0, 1.0); + } + //random gaussian vector times upper triangular matrix + std::vector murndvec(8, 0.0); + for (unsigned int i=0; i<8; i++){ + for (unsigned int j=0; j<8; j++){ + murndvec.at(i) += mU(j,i)*rndvec.at(j); + } + } + //new random vector + std::vector result(8, 0.0); + for (unsigned int i=0; i<8; i++){ + result.at(i) = sis.at(i) + murndvec.at(i); + } + //now get observables + //rndpi = std::vector(8, 0.0); + std::vector rndpi(8, 0.0); + + double fl = result.at(0); + double ft = 1.0-fl; + double s3 = result.at(1); + double s4 = result.at(2); + double s5 = result.at(3); + double afb = result.at(4); + double s7 = result.at(5); + double s8 = result.at(6); + double s9 = result.at(7); + + rndpi.at(0) = fl;//fl + rndpi.at(1) = 2.0*s3/(1.0-fl);//p1 + rndpi.at(2) = 0.5*4.0/3.0*afb/(1.0-fl);//p2 + rndpi.at(3) = -s9/(1-fl);//p3 + rndpi.at(4) = s4/sqrt(fl*ft);//p4 + rndpi.at(5) = s5/sqrt(fl*ft);//p5 + rndpi.at(6) = s7/sqrt(fl*ft);//p6 + rndpi.at(7) = s8/sqrt(fl*ft);//p8 + + randomizedpis.push_back(rndpi); + } + std::vector res(8,0.0); + std::vector rescov(8*8,0.0); + for (unsigned int i=0; iGaus(mean, width); + if (r > min && r < max) finished = true; + } + return r; +} + +double rndgauss(TRandom3* rnd, double mean, double widthlo, double widthhi, double min, double max) +{ + double r = 0.0; + bool finished = false; + bool lo = rnd->Rndm() < 0.5; + while (!finished){ + if (lo) r = mean - fabs(rnd->Gaus(0.0, widthlo)); + else r = mean + fabs(rnd->Gaus(0.0, widthhi)); + + if (r > min && r < max) finished = true; + } + return r; +} + +std::vector GetNOutOfM(UInt_t N, UInt_t M, Int_t Seed, bool DoubleCounts, bool PoissonFluctuate){ + + TRandom3 * R = new TRandom3(Seed); + + if(PoissonFluctuate) N = TMath::Abs(R->Poisson(N)); + + std::vector v; + + if(DoubleCounts){ + while(v.size() < N){ + UInt_t I = R->Integer(M); + v.push_back(I); + } + } + else{ + assert(M > N); + if(N <= M / 2){ //for small N get white list of Integers + while(v.size() < N){ + UInt_t I = R->Integer(M); + bool AlreadyChosen = false; + for(UInt_t i = 0; i < v.size(); i++){ + if(I == v.at(i)){ + AlreadyChosen = true; + break; + } + } + if(!AlreadyChosen){ + v.push_back(I); + } + } + } + else{ //large N: get black list and remove those numbers + for(UInt_t i = 0; i < M; i++){ + v.push_back(i); + } + while(v.size() > N){ + UInt_t I = R->Integer(M); + for(UInt_t i = 0; i < v.size(); i++){ + if(I == v.at(i)){ + v.erase(v.begin()+i); + break; + } + } + } + } + } + + assert(v.size() == N); + + return v; + +} + + +} diff --git a/Code/FCNCFitter/sources/Core/funcs.hh b/Code/FCNCFitter/sources/Core/funcs.hh new file mode 100755 index 0000000..2c5a038 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/funcs.hh @@ -0,0 +1,307 @@ +/** + * @file funcs.hh + * @author Christoph Langenbruch, Renata Kopecna + * @date 2009-03-18 + * + */ + +#ifndef FUNCS_H +#define FUNCS_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fcnc { //Forward declaration, fully defined in options.hh + class options; + class event; +} + +namespace fcnc { + + typedef ROOT::Math::PxPyPzEVector LorentzVector; + typedef ROOT::Math::Boost LorentzBoost; + typedef ROOT::Math::DisplacementVector3D > Vector3; + + TMatrixDSym get_bsz_invcov(); + TMatrixDSym get_bsz_cov(); + TMatrixD get_bsz_mu_invcov(); + + double eff_paper(const double& q2, const double& ctl, const double& ctk, const double& phi); + + double get_sliding_error(double xmeas, double xth, double eup, double edown); + + double crystalball(double m, double mean, double sigma, double alpha, double n); + double twotailedcrystalball(double m, double mean, double sigma, double alpha1, double alpha2, double n1, double n2); + + //blinding + double evaluate_unblind_uniform(double valueSeenByAnalist, const char* blindingString, double scale); + double evaluate_unblind_uniform_angle(double valueSeenByAnalist, const char* blindingString, double scale); + + double sqr(double x); + //basic trigonometric functions + double costheta2(double costheta); + double cos2theta(double costheta); + double sintheta2(double costheta); + double sintheta_abs(double costheta); + double sin2theta(double costheta); + + + double chebyshev(double x, int n); + void chebyshev(double x, int n, std::vector& results); + void chebyshev_to_poly(const std::vector& chebychev, std::vector& poly); + void correct_poly(const std::vector& poly, std::vector& correct, double min, double max); + + double legendre(double x, int n); + void legendre(double x, int n, std::vector& results); + void orthonormal_legendre(double x, int n, std::vector& results); + void legendre_to_poly(const std::vector& legendre, std::vector& poly); + + ///calculates the associated legendre polynomial for l,m order + double assoc_legendre(unsigned int l, unsigned int m, double x); + ///calculates the real part of the spherical harmonics for l, m + double spherical_harmonic_re(unsigned int l, unsigned int m, double theta, double phi); + ///calculates the imaginary part of the spherical harmonics for l, m + double spherical_harmonic_im(unsigned int l, unsigned int m, double theta, double phi); + ///function calculates the angles in the transversity base using the momenta of the final state particles + void calculate_transversity_angles(const LorentzVector& mu_minus, + const LorentzVector& mu_plus, + const LorentzVector& k_minus, + const LorentzVector& k_plus, + double & cos_theta, double & angle_phi, double & cos_psi); + ///this function calculates the convolution sin(angle) from 0 to pi + double convoluted_sin(double angle, double sigma); + double convoluted_cos_sin(double angle, double sigma); + double convoluted_cos(double angle, double sigma);//not used + double convoluted_cos_2(double angle, double sigma);//not used + double convoluted_sin_2(double angle, double sigma);//used by s wave + double convoluted_2_sin(double angle, double sigma);//used by s wave + double convoluted_2_cos(double angle, double sigma);//not used + double convoluted_cos_2_sin(double angle, double sigma); + double convoluted_2_sin_sin(double angle, double sigma); + double convoluted_sin_3(double angle, double sigma); + //this integrates the above expressions (vonvolution before has been from 0 to pi + double int_convoluted_sin(double angle, double sigma); + double int_convoluted_cos_sin(double angle, double sigma); + double int_convoluted_cos_2_sin(double angle, double sigma); + double int_convoluted_2_sin_sin(double angle, double sigma); + double int_convoluted_sin_3(double angle, double sigma); + double int_convoluted_sin_2(double angle, double sigma);//used by s wave + double int_convoluted_2_sin(double angle, double sigma);//used by s wave + //convolutions for phi. this is easier due to the wraparound at +-pi -> convolution from -int to inf + double inf_convoluted_sin(double angle, double sigma); + double inf_convoluted_cos(double angle, double sigma); + double inf_convoluted_cos_2(double angle, double sigma); + double inf_convoluted_sin_2(double angle, double sigma); + double inf_convoluted_2_sin(double angle, double sigma); + //integral of above + double int_inf_convoluted_const(double angle, double sigma); + double int_inf_convoluted_sin(double angle, double sigma); + double int_inf_convoluted_cos(double angle, double sigma); + double int_inf_convoluted_cos_2(double angle, double sigma); + double int_inf_convoluted_sin_2(double angle, double sigma); + double int_inf_convoluted_2_sin(double angle, double sigma); + //integrals from -inf to inf over the convolution from 0 to pi with acceptance + double int_convoluted_sin_cos_n(int n, double sigma); + double int_convoluted_sin_3_cos_n(int n, double sigma); + double int_convoluted_cos_2_sin_cos_n(int n, double sigma); + double int_convoluted_2_sin_sin_cos_n(int n, double sigma); + double int_convoluted_cos_sin_cos_n(int n, double sigma); + double int_convoluted_sin_2_cos_n(int n, double sigma); + //integrals from 0 to pi over the convolution from -inf to inf with acceptance + double int_inf_convoluted_const_x_n(int n, double sigma); + double int_inf_convoluted_cos_2_x_n(int n, double sigma); + double int_inf_convoluted_sin_2_x_n(int n, double sigma); + double int_inf_convoluted_sin_x_n(int n, double sigma); + double int_inf_convoluted_2_sin_x_n(int n, double sigma); + double int_inf_convoluted_cos_x_n(int n, double sigma); + + + ///function gives the result of exp(-ct/tau)*sin(delta_m*ct) and exp(-ct/tau)*cos(delta_m*ct) convoluted with a gaussian with width sigma + void convoluted_exp_sincos(double ct, double sigma, double tau, double deltam, double& one, double& two); + ///function gives the norm of the expression exp(-ct/tau)*sin(delta_m*ct) and exp(-ct/tau)*cos(delta_m*ct) convoluted with a gaussian with width sigma + void norm_convoluted_exp_sincos(double tau, double deltam, double& one, double& two); + ///function calculates exp(-ct/tau) convoluted with a gaussian with width sigma + double convoluted_exp(double ct, double sigma_ct, double S); + ///function calculates exp(-ct/tau) depending on the parameters normalized or not + double expdecay(double t, double tau, bool normalized); + ///function calculates 1/(sqrt(2*pi)*exp(-(x-mean)^2/(2*sigma^2))) + double gauss(double x, double sigma, double mean); + ///function calculates a normed gaussian between the values min and max used in the mass pdfs + double normed_gauss(double x, double sigma, double mean, double min, double max); + ///integrate gauss from a to b + double linear(double x, double min, double max, double slope); + ///very important helper function, the error function with complex argument. This is probably one of the performance bottlenecks. Probably much faster with a lookup table and interpolation + + double threshold(double x, double thr, double n); + double int_threshold(double a, double b, double thr, double n); + + + //see arxiv 1207.4004 + /* + std::complex bw_kstar_amp(double mkpi_squared, double gammakstar, double mkstar); + std::complex bw_kstarzero_amp(double mkpisquared, double gk_re, double gk_im, double gammak, double mk, double gammakstarzero, double mkstarzero); + double bw_kstar_amp_squared(double mkpisquared, double gammakstar, double mkstar); + std::complex bw_kstar_amp_kstarzero_amp_bar(double mkpisquared, double gammakstar, double mkstar, double gk_re, double gk_im, double gammak, double mk, double gammakstarzero, double mkstarzero); + double bw_kstarzero_amp_squared(double mkpisquared, double gk_re, double gk_im, double gammak, double mk, double gammakstarzero, double mkstarzero); + */ + double daughtermom(double m, double m1, double m2); + std::complex mkpi_simple_bw_kstar_amp(double mkpi, double qsquared, double gammakstar, double mkstar); + double mkpi_simple_bw_kstar_amp_squared(double mkpi, double qsquared, double gammakstar, double mkstar); + double gsl_mkpi_simple_bw_kstar_amp_squared(double x, void* par); + double int_mkpi_simple_bw_kstar_amp_squared(const double& mkpia, const double& mkpib, const double& qsquared, const double& gammakstar, const double& mkstar); + + std::complex mkpi_simple_kstarzero_amp(double mkpi, double qsquared, double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero); + double mkpi_simple_kstarzero_amp_squared(double mkpi, double qsquared, double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero); + double gsl_mkpi_simple_kstarzero_amp_squared(double x, void* par); + double int_mkpi_simple_kstarzero_amp_squared(const double& mkpia, const double& mkpib, const double& qsquared, const double& f800mag, const double& f800phase, const double& gammaf800, const double& mf800, const double& gammakstarzero, const double& mkstarzero); + + std::complex mkpi_simple_bw_kstar_amp_kstarzero_amp_bar(double mkpi, double qsquared, + double gammakstar, double mkstar, double asphase, + double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero); + std::complex mkpi_simple_bw_kstar_amp_bar_kstarzero_amp(double mkpi, double qsquared, + double gammakstar, double mkstar, double asphase, + double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero); + + std::complex int_mkpi_simple_bw_kstar_amp_kstarzero_amp_bar(const double& mkpia, const double& mkpib, const double& qsquared, + const double& gammakstar, const double& mkstar, const double& asphase, + const double& f800mag, const double& f800phase, const double& gammaf800, const double& mf800, const double& gammakstarzero, const double& mkstarzero); + std::complex int_mkpi_simple_bw_kstar_amp_bar_kstarzero_amp(const double& mkpia, const double& mkpib, const double& qsquared, + const double& gammakstar, const double& mkstar, const double& asphase, + const double& f800mag, const double& f800phase, const double& gammaf800, const double& mf800, const double& gammakstarzero, const double& mkstarzero); + + double gsl_mkpi_simple_re_bw_kstar_amp_kstarzero_amp_bar(double x, void* par); + double gsl_mkpi_simple_im_bw_kstar_amp_kstarzero_amp_bar(double x, void* par); + double gsl_mkpi_simple_re_bw_kstar_amp_bar_kstarzero_amp(double x, void* par); + double gsl_mkpi_simple_im_bw_kstar_amp_bar_kstarzero_amp(double x, void* par); + + + std::complex mkpi_bw_kstar_amp(double mkpi, double qsquared, double gammakstar, double mkstar, double R); + std::complex mkpi_kstarzero_lass_amp(double mkpi, double qsquared, double asphase, double a, double r, double gammakstarzero, double mkstarzero, double R); + std::complex mkpi_bw_kstar_amp_kstarzero_lass_amp_bar(double mkpi, double qsquared, double gammakstar, double mkstar, double asphase, double a, double r, double gammakstarzero, double mkstarzero, double R); + std::complex mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(double mkpi, double qsquared, double gammakstar, double mkstar, double asphase, double a, double r, double gammakstarzero, double mkstarzero, double R); + double mkpi_bw_kstar_amp_squared(double mkpi, double qsquared, double gammakstar, double mkstar, double R); + double mkpi_kstarzero_lass_amp_squared(double mkpi, double qsquared, double asphase, double a, double r, double gammakstarzero, double mkstarzero, double R); + + std::complex mkpi_kstarzero_isobar_amp(double mkpi, double qsquared, double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero, double R); + double mkpi_kstarzero_isobar_amp_squared(double mkpi, double qsquared, double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero, double R); + std::complex mkpi_bw_kstar_amp_kstarzero_isobar_amp_bar(double mkpi, double qsquared, + double gammakstar, double mkstar, double asphase, + double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero, double R); + std::complex mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(double mkpi, double qsquared, + double gammakstar, double mkstar, double asphase, + double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero, double R); + double gsl_mkpi_kstarzero_isobar_amp_squared(double x, void* par); + double gsl_mkpi_re_bw_kstar_amp_kstarzero_isobar_amp_bar(double x, void* par); + double gsl_mkpi_im_bw_kstar_amp_kstarzero_isobar_amp_bar(double x, void* par); + double gsl_mkpi_re_bw_kstar_amp_bar_kstarzero_isobar_amp(double x, void* par); + double gsl_mkpi_im_bw_kstar_amp_bar_kstarzero_isobar_amp(double x, void* par); + + double gsl_mkpi_bw_kstar_amp_squared(double x, void* par); + double gsl_mkpi_kstarzero_lass_amp_squared(double x, void* par); + double gsl_mkpi_re_bw_kstar_amp_kstarzero_lass_amp_bar(double x, void* par); + double gsl_mkpi_im_bw_kstar_amp_kstarzero_lass_amp_bar(double x, void* par); + double gsl_mkpi_re_bw_kstar_amp_bar_kstarzero_lass_amp(double x, void* par); + double gsl_mkpi_im_bw_kstar_amp_bar_kstarzero_lass_amp(double x, void* par); + + double int_mkpi_bw_kstar_amp_squared(double mkpia, double mkpib, double qsquared, double gammakstar, double mkstar, double R); + double int_mkpi_bw_kstar_amp_squared(double qsquared, double gammakstar, double mkstar, double R); + double int_mkpi_kstarzero_lass_amp_squared(double mkpia, double mkpib, double qsquared, double asphase, double a, double r, double gammakstarzero, double mkstarzero, double R); + double int_mkpi_kstarzero_lass_amp_squared(double qsquared, double asphase, double a, double r, double gammakstarzero, double mkstarzero, double R); + + std::complex int_mkpi_bw_kstar_amp_kstarzero_lass_amp_bar(double mkpia, double mkpib, double qsquared, double gammakstar, double mkstar, double asphase, double a, double r, double gammakstarzero, double mkstarzero, double R); + std::complex int_mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(double mkpia, double mkpib, double qsquared, double gammakstar, double mkstar, double asphase, double a, double r, double gammakstarzero, double mkstarzero, double R); + std::complex int_mkpi_bw_kstar_amp_kstarzero_lass_amp_bar(double qsquared, double gammakstar, double mkstar, double asphase, double a, double r, double gammakstarzero, double mkstarzero, double R); + std::complex int_mkpi_bw_kstar_amp_bar_kstarzero_lass_amp(double qsquared, double gammakstar, double mkstar, double asphase, double a, double r, double gammakstarzero, double mkstarzero, double R); + + double int_mkpi_kstarzero_isobar_amp_squared(double mkpia, double mkpib, double qsquared, double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero, double R); + double int_mkpi_kstarzero_isobar_amp_squared(double qsquared, double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero, double R); + + std::complex int_mkpi_bw_kstar_amp_kstarzero_isobar_amp_bar(double mkpia, double mkpib, double qsquared, + double gammakstar, double mkstar, double asphase, + double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero, double R); + std::complex int_mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(double mkpia, double mkpib, double qsquared, + double gammakstar, double mkstar, double asphase, + double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero, double R); + std::complex int_mkpi_bw_kstar_amp_kstarzero_isobar_amp_bar(double qsquared, + double gammakstar, double mkstar, double asphase, + double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero, double R); + std::complex int_mkpi_bw_kstar_amp_bar_kstarzero_isobar_amp(double qsquared, + double gammakstar, double mkstar, double asphase, + double f800mag, double f800phase, double gammaf800, double mf800, double gammakstarzero, double mkstarzero, double R); + + double rndgauss(TRandom3* rnd, double mean, double width, double min, double max); + double rndgauss(TRandom3* rnd, double mean, double widthlo, double widthhi, double min, double max); + + void moments_to_observables(TRandom3* rnd, + std::vector mom, + std::vector momcov, + double fsext, + double dfsext, + std::vector& obs, + std::vector& obscov, + bool usefsext = true + ); + + template struct NumberGreaterThan + { + bool operator()(const T a, const T b) const + { return std::abs(a) > std::abs(b); } + }; + + template typename iterator::value_type add_numbers(iterator begin, iterator end){ + typedef typename iterator::value_type T; + if (end == begin) return 0.; + std::make_heap(begin, end, NumberGreaterThan()); + + for (; begin + 1 < end; ) { + T x = *begin; + std::pop_heap(begin, end--, NumberGreaterThan()); + do { + x += *begin; + std::pop_heap(begin, end--, NumberGreaterThan()); + } while (std::abs(*begin) >= std::abs(x) && begin < end); + *end++ = x; + std::push_heap(begin, end, NumberGreaterThan()); + } + return *begin; + }; + + std::vectorGetNOutOfM(UInt_t N, UInt_t M, Int_t Seed, bool DoubleCounts, bool PoissonFluctuate); + + template typename iterator::value_type add_numbers(iterator begin, iterator end); + + int throw_multivariate_normal(const unsigned int ndim, const unsigned int ntoys, const std::vector& xi, const std::vector& cov, std::vector >& results); + int get_mean_cov(const std::vector >& meas, std::vector& mean, std::vector& cov); + + void sis_to_pis(TRandom3* rnd, + std::vector sis, + std::vector sicorrs, + std::vector& pis, + std::vector& picorrs); + + + std::complex cErrF(const std::complex& x); + ///implementation 2 of the complex error function + std::complex cErrF_2(const std::complex& x); + std::complex ErrF_2(const std::complex& x); + + ///implementation 3 of the complex error function + std::complex cErrF_3(const std::complex& x); + ///the faddeeva function function + std::complex Faddeeva_2 (const std::complex& z); + ///used by cErrF, does the actual calculations + std::complex wErrF(const std::complex& arg); + ///This is another version of the complex error function, used in the newer cdf code + std::complex nwwerf(const std::complex z); + +} + +#endif diff --git a/Code/FCNCFitter/sources/Core/generator.hh b/Code/FCNCFitter/sources/Core/generator.hh new file mode 100644 index 0000000..02a7468 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/generator.hh @@ -0,0 +1,26 @@ +/** + * @file generator.hh + * @author Christoph Langenbruch, Renata Kopecna + * @date 2009-03-18 + * + */ + +#ifndef GENERATOR_H +#define GENERATOR_H + +#include +#include + +namespace fcnc { + +///An abstract base class for toy monte carlo generators +class generator { +public: + ///generates nevents toy monte carlo events + virtual std::vector generate(unsigned int nevents, parameters* parameters, pdf* probability)=0; +}; + +} + +#endif + diff --git a/Code/FCNCFitter/sources/Core/integrals.cc b/Code/FCNCFitter/sources/Core/integrals.cc new file mode 100644 index 0000000..38dcf06 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/integrals.cc @@ -0,0 +1,574 @@ +//Renata Kopecna + +#include "integrals.hh" + +#include +#include +#include + +#include +#include + +#include + +double integral_x_to_n(double x, int n){ + return pow(x,n+1)/(n+1.0); +} +double integrate_x_to_n(double a, double b, int n){ + return integral_x_to_n(b,n) - integral_x_to_n(a,n); +} + +//this methods are helpful for the phi integration +//calculates int x^n * sin(x) dx +double integral_x_to_n_times_sin_x(double x, int n){ + assert(n >= 0); + if (n == 0) return -cos(x); + else return -pow(x, n)*cos(x) + n*integral_x_to_n_times_cos_x(x, n-1); +} +double integrate_x_to_n_times_sin_x(double a, double b, int n){ + return integral_x_to_n_times_sin_x(b, n) - integral_x_to_n_times_sin_x(a, n); +} + +//calculates int x^n * cos(x) dx (recursive using per partes) +double integral_x_to_n_times_cos_x(double x, int n){ + assert(n >= 0); + if (n == 0) return sin(x); + else return pow(x,n)*sin(x) - n*integral_x_to_n_times_sin_x(x, n-1); +} +double integrate_x_to_n_times_cos_x(double a, double b, int n){ + return integral_x_to_n_times_cos_x(b, n)-integral_x_to_n_times_cos_x(a, n); +} + +//calculates int x^n * sin(2x) dx (recursive using per partes) +double integral_x_to_n_times_sin_2x(double x, int n){ + assert(n >= 0); + if (n == 0) return -0.5*cos(2.0*x); + else return -pow(x,n)*0.5*cos(2.0*x) + +0.5*n*integral_x_to_n_times_cos_2x(x,n-1); +} +double integrate_x_to_n_times_sin_2x(double a, double b, int n){ + return integral_x_to_n_times_sin_2x(b, n) - integral_x_to_n_times_sin_2x(a, n); +} + +//calculates int x^n * cos(2x) dx (recursive using per partes) +double integral_x_to_n_times_cos_2x(double x, int n){ + assert(n >= 0); + if (n == 0) return 0.5*sin(2.0*x); + else return +0.5*pow(x,n)*sin(2.0*x) + -0.5*n*integral_x_to_n_times_sin_2x(x,n-1); +} +double integrate_x_to_n_times_cos_2x(double a, double b, int n){ + return integral_x_to_n_times_cos_2x(b, n) - integral_x_to_n_times_cos_2x(a, n); +} + +//calculates int x^n * cos(x)^2 dx +double integral_x_to_n_times_cos_x_2(double x, int n){ + assert(n >= 0); + return +1.0/(1.0 + n)*pow(x,n+1)*cos(x)*cos(x) + +1.0/(1.0+n)*integral_x_to_n_times_sin_2x(x, n+1); +} + +//calculates int x^n * sin(x)^2 dx +double integral_x_to_n_times_sin_x_2(double x, int n){ + assert(n >= 0); + return +1.0/(1.0 + n)*pow(x,n+1)*sin(x)*sin(x) + -1.0/(1.0+n)*integral_x_to_n_times_sin_2x(x, n+1); +} + +//calculates int x^n * asin(x) dx +double integral_x_to_n_times_asin_x(double x, int n){ + assert(n >= 0); + if (n == 0){ + return x*asin(x)+sqrt(1-x*x); + } + else{ + // return 1.0/(n+1.0)*pow(x,n)*(x*asin(x)+sqrt(1-x*x)) + // -n*integral_x_to_n_times_sqrt_1_minus_x2(x, n-1); + //factor 1/(n+1) missing??? + //fix below! + return 1.0/(n+1.0)*pow(x,n)*(x*asin(x)+sqrt(1-x*x)) + -n/(n+1.0)*integral_x_to_n_times_sqrt_1_minus_x2(x, n-1); + } +} + +//calculates int x^n * sqrt(1-x^2) dx (recursive using per partes) +double integral_x_to_n_times_sqrt_1_minus_x2(double x, int n){ + assert(n >= 0); + if (n == 0) return 0.5*asin(x)+0.5*x*sqrt(1-x*x); + else return 2.0/(n+2.0)*pow(x, n)*(0.5*asin(x)+0.5*x*sqrt(1-x*x))-n/(n+2.0)*integral_x_to_n_times_asin_x(x, n-1); +} + +double integrate_x_to_n_times_sqrt_1_minus_x2(double a, double b, int n){ + return integral_x_to_n_times_sqrt_1_minus_x2(b, n)-integral_x_to_n_times_sqrt_1_minus_x2(a, n); +} + +double integral_chebyshev(double x, int n){ + assert(n >= 0); + if (n == 0) return x; + else if (n == 1) return 0.5*x*x; + else return 0.5*(fcnc::chebyshev(x, n+1)/(n+1) - fcnc::chebyshev(x, n-1)/(n-1)); +} + +double integrate_gauss(double sigma, double mean, double min, double max){ + return 0.5*(TMath::Erf((mean-min)/sqrt(2.0)/sigma) - TMath::Erf((mean-max)/sqrt(2.0)/sigma)); +} + +double integrate_crystalball(double mean, double sigma, double alpha, double n, double min, double max){ + + //implementation taken from RooFit: https://root.cern.ch/doc/master/RooCBShape_8cxx_source.html#l00108 + + static const double sqrtPiOver2 = 1.2533141373; + static const double sqrt2 = 1.4142135624; + + double result = 0.0; + bool useLog = false; + + if( fabs(n-1.0) < 1.0e-05 ) + useLog = true; + + double sig = fabs((Double_t)sigma); + + //double tmin = (m.min(rangeName)-m0)/sig; + //double tmax = (m.max(rangeName)-m0)/sig; + double tmin = (min - mean ) / sigma; + double tmax = (max - mean ) / sigma; + + if(alpha < 0) { + double tmp = tmin; + tmin = -tmax; + tmax = -tmp; + } + + double absAlpha = fabs(alpha); + + if( tmin >= -absAlpha ) { + result += sig*sqrtPiOver2*( TMath::Erf(tmax/sqrt2) + - TMath::Erf(tmin/sqrt2) ); + } + else if( tmax <= -absAlpha ) { + double a = TMath::Power(n/absAlpha,n)*exp(-0.5*absAlpha*absAlpha); + double b = n/absAlpha - absAlpha; + + if(useLog) { + result += a*sig*( log(b-tmin) - log(b-tmax) ); + } + else { + result += a*sig/(1.0-n)*( 1.0/(TMath::Power(b-tmin,n-1.0)) + - 1.0/(TMath::Power(b-tmax,n-1.0)) ); + } + } + else { + double a = TMath::Power(n/absAlpha,n)*exp(-0.5*absAlpha*absAlpha); + double b = n/absAlpha - absAlpha; + + double term1 = 0.0; + if(useLog) { + term1 = a*sig*( log(b-tmin) - log(n/absAlpha)); + } + else { + term1 = a*sig/(1.0-n)*( 1.0/(TMath::Power(b-tmin,n-1.0)) + - 1.0/(TMath::Power(n/absAlpha,n-1.0)) ); + } + + double term2 = sig*sqrtPiOver2*( TMath::Erf(tmax/sqrt2) + - TMath::Erf(-absAlpha/sqrt2) ); + + result += term1 + term2; + } + + return result; + +} + +double integrate_twotailedcrystalball(double mean, double sigma, double alpha1, double alpha2, double n1, double n2, double min, double max){ + + double central = 0.0; + double left = 0.0; + double right = 0.0; + double result = 0.0; + + assert(alpha1 > 0.0); + assert(alpha2 > 0.0); + + //implementation taken from RooFit: RooDoubleCB.cxx + + static const double rootPiBy2 = sqrt(atan2(0.0,-1.0)/2.0); + static const double invRoot2 = 1.0/sqrt(2); + + double invwidth = 1.0/sigma; + + double tmin = (min-mean)*invwidth; + double tmax = (max-mean)*invwidth; + //spdlog::trace("tmin: {0:f}\t tmax: {0:f} ",tmin, tmax); + + bool isfullrange = (tmin<-1000. && tmax>1000.); + + //compute gaussian (central) contribution + double central_low = std::max(min, mean - alpha1*sigma); + double central_high = std::min(max, mean + alpha2*sigma); + + double tcentral_low = (central_low-mean)*invwidth; + double tcentral_high = (central_high-mean)*invwidth; + + //spdlog::trace("central_low: {0:f}\t central_high: {0:f} ",central_low, central_high); + //spdlog::trace("tcentral_low: {0:f}\t tcentral_high: {0:f} ",tcentral_low, tcentral_high); + + if(central_low < central_high){// is the gaussian part in range? + central = rootPiBy2*sigma*(TMath::Erf(tcentral_high*invRoot2)-TMath::Erf(tcentral_low*invRoot2)); + } + + //compute left tail; + if(isfullrange && (n1-1.0)>1.e-3) { + left = sigma*TMath::Exp(-0.5*alpha1*alpha1)*n1/(alpha1*(n1-1.)); + spdlog::trace("left: {0:f}", left); + } + else{ + double left_low = min; + double left_high = std::min(max, mean - alpha1*sigma); + double thigh = (left_high-mean)*invwidth; + + if(left_low < left_high){ //is the left tail in range? + double n1invalpha1 = n1/(fabs(alpha1)); + if(fabs(n1-1.0)>1.e-3){ + double invn1m1 = 1/(n1-1.); + double leftpow = TMath::Power(n1invalpha1,-n1*invn1m1); + assert(leftpow > 0.0); + double left0 = sigma*TMath::Exp(-0.5*alpha1*alpha1)*invn1m1; + double left1, left2; + + if(max > (mean-alpha1*sigma)) + left1 = n1invalpha1; + else + left1 = TMath::Power( leftpow*(n1invalpha1 - alpha1 - thigh), 1.-n1); + + if(tmin<-1000.) + left2 = 0.; + else + left2 = TMath::Power( leftpow*(n1invalpha1 - alpha1 - tmin ), 1.-n1); + + left = left0*(left1-left2); + } + else{ + double A1 = TMath::Power(n1invalpha1,n1)*TMath::Exp(-0.5*alpha1*alpha1); + double B1 = n1invalpha1-fabs(alpha1); + left = A1*sigma*(TMath::Log(B1-(left_low-mean)*invwidth) - TMath::Log(B1-(left_high-mean)*invwidth) ); + } + } + } + + //compute right tail; + if(isfullrange && (n2-1.0)>1.e-3) { + right = sigma*TMath::Exp(-0.5*alpha2*alpha2)*n2/(alpha2*(n2-1.)); + } + else{ + double right_low = std::max(min,mean + alpha2*sigma); + double right_high = max; + double tlow = (right_low - mean)*invwidth; + + if(right_low < right_high){ //is the right tail in range? + double n2invalpha2 = n2/(fabs(alpha2)); + if(fabs(n2-1.0)>1.e-3) { + double invn2m2 = 1.0/(n2-1.); + double rightpow = TMath::Power(n2invalpha2,-n2*invn2m2); + if (rightpow <= 0.0){ + spdlog::error("rightpow < 0.0! Returning NaN"); + spdlog::error("TMath::Power(n2invalpha2,-n2*invn2m2) = {0:.30f}",powl(n2/(fabs(alpha2)),-n2*1.0/(n2-1.))); + spdlog::error("n2invalpha2: {0:f}\tn2: {1:f}\tinvn2m2: {2:f}",n2invalpha2,n2,invn2m2); + spdlog::error("mean: {0:f}\tsigma: {1:f}\talpha1: {2:f}\talpha2: {3:f}\tn1: {4:f}\tn2: {5:f}\tmin: {6:f}\tmax: {7:f}", mean, sigma, alpha1, alpha2, n1, n2, min, max); + return nan(""); + } + double right0 = sigma*TMath::Exp(-0.5*alpha2*alpha2)*invn2m2; + double right1, right2; + + if(min<(mean+alpha2*sigma)) right1 = n2invalpha2; + else right1 = TMath::Power( rightpow*(n2invalpha2 - alpha2 + tlow), 1.-n2); + + if(tmax>1000.) right2 = 0.; + else right2 = TMath::Power( rightpow*(n2invalpha2 - alpha2 + tmax), 1.-n2); + + right = right0*(right1-right2); + } + else{ + double A2 = TMath::Power(n2invalpha2,n2)*TMath::Exp(-0.5*alpha2*alpha2); + double B2 = n2invalpha2-fabs(alpha2); + right = A2*sigma*(TMath::Log(B2+(right_high-mean)*invwidth) - TMath::Log(B2+(right_low-mean)*invwidth) ); + } + } + } + + result = left + central + right; + + if(result <= 0.0){ + spdlog::error("left = {0:e}",left); + spdlog::error("central = {0:e}",central); + spdlog::error("right = {0:e}", right); + spdlog::error("sigma = {0:e}", sigma); + spdlog::error("n1 = {0:e}", n1); + spdlog::error("n2 = {0:e}", n2); + spdlog::error("alpha1 = {0:e}", alpha1); + spdlog::error("alpha1 = {0:e}", alpha2); + assert(0); + } + + if(std::isnan(result) || std::isinf(result)){ + spdlog::critical("Determination of twotailed CB integral failed: {0:f}", result); + spdlog::critical("mean: {1:f}\tsigma: {2:f}\talpha1: {3:f}\talpha2: {4:f}\tn1: {5:f}\tn2: {6:f}", mean, sigma, alpha1, alpha2, n1, n2); + spdlog::critical("left: {0:f}\tcentral: {1:f}\tright: {2:f}", left, central, right); + + assert(0); + } + + return result; +} + +double integral_x_to_n_times_exp_minus_x(double x, double tau, int n){ + assert(n>=0); + if (n == 0) return -tau*exp(-x/tau); + else return pow(x, n)*(-tau*exp(-x/tau)) + n * tau * integral_x_to_n_times_exp_minus_x(x, tau, n-1); +} + + + +//----------------------- +// P wave +//----------------------- + +//THESE FUNCTIONS NEED TO BE CHECKED +//i correspons to ctl, j to ctk and k to phi + + +//int[ sin^2(tk) ] for J1s +double integral_f1(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi){ + //Integrate sin^2 d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return (integral_x_to_n(ctk,n_ctk)-integral_x_to_n(ctk,n_ctk+2)) + *integral_x_to_n(ctl,n_ctl) + *integral_x_to_n(phi,n_phi); +} +double integrate_f1(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi){ + return (integrate_x_to_n(ctk_a, ctk_b, n_ctk)-integrate_x_to_n(ctk_a,ctk_b,n_ctk+2)) + *integrate_x_to_n(ctl_a, ctl_b, n_ctl) + *integrate_x_to_n(phi_a, phi_b, n_phi); +} + +//int[ cos^2(tk) ] for J1c +double integral_f2(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi){ + //Integrate cos^2 thetak d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return integral_x_to_n(ctk,n_ctk+2) + *integral_x_to_n(ctl,n_ctl) + *integral_x_to_n(phi,n_phi); +} +double integrate_f2(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi){ + return integrate_x_to_n(ctk_a, ctk_b, n_ctk+2) + *integrate_x_to_n(ctl_a, ctl_b, n_ctl) + *integrate_x_to_n(phi_a, phi_b, n_phi); +} + +//int[ sin^2(tk) * cos(2tl) ] for J2s +double integral_f3(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi){ + //Integrate sin^2 thetak cos 2thetal d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return (integral_x_to_n(ctk,n_ctk)-integral_x_to_n(ctk,n_ctk+2)) + *(2*integral_x_to_n(ctl,n_ctl+2)-integral_x_to_n(ctl,n_ctl)) //cos(2x) = 2*cos^2(x)-1 + *integral_x_to_n(phi,n_phi); +} +double integrate_f3(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi){ + return (integrate_x_to_n(ctk_a, ctk_b, n_ctk)-integrate_x_to_n(ctk_a, ctk_b, n_ctk+2)) + *(2*integrate_x_to_n(ctl_a, ctl_b, n_ctl+2)-integrate_x_to_n(ctl_a, ctl_b, n_ctl)) //cos(2x) = 2*cos^2(x)-1 + *integrate_x_to_n(phi_a,phi_b,n_phi); +} + +//int[ cos^2(tk) * cos(2tl) ] for J2c +double integral_f4(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi){ + //Integrate cos^2 thetak cos 2thetal d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return integral_x_to_n(ctk,n_ctk+2) + *(2*integral_x_to_n(ctl,n_ctl+2)-integral_x_to_n(ctl,n_ctl)) + *integral_x_to_n(phi,n_phi); +} +double integrate_f4(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi){ + //Integrate cos^2 thetak cos 2thetal d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return integrate_x_to_n(ctk_a, ctk_b, n_ctk+2) + *(2*integrate_x_to_n(ctl_a, ctl_b, n_ctl+2)-integrate_x_to_n(ctl_a, ctl_b, n_ctl)) + *integrate_x_to_n(phi_a,phi_b,n_phi); +} + +//int[ sin^2(tk) * sin^2(tl) * cos(2phi) ] for J3 +double integral_f5(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi){ + //Integrate sin^2 thetak sin^2 thetal cos 2phi d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return (integral_x_to_n(ctk,n_ctk)-integral_x_to_n(ctk,n_ctk+2)) + *(integral_x_to_n(ctl,n_ctl)-integral_x_to_n(ctl,n_ctl+2)) + *(integral_x_to_n_times_cos_2x(phi,n_phi)); +} +double integrate_f5(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi){ + //Integrate sin^2 thetak sin^2 thetal cos 2phi d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return (integrate_x_to_n(ctk_a, ctk_b, n_ctk)-integrate_x_to_n(ctk_a, ctk_b, n_ctk+2)) + *(integrate_x_to_n(ctl_a, ctl_b, n_ctl)-integrate_x_to_n(ctl_a, ctl_b, n_ctl+2)) + *(integrate_x_to_n_times_cos_2x(phi_a,phi_b,n_phi)); +} + +//int[ sin(2tk) * sin(2tl) * cos(phi) ] for J4 +double integral_f6(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi){ + //Integrate sin 2thetak sin 2thetal cos phi d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return 2*integral_x_to_n_times_sqrt_1_minus_x2(ctk,n_ctk+1) + *2*integral_x_to_n_times_sqrt_1_minus_x2(ctl,n_ctl+1) + *integral_x_to_n_times_cos_x(phi,n_phi); +} +double integrate_f6(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi){ + //Integrate sin 2thetak sin 2thetal cos phi d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return 2*integrate_x_to_n_times_sqrt_1_minus_x2(ctk_a, ctk_b, n_ctk+1) + *2*integrate_x_to_n_times_sqrt_1_minus_x2(ctl_a, ctl_b,n_ctl+1) + *integrate_x_to_n_times_cos_x(phi_a,phi_b,n_phi); +} + +//int [ sin(2tk) * sin(tl) * cos(phi) ] for J5 +double integral_f7(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi){ + //Integrate sin 2thetak sin thetal cos phi d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return 2*integral_x_to_n_times_sqrt_1_minus_x2(ctk,n_ctk+1) + *integral_x_to_n_times_sqrt_1_minus_x2(ctl,n_ctl) + *integral_x_to_n_times_cos_x(phi,n_phi); +} +double integrate_f7(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi){ + //Integrate sin 2thetak sin thetal cos phi d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return 2*integrate_x_to_n_times_sqrt_1_minus_x2(ctk_a, ctk_b, n_ctk+1) + *integrate_x_to_n_times_sqrt_1_minus_x2(ctl_a, ctl_b,n_ctl) + *integrate_x_to_n_times_cos_x(phi_a,phi_b,n_phi); +} + +//int [ sin^2(tk) * cos(tl) ] for J6s +double integral_f8(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi){ + //Integrate sin^2 thetak cos thetal d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return (integral_x_to_n(ctk,n_ctk)-integral_x_to_n(ctk,n_ctk+2)) + *integral_x_to_n(ctl,n_ctl+1) + *integral_x_to_n(phi,n_phi); +} +double integrate_f8(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi){ + //Integrate sin^2 thetak cos thetal d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return (integrate_x_to_n(ctk_a, ctk_b, n_ctk)-integrate_x_to_n(ctk_a, ctk_b, n_ctk+2)) + *integrate_x_to_n(ctl_a, ctl_b,n_ctl+1) + *integrate_x_to_n(phi_a,phi_b,n_phi); +} + +//int [ cos^2(tk) * cos(tl) ] for J6c +double integral_f9(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi){ + //Integrate sin^2 thetak cos thetal d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return integral_x_to_n(ctk,n_ctk+2) + *integral_x_to_n(ctl,n_ctl+1) + *integral_x_to_n(phi,n_phi); +} +double integrate_f9(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi){ + //Integrate sin^2 thetak cos thetal d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return integrate_x_to_n(ctk_a, ctk_b, n_ctk+2) + *integrate_x_to_n(ctl_a, ctl_b,n_ctl+1) + *integrate_x_to_n(phi_a,phi_b,n_phi); +} + +//int [ sin(2tk) * sin(tl) * sin(phi) ] for J7 +double integral_f10(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi){ + //Integrate sin 2thetak sin thetal sin phi d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return 2*integral_x_to_n_times_sqrt_1_minus_x2(ctk,n_ctk+1) + *integral_x_to_n_times_sqrt_1_minus_x2(ctl,n_ctl+1) + *integral_x_to_n_times_sin_x(phi,n_phi); +} +double integrate_f10(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi){ + //Integrate sin 2thetak sin thetal sin phi d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return 2*integrate_x_to_n_times_sqrt_1_minus_x2(ctk_a, ctk_b, n_ctk+1) + *integrate_x_to_n_times_sqrt_1_minus_x2(ctl_a, ctl_b,n_ctl+1) + *integrate_x_to_n_times_sin_x(phi_a,phi_b,n_phi); +} + +//int [ sin(2tk) * sin(2tl) * sin(phi) ] for J8 +double integral_f11(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi){ + //Integrate sin 2thetak sin 2thetal sin phi d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return 2*integral_x_to_n_times_sqrt_1_minus_x2(ctk,n_ctk+1) + *2*integral_x_to_n_times_sqrt_1_minus_x2(ctl,n_ctl+1) + *integral_x_to_n_times_sin_x(phi,n_phi); +} +double integrate_f11(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi){ + //Integrate sin 2thetak sin 2thetal sin phi d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return 2*integrate_x_to_n_times_sqrt_1_minus_x2(ctk_a, ctk_b,n_ctk+1) + *2*integrate_x_to_n_times_sqrt_1_minus_x2(ctl_a, ctl_b,n_ctl+1) + *integrate_x_to_n_times_sin_x(phi_a,phi_b,n_phi); +} + +//int [ sin^2(tk) * sin^2(tl) * sin(2phi) ] for J9 +double integral_f12(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi){ + //Integrate sin^2 thetak sin^2 thetal sin 2phi d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return (integral_x_to_n(ctk,n_ctk)-integral_x_to_n(ctk,n_ctk+2)) + *(integral_x_to_n(ctl,n_ctl)-integral_x_to_n(ctl,n_ctl+2)) + *(integral_x_to_n_times_sin_2x(phi,n_phi)); +} +double integrate_f12(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi){ + //Integrate sin^2 thetak sin^2 thetal sin 2phi d costhetak d costhetal d phi times ctk^n1+ctl^n2*phi^n3 + return (integrate_x_to_n(ctk_a, ctk_b,n_ctk)-integrate_x_to_n(ctk_a, ctk_b,n_ctk+2)) + *(integrate_x_to_n(ctl_a, ctl_b,n_ctl)-integrate_x_to_n(ctl_a, ctl_b,n_ctl+2)) + *(integrate_x_to_n_times_sin_2x(phi_a,phi_b,n_phi)); +} + +//----------------------- +// S wave +//----------------------- + +double integral_s_f1(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi){ + return (integral_x_to_n(ctl,n_ctl)-integral_x_to_n(ctl,n_ctl+2)) + *integral_x_to_n(ctk,n_ctk) + *integral_x_to_n(phi, n_phi); +} +double integrate_s_f1(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi){ + return (integrate_x_to_n(ctl_a,ctl_b,n_ctl)-integrate_x_to_n(ctl_a,ctl_b,n_ctl+2)) + *integrate_x_to_n(ctk_a,ctk_b,n_ctk) + *integrate_x_to_n(phi_a,phi_b,n_phi); +} + +double integral_s_f2(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi){ + return (integral_x_to_n(ctl,n_ctl)-integral_x_to_n(ctl,n_ctl+2)) + *integral_x_to_n(ctk,n_ctk+1) + *integral_x_to_n(phi, n_phi); +} +double integrate_s_f2(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi){ + return (integrate_x_to_n(ctl_a,ctl_b,n_ctl)-integrate_x_to_n(ctl_a,ctl_b,n_ctl+2)) + *integrate_x_to_n(ctk_a,ctk_b,n_ctk+1) + *integrate_x_to_n(phi_a,phi_b,n_phi); +} + +double integral_s_f3(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi){ + return 2*integral_x_to_n_times_sqrt_1_minus_x2(ctl,n_ctl+1) + *integral_x_to_n_times_sqrt_1_minus_x2(ctk,n_ctk) + *integral_x_to_n_times_cos_x(phi, n_phi); +} +double integrate_s_f3(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi){ + return 2*integrate_x_to_n_times_sqrt_1_minus_x2(ctl_a,ctl_b,n_ctl+1) + *integrate_x_to_n_times_sqrt_1_minus_x2(ctk_a,ctk_b,n_ctk) + *integrate_x_to_n_times_cos_x(phi_a,phi_b,n_phi); +} + +double integral_s_f4(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi){ + return integral_x_to_n_times_sqrt_1_minus_x2(ctl,n_ctl) + *integral_x_to_n_times_sqrt_1_minus_x2(ctk,n_ctk) + *integral_x_to_n_times_cos_x(phi, n_phi); +} +double integrate_s_f4(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi){ + return integrate_x_to_n_times_sqrt_1_minus_x2(ctl_a,ctl_b,n_ctl) + *integrate_x_to_n_times_sqrt_1_minus_x2(ctk_a,ctk_b,n_ctk) + *integrate_x_to_n_times_cos_x(phi_a,phi_b,n_phi); +} + +double integral_s_f5(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi){ + return integral_x_to_n_times_sqrt_1_minus_x2(ctl,n_ctl) + *integral_x_to_n_times_sqrt_1_minus_x2(ctk,n_ctk) + *integral_x_to_n_times_sin_x(phi, n_phi); +} +double integrate_s_f5(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi){ + return integrate_x_to_n_times_sqrt_1_minus_x2(ctl_a,ctl_b,n_ctl) + *integrate_x_to_n_times_sqrt_1_minus_x2(ctk_a,ctk_b,n_ctk) + *integrate_x_to_n_times_sin_x(phi_a,phi_b,n_phi); +} + +double integral_s_f6(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi){ + return 2*integral_x_to_n_times_sqrt_1_minus_x2(ctl,n_ctl+1) + *integral_x_to_n_times_sqrt_1_minus_x2(ctk,n_ctk) + *integral_x_to_n_times_sin_x(phi, n_phi); +} +double integrate_s_f6(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi){ + return 2*integrate_x_to_n_times_sqrt_1_minus_x2(ctl_a,ctl_b,n_ctl+1) + *integrate_x_to_n_times_sqrt_1_minus_x2(ctk_a,ctk_b,n_ctk) + *integrate_x_to_n_times_sin_x(phi_a,phi_b,n_phi); +} + diff --git a/Code/FCNCFitter/sources/Core/integrals.hh b/Code/FCNCFitter/sources/Core/integrals.hh new file mode 100644 index 0000000..ec7d3fa --- /dev/null +++ b/Code/FCNCFitter/sources/Core/integrals.hh @@ -0,0 +1,108 @@ +//Renata Kopecna + +#ifndef INTEGRALS_HH +#define INTEGRALS_HH + +double integral_x_to_n(double x, int n); +double integrate_x_to_n(double a, double b, int n); + +//this methods are helpful for the phi integration +//calculates int x^n * sin(x) dx +double integral_x_to_n_times_sin_x(double x, int n); +double integrate_x_to_n_times_sin_x(double a, double b, int n); + +//calculates int x^n * cos(x) dx +double integral_x_to_n_times_cos_x(double x, int n); +double integrate_x_to_n_times_cos_x(double a, double b, int n); + +//calculates int x^n * sin(2x) dx +double integral_x_to_n_times_sin_2x(double x, int n); +double integrate_x_to_n_times_sin_2x(double a, double b, int n); + +//calculates int x^n * cos(2x) dx +double integral_x_to_n_times_cos_2x(double x, int n); +double integrate_x_to_n_times_cos_2x(double a, double b, int n); + +//calculates int x^n * cos(x)^2 dx +double integral_x_to_n_times_cos_x_2(double x, int n); + +//calculates int x^n * sin(x)^2 dx +double integral_x_to_n_times_sin_x_2(double x, int n); + +//calculates int x^n * asin(x) dx +double integral_x_to_n_times_asin_x(double x, int n); +//calculates int x^n * sqrt(1-x^2) dx +double integral_x_to_n_times_sqrt_1_minus_x2(double x, int n); + +double integrate_x_to_n_times_sqrt_1_minus_x2(double a, double b, int n); + +double integral_chebyshev(double x, int n); +double integrate_gauss(double sigma, double mean, double min, double max); + +double integrate_crystalball(double mean, double sigma, double alpha, double n, double min, double max); + +double integrate_twotailedcrystalball(double mean, double sigma, double alpha1, double alpha2, double n1, double n2, double min, double max); + +double integral_x_to_n_times_exp_minus_x(double x, double tau, int n); +//THESE FUNCTIONS NEED TO BE CHECKED +//i correspons to ctl, j to ctk and k to phi +double integral_f1(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi); +double integrate_f1(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi); + +double integral_f2(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi); +double integrate_f2(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi); + +double integral_f3(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi); +double integrate_f3(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi); + +double integral_f4(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi); +double integrate_f4(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi); + +double integral_f5(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi); +double integrate_f5(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi); + +double integral_f6(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi); +double integrate_f6(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi); + +double integral_f7(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi); +double integrate_f7(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi); + +double integral_f8(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi); +double integrate_f8(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi); + +double integral_f9(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi); +double integrate_f9(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi); + +double integral_f10(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi); +double integrate_f10(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi); + +double integral_f11(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi); +double integrate_f11(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi); + +double integral_f12(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi); +double integrate_f12(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi); + + +/////////////////// +// sWave // +/////////////////// + +double integral_s_f1(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi); +double integrate_s_f1(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi); + +double integral_s_f2(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi); +double integrate_s_f2(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi); + +double integral_s_f3(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi); +double integrate_s_f3(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi); + +double integral_s_f4(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi); +double integrate_s_f4(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi); + +double integral_s_f5(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi); +double integrate_s_f5(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi); + +double integral_s_f6(double ctl, double ctk, double phi, int n_ctl, int n_ctk, int n_phi); +double integrate_s_f6(double ctl_a, double ctl_b, double ctk_a, double ctk_b, double phi_a, double phi_b, int n_ctl, int n_ctk, int n_phi); + +#endif // INTEGRALS_HH diff --git a/Code/FCNCFitter/sources/Core/options.cc b/Code/FCNCFitter/sources/Core/options.cc new file mode 100644 index 0000000..28cab4d --- /dev/null +++ b/Code/FCNCFitter/sources/Core/options.cc @@ -0,0 +1,224 @@ +//Renata Kopecna + +#include + +#include +#include +#include +#include + +#include +#include +#include +//https://github.com/gabime/spdlog +#include + +///Try to extract a number from the name (option given on command line) +int fcnc::options::get_job_id() { + return job_id; +}; + +//reset the ranges of all three angles back to full_angular configuration +void fcnc::options::reset_angle_ranges(){ + ctl_min = CTK_MIN; + ctl_max = CTL_MAX; + ctk_min = CTK_MIN; + ctk_max = CTK_MAX; + phi_min = PHI_MIN; + phi_max = PHI_MAX; + + //spdlog::debug( "Reset angles: ctl=[ {0:0.2f} - {1:0.2f}]", ctl_min ,ctl_max); + //spdlog::debug( "Reset angles: ctk=[ {0:0.2f} - {1:0.2f}]", ctk_min ,ctk_max); + //spdlog::debug( "Reset angles: phi=[ {0:0.2f} - {1:0.2f}]", phi_min ,phi_max); +} + +bool fcnc::options::canIFold(){ + //Check the ranges of the angles, if the ranges are smaller than the full ones, do not perform folding + if (folding == -1) return true; + if (PHI_MIN != -1.0*TMath::Pi() || PHI_MAX != 1.0*TMath::Pi()) return false; + if (folding > 1 && (CTL_MIN != -1.0 || CTL_MAX != 1.0)) return false; + return true; +} + +void fcnc::options::update_angle_ranges(){ + reset_angle_ranges(); + if(full_angular || folding == -1)return; + //Check the ranges of the angles, if the ranges are smaller than the full ones, do not perform folding + if (!canIFold()){ + spdlog::warn("Range of the angles is assymetric, cannot perform update of folded angle ranges!"); + return; + } + switch(folding){ + case 0: + phi_min = 0.; + break; + case 1: + phi_min = 0.; + ctl_min = 0.; + break; + case 2: + phi_min = 0.; + ctl_min = 0.; + break; + case 3: + phi_min = -MY_PI/2.; + phi_max = +MY_PI/2.; + ctl_min = 0.; + break; + case 4: + phi_min = -MY_PI/2.; + phi_max = +MY_PI/2.; + ctl_min = 0.; + ctk_max = std::min(fabs(CTK_MIN), fabs(CTK_MAX)); //Take smaller value from abs(max), abs(min) = M + ctk_min = -ctk_max; //And take range (-M,M) + break; + } + + spdlog::debug( "Update angles: ctl=[{0:0.2f} - {1:0.2f}]", ctl_min ,ctl_max); + spdlog::debug( "Update angles: ctk=[{0:0.2f} - {1:0.2f}]", ctk_min ,ctk_max); + spdlog::debug( "Update angles: phi=[{0:0.2f} - {1:0.2f}]", phi_min ,phi_max); + +} +///This method prints the used options. + +void fcnc::options::print(){ + spdlog::info( "Options:"); + spdlog::info( "Number of threads:\t\t {0:d}", ncores); + spdlog::info( "Use angular acceptance: " + boolToString(use_angular_acc)); + spdlog::info( "Fit angular corr. coefficients "+ boolToString(angularacceptance)); + spdlog::info( "Do projections: "+ boolToString(project)); + spdlog::info( "Write eps files: "+ boolToString(write_eps)); + spdlog::info( "Write C files: "+ boolToString(write_C)); + spdlog::info( "Load only truthmatched: "+ boolToString(only_truthmatched)); + spdlog::info( "Use only true quantities: "+ boolToString(use_truth)); + spdlog::info( "Shift likelihood: "+ boolToString(shift_lh)); + spdlog::info( "Repeat on error: "+ boolToString(repeat_on_fail)); + spdlog::info( "Use asymmetric Minos errors: "+ boolToString(minos_errors)); + spdlog::info( "Run Simplex before Migrad: "+ boolToString(simplex_prerun)); + spdlog::info( "Run Hesse after Migrad: "+ boolToString(hesse_postrun)); + spdlog::info( "Perform weighted fit: "+ boolToString(weighted_fit)); + spdlog::info( "Verbosity: "+ spdlog::default_logger_raw()->level()); + spdlog::info( "Static seed: "+ boolToString(static_seed)); + spdlog::info( "Always static seed: "+ boolToString(always_static_seed)); + spdlog::info( "Refit the same data set: "+ boolToString(refitting_nominal)); +} + +std::vector fcnc::options::getAllPlotTypes(){ + std::vector ext; + if (write_C) ext.push_back("C"); + if (write_eps) ext.push_back("eps"); + if (write_jpg) ext.push_back("jpg"); + if (write_pdf) ext.push_back("pdf"); + return ext; +} + + +//Get the number of Q2 bins from the lenght of ThQ2binsmin vector +unsigned int fcnc::options::get_nQ2bins(){ + return TheQ2binsmin.size(); +} +////////////////////////////// +// Set systematics options // +////////////////////////////// + +void which_systematics( fcnc::options opts, int job_id){ + + if(opts.systematic == 1){ + spdlog::info( "Run systematic study #1: BOOTSTRAPPING of PHSP MC"); + opts.write_eps = job_id == -1; + } + if(opts.systematic == 2){ + spdlog::info( "Run systematic study #2: Forced symmetric acceptance correction in cos(Theta_L)"); + opts.write_eps = false; + } + opts.orderincrease = 2; + if(opts.systematic == 3){ + spdlog::info( "Run systematic study #3: Increase of Legendre order of PHSP MC parametrization"); + opts.eff_order_costhetal += opts.orderincrease; + opts.eff_order_costhetak += opts.orderincrease; + opts.eff_order_phi += opts.orderincrease; + opts.eff_order_q2 += opts.orderincrease; + } + if(opts.systematic == 4){ + spdlog::info( "Run systematic study #4: Vary PHSP MC reweights within their uncertainty"); + opts.write_eps = false; + } + if(opts.systematic == 5){ + spdlog::info( "Run systematic study #5: Vary S-wave fraction FS in q2bin within its uncertainty"); + opts.write_eps = false; + } + if(opts.systematic == 6){ + spdlog::info( "Run systematic study #6: Vary angles (ctk, ctl and phi) within the angular resoluation"); + opts.write_eps = false; + } + if(opts.systematic == 7){ + spdlog::info( "Run systematic study #7: Generate toy events with double-gaussian profile and fit with CB"); + opts.write_eps = false; + } + if(opts.systematic == 8){ + spdlog::info( "Run systematic study #8: Systematic study on angular background model"); + opts.write_eps = false; + } + if(opts.systematic == 9){ + spdlog::info( "Run systematic study #9: Investigate systematic effects due to trigger selection"); + opts.write_eps = false; + } + if(opts.systematic == 10){ + spdlog::info( "Run systematic study #10: Reweight the PHSP MC according to discrepancy in Kshort PT distributions for DD tracks"); + opts.write_eps = false; + } + if(opts.systematic == 11){ + spdlog::info( "Run systematic study #11: Remove a gaussian shaped hole in the upper mass sideband of the background to mimic the B0 veto"); + opts.write_eps = false; + } + +} + +std::vector get_observables_vec (fcnc::options opts){ + std::vector obs; + if(opts.fit_fl) obs.push_back("Fl"); + else obs.push_back("S1s"); + + obs.push_back("S3"); + + if(opts.full_angular || opts.folding == 1) obs.push_back("S4"); + if(opts.full_angular || opts.folding == 2) obs.push_back("S5"); + if(opts.full_angular || opts.folding == 0){ + if(opts.fit_afb) obs.push_back("Afb"); + else obs.push_back("S6s"); + } + if(opts.full_angular || opts.folding == 3) obs.push_back("S7"); + if(opts.full_angular || opts.folding == 4) obs.push_back("S8"); + if(opts.full_angular || opts.folding == 0) obs.push_back("S9"); + return obs; + +} + + +void set_ang_year_options(fcnc::options &opts){ + //Takes care of setting the year/run options for angular corrections + + //use data from run 1 and run 2 combined + opts.angacccorrbothruns = (opts.run == 12); + //use 2015+2016 or 2017+2018 + opts.angacccorrpertwoyears = (opts.run == 21 || opts.run == 22); + //If run/two years are used, turn off the per-year correction + if (opts.angacccorrbothruns || opts.angacccorrpertwoyears) opts.angacccorrperyear = false; + return; +} + +bool is_param_folded(int param, fcnc::options *opts){ + //int param is the number of the parameter according to get_angObser_withTeX_vec() + //if the parameter is folded, return true + + if (param==5) return !(opts->full_angular || opts->folding == 1); + if (param==6) return !(opts->full_angular || opts->folding == 2); + if (param==7) return !(opts->full_angular || opts->folding == 0); + if (param==8) return !(opts->full_angular || opts->folding == 0); + if (param==9) return !(opts->full_angular || opts->folding == 3); + if (param==10) return !(opts->full_angular || opts->folding == 4); + if (param==11) return !(opts->full_angular || opts->folding == 0); + return false; + + +} diff --git a/Code/FCNCFitter/sources/Core/options.hh b/Code/FCNCFitter/sources/Core/options.hh new file mode 100644 index 0000000..508eb97 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/options.hh @@ -0,0 +1,447 @@ +/** + * @file options.hh + * @author Christoph Langenbruch, Renata Kopecna + * @date 2009-03-18 + * + * This file contains the options class which is used to store all the settings which are needed + * for the fit. The likelihood, fitter, and plotter classes each + * hold a pointer to an options object which must be supplied in their constructor. + * On initialisation of the fitter class, the chosen options are printed + * and should be redirected to a logfile + * + */ + +#ifndef OPTIONS_H +#define OPTIONS_H + +#include +#include + +#include + + + +namespace fcnc { + +///class that stores the options used in the analysis +class options { +public: + ///number of cores to use + unsigned int ncores; + ///use angular acceptance in the likelihood + bool use_angular_acc; + /// fit angular acceptance correction coefficients + bool angularacceptance; + /// get angular acceptance corrections for every year individually + bool angacccorrperyear; + /// combine every 2 years (2011+12, 2015+16, 2017+18) for acceptance correction + bool angacccorrpertwoyears; + /// combine the dataset of both runs for the angular acceptance correction: + bool angacccorrbothruns; + /// only calculate chi2's from the 1D projections of cos(tl), cos(tk), phi and q2 + bool only_4_1D_chi2; + /// scan the parametrization of angular acceptance corrections coefficients + /// by changing the max. order of legendre polynoms + bool scan_max_order_angacccorrection; + ///do plots after every step in a toystudy + bool project; + ///write .eps files + bool write_eps; + ///write .C files (of plots) + bool write_C; + ///write .jpg files (of plots) + bool write_jpg; + ///write .pdf files (of plots) + bool write_pdf; + ///read only out truthmatched bs candidates from file + bool only_truthmatched; + ///use only true quantities for the fit. Not implemented yet + bool use_truth; + ///use numerically optimal summation of likelihoods + bool shift_lh; + ///repeat on fail + bool repeat_on_fail; + ///use minos for error calculation + bool minos_errors; + ///use simplex first + bool simplex_prerun; + ///use Markov chain Monte Carlo + bool use_mcmc; + ///hesse postrun + bool hesse_postrun; + ///use accymptotic hesse, broken at this moment!!! + bool asymptotic; + ///weighted fit + bool weighted_fit; + ///generate background with acceptance correction in the PDF + bool use_weighted_bkg; + ///in the case of a folded and acc corrected fit, use full angular PDF for background + bool fit_full_angular_bkg; + ///use event q2 when determining weight + bool use_event_norm; + ///static seed for toys + bool static_seed; + ///Always use the same seed for toy generation, useful in systematics + bool always_static_seed; + ///extended ml fit + bool extended_ml; + ///refitting of nominal values for systematic studies + bool refitting_nominal; + ///Options to set the mass shape + bool crystalball; + bool twotailedcrystalball; + bool swave; + bool simple_mkpi; + //THIS TURNS ON FITTING BOTH K*mass and B+ mass + //AND it turns off the angle fits + bool only_mass2DFit; + bool use_p2; + //order of fitted polynomials + unsigned int eff_order_costhetal; + unsigned int eff_order_costhetak; + unsigned int eff_order_phi; + unsigned int eff_order_q2; + int orderincrease; + //order of background, currently does nothing, might be useful in the future + unsigned int bkg_order_costhetal; + unsigned int bkg_order_costhetak; + unsigned int bkg_order_phi; + + //minimum and maximum mass + bool cutsignalwindow; + double m_min; //signal window left edge + double m_max; //signal window right edge + double m_low; //considered mass spectrum left edge + double m_high; //considered mass spectrum right edge + double q2_min;//this is only used in weighted generation + double q2_max; + //Initialize using the SM values? + bool initSM; + ///Options for all plots + double ctl_min; + double ctl_max; + double ctk_min; + double ctk_max; + double phi_min; + double phi_max; + unsigned int plots_m_bins; + unsigned int plots_mkpi_bins; + unsigned int plots_costhetal_bins; + unsigned int plots_costhetak_bins; + unsigned int plots_phi_bins; + std::string plot_label; + std::string plot_folder; + std::string q2_label; + bool plot_chi2; + std::string name; + double minuit_strategy; + bool flat_bkg; + bool full_angular; //If false, use folding + bool always_generate_full_angular; //I have no idea what it does but it is always true everywhere + unsigned int fitsperjob; + int job_id; + //Fit only mass/angles/kpi mass + bool only_Bmass; //For whatever fucking reason, this forces mkpi probability to be 1, so unless you don't fit it, set this to false + bool only_angles; + bool only_mkpi; + bool reset_start; + //for a simultaneous fit: TRUE if all param names have individual suffix to distinguish between sets of parameters + bool use_individual_param_names; + bool fit_asymmetries; + bool fit_fl; + bool fit_afb; + bool fit_pprimes; + //fit m(Kpi) mass spectrum? + bool fit_mkpi; //4D+1D fit + bool fit_lambda; + //use the information of the m(Kpi) dimension in the angular_prob + bool use_mkpi; //5D fit + bool individual_penalties; + double mkpi_min; + double mkpi_max; + bool update_efficiencies; + bool squared_hesse; + bool mkpi_threshold; + bool mkpi_full_range_norm; + //Generation + bool generate_mkpi; + bool generate_only_bkg; + bool isobar; + bool multiply_eff; + bool cache_fis; + bool mcweight; + bool chisquaredstudy; + int systematic; + bool useMC; + int run; + int year; + int verbose; + std::string DDLL; + bool DTF; + bool KS; + std::vector TheQ2binsmin; + std::vector TheQ2binsmax; + bool IsFlatQ2; + int folding; + bool reject_identical_muon_TRUEID; + //File used for latex output //TODO + std::string latexFileTag; + + ///constructor + options(std::string argument=""): + ncores(1), + use_angular_acc(false), + angularacceptance(false), + angacccorrperyear(false), + angacccorrpertwoyears(false), + angacccorrbothruns(false), + only_4_1D_chi2(false), + scan_max_order_angacccorrection(false), + project(false), + write_eps(false), + write_C(false), + write_jpg(false), + write_pdf(false), + shift_lh(false), + repeat_on_fail(false), + minos_errors(false), + simplex_prerun(false), + use_mcmc(false), + hesse_postrun(true), + asymptotic(false), + weighted_fit(false), + use_weighted_bkg(false), + fit_full_angular_bkg(true), + use_event_norm(false), + static_seed(false), + always_static_seed(false), + extended_ml(false), + refitting_nominal(true), + crystalball(!DOUBLE_CB), + twotailedcrystalball(DOUBLE_CB), + swave(false), + simple_mkpi(false), + only_mass2DFit(false), + use_p2(false), + eff_order_costhetal(ORDER_COSTHETAL), + eff_order_costhetak(ORDER_COSTHETAK), + eff_order_phi(ORDER_PHI), + eff_order_q2(ORDER_Q2), + orderincrease(0), + bkg_order_costhetal(2), //TODO + bkg_order_costhetak(4), //TODO + bkg_order_phi(0), //TODO + + cutsignalwindow(false), + m_min(PDGMASS_B-B_MASS_TIGHT_WINDOW), + m_max(PDGMASS_B+B_MASS_TIGHT_WINDOW), + m_low(B_MASS_LOW), + m_high(B_MASS_HIGH), + q2_min(-1.0), + q2_max(-1.0), + initSM(false), + ctl_min(CTL_MIN), + ctl_max(CTL_MAX), + ctk_min(CTK_MIN), + ctk_max(CTK_MAX), + phi_min(PHI_MIN), + phi_max(PHI_MAX), + plots_m_bins(PLOT_NBINS_MB), + plots_mkpi_bins(PLOT_NBINS_MKSTAR), + plots_costhetal_bins(PLOT_NBINS_ANGLES), + plots_costhetak_bins(PLOT_NBINS_ANGLES), + plots_phi_bins(PLOT_NBINS_ANGLES), + plot_label("LHCb 9.1 fb^{-1}"), + plot_folder(""), + q2_label("1.1 < q^2 < 19.0"), + plot_chi2(false), + name(argument), + minuit_strategy(2.0), + flat_bkg(false), + full_angular(false), + always_generate_full_angular(true), + fitsperjob(10), + job_id(-1), + only_Bmass(false), + only_angles(false), + only_mkpi(false), + reset_start(true), + use_individual_param_names(false), + fit_asymmetries(false), + fit_fl(false), + fit_afb(false), + fit_pprimes(false), + fit_mkpi(false), + fit_lambda(false), + use_mkpi(false), + individual_penalties(false), + mkpi_min(KPI_MASS_MIN), + mkpi_max(KPI_MASS_MAX), + update_efficiencies(true), + squared_hesse(true), + mkpi_threshold(false), + mkpi_full_range_norm(false), + generate_mkpi(false), + generate_only_bkg(false), + isobar(false), + multiply_eff(false), + cache_fis(false), + mcweight(false), //Not changed anywhere, only in pdf to decide what weights to use and there it is always true, no clue what it is supposed to do + chisquaredstudy(false), + systematic(-1), + useMC(false), + run(-1), + year(-1), + verbose(2), //Set to info + DDLL("DD"), + DTF(true), + KS(true), + TheQ2binsmin(std::vector(6, 0.0)), + TheQ2binsmax(std::vector(6, 0.0)), + IsFlatQ2(true), + folding(-1), + reject_identical_muon_TRUEID(false), + latexFileTag("_basic") //TODO + { + }; + + //assignment operator: + options operator=(const options o){ + //self-assignment guard + // if (this == &o) //TODO: requires operator== + // return *this; + ncores = o.ncores; + use_angular_acc = o.use_angular_acc; + angularacceptance = o.angularacceptance; + angacccorrperyear = o.angacccorrperyear; + angacccorrpertwoyears = o.angacccorrpertwoyears; + angacccorrbothruns = o.angacccorrbothruns; + only_4_1D_chi2 = o.only_4_1D_chi2; + scan_max_order_angacccorrection = o.scan_max_order_angacccorrection; + project = o.project; + write_eps = o.write_eps; + write_C = o.write_C; + write_jpg = o.write_jpg; + write_pdf = o.write_pdf; + only_truthmatched = o.only_truthmatched; + use_truth = o.use_truth; + shift_lh = o.shift_lh; + repeat_on_fail = o.repeat_on_fail; + minos_errors = o.minos_errors; + simplex_prerun = o.simplex_prerun; + use_mcmc = o.use_mcmc; + asymptotic = o.asymptotic; + hesse_postrun = o.hesse_postrun; + weighted_fit = o.weighted_fit; + use_weighted_bkg = o.use_weighted_bkg; + fit_full_angular_bkg = o.fit_full_angular_bkg; + use_event_norm = o.use_event_norm; + static_seed = o.static_seed; + always_static_seed = o.always_static_seed; + extended_ml = o.extended_ml; + refitting_nominal = o.refitting_nominal; + crystalball = o.crystalball; + twotailedcrystalball = o.twotailedcrystalball; + swave = o.swave; + simple_mkpi = o.simple_mkpi; + only_mass2DFit = o.only_mass2DFit; + use_p2 = o.use_p2; + eff_order_costhetal = o.eff_order_costhetal; + eff_order_costhetak = o.eff_order_costhetak; + eff_order_phi = o.eff_order_phi; + eff_order_q2 = o.eff_order_q2; + bkg_order_costhetal = o.bkg_order_costhetal; + bkg_order_costhetak = o.bkg_order_costhetak; + bkg_order_phi = o.bkg_order_phi; + orderincrease = o.orderincrease; + cutsignalwindow = o.cutsignalwindow; + m_min = o.m_min; + m_max = o.m_max; + m_low = o.m_low; + m_high = o.m_high; + q2_min = o.q2_min; + q2_max = o.q2_max; + initSM = o.initSM; + ctl_min = o.ctl_min; + ctl_max = o.ctl_max; + ctk_min = o.ctk_min; + ctk_max = o.ctk_max; + phi_min = o.phi_min; + phi_max = o.phi_max; + plots_m_bins = o.plots_m_bins; + plots_mkpi_bins = o.plots_mkpi_bins; + plots_costhetal_bins = o.plots_costhetal_bins; + plots_costhetak_bins = o.plots_costhetak_bins; + plots_phi_bins = o.plots_phi_bins; + plot_label = o.plot_label; + plot_folder = o.plot_folder; + q2_label = o.q2_label; + plot_chi2 = o.plot_chi2; + name = o.name; + minuit_strategy = o.minuit_strategy; + flat_bkg = o.flat_bkg; + full_angular = o.full_angular; + always_generate_full_angular = o.always_generate_full_angular; + fitsperjob = o.fitsperjob; + job_id = o.job_id; + only_Bmass = o.only_Bmass; + only_angles = o.only_angles; + only_mkpi = o.only_mkpi; + reset_start = o.reset_start; + use_individual_param_names = o.use_individual_param_names; + fit_asymmetries = o.fit_asymmetries; + fit_fl = o.fit_fl; + fit_afb = o.fit_afb; + fit_pprimes = o.fit_pprimes; + fit_mkpi = o.fit_mkpi; + fit_lambda = o.fit_lambda; + use_mkpi = o.use_mkpi; + individual_penalties = o.individual_penalties; + mkpi_min = o.mkpi_min; + mkpi_max = o.mkpi_max; + update_efficiencies = o.update_efficiencies; + squared_hesse = o.squared_hesse; + mkpi_threshold = o.mkpi_threshold; + mkpi_full_range_norm = o.mkpi_full_range_norm; + generate_mkpi = o.generate_mkpi; + generate_only_bkg = o.generate_only_bkg; + isobar = o.isobar; + multiply_eff = o.multiply_eff; + cache_fis = o.cache_fis; + mcweight = o.mcweight; + chisquaredstudy = o.chisquaredstudy; + systematic = o.systematic; + useMC = o.useMC; + run = o.run; + year = o.year; + verbose = o.verbose; + DDLL = o.DDLL; + DTF = o.DTF; + KS = o.KS; + TheQ2binsmin = o.TheQ2binsmin; + TheQ2binsmax = o.TheQ2binsmax; + IsFlatQ2 = o.IsFlatQ2; + folding = o.folding; + reject_identical_muon_TRUEID = o.reject_identical_muon_TRUEID; + return *this; + } + + int get_job_id(); + //Check if the angle ranges are not interfering with the folding + bool canIFold(); + void reset_angle_ranges(); + void update_angle_ranges(); + unsigned int get_nQ2bins(); + //Reutrns a vector with strings of all types that are required by write_eps, write_C, write_jpg and write_pdf + std::vector getAllPlotTypes(); + void print(); +}; + +} + +std::vector get_observables_vec (fcnc::options opts); //TODO: add into fcnc class +void set_ang_year_options(fcnc::options &opts); + +//If true, than the parameter is folded and typically set to 0 //TODO: add into fcnc class +bool is_param_folded(int param, fcnc::options *opts); +#endif diff --git a/Code/FCNCFitter/sources/Core/pdf.hh b/Code/FCNCFitter/sources/Core/pdf.hh new file mode 100644 index 0000000..07819f7 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/pdf.hh @@ -0,0 +1,52 @@ +/** + * @file pdf.hh + * @author Christoph Langenbruch, Renata Kopecna + + * @date 2009-03-18 + * + */ + +#ifndef PDF_H +#define PDF_H + +namespace fcnc { + class parameters; + class event; + class options; + + +///abstract base class that defines the interface for a pdf +///your pdf needs to inherit form this and implement all the abstract methods +class pdf { +public: + virtual ~pdf() {}; + ///returns the probability of one event + virtual double prob(const parameters* params, const event& meas) const = 0; + virtual double chi2(const parameters* params) {return 0.0;}; + ///updates the cached normalization after a parameter change + virtual void update_cached_normalization(const parameters* params) = 0; + virtual void update_cached_normalization(const parameters* params, std::vector* events) {return;}; + virtual void update_cached_integrated_fis(const parameters* params) {return;}; + ///updates the cached efficiencies, useable in case of fixed q2 eff or for a weighted fit + virtual void update_cached_efficiencies(const parameters* params, std::vector* events) {return;}; + ///updates the cached xis paramters for every event, this allows to use a different q2 dependent norm for every event + virtual void update_cached_xis(const parameters* params, std::vector* events) {return;}; + ///performs the necessary initialisations for the pdf + virtual void init(parameters* params) = 0; + //I am exposing these for now, needed for the S-wave hack + virtual void get_swave_integrated_fj(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const {return;}; + virtual void get_integrated_fj(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, + double& f7, double& f8, double& f9, double& f10, double& f11, double& f12) const {return;}; + + virtual void swave_integrated_fj_noacc(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6) const {return;}; + //virtual void swave_integrated_fj_chebyshev(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, double q2) const {return;}; + virtual void integrated_fj_noacc(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, + double& f7, double& f8, double& f9, double& f10, double& f11, double& f12) const {return;}; + //virtual void integrated_fj_chebyshev(double& f1, double& f2, double& f3, double& f4, double& f5, double& f6, + // double& f7, double& f8, double& f9, double& f10, double& f11, double& f12, double q2) const {return;}; + +}; + +} + +#endif diff --git a/Code/FCNCFitter/sources/Core/plotter.hh b/Code/FCNCFitter/sources/Core/plotter.hh new file mode 100644 index 0000000..46b6885 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/plotter.hh @@ -0,0 +1,32 @@ +/** + * @file plotter.hh + * @author Christoph Langenbruch, Renata Kopecna + + * @date 2009-03-18 + * + */ + +#ifndef PLOTTER_H +#define PLOTTER_H + +#include +#include + +namespace fcnc { + class pdf; + class event; + class parameters; + +///abstract base class that defines the interface for a plotter +///your plotter needs to inherit form this and implement all the abstract methods +class plotter { +public: + virtual ~plotter() {}; + ///plots the pdf projections + virtual int plot_data(pdf* prob, parameters* params, std::vector* ev, std::string index) = 0; + +}; + +} + +#endif diff --git a/Code/FCNCFitter/sources/Core/toystudy.cc b/Code/FCNCFitter/sources/Core/toystudy.cc new file mode 100644 index 0000000..66d252b --- /dev/null +++ b/Code/FCNCFitter/sources/Core/toystudy.cc @@ -0,0 +1,355 @@ +/** + * @file toystudy.cc + * @author Renata Kopecna (cause I find 500 lines functioned defined in a header disgusting) + * @date 2021-02-25 + * + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +void fcnc::toystudy::toy(unsigned int nevents, unsigned int nruns, pdf* prob, parameters* params, generator* gen){ + std::vector the_nevents; + the_nevents.push_back(nevents); + + std::vector probs; + probs.push_back(prob); + + std::vector the_params; + the_params.push_back(params); + + std::vector gens; + gens.push_back(gen); + + toy(the_nevents, nruns, probs, the_params, gens); +} + +void fcnc::toystudy::toy(std::vector nevents, unsigned int nruns, std::vector pdfs, std::vector params, std::vector gens){ + + //Open texFile + std::ofstream myFile; + open_Latex_noteFile(latex_toyFile(), myFile); + + spdlog::info("Starting toy study on toy data"); + //unsigned int run_no = 0; + + spdlog::info("Will run over {0:d} runs with {1:d}", nruns, nevents.at(0)); + if (spdlog_info()){ + for (unsigned int i=1; iSetSeed(0);//non-static seed + //initialisation for histos and arrrays + unsigned int nparams = 0; + for (unsigned int i=0; inparameters(); + } + + std::vector pull_width(nparams, 0.0); + std::vector pull_mean(nparams, 0.0); + std::vector pull_width_sigma(nparams, 0.0); + std::vector pull_mean_sigma(nparams, 0.0); + std::vector pull_chisquared(nparams, 0.0); + std::vector value_width(nparams, 0.0); + std::vector value_mean(nparams, 0.0); + std::vector value_width_sigma(nparams, 0.0); + std::vector value_mean_sigma(nparams, 0.0); + std::vector value_chisquared(nparams, 0.0); + std::vector error_width(nparams, 0.0); + std::vector error_mean(nparams, 0.0); + std::vector error_width_sigma(nparams, 0.0); + std::vector error_mean_sigma(nparams, 0.0); + std::vector error_chisquared(nparams, 0.0); + std::vector > errors(nparams, std::vector()); + std::vector > errors_up(nparams, std::vector()); + std::vector > errors_down(nparams, std::vector()); + std::vector > values(nparams, std::vector()); + std::vector > nominal_errors(nparams, std::vector()); + std::vector > nominal_values(nparams, std::vector()); + std::vector return_values(nruns); + std::vector > > corrs(nparams, std::vector >()); + + fcnc::fitter fit(opts); + for (unsigned int i=0; iinit(params.at(i)); + } + fit.set_common_parameters(common_params); + + for (unsigned int i=0; i < nruns; i++) { + spdlog::info("Starting run no. {0:d}", i + 1); + //run_no = i; + + std::vector< std::vector > temp_events; + for (unsigned int j=0; j ev = gens.at(j)->generate(nevents.at(j), params.at(j), pdfs.at(j)); + temp_events.push_back(ev); + } + std::vector< std::vector* > events; + for (unsigned int j=0; jnparameters(); k++){ + parameter* param = params.at(j)->get_parameter(k); + double shift = rnd->Rndm() > 0.5 ? -fabs(rnd->Gaus(0.0, param->get_previous_error_low())) : fabs(rnd->Gaus(0.0, param->get_previous_error_high()));//TODO, actually should probably use PDG method + if (param->get_gaussian_constraint()){ + param->set_previous_measurement(param->get_start_value() + shift);//rnd->Gaus(0.0, sigma)); + } + } + } + if (opts->eos_bsz_ff){ + TMatrixD mU = fcnc::get_bsz_mu_invcov(); + + std::vector rndvec(21, 0.0); + for (unsigned int i=0; i<21; i++){ + rndvec.at(i) = rnd->Gaus(0.0, 1.0); + } + std::vector shiftvec(21, 0.0); + for (unsigned int i=0; i<21; i++){ + for (unsigned int j=0; j<21; j++){ + shiftvec.at(i) += mU(j,i)*rndvec.at(j);//new order, corrected and tested + } + } + for (unsigned int j = 0; j < params.size(); j++){ + if (params.at(j)->get_parameter("a0_0") != 0){ + //TODO: jitter according to covariance matrix given + //std::vector coeffvec(21, 0.0);// = nominal;//fcnc::legendre_coefficients_nominal; + for (unsigned int i=0; i<21; i++){ + parameter* param = 0; + switch (i) { + case 0 : param = params.at(j)->get_parameter("a0_0"); break; + case 1 : param = params.at(j)->get_parameter("a0_1"); break; + case 2 : param = params.at(j)->get_parameter("a0_2"); break; + case 3 : param = params.at(j)->get_parameter("a1_0"); break; + case 4 : param = params.at(j)->get_parameter("a1_1"); break; + case 5 : param = params.at(j)->get_parameter("a1_2"); break; + //case 6 : param = params.at(j)->get_parameter(""); break; + case 7 : param = params.at(j)->get_parameter("a12_1"); break; + case 8 : param = params.at(j)->get_parameter("a12_2"); break; + case 9 : param = params.at(j)->get_parameter("v_0"); break; + case 10 : param = params.at(j)->get_parameter("v_1"); break; + case 11 : param = params.at(j)->get_parameter("v_2"); break; + case 12 : param = params.at(j)->get_parameter("t1_0"); break; + case 13 : param = params.at(j)->get_parameter("t1_1"); break; + case 14 : param = params.at(j)->get_parameter("t1_2"); break; + //case 15 : param = params.at(j)->get_parameter(""); break; + case 16 : param = params.at(j)->get_parameter("t2_1"); break; + case 17 : param = params.at(j)->get_parameter("t2_2"); break; + case 18 : param = params.at(j)->get_parameter("t23_0"); break; + case 19 : param = params.at(j)->get_parameter("t23_1"); break; + case 20 : param = params.at(j)->get_parameter("t23_2"); break; + }; + if (param != 0){ + param->set_previous_measurement(param->get_start_value() + shiftvec.at(i)); + } + } + } + } + } + //perform the actual fit + result = fit.fit(pdfs, params, events, num); + return_values.at(i) = result; + + if (result != 300 && opts->repeat_on_fail) { + spdlog::error("Fit failed, repeating run"); + for (unsigned int j = 0; j < params.size(); j++){ + params.at(j)->reset_parameters(); + } + i--; + continue; + } + + //extract the parameters from the fit + unsigned int start_param = 0; + for (unsigned int j = 0; j < params.size(); j++) { + for (unsigned int k = 0; k < params.at(j)->nparameters(); k++){ + parameter* param = params.at(j)->get_parameter(k); + unsigned int idx = start_param+k; + values.at(idx).push_back(param->get_value()); + errors.at(idx).push_back(param->get_error()); + errors_up.at(idx).push_back(param->get_error_up()); + errors_down.at(idx).push_back(param->get_error_down()); + corrs.at(idx).push_back(param->correlations);//for some, this is empty + } + start_param += params.at(j)->nparameters(); + } + //todo whats this? //I don't know, David. Sincerely, Renata + for (unsigned int j = 0; j < nparams; j++){ + nominal_values.at(j).push_back(0.0); + nominal_errors.at(j).push_back(0.0); + } + + //Update pull histos every 10 steps or when finished. + //if ((i+1 >= 100) && (((i+1)%100 == 0) || (i+1 == nruns))) + if (i+1 == nruns) { + //This should be done a little differently: + //recreate histos every time, use min and max values as axis. + start_param = 0; + for (unsigned int j = 0; j < params.size(); j++){//this plots the pull histos + for (unsigned int k = 0; k < params.at(j)->nparameters(); k++){//this plots the pull histos + parameter* par = params.at(j)->get_parameter(k); + if (par->get_step_size() != 0.0) { + unsigned int idx = start_param+k; + update_pull(par, values.at(idx), + errors.at(idx), + pull_mean[idx], pull_mean_sigma[idx], + pull_width[idx], pull_width_sigma[idx], + pull_chisquared[idx]); + update_value(par, values.at(idx), errors.at(idx), + value_mean[idx], value_mean_sigma[idx], + value_width[idx], value_width_sigma[idx], + value_chisquared[idx]); + update_error(par, values.at(idx), errors.at(idx), + error_mean[idx], error_mean_sigma[idx], + error_width[idx], error_width_sigma[idx], + error_chisquared[idx]); + } + } + start_param += params.at(j)->nparameters(); + } + } + + for (unsigned int j = 0; j < params.size(); j++){ + params.at(j)->reset_parameters(); + } + + spdlog::info("Run {0:d} finished", i + 1); + } + //delete rnd; + + //save result trees to root file + //TFile* output; + output->cd(); + int param_index = 0; + + unsigned int start_param = 0; + for (unsigned int j = 0; j < params.size(); j++){ + for (unsigned int k = 0; k < params.at(j)->nparameters(); k++){ + parameter* param = params.at(j)->get_parameter(k); + unsigned int idx = start_param+k; + //for (unsigned int j = 0; j < nparams; j++)//this gives nice output + if (param->get_step_size() != 0.0) {//todo common parameters, only save once... + std::string parname(param->get_name()); + std::string pardesc(param->get_description()); + TTree* t = new TTree(parname.c_str(), pardesc.c_str()); + double value, error, error_up, error_down, start_value, nominal_value, nominal_error; + int run, migrad, status_cov; + double tmp_corr[corrs.at(idx).at(0).size()]; + t->Branch("run",&run,"run/I"); + t->Branch("value",&value,"value/D"); + t->Branch("error",&error,"error/D"); + t->Branch("error_up",&error_up,"error_up/D"); + t->Branch("error_down",&error_down,"error_down/D"); + t->Branch("start_value",&start_value,"start_value/D"); + t->Branch("migrad",&migrad,"migrad/I"); + t->Branch("status_cov",&status_cov,"status_cov/I"); + t->Branch("nominal_value",&nominal_value,"nominal_value/D"); + t->Branch("nominal_error",&nominal_error,"nominal_error/D"); + t->Branch("index",¶m_index, "index/I"); + std::string corr_string = "correlations"; + std::stringstream corr_stream; + corr_stream << "correlations[" << corrs.at(idx).at(0).size() << "]/D"; + t->Branch("correlations",&tmp_corr,corr_stream.str().c_str()); + for (unsigned int i=0; iis_blind()){ + value = values.at(idx).at(i) + param->get_blinding_delta();//TODO add delta + } + else{ + value = values.at(idx).at(i);//TODO add delta + } + error = errors.at(idx).at(i); + if (param->is_blind()){ + nominal_value = nominal_values.at(idx).at(i) + param->get_blinding_delta(); + } + else{ + nominal_value = nominal_values.at(idx).at(i); + } + nominal_error = nominal_errors.at(idx).at(i); + error_up = errors_up.at(idx).at(i); + error_down = errors_down.at(idx).at(i); + if (param->is_blind()){ + start_value = param->get_start_value() + param->get_blinding_delta(); + } + else{ + start_value = param->get_start_value(); + } + migrad = return_values.at(i) % 100; + status_cov = return_values.at(i) / 100; + //corr = corrs.at(idx).at(i); + for (unsigned int l = 0; l < corrs.at(idx).at(i).size(); l++){ + tmp_corr[l] = corrs.at(idx).at(i).at(l); + } + t->Fill(); + } + t->Write(); + delete t; + param_index++; + } + } + start_param += params.at(j)->nparameters(); + } + //latex output + bool blind = false; + for (unsigned int j = 0; j < params.size(); j++){ + if (!params.at(j)->is_blind()) blind = true; + } + spdlog::info("Toy Study results"); + if (!blind){ + myFile <<"\\begin{tabular}{|cccccccc|}\\hline" << std::endl; + myFile <<"\\# & parameter & Mean Value & Mean Width & Mean Error & Error Width & Pull Mean & Pull Width \\\\ \\hline \\hline" << std::endl; + start_param = 0; + for (unsigned int j = 0; j < params.size(); j++) + { + for (unsigned int k = 0; k < params.at(j)->nparameters(); k++) + { + parameter* param = params.at(j)->get_parameter(k); + unsigned int idx = start_param+k; + if (param->get_step_size() != 0.0){ + std::string partex = param->get_description(); + myFile <nparameters(); + } + myFile <<"\\hline\\end{tabular}" << std::endl; + } + + delete rnd; + + //Close Latex file + myFile.close(); + +} + + diff --git a/Code/FCNCFitter/sources/Core/toystudy.hh b/Code/FCNCFitter/sources/Core/toystudy.hh new file mode 100644 index 0000000..3d32f01 --- /dev/null +++ b/Code/FCNCFitter/sources/Core/toystudy.hh @@ -0,0 +1,64 @@ +/** + * @file toystudy.hh + * @author Christoph Langenbruch, Renata Kopecna + + * @date 2010-10-15 + * + */ + +#ifndef TOYSTUDY_H +#define TOYSTUDY_H + +#include +#include + +#include + +namespace fcnc { + class options; + class pdf; + class parameters; + class generator; + +///class to perform a toystudy, i.e. a repeated fit using generated toy data +//template +class toystudy: public multifit { +private: + ///common parameters in different parameter sets + std::vector< std::string > common_params; +public: + ///constructor + toystudy(options* o); + /** + * perform a toy study on generated toy data + * @param nevents the number of events used per fit of the toy data + * @param nruns the number of repeats + * @param prob pointer to the pdf to use in the likelihood fit + * @param params pointer to parameterset to use in the likelihood fit + * @param gen pointer to the toy data generator to use + **/ + void toy(unsigned int nevents, unsigned int nruns, pdf* prob, parameters* params, generator* gen); + /** + * perform a toy study on fully simulated mc data + * @param nevents the number of events used per fit of the toy data + * @param nruns the number of repeats + * @param pdfs pointer to the pdfs to use in the likelihood fit + * @param params pointer to parametersets to use in the likelihood fit + * @param string filename to load + **/ + void toy(std::vector nevents, unsigned int nruns, std::vector pdfs, std::vector params, std::vector gens); + ///set common parameters + void set_common_parameters(std::vector common_pars) { + common_params = common_pars; + }; +}; + +toystudy::toystudy(options* o): + multifit(o) +{ +}; + +} + + +#endif diff --git a/Code/FCNCFitter/sources/Helpers/colors.hh b/Code/FCNCFitter/sources/Helpers/colors.hh new file mode 100644 index 0000000..5885423 --- /dev/null +++ b/Code/FCNCFitter/sources/Helpers/colors.hh @@ -0,0 +1,115 @@ +//Renata Kopecna + +#include "TColor.h" +#include + +#ifndef COLORS_HH +#define COLORS_HH + +//========================================= +// +// Colors +// +//========================================= + +namespace myColorScheme{ + /* // Taken from https://gist.github.com/gipert/df72b67c1d02bbb41f1dd406b6397811 + * Handy enum for later color referencing + */ + enum { + // Bright color scheme + kTBriBlue = 9000, + kTBriCyan = 9001, + kTBriGreen = 9002, + kTBriYellow = 9003, + kTBriRed = 9004, + kTBriPurple = 9005, + kTBriGrey = 9006, + + // Vibrant color scheme + kTVibBlue = 9007, + kTVibCyan = 9008, + kTVibTeal = 9009, + kTVibOrange = 9010, + kTVibRed = 9011, + kTVibMagenta = 9012, + kTVibGrey = 9013, + + // Muted color scheme //10 colors + kTMutIndigo = 9014, + kTMutCyan = 9015, + kTMutTeal = 9016, + kTMutGreen = 9017, + kTMutOlive = 9018, + kTMutSand = 9019, + kTMutRose = 9020, + kTMutWine = 9021, + kTMutPurple = 9022, + kTMutPaleGrey = 9023, + + // Light color scheme //9 colors + kTLigLightBlue = 9024, + kTLigLightCyan = 9025, + kTLigMint = 9026, + kTLigPear = 9027, + kTLigOlive = 9028, + kTLigLightYellow = 9029, + kTLigOrange = 9030, + kTLigPink = 9031, + kTLigPaleGrey = 9032, + + // To label "bad" data (see BuRd and PRGn palettes below) + kTBadData = 9033 + + + }; + + void init() { + gStyle->SetColorModelPS(0); + + // Bright color scheme + new TColor(kTBriBlue, 68./255, 119./255, 170./255, "tol-bri-blue" ); + new TColor(kTBriCyan, 102./255, 204./255, 238./255, "tol-bri-cyan" ); + new TColor(kTBriGreen, 34./255, 136./255, 51./255, "tol-bri-green" ); + new TColor(kTBriYellow, 204./255, 187./255, 68./255, "tol-bri-yellow" ); + new TColor(kTBriRed, 238./255, 102./255, 119./255, "tol-bri-red" ); + new TColor(kTBriPurple, 170./255, 51./255, 119./255, "tol-bri-purple" ); + new TColor(kTBriGrey, 187./255, 187./255, 187./255, "tol-bri-grey" ); + + // Vibrant color scheme + new TColor(kTVibBlue, 0./255, 119./255, 187./255, "tol-vib-blue" ); + new TColor(kTVibCyan, 51./255, 187./255, 238./255, "tol-vib-cyan" ); + new TColor(kTVibTeal, 0./255, 153./255, 136./255, "tol-vib-teal" ); + new TColor(kTVibOrange, 238./255, 119./255, 51./255, "tol-vib-orange" ); + new TColor(kTVibRed, 204./255, 51./255, 17./255, "tol-vib-red" ); + new TColor(kTVibMagenta, 238./255, 51./255, 119./255, "tol-vib-magenta" ); + new TColor(kTVibGrey, 187./255, 187./255, 187./255, "tol-vib-grey" ); + + // Muted color scheme + new TColor(kTMutIndigo, 51./255, 34./255, 136./255, "tol-mut-indigo" ); + new TColor(kTMutCyan, 136./255, 204./255, 238./255, "tol-mut-cyan" ); + new TColor(kTMutTeal, 68./255, 170./255, 153./255, "tol-mut-teal" ); + new TColor(kTMutGreen, 17./255, 119./255, 51./255, "tol-mut-green" ); + new TColor(kTMutOlive, 153./255, 153./255, 51./255, "tol-mut-olive" ); + new TColor(kTMutSand, 221./255, 204./255, 119./255, "tol-mut-sand" ); + new TColor(kTMutRose, 204./255, 102./255, 119./255, "tol-mut-rose" ); + new TColor(kTMutWine, 136./255, 34./255, 85./255, "tol-mut-wine" ); + new TColor(kTMutPurple, 170./255, 68./255, 153./255, "tol-mut-purple" ); + new TColor(kTMutPaleGrey, 221./255, 221./255, 221./255, "tol-mut-palegrey" ); + + // Light color scheme + new TColor(kTLigLightBlue, 119./255, 170./255, 221./255, "tol-lig-lightblue" ); + new TColor(kTLigLightCyan, 153./255, 221./255, 255./255, "tol-lig-lightcyan" ); + new TColor(kTLigMint, 68./255, 187./255, 153./255, "tol-lig-mint" ); + new TColor(kTLigPear, 187./255, 204./255, 51./255, "tol-lig-pear" ); + new TColor(kTLigOlive, 170./255, 170./255, 0./255, "tol-lig-olive" ); + new TColor(kTLigLightYellow, 238./255, 221./255, 136./255, "tol-lig-lightyellow"); + new TColor(kTLigOrange, 238./255, 136./255, 102./255, "tol-lig-orange" ); + new TColor(kTLigPink, 255./255, 170./255, 187./255, "tol-lig-pink" ); + new TColor(kTLigPaleGrey, 221./255, 221./255, 221./255, "tol-lig-palegrey" ); + + new TColor(kTBadData, 255./255, 238./255, 153./255, "tol-bad-data" ); + } +}; + +#endif // COLORS_HH diff --git a/Code/FCNCFitter/sources/Helpers/design.cc b/Code/FCNCFitter/sources/Helpers/design.cc new file mode 100644 index 0000000..07d1784 --- /dev/null +++ b/Code/FCNCFitter/sources/Helpers/design.cc @@ -0,0 +1,621 @@ +//Renata Kopecna + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +//========================================= +// +// Latex in plots +// +//========================================= + +std::string latex_decay(bool DTF){ + //return "K_{S}^{0}#pi^{+}#mu^{+}#mu^{-}"; + if (DTF) return "K^{+}#pi^{0}#mu^{+}#mu^{-}"; + else return "#K^{+}#gamma#gamma#mu^{+}#mu^{-}"; +} + +std::string latex_Kst_decay(bool DTF){ + if (DTF) return "K^{+}#pi^{0}"; + else return "#K^{+}#gamma#gamma"; +} + +std::string MeVc(){ + return "MeV"; +} +std::string GeVc(){ + return "GeV"; +} +std::string GeVc_2(){ + return "GeV^{2}"; +} + +std::string latex_pull(){ + return "(x-x_{0})/#sigma"; +} + +std::string latex_angle(std::string angle, bool &is_ctl, bool &is_ctk, bool &is_phi){ + + if(strcmp(angle.c_str(), "ctk") == 0){ + is_ctk = true; + return "cos(#Theta_{K})"; + } + else if(strcmp(angle.c_str(), "ctl") == 0){ + is_ctl = true; + return "cos(#Theta_{L})"; + } + else if(strcmp(angle.c_str(), "phi") == 0){ + is_phi = true; + return "#phi [rad]"; + } + return ""; +} + +//Define the angles as chars, because ROOT +//Very not cool, but also very not cool +//of ROOT to not accept strings and I cannot be bothered +const char *LATEX_Q2_CH() { return LATEX_Q2.c_str(); } +const char *LATEX_TL_CH() { return LATEX_TL.c_str(); } +const char *LATEX_CTL_CH(){ return LATEX_CTL.c_str();} +const char *LATEX_TK_CH() { return LATEX_TK.c_str(); } +const char *LATEX_CTK_CH(){ return LATEX_CTK.c_str();} +const char *LATEX_PHI_CH(){ return LATEX_PHI.c_str();} + +std::string q2_label(double low_q2, double high_q2){ + std::ostringstream qqbin; //TODO + qqbin << std::fixed << std::setprecision(2) <SetOptStat(0); + gStyle->SetOptFit(0); + gStyle->SetLabelFont(132, "xyz"); + gStyle->SetTitleFont(132, "xyz"); + gStyle->SetLegendFont(132); + gStyle->SetStatFont(132); + gStyle->SetPaintTextFormat(".1f"); +} + +//Save canvas with a given name and automatically append the type +//Type should be specified without the dot, so eg "eps" instead of ".eps +void saveTCanvas(TCanvas *c, std::string name, std::string type){ + c->Print((name+"."+type).c_str(), type.c_str()); + return; +} + +//Save several file types in one go +void saveTCanvas(TCanvas *c, std::string name, std::vector types){ + for (auto type: types) saveTCanvas(c,name,type); + return; +} + + +TLine *threeSigmaLine(double min, double max, bool plus){ + int sigma = plus ? +3.0 : -3.0; + TLine * line = new TLine(min, sigma, max, sigma); + line->SetLineStyle(5); + line->SetLineWidth(gStyle->GetLineWidth()); + return line; +} +TLine *oneSigmaLine(double min, double max, bool plus){ + int sigma = plus ? +1.0 : -1.0; + TLine * line = new TLine(min, sigma, max, sigma); + line->SetLineStyle(7); + line->SetLineWidth(gStyle->GetLineWidth()); + return line; +} + +void plotAndSave(TH1D *hist, std::string canvasName, std::string targetPath, std::string plotType){ + + TCanvas* cnvs = new TCanvas(canvasName.c_str(), canvasName.c_str(), 1600, 1200); + cnvs->cd(); + hist->Draw(); + saveTCanvas(cnvs,targetPath, plotType); + + delete cnvs; + return; + +} +void plotAndSave(TH2D *hist, std::string canvasName, std::string targetPath, std::string plotType){ + + TCanvas* cnvs = new TCanvas(canvasName.c_str(), canvasName.c_str(), 1600, 1200); + cnvs->cd(); + hist->Draw("COLZ"); + saveTCanvas(cnvs,targetPath, plotType); + + delete cnvs; + return; + +} + +void plotAndSaveWithLine(TH1D* hist, TF1 *line, std::string canvasName, std::string targetPath, std::string plotType){ + + //Create canvas + TCanvas* cnvs = new TCanvas(canvasName.c_str(), canvasName.c_str(), 1600, 1200); + cnvs->cd(); + + //Add legend + //TLatex cannot do break lines and I cannot. Even. + TPaveText *leg = new TPaveText(0.55,0.65,0.87,0.87); + leg->Paint("NDC"); + leg->SetFillColor(kWhite); + leg->SetTextFont(132); + //Loop over params and print them + for (int n = 0; n < line->GetNpar(); n++){ + std::ostringstream sParams; + sParams << line->GetParName(n) << ": " << std::fixed << std::setprecision(4) << line->GetParameter(n) << "#pm" << line->GetParError(n); + leg->AddText(sParams.str().c_str()); + } + + //Draw + hist->Draw("E1"); + line->Draw("same"); + leg->Draw("same"); + + //Save + cnvs->Print((targetPath+"."+plotType).c_str(), plotType.c_str()); + + //Delete and return + delete leg; + delete cnvs; + return; + +} + +//Sets TLatex +TLatex *getPrettyTex(double TextFontSize, int TextAlign){ + TLatex *tex = new TLatex(); + tex->SetNDC(true); + tex->SetTextFont(132); + tex->SetTextSize(TextFontSize); + tex->SetTextAlign(TextAlign); + return tex; +} + +//Add myThesis tag +void addThesistag(double x = 0.6, double y = 0.85, int color = 1, double scaling = 1.0){ + if (!PLOT_THISTHESIS_TAG) return; + TLatex* lhcbtext = getPrettyTex(0.07*scaling, 13); + lhcbtext->SetTextColor(color); + lhcbtext->DrawLatex(x,y,THISTHESIS_TAG.c_str()); + return; +} +//Add lhcb tag +void addLHCbtag(double x = 0.6, double y = 0.85, std::string suffix = "", int color = 1, double scaling = 1.0){ + TLatex* lhcbtext = getPrettyTex(0.07*scaling, 13); + lhcbtext->SetTextColor(color); + lhcbtext->DrawLatex(x,y,("LHCb "+suffix).c_str()); + return; +} + +//========================================= +// +// Angular correction plots +// +//========================================= + +//plot eff histograms for angular corrections +void plotAngular(TH1D *hist, TH1D *moments, bool write,std::string name, + std::string appendix, std::string q2region, + TLatex *tex, std::string folderName){ + TCanvas* c0 = new TCanvas("c0", "c0", 1600, 1200); + c0->cd(); + hist->Scale(hist->GetNbinsX()/hist->Integral()); + hist->SetMinimum(0.0); + hist->Draw(); + hist->GetYaxis()->SetTitle("Normalized entries (a.u.)"); + moments->Scale(moments->GetNbinsX()/moments->Integral()); + addLHCbtag(0.15,0.27,"simulation",1,1.0); + addThesistag(0.15,0.20,1,0.9); + moments->Draw("samel"); + + if (q2region != "") tex->DrawLatex(0.85, 0.15, q2region.c_str()); + if (write) saveTCanvas(c0,folderName+name+appendix,"eps"); + delete c0; +} + +//Overload the plot without plotting q2 region +void plotAngular(TH1D *hist, TH1D *moments, bool write,std::string name, std::string appendix, std::string folderName){ + TLatex *tex = new TLatex(); + plotAngular(hist, moments, write, name, appendix, "", tex, folderName); +} + +//plot 2D histograms for angular corrections +void plotAngular(TH2D *hist, TH2D *moments, bool write, std::string name, std::string appendix, std::string q2region, TLatex *tex, std::string folderName){ + TCanvas* c0 = new TCanvas("c0", "c0", 1600, 800); + c0->Divide(2,1); + c0->cd(1); + hist->Scale(hist->GetNbinsX()*hist->GetNbinsY()/hist->Integral()); + hist->SetMinimum(0.0); + hist->SetMaximum(1.4); + hist->Draw("colz"); + c0->cd(2); + moments->Scale(moments->GetNbinsX()*moments->GetNbinsY()/moments->Integral()); + moments->SetMinimum(0.0); + moments->SetMaximum(1.4); + moments->Draw("colz"); + if (q2region != "") tex->DrawLatex(0.85, 0.15, q2region.c_str()); + if (write) saveTCanvas(c0,folderName+name+appendix,"eps"); + delete c0; +} + +//Overload the plot without plotting q2 region +void plotAngular(TH2D *hist, TH2D *moments, bool write,std::string name, std::string appendix, std::string folderName){ + TLatex *tex = new TLatex(); + plotAngular(hist, moments, write, name, appendix, "", tex, folderName); +} + +//Plot all the angular corrections in one canvas +void plotAngularInOne(TCanvas *c, int whichC, TH1D *moments, TH1D *ub, TH1D *hist, TH1D* ml, bool run_minuit, double q2min, double q2max, double y, bool cross){ + c->cd(whichC)->SetMargin(0.15,0.05,0.1,0.05); + moments->Draw("l"); + + TLine* line= new TLine(); + line->SetLineStyle(kDashed); + if (cross){ + line->SetLineColor(kGray+1); + line->DrawLine(q2min, -0.5, q2max, +0.5); + line->DrawLine(q2min, +0.5, q2max, -0.5); + } + else{ + ub->Draw("same"); + hist->Draw("same"); + if (run_minuit) ml->Draw("lsame"); + line->SetLineColor(kRed); + line->DrawLine(q2min, y, q2max, y); + } +} + +//Label axes for angular correction polynomial scan +void labelAngularScan(std::vectorscan_low, std::vectorscan_range,TH2D *hist){ + + //label the x-axis + //loop over the range in thetak and thetal and print all possible combination + for(int tk = 0; tk < scan_range.at(1); tk++){ + for(int tl = 0; tl < scan_range.at(2); tl++){ + hist->GetXaxis()->SetBinLabel(tk * scan_range.at(2) + tl + 1, //+1 because bins start at 1 + ("#bf{"+std::to_string(tk+scan_low.at(1))+"} - "+std::to_string(tl+scan_low.at(2))).c_str()); + } + } + + //label the y-axis + for(int qq = 0; qq < scan_range.at(0); qq++){ + for(int fi =0; fi < scan_range.at(3); fi++){ + hist->GetYaxis()->SetBinLabel(qq * scan_range.at(3) + fi + 1, + ("#bf{"+std::to_string(qq+scan_low.at(0))+"} - "+std::to_string(fi+scan_low.at(3))).c_str()); + } + } + + //draw labels on x-axis vertically + hist->GetXaxis()->LabelsOption("v"); + + return; +} + +//========================================= +// +// Fit results plots +// +//========================================= +int design_pull_basic(TH1D *pull, Float_t textsize, double eff_pullHeight){ + pull->GetXaxis()->SetNoExponent(); //<-- spoils MaxDigits settings, so don't use it on other axis + pull->GetXaxis()->SetNdivisions(gStyle->GetNdivisions("X")); + + pull->GetYaxis()->SetTitleSize(textsize/eff_pullHeight); + pull->GetYaxis()->SetLabelSize(textsize/eff_pullHeight); + pull->GetYaxis()->SetTitleOffset(gStyle->GetTitleOffset()*eff_pullHeight); + + return 0; +} +int design_pull(TH1D *pull, Color_t lineColor, Color_t fillColor, double eff_pullHeight, double pullFrameRange){ + Float_t textsize = gStyle->GetTextSize(); + pull->GetXaxis()->SetTitleOffset(1.05); + design_pull_basic(pull, textsize, eff_pullHeight); + + pull->GetXaxis()->SetTitleSize (textsize/eff_pullHeight); + pull->GetXaxis()->SetLabelSize (textsize/eff_pullHeight); + pull->GetXaxis()->SetTickLength (pull->GetXaxis()->GetTickLength()/(eff_pullHeight/(1-eff_pullHeight))); + + pull->GetYaxis()->CenterTitle(); + pull->GetYaxis()->SetNdivisions (3, 9, 0, kTRUE);//gStyle->GetNdivisions("Y")); + pull->GetYaxis()->SetRangeUser (-pullFrameRange, pullFrameRange); + pull->SetFillColor(fillColor); + pull->SetLineColor(lineColor); + pull->SetLineWidth(1); + + return 0; +} +int design_pull(TGraphErrors *pull, Color_t lineColor, Color_t fillColor, double eff_pullHeight, double pullFrameRange){ + Float_t textsize = gStyle->GetTextSize(); + pull->GetXaxis()->SetTitleOffset(1.05); + pull->GetXaxis()->SetNoExponent(); //<-- spoils MaxDigits settings, so don't use it on other axis + + pull->GetYaxis()->SetTitleSize(textsize/eff_pullHeight); + pull->GetYaxis()->SetLabelSize(textsize/eff_pullHeight); + pull->GetYaxis()->SetTitleOffset(gStyle->GetTitleOffset()*eff_pullHeight); + + pull->GetXaxis()->SetTitleSize (textsize/eff_pullHeight); + pull->GetXaxis()->SetLabelSize (textsize/eff_pullHeight); + pull->GetXaxis()->SetTickLength (pull->GetXaxis()->GetTickLength()/(eff_pullHeight/(1-eff_pullHeight))); + + pull->GetYaxis()->CenterTitle(); + pull->GetYaxis()->SetRangeUser (-pullFrameRange, pullFrameRange); + pull->SetFillColor(fillColor); + pull->SetLineColor(lineColor); + pull->SetLineWidth(1); + + return 0; +} + +void drawResonances(TCanvas *c, double min, double max){ + c->cd(); + TBox* box = new TBox(); + box->SetFillColor(21); + box->SetLineColor(21); + box->SetFillStyle(1001); + box->DrawBox(0.98, min, 1.10, max); + box->DrawBox(8.0, min, 11.0, max); + box->DrawBox(12.5, min, 15.0, max); + c->Update(); //Probably not needed, but just ot be sure + return; +} +void drawResonances(TPad *c, double min, double max){ + c->cd(); + TBox* box = new TBox(); + box->SetFillColor(21); + box->SetLineColor(21); + box->SetFillStyle(1001); + box->DrawBox(0.98, min, 1.10, max); + box->DrawBox(8.0, min, 11.0, max); + box->DrawBox(12.5, min, 15.0, max); + c->Update(); //Probably not needed, but just ot be sure + return; +} + + +void designTGraph(TGraphErrors *graph, std::string title, std::string xAxisName, std::string yAxisName, Color_t color, Int_t markerStyle){ + graph->SetName(title.c_str()); + graph->SetLineColor(color); + //graph->SetLineWidth(0); + graph->SetMarkerStyle(markerStyle); + graph->SetMarkerColor(color); + graph->GetXaxis()->SetTitle(xAxisName.c_str()); + graph->GetYaxis()->SetTitle(yAxisName.c_str()); + + graph->GetXaxis()->SetTitleOffset(1.0); + graph->GetYaxis()->SetTitleOffset(1.7); + graph->SetTitle(""); + graph->GetXaxis()->SetLabelSize(0.09); + graph->GetYaxis()->SetLabelSize(0.09); + graph->GetXaxis()->SetTitleSize(0.07); + graph->GetYaxis()->SetTitleSize(0.05); + return; +} + +void designMultiGraph(TMultiGraph *multGraph, std::string title, std::string xAxisName, std::string yAxisName){ + + //One needs to draw the multGraph first! + multGraph->SetName(title.c_str()); + multGraph->GetXaxis()->SetTitle(xAxisName.c_str()); + multGraph->GetYaxis()->SetTitle(yAxisName.c_str()); + gStyle->SetOptStat(0); + + multGraph->GetXaxis()->SetTitleOffset(1.0); + multGraph->GetYaxis()->SetTitleOffset(1.4); + multGraph->SetTitle(""); + multGraph->GetXaxis()->SetLabelSize(0.05); + multGraph->GetYaxis()->SetLabelSize(0.05); + multGraph->GetXaxis()->SetTitleSize(0.05); + multGraph->GetYaxis()->SetTitleSize(0.055); + return; +} + + +int design_YieldInQ2(int Run, TGraphErrors *graphSig, TGraphErrors *graphBkg, TGraphErrors *graphSignificance, TGraphErrors *CMS, bool fixRange, std::string savePath, std::vector extensions){ + + std::string mainName = "Q2_Run" + std::to_string(Run); + double y_scale = 1.5; + double y_scale_1 = (Run==1) ? 2.5 : 1.75; + + //Create a TCanvas + TCanvas *c = new TCanvas(mainName.c_str(),mainName.c_str(),750, 575); + c->SetRightMargin(0.13); + c->SetLeftMargin(0.23); + c->SetTopMargin(0.075); + c->SetBottomMargin(0.12); + c->cd(); + + designTGraph(graphSig,"Signal","Q2","Yield",kBlack,20); + designTGraph(graphBkg,"Background","Q2","Yield",kRed,20); + graphSig->SetLineStyle(1); + graphSig->SetLineWidth(1); + graphSig->SetMarkerSize(0.5); + graphBkg->SetLineStyle(1); + graphBkg->SetLineWidth(1); + graphBkg->SetMarkerSize(0.65); + + designTGraph(graphSignificance,"Significance","Q2","S/(S+B)",kBlue,20); + designTGraph(CMS,"Significance_CMS","Q2","S/(S+B)",kGreen+2,20); + + graphSignificance->GetYaxis()->SetRangeUser(0.0,graphSignificance->GetY()[0]*y_scale); + graphSignificance->GetXaxis()->SetRangeUser(Q2_MIN_RANGE,Q2_MAX_RANGE); + CMS->GetXaxis()->SetRangeUser(Q2_MIN_RANGE,Q2_MAX_RANGE); + graphSignificance->SetLineWidth(3); + CMS->SetLineWidth(3); + + //Create multigraphs + TMultiGraph *mg = new TMultiGraph(); + mg->Add(graphSig,"AP"); + mg->Add(graphBkg,"AP"); + mg->Draw("AP"); + mg->GetYaxis()->SetRangeUser(0.0,graphBkg->GetY()[1]*y_scale); + mg->GetXaxis()->SetRangeUser(Q2_MIN_RANGE,Q2_MAX_RANGE); + designMultiGraph(mg,"","q^{2} [GeV^{2}]","Yield"); + + TMultiGraph *mg_FoM = new TMultiGraph(); + mg_FoM->Add(graphSignificance,"AP"); + mg_FoM->Add(CMS,"AP"); + mg_FoM->Draw("AP"); + mg_FoM->GetXaxis()->SetRangeUser(Q2_MIN_RANGE,Q2_MAX_RANGE); + designMultiGraph(mg_FoM,"","q^{2} [GeV^{2}]","S/(S+B)"); + + + //Create two pads (to get significance y-axis on the right) + TPad *pad1 = new TPad("pad1","",0,0,1,1); + TPad *pad2 = new TPad("pad2","",0,0,1,1); + + pad2->SetFillStyle(4000); //will be transparent + pad2->SetFrameFillStyle(0); + + pad1->SetRightMargin(0.13); + pad1->SetLeftMargin(0.15); + pad1->SetTopMargin(0.07); + pad1->SetBottomMargin(0.12); + + pad2->SetRightMargin(0.13); + pad2->SetLeftMargin(0.15); + pad2->SetTopMargin(0.07); + pad2->SetBottomMargin(0.12); + + pad1->Draw(); + pad1->cd(); + + //Add legends + TLegend *leg = new TLegend(0.15,0.93,0.52,0.82); + leg->AddEntry(graphSig, "Signal yield","l"); + leg->AddEntry(graphBkg, "Background yield","l"); + + TLegend *legSignificance = new TLegend(0.52,0.93,0.8,0.82); + legSignificance->AddEntry(graphSignificance, "Significance","l"); + legSignificance->AddEntry(CMS, "CMS","l"); + + //Plot it + pad1->cd(); + gStyle->SetGridColor(kGray); + pad1->SetGridy(); + pad1->SetGridx(); + mg->Draw("SAME"); + mg->GetYaxis()->SetTitle("Yield"); + mg->GetYaxis()->SetRangeUser(0.0,graphBkg->GetY()[1]*y_scale); + mg->GetXaxis()->SetRangeUser(Q2_MIN_RANGE,Q2_MAX_RANGE); + mg->GetXaxis()->SetLabelSize(0); + mg->GetYaxis()->SetTickLength(0); + leg->Draw("SAME"); + pad1->Update(); + c->cd(); + + pad2->Draw(); + pad2->cd(); + //Get axis on the left side + TGaxis *axis = new TGaxis(Q2_MAX_RANGE,0.0,Q2_MAX_RANGE,graphSignificance->GetY()[0]*y_scale_1,0,graphSignificance->GetY()[0]*y_scale_1,510,"+L"); + axis->SetTitle("S/sqrt(S+B)"); + axis->SetTextFont(21); + mg_FoM->Draw("AP"); + mg_FoM->GetXaxis()->SetRangeUser(Q2_MIN_RANGE,Q2_MAX_RANGE); + mg_FoM->GetYaxis()->SetRangeUser(0.0,graphSignificance->GetY()[0]*y_scale_1); + mg_FoM->GetYaxis()->SetLabelSize(0); + mg_FoM->GetYaxis()->SetTickLength(0); + mg_FoM->GetYaxis()->SetTitle(""); + axis->Draw("SAME"); + legSignificance->Draw("SAME"); + pad2->Update(); + c->cd(); + + //Save it + if (!fixRange) savePath = savePath + "_sigma"; + TFile *file = new TFile ((savePath+".root").c_str(), "RECREATE"); + file->cd(); + graphSig->Write(); + graphBkg->Write(); + graphSignificance->Write(); + CMS->Write(); + c->Write(); + file->Close(); + saveTCanvas(c,savePath,extensions); + + return 0; +} + +int design_SignificanceInQ2(int Run, TGraphErrors *graphSignificance, TGraphErrors *CMS, bool fixRange, std::string savePath, std::vectorextensions){ + + std::string mainName = "Q2_Run" + std::to_string(Run); + double y_scale = 1.4; + + //Create a TCanvas + TCanvas *c = new TCanvas(mainName.c_str(),mainName.c_str(),750, 600); + c->SetRightMargin(0.13); + c->SetLeftMargin(0.15); + c->SetTopMargin(0.07); + c->SetBottomMargin(0.12); + gStyle->SetGridColor(kGray); + c->SetGridy(); + c->SetGridx(); + c->SetBottomMargin(0.16); + + + designTGraph(graphSignificance,"Significance","Q2","S/(S+B)",kBlue,20); + designTGraph(CMS,"Significance_CMS","Q2","S/(S+B)",kGreen+2,20); + + graphSignificance->GetYaxis()->SetRangeUser(0.0,graphSignificance->GetY()[0]*y_scale); + graphSignificance->GetXaxis()->SetRangeUser(Q2_MIN_RANGE,Q2_MAX_RANGE); + CMS->GetXaxis()->SetRangeUser(Q2_MIN_RANGE,Q2_MAX_RANGE); + graphSignificance->SetLineWidth(3); + CMS->SetLineWidth(3); + + //Create multigraph + TMultiGraph *mg_FoM = new TMultiGraph(); + mg_FoM->Add(graphSignificance,"AP"); + mg_FoM->Add(CMS,"AP"); + mg_FoM->Draw("AP"); + designMultiGraph(mg_FoM,"","q^{2} [GeV^{2}]","S/(S+B)"); + + + //Add legend + TLegend *legSignificance = new TLegend(0.35,0.9,0.65,0.75); + legSignificance->AddEntry(graphSignificance, "Significance","l"); + legSignificance->AddEntry(CMS, "CMS","l"); + + //Plot it + c->cd(); + mg_FoM->Draw("AP"); + mg_FoM->GetYaxis()->SetTitle("S/(S+B)"); + mg_FoM->GetXaxis()->SetRangeUser(Q2_MIN_RANGE,Q2_MAX_RANGE); + mg_FoM->GetYaxis()->SetRangeUser(0.0,graphSignificance->GetY()[0]*y_scale); + mg_FoM->GetXaxis()->SetTitle("q^{2} [GeV^{2}]"); + legSignificance->Draw("SAME"); + c->Update(); + + //Save it + if (!fixRange) savePath = savePath + "_sigma"; + TFile *file = new TFile ((savePath+".root").c_str(), "RECREATE"); + file->cd(); + graphSignificance->Write(); + CMS->Write(); + c->Write(); + file->Close(); + saveTCanvas(c,savePath,extensions); + + return 0; + +} diff --git a/Code/FCNCFitter/sources/Helpers/design.hh b/Code/FCNCFitter/sources/Helpers/design.hh new file mode 100644 index 0000000..b501123 --- /dev/null +++ b/Code/FCNCFitter/sources/Helpers/design.hh @@ -0,0 +1,96 @@ +//Renata Kopecna + +#ifndef DESIGN_HH +#define DESIGN_HH + +#include +#include +#include +#include +#include +#include + +//========================================= +// +// Latex in plots +// +//========================================= + +std::string latex_decay(bool DTF); +std::string latex_Kst_decay(bool DTF); +std::string MeVc(); +std::string GeVc(); +std::string GeVc_2(); +std::string latex_pull(); +std::string latex_angle(std::string angle, bool &is_ctl, bool &is_ctk, bool &is_phi); +const std::string LATEX_Q2 = "q^{2}"; +const std::string LATEX_TL = "#theta_{L}"; +const std::string LATEX_CTL = "cos#theta_{L}"; +const std::string LATEX_TK = "#theta_{K}"; +const std::string LATEX_CTK = "cos#theta_{K}"; +const std::string LATEX_PHI = "#phi"; +const std::string EVENTS_TAG = "Weighted candidates"; + +//Define the angles as chars, because ROOT +//Very not cool to have a function here, but also very not +//cool of ROOT to not accept strings and I cannot be bothered +const char *LATEX_Q2_CH(); +const char *LATEX_TL_CH(); +const char *LATEX_CTL_CH(); +const char *LATEX_TK_CH(); +const char *LATEX_CTK_CH(); +const char *LATEX_PHI_CH(); + +const Color_t pWaveColor = kSpring; +const Color_t sWaveColor = kOrange; +const Color_t psInterferenceColor = kMagenta-10; + + +std::string q2_label(double low_q2, double high_q2); + +//========================================= +// +// General +// +//========================================= + +void set_gStyle(); +//Save several file types in one go +void saveTCanvas(TCanvas *c, std::string name, std::vector types); +TLine *threeSigmaLine(double min, double max, bool plus); +TLine *oneSigmaLine(double min, double max, bool plus); + +void plotAndSave(TH1D *hist, std::string canvasName, std::string targetPath, std::string plotType); +void plotAndSave(TH2D *hist, std::string canvasName, std::string targetPath, std::string plotType); +void plotAndSaveWithLine(TH1D* hist, TF1 *line, std::string canvasName, std::string targetPath, std::string plotType); +TLatex *getPrettyTex(double TextFontSize, int TextAlign); + +//========================================= +// +// Angular correction plots +// +//========================================= +void plotAngular(TH1D *hist, TH1D *moments, bool write, std::string name, std::string appendix, std::string q2region, TLatex *tex, std::string folderName); +void plotAngular(TH1D *hist, TH1D *moments, bool write, std::string name, std::string appendix, std::string folderName); +void plotAngular(TH2D *hist, TH2D *moments, bool write, std::string name, std::string appendix, std::string q2region, TLatex *tex, std::string folderName); +void plotAngular(TH2D *hist, TH2D *moments, bool write, std::string name, std::string appendix, std::string folderName); +void plotAngularInOne(TCanvas *c, int whichC, TH1D *moments, TH1D *ub, TH1D *hist, TH1D* ml, bool run_minuit, double q2min, double q2max, double y, bool cross); +void labelAngularScan(std::vectorscan_low, std::vectorscan_range,TH2D *hist); + + +//========================================= +// +// Fit results plots +// +//========================================= +int design_pull_basic(TH1D *pull, Float_t textsize, double eff_pullHeight); +int design_pull(TH1D *pull, Color_t lineColor, Color_t fillColor, double eff_pullHeight, double pullFrameRange); +int design_pull(TGraphErrors *pull, Color_t lineColor, Color_t fillColor, double eff_pullHeight, double pullFrameRange); +//Draw shaded boxes at q2 regions of resonances +void drawResonances(TCanvas *c, double min, double max); +void drawResonances(TPad *c, double min, double max); + +int design_YieldInQ2(int Run, TGraphErrors *graphSig, TGraphErrors *graphBkg, TGraphErrors *graphSignificance, TGraphErrors *CMS, bool fixRange, std::string savePath, std::vector extensions); +int design_SignificanceInQ2(int Run, TGraphErrors *graphSignificance, TGraphErrors *CMS, bool fixRange, std::string savePath, std::vector extensions); + +#endif // DESIGN_HH diff --git a/Code/FCNCFitter/sources/Helpers/helpers.cc b/Code/FCNCFitter/sources/Helpers/helpers.cc new file mode 100644 index 0000000..27cfe02 --- /dev/null +++ b/Code/FCNCFitter/sources/Helpers/helpers.cc @@ -0,0 +1,1217 @@ +//Renata Kopecna + +#include +#include //Needed to remove/copy files +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include //includes accumulate +#include + +#include +#include + +//----------------------// +// Print utils // +//----------------------// +std::string boolToString(bool isTrue){ + if (isTrue) return "TRUE"; + else return "FALSE"; +} + +void reset_spdlog(){ + spdlog::set_pattern("[%^%l%$]\t %v"); +} + +void set_spdlog_level(int verboseLvl){ + switch(verboseLvl) { + case 0: + spdlog::set_level(spdlog::level::trace); + break; + case 1: + spdlog::set_level(spdlog::level::debug); + break; + case 2: + spdlog::set_level(spdlog::level::info); + break; + case 3: + spdlog::set_level(spdlog::level::warn); + break; + case 4: + spdlog::set_level(spdlog::level::err); + break; + case 5: + spdlog::set_level(spdlog::level::critical); + break; + } + return; + +} + +bool spdlog_trace(){ + return (spdlog::default_logger_raw()->level()<=spdlog::level::trace); +} +bool spdlog_debug(){ + return (spdlog::default_logger_raw()->level()<=spdlog::level::debug); +} +bool spdlog_info(){ + return (spdlog::default_logger_raw()->level()<=spdlog::level::info); +} +bool spdlog_warn(){ + return (spdlog::default_logger_raw()->level()<=spdlog::level::warn); +} +bool spdlog_error(){ + return (spdlog::default_logger_raw()->level()<=spdlog::level::err); +} + +std::string get_sample_from_jobID(int job_id){ + if(job_id == 0) return "DATA"; + else if(job_id == 1) return "SIGNAL MC"; + else if(job_id == 2) return "REFERENCE MC "; + else if(job_id == 3) return "PHSP MC "; + else if(job_id == 4) return "GenLevel PHSP MC"; + else if(job_id == 5) return "GenLevel MC"; + else { + spdlog::error("Invalid index for conversion function given: {0:d}", job_id); + assert(0); + } +} + +std::string format_double(double value, unsigned int digits){ + std::stringstream out; + out << std::fixed << std::setprecision(digits) << value; + return out.str(); +}; + +std::string format_value(double value, double error, unsigned int digits){ + //format value such that the relevant number of digits is given back + //determine first "digits" significant places of error + if (error == 0.0){ + std::stringstream out; //to_string(value) returns something else than this.... I hate c++ + out << value; + return out.str(); + } + else{ + int first_significant = floor(log10(error)); + if (first_significant > 0) first_significant = 0; + //ln(e^x)=x log10(c*10^x)=x+log10(c) with log10(c) < 1 + return format_double(value,fabs(first_significant)+digits-1); + } +}; + +std::string format_error(double error, unsigned int digits){ + return (format_value(error,error,digits)); +}; + + +//----------------------// +// Year utils // +//----------------------// +//generate vector with years for every run option +//notation for usage of runs: +//1 : Run 1 +//2 : Run 2 +//12: Run 1+2 +//21: 'Run 2.1' = 2015+2016 +//22: 'Run 2.2' = 2017+2018 + +std::vector get_years(int Run, bool MCsig, bool MCref){ + std::vectoryears; + + if(Run == 1 || Run == 12){ + years.push_back(2011); + years.push_back(2012); + } + + if(Run== 2 || Run == 12 || Run== 21){ + if (!MCsig) years.push_back(2015); //No MC for 2015 + years.push_back(2016); + } + if (!MCref){ //No RefMC for 2017+2018 + if(Run == 2 || Run == 12 || Run == 22){ + years.push_back(2017); + years.push_back(2018); + } + } + return years; +} + +//Check if year is a run year +void check_year(int year){ + std::set yearSet = {2011,2012,2015,2016,2017,2018}; + //Check if year is in a set, if not, throw exception + assert(yearSet.find(year)!= yearSet.end()); + return; +} + +int MC_dataset(bool Reference, bool PHSP){ + if (PHSP) return 3; //PHSP + else if (Reference) return 2; //Ref MC + else return 1; //Sig MC +} + +int get_yearFromRun(int year){ + if (year == 2011 || year == 2012) return 1; + if (year == 2015 || year == 2016 || year == 2017 || year == 2018) return 2; + spdlog::error("Year not recognized!"); + assert(0); +} + +//--------------------------------------// +// General helpers // +//--------------------------------------// + +//Copy file +int copyFile(std::string from, std::string to){ + std::ifstream src(from); + std::ofstream dst(to); + dst << src.rdbuf(); + return 0; +} + +//Check if file exists +//https://stackoverflow.com/questions/12774207/fastest-way-to-check-if-a-file-exist-using-standard-c-c11-c +bool existsTest (const std::string& name) { + struct stat buffer; + return (stat (name.c_str(), &buffer) == 0); +} + +//https://stackoverflow.com/questions/50960492/creating-folders-in-c +//Create parent folders if needed +void makeFolder (const std::string& name) { + std::string parentfolder = name.substr(0, name.find_last_of("/\\")); + if(!existsTest(parentfolder))makeFolder(parentfolder); + spdlog::info("Creating folder '"+name+"'"); + mkdir(name.c_str(), 0755); + return; +} + +//Convert vector into number-space-number... string +std::string convert_vector_to_string(std::vector myVector){ + std::stringstream ss; + copy(myVector.begin(), myVector.end(), std::ostream_iterator(ss, " ")); + std::string s = ss.str(); + return s.substr(0, s.length()-1); // get rid of the trailing space +} + +std::string convert_vector_to_string(std::vector myVector){ + std::stringstream ss; + copy(myVector.begin(), myVector.end(), std::ostream_iterator(ss, " ")); + std::string s = ss.str(); + return s.substr(0, s.length()-1); // get rid of the trailing space +} +std::string convert_vector_to_string(std::vector myVector){ + std::stringstream ss; + copy(myVector.begin(), myVector.end(), std::ostream_iterator(ss, " ")); + std::string s = ss.str(); + return s.substr(0, s.length()-1); // get rid of the trailing space +} + +std::vector merge_two_vecs(std::vector one, std::vector two){ + std::vector merged_vec; + merged_vec.insert(merged_vec.end(), one.begin(), one.end()); + merged_vec.insert(merged_vec.end(), two.begin(), two.end()); + return merged_vec; +} +std::vector merge_two_vecs(std::vector one, std::vector two){ + std::vector merged_vec; + merged_vec.insert(merged_vec.end(), one.begin(), one.end()); + merged_vec.insert(merged_vec.end(), two.begin(), two.end()); + return merged_vec; +} +std::vector merge_two_vecs(std::vector one, std::vector two){ //TODO: I bet there is a way to avoid overloading + std::vector merged_vec; + merged_vec.insert(merged_vec.end(), one.begin(), one.end()); + merged_vec.insert(merged_vec.end(), two.begin(), two.end()); + return merged_vec; +} + +bool replace(std::string& str, const std::string& from, const std::string& to) { + size_t start_pos = str.find(from); + if(start_pos == std::string::npos) + return false; + while ( (start_pos = str.find(from,start_pos)) != std::string::npos){ + str.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + return true; +} + +//Sum a vector of ints +int sum_vector(std::vector vec){ + return std::accumulate(vec.begin(), vec.end(), 0); +} +//Sum a vector of doubles +double sum_vector(std::vector vec){ + return std::accumulate(vec.begin(), vec.end(), 0.0); +} + +//Return the center of a bin +double bin_center(double low, double high){ + return (high+low)/2.0; +} + +//Return the center of a q2 bin +double bin_center_q2(fcnc::options opts, int b){ + return bin_center(opts.TheQ2binsmin.at(b),opts.TheQ2binsmax.at(b)); +} +double bin_center_q2(fcnc::options *opts, int b){ + return bin_center(opts->TheQ2binsmin.at(b),opts->TheQ2binsmax.at(b)); +} +double bin_center_q2(std::vector q2min, std::vector q2max , int b){ + return bin_center(q2min.at(b),q2max.at(b)); +} + +//Return half of the width (useful for errors) +double bin_halfWidth(double low, double high){ + return (high-low)/2.0; +} +double bin_halfWidth_q2(std::vector q2min, std::vector q2max, int b){ + return (q2max.at(b)-q2min.at(b))/2.0; +} +double bin_halfWidth_q2(fcnc::options opts, int b){ + return (opts.TheQ2binsmax.at(b)-opts.TheQ2binsmin.at(b))/2.0; +} +double bin_halfWidth_q2(fcnc::options *opts, int b){ + return (opts->TheQ2binsmax.at(b)-opts->TheQ2binsmin.at(b))/2.0; +} + + +//Check if the angles are in the correct range given by options +bool isEvtInAngleRange(fcnc::event *evt, fcnc::options *opts){ + if (evt->costhetal > opts->ctl_max) return false; + if (evt->costhetal < opts->ctl_min) return false; + if (evt->costhetak > opts->ctk_max) return false; + if (evt->costhetak < opts->ctk_min) return false; + if (evt->phi > opts->phi_max) return false; + if (evt->phi < opts->phi_min) return false; + if (evt->q2 > opts->TheQ2binsmax.back()) return false; + if (evt->q2 < opts->TheQ2binsmin.front()) return false; + return true; + +} +//Check if the angles are in the correct range given by default +bool isEvtInAngleRange(fcnc::event *evt){ + if (evt->costhetal > CTL_MAX){ + spdlog::trace("ctl of event:\t{0:f}",evt->costhetal); + return false; + } + if (evt->costhetal < CTL_MIN){ + spdlog::trace("ctl of event:\t{0:f}",evt->costhetal); + return false; + } + if (evt->costhetak > CTK_MAX) { + spdlog::trace("ctk of event:\t{0:f}",evt->costhetak); + return false; + } + if (evt->costhetak < CTK_MIN) { + spdlog::trace("ctk of event:\t{0:f}",evt->costhetak); + return false; + } + if (evt->phi > PHI_MAX){ + spdlog::trace("phi of event:\t{0:f}",evt->phi); + return false; + } + if (evt->phi < PHI_MIN) { + spdlog::trace("phi of event:\t{0:f}",evt->phi); + return false; + } + if (evt->q2 < Q2_MIN_RANGE) return false; + if (evt->q2 > Q2_MAX_RANGE) return false; + return true; + +} + +//For now filter out events that are dumb dumb for folding four +bool filterFldFour(fcnc::event *evt, fcnc::options *opts){ + if (opts->folding==4){ + //TODO: this is idiotic and will cause trouble if one cuts on ctl. Unfortunatelly, otherwise it cuts the folded parameters too, which is not very beneficial + // SO this if (!isEvtInAngleRange(&evt,&opts)) continue; is not possible + if (evt->costhetak > opts->ctk_max) return false; + if (evt->costhetak < opts->ctk_min) return false; + } + return true; +} + +//Check if value is in a vector +bool isInVec(int key, std::vectorvec){ + return (std::find(vec.begin(), vec.end(), key)!= vec.end()); +} +bool isInVec(double key, std::vectorvec){ + return (std::find(vec.begin(), vec.end(), key)!= vec.end()); +} +bool isInVec(std::string key, std::vectorvec){ + return (std::find(vec.begin(), vec.end(), key)!= vec.end()); +} + + +//--------------------------------------// +// Helpers for converting the tuples // +//--------------------------------------// + +//Returns the correct tree name as Data/MC and genLvl have different tree names +std::string get_inputTree_name(int job_id){ + if(job_id == 0) return "DecayTree"; + else if(job_id == 1) return "DecayTreeTruthMatched"; + else if(job_id == 2) return "DecayTreeTruthMatched"; + else if(job_id == 3) return "DecayTreeTruthMatched"; + else if(job_id == 4) return "DecayTree"; + else if(job_id == 5) return "DecayTree"; + else { + spdlog::error("Invalid index for conversion function given: {0:d}", job_id); + assert(0); + } +} + +//--------------------------------------// +// Helpers for angular corrections // +//--------------------------------------// + +TF1 *fitStraightLine(TH1D* hist, std::string lineName, double lowEdge, double highEdge){ + //Define the fit line + TF1 *fitLine= new TF1(lineName.c_str(), "[0]*x+[1]", lowEdge, highEdge); + + fitLine->SetParameters(0.0, 1.0); + fitLine->SetParLimits(0,-0.5,0.5); + fitLine->SetParLimits(1,0.5,1.5); + fitLine->SetParNames("a","b"); + + std::string fitOption = spdlog_debug() ? "R" : "RQ"; //C turns off chi2 calculation, faster, Q=quiet + + hist->Fit(lineName.c_str(), fitOption.c_str()); + + spdlog::debug("Fitted value is:\t{0:f}+-{1:f}",fitLine->GetParameter(0), fitLine->GetParError(0)); + + return fitLine; +} + +//--------------------------------------// +// Helpers for bu2kstarmumu_pdf // +//--------------------------------------// + +const std::vector> get_angObser_withTeX_vec(){ + return { + {"1s","#xi_{1}^{s}"}, + {"1c","#xi_{1}^{c}"}, + {"2s","#xi_{2}^{s}"}, + {"2c","#xi_{2}^{c}"}, + {"3","#xi_{3}"}, + {"4", "#xi_{4}"}, + {"5","#xi_{5}"}, + {"6s","#xi_{6}^{s}"}, + {"6c","#xi_{6}^{c}"}, + {"7","#xi_{7}"}, + {"8","#xi_{8}"}, + {"9","#xi_{9}"} + }; +} + +std::vector get_angObser_vec(){ + std::vector tmp; + for (auto obs: get_angObser_withTeX_vec()){ + tmp.push_back(obs[0]); + } + return tmp; +} + +std::vector get_angObserTeX_vec(){ + std::vector tmp; + for (auto obs: get_angObser_withTeX_vec()){ + tmp.push_back(obs[1]); + } + return tmp; +} + +//--------------------------------------// +// Helpers for time measuring // +//--------------------------------------// + +void runTime::start(){ + sw->Reset(); + sw->Start(); + return; +} + +void runTime::stop(time_t startTime){ + sw->Stop(); + real_times.push_back(sw->RealTime()); + cpu_times.push_back(sw->CpuTime()); + cpp_times.push_back(Double_t(time(0) - startTime)); + return; +} + +void runTime::print(unsigned int nBins){ + spdlog::info(""); + spdlog::info("=========================================="); + spdlog::info("|| TIME OF FIT ||"); + spdlog::info("=========================================="); + spdlog::info("|| BIN\t\tCPU time[s]\treal time[s]\tC++ time[s]\t||"); + + for(unsigned int b = 0; b < nBins; b++){ + Int_t CpuHours = Int_t(cpu_times.at(b) / 3600); + cpu_times.at(b) -= CpuHours * 3600; + Int_t CpuMinutes = Int_t(cpu_times.at(b) / 60); + cpu_times.at(b) -= CpuMinutes * 60; + Int_t CpuSeconds = Int_t(cpu_times.at(b)); + + Int_t RealHours = Int_t(real_times.at(b) / 3600); + real_times.at(b) -= RealHours * 3600; + Int_t RealMinutes = Int_t(real_times.at(b) / 60); + real_times.at(b) -= RealMinutes * 60; + Int_t RealSeconds = Int_t(real_times.at(b)); + + Int_t CppHours = Int_t(cpp_times.at(b) / 3600); + cpp_times.at(b) -= CppHours * 3600; + Int_t CppMinutes = Int_t(cpp_times.at(b) / 60); + cpp_times.at(b) -= CppMinutes * 60; + Int_t CppSeconds = Int_t(cpp_times.at(b)); + + spdlog::info("|| {0:d}\t\t{1:d}:{2:02d}:{3:02d}\t\t{4:d}:{5:02d}:{6:02d}\t\t{7:d}:{8:02d}:{9:02d} \t||", b, CpuHours, CpuMinutes, CpuSeconds, RealHours, RealMinutes, RealSeconds, CppHours, CppMinutes, CppSeconds); + } + +} + + +//--------------------------------------// +// Helpers for fit scripts // +//--------------------------------------// +std::vector param_string_pPrimes(bool fitFL){ + std::vector params; + if(fitFL) params.push_back("Fl"); + else params.push_back("S1s"); + params.push_back("P1"); + params.push_back("P4"); + params.push_back("P5"); + params.push_back("P2"); + params.push_back("P6"); + params.push_back("P8"); + params.push_back("P3"); + return params; +} +std::vector param_string_pPrimes(bool fitFL, int folding){ + std::vector params; + if(fitFL) params.push_back("Fl"); + else params.push_back("S1s"); + if(folding == 0){ + params.push_back("P2"); + params.push_back("P3"); + return params; + } + else if(folding == 1)params.push_back("P4"); //could be a switch, but meh + else if(folding == 2)params.push_back("P5"); + else if(folding == 3)params.push_back("P6"); + else if(folding == 4)params.push_back("P8"); + return params; +} + +std::vector param_string_s(bool fitFL, bool fitAFB){ + std::vector params; + if(fitFL) params.push_back("Fl"); + else params.push_back("S1s"); + params.push_back("S3"); + params.push_back("S4"); + params.push_back("S5"); + if (fitAFB) params.push_back("Afb"); + else params.push_back("S6s"); + params.push_back("S7"); + params.push_back("S8"); + params.push_back("S9"); + return params; +} +std::vector param_string_s(bool fitFL, bool fitAFB, int folding){ + std::vector params; + if(fitFL) params.push_back("Fl"); + else params.push_back("S1s"); + params.push_back("S3"); + if(folding == 0){ + if(fitAFB) params.push_back("Afb"); + else params.push_back("S6s"); + + params.push_back("S9"); + return params; + } + else if(folding == 1)params.push_back("S4"); + else if(folding == 2)params.push_back("S5"); + else if(folding == 3)params.push_back("S7"); + else if(folding == 4)params.push_back("S8"); + return params; +} + +std::vector param_string_sWave(){ + std::vector params; + params.push_back("FS"); + params.push_back("SS1"); + params.push_back("SS2"); + params.push_back("SS3"); + params.push_back("SS4"); + params.push_back("SS5"); + return params; +} +std::vector param_string_sWave(int folding){ + std::vector params; + params.push_back("FS"); + if(folding == 1) params.push_back("SS2"); + if(folding == 2) params.push_back("SS3"); + if(folding > 2) params.push_back("SS4"); + if(folding < 4) params.push_back("SS1"); + return params; +} + +//TODO: merge with parNamesWithTex +std::vector param_string_bkg(){ + std::vector str; + for (auto ang: ANGLES){ + for (int i = 1; i < 5; i++){ + str.push_back("cbkg"+ang+std::to_string(i)); + } + } + return str; +} + +std::vector param_string_bkg_mkpi(){ + std::vector str; + for (int i = 1; i < 2; i++){ + str.push_back("cbkgmkpi"+std::to_string(i)); + } + return str; +} + +std::vector param_string(fcnc::options opts, bool MC){ + std::vector params; + //This is suboptimal but I feel it is easier for the reader + if (opts.full_angular){ + if(opts.fit_pprimes) params = param_string_pPrimes(opts.fit_fl); + else params = param_string_s(opts.fit_fl, opts.fit_afb); + if(opts.swave){ + std::vector sWave = param_string_sWave(); + params.insert(params.end(), sWave.begin(), sWave.end()); + } + if(!MC){ + std::vector bkg = PAR_BKG_STRING(-1,opts.bkg_order_costhetal,opts.bkg_order_costhetak); //Returns only varied parameters + params.insert(params.end(), bkg.begin(), bkg.end()); + } + return params; + } + else{ + if(opts.fit_pprimes) params = param_string_pPrimes(opts.fit_fl,opts.folding); + else params = param_string_s(opts.fit_fl, opts.fit_afb,opts.folding); + if(opts.swave){ + std::vector sWave = param_string_sWave(opts.folding); + params.insert(params.end(), sWave.begin(), sWave.end()); + } + if(!MC){ + std::vector bkg = PAR_BKG_STRING(opts.folding,opts.bkg_order_costhetal,opts.bkg_order_costhetak); + params.insert(params.end(), bkg.begin(), bkg.end()); + } + return params; + } +} + +std::vector params_string_mass(fcnc::options opts){ + std::vector params; + params.push_back("m_b"); + if (!opts.twotailedcrystalball) params.push_back("m_res_1"); + params.push_back("m_sigma_1"); + if (!opts.twotailedcrystalball) params.push_back("m_sigma_2"); + params.push_back("alpha_1"); + params.push_back("alpha_2"); + params.push_back("n_1"); + params.push_back("n_2"); + return params; +} + +fcnc::parameter* par_with_correct_name(int pos, std::string parname, fcnc::parameters* theParams){ + //pos is the position of the parameter I want to save + + fcnc::parameter* par = theParams->get_parameter(pos); + + //I am not sure, but from the code it seems the parameters should be at the same spot for all pdfs + //Therefore first check if the name on the spot is correct + if (par->get_name() == parname.c_str()) return par; + + unsigned int paridx = 0; + while(paridx != theParams->nparameters()){ + par = theParams->get_parameter(paridx); + if (par->get_name() == parname.c_str()) return par; + paridx++; + } + spdlog::warn("Parameter "+parname+" not found in PDF {0:d}. Continue with next PDF."); + return NULL; +} + + +double get_sigmaRatio_fromMC(basic_params params, int nBins, int bin, int pdf){ + + std::string sigma_name = "m_sigma_1"; //In case one needs m_sigma or m_sigma_2 or so + std::string fileName_sig = final_result_name_MC(params, nBins, false, false, true, false, false); + std::string fileName_ref = final_result_name_MC(params, 1, true, false, true, false, true); + + return double(get_param_value_from_rootfile(fileName_sig,sigma_name,pdf,bin))/ double(get_param_value_from_rootfile(fileName_ref,sigma_name,pdf,0)); +} + +//--------------------------------------// +// Helpers for printing fit results // +//--------------------------------------// + +void print_all_parameters(unsigned int nBins, fcnc::bu2kstarmumu_parameters *theParams[], + int spdlog_level, std::string savePath){ + //Check whether the desired level >= current level + if (spdlog_level >= spdlog::default_logger_raw()->level()){ + //If yes, print the parameters at info level + + //Save current level of spdlog + spdlog::level::level_enum tmp_log_level = spdlog::default_logger_raw()->level(); + + //Set the level to info so it is printed for sure + spdlog::set_level(spdlog::level::info); + spdlog::info(""); + spdlog::info("=========================================="); + spdlog::info("|| PARAMETERS ||"); + spdlog::info("=========================================="); + for(unsigned int b = 0; b < nBins; b++){ + spdlog::info("|| BIN {0:d}", b); + if(spdlog::default_logger_raw()->level()<=spdlog_level){ + theParams[b]->print_parameters(false); + } + if (savePath != ""){ + std::string saveBinPath = savePath + "_bin" + std::to_string(b) + ".txt"; + theParams[b]->save_param_values(saveBinPath + ""); + } + theParams[b]->print_parameters(false); + } + //Reset the level back where it was + spdlog::set_level(tmp_log_level); + } + else return; + + +} + + +void print_all_parameters(unsigned int nBins, std::vector pdf_idx, + std::vector theParams[], + int spdlog_level){ + //Check whether the desired level >= current level + if (spdlog_level >= spdlog::default_logger_raw()->level()){ + //If yes, print the parameters at info level + + //Save current level of spdlog + spdlog::level::level_enum tmp_log_level = spdlog::default_logger_raw()->level(); + + //Set the level to trace so it is printed for sure + //Pritn_parameters needs trace + spdlog::set_level(spdlog::level::trace); + + spdlog::info(""); + spdlog::info("=========================================="); + spdlog::info("|| PARAMETERS ||"); + spdlog::info("=========================================="); + for(unsigned int b = 0; b < nBins; b++){ + for(UInt_t i = 0; i < pdf_idx.size(); i++){ + spdlog::info("|| BIN {0:d}\tPDF {1:d}", b, pdf_idx.at(i)); + theParams[b].at(i)->print_parameters(false); + } + } + //Reset the level back where it was + spdlog::set_level(tmp_log_level); + } + else return; +} + +void tex_all_parameters(unsigned int nBins, std::vector pdf_idx, + std::vector theParams[]){ + std::ofstream myFile; + open_Latex_noteFile(latex_params(), myFile); //open file with parameters + + for(unsigned int b = 0; b < nBins; b++){ + for(UInt_t i = 0; i < pdf_idx.size(); i++){ + myFile << "\\captionof{table}{PDF " << i << " bin " << b<< "}" << std::endl; + theParams[b].at(i)->print_parameters(true); + } + } + return; +} + + +void tex_all_parameters(unsigned int nBins, int n_pdf, fcnc::bu2kstarmumu_parameters **theParams){ + std::ofstream myFile; + open_Latex_noteFile(latex_params(), myFile); //open file with parameters + + for(unsigned int b = 0; b < nBins; b++){ + myFile << "\\captionof{table}{PDF " << n_pdf<< " bin " << b<< "}" << std::endl; + theParams[b]->print_parameters(true); + } + return; +} + + +void print_fit_results(unsigned int nBins,std::vector fitresults){ + + spdlog::info("=========================================="); + spdlog::info("|| FIT RESULTS ||"); + spdlog::info("=========================================="); + if(spdlog_info()){ + spdlog::info("|| BIN\t\tfit result ||"); + for(UInt_t b = 0; b < nBins; b++){ + spdlog::info("|| {0:d}\t\t{1:d}\t||", b, fitresults.at(b)); + } + } + return; +} +void print_fit_results(unsigned int nBins, std::vector pdf_idx, std::vector fitresults[], bool simFit){ + + spdlog::info("=========================================="); + spdlog::info("|| FIT RESULTS ||"); + spdlog::info("=========================================="); + if(spdlog_info()){ + spdlog::info("|| BIN\t\tPDF\t\tfit result ||"); + for(UInt_t b = 0; b < nBins; b++){ + if(!simFit){ + for_indexed(auto idx: pdf_idx){ + spdlog::info("|| {0:d}\t\t{1:d}\t\t{2:d} \t||\n", b, idx, fitresults[b].at(i)); + } + } + else{ + spdlog::info("|| {0:d}\t\t All PDFs\t\t{1:d} \t||\n", b, fitresults[b].at(0)); //TODO + } + } + } + return; +} + +void print_sig_yields(unsigned int nBins, std::vector pdf_idx, + std::vector *evts_cntr, std::vector *f_sigs, std::vector *f_sigserr){ + spdlog::info(""); + spdlog::info("=========================================="); + spdlog::info("|| SIGNAL YIELDS ||"); + spdlog::info("=========================================="); + spdlog::info("|| BIN\t\tPDF\tsignal yield ||"); + for(unsigned int b = 0; b < nBins; b++){ + for(UInt_t i = 0; i < pdf_idx.size(); i++){ + spdlog::info("|| {0:d}\t\t{1:d}\t{2:f}+/-{3:f}\t||", b, pdf_idx.at(i), evts_cntr[b].at(i)*f_sigs[b].at(i), evts_cntr[b].at(i)*f_sigserr[b].at(i)); + } + } + spdlog::info(""); +} + +void print_bkg_yields(unsigned int nBins, std::vector pdf_idx, + std::vector *evts_cntr, std::vector *f_sigs, std::vector *f_sigserr){ + spdlog::info(""); + spdlog::info("=========================================="); + spdlog::info("|| BACKGROUND YIELDS ||"); + spdlog::info("=========================================="); + spdlog::info("|| BIN\t\tPDF\tbkg yield ||"); + for(unsigned int b = 0; b < nBins; b++){ + for(UInt_t i = 0; i < pdf_idx.size(); i++){ + spdlog::info("|| {0:d}\t\t{1:d}\t{2:.1f}+/-{3:.1f}\t ||", b, pdf_idx.at(i), evts_cntr[b].at(i)*(1 - f_sigs[b].at(i)), evts_cntr[b].at(i)*f_sigserr[b].at(i)); + } + } + spdlog::info(""); + +} + + +void print_bkgOnly_yields(unsigned int nBins, std::vector pdf_idx, + std::vector theParams[], + std::vector bkg_int_full_range[], std::vector *evts_cntr){ + spdlog::info(""); + spdlog::info("=========================================="); + spdlog::info("|| BACKGROUND YIELDS ||"); + spdlog::info("=========================================="); + spdlog::info("|| BIN\t\tPDF\tbkg yield ||"); + for(unsigned int b = 0; b < nBins; b++){ + for(UInt_t i = 0; i < pdf_idx.size(); i++){ + spdlog::info("[BIN{0:d}]\tBckgnd est.: {1:.4f}\tBkg prob: {2:.4f}\tBkg iac: {3:.4f}\tExpCoeff: {4:.4f}", + i, + evts_cntr[b].at(i) * bkg_int_full_range[i].at(b) * (1 - theParams[b].at(i)->f_sig.get_value()), + bkg_int_full_range[b].at(i), + 1 - theParams[b].at(i)->f_sig.get_value(), + theParams[b].at(i)->m_lambda.get_value()); + } + } + spdlog::info(""); + +} + + +void print_sig_yields_tex(std::string texFiletag, unsigned int nBins, std::vector pdf_idx, + fcnc::options *theOptions, + std::vector *evts_cntr, std::vector *f_sigs, std::vector *f_sigserr){ + + //Open texFile + std::ofstream myFile; + open_Latex_noteFile(texFiletag, myFile); + + double yield[nBins], yielderr[nBins]; + + myFile << "\\begin{tabular}{|l|"; //TODO: have a function for this + for(UInt_t i = 0; i < pdf_idx.size(); i++) myFile << "r"; + myFile << "|r|}\\hline" << std::endl; + myFile << "\\qsq bin"; + for(UInt_t i = 0; i < pdf_idx.size(); i++){ + myFile << "\t& Run" << theOptions[i].run; + } + myFile << "\\\\" << std::endl; + myFile << "\\hline\\hline" << std::endl; + for(unsigned int b = 0; b < nBins; b++){ + myFile << b << "\t&"; + yield[b] = 0.0; yielderr[b] = 0.0; + for(UInt_t i = 0; i < pdf_idx.size(); i++){ + myFile << "$" << std::setprecision(1) << std::fixed << evts_cntr[b].at(i)*f_sigs[b].at(i) << "\\pm" << evts_cntr[b].at(i)*f_sigserr[b].at(i) << "$ \t&"; + yield[b] += evts_cntr[b].at(i)*f_sigs[b].at(i); + yielderr[b] += evts_cntr[b].at(i)*f_sigserr[b].at(i)*evts_cntr[b].at(i)*f_sigserr[b].at(i); + } + myFile << "$" << yield[b] << "\\pm" << TMath::Sqrt(yielderr[b]) << "$\\\\" << std::endl; + } + myFile << "\\hline\\end{tabular}" << std::endl << std::endl << std::endl << std::endl; + + myFile << "\\begin{tabular}{|l|r|}\\hline" << std::endl; + myFile << "\\qsq bin \t& signal yield\\\\" << std::endl; + myFile << "\\hline\\hline" << std::endl; + for(unsigned int b = 0; b < nBins; b++) myFile << b << "\t& $" << yield[b] << "\\pm" << TMath::Sqrt(yielderr[b]) << "$\\\\" << std::endl; + myFile << "\\hline\\end{tabular}" << std::endl << std::endl; + myFile.close(); +} + + +int save_results(std::string results_file, unsigned int nBins, std::vector pdf_idx, std::vector*fit_results, std::vector *theParams, bool simFit, fcnc::options *opts){ + + //Open the root file + spdlog::info("[SAVE]\t\tSaving result values to file " + results_file); + TFile* fout = new TFile(results_file.c_str(), "RECREATE"); + fout->cd(); + + int param_index = 0; + + //loop over parameters: + for(UInt_t p = 0; p < theParams[0].at(0)->nparameters(); p++){ + fcnc::parameter* param = theParams[0].at(0)->get_parameter(p); + //if(param->get_step_size() == 0.0) continue; //skip fixed parameters + std::string parname(param->get_name()); + std::string pardesc(param->get_description()); + spdlog::trace("Creating new TTree for parameter:" + parname); + TTree* t = new TTree(parname.c_str(), pardesc.c_str()); + int pdf = DEFAULT_TREE_INT; + int bin = DEFAULT_TREE_INT; + int migrad = DEFAULT_TREE_INT; + int status_cov = DEFAULT_TREE_INT; + int totBins = DEFAULT_TREE_INT; + + double q2a = DEFAULT_TREE_VAL; + double q2b = DEFAULT_TREE_VAL; + double value = DEFAULT_TREE_VAL; + double error = DEFAULT_TREE_ERR; + double error_up = DEFAULT_TREE_ERR; + double error_down = DEFAULT_TREE_ERR; + double start_value = DEFAULT_TREE_VAL; + double prev_value = DEFAULT_TREE_VAL; + double prev_error = DEFAULT_TREE_ERR; + + const unsigned int corr_max = param->correlations.size(); + double tmp_corr[corr_max]; + + t->Branch("pdf",&pdf,"pdf/I"); + t->Branch("bin",&bin,"bin/I"); + t->Branch("totBins",&totBins,"totBins/I"); + t->Branch("migrad",&migrad,"migrad/I"); + t->Branch("status_cov",&status_cov,"status_cov/I"); + + t->Branch("value",&value,"value/D"); + t->Branch("q2min",&q2a,"q2min/D"); + t->Branch("q2max",&q2b,"q2max/D"); + t->Branch("error",&error,"error/D"); + t->Branch("error_up",&error_up,"error_up/D"); + t->Branch("error_down",&error_down,"error_down/D"); + t->Branch("start_value",&start_value,"start_value/D"); + t->Branch("prev_value",&prev_value,"prev_value/D"); + t->Branch("prev_error",&prev_error,"prev_error/D"); + + t->Branch("index",¶m_index, "index/I"); + t->Branch("correlations",&tmp_corr,("correlations["+std::to_string(corr_max)+"]/D").c_str()); + + //loop over PDFs + for_indexed(auto n_pdf: pdf_idx){ + for(unsigned int b = 0; b < nBins; b++){ + fcnc::parameter* par = par_with_correct_name(p, parname, theParams[b].at(i)); + if (par == NULL) break; + totBins = nBins; + bin = b; + pdf = n_pdf; + migrad = fit_results[b].at(simFit ? 0 : i) % 100; + status_cov = fit_results[b].at(simFit ? 0 : i) / 100; + + q2a = opts->TheQ2binsmin[b]; + q2b = opts->TheQ2binsmax[b]; + value = par->get_value(); + error = par->get_error(); + error_up = par->get_error_up(); + error_down = par->get_error_down(); + if (opts->minos_errors){ + if (error_up==0.0 && value < par->get_max()) error_up = par->get_max() - value; + if (error_down==0.0 && value > par->get_min()) error_down = par->get_min() - value;//needs to be negative + } + start_value = par->get_start_value(); + prev_value = par->get_previous_measurement(); + prev_error = par->get_previous_error(); + + for (unsigned int l = 0; l < corr_max; l++) tmp_corr[l] = 0.0; //Fill with zeroes + for (unsigned int l = 0; l < par->correlations.size(); l++){ + tmp_corr[l] = par->correlations.at(l); + } + t->Fill(); + } + } //end loop over pdfs + + //Write the parameter tree + t->Write(); + delete t; + param_index++; + } + + //Close the root file + spdlog::info("Finished saving the parameters into the file {0:s}.",fout->GetName()); + fout->Close(); + delete fout; + + //Delete the tex file with parameters + clear_Latex_noteFile(latex_params()); + //Copy the parameter in TeX format into the same place as the final results file + tex_all_parameters(nBins,pdf_idx,theParams); + replace(results_file,".root",".tex"); + copyFile(get_Latex_noteFile(latex_params()),results_file); + + return 0; +} + + +int save_results(std::string results_file, unsigned int nBins, int n_pdf, std::vector fit_results, fcnc::bu2kstarmumu_parameters **theParams, fcnc::options *opts){ + + //Open the root file + spdlog::info("[SAVE]\t\tSaving result values to file " + results_file); + TFile* fout = new TFile(results_file.c_str(), "RECREATE"); + fout->cd(); + + int param_index = 0; + + //loop over parameters: + for(UInt_t p = 0; p < theParams[0]->nparameters(); p++){ + fcnc::parameter* param = theParams[0]->get_parameter(p); + //if(param->get_step_size() == 0.0) continue; //skip fixed parameters + std::string parname(param->get_name()); + std::string pardesc(param->get_description()); + spdlog::trace("Creating new TTree for parameter:" + parname); + TTree* t = new TTree(parname.c_str(), pardesc.c_str()); + int pdf = DEFAULT_TREE_INT; + int bin = DEFAULT_TREE_INT; + int migrad = DEFAULT_TREE_INT; + int status_cov = DEFAULT_TREE_INT; + int totBins = DEFAULT_TREE_INT; + + double q2a = DEFAULT_TREE_VAL; + double q2b = DEFAULT_TREE_VAL; + double value = DEFAULT_TREE_VAL; + double error = DEFAULT_TREE_ERR; + double error_up = DEFAULT_TREE_ERR; + double error_down = DEFAULT_TREE_ERR; + double start_value = DEFAULT_TREE_VAL; + double prev_value = DEFAULT_TREE_VAL; + double prev_error = DEFAULT_TREE_ERR; + + const unsigned int corr_max = param->correlations.size(); + double tmp_corr[corr_max]; + + t->Branch("pdf",&pdf,"pdf/I"); + t->Branch("bin",&bin,"bin/I"); + t->Branch("totBins",&totBins,"totBins/I"); + t->Branch("migrad",&migrad,"migrad/I"); + t->Branch("status_cov",&status_cov,"status_cov/I"); + + t->Branch("value",&value,"value/D"); + t->Branch("q2min",&q2a,"q2min/D"); + t->Branch("q2max",&q2b,"q2max/D"); + t->Branch("error",&error,"error/D"); + t->Branch("error_up",&error_up,"error_up/D"); + t->Branch("error_down",&error_down,"error_down/D"); + t->Branch("start_value",&start_value,"start_value/D"); + t->Branch("prev_value",&prev_value,"prev_value/D"); + t->Branch("prev_error",&prev_error,"prev_error/D"); + + t->Branch("index",¶m_index, "index/I"); + t->Branch("correlations",&tmp_corr,("correlations["+std::to_string(corr_max)+"]/D").c_str()); + + //loop over nBins + for(unsigned int b = 0; b < nBins; b++){ + fcnc::parameter* par = par_with_correct_name(p, parname, theParams[b]); + if (par == NULL) break; + totBins = nBins; + bin = b; + pdf = n_pdf; + migrad = fit_results[b] % 100; + status_cov = fit_results[b] / 100; + + q2a = opts->TheQ2binsmin[b]; + q2b = opts->TheQ2binsmax[b]; + value = par->get_value(); + error = par->get_error(); + error_up = par->get_error_up(); + error_down = par->get_error_down(); + if (opts->minos_errors){ + if (error_up==0.0 && value < par->get_max()) error_up = par->get_max() - value; + if (error_down==0.0 && value > par->get_min()) error_down = par->get_min() - value;//needs to be negative + } + start_value = par->get_start_value(); + prev_value = par->get_previous_measurement(); + prev_error = par->get_previous_error(); + + for (unsigned int l = 0; l < corr_max; l++) tmp_corr[l] = 0.0; //Fill with zeroes + for (unsigned int l = 0; l < par->correlations.size(); l++){ + tmp_corr[l] = par->correlations.at(l); + } + t->Fill(); + + } + //Write the parameter tree + t->Write(); + delete t; + param_index++; + } //End loop over names + + //Close the root file + spdlog::info("Finished saving the parameters into the file {0:s}.",fout->GetName()); + fout->Close(); + + //Delete the tex file with parameters + clear_Latex_noteFile(latex_params()); + //Copy the parameter in TeX format into the same place as the final results file + tex_all_parameters(nBins,n_pdf,theParams); + replace(results_file,".root",".tex"); + copyFile(get_Latex_noteFile(latex_params()),results_file); + + delete fout; + return 0; +} + + +//--------------------------------------// +// Helpers for writting latex stuff // +//--------------------------------------// +int clear_Latex_noteFile(std::string tag){ + if( remove(get_Latex_noteFile(tag).c_str()) != 0 ) spdlog::warn( "Unable to delete file " + get_Latex_noteFile(tag) ); //Do not return an error status cause the file might just not exist, which is ok + else spdlog::trace( "Latex noteFile successfully deleted" ); + return 0; +} + +int open_Latex_noteFile(std::string tag, std::ofstream &myfile){ + //This is not working cause this thing is for whatever efin reason stuck with gcc 4. + myfile.open (get_Latex_noteFile(tag), std::ios::out | std::ios::app); + if (!myfile.is_open()){ + spdlog::error("Latex noteFile" + get_Latex_noteFile(tag) + " is not opened."); + return 404; + } + else{ + spdlog::trace("Latex noteFile successfully deleted"); + return 0; + } +} + + + +//--------------------------------------// +// Helpers for reading the parameters // +//--------------------------------------// + +//Checks if the observable is in the TFile +//If required Fl and there is S1s, it returns 11, ... +//Modulo 10 then returns whether the observable actually exists +//Example usage: if (try_getObservable(paramName, file)%10==0) assert(0) +int try_getObservable(std::string observable, TFile* file){ + if (!file->GetListOfKeys()->Contains(observable.c_str())){ + //Also check if Fl<->S1s and A_FB<->S6s is available + if (observable == "Fl") return 10+try_getObservable("S1s",file); + if (observable == "S1s") return 20+try_getObservable("Fl",file); + if (observable == "Afb") return 30+try_getObservable("S6s",file); + if (observable == "S6s") return 40+try_getObservable("Afb",file); + return 0; + } + else return 1; +} + +std::vector load_param_values_into_vector(std::string paramName, std::string fileName){ + //There is a function for this in bu2kstarmumu_parameters.cc, but that is inherited from parameters, therefore a parameter class needs to be created for this + //That would be tedious, so there is a new class that opens the root file with results and reads it from a tree directly into an array + + //Create the vector that will be returned + std::vector output; + + //Open file + spdlog::info("Opening " + fileName); + TFile* file = new TFile(fileName.c_str(), "READ"); + + int isFoundFlag = try_getObservable(paramName, file); + if (!(isFoundFlag%10)){ + spdlog::critical("Wrong tree name " + paramName + "! Returning an empty vector!"); + //It should not crash here as it might be desired to init some observables but not use them + return {}; + } + else{ + switch(isFoundFlag){ + case 11: //Need Fl, have S1s + paramName = "S1s"; + break; + case 21: //Need S1s, have FL + paramName = "Fl"; + break; + case 31: //Need Afb, have S6s + paramName = "S6s"; + break; + case 41: //Need S6s, have Afb + paramName = "Afb"; + break; + } + //case 1: all good, move one + } + + //Get the tree + TTree* tree = (TTree*)file->Get(paramName.c_str()); + //Activate only needed branches + tree->SetBranchStatus("*",0); + tree->SetBranchStatus("value",1); + double value = DEFAULT_TREE_VAL; + tree->SetBranchAddress("value", &value); + + //Loop over nBins that are saved in the tree + for (int b = 0; b < tree->GetEntries(); b++){ + tree->GetEntry(b); + //There are not many bins so just do a switch and fill accordingly + switch(isFoundFlag){ + case 1: + output.push_back(value); + case 11: //Need Fl, have S1s + output.push_back(1-4.0/3.0*value); + break; + case 21: //Need S1s, have FL + output.push_back(3.0/4.0*(1-value)); + break; + case 31: //Need Afb, have S6s + output.push_back(3.0/4.0*value); + break; + case 41: //Need S6s, have Afb + output.push_back(4.0/3.0*value); + break; + } + } + + spdlog::debug(convert_vector_to_string(output)); + return output; +} diff --git a/Code/FCNCFitter/sources/Helpers/helpers.hh b/Code/FCNCFitter/sources/Helpers/helpers.hh new file mode 100644 index 0000000..e8d6f84 --- /dev/null +++ b/Code/FCNCFitter/sources/Helpers/helpers.hh @@ -0,0 +1,229 @@ +//Renata Kopecna + +#ifndef HELPERS_HH +#define HELPERS_HH + +#include +#include +#include +#include +#include +#include + +//indexed auto looping over vectors +#define for_indexed(...) for_indexed_v(i, __VA_ARGS__) +#define for_indexed_v(v, ...) for(bool _i_ = true, _break_ = false; _i_;) for(size_t v = 0; _i_; _i_ = false) for(__VA_ARGS__) if(_break_) break; else for(bool _j_ = true; _j_;) for(_break_ = true; _j_; _j_ = false) for(bool _k_ = true; _k_; v++, _k_ = false, _break_ = false) +/// usage: +/// std::vector v{1, 2, 3}; +///for_indexed (auto const& item : v) { //the index is always i +/// if (i > 0) std::cout << ", "; +/// std::cout << i << ": " << item; +///} +/// for_indexed_v (my_counter, auto const& item : v) //the index is v here + + +//TODO: work on more forward declarations, it reduces the compiler time as cross-referencing is not recompiled 400 times anymore +//TODO: simirarly move your includes into .cpp in order to avoid this + +namespace fcnc { //Forward declaration, fully defined in options.hh + class options; + class parameters; + class bu2kstarmumu_parameters; + class event; +} + + +//----------------------// +// Print utils // +//----------------------// +std::string boolToString(bool isTrue); + +//reset the spdlog into my default +void reset_spdlog(); + +//set spdlog level +void set_spdlog_level(int verboseLvl); + +//what lever is the spdlog? +bool spdlog_trace(); +bool spdlog_debug(); +bool spdlog_info(); +bool spdlog_warn(); +bool spdlog_error(); + +//Get job_id and turn it in a string +std::string get_sample_from_jobID(int job_id); + +//Make pretty outputs with given precision (feault is two) +std::string format_double(double value, unsigned int digits=2); +std::string format_value(double value, double error, unsigned int digits=2); +std::string format_error(double error, unsigned int digits=2); + +//----------------------// +// Year utils // +//----------------------// + +//Get years according to a run +std::vector get_years(int Run, bool MCsig, bool MCref); +//Check if year makes sense +void check_year(int year); +int get_yearFromRun(int year); + +int MC_dataset(bool Reference, bool PHSP); +//--------------------------------------// +// General helpers // +//--------------------------------------// + +//Copy file +int copyFile(std::string from, std::string to); +//Check if file/folder exists +bool existsTest (const std::string& name); +//Create new folder +void makeFolder (const std::string& name); + +//Convert vector into number-space-number... string +std::string convert_vector_to_string(std::vector myVector); +std::string convert_vector_to_string(std::vector myVector); +std::string convert_vector_to_string(std::vector myVector); + +//Merge two vectors +std::vector merge_two_vecs(std::vector one, std::vector two); +std::vector merge_two_vecs(std::vector one, std::vector two); +std::vector merge_two_vecs(std::vector one, std::vector two); + +//Replace a part of a string +bool replace(std::string& str, const std::string& from, const std::string& to); + +//Sum a vectors +int sum_vector(std::vector vec); +double sum_vector(std::vector vec); + +//Return the center of a bin +double bin_center(double low, double high); +//Return the center of a q2 bin +double bin_center_q2(fcnc::options opts, int b); +double bin_center_q2(fcnc::options *opts, int b); +double bin_center_q2(std::vector q2min, std::vector q2max , int b); + +//Return half of the width (useful for errors) +double bin_halfWidth(double low, double high); +double bin_halfWidth_q2(fcnc::options opts, int b); +double bin_halfWidth_q2(fcnc::options *opts, int b); +double bin_halfWidth_q2(std::vector q2min, std::vector q2max, int b); + +//Check if the angles are in the correct range given by options +bool isEvtInAngleRange(fcnc::event *evt, fcnc::options *opts); +//Check if the angles are in the correct range given by default +bool isEvtInAngleRange(fcnc::event *evt); +//For now filter out events that are dumb dumb for folding four +bool filterFldFour(fcnc::event *evt, fcnc::options *opts); + +//Check if value is in a vector +bool isInVec(int key, std::vectorvec); +bool isInVec(double key, std::vectorvec); +bool isInVec(std::string key, std::vectorvec); + + +//--------------------------------------// +// Helpers for converting the tuples // +//--------------------------------------// + +//Return's OG tuple name +std::string get_inputTree_name(int job_id); + +//--------------------------------------// +// Helpers for angular corrections // +//--------------------------------------// + +TF1 *fitStraightLine(TH1D* hist, std::string lineName, double lowEdge, double highEdge); + +//--------------------------------------// +// Helpers for bu2kstarmumu_pdf // +//--------------------------------------// + +//Returns a vector with the {p wave observables, obervable in tex}, useful for histograms in a loop +const std::vector> get_angObser_withTeX_vec(); + + +//Returns a vector with the p wave observables +std::vector get_angObser_vec(); + +//Returns a vector with the p wave observables in tex +std::vector get_angObserTeX_vec(); + +//--------------------------------------// +// Helpers for time measuring // +//--------------------------------------// + +struct runTime{ + //Measure the time for the fit: + std::vector real_times; + std::vector cpu_times; + std::vector cpp_times; + TStopwatch * sw;// = new TStopwatch(); + runTime(){ + sw = new TStopwatch(); + } + void print(unsigned int nBins); + void start(); + void stop(time_t startTime); +}; + +//--------------------------------------// +// Helpers for fit scripts // +//--------------------------------------// + +//get a vector of all available angle bkg parameters +std::vector param_string_bkg(); +//get a vector of all available angle mkpi parameters +std::vector param_string_bkg_mkpi(); +//get a string vector of all effectivelly used parameters +std::vector param_string(fcnc::options opts, bool MC); +//get a string vector of mass parameters +std::vector params_string_mass(fcnc::options opts); +//Reads MC fit files (massFitOnly) and gets the sigma ratio of ref/MC for given bin and pdf +double get_sigmaRatio_fromMC(basic_params params, int nBins, int bin, int pdf); + +//---------------------------------------------// +// Helpers for printing and saving fit results // +//---------------------------------------------// + +void print_all_parameters(unsigned int nBins, fcnc::bu2kstarmumu_parameters *theParams[], + int spdlog_level, std::string savePath); +void print_all_parameters(unsigned int nBins, std::vector pdf_idx, + std::vector theParams[], + int spdlog_level); + +void tex_all_parameters(unsigned int nBins, std::vector pdf_idx, + std::vector theParams[]); + +void print_fit_results(unsigned int nBins, std::vector fitresults); +void print_fit_results(unsigned int nBins, std::vector pdf_idx, std::vector fitresults[], bool simFit); +void print_sig_yields(unsigned int nBins, std::vector pdf_idx, + std::vector *evts_cntr, std::vector *f_sigs, std::vector *f_sigserr); +void print_bkg_yields(unsigned int nBins, std::vector pdf_idx, + std::vector *evts_cntr, std::vector *f_sigs, std::vector *f_sigserr); +void print_bkgOnly_yields(unsigned int nBins, std::vector pdf_idx, + std::vector theParams[], + std::vector bkg_int_full_range[], std::vector *evts_cntr); +void print_sig_yields_tex(std::string texFiletag, + unsigned int nBins, std::vector pdf_idx, + fcnc::options *theOptions, + std::vector *evts_cntr, std::vector *f_sigs, std::vector *f_sigserr); + +int save_results(std::string results_file, unsigned int nBins, std::vector pdf_idx, std::vector*fit_results, std::vector *theParams, bool simFit, fcnc::options *opts); +int save_results(std::string results_file, unsigned int nBins, int n_pdf, std::vector fit_results, fcnc::bu2kstarmumu_parameters **theParams, fcnc::options *opts); +//--------------------------------------// +// Helpers for writting latex stuff // +//--------------------------------------// + +int clear_Latex_noteFile(std::string tag); //Deletes the old file +int open_Latex_noteFile(std::string tag, std::ofstream &myfile); //Appends output at the end of the file + + +//--------------------------------------// +// Helpers for reading the parameters // +//--------------------------------------// + +std::vector load_param_values_into_vector(std::string paramName, std::string fileName); +#endif // HELPERS_HH diff --git a/Code/FCNCFitter/sources/Params/constants.cc b/Code/FCNCFitter/sources/Params/constants.cc new file mode 100644 index 0000000..1ac393b --- /dev/null +++ b/Code/FCNCFitter/sources/Params/constants.cc @@ -0,0 +1,512 @@ +// Renata Kopecna + +#include +#include + +////////////////////////// +// Q2 bins // +////////////////////////// + +//Return a vector with low bin edges in Q2, depending on the number of bins +std::vector get_TheQ2binsmin(int nBins, bool Reference){ + //choose binning scheme: + if (Reference) return {8.68}; + else if (nBins == 1) return {Q2_MIN_RANGE}; + else if (nBins == 2) return {Q2_MIN_RANGE, 11.0}; + else if (nBins == 4) return {Q2_MIN_RANGE, 4.0, 11.0, 15.0}; //Default is 4 bins + else if (nBins == 5) return {Q2_MIN_RANGE, 4.0, 11.0, 15.0, 1.1}; //Basics 4 + 1.1-6.0 Gev + else if (nBins == 8) return {0.1 , 1.1, 2.5, 4.0, 6.0, 11.0, 15.0, 17.0}; //Same binning as B0 and Ks->PiPi + else if (nBins == 9) return {0.1 , 1.1, 2.5, 4.0, 6.0, 8.68, 11.0, 15.0, 17.0}; //Same binning as B0 and Ks->PiPi + Jpsi, useful in MC checks + else return {}; +} + +//Return a vector with upper bin edges in Q2, depending on the number of bins +std::vector get_TheQ2binsmax(int nBins, bool Reference){ + //choose binning scheme + if (Reference) return {10.09}; + else if (nBins == 1) return {Q2_MAX_RANGE}; + else if (nBins == 2) return {1.0, Q2_MAX_RANGE}; + else if (nBins == 4) return {4.0, 8.0, 12.5, Q2_MAX_RANGE}; //Default is 4 bins + else if (nBins == 5) return {4.0, 8.0, 12.5, Q2_MAX_RANGE, 6.0}; //Basic 4 + 1.1-6.0 Gev + else if (nBins == 8) return {0.98, 2.5, 4.0, 6.0, 8.0, 12.5, 17.0, 19.0};//Same binning as B0 and Ks->PiPi + else if (nBins == 9) return {0.98, 2.5, 4.0, 6.0, 8.0, 10.09, 12.5, 17.0, 19.0};//Same binning as B0 and Ks->PiPi + Jpsi, useful in MC checks + else return {}; +} + +////////////////////////// +// Angle ranges // +////////////////////////// + +//Returns pretty much the max-min for different dimensions +double CTL_RANGE(){ return CTL_MAX - CTL_MIN; } +double CTK_RANGE(){ return CTK_MAX - CTK_MIN; } +double PHI_RANGE(){ return PHI_MAX - PHI_MIN; } + +double Q2_RANGE_FULL(){ return Q2_MAX_RANGE - Q2_MIN_RANGE; } +//Same, just in angles or in angles+q2 +double RANGE_3D(){ return CTL_RANGE()*CTK_RANGE()*PHI_RANGE(); } +double RANGE_4D(){ return RANGE_3D()*Q2_RANGE_FULL(); } + +////////////////////////// +// RESOLUTION // +////////////////////////// +/// \brief get_resolution +/// \return resolution obtained by angular resolution, used for systematic studies +/// +std::vector> get_resolution(){ + std::vector> resolution; + resolution.push_back({0.0139, 0.0144, 0.0141, 0.0141, 0.0140, 0.0140});//ctk + resolution.push_back({0.00481,0.00504,0.00503,0.00503,0.00497,0.00499});//ctl + resolution.push_back({0.0256, 0.0253, 0.0260, 0.0260, 0.0258, 0.0248}); //phi + return resolution; +} + +////////////////////////// +// Main Fit // +////////////////////////// + +//This string contains parameters that are varied when fitting bkg +//TODO: I hope this doesn't change perf bin, but wurst käse scenario I add bin argument +std::vector PAR_BKG_STRING_CTL(int folding, int order){ + std::vector str; + for (int ord = 1; ord <= order; ord++){ + if (ord%2==1 && folding>0) continue; //odd values excluded from folding 1,2,3,4 + str.push_back("cbkgctl"+std::to_string(ord)); + } + return str; +} +std::vector PAR_BKG_STRING_CTK(int folding, int order){ + std::vector str; + for (int ord = 1; ord <= order; ord++){ + if (ord%2==1 && folding == 4) continue; //odd values excluded from folding 4 + str.push_back("cbkgctk"+std::to_string(ord)); + } + return str; +} +std::vector PAR_BKG_STRING_PHI(){ + //For now return an empty string as the phi is flat + return {}; +} + +std::vector PAR_BKG_STRING(int folding, int nCtl, int nCtk){ + std::vector str; + std::vector ctl = PAR_BKG_STRING_CTL(folding,nCtl); + std::vector ctk = PAR_BKG_STRING_CTK(folding,nCtk); + std::vector phi = PAR_BKG_STRING_PHI(); + str.insert(str.end(), ctl.begin(), ctl.end()); + str.insert(str.end(), ctk.begin(), ctk.end()); + str.insert(str.end(), phi.begin(), phi.end()); + return str; +} + +//Init values of said parameters +//CAREFUL!!!! HAS TO BE THE SAME AS PAR_BKG_STRING!!!! +std::vector init_bkg_ctl(int folding, int order){ + std::vector init_val; + for (int ord = 1; ord <= order; ord++){ + if (ord%2==1 && folding>0) continue; //odd values excluded from foldings 1,2,3,4 + init_val.push_back(0.02); //Even values always push + } + return init_val; +} +std::vector init_bkg_ctk(int folding, int order){ + std::vector init_val; + for (int ord = 1; ord <= order; ord++){ + if (ord%2==1 && folding==4) continue; //odd values excluded from folding 4 + if (ord%2==1) init_val.push_back(-0.7); + else init_val.push_back(-0.5); + } + return init_val; +} +std::vector init_bkg_phi(){ + return {}; +} + +std::vector init_bkg(int folding, int nCtl, int nCtk){ + std::vector init_val; + std::vector ctl = init_bkg_ctl(folding,nCtl); + std::vector ctk = init_bkg_ctk(folding,nCtk); + std::vector phi = init_bkg_phi(); + init_val.insert(init_val.end(), ctl.begin(), ctl.end()); + init_val.insert(init_val.end(), ctk.begin(), ctk.end()); + init_val.insert(init_val.end(), phi.begin(), phi.end()); + return init_val; +} + +std::vector > fracs(int nBins){ + if(nBins == 5 || nBins == 4){ + return {{0.040286, 0.060429, 0.016244, 0.012995, 0.051982}, + {0.246914, 0.434048, 0.115010, 0.074074, 0.348928}}; + } + else { + spdlog::error("No event number fractions given for binning scheme with {0:d} q2 bins. Exit", nBins); + return std::vector >(2, std::vector(nBins, 0.)); + } +} + +std::vector init_n_signal(int nBins){ //init the number of sig events + if(nBins == 5) return {80., 75., 50., 90., 155.}; + else if(nBins == 4) return {80., 75., 50., 90.}; + else if(nBins == 2) return {80.+75., 50.+90.}; + else if(nBins == 1) return {9591.+41809.}; + else { + spdlog::error("No Signal event numbers given for binning scheme with {0:d} q2 bins. Exit", nBins); + assert(0); + } + return {}; //useles, but compiler would complain +} +std::vector init_n_bckgnd(int nBins){//init the number of bkg events + if(nBins == 5) return {80., 160., 40., 20., 240.}; + else if(nBins == 4) return {80., 160., 40., 20.}; + else if(nBins == 2) return {206.+279.+358.+358., 158.+93.}; + else if(nBins == 1) return {716.+4337.}; + else { + spdlog::error("No Background event numbers given for binning scheme with {0:d} q2 bins. Exit", nBins); + assert(0); + } + return {}; //useles, but compiler would complain +} +std::vector init_f_lambda(int nBins){ //init lambda + if(nBins == 5) return {-0.0064, -0.0064, -0.0065, -0.0065, -0.0064}; + else if(nBins == 4) return {-0.0064, -0.0064, -0.0065, -0.0065}; + else if(nBins == 2) return {-0.0064, -0.0065}; + else if(nBins == 1) return {-0.0044}; + else { + spdlog::error("No values for the exponential background description are given for binning scheme with {0:d} q2 bins. Exit", nBins); + assert(0); + } + return {}; //useles, but compiler would complain +} + +std::vector get_f_subset(int nPDFs){ + //obtained from jpsi channel, data, 5D fit, full range + if(nPDFs == 4) return {0., 0., 0., 0.}; //TODO!!! + else if(nPDFs == 2) return {0.0, 0.0}; //TODO!!! + else if(nPDFs == 1) return {1.}; + else{ + spdlog::warn("No values for the signal fraction are given for simultaneous fits with {0:d} pdf's. Use default: f_sig = 0.5", nPDFs); + return std::vector (nPDFs, 0.5); + } + return {}; +} + +std::vector> init_angular_params(int nBins, bool NP, bool isReference){ + if (nBins==5){ + if (NP) return { + //predictions from flavio for new physics scenario with C9 = -1.0, using min(Q2) = 0.25 and max(Q2) = 18.0 + {0.30284413148097966,0.27262304293367756,0.4271747118350757,0.4947224191764013,0.22062375348447547}, + {0.0016779452277498482,-0.03166521898839871,-0.08541706129465602,-0.18930463721455312,-0.011913104816645514}, + {-0.03554278140794295,-0.2399493206724746,-0.28043043274306023,-0.296509757783654,-0.14577653963645607}, + {0.1323358147544716,-0.29136093172458405,-0.37328734325703,-0.2736851726358371,-0.08401219272607802}, + {-0.18973621926844692,0.1460462265211582,0.4666205500210169,0.468761474000308,-0.08526703027846606}, + {-0.021811112779860177,-0.01286712550773734,-0.002747600804479865,-0.0014945589348205987,-0.01889737958853306}, + {-0.00881926856860235,-0.003687673879434568,0.0016256878486157777,0.0005018180644191919,-0.005992663137417108}, + {-0.0006860405719520938,-0.0006097376632470255,0.0006613554952330075,0.00044525884942171284,-0.0006319657235214326} + }; + else return{ + //SM predictions from flavio, using min(Q2) = 0.25 and max(Q2) = 18.0 + {+0.248569008046490070, +0.2581971160208132000, +0.42526014659559220000, +0.49420669353506260000, +0.1850102996703149000}, //s1s + {+0.000732569649322501, -0.0324523859139632900, -0.08563864422457230000, -0.18934424485647136000, -0.0130310503598977030}, //s3 + {-0.028317693174889150, -0.2425837027660650600, -0.28116530113868093000, -0.29668531019781386000, -0.1468982883895949300}, //s4 + {+0.035479698896675250, -0.3745017565795041000, -0.40726931726860705000, -0.30161750053585110000, -0.1915219985323076700}, //s5 + {-0.122319885918514240, +0.2473816826915200600, +0.52432045165541470000, +0.52106439209368990000, +0.0147578966169414490}, //s6s + {-0.019468600975846337, -0.0105435770924197210, -0.00219285191192886900, -0.00119446595061885200, -0.0160492529928752330}, //s7 + {-0.010192773160727949, -0.0043019891737210840, +0.00104987431866559550, +0.00027244645255727460, -0.0070279543261629670}, //s8 + {-0.000756965302130655, -0.0006959911482550733, +0.00044741790607562027, +0.00026464193866571387, -0.0007199408885633002} //s9 + }; + } + else if (nBins==4){ + if (NP) return { + //predictions from flavio for new physics scenario with C9 = -1.0, using min(Q2) = 0.25 and max(Q2) = 18.0 + {0.30284413148097966,0.27262304293367756,0.4271747118350757,0.4947224191764013}, + {0.0016779452277498482,-0.03166521898839871,-0.08541706129465602,-0.18930463721455312}, + {-0.03554278140794295,-0.2399493206724746,-0.28043043274306023,-0.296509757783654}, + {0.1323358147544716,-0.29136093172458405,-0.37328734325703,-0.2736851726358371}, + {-0.18973621926844692,0.1460462265211582,0.4666205500210169,0.468761474000308}, + {-0.021811112779860177,-0.01286712550773734,-0.002747600804479865,-0.0014945589348205987}, + {-0.00881926856860235,-0.003687673879434568,0.0016256878486157777,0.0005018180644191919}, + {-0.0006860405719520938,-0.0006097376632470255,0.0006613554952330075,0.00044525884942171284} + }; + else return{ + //SM predictions from flavio, using min(Q2) = 0.25 and max(Q2) = 18.0 + {0.24856900804649007,0.2581971160208132,0.4252601465955922,0.4942066935350626}, //s1s + {0.000732569649322501,-0.03245238591396329,-0.0856386442245723,-0.18934424485647136}, //s3 + {-0.02831769317488915,-0.24258370276606506,-0.28116530113868093,-0.29668531019781386}, //s4 + {0.03547969889667525,-0.3745017565795041,-0.40726931726860705,-0.3016175005358511}, //s5 + {-0.12231988591851424,0.24738168269152006,0.5243204516554147,0.5210643920936899}, //s6s + {-0.019468600975846337,-0.010543577092419721,-0.002192851911928869,-0.001194465950618852}, //s7 + {-0.010192773160727949,-0.004301989173721084,0.0010498743186655955,0.0002724464525572746}, //s8 + {-0.000756965302130655,-0.0006959911482550733,0.00044741790607562027,0.00026464193866571387} //s9 + }; + } + else if (nBins==2){ + return { //results from signal channel generator level MC fit TODO + {0.0,0.0}, //s1s + {0.0,0.0}, //s3 + {0.0,0.0}, //s4 + {0.0,0.0}, //s5 + {0.0,0.0}, //s6s + {0.0,0.0}, //s7 + {0.0,0.0}, //s8 + {0.0,0.0} //s9 + }; + } + else if (nBins==1){ + if (isReference) return { //TODO, David's for now + {+0.321}, //s1s //FL = 0.572 + {-0.002}, //s3 + {-0.246}, //s4 + {-0.003}, //s5 + {-0.003}, //s6s + {-0.001}, //s7 + {-0.063}, //s8 + {-0.084} //s9 + }; + else return { //TODO + {+0.321}, //s1s//FL = 0.572 + {-0.002}, //s3 + {-0.246}, //s4 + {-0.003}, //s5 + {-0.003}, //s6s + {-0.001}, //s7 + {-0.063}, //s8 + {-0.084} //s9 + }; + } + else { + spdlog::error("No SM values given for binning scheme with {0:d} q2 bins. Exit", nBins); + assert(0); + return {}; + } +} + +std::vector> init_angular_params_MC(int nBins){ + if (nBins==4){ + return { + {+0.3, +0.25, +0.4, +0.48}, //s1s // 0 //S1s = 3/4(1-FL) + {-0.06, -0.01, -0.05, -0.2}, //s3 // 1 + {-0.02, -0.02, -0.2, -0.3}, //s4 // 2 + {+0.06, -0.30, -0.4, -0.3}, //s5 // 3 + {-0.12, +0.2, +0.5, +0.5}, //s6s // 4 //S6 = 4/3 AFB + {+0.01, +0.0, +0.0, +0.0}, //s7 // 5 + {+0.05, +0.05, +0.05, +0.0}, //s8 // 6 big influence on ctl + {-0.01, +0.01, +0.01, +0.0} //s9 // 7 + }; + } + else if (nBins==5){ + return { + {+0.3, +0.25, +0.3, +0.4, +0.2}, //s1s // 0 //S1s = 3/4(1-FL) + {-0.06, -0.01, -0.07, -0.05, -0.01}, //s3 // 1 + {-0.02, -0.20, -0.15, -0.2, -0.13}, //s4 // 2 + {+0.09, -0.35, -0.4, -0.4, -0.13}, //s5 // 3 + {-0.12, +0.2, +0.2, +0.5, -0.32}, //s6s // 4 //S6 = 4/3 AFB + {+0.01, +0.0, +0.01, +0.0, +0.00}, //s7 // 5 + {+0.05, +0.05, +0.03, +0.05, +0.03}, //s8 // 6 big influence on ctl + {-0.01, +0.01, +0.0, +0.01, -0.01} //s9 // 7 + }; + } + else if (nBins==8){ + return { + {+0.5, +0.3, +0.1, +0.2, +0.3, +0.4, +0.5, +0.5}, //s1s // 0 //S1s = 3/4(1-FL) + {+0.0, +0.0, -0.0, -0.0, -0.1, -0.1, -0.2, -0.2}, //s3 // 1 + {+0.1, +0.0, -0.2, -0.2, -0.3, -0.3, -0.3, -0.3}, //s4 // 2 + {+0.2, +0.1, -0.2, -0.3, -0.4, -0.4, -0.3, -0.2}, //s5 // 3 + {-0.1, -0.2, -0.0, +0.1, +0.3, +0.5, +0.6, +0.5}, //s6s // 4 //S6 = 4/3 AFB + {+0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0}, //s7 // 5 + {+0.0, -0.0, -0.0, -0.0, +0.0, +0.0, +0.0, +0.0}, //s8 // 6 big influence on ctl + {-0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0} //s9 // 7 + }; + /* David's reuslts + s1s = { 0.5120, 0.1800, 0.1370, 0.1930, 0.2750, 0.4170, 0.4840, 0.5030}; + s1c = { 0.2450, 0.6996, 0.7993, 0.7384, 0.6414, 0.4201, 0.3513, 0.3344}; + s2s = { 0.1448, 0.0749, 0.0514, 0.0662, 0.0900, 0.1449, 0.1620, 0.1662}; + s2c = {-0.1953,-0.6639,-0.7774,-0.7254,-0.6334,-0.4171,-0.3497,-0.3332}; + s3 = { 0.0000, 0.0020,-0.0080,-0.0120,-0.0240,-0.0620,-0.1520,-0.2330}; + s4 = { 0.0870, 0.0040,-0.1080,-0.1950,-0.2510,-0.2770,-0.2900,-0.3040}; + s5 = { 0.2440, 0.0950,-0.1590,-0.3050,-0.4140,-0.4210,-0.3400,-0.2490}; + s6s = {-0.1270,-0.2070,-0.0860, 0.0950, 0.3020, 0.5140, 0.5570, 0.4700}; + s6c = { 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000}; + s7 = {-0.0060,-0.0100,-0.0030, 0.0020, 0.0030,-0.0020,-0.0020, 0.0050}; + s8 = { 0.0010,-0.0030,-0.0040,-0.0030,-0.0010, 0.0030,-0.0010, 0.0030}; + s9 = {-0.0020, 0.0000, 0.0020, 0.0040,-0.0020,-0.0010,-0.0010, 0.0010}; + */ + } + else if (nBins==9){ //8 bins + Jpsi + return { + {+0.5, +0.3, +0.1, +0.2, +0.3, +0.3, +0.4, +0.5, +0.5}, //s1s // 0 //S1s = 3/4(1-FL) + {+0.0, +0.0, -0.0, -0.0, -0.1, -0.1, -0.1, -0.2, -0.2}, //s3 // 1 + {+0.1, +0.0, -0.2, -0.2, -0.3, -0.3, -0.3, -0.3, -0.3}, //s4 // 2 + {+0.2, +0.1, -0.2, -0.3, -0.4, -0.4, -0.4, -0.3, -0.2}, //s5 // 3 + {-0.1, -0.2, -0.0, +0.1, +0.3, +0.5, +0.5, +0.6, +0.5}, //s6s // 4 //S6 = 4/3 AFB + {+0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0}, //s7 // 5 + {+0.0, -0.0, -0.0, -0.0, +0.0, +0.0, +0.0, +0.0, +0.0}, //s8 // 6 + {-0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0} //s9 // 7 + }; + } + else if (nBins==2){ + return { + {0.0,0.0}, //s1s // 0 + {0.0,0.0}, //s3 // 1 + {0.0,0.0}, //s4 // 2 + {0.0,0.0}, //s5 // 3 + {0.0,0.0}, //s6s // 4 + {0.0,0.0}, //s7 // 5 + {0.0,0.0}, //s8 // 6 + {0.0,0.0} //s9 // 7 + }; + } + else if (nBins==1){ + return { //TODO + {+0.321}, //s1s // 0 + {-0.013}, //s3 // 1 + {-0.250}, //s4 // 2 + {-0.00}, //s5 // 3 + {-0.00}, //s6s // 4 + {-0.00}, //s7 // 5 + {-0.048}, //s8 // 6 + {-0.084} //s9 // 7 + }; + } + else { + spdlog::error("No default vectors with values for angular observables obtained from MC defined for binning scheme with {0:d} q2 bins. Exit", nBins); + assert(0); + return {}; + } +} + +std::vector> init_angular_params_zeros(int nBins){ + return std::vector > (12, std::vector (nBins, 0.0)); +} + +std::vector> init_mass_params_MC(int nBins, int nPDF){ + if (nBins == 9){ //Used only in sanity checks, so put zeros for now + return { + {+33.0, +33.0, +29.0, +29.0, +27.0, +27.0, +25.0, +22.8, +22.8}, //sigma 1 //0 + {+0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0}, //sigma 1 //0 + {+1.33, +1.33, +1.40, +1.40, +1.37, +1.26, +1.18, +1.85, +1.85}, //sigma 1 //0 + {+0.91, +0.91, +0.99, +0.99, +0.99, +1.01,+1.01, +1.34, +1.34}, //alpha 2 //3 + {+2.36,+2.36,+2.35,+2.35,+2.28,+2.28,+4.28,+3.1, +3.1}, //n 1 //4 + {+3.39,+3.39,+3.23,+3.23,+3.63,+3.63,+5.46,+3.5, +3.5} //n 2 // 5 + }; + } + else if (nBins == 8){ //Used only in sanity checks, so put zeros for now //TODO: add + return { + {+0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0}, //sigma 1 //0 + {+0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0}, //sigma 1 //0 + {+0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0}, //sigma 1 //0 + {+0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0}, //alpha 2 //3 + {-0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0}, //n 1 //4 + {+0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0, +0.0} //n 2 // 5 + }; + } + else if (nBins == 5){//TODO update values of bin 5 to actual results from MC fit. for now, taking average values of first two bins + if (nPDF ==0) return { //Run 1 + {+30.0, +31.0, +24.5, +25.2, +30.5}, //sigma 1 //0 + {+25.0, +25.0, +25.0, +25.0, +25.0}, //sigma 2 //1 + {+1.40, +1.3967, +1.37, +1.8541,+1.39835},//alpha 1 //2 + {+0.94, +0.9847, +1.0039,+1.3360,+0.96235},//alpha 2 //3 + {+3.98, +2.35, +1.85, +3.1, +3.165}, //n 1 //4 + {+4.39, +3.23, +3.63, +3.50, +3.81} //n 2 //5 + }; + if (nPDF==1) return { //Run 2 + {+35.8, +31.0, +24.5, +22.0, +33.4}, //sigma 1 //0 + {+25.0, +25.0, +25.0, +25.0, +25.0}, //sigma 2 //1 + {+1.41, +1.2853, +1.4168,+1.8406,+1.34765},//alpha 1 //2 + {+1.13, +1.0736, +1.0649,+0.9954,+1.1018}, //alpha 2 //3 + {+3.36, +2.35, +2.28, +3.1 ,+2.855}, //n 1 //4 + {+4.39, +3.23, +3.63, +3.50 ,+3.81} //n 2 //5 + }; + } + else if (nBins == 4){ + if (nPDF ==0) return { //Run 1 + {+30.0, +31.0, +24.5, +25.2}, //sigma 1 //0 + {+25.0, +25.0, +25.0, +25.0}, //sigma 2 //1 + {+1.40, +1.3967, +1.37, +1.8541},//alpha 1 //2 + {+0.94, +0.9847, +1.0039,+1.3360},//alpha 2 //3 + {+3.98, +2.35, +1.85, +3.1}, //n 1 //4 + {+4.39, +3.23, +3.63, +3.50} //n 2 //5 + }; + if (nPDF==1) return { //Run 2 + {+35.8, +31.0, +24.5, +22.0}, //sigma 1 //0 + {+25.0, +25.0, +25.0, +25.0}, //sigma 2 //1 + {+1.41, +1.2853, +1.4168,+1.8406},//alpha 1 //2 + {+1.13, +1.0736, +1.0649,+0.9954},//alpha 2 //3 + {+3.36, +2.35, +2.28, +3.1}, //n 1 //4 + {+4.39, +3.23, +3.63, +3.50} //n 2 //5 + }; + } + else if (nBins==1){ + if (nPDF==0) return{ //Run 1 + {+31.0}, //sigma 1 //0 + {+31.0}, //sigma 2 //1 + {+1.40},//alpha 1 //2 + {+0.939},//alpha 2 //3 + {+4.03}, //n 1 //4 + {+5.9} //n 2 //5 + }; + if (nPDF==1) return{ //Run 2 + {+31.0}, //sigma 1 //0 + {+31.0}, //sigma 2 //1 + {+1.442},//alpha 1 //2 + {+1.013},//alpha 2 //3 + {+3.74}, //n 1 //4 + {+3.90} //n 2 //5 + }; + } + else { + spdlog::error("No mass param vectors defined for binning scheme with {0:d} q2 bins. Exit", nBins); + assert(0); + return {}; + } + return {}; //Not needed but compiler complains +} + +//Jpsi results from B+->K*(Kspi+)mumu +std::vector init_angular_params_RefFromDavid(){ + return { + +0.321, //s1s // 0 + -0.002, //s3 // 1 + -0.246, //s4 // 2 + -0.003, //s5 // 3 + -0.003, //s6s // 4 + -0.001, //s7 // 5 + -0.063, //s8 // 6 + -0.084 //s9 // 7 + }; +} + +//obtain parameter ranges and stepsize for (most) parameters +double GetParamStepsize(std::string name){ + double stepsize = 0.1; + //TODO improving the stepsizes can be done later! + spdlog::debug("Stepsize of '"+name+"': {0:f}", stepsize); + return stepsize; +} + +std::vector GetParamRange(std::string name){ + std::vector range = {-1., +1.}; + if(name.find("m_b") != std::string::npos) return range = {B_MASS_LOW, B_MASS_HIGH}; + else if(name.find("f_sig") != std::string::npos) return range = {0.0 , 1.0}; + else if(name.find("m_sigma") != std::string::npos) return range = {PAR_SIGMA_LOW, PAR_SIGMA_HIGH}; + else if(name.find("alpha_") != std::string::npos) return range = {0.5 , 5.0}; + else if(name.find("_lambda") != std::string::npos) return range = {PAR_LAMBDA*PAR_LAMBDA_SCALE, + PAR_LAMBDA/PAR_LAMBDA_SCALE}; + else if(name.find("_tau") != std::string::npos) return range = {0.0 , 1.0}; + else if(name.find("_scale") != std::string::npos) return range = {0.0 , 2.0}; + else if(name.find("gamkstp") != std::string::npos) return range = {0.1 , 0.8}; //Width of K1, the naming convention is stupid + else if(name.find("mkstp") != std::string::npos) return range = {1.2 , 1.6}; + else if(name.find("gammakstar") != std::string::npos) return range = {0.01, 1.0}; //Width of K* + else if(name.find("mkst") != std::string::npos) return range = {K_ONE_PLUS-PAR_KSTAR_WIDTH/1.0e3, + K_ONE_PLUS+PAR_KSTAR_WIDTH/1.0e3}; + else if(name.find("nthreshold") != std::string::npos) return range = {0.1 , 10.0}; + else if(name.find("cbkg") != std::string::npos) return range = {-2.25, +1.5}; + else if(name.find("FS") != std::string::npos) return range = {0.0 , 1.0}; + else if(name == "n_1" || name == "n_2") return range = {1.0 , 8.0}; + else if(name.at(0) == 'S'){ + if (name.at(1)=='S') return range = {-PAR_ANG_RANGE, PAR_ANG_RANGE}; //S wave + else return range = {-PAR_ANG_RANGE, PAR_ANG_RANGE}; //P wave + } + else spdlog::warn("Using default range for '"+name+"': [{0:f} - {1:f}]", range.front(), range.back()); + return range; +} + diff --git a/Code/FCNCFitter/sources/Params/constants.hh b/Code/FCNCFitter/sources/Params/constants.hh new file mode 100644 index 0000000..333edec --- /dev/null +++ b/Code/FCNCFitter/sources/Params/constants.hh @@ -0,0 +1,300 @@ +// Renata Kopecna + +#ifndef CONSTANTS_HH +#define CONSTANTS_HH + +#include +#include +#include +#include + +//general constnats +const double MY_PI = TMath::Pi(); +const double C_PWAVE = 9.0/32.0/MY_PI; +const double C_SWAVE = 3.0/16.0/MY_PI; + +const double ONE_SIGMA = 0.683; +const double TWO_SIGMAS = 0.9773; +const double THREE_SIGMAS = 0.9987; + +const int DEFAULT_TREE_INT = -1; //Used when initializing doubles in trees +const double DEFAULT_TREE_VAL = -100.0; //Used when initializing doubles in trees +const double DEFAULT_TREE_ERR = 0.0; //Used when initializing error of doubles in trees + +//Set binning scheme +const double Q2_MIN_RANGE = 0.25; //Not necesarilly connected to get_TheQ2binsmin, used only when the full q2 range is used, eg for plotting +const double Q2_MAX_RANGE = 18.0; +const double Q2_MAX_RANGE_B0 = 19.0; + //Not necesarilly connected to get_TheQ2binsmax, used only when the full q2 range is used, eg for plotting +std::vector get_TheQ2binsmin(int nBins, bool Reference); +std::vector get_TheQ2binsmax(int nBins, bool Reference); + +//List excluded Q2 regions +const std::vector> EXCLUDED_Q2 ={ + {0.98,1.1}, //meaning events with q^2 in 0.98-1.1 will not be considered + {8.0,11.0}, + {12.5,15} +}; + +const int NBINS_DEFAULT = 4; //used as a default number of q2 bins + +//Set resolution +std::vector> get_resolution(); + +//Set limits of the angles +const double CTL_MIN = -1.0; +const double CTL_MAX = +1.0; +const double CTK_MIN = -1.0; +const double CTK_MAX = +0.8; +const double PHI_MIN = -TMath::Pi(); +const double PHI_MAX = +TMath::Pi(); + +//Set the maximum number of folding ID, useful for loops +const double MAX_FOLDING = 5; + +//Ranges of the angles, always max-min +double CTL_RANGE(); +double CTK_RANGE(); +double PHI_RANGE(); +double Q2_RANGE_FULL(); +double RANGE_3D(); //ctl*ctk*phi range +double RANGE_4D(); //ctl*ctk*phi*q2 range + + +const int nANGLES = 3; +const std::vector ANGLES = {"ctl", "ctk", "phi"}; +//This *could* be in design.hh, but then it has to be sourced everywhere and this is just easier +const std::vector latex_angles = {"cos(#Theta_{L})", "cos(#Theta_{K})", "#phi"}; +const std::vector latex_2angles = {"\\ctl", "\\ctk", "$\\phi$"}; + +////////////////////////////////// +// Fitter options // +////////////////////////////////// + +//Set number of used cores +const int NCORES = 8; + +const double MIG_MAX_CALLS = 100000000.0; +const double MIG_TOLERANCE = 0.1; //TODO +// The default tolerance in TMinuit is 0.1 +// The minimization will stop when the estimated vertical distance to the minimum (EDM) is less than 0.001*[tolerance]*UP(see SET ERR) + + +////////////////////////////////// +// Basic paths // +////////////////////////////////// + +//Set decay string and main path +const std::string DECAY_NAME = "KplusPi0Resolved";//"KshortPiplus" +const std::string CONFIG_PHSP_WEIGHT = "config/phspweightq2.root"; + +////////////////////////////////// +// plotting // +////////////////////////////////// +const bool PLOT_THISTHESIS_TAG = true; +const std::string THISTHESIS_TAG = "this thesis"; +const int PLOT_NBINS_MB = 100; +const int PLOT_NBINS_MKSTAR = 50; +const int PLOT_NBINS_ANGLES = 20; +//When plotting, the pdf is plotted as a very fine TH1D, +//PLOT_NBINS_RATIO says how many times more bins is there in the pdf compared to the data bins +const int PLOT_NBINS_RATIO = 20; + + +////////////////////////////////// +// PDG masses // +////////////////////////////////// + +const Double_t PDGMASS_B_PLUS = 5279.29; +const Double_t PDGMASS_B_ZERO = 5279.61; +const Double_t PDGMASS_J_PSI = 3096.90; +const Double_t PDGMASS_PSI_2S = 3686.10; +const Double_t PDGMASS_K_STAR_PLUS = 891.66; +const Double_t K_ONE_PLUS = 1272.0; +const Double_t PDGMASS_K_PLUS = 493.68; +const Double_t PDGMASS_K_SHORT = 497.61; +const Double_t PDGMASS_PI_PLUS = 139.57; +const Double_t PDGMASS_PI_ZERO = 134.98; +const Double_t PDGMASS_MU = 105.66; +const Double_t PDGMASS_GAMMA = 0.0; + +//Decay specific PDG masses +const Double_t PDGMASS_K_STAR = PDGMASS_K_STAR_PLUS; +const Double_t PDGMASS_KST_KAON = PDGMASS_K_PLUS; +const Double_t PDGMASS_KST_PION = PDGMASS_PI_ZERO; +const Double_t PDGMASS_B = PDGMASS_B_PLUS; + +//Set mass range and window of the B mass +const double B_MASS_LOW = 5150.0; +const double B_MASS_HIGH = 5800.0; +//CAREFUL when initializing the m_b parameter: +//the min and max set also the fit range, so it should be always +//set to B_MASS_LOW and B_MASS_HIGH + +//The tight window is used for plotting the very signal only region +const double B_MASS_TIGHT_WINDOW = 100; //David had 50 + +//Set the cuts from where we have only background +const double B_MASS_HIGH_BKG = PDGMASS_B_PLUS + 100; +const double B_MASS_LOW_BKG = PDGMASS_B_PLUS - 100; +const double B_MASS_HIGH_BKG_REF = PDGMASS_B_PLUS + 350; +const double B_MASS_LOW_BKG_REF = 5150; + +const double KPI_MASS_MIN = PDGMASS_K_STAR-100.; +const double KPI_MASS_MAX = PDGMASS_K_STAR+100.; + +////////////////////////////////// +// PARTICLE IDs // +////////////////////////////////// +const int ID_B_PLUS = +521; +const int ID_B_ZERO = +511; + +const int ID_K_STAR_PLUS = +323; +const int ID_K_STAR_ZERO = +313; + +const int ID_K_PLUS = +321; +const int ID_K_SHORT = +310; + +const int ID_PI_PLUS = +211; +const int ID_PI_ZERO = +111; +const int ID_GAMMA = +22; + +const int ID_MU_PLUS = -13; +const int ID_MU_MINUS = +13; +const int ID_J_PSI = +443; +const int ID_RHO_ZERO = +113; + +const int ID_K_ONE_PLUS = +10323; // K1(1270)+ +const int ID_K_ONE_PLUS_1400 = +20323; // K1(1400)+ +const int ID_K_ONE_PLUS_1410 = +100323; // K1(1410)+ +const int ID_K_ONE_ZERO = 10313; // K0(1270)+ +const int ID_ELECTRON = -11; + +////////////////////////////////// +// Angular correction // +////////////////////////////////// + +//Modify this after being done with scannig the corrections +const bool IS_PHI_EVEN = true; +const int ORDER_COSTHETAL = 3; +const int ORDER_COSTHETAK = 6; +const int ORDER_PHI = 1; +const int ORDER_Q2 = 7; + +////////////////////////// +// Reweighting // +////////////////////////// + +//Descides at what 1/weight you reject events +//Large weights result in large errorbars and can be a source of fluctuations +const double EFF_CUTOFF = 0.01; + + +////////////////////////////////// +// Idk why, but here are pies // +////////////////////////////////// +const double M_4_PI = 1.2732395447351626861510701069801; // 4/Pi +const double M_SQRTPI = 1.7724538509055160272981674833411; // sqrt(Pi) +const double M_SQRT2PI = 2.5066282746310005024157652848111; // sqrt(2Pi) +const double M_SQRT_PI_2= 1.2533141373155002512078826424055; // sqrt(Pi/2) +const double M_SQRT_2_PI= 0.79788456080286535587989211986876; // sqrt(2/Pi) +const double M_1_SQRTPI = 0.56418958354775628694807945156077; // 1/sqrt(Pi) +const double m_2_SQRTPI = 1.1283791670955125738961589031216; // 2/sqrt(Pi) +//M_2_SQRTPI is defined in math.h, see https://stackoverflow.com/questions/52796736/why-does-c-define-m-2-sqrtpi-constant-in-math-h +const double M_SQRT_2PI = 0.39894228040143267793994605993438; // 1/sqrt(2Pi) +const double M_SQRT_2 = 0.70710678118654752440084436210485; // sqrt(1/2) +const double M_2PI = 6.2831853071795864769252867665590; // 2Pi +const double M_4PI = 12.5663706143591729538505735331180; //4Pi + + + +////////////////////////// +// Fit parameters // +////////////////////////// + +//Set default values for most parameters +//These values can be set individually, but it is good to have some default starting points + +//Check the definitions in bu2kstarmumu_parameters! + +const double PAR_ANG_RANGE = 1.0; //Default range for all angular observables +const double PAR_SIGMA = 30.0; //[MeV] +const double PAR_SIGMA_LOW = 25.0; //[MeV] +const double PAR_SIGMA_HIGH = 50.0; //[MeV] +const double PAR_TAU = 100.0; +const double PAR_TAU_SCALE = 100.0; //Tau range is then par_tau/scale to par_tau*scale +const double PAR_LAMBDA = -0.0001; +const double PAR_LAMBDA_SCALE = 100.0; //Lambda range is then par_lambda*scale to par_lambda/scale +const double PAR_NTRESHOLD = 1.5; +const double PAR_KSTAR_WIDTH = 50.0; //[MeV] +const double PAR_K1_WIDTH = 270.0; //[MeV] +const double PAR_N_SIG = 150.0; +const double PAR_N_BKG = 500.0; //f_sig is init as PAR_N_SIG/(PAR_N_SIG+PAR_N_BKG) + +//If you want to have only 1 exponential in bkg, set to false +const double FIX_FM = true; +const double DOUBLE_CB = true; //Just always use double CB, it is not like anyone is going to switch this halfway through the code + +//This string contains parameters that are varied when fitting bkg +//TODO: optimize at some point +std::vector PAR_BKG_STRING(int folding, int nCtl, int nCtk); +//Init values of said parameters +//CAREFUL!!!! HAS TO BE THE SAME AS PAR_BKG_STRING!!!! +std::vector init_bkg(int folding, int nCtl, int nCtk); + +////////////////////////////////// +// Main Fit Parameters // +////////////////////////////////// + +//Number of angular terms: 12 for P wave, 6 for S wave +const int NTERMS_P = 12; +const int NTERMS_S = 6; +const int NTERMS = NTERMS_S + NTERMS_P; //If no s Wave ever, one can also set it to 12 and save some memory + +//Fraction of events in each subset +std::vector > fracs(int nBins); + +//Init default parameters +std::vector init_n_signal(int nBins); +std::vector init_n_bckgnd(int nBins); +std::vector init_f_lambda(int nBins); +std::vector get_f_subset(int nPDFs); + +//Used in EventNumbers +const std::vector > sig_unblinded = { //Set only for 8 bins and 4 pdfs //TODO + {5.86168, 13.9418, 54.4478, 27.3012}, + {2.36522, 1.09800, 31.7908, 13.7227}, + {8.99630, 6.53635, 14.4187, 12.2178}, + {14.0240, 8.82742, 62.4731, 23.5189}, + {5.11878, 7.85420, 59.2977, 32.3194}, + {17.7802, 12.8009, 39.0769, 40.8969}, + {19.8873, 12.7440, 81.8400, 29.7622}, + {3.73514, 7.56100, 32.8754, 31.5777} +}; + +const std::vector > bkg_unblinded = { //Set only for 8 bins and 4 pdfs //TODO + {18.6849, 10.7306, 130.508, 26.1523}, + {28.8699, 11.4018, 152.795, 26.1676}, + {36.0865, 7.24722, 196.480, 35.0536}, + {39.2519, 22.7192, 163.944, 61.0158}, + {65.1688, 19.2037, 165.299, 48.0148}, + {19.5884, 16.5293, 88.6190, 46.0676}, + {17.2658, 14.1666, 42.6978, 34.5553}, + {17.6887, 20.2719, 41.7393, 26.3643} +}; + +std::vector> init_angular_params(int nBins, bool NP, bool isReference); + +std::vector> init_angular_params_MC(int nBins); +std::vector> init_angular_params_zeros(int nBins); + +std::vector> init_mass_params_MC(int nBins, int nPDF); + +//Jpsi results from B+->K*(Kspi+)mumu +std::vector init_angular_params_RefFromDavid(); + +//obtain parameter ranges and stepsize for (most) parameters +double GetParamStepsize(std::string); +std::vector GetParamRange(std::string); + +#endif // CONSTANTS_HH diff --git a/Code/FCNCFitter/sources/Params/parameters.cc b/Code/FCNCFitter/sources/Params/parameters.cc new file mode 100644 index 0000000..3cb26e1 --- /dev/null +++ b/Code/FCNCFitter/sources/Params/parameters.cc @@ -0,0 +1,230 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +/** + * @file parameters.cc + * @author Renata Kopecna + * @date 2021-03-02 + * + */ + +void fcnc::parameter::set_values_n_errors(double v, double e){ + value = v; + start_value = v; + previous_measurement = v; + + error = e; + error_down = e; + error_up = e; + previous_error_low = e; + previous_error_high = e; + //step_size = e; //not correct +} +void fcnc::parameter::reset_correlations(){ + correlations.clear(); +} +void fcnc::parameter::set_correlation(double corr, unsigned int idx){ + while(correlations.size() <= idx) correlations.push_back(0.0); + correlations.at(idx) = corr; +} +void fcnc::parameter::set_correlations(std::vector corrs, unsigned int first, unsigned int last, double scalefactor){ + reset_correlations(); + assert(first < last); + assert(last < corrs.size()); + for(unsigned int idx = first; idx <= last; idx++){ + correlations.push_back(scalefactor * corrs.at(idx)); + } +} + +///set blinding string +void fcnc::parameter::set_blinding_string(std::string s) { + blinding_string = s; +} +void fcnc::parameter::set_blinding(bool b, double b_scale, bool is_angle, std::string b_string) { + blind = b; + blinding_scale = b_scale; + blinding_string = b_string; + //this is new, apparently the shi(f)t needs to be subtracted, who knew? + /* removed by David 18/07/18, as the functions are commented out in funcs.cc anyhow... + if (is_angle) + blinding_delta = -evaluate_unblind_uniform(0.0, blinding_string.c_str(), blinding_scale); + else + blinding_delta = -evaluate_unblind_uniform_angle(0.0, blinding_string.c_str(), blinding_scale); +*/ + //new blinding: just add + TRandom3 * rn = new TRandom3(0); + blinding_delta = rn->Gaus(0., 1.); + delete rn; +} + +std::string fcnc::parameter::get_root_name() const { + std::string rootstring = get_description(); + size_t j; + while ((j = rootstring.find("\\mathrm ")) != std::string::npos) rootstring.replace(j,8,""); + while ((j = rootstring.find("\\")) != std::string::npos) rootstring.replace(j,1,"#"); + return rootstring; +} + + +///The parameters class stores a collection of parameters used in the analysis. Every analysis should implement its own set e.g. bs2jpsiphi_parameters +void fcnc::parameters::add_parameter(parameter* param) { + param->set_index(params.size()); + param->set_parent(this); + params.push_back(param); +} + +bool fcnc::parameters::is_blind() const { + for (unsigned int i = 0; iis_blind()) return true; + } + return false; +} + +unsigned int fcnc::parameters::nparameters() const{ + return params.size(); +} + +///Methos returns a pointer to parameter with index i +fcnc::parameter* fcnc::parameters::get_parameter(unsigned int i) const{ + return params.at(i); +} + +///returns parameter with specific name +fcnc::parameter* fcnc::parameters::get_parameter(std::string name) const{ + parameter* res=0; + for (unsigned int i =0; iget_name() == name){ + res = get_parameter(i); + break; + } + return res; +} + +///Resets all parameters to their start values +void fcnc::parameters::reset_parameters(){ + for (unsigned int i = 0; i < nparameters(); i++) params.at(i)->reset_start(); +} + +///Method that prints the parameter set, the current values, errors and the deviation from the start value in sigma +void fcnc::parameters::print_parameters(bool latex_output) const{ + + std::ofstream myFile; + open_Latex_noteFile(latex_params(), myFile); + if (!latex_output){ + if (spdlog_trace()){ + std::cout << std::endl << "Parameters" << std::endl; + spdlog::info("Blinded Parameters: "); + for (unsigned int j = 0; j < nparameters(); j++){ + if (params[j]->is_blind()) std::cout << params[j]->get_name() << " "; + } + std::cout << std::endl; + + spdlog::info("The {0:d} Parameters: ", nparameters()); + for (unsigned int j = 0; j < nparameters(); j++) { + std::string parname(params[j]->get_name());//the_minimizer->fCpnam[j]); + std::cout.setf(std::ios::left); + double nsigma = 0.0; + if (params[j]->get_error() > 0.0){ + nsigma = (params[j]->get_value() - params[j]->get_start_value())/params[j]->get_error(); + } + double value = params[j]->get_value(); + // if (params[j]->is_blind()) + // value += params[j]->blinding_delta;//todo + double error = params[j]->get_error(); + double error_up = params[j]->get_error_up(); + double error_down = params[j]->get_error_down(); + if (params[j]->is_blind()){ + value += params[j]->blinding_delta * (error_up + error_down) / 2.; + } + if (error_up == error_down){ + std::cout << std::setw(12) << parname + //<< std::setw(12) << (params[j]->is_blind() ? "(*)" : format_value(value, error)) + << std::setw(12) << (format_value(value, error)) + << std::setw(12) << "+-" + << std::setw(12) << format_error(error) + << std::setw(12) << (params[j]->is_blind() ? " (*)": "") + << " " << (params[j]->is_blind() ? "(*)" : format_double(nsigma)) << " sigma" << std::endl; + } + else { + std::cout << std::setw(12) << parname + //<< std::setw(12) << (params[j]->is_blind() ? "(*)" : format_value(value, error)) + << std::setw(12) << (format_value(value, error)) + << std::setw(12) << " " << format_error(error_down) + << std::setw(12) << " " << format_error(error_up) + << std::setw(12) << (params[j]->is_blind() ? "(*)": "") + << " " << (params[j]->is_blind() ? "(*)" : format_double(nsigma)) << " sigma" << std::endl; + } + } + } + } + else { + if (params[0]->get_error_up() == params[0]->get_error_down()){ + myFile << "\\begin{tabular}{|c|c|c|} \\hline" << std::endl; + myFile << "parameter & result & $\\sigma$ from nominal \\\\ \\hline \\hline" << std::endl; + } + else{ + myFile << "\\begin{tabular}{|c|c|c|c|c|} \\hline" << std::endl; + myFile << "parameter & result & $\\sigma_\\text{down}$ & $\\sigma_\\text{up}$ & $\\sigma$ from nominal \\\\ \\hline \\hline" << std::endl; + } + for (unsigned int j = 0; j < nparameters(); j++){ + std::string pardesc(params[j]->get_description());//the_minimizer->fCpnam[j]); + std::string partex(""); + for (std::string::iterator it = pardesc.begin(); it != pardesc.end(); it++){ //Replace the ROOT tex by actual latex //TODO: maybe do this properly + if (*it != '#') partex += *it; + else partex += "\\"; + } + double value = params[j]->get_value(); + if (params[j]->is_blind()) value += params[j]->blinding_delta;//todo + double error = params[j]->get_error(); + if (error == 0.0) continue; //Do not print fixed params into latex + double error_up = params[j]->get_error_up(); + double error_down = params[j]->get_error_down(); + double nsigma = 0.0; + if (error > 0.0) nsigma = (value - params[j]->get_start_value())/error; + std::cout.setf(std::ios::left); + + if (error_up == error_down){ + myFile << "$" << std::setw(20) << partex << "$ & $" + //<< std::setw(12) << (params[j]->is_blind() ? "(*)" : format_value(value, error)) + << std::setw(12) << ((params[j]->get_step_size() == 0.0 && params[j]->is_blind()) ? "" : format_value(value, error)) + << "\\pm " << std::setw(12) << format_error(error) << (params[j]->is_blind() ? "(*)": "") << "$ & " + << (params[j]->is_blind() ? "(*)" : format_double(nsigma)) << "\\\\" << std::endl; + } + else{ + myFile << "$" << std::setw(20) << partex << "$ & $" + << std::setw(12) + //<< (params[j]->is_blind() ? "(*)" : format_value(value, error)) + << (format_value(value, error)) + << "\\pm " + << std::setw(12) << format_error(error) << (params[j]->is_blind() ? "(*)": "") << "$ & " + << std::setw(12) << format_error(error_down)<< " & " + << std::setw(12) << "+" << format_error(error_up) << " & " + << (params[j]->is_blind() ? "(*)" : format_double(nsigma)) << "\\\\" << std::endl; + } + } + myFile << "\\hline" << std::endl; + myFile << "\\end{tabular}" << std::endl; + } +} + +///fix all parameters +void fcnc::parameters::fix_parameters() { + for (unsigned int i = 0; i < params.size(); i++) params.at(i)->set_step_size(0.0); +} +///set all parameters to current values! Careful with this, please. +void fcnc::parameters::take_current_as_start() { + for (unsigned int i = 0; i < params.size(); i++) { + parameter* p = params.at(i); + p->set_start_value(p->get_value()); + } +} + + diff --git a/Code/FCNCFitter/sources/Params/parameters.hh b/Code/FCNCFitter/sources/Params/parameters.hh new file mode 100755 index 0000000..86554cb --- /dev/null +++ b/Code/FCNCFitter/sources/Params/parameters.hh @@ -0,0 +1,245 @@ +/** + * @file parameters.hh + * @author Christoph Langenbruch, Renata Kopecna + * @date 2009-03-18 + * + */ +#ifndef PARAMETERS_H +#define PARAMETERS_H + +#include +#include + +namespace fcnc { + +class parameters; + +/// The parameter class stores the different attributes of a parameter used in the analysis, e.g. the name, start value and the parameter range. +class parameter { + friend class parameters; + friend class feldman_cousins; +private: + ///blind this parameter + bool blind; + ///blinding string + std::string blinding_string; + ///blinding delta, never look at this + double blinding_delta; + ///blinding range + double blinding_scale; + ///This name is supplied as the parameter name to minuit. Please give every parameter a different name. + std::string name; + ///The parameter description is used by the plotter for plot captions and axis titles. + std::string description; + ///The start value of the parameter. After every step in the toy study, the parameter is reset to this value. + double start_value; + ///The current value of the parameter + double value; + ///The minimum possible value for the parameter + double min; + ///The maximum possible value for the parameter + double max; + ///The initial step size used by minuit + double step_size; + ///The error of the fitted result + double error; + ///asymmetric errors if a minos error analysis has been performed + double error_up; + ///asymmetric errors if a minos error analysis has been performed + double error_down; + ///the index of this parameter in the params array of the parameter set + int index; + ///should the parameter float without limits? + bool unlimited; + ///this has been the error of a previous measurement + double previous_error_low; + double previous_error_high; + ///previous measurement, this can be different from the start value, e.g. when running a toy study + double previous_measurement; + ///do we want to vary the parameter so that it is compatible with an earlier measurement + bool gaussian_constraint; + bool do_minos; + ///pointer to parent parameterset this parameter was added to! + parameters* parent; +public: + /// + void set_parent(parameters* p) {parent = p;}; + //correlations + std::vector correlations; + ///public set routines + void set_name(std::string n) {name = n;}; + void set_min(double m) {min = m;}; + void set_max(double m) {max = m;}; + void set_step_size(double s) {step_size = s;}; + void set_value(double v) {value = v;}; + void set_start_value(double v) {start_value = v;}; + //void set_true_value(double v) {true_value = v;}; + void set_description(std::string d) {description = d;}; + void set_error(double e) {error = e;}; + void set_error_down(double e) {error_down = e;}; + void set_error_up(double e) {error_up = e;}; + void set_unlimited(bool u) {unlimited = u;}; + void set_index(int idx) {index = idx;}; + void set_previous_measurement(double m) {previous_measurement = m;}; + void set_previous_error_low(double e) {previous_error_low = e;}; + void set_previous_error_high(double e) {previous_error_high = e;}; + void set_values_n_errors(double v, double e); + void reset_correlations(); + void set_correlation(double corr, unsigned int idx); + void set_correlations(std::vector corrs, unsigned int first, unsigned int last, double scalefactor = 1.0); + + ///set blinding string + void set_blinding_string(std::string s); + void set_minos(bool minos) { do_minos = minos; }; + bool get_minos() { return do_minos; }; + void set_blinding(bool b, double b_scale, bool is_angle=false, std::string b_string="DefaultBlinder"); + + ///set all values which make sense on initialisation + void init(double v, double min, double max, double stepsize) + { + set_value(v); + start_value = v; + set_min(min); + set_max(max); + set_step_size(stepsize); + set_error(0.0); + set_error_up(0.0); + set_error_down(0.0); + set_unlimited(false); + set_minos(false); + gaussian_constraint = false; + previous_measurement = v; + correlations.clear(); + }; + + void init_fixed(double v){ + init(v, v-0.01, v+0.01, 0.0); + //This eaquals to the previous init with limits of v-0.01, v+0.01 + //Not sure if there is a < or <= further in the code, so let's play it safe + } + void init(double v, double min, double max, double stepsize, double previous_measurement_error, bool constrain) + { + init(v, min, max, stepsize); + previous_error_low = previous_measurement_error; + previous_error_high = previous_measurement_error; + gaussian_constraint = constrain; + } + void init(double v, double min, double max, double stepsize, double previous_measurement_error_low, double previous_measurement_error_high, bool constrain) + { + init(v, min, max, stepsize); + previous_error_low = previous_measurement_error_low; + previous_error_high = previous_measurement_error_high; + gaussian_constraint = constrain; + } + void init_unlimited( double v, double min, double max, double stepsize, bool nolimits) + { + init(v, min, max, stepsize); + unlimited = nolimits; + }; + + ///public get routines + std::string get_name() const {return name;}; + const char* get_mn_name() const {return get_name().c_str();}; + double get_min() const {return min;}; + double get_max() const {return max;}; + double get_blinding_delta() const {return blinding_delta;}; + double get_step_size() const {return step_size;}; + double get_value() const {return value;}; + double get_start_value() const {return start_value;}; + //double get_true_value() const {return true_value;}; + double get_previous_error() const {return 0.5*(previous_error_low+previous_error_high);}; + double get_previous_error_low() const {return previous_error_low;}; + double get_previous_error_high() const {return previous_error_high;}; + double get_previous_measurement() const {return previous_measurement;}; + std::string get_description() const {return description;}; + bool get_unlimited() const {return unlimited;}; + bool get_gaussian_constraint() const {return gaussian_constraint;}; + + std::string get_root_name() const; + ///public set routines + void set_constant() {step_size = 0.0;}; + double operator() () const {return value;}; + double get_error() const {return error;}; + double get_error_up() const {return error_up;}; + double get_error_down() const {return error_down;}; + int get_index() const {return index;}; + void reset_start() {value = start_value; error = 0.0;}; + ///default constructor + parameter(std::string n, std::string d): + blind(false), + blinding_string("DefaultBlinder"), + blinding_delta(0.0), + name(n), + description(d), + start_value(0.0), + value(0.0), + min(-1.0), + max(+1.0), + step_size(0.001), + error(0.0), + error_up(0.0), + error_down(0.0), + index(-1), + unlimited(false), + previous_error_low(0.0), + previous_error_high(0.0), + previous_measurement(0.0), + gaussian_constraint(false) + {}; + ///normal constructor + parameter(std::string n, std::string d, double v, + double minimum, double maximum, double stepsize = 0.0, bool nolimits=false): + blind(false), + blinding_string("DefaultBlinder"), + blinding_delta(0.0), + name(n), + description(d), + start_value(v), + // true_value(v), + value(v), + min(minimum), + max(maximum), + step_size(stepsize), + error(0.0), + error_up(0.0), + error_down(0.0), + index(-1), + unlimited(nolimits), + gaussian_constraint(false) + {}; + bool is_blind() { + return blind; + }; +}; + +///The parameters class stores a collection of parameters used in the analysis. Every analysis should implement its own set e.g. bs2jpsiphi_parameters +class parameters +{ +private: + ///this vector holds the different parameters + std::vector params; +protected: + ///Add a certain parameter to the params vector. + void add_parameter(parameter* param); +public: + bool is_blind() const; + virtual ~parameters() {}; + ///Method gives back he number of parameters + unsigned int nparameters() const; + ///Methos returns a pointer to parameter with index i + parameter* get_parameter(unsigned int i) const; + ///returns parameter with specific name + parameter* get_parameter(std::string name) const; + ///Resets all parameters to their start values + void reset_parameters(); + ///Method that prints the parameter set, the current values, errors and the deviation from the start value in sigma + void print_parameters(bool latex_output=true) const; + ///fix all parameters + void fix_parameters(); + ///set all parameters to current values! Careful with this, please. + void take_current_as_start(); +}; + +} + +#endif diff --git a/Code/FCNCFitter/sources/Params/parameterscan.cc b/Code/FCNCFitter/sources/Params/parameterscan.cc new file mode 100644 index 0000000..77b3685 --- /dev/null +++ b/Code/FCNCFitter/sources/Params/parameterscan.cc @@ -0,0 +1,458 @@ +#include + + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +/** + * @file parameterscan.cc + * @author Renata Kopecna + * @date 2021-03-02 + * + */ + +fcnc::parameterscan::parameterscan(options* o): + multifit(o) +{ +}; + +void fcnc::parameterscan::scan(std::string param_name, double min, double max, unsigned int nsteps, unsigned int nevents, unsigned int reruns, pdf* prob, parameters* params, generator* gen, bool only_float_in_generation){ + std::vector events; + events.push_back(nevents); + + std::vector probs; + probs.push_back(prob); + + std::vector the_params; + the_params.push_back(params); + + std::vector gens; + gens.push_back(gen); + + scan(param_name, min, max, nsteps, events, reruns, probs, the_params, gens, only_float_in_generation); +} + +//void parameterscan::scan(std::string param_name, double min, double max, unsigned int nsteps, unsigned int nevents, unsigned int reruns, pdf_type* prob, params_type* params, generator_type* gen, bool only_float_in_generation) //fixed in fit on fixed value +void fcnc::parameterscan::scan(std::string param_name, double min, double max, unsigned int nsteps, std::vector nevents, unsigned int reruns, std::vector pdfs, std::vector params, std::vector gens, bool only_float_in_generation){ + parameter* param_varied = 0; + for (unsigned int i=0; iget_parameter(param_name)) { + param_varied = params.at(i)->get_parameter(param_name); + break; + } + } + + //open TeX file + std::ofstream myFile; + open_Latex_noteFile(latex_paramScan(), myFile); + + //parameter* param_varied = params->get_parameter(param_name); + + double fit_start_value = param_varied->get_start_value(); + if (only_float_in_generation) spdlog::info( "The fit start value will be fixed at: {0:f}",fit_start_value); + + int param_index = param_varied->get_index(); + if (param_varied != 0){ + std::string param_description = param_varied->get_description(); + std::string param_root = param_varied->get_root_name(); + spdlog::info( "Doing parameter scan of parameter {0:d}: {1:s}", param_index, param_name); + spdlog::info( "Varying parameter from {0:f} to {1:f}", min, max); + + unsigned int nparams = 0; + for (unsigned int i=0; inparameters(); + } + //params->nparameters(); + + TH1D* error_hists[nparams]; + TH1D* value_hists[nparams]; + double mean_values[nparams][nsteps+1]; + double sigma_mean_values[nparams][nsteps+1]; + double mean_errors[nparams][nsteps+1]; + double sigma_mean_errors[nparams][nsteps+1]; + + double min_hist = min - 0.5*(max-min)/nsteps; + double max_hist = max + 0.5*(max-min)/nsteps; + //create histograms + unsigned int start_param = 0; + for (unsigned int i=0; iget_parameter(j); + error_hists[idx] = new TH1D(("error_" + param->get_name()).c_str(), + ("#sigma" + param->get_root_name() + ";" + param_root).c_str(), + nsteps+1, min_hist, max_hist); + error_hists[idx]->SetMarkerStyle(8); + error_hists[idx]->SetMarkerColor(4); + value_hists[idx] = new TH1D(("value_" + param->get_name()).c_str(), + (param->get_root_name() + ";" + param_root).c_str(), + nsteps+1, min_hist, max_hist); + value_hists[idx]->SetMarkerStyle(8); + value_hists[idx]->SetMarkerColor(4); + } + start_param += params.at(i)->nparameters(); + } + //do precalculations + for (unsigned int i=0; iinit(params.at(i)); + } + //create output trees + //current values to fill into the tree + double value, error, error_up, error_down, start_value, param_value, nominal_error, nominal_value; + int step, run, migrad, status_cov; + std::vector trees;//one tree for every varied parameter + //start_param = 0; + for (unsigned int i=0; iget_parameter(j); + if (param->get_step_size() != 0.0){ + std::string parname(param->get_name()); + std::string pardesc(param->get_description());// + " results"); + TTree* t = new TTree(parname.c_str(), pardesc.c_str()); + t->Branch("step",&step,"step/I"); + t->Branch("run",&run,"run/I"); + t->Branch("param_value",¶m_value,"param_value/D"); + t->Branch("value",&value,"value/D"); + t->Branch("error",&error,"error/D"); + t->Branch("nominal_value",&nominal_value,"nominal_value/D"); + t->Branch("nominal_error",&nominal_error,"nominal_error/D"); + t->Branch("error_up",&error_up,"error_up/D"); + t->Branch("error_down",&error_down,"error_down/D"); + t->Branch("start_value",&start_value,"start_value/D"); + t->Branch("migrad",&migrad,"migrad/I"); + t->Branch("status_cov",&status_cov,"status_cov/I"); + trees.push_back(t); + } + } + //start_param += params.at(i)->nparameters(); + } + + //enter main loop + for (unsigned int i = 0; i <= nsteps; i++){ + //reset all results + std::vector > values(nparams, std::vector(reruns, 0.0)); + std::vector > errors(nparams, std::vector(reruns, 0.0)); + std::vector > errors_up(nparams, std::vector(reruns, 0.0)); + std::vector > errors_down(nparams, std::vector(reruns, 0.0)); + std::vector > nominal_values(nparams, std::vector(reruns, 0.0)); + std::vector > nominal_errors(nparams, std::vector(reruns, 0.0)); + std::vector return_values(reruns); + + //only_float_in_generation means that you use a varied parameter + //for generation but in the fit use the start_value + //this can be used for systematic studies + //we would also need to do a nominal fit + //then we can see the actual difference + + //choose new value for the scan parameter + param_value = double(i)*(max - min)/(nsteps) + min; + if (!only_float_in_generation){ //float in generation and fit + param_varied->set_value(param_value); + param_varied->set_start_value(param_value); + } + // param_varied->init(param_name, param_description, + // param_value, + // param_varied->get_min(), param_varied->get_max(), + // param_varied->get_step_size()); + + //this is the scanned parameter so usually we change it before generation and fit + //this is the point: we need to do a couple reruns + fitter fit(opts); + fit.set_common_parameters(common_params); + + for (unsigned int k = 0; k < reruns; k++){ + spdlog::info( "Parameter "+param_name+" {0:f}", param_value); + spdlog::info( "Run no. {0:d}", k); + std::string num; + std::stringstream out; + out << opts->name << "_" << (i+1) << "_" << (k+1); //TOOD: move to paths + num = out.str(); + + if (only_float_in_generation){//this generates with updated parameter values + param_varied->set_value(param_value); + param_varied->set_start_value(param_value); + } + // param_varied->init(param_name, param_description, + // param_value, + // param_varied->get_min(), param_varied->get_max(), + // param_varied->get_step_size()); + + for (unsigned int j=0; jreset_parameters();//this line was missing before? did we generate with fitted params? + } + + std::vector< std::vector > temp_events; + for (unsigned int j=0; j ev = gens.at(j)->generate(nevents.at(j), params.at(j), pdfs.at(j)); + temp_events.push_back(ev); + } + std::vector< std::vector * > events; + for (unsigned int j=0; jset_value(fit_start_value); + param_varied->set_start_value(fit_start_value); + } + // param_varied->init(param_name, param_description, + // fit_start_value, //use start value here! + // param_varied->get_min(), param_varied->get_max(), + // param_varied->get_step_size()); + + + for (unsigned int j=0; jreset_parameters(); + } + int result = 0; + result = fit.fit(pdfs, params, events, num); + + return_values.at(k) = result; + if (result != 0 && opts->repeat_on_fail){ + spdlog::warn( "Fit failed, repeating run"); + k--; + continue; + } + unsigned int start_param = 0; + for (unsigned int j = 0; j < params.size(); j++){ + for (unsigned int l = 0; l < params.at(j)->nparameters(); l++){ + unsigned int idx = start_param+l; + parameter* param = params.at(j)->get_parameter(l); + values.at(idx).at(k) = param->get_value(); + errors.at(idx).at(k) = param->get_error(); + errors_up.at(idx).at(k) = param->get_error_up(); + errors_down.at(idx).at(k) = param->get_error_down(); + } + start_param += params.at(j)->nparameters(); + } + //now we want to do a nominal fit (if the respective options are set) + if (opts->refitting_nominal && only_float_in_generation){//now we do a nominal fit + spdlog::info( "Nominal fit"); + + param_varied->set_value(param_value); + param_varied->set_start_value(param_value); + // param_varied->init(param_name, param_description, + // param_value, + // param_varied->get_min(), param_varied->get_max(), + // param_varied->get_step_size()); + + for (unsigned int j = 0; j < params.size(); j++){ + params.at(j)->reset_parameters(); + } + //and lets fit + fit.fit(pdfs, params, events, num); + + //extract the parameters from the fit + start_param = 0; + for (unsigned int j = 0; j < params.size(); j++){ + for (unsigned int l = 0; l < params.at(j)->nparameters(); l++){ + unsigned int idx = start_param+l; + parameter* param = params.at(j)->get_parameter(l); + nominal_values.at(idx).at(k) = (param->get_value()); + nominal_errors.at(idx).at(k) = (param->get_error()); + } + start_param += params.at(j)->nparameters(); + } + } + else{ + for (unsigned int j = 0; j < nparams; j++){ + nominal_values.at(j).at(k) = (0.0); + nominal_errors.at(j).at(k) = (0.0); + } + } + + }//end reruns + + //determine means/widths of the distributions via gauss-fits + unsigned int start_param = 0; + for (unsigned int j = 0; j < params.size(); j++){ + for (unsigned int k = 0; k < params.at(j)->nparameters(); k++){ + unsigned int idx = start_param + k; + parameter* param = params.at(j)->get_parameter(k); + if (param->get_step_size() != 0.0){ + std::string step; + std::stringstream out; + out << (i+1); + step = out.str(); + + double dummy1, dummy2, dummy3, dummy4, dummy5; + double mean_value, mean_error, sigma_mean_value, sigma_mean_error; + update_pull(param, values.at(idx), errors.at(idx), + dummy1, dummy2, dummy3, dummy4, dummy5, step); + update_value(param, values.at(idx), errors.at(idx), + mean_value, sigma_mean_value, dummy3, dummy4, dummy5, step); + update_error(param, values.at(idx), errors.at(idx), + mean_error, sigma_mean_error, dummy3, dummy4, dummy5, step); + + value_hists[idx]->SetBinContent(i+1,mean_value); + value_hists[idx]->SetBinError(i+1,sigma_mean_value); + error_hists[idx]->SetBinContent(i+1,mean_error); + error_hists[idx]->SetBinError(i+1,sigma_mean_error); + + mean_values[idx][i] = mean_value;//for the output tables + sigma_mean_values[idx][i] = sigma_mean_value;//for the output tables + mean_errors[idx][i] = mean_error; + sigma_mean_errors[idx][i] = sigma_mean_error; + } + } + start_param += params.at(j)->nparameters(); + } + + //save tree results + int param_idx = 0; + output->cd(); + start_param = 0; + for (unsigned int j = 0; j < params.size(); j++){//this gives nice output + for (unsigned int l = 0; l < params.at(j)->nparameters(); l++){ + unsigned int idx = start_param+l; + parameter* param = params.at(j)->get_parameter(l); + if (param->get_step_size() != 0.0){ + TTree* t = trees.at(param_idx); + for (unsigned int k=0; kget_start_value(); + migrad = return_values.at(k) % 100; + status_cov = return_values.at(k) / 100; + t->Fill(); + } + param_idx++; + } + } + start_param += params.at(j)->nparameters(); + } + } + //save output trees + for (unsigned int j = 0; j < trees.size(); j++){ + trees.at(j)->Write(); + } + + //summary output + myFile << "Parameter scan results: values\\\\" << std::endl; + myFile << "\\begin{tabular}{|c|"; + for (unsigned int i=0; i<=nsteps; i++){ + myFile << "c"; + } + myFile << "|}\\hline" << std::endl; + myFile << "$" << param_varied->get_description() << "$"; + for (unsigned int i=0; i<=nsteps; i++){ + double param_value = double(i)*(max - min)/(nsteps) + min; + myFile << " & " << std::setprecision(2) << param_value; + } + myFile << "\\\\ \\hline" << std::endl; + + start_param = 0; + for (unsigned int i=0; i < params.size(); i++){ + for (unsigned int j=0; j < params.at(i)->nparameters(); j++){ + unsigned int idx = start_param+j; + if (params.at(i)->get_parameter(j)->get_step_size() != 0.0){ + myFile << "$" << params.at(i)->get_parameter(j)->get_description() << "$"; + for (unsigned int k=0; k <= nsteps; k++){ + myFile << " & $" << std::setprecision(2) + << mean_values[idx][k] << " \\pm " + //<< mean_errors[i][j] + << sigma_mean_values[idx][k] + << "$"; + } + myFile << "\\\\" << std::endl; + } + } + start_param += params.at(i)->nparameters(); + } + myFile << "\\hline \\end{tabular}" << std::endl; + + myFile << "Parameter scan results: errors\\\\" << std::endl; + myFile << "\\begin{tabular}{|c|"; + for (unsigned int i=0; i<=nsteps; i++){ + myFile << "c"; + } + myFile << "|}\\hline" << std::endl; + myFile << "$" << param_varied->get_description() << "$"; + for (unsigned int i=0; i<=nsteps; i++){ + double param_value = double(i)*(max - min)/(nsteps) + min; + myFile << " & " << std::setprecision(2) << param_value; + } + myFile << "\\\\ \\hline" << std::endl; + + start_param = 0; + for (unsigned int i=0; i < params.size(); i++){ + for (unsigned int j=0; j < params.at(i)->nparameters(); j++){ + unsigned int idx = start_param+j; + if (params.at(i)->get_parameter(j)->get_step_size() != 0.0){ + myFile << "$" << params.at(i)->get_parameter(j)->get_description() << "$"; + for (unsigned int k=0; k <= nsteps; k++){ + myFile << " & $" << std::setprecision(2) + << mean_errors[idx][k] << " \\pm " + << sigma_mean_errors[idx][k] << "$"; + } + myFile << "\\\\" << std::endl; + } + } + start_param += params.at(i)->nparameters(); + } + myFile << "\\hline \\end{tabular}" << std::endl; + + start_param = 0; + for (unsigned int i=0; i < params.size(); i++){ + for (unsigned int j=0; j < params.at(i)->nparameters(); j++){ + unsigned int idx = start_param+j; + //print result histos + if (params.at(i)->get_parameter(j)->get_step_size() != 0.0){ + output->cd(); + parameter* param = params.at(i)->get_parameter(j); + + std::string error_name = "parameter scan sigma(" + param->get_name() + ")"; + TCanvas *c1 = new TCanvas(error_name.c_str(), error_name.c_str(), 1600, 1200); + c1->cd(); + error_hists[idx]->Draw("e"); + if (opts->write_eps) c1->Print(get_param_scan_path(param->get_name(),true).c_str(), "eps"); + c1->Write(); + delete error_hists[idx]; + delete c1; + + std::string value_name = "Parameter scan "+param->get_name(); + TCanvas *c2 = new TCanvas(value_name.c_str(), value_name.c_str(), 1600, 1200); + c2->cd(); + value_hists[idx]->Draw("e"); + if (opts->write_eps) c2->Print(get_param_scan_path(param->get_name(),false).c_str(), "eps"); + c2->Write(); + delete value_hists[idx]; + delete c2; + + //TODO add pulls + } + } + start_param += params.at(i)->nparameters(); + } + } + else{ + spdlog::error("Parameter "+param_name+" not found."); + assert(0); + } +} + diff --git a/Code/FCNCFitter/sources/Params/parameterscan.hh b/Code/FCNCFitter/sources/Params/parameterscan.hh new file mode 100644 index 0000000..f994304 --- /dev/null +++ b/Code/FCNCFitter/sources/Params/parameterscan.hh @@ -0,0 +1,70 @@ +/** + * @file parameterscan.hh + * @author Christoph Langenbruch, Renata Kopecna + * @date 2009-03-18 + * + */ + +#ifndef PARAMETERSCAN_H +#define PARAMETERSCAN_H + +#include +#include +#include + +//TODO: move to /Run/! + +namespace fcnc { + class options; + class generator; + class parameters; + class pdf; + +///class to perform repeated fits while changing a parameter value, e.g. background fraction +class parameterscan: public multifit { +private: + ///common parameters in different parameter sets + std::vector< std::string > common_params; +public: + ///constructor + parameterscan(options* o); + /** + * perform a parameter scan + * @param param_name the name of the parameter which will be varied in the scan + * @param min the start value for the varied parameter + * @param max the stop value for the varied parameter + * @param nsteps the number of steps in which to vary the parameter + * @param nevents the number of events used per fit of the toy data + * @param reruns the number of repeats for a single value of the parameter + * @param prob pointer to the pdf to use in the likelihood fit + * @param params pointer to parameterset to use in the likelihood fit + * @param gen pointer to the toy data generator to use + * @param only_float_in_generation only varies the parameter in the generation, + * but fixes it in the fit. This way one can do systematic studies. + **/ + void scan(std::string param_name, double min, double max, unsigned int nsteps, unsigned int nevents, unsigned int reruns, pdf* prob, parameters* params, generator* gen, bool only_float_in_generation=false); + /** + * perform a parameter scan + * @param param_name the name of the parameter which will be varied in the scan + * @param min the start value for the varied parameter + * @param max the stop value for the varied parameter + * @param nsteps the number of steps in which to vary the parameter + * @param nevents the number of events used per fit of the toy data + * @param reruns the number of repeats for a single value of the parameter + * @param prob pointer to the pdf to use in the likelihood fit + * @param params pointer to parameterset to use in the likelihood fit + * @param gen pointer to the toy data generator to use + * @param only_float_in_generation only varies the parameter in the generation, + * but fixes it in the fit. This way one can do systematic studies. + **/ + void scan(std::string param_name, double min, double max, unsigned int nsteps, std::vector nevents, unsigned int reruns, std::vector pdfs, std::vector params, std::vector gens, bool only_float_in_generation=false); + ///set common parameters + void set_common_parameters(std::vector common_pars) { + common_params = common_pars; + }; +}; + +} + + +#endif diff --git a/Code/FCNCFitter/sources/Params/values.hh b/Code/FCNCFitter/sources/Params/values.hh new file mode 100644 index 0000000..f00146e --- /dev/null +++ b/Code/FCNCFitter/sources/Params/values.hh @@ -0,0 +1,58 @@ +/** + * @file values.hh + * @author David Gerick + * @date 2018-04-03 + * + * This file contains the values that may be shared between functions! + * + */ + +#ifndef VALUES_H +#define VALUES_H + +namespace fcnc { + +///class that stores the options used in the analysis +class values { +public: + + ///resulting chi2 of angular acceptance correction parametrization + double angacccorr_chi2; + ///number of degrees of freedom in chi2 test of angular acceptance correction + int angacccorr_ndof; + + ///chi2 calculated from 4 * 1D projections in angular acceptance corrections + double chi2_4_1D; + double chi2_4_1D_ctk; + double chi2_4_1D_ctl; + double chi2_4_1D_phi; + double chi2_4_1D_q2; + ///number of degrees of freedom in 4 * 1D projections + int ndof_4_1D; + int ndof_4_1D_ctk; + int ndof_4_1D_ctl; + int ndof_4_1D_phi; + int ndof_4_1D_q2; + + //constructor: + values(): + angacccorr_chi2(1.0), + angacccorr_ndof(1), + chi2_4_1D(1.0), + chi2_4_1D_ctk(1.0), + chi2_4_1D_ctl(1.0), + chi2_4_1D_phi(1.0), + chi2_4_1D_q2(1.0), + ndof_4_1D(1), + ndof_4_1D_ctk(1), + ndof_4_1D_ctl(1), + ndof_4_1D_phi(1), + ndof_4_1D_q2(1) + { + }; + +}; + +} + +#endif diff --git a/Code/FCNCFitter/sources/Run/angularcorr.cc b/Code/FCNCFitter/sources/Run/angularcorr.cc new file mode 100644 index 0000000..12ee21d --- /dev/null +++ b/Code/FCNCFitter/sources/Run/angularcorr.cc @@ -0,0 +1,908 @@ +//Renata Kopecna + +#include +#include // std::istringstream + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +//------------------------------- +// scan angular acceptance max. order of legendre +//------------------------------- + + +void logYears(std::vectoryears, std::vector< std::vector > eves, int loadedSize){ + + for(UInt_t y = 0; y < years.size(); y++){ + spdlog::info("Events in run {0:d} : {1:d}", years.at(y) , eves.at(y).size()); + } + spdlog::info( "------------------------"); + spdlog::info("Events in total: {0:d}", loadedSize); + return; +} + +void logYears(int run, int evtsSize, int loadedSize){ + spdlog::info("Events in run {0:d} : {1:d}", run, evtsSize); + spdlog::info("------------------------"); + spdlog::info("Events in total : {0:d}", loadedSize); +} + +//------------------------------- +// scan angular acceptance +//------------------------------- + +std::vector get_scan_low(bool quickTest, bool only_1D_chi2){ + //q2, thetak, thetal, phi + if (quickTest) return {6,5,5,2};//use small range for quick tests on format or algorithms: + if (only_1D_chi2) return {2,2,2,2};//use huge range for quick tests of 1D chi2: + return {6,5,2,1}; +} + +std::vector get_scan_high(bool quickTest, bool only_1D_chi2){ + //q2, thetak, thetal, phi + if (quickTest) return {6,10,5,2};//use small range for quick tests on format or algorithms: + if (only_1D_chi2) return {9,9,9,9};//use huge range for quick tests of 1D chi2: + return {8,7,4,3}; +} + +std::vector get_scan_range(std::vector scan_low, std::vector scan_high){ + std::vector scan_range; + for_indexed(auto item: scan_low){ + //If high >= low, raise an exception + assert(scan_high.at(i) >= item); + scan_range.push_back(scan_high.at(i) -item + 1); + } + return scan_range; +} + +int sanityCheck(std::vectorevents, fcnc::options opts, bool PHSP, int bin, bool norm){ + //events: input events + //opts: general options + //PHSP: using PHSP or sigMC? + //bin: # of bin in q2, when all, set to -1 + //norm: Normalize the plots? + + //Create parameter set + fcnc::bu2kstarmumu_parameters * leParameters = new fcnc::bu2kstarmumu_parameters(&opts); + //create PDF + fcnc::bu2kstarmumu_pdf * lePDF = new fcnc::bu2kstarmumu_pdf(&opts, leParameters); + std::vector *leEvents= new std::vector; + + opts.weighted_fit = true; //Jesus efin christ + int nAngleBins = 20; + + for(auto meas: events){ + leEvents->push_back(meas); + } + leParameters->use_default(); + leParameters->take_current_as_start(); + + lePDF->load_coeffs_eff_phsp_4d(); + opts.multiply_eff = true; + opts.weighted_fit = true; + lePDF->update_cached_efficiencies(leParameters, leEvents); + lePDF->update_cached_normalization(leParameters); + + //check the distributions of weighted events + TH1D * ctl = new TH1D ("h_ctl", "h_ctl", nAngleBins, CTL_MIN, CTL_MAX); + TH1D * ctk = new TH1D ("h_ctk", "h_ctk", nAngleBins, CTK_MIN, CTK_MAX); + TH1D * phi = new TH1D ("h_phi", "h_phi", nAngleBins, PHI_MIN, PHI_MAX); + TH1D * q2 = new TH1D ("h_q2" , "h_q2" , nAngleBins, Q2_MIN_RANGE, Q2_MAX_RANGE); + TH2D * ctkq2 = new TH2D ("h_ctkq2" , "h_ctkq2", nAngleBins, CTK_MIN, CTK_MAX, nAngleBins, Q2_MIN_RANGE, Q2_MAX_RANGE); + TH2D * ctlq2 = new TH2D ("h_ctlq2" , "h_ctlq2", nAngleBins, CTL_MIN, CTL_MAX, nAngleBins, Q2_MIN_RANGE, Q2_MAX_RANGE); + TH2D * phiq2 = new TH2D ("h_phiq2" , "h_phiq2", nAngleBins, PHI_MIN, PHI_MAX, nAngleBins, Q2_MIN_RANGE, Q2_MAX_RANGE); + TH1D * ctl_noW = new TH1D ("ctl_noW", "ctl_noW", nAngleBins, CTL_MIN, CTL_MAX); + TH1D * ctk_noW = new TH1D ("ctk_noW", "ctk_noW", nAngleBins, CTK_MIN, CTK_MAX); + TH1D * phi_noW = new TH1D ("phi_noW", "phi_noW", nAngleBins, PHI_MIN, PHI_MAX); + TH1D * q2_noW = new TH1D ("q2_noW" , "q2_noW" , nAngleBins, Q2_MIN_RANGE, Q2_MAX_RANGE); + TH1D* hweight = new TH1D("hweight", ";w;", 100, 0.0, 1.0/EFF_CUTOFF); + + + for(auto &meas: *leEvents){ + if(meas.weight < 0.0){ + spdlog::warn("negative weight event:\tm={0:f} \t\tctl={1:f} \tctk={2:f}\tphi={3:f} \tweight={4:f}", meas.m, meas.costhetal, meas.costhetak, meas.phi, meas.weight); + } + ctl->Fill(meas.costhetal, meas.weight); + ctk->Fill(meas.costhetak, meas.weight); + phi->Fill(meas.phi, meas.weight); + q2 ->Fill(meas.q2, meas.weight); + ctkq2->Fill(meas.costhetak, meas.q2, meas.weight); + ctlq2->Fill(meas.costhetal, meas.q2, meas.weight); + phiq2->Fill(meas.phi, meas.q2, meas.weight); + + ctl_noW->Fill(meas.costhetal); + ctk_noW->Fill(meas.costhetak); + phi_noW->Fill(meas.phi); + q2_noW ->Fill(meas.q2); + if (meas.weight > 30){ + spdlog::warn("Event with very high weight {0:f} found!", meas.weight); + print_event(meas); + } + + hweight->Fill(meas.weight); + + } + //phi->GetYaxis()->SetRangeUser(5000,7000); + + + int tagNumber =1*opts.eff_order_q2+ + 100*opts.eff_order_costhetak+ + 10000* opts.eff_order_costhetal+ + 1000000*opts.eff_order_phi ; + + + //Normalize to one + + if (norm){ + ctl->Scale(nAngleBins/ctl->Integral()); + ctk->Scale(nAngleBins/ctk->Integral()); + phi->Scale(nAngleBins/phi->Integral()); + q2->Scale(nAngleBins/q2->Integral()); + ctkq2->Scale(nAngleBins*nAngleBins/ctkq2->Integral()); + ctlq2->Scale(nAngleBins*nAngleBins/ctlq2->Integral()); + phiq2->Scale(nAngleBins*nAngleBins/phiq2->Integral()); + } + + std::string subfolder = get_angCorrPath(false); + std::string tag = (PHSP ? "" : "MC_") + (bin==-1 ? "" : "_bin"+std::to_string(bin)) + tag_Run(opts.run) +"_" + std::to_string(tagNumber); + if (PHSP){ + //Get the fitted lines + TF1 *fitLine_ctl = fitStraightLine(ctl, "fitLine_ctl", CTL_MIN, CTL_MAX); + TF1 *fitLine_ctk = fitStraightLine(ctk, "fitLine_ctk", CTK_MIN, CTK_MAX); + TF1 *fitLine_phi = fitStraightLine(phi, "fitLine_phi", PHI_MIN, PHI_MAX); + TF1 *fitLine_q2 = fitStraightLine(q2, "fitLine_q2", Q2_MIN_RANGE, Q2_MAX_RANGE); + //and plot them + plotAndSaveWithLine(ctl,fitLine_ctl,"c_ctl",subfolder+"debug_ctl_"+tag,"eps"); + plotAndSaveWithLine(ctk,fitLine_ctk,"c_ctk",subfolder+"debug_ctk_"+tag,"eps"); + plotAndSaveWithLine(phi,fitLine_phi,"c_phi",subfolder+"debug_phi_"+tag,"eps"); + plotAndSaveWithLine(q2, fitLine_q2, "c_q2" ,subfolder+"debug_q2_"+tag, "eps"); + } + else{ + plotAndSave(ctl,"c_ctl",subfolder+"debug_ctl_"+tag,"eps"); + plotAndSave(ctk,"c_ctk",subfolder+"debug_ctk_"+tag,"eps"); + plotAndSave(phi,"c_phi",subfolder+"debug_phi_"+tag,"eps"); + plotAndSave(q2, "c_q2" ,subfolder+"debug_q2_"+tag, "eps"); + } + plotAndSave(ctkq2, "c_ctkq2" ,subfolder+"debug_ctkq2_"+tag, "eps"); + plotAndSave(ctlq2, "c_ctlq2" ,subfolder+"debug_ctlq2_"+tag, "eps"); + plotAndSave(phiq2, "c_phiq2" ,subfolder+"debug_phiq2_"+tag, "eps"); + plotAndSave(hweight, "c_weight" ,subfolder+"debug_weights_"+tag, "eps"); + + std::string outputPath = subfolder + "debug_angles"+ tag + ".root"; + TFile *output = new TFile(outputPath.c_str(),"RECREATE"); + output->cd(); + ctl->Write("",TObject::kWriteDelete); + ctk->Write("",TObject::kWriteDelete); + phi->Write("",TObject::kWriteDelete); + q2->Write("",TObject::kWriteDelete); + ctkq2->Write("",TObject::kWriteDelete); + ctlq2->Write("",TObject::kWriteDelete); + phiq2->Write("",TObject::kWriteDelete); + hweight->Write("",TObject::kWriteDelete); + output->Close(); + + + if (norm){ //save only when the option of normalization is on + plotAndSave(ctl_noW,"c_ctl_noW",subfolder+"debug_ctl_noW_"+tag,"eps"); + plotAndSave(ctk_noW,"c_ctk_noW",subfolder+"debug_ctk_noW_"+tag,"eps"); + plotAndSave(phi_noW,"c_phi_noW",subfolder+"debug_phi_noW_"+tag,"eps"); + plotAndSave(q2_noW, "c_q2_noW" ,subfolder+"debug_q2_noW_"+tag, "eps"); + } + + delete ctl; + delete ctk; + delete phi; + delete q2; + delete ctlq2; + delete ctkq2; + delete phiq2; + delete ctl_noW; + delete ctk_noW; + delete phi_noW; + delete q2_noW; + return 1; +} + +int sanityCheck_MC(fcnc::options opts){ + + spdlog::info("Checking MC distribution after correction"); + + //load MC + std::vector events; + + if (opts.run == 1){ + events = fcnc::load_events(get_theFCNCpath(1,1), "Events", -1); + } + else if (opts.run == 2){ + events = fcnc::load_events(get_theFCNCpath(1,2), "Events", -1); + } + else { + std::vector events1 = fcnc::load_events(get_theFCNCpath(1,1), "Events", -1); + std::vector events2 = fcnc::load_events(get_theFCNCpath(1,2), "Events", -1); + events = {merge_two_evtVecs(events1,events2)}; + } + for (unsigned int b = 0; b < opts.get_nQ2bins(); b++){ + std::vector filtered_events; + for (auto &evt: events){ + + if (evt.costhetal > opts.ctl_max) continue; + if (evt.costhetal < opts.ctl_min) continue; + if (evt.costhetak > opts.ctk_max) continue; + if (evt.costhetak < opts.ctk_min) continue; + if (evt.phi > opts.phi_max) continue; + if (evt.phi < opts.phi_min) continue; + if (evt.q2 > opts.TheQ2binsmax[b]) continue; + if (evt.q2 < opts.TheQ2binsmin[b]) continue; + filtered_events.push_back(evt); + } + sanityCheck(filtered_events, opts, false, b, false); + } + + return 0; +} +std::vector< std::vector > select_event(fcnc::options opts,std::vector years){ + //Load and check size of events in both runs + + std::vectorevents[2] = { + fcnc::load_events(get_theFCNCpath(3,1), "Events", -1), + fcnc::load_events(get_theFCNCpath(3,2), "Events", -1) + }; + assert(events[0].size()); + assert(events[1].size()); + spdlog::debug("Load angular corrections per two years?\t{0:b}",opts.angacccorrpertwoyears); + spdlog::debug("Load angular corrections for both runs?\t{0:b}",opts.angacccorrbothruns); + + std::vector loaded_events; + if (opts.angacccorrbothruns) loaded_events = merge_two_evtVecs(events[0], events[1]); + else if (opts.angacccorrpertwoyears) loaded_events = events[1]; + else loaded_events = events[opts.run-1]; + + std::vector< std::vector > eves; + + if (opts.angacccorrperyear || opts.angacccorrpertwoyears){ + spdlog::debug("Seperate sample into {0:d} sub-samples. One per year!",years.size()); + //create indidividual vectors for every year + std::vectoreve_year(years.size()); + //fill events into the correct vector + for(auto ev: loaded_events){ + for(uint y = 0; y < years.size(); y++){ + if(ev.year == years.at(y)) eves.at(y).push_back(ev); + } + } + + //print the corresponding numbers in every vector: + logYears(years, eves, loaded_events.size()); + } + else eves.push_back(loaded_events); + + //If the correction is done by two years only, merge the two vectors into one + if (opts.angacccorrpertwoyears){ + eves = {merge_two_evtVecs(eves.at(0),eves.at(1))}; + spdlog::debug("Size of the final vector is {0:d}",eves.size()); + spdlog::debug("Size of the final vector at(0) is {0:d}",eves.at(0).size()); + } + + return eves; + +} + +int get_flat_Q2_weights(){ + + spdlog::info("Start preparing weights for flat-flat PHSP."); + std::string PHSPpath = getSelectedTuplePath(4,2017,2); + + TFile *output = new TFile(CONFIG_PHSP_WEIGHT.c_str(),"RECREATE"); + output->cd(); + spdlog::debug("Created " + std::string(output->GetPath())); + TH1D *flatq2weights = new TH1D("flatq2weights","flatq2weights",100,Q2_MIN_RANGE,Q2_MAX_RANGE); + TH1D *originalQ2 = new TH1D("originalQ2","originalQ2",100,Q2_MIN_RANGE,Q2_MAX_RANGE); + + + spdlog::debug("Reading tree DecayTree from " + PHSPpath); + TChain *tree = new TChain("DecayTree"); + tree->Add(PHSPpath.c_str()); + spdlog::debug("Events in tree DecayTree:\t{0:d}", tree->GetEntries()); + + double Q2; + tree->SetBranchStatus("Q2",1); + tree->SetBranchAddress("Q2",&Q2); + + for (int e = 0; eGetEntries(); e++){ + //spdlog::trace("Q2 for event {0:d}:\t{1:f}",e,Q2); + tree->GetEntry(e); + originalQ2->Fill(Q2/1e6); //Fill q2 in GeV instead of MeV + } + + + for (int b =1; b <= originalQ2->GetNbinsX(); b++){ + flatq2weights->SetBinContent(b,1.0/originalQ2->GetBinContent(b)); //Create the weights + } + flatq2weights->Scale(flatq2weights->GetNbinsX()/ flatq2weights->Integral()); //Normalize the weights + output->cd(); + originalQ2->Write("",TObject::kWriteDelete); + flatq2weights->Write("",TObject::kWriteDelete); + output->Close(); + spdlog::info("Done preparing weights for flat-flat PHSP."); + + return 0; +} + +int scan_max_order_angular_ccorrection(fcnc::options opts, + bool assumePhiEven, + bool quickTest, bool test_4times1D, + bool checkSignificance, bool runMinuit, + bool checkFactorization, bool do3Dmoments){ + get_flat_Q2_weights(); + //only use chi2 from 1D projections + opts.only_4_1D_chi2 = test_4times1D; + //prevent any plot printing for the scan + opts.write_eps = quickTest || test_4times1D; + //Set year/run options + set_ang_year_options(opts); + + //define the range to scan through the parameters: + //format: {q2, theta_K, theta_L, phi} + std::vector scan_low = get_scan_low(quickTest, opts.only_4_1D_chi2); + std::vector scan_high = get_scan_high(quickTest, opts.only_4_1D_chi2); + std::vector scan_range = get_scan_range(scan_low, scan_high); + + spdlog::debug("Scan range:" + convert_vector_to_string(scan_range)); + + //construct results in 2D histogram: + const UInt_t nBinsX = scan_range.at(1)*scan_range.at(2); // cos(theta_K) and cos(theta_L) + const UInt_t nBinsY = scan_range.at(0)*scan_range.at(3); // q^2 and phi + + //load phase-space MC events + std::vector years = get_years(opts.run,false, false); + std::vector< std::vector > eves = select_event(opts, years); + + //object for exporting values from the parametrization process: + fcnc::values valu; + spdlog::debug("Eves vector size: {0:d}", eves.size()); + + for_indexed(auto evts: eves){ + + if(opts.angacccorrperyear ){ + opts.year = years.at(i); + spdlog::debug("[YEAR]\t\t{0:d}", opts.year); + } + else opts.year = -1; + + std::string sample_suffix; + if (opts.angacccorrbothruns) sample_suffix = "Run1and2"; + else if(opts.angacccorrperyear)sample_suffix = std::to_string(opts.year); + else sample_suffix = "Run"+std::to_string(opts.run); + + TH2D * chi2histo = new TH2D(("ScanLegendreOrders_Chi2result_"+sample_suffix).c_str(), + ("#chi^{2} scan of max. order of polynoms ("+sample_suffix+");#bf{#theta_{K}} - #theta_{L};#bf{q^{2}} - #phi").c_str(), + nBinsX, -0.5, nBinsX - 0.5, + nBinsY, -0.5, nBinsY - 0.5); + + TH2D * pvaluehisto = new TH2D(("ScanLegendreOrders_Pvalueresult_"+sample_suffix).c_str(), + ("p-value scan of max. order of polynoms ("+sample_suffix+");#bf{#theta_{K}} - #theta_{L};#bf{q^{2}} - #phi").c_str(), + nBinsX, -0.5, nBinsX - 0.5, + nBinsY, -0.5, nBinsY - 0.5); + + + //label the axese + labelAngularScan(scan_low, scan_range, chi2histo); + labelAngularScan(scan_low, scan_range, pvaluehisto); + + /* + //individual histograms for each 1D projection: + TH2D * dist_4_1D[4]; + std::string svar[4] = {"ctk", "ctl", "phi", "q2"}; + + if(opts.only_4_1D_chi2){ + //was only needed to proof that all four 1D projections are indipendent. + //keep the code for possible re-checks: + for(int h = 0; h < 4; h++){ + dist_4_1D[h] = new TH2D(("ScanLegendreOrders_Chi2result_"+svar[h]+"_"+sample_suffix).c_str(), + (svar[h]+": #chi^{2} scan of max. order of polynoms ("+sample_suffix+");#bf{#theta_{K}} - #theta_{L};#bf{q^{2}} - #phi").c_str(), + nBinsX, -0.5, nBinsX - 0.5, + nBinsY, -0.5, nBinsY - 0.5); + //label the x-axis + labelAngularScan(scan_low, scan_range, dist_4_1D[h]); + } + } + */ + + + + //determine max scan range: + int range_low = *min_element(std::begin(scan_low),std::end(scan_low)); + //for_indexed(auto item: scan_low) if(scan_low[c] < range_low)range_low = scan_low[c]; + int range_high = *max_element(std::begin(scan_high),std::end(scan_high)); + + //get the histogram for all four varialbes: + TH2D * chi2_4_1D = new TH2D(("Scan_Chi2result_"+sample_suffix).c_str(), + ("#chi^{2} scan of max. order of polynoms ("+sample_suffix+");max. order;variable").c_str(), + range_high - range_low + 1, range_low - 0.5, range_high + 0.5, + 4, -0.5, 3.5); + //label the x-axis + for(int b = range_low; b <= range_high; b++){ + chi2_4_1D->GetXaxis()->SetBinLabel(b - range_low + 1, (std::to_string(b)).c_str()); + } + //label the y-axis + chi2_4_1D->GetYaxis()->SetBinLabel(1, LATEX_Q2_CH()); + chi2_4_1D->GetYaxis()->SetBinLabel(2, LATEX_TK_CH()); + chi2_4_1D->GetYaxis()->SetBinLabel(3, LATEX_TL_CH()); + chi2_4_1D->GetYaxis()->SetBinLabel(4, LATEX_PHI_CH()); + + if(opts.only_4_1D_chi2){ //Screams in python + for(int i = 0; i < 4; i++){ + for(int j = scan_low.at(i); j <= scan_high.at(i); j++){ + + //set to max order to current scan value and all others to min value + if(i == 0)opts.eff_order_q2 = j; + else opts.eff_order_q2 = scan_low.at(0); + if(i == 1)opts.eff_order_costhetak = j; + else opts.eff_order_costhetak = scan_low.at(1); + if(i == 2)opts.eff_order_costhetal = j; + else opts.eff_order_costhetal = scan_low.at(2); + if(i == 3)opts.eff_order_phi = j; + else opts.eff_order_phi = scan_low.at(3); + + spdlog::debug("[SCAN]\t\tq2 {0:d} \tcos(t_K) {1:d} \tcos(t_L) {2:d} \tphi {3:d}", opts.eff_order_q2, opts.eff_order_costhetak, opts.eff_order_costhetal , opts.eff_order_phi); + + //All Unbiased parameters! + fcnc::bu2kstarmumu_parameters params(&opts); + //pdf + fcnc::bu2kstarmumu_pdf prob(&opts, ¶ms); + + //prob.parametrize_eff_phsp(selected); + int tagNumber = i*10+j; + spdlog::debug("Tag number:\t{0:d}", tagNumber); + prob.parametrize_eff_phsp_4d(evts, &valu,tagNumber, assumePhiEven, checkSignificance, runMinuit, checkFactorization, do3Dmoments); + //Tag for all possible combinations when testing + + //save the one chi2 value: + double chi2 = 0.; + if(i == 0) chi2 = valu.chi2_4_1D_q2; + else if(i == 1)chi2 = valu.chi2_4_1D_ctk; + else if(i == 2)chi2 = valu.chi2_4_1D_ctl; + else chi2 = valu.chi2_4_1D_phi; + int ndof = 1; + if(i == 0) ndof = valu.ndof_4_1D_q2; + else if(i == 1)ndof = valu.ndof_4_1D_ctl; + else if(i == 2)ndof = valu.ndof_4_1D_ctl; + else ndof = valu.ndof_4_1D_phi; + if(chi2 / ndof < 2.) chi2_4_1D->SetBinContent(j - range_low + 1, i + 1, chi2 / ndof); + } + } + } + else{ + for(int qq = 0; qq < scan_range.at(0); qq++){ + for(int tk = 0; tk < scan_range.at(1); tk++){ + for(int tl = 0; tl < scan_range.at(2); tl++){ + for(int fi = 0; fi < scan_range.at(3); fi++){ + + //change max order of polynoms according to the scan: + opts.eff_order_q2 = qq+scan_low.at(0); + opts.eff_order_costhetak = tk+scan_low.at(1); + opts.eff_order_costhetal = tl+scan_low.at(2); + opts.eff_order_phi = fi+scan_low.at(3); + + int tagNumber = 1*opts.eff_order_q2+ + 10*opts.eff_order_costhetak+ + 100* opts.eff_order_costhetal+ + 1000*opts.eff_order_phi ; + //This works fine assuming all the orders are <10! + + spdlog::info("[SCAN]\t\tq2 {0:d} \tcos(t_K) {1:d} \tcos(t_L) {2:d} \tphi {3:d}", opts.eff_order_q2, opts.eff_order_costhetak, opts.eff_order_costhetal , opts.eff_order_phi); + spdlog::debug("Tag number:\t{0:d}", tagNumber); + + //All Unbiased parameters! + fcnc::bu2kstarmumu_parameters params(&opts); + //pdf + fcnc::bu2kstarmumu_pdf prob(&opts, ¶ms); + + //prob.parametrize_eff_phsp(selected); + prob.parametrize_eff_phsp_4d(evts, &valu, tagNumber, assumePhiEven, checkSignificance, runMinuit, checkFactorization, do3Dmoments); + + double chi2 = valu.angacccorr_chi2; + int ndof = valu.angacccorr_ndof; + + chi2histo->SetBinContent(tk * scan_range.at(2) + tl + 1, + qq * scan_range.at(3) + fi + 1, chi2 / ndof); + + pvaluehisto->SetBinContent(tk * scan_range.at(2) + tl + 1, + qq * scan_range.at(3) + fi + 1, + TMath::Prob(chi2, ndof)); + //P(chi2,ndof) represents the probability that the observed Chi-squared + //for a correct model should be less than the value chi2. + //The returned probability corresponds to 1-P(chi2,ndof), + //which denotes the probability that an observed Chi-squared exceeds + //the value chi2 by chance, even for a correct model. + } + } + } + }//loop over max. orders + } + + //save the histogram with chi2/ndof output + TCanvas * cChi2Ndof = new TCanvas(("cChi2Ndof_"+sample_suffix).c_str(), ("cChi2Ndof_"+sample_suffix).c_str()); + TCanvas * cPvalue = new TCanvas(("cPvalue_"+sample_suffix).c_str(), ("cPvalue_"+sample_suffix).c_str()); + + gStyle->SetPaintTextFormat("1.3f"); + std::string plotName = "plots/angular/test/ScanChi2MaxOrderPolynom" + sample_suffix+std::string(quickTest ? "_quickTest" : ""); + if(opts.only_4_1D_chi2){ + replace(plotName,"Polynom","Polynom_4_1D_"); + cChi2Ndof->cd(); + cChi2Ndof->SetLogz(false); + chi2_4_1D->GetZaxis()->SetRangeUser(-1.0,2.5); + chi2_4_1D->Draw("TEXTCOLZ"); + cChi2Ndof->SaveAs((plotName+".eps").c_str(), "eps"); + } + else{ + cChi2Ndof->cd(); + chi2histo->GetZaxis()->SetRangeUser(0.98, 1.05); + chi2histo->Draw("TEXTCOLZ"); + cChi2Ndof->SaveAs((plotName + ".eps").c_str(), "eps"); + cChi2Ndof->SetLogz(); + cChi2Ndof->SaveAs((plotName+"_log.eps").c_str(), "eps"); + + replace(plotName,"Chi2Max","PvalueMax"); + cPvalue->cd(); + //pvaluehisto->GetZaxis()->SetRangeUser(1e-8, 2.5e-2); + pvaluehisto->Draw("TEXTCOLZ"); + + cPvalue->SaveAs((plotName+".eps").c_str(), "eps"); + cPvalue->SetLogz(); + cPvalue->SaveAs((plotName+"_log.eps").c_str(), "eps"); + + + replace(plotName,"PvalueMax","Max"); + TFile * f = new TFile((plotName+".root").c_str(), "UPDATE"); + f->cd(); + chi2histo ->Write("", TObject::kWriteDelete); + pvaluehisto->Write("", TObject::kWriteDelete); + f->Close(); + } + + delete cChi2Ndof; + delete cPvalue; + + delete chi2histo; + delete pvaluehisto; + + } + + //end program after scan + return 0; + +} + +//------------------------------- +// fit angular acceptance +//------------------------------- +int get_angular_acceptance(fcnc::options opts, bool testSaving){ + + //Mostly useless here, but in case it is needed quickly get the correction to PHSP from genLvl MC + //Needed to correct for flat q2 + get_flat_Q2_weights(); + + spdlog::info("[START] Determination of angular acceptance corrections"); + //Set year/run options + set_ang_year_options(opts); + + //load phase-space MC + std::vector years = get_years(opts.run,false, false); + std::vector< std::vector > eves = select_event(opts, years); + + //object for exporting values from the parametrization process: + fcnc::values valu; + + for(UInt_t y = 0; y < (opts.angacccorrperyear ? years.size() : 1); y++){ + + opts.year = opts.angacccorrperyear ? years.at(y) : -1; + if(opts.angacccorrperyear) spdlog::debug("[YEAR]\t\t{0:d}",years.at(y)); + + //All Unbiased parameters! + fcnc::bu2kstarmumu_parameters params(&opts); + //pdf + fcnc::bu2kstarmumu_pdf prob(&opts, ¶ms); + + //prob.parametrize_eff_phsp(selected); + prob.parametrize_eff_phsp_4d(eves.at(y), &valu, 0, IS_PHI_EVEN, false, false, false, false); + + //save the coefficients to .dat file + prob.save_coeffs_eff_phsp_4d(); + + + //Plot the corrected distributions + sanityCheck(eves.at(y), opts, true, -1, true); + + //test succesfull saving by loading and checking the coefficients: + if(testSaving){ + //load the coefficients from file: + std::vectortestCoeffs; + testCoeffs = prob.read_coeffs_eff_phsp_4d(); + //check if the correct number of coeffs is saved and reloaded + assert(testCoeffs.size() == prob.coeffs_eff_4d.size()); + + //test if all coeffs are identical + for(UInt_t c = 0; c < prob.coeffs_eff_4d.size(); c++){ + if(TMath::Abs(testCoeffs.at(c) - prob.coeffs_eff_4d.at(c)) > 1.0e-14){ + spdlog::warn(" Coeff #{0:d} unequal.",c+1); + spdlog::warn(" Saved: {0:f}", prob.coeffs_eff_4d.at(c)); + spdlog::warn(" Loaded: {0:f}", testCoeffs.at(c)); + spdlog::warn(" Difference: {0:f}", testCoeffs.at(c) - prob.coeffs_eff_4d.at(c)); + } + } + } + + + npolynom npol(&opts); + assert(prob.coeffs_eff_4d.size() == npol.getSize()); + + //this can be varying parameter, or can be fixed for example to the middle of the bin + //double q2 = params->eff_q2(); + TRandom3* rnd = new TRandom3(432759); + std::vector negativeeff; + const bool testdata = false; + const bool testtoy = false; + unsigned int ntest = 100000; + if (testdata){ + std::vector dataevents = fcnc::filterResonances(fcnc::load_events( get_theFCNCpath(0, opts.run), "Events", ntest)); + ntest = 0;//dataevents.size(); + for (unsigned int l=0; l Q2_MAX_RANGE) + || (meas.m < opts.m_low || meas.m > opts.m_high) ) + continue; + + continue; + ntest++; + + double eff = 0.0; + unsigned int bin = 0; + double costhetal = meas.costhetal; + double costhetak = meas.costhetak; + double phi = meas.phi; + double q2 = meas.q2; + for (unsigned int h = 0; h < npol.q2; h++){ + for (unsigned int i = 0; i < npol.ctl; i++){ + for (unsigned int j = 0; j < npol.ctk; j++){ + for (unsigned int k = 0; k < npol.phi; k++){ + bin = npol.get_bin_in4D(h,i,j,k); + eff += prob.coeffs_eff_4d.at(bin)*pow(q2, h)*pow(costhetal, i)*pow(costhetak, j)*pow(phi, k); + } + } + } + } + if (eff < 0.0){ + meas.weight = eff; + negativeeff.push_back(meas); + } + } + } + else if (testtoy){ + for (unsigned int l=0; lRndm()*CTL_RANGE(); + double costhetak = CTK_MIN + rnd->Rndm()*CTK_RANGE(); + double phi = PHI_MIN + rnd->Rndm()*PHI_RANGE(); + double q2 = Q2_MIN_RANGE + rnd->Rndm()*Q2_RANGE_FULL(); + for (unsigned int h = 0; h < npol.q2; h++){ + for (unsigned int i = 0; i < npol.ctl; i++){ + for (unsigned int j = 0; j < npol.ctk; j++){ + for (unsigned int k = 0; k < npol.phi; k++){ + bin = npol.get_bin_in4D(h,i,j,k); + eff += prob.coeffs_eff_4d.at(bin)*pow(q2, h)*pow(costhetal, i)*pow(costhetak, j)*pow(phi, k); + } + } + } + } + if (eff < 0.0){ + fcnc::event meas; + meas.costhetal = costhetal; + meas.costhetak = costhetak; + meas.phi = phi; + meas.q2 = q2; + meas.weight = eff; + negativeeff.push_back(meas); + } + else if (eff > 3.0) spdlog::debug("LARGE {0:f} {1:f} {2:f} {3:f} {4:f}", costhetal, costhetak, phi, q2, eff); + } + } + if(testtoy || testdata){ + spdlog::info( "looping over {0:d} events"+ std::string(testtoy ? " (TOYS)" : " (DATA)"),ntest); + for (unsigned int i=0; i>>> " + std::string(opts.year == -1 ? (opts.angacccorrbothruns ? "Run1+2" : "Run"+std::to_string(opts.run)) : std::to_string(opts.year)) + " <<<< data set:"); + spdlog::debug( "Reduced chi2 of 4*1D projections:\t {0:f} ({1:f}/{2:f})", + valu.chi2_4_1D/ valu.ndof_4_1D, valu.chi2_4_1D,valu.ndof_4_1D); + spdlog::debug( "Reduced chi2 of 4*1D projections: ctk \t {0:f} ({1:f}/{2:f})", + valu.chi2_4_1D_ctk/valu.ndof_4_1D_ctk, valu.chi2_4_1D_ctk, valu.ndof_4_1D_ctk); + spdlog::debug( "Reduced chi2 of 4*1D projections: ctl\t {0:f} ({1:f}/{2:f})", + valu.chi2_4_1D_ctl/valu.ndof_4_1D_ctl, valu.chi2_4_1D_ctl, valu.ndof_4_1D_ctl); + spdlog::debug( "Reduced chi2 of 4*1D projections: phi\t {0:f} ({1:f}/{2:f})", + valu.chi2_4_1D_phi/valu.ndof_4_1D_phi, valu.chi2_4_1D_phi, valu.ndof_4_1D_phi); + spdlog::debug( "Reduced chi2 of 4*1D projections: q2\t {0:f} ({1:f}/{2:f})", + valu.chi2_4_1D_q2/valu.ndof_4_1D_q2, valu.chi2_4_1D_q2, valu.ndof_4_1D_q2 ); + } + } + + return 0; +} + + +//------------------------------- +// fit angular resolution +//------------------------------- +int get_angular_resolution(fcnc::options opts, std::vector years){ + //Don't forget to set the full ctk range when doing this! + + //create resolution histograms for all three angles (x - x_true) + const unsigned int leBins = 50; + const double leRange = 0.12; + + + spdlog::info("Determine angular resolutions from signal MC true information!"); + gROOT->SetBatch(kTRUE); + gROOT->SetStyle("Plain"); + set_gStyle(); + + assert(years.size()); + opts.reject_identical_muon_TRUEID = true; + fcnc::bu2kstarmumu_loader loader(&opts); + + double resolution[3][years.size()]; + + for_indexed(auto yr: years){ + spdlog::info("Evaluate year {0:d}", yr); + //load tuples: + std::vector MCevents = loader.read_full_tuple(yr, + getSelectedTuplePath(1, get_yearFromRun(yr), + yr), + get_inputTree_name(1), + true, false, false, -1); + + std::vector MCtrue = loader.read_full_tuple(yr, + getSelectedTuplePath(1, get_yearFromRun(yr), + yr), + get_inputTree_name(1), + true, true, false, -1); + + assert(MCevents.size() == MCtrue.size()); + + //create resolution histograms for all three angles (x - x_true) + + TCanvas * cReso = nullptr; + std::string sangle[3] = {"ctk", "ctl", "phi"}; + std::string latexangle[3] = {LATEX_CTK,LATEX_CTL,LATEX_PHI}; + + TH1D * h[3]; + for(unsigned int i = 0; i < 3; i++){ + h[i] = new TH1D(("h"+sangle[i]+"_"+std::to_string(yr)).c_str(), + (";"+latexangle[i]+" - "+latexangle[i]+"_{true};Events").c_str(), + leBins, -leRange, +leRange); + } + + //fill histograms: + for(unsigned int e = 0; e < MCevents.size(); e++){ + fcnc::event measMC = MCevents.at(e); + fcnc::event measTRUE = MCtrue.at(e); + + h[0]->Fill(measMC.costhetak - measTRUE.costhetak); + h[1]->Fill(measMC.costhetal - measTRUE.costhetal); + h[2]->Fill(measMC.phi - measTRUE.phi); + } + + spdlog::info("Entries in histograms: {0:f}", h[0]->Integral()); + + TF1 * fGauss = new TF1("theGaussian", "[0]*([2]*exp(-0.5*((x-[1])/[3])**2)+(1.-[2])*exp(-0.5*((x-[1])/[4])**2))", -leRange, +leRange); + + fGauss->SetLineStyle(kDashed); + fGauss->SetLineColor(kMagenta - 3); + + //Set init parameters differently for each variable + double initSigma[3] = {0.0125, 0.005, 0.025}; + double sigmaLowRange[3] = {0.008, 0.001, 0.01}; + double sigmaHighRange[3] = {0.020, 0.01, 0.04}; + for(int j = 0; j < 3; j++){ + fGauss->SetParameter(0, MCevents.size()); + fGauss->SetParameter(1, 0.); + fGauss->SetParameter(2, 0.5); + fGauss->SetParLimits(2, 0.0, 1.0); + //Set the init resolution extra for ctl, as it is very narrow compared to phi and ctk + + fGauss->SetParameter(3, initSigma[j]); + fGauss->SetParLimits(3, sigmaLowRange[j], sigmaHighRange[j]); + fGauss->SetParameter(4, initSigma[j]); + fGauss->SetParLimits(4, sigmaLowRange[j], sigmaHighRange[j]); + TFitResultPtr fr; + do{ + h[j]->GetListOfFunctions()->Clear(); + fr = h[j]->Fit(fGauss, "MS+Q"); + spdlog::info("Fit status = {0:d}", fr->Status()); + } while (!fr->IsValid()); + TMatrixD covmat = fr->GetCovarianceMatrix(); + if (spdlog::default_logger_raw()->level()==spdlog::level::trace) covmat.Print(); + + double rel_frac = fGauss->GetParameter(2); + double drel_frac = fGauss->GetParError(2); + double sigma1 = fGauss->GetParameter(3); + double dsigma1 = fGauss->GetParError(3); + double sigma2 = fGauss->GetParameter(4); + double dsigma2 = fGauss->GetParError(4); + + double eff_sigma = sqrt(rel_frac*sigma1*sigma1 + (1.-rel_frac)*sigma2*sigma2); + double deff_sigma = 1./(2.*eff_sigma) * sqrt( + TMath::Power(2*rel_frac*sigma1*dsigma1, 2) + + TMath::Power(2*(1.-rel_frac)*sigma2*dsigma2, 2) + + TMath::Power((sigma1*sigma1-sigma2*sigma2)*drel_frac, 2) + + 2 * 2*rel_frac*sigma1 * 2*(1.-rel_frac)*sigma2 * covmat[3][4] + + 2 * 2*rel_frac*sigma1 * (sigma1*sigma1-sigma2*sigma2) * covmat[3][2] + + 2 * 2*(1.-rel_frac)*sigma2 * (sigma1*sigma1-sigma2*sigma2) * covmat[4][2]); + + cReso = new TCanvas((sangle[j]+"_reso_"+std::to_string(yr)).c_str(), + (sangle[j]+"_reso_"+std::to_string(yr)).c_str(), 1600, 1200); + TLatex * leg = getPrettyTex(0.06, 13); + + std::ostringstream sRMS; + sRMS << std::fixed << std::setprecision(4) << "#sigma = " << eff_sigma << " #pm " << deff_sigma; + resolution[j][i] = eff_sigma; + + cReso->SetMargin(0.125,0.05,0.115,0.05); + cReso->cd(); + h[j]->GetYaxis()->SetTitleOffset(1.15); + h[j]->GetYaxis()->SetTitleSize(0.05); + h[j]->GetYaxis()->SetLabelSize(0.05); + h[j]->GetXaxis()->SetTitleSize(0.05); + h[j]->GetXaxis()->SetLabelSize(0.05); + h[j]->Draw("E1"); + leg->DrawLatex(0.15,0.84, sRMS.str().c_str()); + leg->DrawLatex(0.7,0.88, "LHCb MC"); + leg->DrawLatex(0.7,0.82, std::to_string(yr).c_str()); + + cReso->Print(get_angResoPlot_path(sangle[j],yr,"eps").c_str(), "eps"); + cReso->SaveAs(get_angResoPlot_path(sangle[j],yr,"root").c_str()); + + delete h[j]; + } + } + + //print out resolutions: + spdlog::info("resolution: {"); + for(int i = 0; i < 3; i++){ + std::cout << "{"; + for(UInt_t y = 0; y < years.size(); y++){ + std::cout << std::fixed << std::setprecision(6) << resolution[i][y]; + if(y < years.size() - 1) + std::cout << ", "; + } + std::cout << "}" << std::endl; + } + return 0; +} diff --git a/Code/FCNCFitter/sources/Run/angularcorr.hh b/Code/FCNCFitter/sources/Run/angularcorr.hh new file mode 100644 index 0000000..19d111c --- /dev/null +++ b/Code/FCNCFitter/sources/Run/angularcorr.hh @@ -0,0 +1,21 @@ +//Renata Kopecna + +#ifndef ANGULARCORR_HH +#define ANGULARCORR_HH + +#include + +namespace fcnc { //Forward declarations + class event; + class options; +} + +int scan_max_order_angular_ccorrection(fcnc::options opts, bool assumePhiEven, bool quickTest, bool test_4times1D, bool checkSignificance, bool runMinuit, bool checkFactorization, bool do3Dmoments); + +int sanityCheck_MC(fcnc::options opts); +int sanityCheck(std::vectorevents, fcnc::options opts, bool PHSP, int bin, bool norm); +int get_angular_acceptance(fcnc::options opts, bool testSaving); + +int get_angular_resolution(fcnc::options opts, std::vector years); + +#endif // ANGULARCORR_HH diff --git a/Code/FCNCFitter/sources/Run/backgroundfit.cc b/Code/FCNCFitter/sources/Run/backgroundfit.cc new file mode 100644 index 0000000..8dcb31f --- /dev/null +++ b/Code/FCNCFitter/sources/Run/backgroundfit.cc @@ -0,0 +1,421 @@ +//Renata Kopecna + +#include + +#include +#include // std::istringstream + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +//Do the actuall background fit +int backgroundfit(fcnc::options opts, + bool fitReference, bool LowMassFit, bool HighMassFit, bool fitKpi, + bool Use2DAngularBins, basic_params params){ + //params now only used to tag nBins in the names + + //Technically, this should be simFit between Run 1 and 2, but since we need it only for the toys atm, no need for it + + gROOT->SetBatch(kTRUE); + gROOT->SetStyle("Plain"); + set_gStyle(); + + //Open texFile + std::ofstream myFile; + open_Latex_noteFile(latex_bkgFit(), myFile); + + spdlog::info("[FIT]\t\tFit only angular and m(Kpi) background"); + + + //Used to check whether the background is "correlated" between each other + //TODO: not needed atm, maybe fix later + /* 1D angular bins + 1: ctl < -0.5 + 2: -0.5 < ctl < 0.0 + 3: 0.0 < ctl < 0.5 + 4: 0.5 < ctl + 5: ctk < -0.5 + 6: -0.5 < ctk < 0.0 + 7: 0.0 < ctk < 0.5 + 8: 0.5 < ctk + */ + /* 2D angular bins + 1: ctl < 0.0 && ctk < 0.0 + 2: ctl < 0.0 && ctk > 0.0 + 3: ctl > 0.0 && ctk < 0.0 + 4: ctl > 0.0 && ctk > 0.0 + */ + + double HighBpeakCut = fitReference ? B_MASS_HIGH_BKG_REF : B_MASS_HIGH_BKG; + double LowBpeakCut = fitReference ? B_MASS_LOW_BKG_REF : B_MASS_LOW_BKG; + + assert(!(HighMassFit && LowMassFit)); + + opts.fit_full_angular_bkg = true; + + opts.only_angles = !(HighMassFit || LowMassFit); //Fit mass only if one sideband is selected + opts.only_Bmass = false; + opts.only_mkpi = false; + + opts.swave = false; + + opts.bkg_order_costhetak = 5; + opts.shift_lh = false; //keep it, it was there before + opts.weighted_fit = true; + opts.squared_hesse = true; + opts.minos_errors = false; + opts.asymptotic = false; + + opts.flat_bkg = false; + + opts.fit_mkpi = false; //set to true only later + opts.use_mkpi = false; + opts.simple_mkpi = false; //S-wave model + opts.isobar = false; //S-wave model + + //Plotting options + opts.plot_chi2 = false; + opts.plots_m_bins = 20; + opts.plots_mkpi_bins = 20; + + //load events from data tuple + std::vector>events; + std::vector run_idx; + + if (opts.run == 1 || opts.run == 12){ + std::vector tmp = fcnc::load_events(get_theFCNCpath(0,1), "Events", -1); + if (!fitReference) events.push_back(fcnc::filterResonances(tmp)); + else events.push_back(tmp); + run_idx.push_back(1); + } + if (opts.run == 2 || opts.run == 12){ + std::vector tmp = fcnc::load_events(get_theFCNCpath(0,2), "Events", -1); + if (!fitReference) events.push_back(fcnc::filterResonances(tmp)); + else events.push_back(tmp); + run_idx.push_back(2); + } + + std::vector fitresults; + + //determine number of bins: + const UInt_t nBins = opts.TheQ2binsmin.size(); + + //current fitter, plotter, parameteres and pdfs: + fcnc::fitter f(&opts); + fcnc::folder fldr(&opts); + fcnc::bu2kstarmumu_plotter thePlotter(&opts); + + fcnc::bu2kstarmumu_parameters * theParams[nBins]; + fcnc::bu2kstarmumu_pdf * theProb[nBins]; + std::vector * theEvents[nBins]; + + + for(UInt_t b = 0; b < nBins; b++){ + + theParams[b] = new fcnc::bu2kstarmumu_parameters(&opts); + theProb[b] = new fcnc::bu2kstarmumu_pdf(&opts, theParams[b]); + theEvents[b] = new std::vector(); + + //Init parameters + theParams[b]->f_sig.init_fixed(0.0); + theParams[b]->m_b.init(PDGMASS_B, HighMassFit ? HighBpeakCut : B_MASS_LOW, LowMassFit ? LowBpeakCut : B_MASS_HIGH, 0.0); + //The rest of the mass parameters can be left to default values + //They are defined in bu2kstamumu_parameters + + //Init the bkg shape + theParams[b]->init_angular_background_parameters(fitReference,0.1); + + //Init the mass bkg shape + theParams[b]->init_mass_background_parameters(nBins,b,true); + //theParams[b]->cbkgctk3.init_fixed(-2.5); + + //Select events + for_indexed(auto evts: events){ + //update weights according to sub-set for all events + opts.run = run_idx.at(i); + opts.update_efficiencies = true; + + theProb[b]->load_coeffs_eff_phsp_4d(); + theProb[b]->update_cached_normalization(theParams[b]); + theProb[b]->update_cached_efficiencies(theParams[b], &evts); + opts.update_angle_ranges(); //Update angles to get rid of events that cannot be folded + //select events + spdlog::debug("Loop over {0:d} events and select the suitable ones", evts.size()); + for(auto meas: evts){ + + if(meas.q2 < opts.TheQ2binsmin.at(b) || meas.q2 > opts.TheQ2binsmax.at(b)) continue; + if(meas.m < opts.m_low || meas.m > opts.m_high) continue; + + if(LowMassFit && meas.m > LowBpeakCut) continue; + else if(HighMassFit && meas.m < HighBpeakCut) continue; + else if(meas.m > LowBpeakCut && meas.m < HighBpeakCut) continue; + + if(meas.mkpi < opts.mkpi_min || meas.mkpi > opts.mkpi_max) continue; + + if(params.bin > 1){ + bool keep_event = true; + if(Use2DAngularBins){ + switch(params.bin){ + case 2: + if(meas.costhetal > 0.0 || meas.costhetak > 0.0) keep_event = false; + break; + case 3: + if(meas.costhetal > 0.0 || meas.costhetak < 0.0) keep_event = false; + break; + case 4: + if(meas.costhetal < 0.0 || meas.costhetak > 0.0) keep_event = false; + break; + case 5: + if(meas.costhetal < 0.0 || meas.costhetak < 0.0) keep_event = false; + break; + } + } + else{ //1D angular bins + switch(params.bin){ + case 2: + if(meas.costhetal > -0.5) keep_event = false; + break; + case 3: + if(meas.costhetal < -0.5 || meas.costhetal > 0.0) keep_event = false;; + break; + case 4: + if(meas.costhetal < 0.0 || meas.costhetal > 0.5) keep_event = false;; + break; + case 5: + if(meas.costhetal > 0.5) keep_event = false;; + break; + case 6: + if(meas.costhetak > -0.5) keep_event = false;; + break; + case 7: + if(meas.costhetak < -0.5 || meas.costhetak > 0.0) keep_event = false;; + break; + case 8: + if(meas.costhetak < 0.0 || meas.costhetak > 0.5) keep_event = false;; + break; + case 9: + if(meas.costhetak > 0.5) keep_event = false;; + break; + } + } + if(!keep_event) continue; + } + + if(!filterFldFour(&meas, &opts)) continue; + fldr.fold(&meas); + + //only one combined event vector + theEvents[b]->push_back(meas); + } + spdlog::debug("Selected {0:d} events.", theEvents[b]->size()); + } + spdlog::info("[BIN {0:d}]\tDone!",b); + }//end loop over bins + + //do not update cached efficiencies anyomre, to keep individual ones for four sub-sets + opts.update_efficiencies = false; + + //create 2D correlation plots for all angles (3) and all bins (8): 3! * 8 = 24 + const unsigned int nANGLES = 3; + + double hmin[nANGLES] = {CTL_MIN, CTK_MIN, PHI_MIN}; + double hmax[nANGLES] = {CTL_MAX, CTK_MAX, PHI_MAX}; + double corrfactor[nBins][nANGLES][nANGLES]; + const int nCorrBins = 10; + for(UInt_t b = 0; b < nBins; b++){ + spdlog::info("[START]\tStart the background 2D correlation plotting for bin #{0:d}", b); + for(UInt_t a = 0; a < nANGLES - 1; a++){ + for(UInt_t aa = a + 1; aa < nANGLES; aa++){ + std::string mainName = "bckgnd_correl_"+ANGLES[a]+"_"+ANGLES[aa]+"_q2bin"+std::to_string(b); + TCanvas * cAngCorr = new TCanvas(("c"+mainName).c_str(), + ("c"+mainName).c_str(), 1400, 1200); + cAngCorr->cd()->SetMargin(0.1,0.125,0.125,0.125); + cAngCorr->cd(); + TH2D * h = new TH2D((mainName).c_str(), + (mainName+";"+latex_angles[a]+";"+latex_angles[aa]).c_str(), + nCorrBins, hmin[a], hmax[a], nCorrBins, hmin[aa], hmax[aa]); + + for(UInt_t e = 0; e < theEvents[b]->size(); e++){ + fcnc::event meas = theEvents[b]->at(e); + double x=0.0, y=0.0; + switch(a){ //TODO: make a function in helpers + case 0: + x = meas.costhetal; + break; + case 1: + x = meas.costhetak; + break; + } + switch(aa){ + case 1: + y = meas.costhetak; + break; + case 2: + y = meas.phi; + break; + } + h->Fill(x, y); + } + h->GetZaxis()->SetRangeUser(0, fitReference ? 25 : 5); + h->GetZaxis()->SetTitle("Number of entries"); + + h->GetXaxis()->SetTitleSize(0.05); + h->GetXaxis()->SetLabelSize(0.05); + h->GetXaxis()->SetTitleOffset(0.95); + + h->GetYaxis()->SetTitleSize(0.05); + h->GetYaxis()->SetLabelSize(0.05); + h->GetYaxis()->SetTitleOffset(0.75); + + h->GetZaxis()->SetTitleSize(0.05); + h->GetZaxis()->SetLabelSize(0.05); + h->GetZaxis()->SetTitleOffset(0.75); + + h->SetTitle(""); + h->Draw("COLZ"); + + corrfactor[b][a][aa] = h->GetCorrelationFactor(); + + TLatex * leg = getPrettyTex(0.06,13); + leg->SetTextColor(kBlack); + std::ostringstream sCorrout; //TODO: move the path + sCorrout << std::fixed << std::setprecision(2) << "corr(" << latex_angles[a] << ", " << latex_angles[aa] <<") = " << corrfactor[b][a][aa]*100. << "\%"; + leg->DrawLatex(0.22,0.98, sCorrout.str().c_str()); + leg->SetTextSize(0.04); + leg->DrawLatex(0.25,0.92, ("Events: "+std::to_string((int) h->GetEntries())).c_str()); + cAngCorr->Print(get_bkgCorrPlot_path(ANGLES[a],ANGLES[aa],b,nBins,fitReference, LowMassFit, HighMassFit, fitKpi, params).c_str(), "eps"); + + } + } + + //Save the correlations s + myFile << "\\begin{tabular}{r|ccc}\\hline" << std::endl; + myFile << std::fixed << std::setprecision(2) << "[" << opts.TheQ2binsmin.at(b) << ", " << opts.TheQ2binsmax.at(b) << "]"; + for(UInt_t a = 0; a < nANGLES; a++) myFile << "\t&" << latex_2angles[a]; + myFile << "\\\\" << std::endl; + myFile << "\\hline\\hline" << std::endl; + for(UInt_t a = 0; a < nANGLES; a++){ + myFile << latex_2angles[a]; + for(UInt_t aa = 0; aa < nANGLES; aa++){ + myFile << "\t&"; + if(aa > a) myFile << std::setprecision(3) << std::fixed << corrfactor[b][a][aa]; + else if(aa == a) myFile << "1.00"; + else if(aa < a) myFile << " "; + } + myFile << "\\\\" << std::endl; + } + myFile << "\\hline" << std::endl; + myFile << "\\end{tabular}"<< std::endl; + myFile << std::endl; + + } + + //FIT ANGULAR BACKGROUND + B mass + opts.update_angle_ranges(); //Just in case + //fit all bins: + for(UInt_t b = 0; b < nBins; b++){ + + spdlog::info("[START]\tStart the fit for bin #{0:d}", b); + + //fit the events: + int fitresult = f.fit(theProb[b], theParams[b], theEvents[b]); + fitresults.push_back(fitresult); + + spdlog::info("[BIN{0:d}]:\tFitresult: {1:d}", b, fitresult); + + //plot pdf with the data points: + opts.plot_label = "LHCb data"; + opts.q2_label = q2_label(opts.TheQ2binsmin.at(b), opts.TheQ2binsmax.at(b)); + + if(opts.write_eps){ + std::string label = get_bkg_tag(b,nBins,fitReference, LowMassFit, HighMassFit, false, params); + spdlog::info("[PLOT]\t" + label); + thePlotter.plot_data(theProb[b], theParams[b], theEvents[b], get_bkgFitPlot_path(), label, false); + } + //print all parameters + std::string fitResultTxt = get_bkgFitResult_path()+ "fitresult_" + get_bkg_tag(b,nBins,fitReference, LowMassFit, HighMassFit, false, params); + spdlog::debug("Saving into "+fitResultTxt); + print_all_parameters(nBins, theParams, 2, fitResultTxt); + } + + //print all fitresults + print_fit_results(nBins, fitresults); + + //Save results to root file + std::string results_file = final_result_name_bkg(nBins, fitReference, LowMassFit, HighMassFit, false, params); + save_results(results_file, nBins, params.Run, fitresults, theParams, &opts); + + //FIT M(KPI) BACKGROUND + if (!fitKpi){ //first check if you really want to fit M(KPI) :) + //Close Latex file + myFile.close(); + return 0; + } + + //Reset the options + opts.only_angles = false; + opts.only_mkpi = true; + opts.fit_mkpi = true; + + + //fit all bins: + spdlog::info("[BKGFIT]\tFit the Kpi mass"); + for(UInt_t b = 0; b < nBins; b++){ + + theParams[b]->use_default_bkg(); + //null the lambda(s) and taus + theParams[b]->m_lambda.init_fixed(0.0); + theParams[b]->m_lambda_2.init_fixed(0.0); + theParams[b]->m_tau.init_fixed(0.0); + theParams[b]->m_tau_2.init_fixed(0.0); + //Init the floating parameters + theParams[b]->init_kpi_background_parameters(fitReference,0.01); + + spdlog::info("[START]\tStart the fit for bin #{0:d}", b); + + //fit the events: + fitresults.push_back(f.fit(theProb[b], theParams[b], theEvents[b])); + spdlog::info("[BIN{0:d} ]:\tFitresult: {1:d}",b, fitresults.at(b)); + + //plot pdf with the data points: + opts.q2_label = q2_label(opts.TheQ2binsmin.at(b), opts.TheQ2binsmax.at(b)); + + if(opts.write_eps){ + std::string label = get_bkg_tag(b,nBins,fitReference, LowMassFit, HighMassFit, false, params); + spdlog::info("[PLOT]\t" + label); + thePlotter.plot_data(theProb[b], theParams[b], theEvents[b], get_bkgFitPlot_path(), label, false); + } + //Print all parameters, but don't save + print_all_parameters(nBins, theParams, 2, ""); + + //print all parameters to txt file + std::string fitResultTxt = get_bkgFitResult_path()+ "fitresult_" + get_bkg_tag(b,nBins,fitReference, LowMassFit, HighMassFit, true, params); + spdlog::debug("Saving into "+fitResultTxt); + print_all_parameters(nBins, theParams, 2, fitResultTxt); + } + spdlog::info("[BKGFIT]\tDone with Kpi fit."); + //Save results to root file + results_file = final_result_name_bkg(nBins, fitReference, LowMassFit, HighMassFit, true, params); + save_results(results_file, nBins, params.Run, fitresults, theParams, &opts); + + //Close Latex file + myFile.close(); + + spdlog::info("[BKGFIT]\tFinished."); + return 0; +} diff --git a/Code/FCNCFitter/sources/Run/backgroundfit.hh b/Code/FCNCFitter/sources/Run/backgroundfit.hh new file mode 100644 index 0000000..31cea47 --- /dev/null +++ b/Code/FCNCFitter/sources/Run/backgroundfit.hh @@ -0,0 +1,13 @@ +//Renata Kopecna + +#ifndef BACKGROUNDFIT_HH +#define BACKGROUNDFIT_HH + +#include +#include + +int backgroundfit(fcnc::options opts, + bool fitReference, bool LowMassFit, bool HighMassFit,bool fitKpi, + bool Use2DAngularBins, basic_params params); + +#endif // BACKGROUNDFIT_HH diff --git a/Code/FCNCFitter/sources/Run/feldman_cousins.cc b/Code/FCNCFitter/sources/Run/feldman_cousins.cc new file mode 100644 index 0000000..f844421 --- /dev/null +++ b/Code/FCNCFitter/sources/Run/feldman_cousins.cc @@ -0,0 +1,629 @@ +/** + * @file feldman_cousins.hh + * @author Christoph Langenbruch, David Gerick, Renata Kopecna + * @date 2021-01-12 + * + */ + +#include + +//TODO: removed what all is unused +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "folder.hh" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + +bool fcnc::feldman_cousins::fc_1d(std::string parname, unsigned int nsteps, double parmin, double parmax, unsigned int ntoys, unsigned int pdfidx, + std::vector probs, std::vector params, generator* gen, fitter* f, + std::vector *> events, unsigned int bin, int from, int to){ + std::ostringstream sout; + bool TwoBins = false; + if(opts->TheQ2binsmin.size() == 8) TwoBins = false; + else if(opts->TheQ2binsmin.size() == 2) TwoBins = true; + else assert(opts->TheQ2binsmin.size() == 2 || opts->TheQ2binsmin.size() == 8); + + sout << "FCresult" << (TwoBins ? "_2BINS_" : "") << bin << "_" << parname << "_" << from << "_" << to << ".root"; + struct stat buffer; + if(stat (sout.str().c_str(), &buffer) == 0){ + spdlog::warn("[SKIP]\t\tFC job already run as root-file '" + sout.str() + "' exists, continue to next job!"); + return false; + } + else{ + spdlog::info("Feldman-Cousins study for parameter="+ parname + " in q2bin={0:d}", bin); + } + // if(!opts->full_angular) + // opts->always_generate_full_angular = false; + bool cache_minos = opts->minos_errors; + bool cache_hesse = opts->hesse_postrun; + bool cache_sq_hesse = opts->squared_hesse; + bool cache_shift = opts->shift_lh; + //int cache_print = spdlog::default_logger_raw()->level(); + + const unsigned int nPDF = probs.size(); + assert(params.size() == nPDF); + assert(events.size() == nPDF); + assert(pdfidx < nPDF); + + //temp save parameter set + unsigned int nparameters = params.at(pdfidx)->nparameters(); + std::vector > smvalues (nPDF, std::vector (nparameters, 0.0)); + for(unsigned int n = 0; n < nPDF; n++){ + for (unsigned int k=0; kget_parameter(k)->get_value(); + } + } + + parameter* par = params.at(pdfidx)->get_parameter(parname); + if (par != 0){ + opts->minos_errors = false; + opts->squared_hesse = false; + opts->hesse_postrun = false; + opts->simplex_prerun = false; + opts->shift_lh = false; + + opts->minuit_strategy = 2.0; + //fitter f(opts); + int statusdatafloated = f->fit(probs, params, events); + double lhdatafloated = f->likelihood(); + double valuedatafloated = par->get_value(); + spdlog::info("Data fit finished with -2logLh = {0:f}",lhdatafloated ); + std::vector > floatingvalues(nPDF, std::vector (nparameters, 0.0)); + std::vector > prev_error_low(nPDF, std::vector (nparameters, 0.0)); + std::vector > prev_error_high(nPDF, std::vector (nparameters, 0.0)); + std::vector > prev_meas(nPDF, std::vector (nparameters, 0.0)); + std::vector > isConstraint(nPDF, std::vector (nparameters, false)); + for(unsigned int n = 0; n < nPDF; n++){ + for (unsigned int k=0; kget_parameter(k)->get_value(); + prev_error_low.at(n).at(k) = params.at(n)->get_parameter(k)->get_previous_error_low(); + prev_error_high.at(n).at(k) = params.at(n)->get_parameter(k)->get_previous_error_high(); + prev_meas.at(n).at(k) = params.at(n)->get_parameter(k)->get_previous_measurement(); + isConstraint.at(n).at(k) = params.at(n)->get_parameter(k)->get_gaussian_constraint(); + } + } + + for(unsigned int n = 0; n < nPDF; n++){ + for (unsigned int k=0; kget_parameter(k)->get_name(), + prev_meas.at(n).at(k),prev_error_low.at(n).at(k) ,prev_error_high.at(n).at(k)); + } + } + } + + //opts->minuit_strategy = 1.0;//this should be 2 for the fixed data fit I think + if (from < 0) from = 0; + if (to > int(nsteps) || to < 0) to = nsteps; + std::vector lhdatafixed(to-from, 0.0); + std::vector statusdatafixed(to-from, 0); + std::vector > lhtoysfixed; + std::vector > lhtoysfloated; + + std::vector > statustoysfixed; + std::vector > statustoysfloated; + + std::vector > params_dfloated (nPDF, std::vector< double> (nparameters, 0.0)); + std::vector>>params_dfixed(nPDF,std::vector> + (to-from, std::vector(nparameters, 0.0))); + std::vector > > > params_tfixed (nPDF, + std::vector > > (to - from, + std::vector< std::vector< double> > (ntoys, + std::vector< double> (nparameters, 0.0)))); + std::vector > > > params_tfloated (nPDF, + std::vector > > (to - from, + std::vector< std::vector< double> > (ntoys, + std::vector< double> (nparameters, 0.0)))); + + //buffer floated data values + for(unsigned int n = 0; n < nPDF; n++){ + for (unsigned int k=0; kget_parameter(k)->get_value(); + } + } + + std::string pardesc = par->get_description(); + for (int j=from; jget_parameter(k)->init(floatingvalues.at(n).at(k), params.at(n)->get_parameter(k)->get_min(), params.at(n)->get_parameter(k)->get_max(), + params.at(n)->get_parameter(k)->get_step_size(), prev_error_low.at(n).at(k), prev_error_high.at(n).at(k)); + params.at(n)->get_parameter(k)->set_previous_measurement(prev_meas.at(n).at(k)); + } + else{ + params.at(n)->get_parameter(k)->init(floatingvalues.at(n).at(k), params.at(n)->get_parameter(k)->get_min(), params.at(n)->get_parameter(k)->get_max(), + params.at(n)->get_parameter(k)->get_step_size()); + } + } + params.at(n)->reset_parameters(); + } + for(unsigned int n = 0; n < nPDF; n++){ + params.at(n)->get_parameter(parname)->init(parcur, parmin, parmax, 0.0); + } + opts->minuit_strategy = 2.0;//more precise for fixed data fit (used for lh) + opts->hesse_postrun = false; + opts->simplex_prerun = false; + spdlog::info("Start fit with fixed parameter"); + statusdatafixed.at(j-from) = f->fit(probs, params, events); + lhdatafixed.at(j-from) = f->likelihood(); + spdlog::info("[DONE]\tFinished fit with fixed parameter"); + opts->minuit_strategy = 1.0;//less precise for toys -> speed more important + + opts->hesse_postrun = false; + opts->simplex_prerun = false; + + std::vector > fitvalues (nPDF, std::vector (nparameters, 0.0)); + for(unsigned int n = 0; n < nPDF; n++){ + //parameters from fixed point + for (unsigned int k=0; kget_parameter(k)->get_value(); + } + //buffer fixed data values + for (unsigned int k=0; kget_parameter(k)->get_value(); + } + } + + //make all toys with these params! + std::vector > >toys(ntoys, std::vector > ()); + spdlog::info("Start generating toys"); + for (unsigned int k = 0; k < ntoys; k++){ + spdlog::debug("[TOYS]\tGenerating toy sample {0:d}/{1:d}",k+1,ntoys ); + for(unsigned int n = 0; n < nPDF; n++){ + std::vector toy = gen->generate(events.at(n)->size(), params.at(n), probs.at(n)); + if(!opts->full_angular){ + fcnc::folder fldr(opts); + for(UInt_t e = 0; e < toy.size(); e++){ + fldr.fold(&toy.at(e)); + if(toy.at(e).m < 1000.){ + spdlog::warn("[CORRUPT]\tEvent={0:d} pdf={0:f} toy={0:f}",e, n, k ); + spdlog::warn("[CORRUPT]\tctl={0:f} ctk={0:f} phi={0:f} q2={0:f}", + toy.at(e).costhetal, toy.at(e).costhetak, toy.at(e).phi, toy.at(e).q2 ); + } + } + } + toys.at(k).push_back(toy); + } + } + spdlog::info("[DONE]\tGenerating toys"); + + //init parameters from fixed point + for(unsigned int n = 0; n < nPDF; n++){ + for(unsigned int k=0; kget_parameter(k)->init(fitvalues.at(n).at(k), params.at(n)->get_parameter(k)->get_min(), params.at(n)->get_parameter(k)->get_max(), + params.at(n)->get_parameter(k)->get_step_size(), prev_error_low.at(n).at(k), prev_error_high.at(n).at(k)); + params.at(n)->get_parameter(k)->set_previous_measurement(prev_meas.at(n).at(k)); + } + else{ + params.at(n)->get_parameter(k)->init(fitvalues.at(n).at(k), params.at(n)->get_parameter(k)->get_min(), params.at(n)->get_parameter(k)->get_max(), + params.at(n)->get_parameter(k)->get_step_size()); + } + } + } + //fit toys repeatedly + std::vector toysfixed; + std::vector toysfloated; + std::vector statusfixed; + std::vector statusfloated; + spdlog::info("Start fitting all toys"); + for (unsigned int k=0; kreset_parameters();//these are not the fitted/generated parameters->fix, they should float however, so should be ok? + } + for(unsigned int n = 0; n < nPDF; n++){ + params.at(n)->get_parameter(parname)->init(parcur, parmin, parmax, 0.0); + } + + //save pointers to toy events into vector: + std::vector * > leToys; + for(unsigned int n = 0; n < nPDF; n++){ + leToys.push_back(&toys.at(k).at(n)); + } + + //fit with fixed parameter + spdlog::info("[TOYS]\tFitting fixed toy sample {0:d}/{1:d} at step {2:d}/{3:d}", + k+1, ntoys, j-from+1, to-from ); + int resultfixed = f->fit(probs, params, leToys); + toysfixed.push_back(f->likelihood()); + statusfixed.push_back(resultfixed); + + //buffer fixed toy values + for(unsigned int n = 0; n < nPDF; n++){ + for (unsigned int l=0; lget_parameter(l)->get_value(); + } + params.at(n)->reset_parameters(); + + } + for(unsigned int n = 0; n < nPDF; n++){ + params.at(n)->get_parameter(parname)->init(parcur, parmin, parmax, 0.01); + } + + //fit with floated parameter + spdlog::info("[TOYS]\tFitting freed toy sample0:d}/{1:d} at step {2:d}/{3:d}", + k+1, ntoys, j-from+1, to-from ); + int resultfloated = f->fit(probs, params, leToys); + toysfloated.push_back(f->likelihood()); + statusfloated.push_back(resultfloated); + + //buffer fixed toy values + for(unsigned int n = 0; n < nPDF; n++){ + for (unsigned int l=0; lget_parameter(l)->get_value(); + } + } + } + lhtoysfixed.push_back(toysfixed); + lhtoysfloated.push_back(toysfloated); + statustoysfixed.push_back(statusfixed); + statustoysfloated.push_back(statusfloated); + }// end loop over steps + spdlog::info("[DONE]\tFitting all toys"); + spdlog::debug("tLoop over all {0:d} steps completed. Writing results to file!",nsteps ); + + //save to root file + TFile* fout = new TFile(sout.str().c_str(), "RECREATE"); + fout->cd(); + TTree* t = new TTree(parname.c_str(), pardesc.c_str()); + int pdf=0, step=0, statustfixed=0, statustfloated=0, toy=0, statusdfixed=0, statusdfloated=0; + double value=0.0, lhdfloated=lhdatafloated, lhdfixed=0.0, lhtfixed=0.0, lhtfloated=0.0; + t->Branch("bin",&bin,"bin/I"); + t->Branch("pdf",&pdf,"pdf/I"); + t->Branch("step",&step,"step/I"); + t->Branch("value",&value,"value/D"); + t->Branch("toy",&toy,"toy/I"); + t->Branch("statusdatafixed",&statusdfixed,"statusdatafixed/I"); + t->Branch("statusdatafloated",&statusdfloated,"statusdatafloated/I"); + t->Branch("statustoyfixed",&statustfixed,"statustoyfixed/I"); + t->Branch("statustoyfloated",&statustfloated,"statustoyfloated/I"); + t->Branch("lhdatafloated",&lhdfloated,"lhdatafloated/D"); + t->Branch("valuedatafloated",&valuedatafloated,"valuedatafloated/D"); + t->Branch("lhdatafixed",&lhdfixed,"lhdatafixed/D"); + t->Branch("lhtoyfixed",&lhtfixed,"lhtoyfixed/D"); + t->Branch("lhtoyfloated",&lhtfloated,"lhtoyfloated/D"); + //also save the fitted values + std::vector tfloated(nparameters, 0.0), tfixed(nparameters, 0.0), dfloated(nparameters, 0.0), dfixed(nparameters, 0.0); + for (unsigned int k = 0; k < nparameters; k++){ + fcnc::parameter* param = params.at(pdfidx)->get_parameter(k); + if (param->get_step_size() != 0.0){ + std::string parname(param->get_name()); + std::string pardesc(param->get_description()); + //TTree* t = new TTree(parname.c_str(), pardesc.c_str()); + t->Branch((std::string("datafixed_")+parname).c_str(),&dfixed.at(k),(std::string("datafixed_")+parname+std::string("/D")).c_str()); + t->Branch((std::string("datafloated_")+parname).c_str(),&dfloated.at(k),(std::string("datafloated_")+parname+std::string("/D")).c_str()); + t->Branch((std::string("toyfixed_")+parname).c_str(),&tfixed.at(k),(std::string("toyfixed_")+parname+std::string("/D")).c_str()); + t->Branch((std::string("toyfloated_")+parname).c_str(),&tfloated.at(k),(std::string("toyfloated_")+parname+std::string("/D")).c_str()); + } + } + for(unsigned int n = 0; n < nPDF; n++){ + pdf = n; //TODO: what is this supposed to do? + for (int j=from; jFill(); + } + } + } + t->Write(); + fout->Write(); + fout->Close(); + delete fout; + /* + //analyse results + std::string suffix = ""; + TH1D* cl = new TH1D((std::string("cl")+parname+suffix).c_str(), (std::string(";")+pardesc+std::string(";Confidence level")).c_str(), nsteps, parmin, parmax); + TH1D* lh = new TH1D((std::string("lh")+parname+suffix).c_str(), (std::string(";")+pardesc+std::string(";Confidence level")).c_str(), nsteps, parmin, parmax); + for (unsigned int j=0; j ddata) + nlarger++; + } + lh->SetBinContent(j+1, TMath::Erf(sqrt(lhdatafixed.at(j)-lhdatafloated)/sqrt(2.0))); + cl->SetBinContent(j+1, 1.0-double(nlarger)/ntoys); + } + double low = parmin; + const double thecl = 0.683; + if (cl->GetBinContent(1) > thecl)//??? + { + for (int i=0; iGetBinContent(i+1) > thecl && cl->GetBinContent(i+2) < thecl) + { + low = cl->GetBinCenter(i+1) + (thecl-cl->GetBinContent(i+1))*(cl->GetBinCenter(i+2)-cl->GetBinCenter(i+1))/(cl->GetBinContent(i+2)-cl->GetBinContent(i+1)); + break; + } + } + double high = parmax; + if (cl->GetBinContent(nsteps) > thecl) + { + for (int i=nsteps-1; i>=0; i--) + if (cl->GetBinContent(i+1) < thecl && cl->GetBinContent(i+2) > thecl) + { + high = cl->GetBinCenter(i+1) + (thecl-cl->GetBinContent(i+1))*(cl->GetBinCenter(i+2)-cl->GetBinCenter(i+1))/(cl->GetBinContent(i+2)-cl->GetBinContent(i+1)); + break; + } + } + TCanvas* c1 = new TCanvas("c1", "c1", 1600, 1200); + TLine* l = new TLine(); + c1->cd(); + cl->SetMinimum(0.0); + cl->SetMaximum(1.1); + cl->Draw(); + lh->SetLineColor(4); + lh->Draw("lsame"); + l->SetLineColor(2); + l->DrawLine(low, 0.0, low, 1.1); + l->DrawLine(high, 0.0, high, 1.1); + c1->Print((std::string("plots/cl")+parname+suffix+std::string(".eps")).c_str(),"eps"); + //delete cl; + delete l; + delete c1; + delete cl; + */ + } + else{ + spdlog::critical("Could not find parameter "+parname); + assert(0); + } + spdlog::info("Finished Feldman-Cousins study for parameter "+ parname); + opts->hesse_postrun = cache_hesse; + opts->squared_hesse = cache_sq_hesse; + opts->minos_errors = cache_minos; + opts->shift_lh = cache_shift; + return true; +} + +bool fcnc::feldman_cousins::fc_1d(std::string parname, unsigned int nsteps, double parmin, double parmax, unsigned int ntoys, + pdf* prob, parameters* params, generator* gen, fitter* f, + std::vector * events, unsigned int bin, int from, int to){ + std::vector the_probs; + the_probs.push_back(prob); + + std::vector the_params; + the_params.push_back(params); + + std::vector* > the_events; + the_events.push_back(events); + + return fc_1d(parname, nsteps, parmin, parmax, ntoys, 0, + the_probs, the_params, gen, f, + the_events, bin, from, to); +} + +bool fcnc::feldman_cousins::fc_2d(std::string parxname, unsigned int nstepsx, double parxmin, double parxmax, + std::string paryname, unsigned int nstepsy, double parymin, double parymax, + unsigned int ntoys, unsigned int pdfidx, //this parameter just changes output file + std::vector probs, std::vector params, generator* gen, fitter* f, + std::vector *> events, unsigned int bin, int from, int to){ + spdlog::info("Feldman-Cousins study for parameters" + parxname +", " +paryname ); + /* + bool cache_minos = opts->minos_errors; + bool cache_hesse = opts->hesse_postrun; + bool cache_shift = opts->shift_lh; + int cache_print = opts->print_level; + + const unsigned int nPDF = probs.size(); + assert(params.size() == nPDF); + assert(events.size() == nPDF); + assert(pdfidx < nPDF); + + parameter* parx = params.at(pdfidx)->get_parameter(parxname); + parameter* pary = params.at(pdfidx)->get_parameter(paryname); + if (parx != 0 && pary != 0) + { + opts->minos_errors = false; + opts->hesse_postrun = false; + opts->shift_lh = false; + + //fitter f(opts); + f->fit(probs, params, events); + double lhdatafloated = f.likelihood(); + double valuexdatafloated = parx->get_value(); + double valueydatafloated = pary->get_value(); + spdlog::info("Data fit finished with -2logLh = {0:f}",lhdatafloated ); + + opts->print_level = -1; + //std::cout << from << " {0:f}",to << " {0:f}",from - to << std::endl; + if (from < 0) + from = 0; + if (to > int(nstepsx*nstepsy) || to < 0) + to = nstepsx*nstepsy; + std::vector lhdatafixed(to-from, 0.0); + std::vector > lhtoysfixed; + std::vector > lhtoysfloated; + + std::vector > statustoysfixed; + std::vector > statustoysfloated; + + std::string parxdesc = parx->get_description(); + std::string parydesc = pary->get_description(); + for (int j=from; jinit(parxname, parxdesc, parxcur, parxmin, parxmax, 0.0); + pary->init(paryname, parydesc, parycur, parymin, parymax, 0.0); + f->fit(probs, params, events); + lhdatafixed.at(j-from) = f->likelihood(); + + //make all toys with these params! + std::vector > toys; + for (unsigned int k=0; k toy = gen->generate(events.size(), params, prob); + toys.push_back(toy); + } + //fit toys repeatedly + std::vector toysfixed; + std::vector toysfloated; + std::vector statusfixed; + std::vector statusfloated; + for (unsigned int k=0; kfix, they should float however, so should be ok? + parx->init(parxname, parxdesc, parxcur, parxmin, parxmax, 0.0); + pary->init(paryname, parydesc, parycur, parymin, parymax, 0.0); + int resultfixed = f->fit(probs, params, &toys.at(k)); + toysfixed.push_back(f->likelihood()); + statusfixed.push_back(resultfixed); + + params.reset_parameters(); + parx->init(parxname, parxdesc, parxcur, parxmin, parxmax, 0.01); + pary->init(paryname, parydesc, parycur, parymin, parymax, 0.01); + int resultfloated = f->fit(probs, params, &toys.at(k)); + toysfloated.push_back(f->likelihood()); + statusfloated.push_back(resultfloated); + } + lhtoysfixed.push_back(toysfixed); + lhtoysfloated.push_back(toysfloated); + statustoysfixed.push_back(statusfixed); + statustoysfloated.push_back(statusfloated); + } + //std::cout <<"after loop" ); + + //save to root file + std::ostringstream sout; + sout << "FCresult_" << bin << "_" << parxname << "_" << paryname << "_" << from << "_" << to << ".root"; + TFile* fout = new TFile(sout.str().c_str(), "RECREATE"); + fout->cd(); + TTree* t = new TTree((parxname+std::string("_")+paryname).c_str(), (std::string(";")+parxdesc+std::string(";")+parydesc).c_str()); + int step=0, stepx=0, stepy=0, statustfixed=0, statustfloated=0, toy=0; + double valuex=0.0, valuey, lhdfloated=lhdatafloated, lhdfixed=0.0, lhtfixed=0.0, lhtfloated=0.0; + t->Branch("bin",&bin,"bin/I"); + t->Branch("step",&step,"step/I"); + t->Branch("stepx",&stepx,"stepx/I"); + t->Branch("stepy",&stepy,"stepy/I"); + t->Branch("valuex",&valuex,"valuex/D"); + t->Branch("valuey",&valuey,"valuey/D"); + t->Branch("valuexdatafloated",&valuexdatafloated,"valuexdatafloated/D"); + t->Branch("valueydatafloated",&valueydatafloated,"valueydatafloated/D"); + t->Branch("toy",&toy,"toy/I"); + t->Branch("statustoyfixed",&statustfixed,"statustoyfixed/I"); + t->Branch("statustoyfloated",&statustfloated,"statustoyfloated/I"); + t->Branch("lhdatafloated",&lhdfloated,"lhdatafloated/D"); + t->Branch("lhdatafixed",&lhdfixed,"lhdatafixed/D"); + t->Branch("lhtoyfixed",&lhtfixed,"lhtoyfixed/D"); + t->Branch("lhtoyfloated",&lhtfloated,"lhtoyfloated/D"); + for (int j=from; jFill(); + } + } + t->Write(); + fout->Write(); + fout->Close(); + delete fout; + } + else{ + if (parx == 0) spdlog::error("Could not find parameter" +parxname ); + if (pary == 0) spdlog::error("Could not find parameter" +paryname ); + assert(0); + } + spdlog::info("Finished Feldman-Cousins study for parameters "+parxname + "," +paryname ); + opts->hesse_postrun = cache_hesse; + opts->minos_errors = cache_minos; + opts->shift_lh = cache_shift; + opts->print_level = cache_print; +*/ + return true; +} + +bool fcnc::feldman_cousins::fc_2d(std::string parxname, unsigned int nstepsx, double parxmin, double parxmax, + std::string paryname, unsigned int nstepsy, double parymin, double parymax, + unsigned int ntoys, //this parameter just changes output file + pdf* prob, parameters* params, generator* gen, fitter* f, + std::vector * events, unsigned int bin, int from, int to){ + std::vector the_probs; + the_probs.push_back(prob); + + std::vector the_params; + the_params.push_back(params); + + std::vector* > the_events; + the_events.push_back(events); + + return fc_2d(parxname, nstepsx, parxmin, parxmax, + paryname, nstepsy, parymin, parymax, + ntoys, 0, + the_probs, the_params, gen, f, + the_events, bin, from, to); +} + diff --git a/Code/FCNCFitter/sources/Run/feldman_cousins.hh b/Code/FCNCFitter/sources/Run/feldman_cousins.hh new file mode 100644 index 0000000..4158c46 --- /dev/null +++ b/Code/FCNCFitter/sources/Run/feldman_cousins.hh @@ -0,0 +1,66 @@ +/** + * @file feldman_cousins.hh + * @author Christoph Langenbruch, David Gerick + * @date 2020-06-30 + * + */ + +#ifndef FELDMAN_COUSINS_H +#define FELDMAN_COUSINS_H + +#include +#include +namespace fcnc { + //Forward declarations + class event; + class fitter; + class pdf; + class generator; + class parameters; + class options; + + class feldman_cousins; + + class feldman_cousins { + private: + options* opts; + int from, to; + public: + ///constructor + feldman_cousins(options* o): + opts(o), + from(-1), + to(-1) + { + }; + ///destructor + ~feldman_cousins(){}; + + ///one-dimensional feldman cousins + bool fc_1d(std::string parname, unsigned int nsteps, double parmin, double parmax, + unsigned int ntoys, unsigned int pdfidx, //this parameter just changes output file + std::vector probs, std::vector params, generator* gen, fitter* f, + std::vector *> events, unsigned int bin=0, int from=-1, int to=-1); + + bool fc_1d(std::string parname, unsigned int nsteps, double parmin, double parmax, + unsigned int ntoys, //this parameter just changes output file + pdf* prob, parameters* params, generator* gen, fitter* f, + std::vector * events, unsigned int bin=0, int from=-1, int to=-1); + ///two-dimensional feldman cousins + bool fc_2d(std::string parxname, unsigned int nstepsx, double parxmin, double parxmax, + std::string paryname, unsigned int nstepsy, double parymin, double parymax, + unsigned int ntoys, unsigned int pdfidx, //this parameter just changes output file + std::vector probs, std::vector params, generator* gen, fitter* f, + std::vector *> events, unsigned int bin=0, int from=-1, int to=-1); + + bool fc_2d(std::string parxname, unsigned int nstepsx, double parxmin, double parxmax, + std::string paryname, unsigned int nstepsy, double parymin, double parymax, + unsigned int ntoys, //this parameter just changes output file + pdf* prob, parameters* params, generator* gen, fitter* f, + std::vector * events, unsigned int bin=0, int from=-1, int to=-1); + }; + + +}//end namespace + +#endif diff --git a/Code/FCNCFitter/sources/Run/generatetoys.cc b/Code/FCNCFitter/sources/Run/generatetoys.cc new file mode 100644 index 0000000..dd2805e --- /dev/null +++ b/Code/FCNCFitter/sources/Run/generatetoys.cc @@ -0,0 +1,290 @@ +//Renata Kopecna + +#include "generatetoys.hh" +#include +#include +#include +#include +#include + +#include + +//Options to generate toys: +//Runs: 1, 2 or 1+2 +//Signal only / Bkg only / Both +//Rare / Jpsi +//Bins +//Mass only / Angles only +//S or P + +//Values taken from: MCsig, MCref, Bkg (top/bottom/both), Reference +//Can be also just mass/angle fit + +//TODO: move this somewhere else +bool LowMassFit = false; +bool HighMassFit = true; + + +int initialize_parameters_from_MCfit(fcnc::bu2kstarmumu_parameters *parameters, bool fromRef, int PDF, int bin, std::vector names, basic_params params, fixConstr fixConstrain){ + bool SimFit = true; + bool onlyAngs = false; + int nBins = fromRef ? 1 : params.nBins; //When looping over bins, this protects from trying to read from refMC + std::string fileName_MC = final_result_name_MC(params, nBins, fromRef, false, SimFit, onlyAngs, fromRef); + parameters->get_param_from_rootfile(fileName_MC, names, PDF, fromRef ? 0 : bin, fixConstrain); //TODO: use the struct fixConstr also in the parameters + return 0; +} + +int initialize_parameters_from_BkgFit(fcnc::bu2kstarmumu_parameters *parameters, bool fromRef, bool LowMassFit, bool HighMassFit, bool fitKpi, int PDF, int bin, std::vector names, basic_params params,fixConstr fixConstrain){ + int nBins = fromRef ? 1 : params.nBins; + std::string fileName_topBkg = final_result_name_bkg(nBins, fromRef, LowMassFit, HighMassFit, fitKpi, params); + parameters->get_param_from_rootfile(fileName_topBkg, names, PDF,fromRef ? 0 : bin, fixConstrain); + return 0; +} + +int initialize_parameters_from_MassFit(fcnc::bu2kstarmumu_parameters *parameters, bool fromRef, int PDF, int bin, std::vector names, basic_params params, fixConstr fixConstrain){ + int nBins = fromRef ? 1 : params.nBins; //When looping over bins, this protects from trying to read from refMC + bool splitRuns = true; //Get it per run or not + int b = fromRef ? 0 : bin; + //If not, use the PDF number form the parameter Run + std::string fileName_dataMass = final_result_name_mass(fromRef, nBins, params.Run, params, params.Run); + parameters->get_param_from_rootfile(fileName_dataMass, names, splitRuns ? PDF : params.Run, b, fixConstrain); + + return 0; +} + +int initialize_B_mass(fcnc::bu2kstarmumu_parameters *parameters, bool fromRef, int PDF, int bin, basic_params params){ + int nBins = fromRef ? 1 : params.nBins; //When looping over bins, this protects from trying to read from refMC + bool splitRuns = true; //Get it per run or not + int b = fromRef ? 0 : bin; + //Not part of the other functions as the range needs to be full + std::string fileName_dataMass = final_result_name_mass(fromRef, nBins, params.Run, params, params.Run); + parameters->m_b.init(get_param_value_from_rootfile(fileName_dataMass,"m_b", splitRuns ? PDF : params.Run,b),B_MASS_LOW,B_MASS_HIGH,0); + return 0; +} + + +//Take the default values, set in constants.hh and bu2kstarmumu_parameters.cc +int initialize_default_parameters(fcnc::bu2kstarmumu_parameters *parameters){ + parameters->use_default(); + return 0; +} + +//Generates toys identical to the given parameters +std::vector generateToys(basic_params params, int bin, int PDF, + fcnc::bu2kstarmumu_parameters *toyParameters, + fcnc::options opts){ +/* These options should not be modified inside here + // Set options // + //The options will be taken from the fitter itself + opts.only_angles = false; + opts.only_Bmass = false; + + opts.weighted_fit = true; + opts.use_weighted_bkg = false; + opts.always_generate_full_angular = true; + + opts.swave = false; + opts.shift_lh = false; + opts.individual_penalties = false; + + //Stat. uncertainty determination tool: + opts.squared_hesse = true; + opts.minos_errors = false; + + opts.generate_mkpi = true; + opts.simple_mkpi = false; + opts.isobar = false; + opts.mkpi_full_range_norm = false; + + opts.flat_bkg = false; +*/ + //Init the q2 options, to be sure + opts.q2_min = opts.TheQ2binsmin[bin]; + opts.q2_max = opts.TheQ2binsmax[bin]; + + opts.update_angle_ranges(); //Set angles in options back to defaults + //opts.update_efficiencies = true; //This ensures the acceptance weights to be taken into account. //TODO + if (opts.run == 1) opts.year = 2012; //Cause why not :) + else opts.year = 2017; + + //Create parameter set + fcnc::bu2kstarmumu_pdf prob(&opts, toyParameters); + fcnc::bu2kstarmumu_generator gen(&opts); + + prob.load_coeffs_eff_phsp_4d(); + prob.update_cached_normalization(toyParameters); + //And finally generate the events + //How much events relative to the requedred total number of events? + double frac = eventsInBin_fraction(bin,opts.run,params.nBins,params.reference); + int N = std::lround(params.nEvents*frac); + spdlog::info("Generate {0:d} toy events", N); + + std::vector genToys = gen.generate(N, toyParameters, &prob); + + //Update cached efficiencies of the angular acceptance correction weights + prob.update_cached_efficiencies(toyParameters, &genToys); + + //for folded analysis, fold the angular values of all generated events before returning + if(!opts.full_angular){ + spdlog::debug("Folding the generated {0:d} events according to fold #{1:d}", genToys.size(), opts.folding); + fcnc::folder theFolder(&opts); + for(UInt_t e = 0; e < genToys.size(); e++){ + fcnc::event * evt = &genToys.at(e); + theFolder.fold(evt); + spdlog::trace("Folded event: ctk={0:f}\t ctl={1:f}\t phi={2:f}\t m={3:f} \tmkpi={4:f}", evt->costhetak, evt->costhetal, evt->phi, evt->m, evt->mkpi); + } + } + return genToys; +} + +std::vector generateIndividualToys(basic_params params, int bin, int PDF, + fcnc::bu2kstarmumu_parameters *toyParameters, + fcnc::options opts, bool genOnlySig, bool genOnlyBkg){ + + if (genOnlySig && genOnlyBkg){ + spdlog::error("Cannot generate only bkg and only sig in one go!"); + spdlog::error("Check your options."); + return {{}}; + } + + bool genReference = params.reference; + + // Set options // + //The options will be taken from the fitter itself + opts.only_angles = false; + opts.only_Bmass = false; + + opts.weighted_fit = true; + opts.use_weighted_bkg = false; + opts.always_generate_full_angular = true; + + opts.swave = false; + opts.shift_lh = false; + opts.individual_penalties = false; + + //Stat. uncertainty determination tool: + opts.squared_hesse = true; + opts.minos_errors = false; + + opts.generate_mkpi = true; + opts.generate_only_bkg = genOnlyBkg; + opts.simple_mkpi = false; + opts.isobar = false; + opts.mkpi_full_range_norm = false; + + opts.flat_bkg = false; + + //Init the q2 options, to be sure + opts.q2_min = opts.TheQ2binsmin[bin]; + opts.q2_max = opts.TheQ2binsmax[bin]; + + opts.run = PDF; //Set proper run to options + opts.update_angle_ranges(); //Set angles in options back to defaults + opts.update_efficiencies = true; //This ensures the acceptance weights to be taken into account. + if (opts.run == 1) opts.year = 2012; //Cause why not :) + else opts.year = 2017; + + //Create parameter set + fcnc::bu2kstarmumu_pdf prob(&opts, toyParameters); + fcnc::bu2kstarmumu_generator gen(&opts); + + prob.load_coeffs_eff_phsp_4d(); + prob.update_cached_normalization(toyParameters); + + // Initialize everything // + //Note that hte code will crash if the file is not there, so test before submititng pls + + //Set the f_sig + if (genOnlySig) toyParameters->f_sig.init_fixed(1.0); + else if (genOnlyBkg) toyParameters->f_sig.init_fixed(0.0); + else{ //Or both, in that case load the f_sig from mass only fit + initialize_parameters_from_MassFit(toyParameters,genReference,PDF,bin,{"f_sig"},params,fixConstr(false,false)); + } + + //Init angular parameters from MC + if (genReference) toyParameters->init_ang_parameters_fromRefDavid(bin,1.0,0.01); + else initialize_parameters_from_MCfit(toyParameters,false,PDF,bin,param_string(opts, true),params,fixConstr(false,false)); + + //Init the ratio of sigmas in signal MC/reference MC + //As everything is fixed everywhere and not contrained in mass, this is fine, but this should be done properly //TODO + initialize_parameters_from_MCfit(toyParameters,genReference,PDF,bin,params_string_mass(opts),params,fixConstr(true,false)); + + if (!genReference) toyParameters->m_scale.init_fixed(get_sigmaRatio_fromMC(params,params.nBins,bin, PDF)); + else toyParameters->m_scale.init_fixed(1.0); + + + //Init the bkg parameters from the BKG fit file + //First init the background for angles + initialize_parameters_from_BkgFit(toyParameters, true, LowMassFit, HighMassFit, false, 12, bin,param_string_bkg(),params,fixConstr(false,false)); + //Then init the background for m_Kpi + initialize_parameters_from_BkgFit(toyParameters, true, LowMassFit, HighMassFit, true, 12, bin,param_string_bkg_mkpi(),params,fixConstr(false,false)); + + //Init the mass background from mass fit to reference for now + std::vector fixFromMassFit; //TODO: set as a proper vector depending on using 2 lambdas or anything + if (opts.fit_lambda) fixFromMassFit.push_back("m_lambda"); + else fixFromMassFit.push_back("m_tau"); + initialize_parameters_from_MassFit(toyParameters,true,PDF,bin,fixFromMassFit,params,fixConstr(false,false)); + + //Initialize the q2 by hand, as it is the easiest + toyParameters->eff_q2.init(bin_center_q2(opts,bin), opts.q2_min, opts.q2_max, 0.0); + + //Set the Bmass separatelly as it's range is important + initialize_B_mass(toyParameters,true,PDF,bin,params); + + //Control print of the parameters + toyParameters->print_parameters(false); + + //Update the normalisation with the new parameter settings + prob.update_cached_normalization(toyParameters); + + //And finally generate the events + //How much events relative to the requedred total number of events? + double frac = eventsInBin_fraction(bin,opts.run,params.nBins,params.reference); + int N = std::lround(params.nEvents*frac); + spdlog::info("Generate {0:d} toy events", N); + std::vector genToys = gen.generate(N, toyParameters, &prob); + + //for folded analysis, fold the angular values of all generated events before returning + if(!opts.full_angular){ + spdlog::debug("Folding the generated {0:d} events according to fold #{1:d}", genToys.size(), opts.folding); + fcnc::folder theFolder(&opts); + for(auto evt: genToys){ + theFolder.fold(&evt); + spdlog::trace("Folded event: ctk={0:f}, ctl={1:f}, phi={2:f}", evt.costhetak, evt.costhetal, evt.phi); + } + } + return genToys; +} + +int saveToys(basic_params params, fcnc::options opts, bool genOnlySig, bool genOnlyBkg){ + + std::vector pdf_idx; + if (params.Run == 1 || params.Run == 12) pdf_idx.push_back(1); + if (params.Run == 2 || params.Run == 12) pdf_idx.push_back(2); + + + const int nBins = params.nBins; + + std::vector toyParams [nBins]; + std::vectortmpRes[nBins]; //instead of fit results + + //Now just for saving do this + for (auto idx: pdf_idx){ + std::vector events; + for (int bin = 0; bin < params.nBins; bin++){ + fcnc::bu2kstarmumu_parameters * tmpParams = new fcnc::bu2kstarmumu_parameters (&opts); + std::vector tmp = generateIndividualToys(params, bin, idx, tmpParams, opts,genOnlySig, genOnlyBkg); + events.insert(events.end(),tmp.begin(),tmp.end()); + toyParams[bin].push_back(tmpParams); + tmpRes[bin].push_back(0); + } + std::string saveFile = get_finalToys_file(params.reference, nBins, true, params, idx); + fcnc::save_events(saveFile,events); + } + std::string paramFile = init_params_name_toys(-1,params.reference, nBins, true, params, params.Run, false, false, genOnlySig, genOnlyBkg, false, false); //TODO: fix the naming, as you actually do take stuff from upper-mass sideband + + save_results(paramFile,nBins,pdf_idx,tmpRes,toyParams,true,&opts); + return 0; + +} + diff --git a/Code/FCNCFitter/sources/Run/generatetoys.hh b/Code/FCNCFitter/sources/Run/generatetoys.hh new file mode 100644 index 0000000..7d487de --- /dev/null +++ b/Code/FCNCFitter/sources/Run/generatetoys.hh @@ -0,0 +1,18 @@ +//Renata Kopecna + +#ifndef GENERATETOYS_H +#define GENERATETOYS_H + +#include +#include +#include + +int initialize_parameters_from_MCfit(fcnc::bu2kstarmumu_parameters *parameters, bool fromRef, int PDF, int bin, std::vector names, basic_params params, fixConstr fixConstrain); +int initialize_parameters_from_BkgFit(fcnc::bu2kstarmumu_parameters *parameters, bool fromRef, bool LowMassFit, bool HighMassFit, bool fitKpi, int PDF, int bin, std::vector names, basic_params params, fixConstr fixConstrain); +int initialize_parameters_from_MassFit(fcnc::bu2kstarmumu_parameters *parameters, bool fromRef, int PDF, int bin, std::vector names, basic_params params, fixConstr fixConstrain); +int initialize_B_mass(fcnc::bu2kstarmumu_parameters *parameters, bool fromRef, int PDF, int bin, basic_params params); + +std::vector generateToys(basic_params params, int bin, int PDF, fcnc::bu2kstarmumu_parameters *toyParameters, fcnc::options opts); +std::vector generateIndividualToys(basic_params params, int bin, int PDF, fcnc::bu2kstarmumu_parameters *toyParameters, fcnc::options opts, bool genOnlySig, bool genOnlyBkg); +int saveToys(basic_params params, fcnc::options opts, bool genOnlySig, bool genOnlyBkg); +#endif // GENERATETOYS_H diff --git a/Code/FCNCFitter/sources/Run/genlvlfit.cc b/Code/FCNCFitter/sources/Run/genlvlfit.cc new file mode 100644 index 0000000..f86c4c7 --- /dev/null +++ b/Code/FCNCFitter/sources/Run/genlvlfit.cc @@ -0,0 +1,270 @@ +//Renata Kopecna + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +int genlvlfit(fcnc::options opts, bool fitPHSP, basic_params params){ + + //Gen Lvl always 2017 + params.Run = 2; + params.year = 2017; + + + //yes, it is repetition of mcfit, but it is easier this way + + //-------------------------------- + // Set constants + //-------------------------------- + if(fitPHSP) spdlog::info("[MCFIT]\tFit PHSP genLvl."); //reference channel only + else spdlog::info("[MCFIT]\tFit signal genLvl MC.");//signal MC only + + const bool Blind = false; //False as it is MC, HAS TO BE TRUE FOR DATA + const bool UseBinnedFit = true; //Use bins in q2, if false, nBins is forced to be one + const bool fixBMass = true; //Fix B mass to PDG value + const bool plotPulls = true; //Do you wanna pull plots with or without pulls? + + //Scales for the fit parameters (meaning fit-ranges) + double PprimeRangeScale = 10.0; + double angleRange = +1.0; + if (params.usePprime) angleRange *= PprimeRangeScale; + double angleStepSize = 0.05; + + if (!UseBinnedFit){ + spdlog::info("Running an unbinned fit"); + opts.TheQ2binsmin = get_TheQ2binsmin(1,false); + opts.TheQ2binsmax = get_TheQ2binsmax(1,false); + } + const unsigned int nBins = opts.get_nQ2bins(); //unsigned because vector.size is unsigned + spdlog::debug("Using {0:d} q2 bins.", nBins); + + //-------------------------------- + // Set all options + //-------------------------------- + opts.use_mkpi = false; + opts.fit_mkpi = false; + opts.crystalball = false; + opts.swave = false; + opts.weighted_fit = false; //Needed to plot the weights properly + opts.use_event_norm = false; //Used for convoluting the acceptance into pdf + + opts.only_angles = true; //Do not fit the mass, just angles + opts.only_Bmass = false; //Do not fit the angles, just mass + opts.extended_ml = false; + opts.flat_bkg = false; + + + //TODO: possibly add polarity + //-------------------------------- + // Load data + //-------------------------------- + spdlog::info("[MCFIT]\tLoading data..."); + int dataset = 5; //TODO: have a function for this + if (fitPHSP) dataset = 4; + std::vector events= fcnc::load_events(get_theFCNCpath(dataset,2), "Events", -1); + + UInt_t N_tot = events.size(); + if (N_tot==0){ + spdlog::error("Empty event vector!"); + return 404; + } + else spdlog::debug("Total number of used events:\t{0:d}", N_tot); + + //the rest can happily be arrays as nBins and nPDFs are well defined and it is 1D + std::vector fitresults; + + //Initialize all needed things for the fit + //current fitter, plotter, parameteres and pdfs: + fcnc::fitter f(&opts); + fcnc::folder fldr(&opts); + fcnc::bu2kstarmumu_plotter * thePlotter; + std::vector theParams [nBins]; + std::vector theProbs [nBins]; + std::vector*> selection[nBins]; + + //-------------------------------- + // Read events + //-------------------------------- + + opts.run = params.Run; //Set proper run to options //TODO: check if really needed + spdlog::debug("Run {0:d}", opts.run); + opts.name = get_genLvlFit_label(fitPHSP, nBins, -1, params, opts.only_angles, opts.only_Bmass); + opts.update_angle_ranges(); //Set angles in options back to defaults + opts.update_efficiencies = false; + + //Set the label to MC + opts.plot_label = "LHCb genLvl MC"; + + //Loop over bins + for(unsigned int b = 0; b < nBins; b++){ + opts.q2_min = opts.TheQ2binsmin.front(); + opts.q2_max = opts.TheQ2binsmax.back(); + + //Create parameter set + fcnc::bu2kstarmumu_parameters * leParameters = new fcnc::bu2kstarmumu_parameters(&opts); + //create PDF + fcnc::bu2kstarmumu_pdf * lePDF = new fcnc::bu2kstarmumu_pdf(&opts, leParameters); + + //Initialize basic parameters + //define center of q2bin as effective q2 + leParameters->eff_q2.init_fixed( bin_center_q2(opts,b)); + leParameters->f_sig.init_fixed(1.0); + + if (!opts.only_angles){ //If not fitting the angles, do not init the mass parameters + leParameters->init_mass_parameters(0,nBins,b,0.01); + leParameters->m_b.init(PDGMASS_B_PLUS, B_MASS_LOW, B_MASS_HIGH, fixBMass ? 0.0: 1.0); + leParameters->m_scale.init(1.0, 0.0, 2.0, 0.0); + } + + + //Angular observables + leParameters->init_angular_parameters(nBins,b,angleStepSize, angleRange, false); + + //make sure all configured values are also the start_value: + leParameters->take_current_as_start(); + + theParams[b].push_back(leParameters); + theProbs [b].push_back(lePDF); + spdlog::info("Saved PDF and parameters!"); + + //create vector with events according to the requested fits/pulls + std::vector *leEvents= new std::vector; + + //Loop over events + spdlog::debug("Loop over events"); + for(auto meas: events){ //WARN when more PDFs per run, this will fail!!! + //crosscheck between mag up and mag down: + if(params.polarity==1 && meas.magnet > 0) continue; + if(params.polarity==-1 && meas.magnet < 0) continue; + if(meas.q2 < opts.TheQ2binsmin.at(b) || meas.q2 > opts.TheQ2binsmax.at(b)) continue; + if(meas.mkpi < opts.mkpi_min || meas.mkpi > opts.mkpi_max) continue; + if(!opts.full_angular) fldr.fold(&meas); + + leEvents->push_back(meas); + } + + //Update efficiencies ONCE + lePDF->update_cached_normalization(leParameters); + lePDF->update_cached_efficiencies(leParameters, leEvents); + + spdlog::info("Finished selecting the events: {0:d}",leEvents->size()); + + //save event vector in vector + selection[b].push_back(leEvents); + if ((selection[b]).at(0)->size() > 0){ + spdlog::info("[BIN{0:d}]\tDone!", b); + } + else{ + spdlog::critical("No events found for q2-bin={0:d}. Exit!",b); + assert(0); + } + } //End loop over bins + + //Allocate the plotter + thePlotter = new fcnc::bu2kstarmumu_plotter(&opts); + + + //-------------------------------- + // FIT + //-------------------------------- + spdlog::info("[MCFIT]\tMC fit started."); + + //Measure the time for the fit: + runTime timer = runTime(); + + //Save the fit results + std::vector fit_results[nBins]; + std::vector f_sigs[nBins]; + std::vector f_sigserr[nBins]; + std::vector evts_cntr[nBins]; + std::vector vecParams; + + //fit all bins: + for(unsigned int b = 0; b < nBins; b++){ + + //Start the clock + timer.start(); + time_t startTime = time(0); + + spdlog::info("[START]\tStart the fit for bin #{0:d}", b); + + //Int for fit status + int fitresult = 0; + + //Delete the texFile + std::string tag = get_genLvlFit_label(fitPHSP, nBins, b, params, + opts.only_angles, opts.only_Bmass); + clear_Latex_noteFile(latex_fitterFile(tag)); + + spdlog::info("Running the fitter..."); + fitresult = f.fit(theProbs[b].at(0), theParams[b].at(0), selection[b].at(0),tag); + fit_results[b].push_back(fitresult); + + + //Stop the clock + timer.stop(startTime); + + //Print the fit results + spdlog::info("[BIN{0:d}]:\tFitresult: {1:d}", b, fitresult); + + //save signal fraction and event number for each bin and each pdf: + f_sigs[b].push_back( ((fcnc::bu2kstarmumu_parameters *) theParams[b].at(0))->f_sig.get_value()); + f_sigserr[b].push_back( ((fcnc::bu2kstarmumu_parameters *) theParams[b].at(0))->f_sig.get_error()); + evts_cntr[b].push_back((selection[b]).at(0)->size()); + opts.q2_label = q2_label(opts.TheQ2binsmin.at(b), opts.TheQ2binsmax.at(b)); + if (!plotPulls) tag = tag+"_noPulls"; + + + std::vector * prober = (std::vector *) & theProbs[b]; + std::vector * paramser = (std::vector *) & theParams[b]; + thePlotter->SetPulls(plotPulls); + + thePlotter->plot_added_pdfs(prober, paramser, &selection[b], + get_genLvlFitPlot_path(fitPHSP),tag, false); + + } //end bin loop + + + //-------------------------------- + // Print & Save + //-------------------------------- + + //Print running time + timer.print(nBins); + + //Print all fit results + print_all_parameters(nBins, {0}, theParams, spdlog::level::debug); + + //Save the fit results + for(unsigned int b = 0; b < nBins; b++){ + std::vector * paramser = (std::vector *) & theParams[b]; + paramser->at(0)->save_param_values(finalResult_genLvlMCfit_txt(fitPHSP, nBins, b, params, opts.only_angles, opts.only_Bmass)); + } + + //Print signal yield in the terminal and to a tex file + if (!Blind) print_sig_yields(nBins, {0}, evts_cntr, f_sigs, f_sigserr); + + print_sig_yields_tex(get_genLvlFit_label(fitPHSP, nBins, -1, params, + opts.only_angles, opts.only_Bmass), + nBins, {0}, &opts, evts_cntr, f_sigs, f_sigserr); + + + //Save results to root file + + std::string results_file = final_result_name_genLvlMC(params, nBins, fitPHSP, opts.only_angles, opts.only_Bmass); + save_results(results_file, nBins, {0}, fit_results, theParams, false, &opts); + + spdlog::info("[MCFIT]\tMC fit finished."); + return 0; + +} diff --git a/Code/FCNCFitter/sources/Run/genlvlfit.hh b/Code/FCNCFitter/sources/Run/genlvlfit.hh new file mode 100644 index 0000000..e6f83ff --- /dev/null +++ b/Code/FCNCFitter/sources/Run/genlvlfit.hh @@ -0,0 +1,10 @@ +//Renata Kopecna + +#ifndef GENLVLFIT_HH +#define GENLVLFIT_HH + +#include +#include + +int genlvlfit(fcnc::options opts, bool fitPHSP, basic_params params); +#endif // GENLVLFIT_HH diff --git a/Code/FCNCFitter/sources/Run/likelihoodscan.cc b/Code/FCNCFitter/sources/Run/likelihoodscan.cc new file mode 100644 index 0000000..fcf0d94 --- /dev/null +++ b/Code/FCNCFitter/sources/Run/likelihoodscan.cc @@ -0,0 +1,268 @@ +/** + * @file likelihoodscan.hh + * @author Christoph Langenbruch Renata Kopecna + * @date 2020-01-12 + * + */ + +//TODO: remove unused stuff +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +bool fcnc::likelihoodscan::scan_1d(std::string parname, unsigned int nsteps, double parmin, double parmax, + std::vector probs, std::vector params, + std::vector *> events, std::vector common_par, + unsigned int bin, int from, int to){ + spdlog::info("Likelihood scan study for parameter "+parname); + bool cache_minos = opts->minos_errors; + bool cache_hesse = opts->hesse_postrun; + bool cache_hesse2 = opts->squared_hesse; + bool cache_shift = opts->shift_lh; + //int cache_print = spdlog::default_logger_raw()->level(); + + parameter* par = params.at(0)->get_parameter(parname); + double cache_value = par->get_start_value(); + double cache_step_size = par->get_start_value(); + if (par != 0){ + opts->minos_errors = false; + opts->hesse_postrun = false; + opts->squared_hesse = false; + opts->shift_lh = false; + + fitter f(opts); + if(common_par.size() > 0) f.set_common_parameters(common_par); + + f.fit(probs, params, events); + double lhdatafloated = f.likelihood(); + spdlog::info("Data fit finished with -2logLh = {0:f}", lhdatafloated); + + if (from < 0) from = 0; + if (to > int(nsteps) || to < 0) to = int(nsteps); + + std::vector lhdatafixed(to-from, 0.0); + std::vector statusdatafixed(to-from, 0.0); + + std::string pardesc = par->get_description(); + for (int j=from; jreset_parameters(); + params.at(p)->get_parameter(parname)->init(parcur, parmin, parmax, 0.0); + } + statusdatafixed.at(j-from) = f.fit(probs, params, events); + lhdatafixed.at(j-from) = f.likelihood(); + } + //reactivate parameter for consecutive llh scans: + for(unsigned int p=0; pget_parameter(parname)->init(cache_value, parmin, parmax, cache_step_size); + } + + //save to root file + std::ostringstream sout; + sout << "llhscan_results_" << (opts->full_angular ? "full_angular" : "folding"+std::to_string(opts->folding)) << "_bin" << bin << ".root"; //TODO names + + TFile* fout = new TFile(sout.str().c_str(), "UPDATE"); + fout->cd(); + TTree* t = new TTree(parname.c_str(), pardesc.c_str()); + int step=0, statusdfixed=0; + double value=0.0, lhdfloated=lhdatafloated, lhdfixed=0.0; + t->Branch("bin",&bin,"bin/I"); + t->Branch("step",&step,"step/I"); + t->Branch("value",&value,"value/D"); + t->Branch("statusdatafixed",&statusdfixed,"statusdatafixed/I"); + t->Branch("lhdatafloated",&lhdfloated,"lhdatafloated/D"); + t->Branch("lhdatafixed",&lhdfixed,"lhdatafixed/D"); + for (int j=from; jFill(); + } + t->Write("",TObject::kWriteDelete); + fout->Write(); + fout->Close(); + delete fout; + } + else{ + spdlog::critical("Could not find parameter "+parname); + assert(0); + } + spdlog::info("Finished likelihood scan for parameter "+parname); + opts->hesse_postrun = cache_hesse; + opts->squared_hesse = cache_hesse2; + opts->minos_errors = cache_minos; + opts->shift_lh = cache_shift; + return true; +} + +bool fcnc::likelihoodscan::scan_1d(std::string parname, unsigned int nsteps, + double parmin, double parmax, + pdf* prob, parameters* params, + std::vector * events, + unsigned int bin, int from, int to){ + std::vector the_probs; + the_probs.push_back(prob); + + std::vector the_params; + the_params.push_back(params); + + std::vector* > the_events; + the_events.push_back(events); + + std::vector common_par; + common_par.clear(); + + return scan_1d(parname, nsteps, parmin, parmax, the_probs, the_params, the_events, common_par, bin, from, to); +} + + +bool fcnc::likelihoodscan::scan_2d(std::string parxname, unsigned int nstepsx, double parxmin, double parxmax, + std::string paryname, unsigned int nstepsy, double parymin, double parymax, + std::vector probs, std::vector params, + std::vector *> events, std::vector common_par, + unsigned int bin, int from, int to){ + spdlog::info("Likelihood scan study for parameters "+parxname+", "+paryname); + bool cache_minos = opts->minos_errors; + bool cache_hesse = opts->hesse_postrun; + bool cache_hesse2 = opts->squared_hesse; + bool cache_shift = opts->shift_lh; + //int cache_print = spdlog::default_logger_raw()->level(); + + parameter* parx = params.at(0)->get_parameter(parxname); + parameter* pary = params.at(0)->get_parameter(paryname); + if (parx != 0 && pary != 0){ + opts->minos_errors = false; + opts->hesse_postrun = false; + opts->squared_hesse = false; + opts->shift_lh = false; + + fitter f(opts); + if(common_par.size() > 0) f.set_common_parameters(common_par); + + f.fit(probs, params, events); + double lhdatafloated = f.likelihood(); + spdlog::info("Data fit finished with -2logLh = {0:f}", lhdatafloated); + + if (from < 0) from = 0; + if (to > int(nstepsx*nstepsy) || to < 0) to = nstepsx*nstepsy; + + std::vector lhdatafixed(to-from, 0.0); + std::vector statusdatafixed(to-from, 0.0); + + std::string parxdesc = parx->get_description(); + std::string parydesc = pary->get_description(); + for (int j=from; jreset_parameters(); + params.at(p)->get_parameter(parxname)->init(parxcur, parxmin, parxmax, 0.0); + params.at(p)->get_parameter(paryname)->init(parycur, parymin, parymax, 0.0); + } + + statusdatafixed.at(j-from) = f.fit(probs, params, events); + lhdatafixed.at(j-from) = f.likelihood(); + } + + //save to root file + std::ostringstream sout; + sout << "llh2Dscan_results_" << (opts->full_angular ? "full_angular" : "folding"+std::to_string(opts->folding)) << "_bin" << bin << ".root"; //TODO: name + TFile* fout = new TFile(sout.str().c_str(), "RECREATE"); + fout->cd(); + TTree* t = new TTree((parxname+std::string("_")+paryname).c_str(), (std::string(";")+parxdesc+std::string(";")+parydesc).c_str()); + int step=0, stepx=0, stepy=0, statusdfixed=0; + double valuex=0.0, valuey, lhdfloated=lhdatafloated, lhdfixed=0.0; + t->Branch("bin",&bin,"bin/I"); + t->Branch("step",&step,"step/I"); + t->Branch("stepx",&stepx,"stepx/I"); + t->Branch("stepy",&stepy,"stepy/I"); + t->Branch("valuex",&valuex,"valuex/D"); + t->Branch("valuey",&valuey,"valuey/D"); + t->Branch("statusdatafixed",&statusdfixed,"statusdatafixed/I"); + t->Branch("lhdatafloated",&lhdfloated,"lhdatafloated/D"); + t->Branch("lhdatafixed",&lhdfixed,"lhdatafixed/D"); + for (int j=from; jFill(); + } + t->Write(); + fout->Write(); + fout->Close(); + delete fout; + } + else{ + if (parx == 0) spdlog::info("Could not find parameter "+parxname); + if (pary == 0) spdlog::info("Could not find parameter "+paryname); + assert(0); + } + spdlog::info("Finished likelihood scan for parameters "+parxname+", "+paryname); + opts->hesse_postrun = cache_hesse; + opts->squared_hesse = cache_hesse2; + opts->minos_errors = cache_minos; + opts->shift_lh = cache_shift; + return true; +} + +bool fcnc::likelihoodscan::scan_2d(std::string parxname, unsigned int nstepsx, double parxmin, double parxmax, + std::string paryname, unsigned int nstepsy, double parymin, double parymax, + pdf* prob, parameters* params, + std::vector * events, unsigned int bin, int from, int to){ + + std::vector the_probs; + the_probs.push_back(prob); + + std::vector the_params; + the_params.push_back(params); + + std::vector* > the_events; + the_events.push_back(events); + + std::vector common_par; + common_par.clear(); + + return scan_2d(parxname, nstepsx, parxmin, parxmax, + paryname, nstepsy, parymin, parymax, + the_probs, the_params, the_events, common_par, bin, from, to); +} + diff --git a/Code/FCNCFitter/sources/Run/likelihoodscan.hh b/Code/FCNCFitter/sources/Run/likelihoodscan.hh new file mode 100644 index 0000000..3130fb8 --- /dev/null +++ b/Code/FCNCFitter/sources/Run/likelihoodscan.hh @@ -0,0 +1,60 @@ +/** + * @file likelihoodscan.hh + * @author Christoph Langenbruch Renata Kopecna + * @date 2020-01-12 + * + */ + +#ifndef LIKELIHOODSCAN_H +#define LIKELIHOODSCAN_H + +#include +#include + +namespace fcnc { + //Forward decalrations + class parameters; + class pdf; + class event; + class options; + +class likelihoodscan; + +class likelihoodscan { +private: + options* opts; + int from, to; +public: + ///constructor + likelihoodscan(options* o): + opts(o), + from(-1), + to(-1) + {}; + ///destructor + ~likelihoodscan(){}; + + ///one-dimensional likelihoodscan + bool scan_1d(std::string parname, unsigned int nsteps, double parmin, double parmax, + std::vector probs, std::vector params, + std::vector *> events, std::vector common_par, + unsigned int bin=0, int from=-1, int to=-1); + bool scan_1d(std::string parname, unsigned int nsteps, double parmin, double parmax, + pdf* prob, parameters* params, std::vector * events, + unsigned int bin=0, int from=-1, int to=-1); + + ///two-dimensional likelihood scan + bool scan_2d(std::string parxname, unsigned int nstepsx, double parxmin, double parxmax, + std::string paryname, unsigned int nstepsy, double parymin, double parymax, + std::vector probs, std::vector params, + std::vector *> events, std::vector common_par, + unsigned int bin=0, int from=-1, int to=-1); + bool scan_2d(std::string parxname, unsigned int nstepsx, double parxmin, double parxmax, + std::string paryname, unsigned int nstepsy, double parymin, double parymax, + pdf* prob, parameters* params, std::vector * events, + unsigned int bin=0, int from=-1, int to=-1); +}; + +}//end namespace + +#endif diff --git a/Code/FCNCFitter/sources/Run/mainfit.cc b/Code/FCNCFitter/sources/Run/mainfit.cc new file mode 100644 index 0000000..d2cfca3 --- /dev/null +++ b/Code/FCNCFitter/sources/Run/mainfit.cc @@ -0,0 +1,521 @@ +//Renata Kopecna + +#include + +#include +#include // std::istringstream + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +int mainfit(fcnc::options opts, basic_params params, bool fitReference, bool fitToy, bool likelihoodScan, bool FeldmanCousin){ + + //TODO + bool fitData = !fitToy; + //TODO: add a test where I cna try this on a toy file + + if(fitData) spdlog::info("[FIT]\tFit signal data"); //signal data << FINAL FIT!! + if(fitReference)spdlog::info("[FIT]\tFit reference channel: J/psi K*+"); //reference channel only + + //-------------------------------- + // Set all the options + //-------------------------------- + + //TODO: declare maybe in the header or elsewhere + const bool UseBinnedFit = !fitReference; + const bool SimultaneousFit = true; + const bool FixAngularBckgnd = false; //Fix the background to the shape of the upper mass sideband + const bool constrainBmass = false; + const bool FixedSwave = !fitReference; //TODO + const bool ConstrainedSwave = false; //TODO + const bool ConstrainedFS = false; //TODO + + const bool LoadFSfrom2Dfit = !fitReference && !(opts.systematic > -1); + //const bool JpsiWithRareStats = false; //Try to fit the Jpsi fit with only a subsample of events //TODO + const double fractionOfStats = 1.0; //Use only a fraction of statistics, eg for half set this to 0.5 + + //TODO: set the fraction of stats accordingly if JpsiWithRareStats; will make my life easier + + const bool NP = false; //TODO + const bool Blind = fitData && !fitReference; + + const bool plotPulls = true; //Do you wanna pull plots with or without pulls? + bool plotSignalRegion = fitReference; //Plot only the region around B mass, makes nicer plots + + const unsigned int nBins = UseBinnedFit ? opts.get_nQ2bins() : 1; + + if (fitToy && params.polarity!= 0){ + spdlog::warn("Your polarity is not set to both ofr whatever reason when fitting a toy!"); + spdlog::warn("Setting the polarity to 0!"); + params.polarity = 0; + } + //------------------------------------------------------------------------------------------------ + + if((int)ConstrainedSwave + (int) ConstrainedFS + (int) LoadFSfrom2Dfit > 1){ + //If at least two of those, then crash + spdlog::error("Use only one option to constrain FS:"); + spdlog::error("Constrained sWave" + boolToString(ConstrainedSwave)); + spdlog::error("Constrained FS" + boolToString(ConstrainedFS)); + spdlog::error("Load FS from 2D fit" + boolToString(LoadFSfrom2Dfit)); + assert(0); + } + + opts.fit_full_angular_bkg = true; //fold also the bkg? + opts.individual_penalties = false; + + //If blinded, don't plot anything + opts.write_eps = !Blind; + opts.write_pdf = false; + opts.write_C = false; + + //Fit both angles and mass + opts.only_angles = false; + opts.only_Bmass = false; + + //Fit swave? + opts.swave = true; + + //Use weights + opts.weighted_fit = true; + + //What framework? + opts.shift_lh = false; + opts.hesse_postrun = true; + opts.squared_hesse = true;//params.folding>-1; + opts.minos_errors = false;// params.folding==-1; + + //Flat background? + opts.flat_bkg = false; + //What order of bkg + opts.bkg_order_costhetak = 5; + + opts.fit_mkpi = true; //Use fit to Kpi mass? + opts.use_mkpi = false; //Do the 5D fit? //TODO: probably doesn't work now + opts.simple_mkpi = false; + opts.isobar = false; + opts.asymptotic = false; //Use the improved hesse calculation? + + //Check that sWave is on when fitting Kpi mass + assert(!(opts.fit_mkpi && !opts.swave)); + assert(!(opts.use_mkpi && !opts.swave)); + + //Use angular acceptance corrections + opts.update_efficiencies = true; + + //generate nametag for root file to save results: + std::string results_file = final_result_name(fitReference, false, params, + SimultaneousFit, nBins, params.Run, + fitToy, fractionOfStats, + NP, -1); //FitOnlyRun is not reflected in opts here TODO + + + //Set the available PDFs: this depends on the selected Run for now, so if only one is selected, run over one pdf, if both, use two + std::vector pdf_idx; + if (params.Run == 1 || params.Run == 12) pdf_idx.push_back(1); + if (params.Run == 2 || params.Run == 12) pdf_idx.push_back(2); + + //-------------------------------- + // Load data + //-------------------------------- + spdlog::info("[FIT]\tLoading data..."); + std::vector>events; + + if(fitToy){ + events.push_back(fcnc::load_events(get_finalToys_file(fitReference,nBins, SimultaneousFit, params,1),"Events", -1)); //Run1 + events.push_back(fcnc::load_events(get_finalToys_file(fitReference,nBins, SimultaneousFit, params,2),"Events", -1)); //Run2 + } + else{ + std::vector tmp = fcnc::load_events(get_theFCNCpath(0,1), "Events", -1); //Run1 + if (!fitReference) events.push_back(fcnc::filterResonances(tmp)); + else events.push_back(tmp); + tmp = fcnc::load_events(get_theFCNCpath(0,2), "Events", -1); //Run2 + if (!fitReference) events.push_back(fcnc::filterResonances(tmp)); + else events.push_back(tmp); + } + + //check that the number of pdfs is the same as number of event vectors + if (pdf_idx.size() != events.size()){ + spdlog::error("Something went very wrong when loading the events and setting the pdfs."); + spdlog::error("The number of PDFs != number of event vectors: {0:d} vs {1:d}",pdf_idx.size(), events.size()); + return 5; + } + + //we are good to go, now; how many individual pdfs are used? + const UInt_t nPDFs = pdf_idx.size(); + + //Control print of the loaded events + UInt_t N_tot = 0; + for (UInt_t n = 0; n < nPDFs; n++){ + spdlog::debug("Event vector {0:d}:\t"+(Blind?"Larger 1 ":std::to_string(events.at(n).size())),n); + if (events.at(n).size()==0){ + spdlog::error("Empty event vector!"); + return 404; + } + N_tot += events.at(n).size(); + } + spdlog::info("Total number of used events:\t{0:d}", N_tot); + + //Set fit ranges //TODO: just move it to init angle parameters + double angleRange = 1.0; + double PprimeRangeScale = 10.0; + if (params.usePprime) angleRange *= PprimeRangeScale; + double angleStepSize = 0.1; + + //get signal fractions and event numbers + //TODO: fix this when you know whether we need the eventNumbers here specifically + double sig_frac[nBins]; + + unsigned int event_numbers[nBins][nPDFs]; + + for(unsigned int b = 0; b < nBins; b++){ + for(unsigned int n = 0; n < nPDFs; n++){ + //get event numbers and signal fraction from global function, given the total number of events + //TODO: check what to do with JpsiWithRareStats + EventNumbers(b, n, sig_frac[b], event_numbers[b][n], N_tot, nBins, nPDFs); + event_numbers[b][n] *= fractionOfStats; + } + } + + //Control print + for(unsigned int b = 0; b < nBins; b++){ + for(unsigned int n = 0; n < nPDFs; n++){ + spdlog::debug("q2bin={0:d}\tPDF={1:d}\tf_sig={2:f}\tN={3:d}", b, n, sig_frac[b], event_numbers[b][n]); + } + } + + //create the fitter, plotter, parameteres and pdfs + fcnc::fitter f(&opts); + fcnc::folder fldr(&opts); + fcnc::options theOptions[nPDFs]; + fcnc::bu2kstarmumu_plotter * thePlotter[nPDFs]; + std::vector theParams [nBins]; + std::vector theProbs [nBins]; + std::vector< std::vector* > selection[nBins]; + + //these parameters are common: + std::vector common_params = param_string(opts, false); //set MC to true to avoid background there + spdlog::info("Shared parameters: " + convert_vector_to_string(common_params)); + //set common parameters: + if(SimultaneousFit) f.set_common_parameters(common_params); + + //Get the name of files needed for constraining + std::string signalMCFile = final_result_name_MC(params, nBins, false, false, SimultaneousFit, false, false); + std::string refrenceMCFile = final_result_name_MC(params, 1, true, false, SimultaneousFit, false, true); + bool takeAngBkgFromRef = true; + std::string upperMassBkgFile = final_result_name_bkg(takeAngBkgFromRef ? 1 : nBins, takeAngBkgFromRef, false, true, false, params); + std::string upperMassKpiBkgFile = final_result_name_bkg(takeAngBkgFromRef ? 1 : nBins, takeAngBkgFromRef, false, true, true, params); + std::string RefMassFile = final_result_name_mass(true,1,true,params,params.Run); + + for(UInt_t n = 0; n < nPDFs; n++){ + spdlog::debug("PDF {0:d}", n); + UInt_t idx = pdf_idx.at(n); + opts.update_angle_ranges(); //Set angles in options back to defaults + opts.update_efficiencies = true; //This ensures the acceptance weights to be taken into account. + //Set the label + if (fitToy) opts.plot_label = "Toy sample"; + else opts.plot_label = "LHCb data"; + opts.name = std::to_string(idx+1) + "_"+ get_eps_label(fitReference,false,false,fitToy, nBins, -1,-SimultaneousFit,params); //TODO: FIX THIS!!! + + //Set the options and init the plotter + theOptions[n] = opts; + theOptions[n].run = pdf_idx.at(n); //Set proper run to options + thePlotter[n] = new fcnc::bu2kstarmumu_plotter(&theOptions[n]); + + for(unsigned int b = 0; b < nBins; b++){ + theOptions[n].q2_min = theOptions[n].TheQ2binsmin.at(b) ; + theOptions[n].q2_max = theOptions[n].TheQ2binsmax.at(b); + + //create parameter sets + fcnc::bu2kstarmumu_parameters * leParameters = new fcnc::bu2kstarmumu_parameters(&theOptions[n]); + + //create PDFs + fcnc::bu2kstarmumu_pdf * lePDF = new fcnc::bu2kstarmumu_pdf(&theOptions[n], leParameters); + + //define center of q2bin as effective q2 by hand + leParameters->eff_q2.init_fixed(bin_center_q2(theOptions[n],b)); + + //Init mass + std::string fileName_dataMass = final_result_name_mass(true, 1, true, params, params.Run); + leParameters->init_Bmass(fileName_dataMass,pdf_idx.at(n),0.5,fixConstr(false,constrainBmass)); + + + //initiate the sig/bkg fraction for mass fit + leParameters->f_sig.init(fitReference ? 0.8 : 0.3, 0.0, 1.0, 0.05); + + //Init mass parameters + leParameters->init_mass_parameters(n,nBins,b,0.01); + leParameters->fix_param_from_rootfile(fitReference ? refrenceMCFile : signalMCFile, + {"alpha_1","alpha_2","n_1","n_2"}, idx, b); + //Fix the mass mean to the one from reference channel + if (!fitReference) leParameters->init_Bmass(RefMassFile, pdf_idx.at(n), 0.0, fixConstr(true,false)); + + //Init the ratio of sigmas in signal MC/reference MC + if (!fitReference) leParameters->m_scale.init_fixed(get_sigmaRatio_fromMC(params,nBins,b,pdf_idx.at(n))); + else leParameters->m_scale.init_fixed(1.0); + + //Init mass background + leParameters->init_mass_background_parameters(nBins,b,opts.fit_lambda); + + //(de)activate S-wave + double swaveStepSize = opts.swave && !FixedSwave ? 0.1 : 0.0; + + //Init the Kstar mass fit + if(opts.fit_mkpi || opts.use_mkpi){ + //p-wave + leParameters->init_mkpi_pWave_parameters(fitReference,0.0); + leParameters->init_kpi_background_parameters(fitReference,0.05); + //s-wave + if (opts.swave) leParameters->init_mkpi_sWave_parameters(fitReference, 0.0); + } + + //Init the sWave + if (opts.swave){ + leParameters->init_sWave_parameters(swaveStepSize); + leParameters->get_param_from_rootfile(RefMassFile, {"FS"}, idx, b,fixConstr(!fitReference,ConstrainedFS)); + } + + //Add angular parameters + leParameters->init_angular_parameters(nBins,b,angleStepSize,angleRange, Blind); + + //Add background to angular observables + + if(!theOptions[n].flat_bkg){ //If bkg not flat, init based on upper mass sideband fit + leParameters->get_param_from_rootfile(upperMassBkgFile, + PAR_BKG_STRING(opts.folding,opts.bkg_order_costhetal,opts.bkg_order_costhetak), + params.Run,b,fixConstr(FixAngularBckgnd,false)); + if (params.folding ==4){ + leParameters->cbkgctk2.init(-1.75,-3.0,1.5,0.05); + leParameters->cbkgctk4.init(-1.75,-3.0,1.5,0.05); + } + } + + //make sure all configured values are also the start_value: + leParameters->take_current_as_start(); + + //Add the parameters and the pdf into the vectors + theParams[b].push_back(leParameters); + theProbs [b].push_back(lePDF); + + spdlog::info("[PDF{0:d}]\tSaved PDF and parameters!", n); + + //Load the events + std::vector * leEvents = new std::vector; + + //choose events from the event vector and sort corresponding to q2bin or non-resonant: + //If use all events, just keep the numbers as they are + UInt_t NNN = events[n].size()*fractionOfStats; // UInt_t NNN = fractionOfStats == 1 ? events[n].size() : 0.5 + event_numbers[b][n]; + + //This randomly pre-selected list of events is used, if not all events are wanted (eg if JpsiWithRareStats) + std::vector event_idxs(NNN); + + if(fractionOfStats != 1.0){ + event_idxs = fcnc::GetNOutOfM(NNN, events[n].size(), 0, false, false); + } + else{ + std::iota (std::begin(event_idxs), std::end(event_idxs), 0); //This just puts 0,1,2,3,... into a vector + } + spdlog::info("Running fitter with a total number of events of: {0:d}", event_idxs.size()); + + for_indexed(auto e: event_idxs){ + //if (i%2!=0) continue; + fcnc::event meas = events[n].at(e); + //Cut on B mass + if(meas.m < B_MASS_LOW || meas.m > B_MASS_HIGH) continue; + //Select either magUp or magDown + if(params.polarity==1 && meas.magnet > 0) continue; + if(params.polarity==-1 && meas.magnet < 0) continue; + + //Select only events in the given bin + if(meas.q2 < theOptions[n].TheQ2binsmin.at(b) || meas.q2 > theOptions[n].TheQ2binsmax.at(b)) continue; + + //Cut on Kpi mass + if(meas.mkpi < opts.mkpi_min || meas.mkpi > opts.mkpi_max) continue; + + //Fold if needed + if(!filterFldFour(&meas, &theOptions[n])) continue; //remove ctk events + if(!opts.full_angular) fldr.fold(&meas); + + leEvents->push_back(meas); + } + + //Load the acceptance correction + lePDF->load_coeffs_eff_phsp_4d(); + lePDF->update_cached_normalization(leParameters); + lePDF->update_cached_efficiencies(leParameters, leEvents); + + spdlog::info("[PDF{0:d}]\tFinished selecting the events: {1:d}",n, leEvents->size()); + + //save event vector in vector + selection[b].push_back(leEvents); + + if(selection[b].back()->size() > 0){ + spdlog::info("[PDF{0:d}]\t[BIN{1:d}]\tDone!", n, b); + } + else{ + spdlog::critical("No events found for PDF={0:d} and q2-bin={1:d}. Exit!",n,b); + assert(0); + } + } //end loop over bins + theOptions[n].update_efficiencies = false; //Prevent multiple weights + } //end loop over PDFs + + //Measure the time for the fit: + runTime timer = runTime(); + + //Save the fit results + std::vectorfit_results[nBins]; + std::vectorf_sigs[nBins]; + std::vectorf_sigserr[nBins]; + std::vectorevts_cntr[nBins]; + + //-------------------------------- + // FIT + //-------------------------------- + spdlog::info("[FIT]\tFit started."); + + for(unsigned int b = 0; b < nBins; b++){ + + //Start the clock + timer.start(); + time_t startTime = time(0); + + spdlog::info("[START]\tStart the fit for bin #{0:d}", b); + + //fit the events: + const bool do_fit = !FeldmanCousin; //TODO: ask David wtf + int fitresult = 0; + if(do_fit){ + if(!SimultaneousFit){ + for(UInt_t n = 0; n < nPDFs; n++){ + UInt_t idx = pdf_idx.at(n); + spdlog::info("[FIT{0:d}]\tRunning the fitter...", idx); + fitresult = f.fit(theProbs[b].at(n), theParams[b].at(n), selection[b].at(n)); + fit_results[b].push_back(fitresult); + } + } + else{ + spdlog::info("[FIT]\tFitting the following events simultaenously:"); + for(UInt_t s = 0; s < selection[b].size(); s++) spdlog::info("PDF #{0:d}: {1:d}", pdf_idx.at(s), selection[b].at(s)->size()); + fitresult = f.fit(theProbs[b], theParams[b], selection[b]); + fit_results[b].push_back(fitresult); + spdlog::info("Q2BIN={0:d}\tLLH={1:f}", b, f.likelihood()); + + //run likelihood profile scan //TODO: fix and implement + if(likelihoodScan) return 5; + + //run feldman cousins //TODO: fix and implement + if(FeldmanCousin) return 5; + } + } + else{ //in case of not fit, just update the pdfs....? + for(UInt_t n = 0; n < nPDFs; n++){ + theProbs[b].at(n)->update_cached_efficiencies(theParams[b].at(n), selection[b].at(n)); + fit_results[b].push_back(fitresult); + } + } + + //Stop the clock + timer.stop(startTime); + + + //save signal fraction and event number for each bin and each pdf: + for(UInt_t n = 0; n < nPDFs; n++){ + f_sigs[b] .push_back(((fcnc::bu2kstarmumu_parameters *) theParams[b].at(n))->f_sig.get_value()); + f_sigserr[b].push_back(((fcnc::bu2kstarmumu_parameters *) theParams[b].at(n))->f_sig.get_error()); + evts_cntr[b].push_back(selection[b].at(n)->size()); + } + + //plot each set of pdfs with the data points: + bool do_plot = !(likelihoodScan || FeldmanCousin); + if (do_plot){ + for(UInt_t n = 0; n < nPDFs; n++){ + std::string eps_label = get_eps_label(fitReference,false, false, fitToy, + params.nBins, b, + params.polarity, + SimultaneousFit, theOptions[n]); + + theOptions[n].q2_label = q2_label(opts.TheQ2binsmin.at(b), opts.TheQ2binsmax.at(b)); + + spdlog::info("[PLOT]\t"+eps_label); + thePlotter[n]->SetPulls(plotPulls); + if (plotSignalRegion) thePlotter[n]->plot_data((fcnc::bu2kstarmumu_pdf*)theProbs[b].at(n), (fcnc::bu2kstarmumu_parameters*)theParams[b].at(n), selection[b].at(n), get_MainFitPlot_path(), eps_label, plotSignalRegion); + thePlotter[n]->plot_data((fcnc::bu2kstarmumu_pdf*)theProbs[b].at(n), (fcnc::bu2kstarmumu_parameters*)theParams[b].at(n), selection[b].at(n), get_MainFitPlot_path(), eps_label+"_incBkg", false); + } + + //plot both PDFs together + std::vector * prober = (std::vector *) & theProbs[b]; + + std::string eps_label = get_eps_label(fitReference,false, false, fitToy, + params.nBins, b, + params.polarity, + SimultaneousFit, opts); + std::vector * paramser = (std::vector *) & theParams[b]; + thePlotter[0]->SetPulls(plotPulls); + if (plotSignalRegion) thePlotter[0]->plot_added_pdfs(prober, paramser, & selection[b], get_MainFitPlot_path(), eps_label, plotSignalRegion); //TODO add prefix to the plots + thePlotter[0]->plot_added_pdfs(prober, paramser, & selection[b], get_MainFitPlot_path(), eps_label+"_incBkg", false); + + + }//end do_plot + }//end loop over bins for fitter + + if(likelihoodScan || FeldmanCousin) return 5; //Not implemented yet + + //-------------------------------- + // Print & Save + //-------------------------------- + + //Print running time + timer.print(nBins); + + + if (!Blind) print_all_parameters(nBins, pdf_idx, theParams, spdlog::level::debug); + + //Save the fit results into a txt file in case + for(UInt_t n = 0; n < nPDFs; n++){ + for(unsigned int b = 0; b < nBins; b++){ + //Print all fit results + for(unsigned int b = 0; b < nBins; b++){ + spdlog::info("[BIN{0:d}]:\tFitresult: {1:d}", b, fit_results[n].at(b)); + } + std::string txtFile = get_MainFitResult_path() + "fitresult_" + + get_eps_label(fitReference,false, false, fitToy, + params.nBins, b, + params.polarity, + SimultaneousFit, theOptions[n])+ ".txt"; + ((fcnc::bu2kstarmumu_parameters *) theParams[b].at(n))->save_param_values(txtFile); + } + } + + //Print signal yield in the terminal and to a tex file + if (!Blind){ + print_sig_yields(nBins, pdf_idx, evts_cntr, f_sigs, f_sigserr); + print_bkg_yields(nBins, pdf_idx, evts_cntr, f_sigs, f_sigserr); + } + print_sig_yields_tex(get_eps_label(fitReference,false, false, fitToy, + params.nBins, -1, + params.polarity, + SimultaneousFit, opts), + nBins, pdf_idx, &opts, evts_cntr, f_sigs, f_sigserr); + + + //saving results to root file TODO + save_results(results_file,nBins,pdf_idx,fit_results,theParams,SimultaneousFit,&opts); + spdlog::info("Finished fit."); + + return 0; + +} diff --git a/Code/FCNCFitter/sources/Run/mainfit.hh b/Code/FCNCFitter/sources/Run/mainfit.hh new file mode 100644 index 0000000..3afcbde --- /dev/null +++ b/Code/FCNCFitter/sources/Run/mainfit.hh @@ -0,0 +1,44 @@ +//Renata Kopecna + +#ifndef MAINFIT_HH +#define MAINFIT_HH + +#include +#include + + +//////////////////////////////////////////// +// FL SCALING OF LARGE BINS TO SMALL BINS // +//////////////////////////////////////////// + + // TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO + +//Idea is to scale FS accordingly to FL distributions +//FS is obtained in three bins: [1.0-8.0], [11.0-12.5] and [15.0-19.0] in 2D mass fits +//the following scales for FL are obtained from flav.io and are the ratio of int(FL)_largebin / int(FL)_smallbin +//in principle, only the scaling in q2 below the ccbar peaks is significant + +///including the first q2bin: //TODO: get from my MC +const std::vector FL_scale = {0.4836193455050577, 1.2251014138607774, 1.274499551405837, 1.1368614009399862}; + +const std::vector FL_scale_toys = { //TODO Get from my MC! + 0.5, //scaled from average of bin 1-4 + 1.0 + 0.07 / (61.*4) * (61.+ 62.+ 96.+ 125.), + 1.0 + 0.12 / (62.*4) * (61.+ 62.+ 96.+ 125.), + 1.0 - 0.02 / (96.*4) * (61.+ 62.+ 96.+ 125.), + 1.0 - 0.17 / (125.*4) * (61.+ 62.+ 96.+ 125.), + 1.0,//evaluated by itself + 1.0 + 0.04 / (129. * 2) * (129. + 69.), + 1.0 - 0.04 / (69. * 2) * (129. + 69.), +}; + +//////////////////////////////////////////// +// Other constants // +//////////////////////////////////////////// +const int TotalEvents = 0; + +//////////////////////////////////////////// +/// \brief mainfit +int mainfit(fcnc::options opts, basic_params params, bool fitReference, bool fitToy, bool likelihoodScan, bool FeldmanCousin); + +#endif // MAINFIT_HH diff --git a/Code/FCNCFitter/sources/Run/massfit.cc b/Code/FCNCFitter/sources/Run/massfit.cc new file mode 100644 index 0000000..67ce101 --- /dev/null +++ b/Code/FCNCFitter/sources/Run/massfit.cc @@ -0,0 +1,414 @@ +//Renata Kopecna + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +//Fitter part that fits only the mass of DATA + +bool checkForCommonValues(std::vector vec_one,std::vector vec_two){ + for (auto key: vec_one){ + if (std::find(vec_two.begin(), vec_two.end(), key)!= vec_two.end()){ + spdlog::warn("Parameter " + key + " is shared between two vectors!"); + return true; + } + } + return false; +} + +int massfit(fcnc::options opts, bool fitReference, bool splitRuns, basic_params pars){ + //splitRuns = true means one gets a simFit of Run 1 and Run 2 + //splitRuns = false means Run 1 and Run 2 are fit together + + const bool fitKstarMass = true; + + bool Blind = false;//!fitReference; //If signal channel, blind to be sure + const unsigned int nBins = opts.get_nQ2bins(); //unsigned because vector.size is unsigned + + bool constrainMassFromMC = false; //Use mass fit of MC to constrain mass parameters? + bool constrainMassFromRefMC = true;//Use mass fit of *RefMC* to constrain mass parameters? + bool constrainMassFromData = !fitReference; //Use the mass fit of data Reference to constrain the parameters? + + bool fixBMass = !fitReference; //Fix the B mass to PDG? + + //Set the parameters that should be constrained + std::vector toBeConstrainedMC = {}; + std::vector toBeFixedMC = {}; + + std::vector toBeConstrainedRefMC = {}; + std::vector toBeFixedRefMC = {"alpha_1","alpha_2","n_1","n_2"}; + + std::vector toBeConstrainedRefData = {}; + std::vector toBeFixedRefData = {"m_b","m_sigma_1"}; + + + //Sanity check one doesn't constrain one thing to two different values + if (constrainMassFromMC && constrainMassFromRefMC){ + if (checkForCommonValues(toBeConstrainedMC, toBeConstrainedRefMC)){ + spdlog::warn("Fix your options, aborting now!"); + return 2; + } + if (checkForCommonValues(toBeFixedMC, toBeFixedRefMC)){ + spdlog::warn("Fix your options, aborting now!"); + return 2; + } + } + if (constrainMassFromMC && constrainMassFromData){ + if (checkForCommonValues(toBeConstrainedMC, toBeConstrainedRefData)){ + spdlog::warn("Fix your options, aborting now!"); + return 2; + } + if (checkForCommonValues(toBeFixedMC, toBeFixedRefData)){ + spdlog::warn("Fix your options, aborting now!"); + return 2; + } + } + if (constrainMassFromRefMC && constrainMassFromData){ + if (checkForCommonValues(toBeConstrainedRefMC, toBeConstrainedRefData) ){ + spdlog::warn("Fix your options, aborting now!"); + return 2; + } + if (checkForCommonValues(toBeFixedRefMC, toBeFixedRefData)){ + spdlog::warn("Fix your options, aborting now!"); + return 2; + } + } + + if (constrainMassFromMC && checkForCommonValues(toBeConstrainedMC, toBeFixedMC)){ + spdlog::warn("The parameter will be fixed!"); + } + if (constrainMassFromRefMC && checkForCommonValues(toBeConstrainedRefMC, toBeFixedRefMC)){ + spdlog::warn("The parameter will be fixed!"); + } + if (constrainMassFromData && checkForCommonValues(toBeConstrainedRefData, toBeFixedRefData)){ + spdlog::warn("The parameter will be fixed!"); + } + + gROOT->SetBatch(kTRUE); + gROOT->SetStyle("Plain"); + set_gStyle(); + + //Open texFile + std::ofstream myFile; + open_Latex_noteFile(latex_massFit(), myFile); + + spdlog::info("[FIT]\t\tFitting only mass..."); + + // --- Set the options --- // + opts.only_Bmass = !fitKstarMass; + opts.only_mass2DFit = fitKstarMass; + + opts.swave = fitKstarMass; + opts.shift_lh = false; //keep it, it was there before + opts.weighted_fit = fitKstarMass; // weights for the MASS DATA fit + + opts.plot_chi2 = true; + opts.fit_mkpi = fitKstarMass; + opts.use_mkpi = false; + opts.plot_folder = get_MassFitPlot_path(); //Set the plot path + opts.minos_errors = true; //TODO! + opts.squared_hesse = false; + opts.asymptotic = false; + + if (!fitReference) opts.plots_m_bins = 30; //Plot less bins for signal channel as the stats are sad there + if (!fitReference) opts.plots_mkpi_bins = 20; //Plot less bins for signal channel as the stats are sad there + + // --- Load events from data tuple --- // + std::vector>events; + std::vector pdf_idx; + + if (opts.run == 1 || opts.run == 12){ + std::vector tmp = fcnc::load_events(get_theFCNCpath(0,1), "Events", -1); + if (!fitReference) events.push_back(fcnc::filterResonances(tmp)); + else events.push_back(tmp); + pdf_idx.push_back(1); + } + if (opts.run == 2 || opts.run == 12){ + std::vector tmp = fcnc::load_events(get_theFCNCpath(0,2), "Events", -1); + if (!fitReference) events.push_back(fcnc::filterResonances(tmp)); + else events.push_back(tmp); + pdf_idx.push_back(2); + } + //No need to keep the datasets separated, as there is no need for the weights + if (!splitRuns && opts.run == 12){ + pdf_idx.clear(); + pdf_idx.push_back(12); + //Add the vector from Run 2 into Run 1 vector + events[0].insert(events[0].end(), events[1].begin(), events[1].end()); + //Delete the Run 2 vector + events.pop_back(); + } + + //check that the number of pdfs is the same as number of event vectors + if (pdf_idx.size() != events.size()){ + spdlog::error("Something went very wrong when loading the events and setting the pdfs."); + spdlog::error("The number of PDFs!= number of event vectors: {0:d} vs {1:d}",pdf_idx.size(), events.size()); + return 5; + } + //we are good to go, now; how many individual pdfs are used? + const UInt_t nPDFs = pdf_idx.size(); + + //Check the number of events + UInt_t N_tot = 0; + for (UInt_t n = 0; n < nPDFs; n++){ + spdlog::debug("Event vector {0:d}:\t"+(Blind ? "Larger 1 ":std::to_string(events.at(n).size())), n); + if (events.at(n).size()==0){ + spdlog::error("Empty event vector!"); + return 404; + } + N_tot += events.at(n).size(); + } + spdlog::info("Total number of used events:\t{0:d}", N_tot); + + //Get the path to the file where to get the values/constraints from + //Always use simFit from MCand mass only, it is easier + std::string ParamInitFileMC = final_result_name_MC(pars, nBins, fitReference, false, true, false, false); + std::string ParamInitFileRefMC = final_result_name_MC(pars, 1, true, false, true, false, true); + std::string ParamInitFileRefData = final_result_name_mass(true, 1, splitRuns, pars, pars.Run); + + //current fitter, plotter, parameter and pdf: + fcnc::fitter f(&opts); + fcnc::options theOptions[nPDFs]; + fcnc::bu2kstarmumu_plotter * thePlotter[nPDFs]; + std::vector theParams [nBins]; + std::vector theProbs [nBins]; + std::vector< std::vector*> selection[nBins]; + + //Set FS as a common parameter if fitting the sWeight + if(fitKstarMass) f.set_common_parameters({"FS"}); + + //Loop over PDFs and initialize parameters + for(unsigned n = 0; n < nPDFs; n++){ + opts.run = pdf_idx.at(n); //Set proper run to options + opts.name = get_MassFit_label(fitReference, -1, nBins, splitRuns, pars, pdf_idx.at(n)); + spdlog::debug("Initializing run {0:d}", opts.run); + opts.update_efficiencies = true; //This ensures the acceptance weights to be taken into account. + //loop over number of bins + for(UInt_t b = 0; b < nBins; b++){ + //Create parameter set + fcnc::bu2kstarmumu_parameters * leParameters = new fcnc::bu2kstarmumu_parameters(&opts); + //create PDF + fcnc::bu2kstarmumu_pdf * lePDF = new fcnc::bu2kstarmumu_pdf(&opts, leParameters); + + //Init the sig/bkg fraction + leParameters->f_sig.init(fitReference ? 0.8 : 0.3, 0.1, 1.0, 0.1); + + //Init PDG mass, keep the range this large! + leParameters->m_b.init(PDGMASS_B, B_MASS_LOW, B_MASS_HIGH, fixBMass ? 0.0 : 0.1); + + //Init mass parameters to defaults + leParameters->init_mass_parameters(n,nBins,b,0.01); + + //Overwrite the defaults with constraints/fixes from MC/Ref, if needed + if (constrainMassFromMC){ + leParameters->constrain_param_from_rootfile(ParamInitFileMC, toBeConstrainedMC, splitRuns ? pdf_idx.at(n) : 2, b); + leParameters->fix_param_from_rootfile(ParamInitFileMC, toBeFixedMC, splitRuns ? pdf_idx.at(n) : 2, b); + } + if (constrainMassFromRefMC){ //Fix to refrence channel, so always read 0th bin + leParameters->constrain_param_from_rootfile(ParamInitFileRefMC, toBeConstrainedRefMC, splitRuns ? pdf_idx.at(n) : 2, 0); + leParameters->fix_param_from_rootfile(ParamInitFileRefMC, toBeFixedRefMC, splitRuns ? pdf_idx.at(n) : 2, 0); + } + if (constrainMassFromData){ //Fix to refrence channel, so always read 0th bin + leParameters->constrain_param_from_rootfile(ParamInitFileRefData, toBeConstrainedRefData, splitRuns ? pdf_idx.at(n) : 2, 0); + leParameters->fix_param_from_rootfile(ParamInitFileRefData, toBeFixedRefData, splitRuns ? pdf_idx.at(n) : 2, 0); + } + + //Make sure the B mass range is correct + leParameters->m_b.set_min(B_MASS_LOW); + leParameters->m_b.set_max(B_MASS_HIGH); + + + //Init the ratio of sigmas in signal MC/reference MC + if (!fitReference) leParameters->m_sigma_1.init_fixed(leParameters->m_sigma_1.get_value()*get_sigmaRatio_fromMC(pars,nBins,b,pdf_idx.at(n))); + //I don't trust the m_scale + + + //Init background + leParameters->init_mass_background_parameters(nBins, b, opts.fit_lambda); + + //define center of q2bin as effective q2: + leParameters->eff_q2.init_fixed(bin_center_q2(opts,b)); + + //Init the Kstar mass fit + if(opts.fit_mkpi || opts.use_mkpi){ + //p-wave; + leParameters->init_mkpi_pWave_parameters(fitReference,0.001); + leParameters->init_kpi_background_parameters(fitReference,0.05); + + //s-wave + leParameters->FS.init(0.055, 0.00, 0.5, 0.001); //David got 0.055 + leParameters->init_mkpi_sWave_parameters(fitReference, 0.0); //Fix it, otherwise it doesn't converge + } + + //Control print of the parameters + //leParameters->print_parameters(false); + + //Save the parameters and PDF per bin + leParameters->take_current_as_start(); + theParams[b].push_back(leParameters); + theProbs [b].push_back(lePDF); + spdlog::info("[PDF{0:d}]\tSaved PDF and parameters!", pdf_idx.at(n)); + + //create vector with events according to the requested fits/pulls + std::vector *leEvents= new std::vector; + //Loop over events + spdlog::debug("Loop over events"); + + for (auto meas: events.at(n)){ + if(meas.m < opts.m_low || meas.m > opts.m_high) continue; + if(pars.polarity==1 && meas.magnet > 0) continue; + if(pars.polarity==-1 && meas.magnet < 0) continue; + if(meas.q2 < opts.TheQ2binsmin.at(b) || meas.q2 > opts.TheQ2binsmax.at(b)) continue; + leEvents->push_back(meas); + } + //Update efficiencies (aka take into account angular parametrization weights) ONCE + lePDF->load_coeffs_eff_phsp_4d(); + lePDF->update_cached_normalization(leParameters); + lePDF->update_cached_efficiencies(leParameters, leEvents); + + spdlog::info("[PDF{0:d}]\tFinished selecting the events: {1:d}",n, leEvents->size()); + + //save event vector in vector + selection[b].push_back(leEvents); + if(selection[b].back()->size() > 0){ + spdlog::info("[PDF{0:d}]\t[BIN{1:d}]\tDone!", n, b); + } + else{ + spdlog::critical("No events found for PDF={0:d} and q2 bin={1:d}. Exit!",n,b); + assert(0); + } + + } //End loop over bins + opts.update_efficiencies = false; //Prevent the weights to be applied several more times in fitter::fit + + theOptions[n] = opts; + //Allocate the plotter... sigh #ItIsn'tThe90sAnymore + thePlotter[n] = new fcnc::bu2kstarmumu_plotter(&theOptions[n]); + }//end loop over PDFs + + //-------------------------------- + // FIT + //-------------------------------- + spdlog::info("[MASSFIT]\tMass fit started."); + + //Measure the time for the fit: + runTime timer = runTime(); + + //Save the fit results + std::vectorfit_results[nBins]; + std::vectorf_sigs[nBins]; + std::vectorf_sigserr[nBins]; + std::vector bkg_int_full_range[nBins]; //Not really used + std::vectorevts_cntr[nBins]; + + //fit per bins: + for(unsigned int b = 0; b < nBins; b++){ + + //Start the clock + timer.start(); + time_t startTime = time(0); + spdlog::info("[START]\tStart the fit for bin #{0:d}", b); + + std::string tag = get_MassFit_label(fitReference, b,nBins, splitRuns, pars, 0); + clear_Latex_noteFile(latex_fitterFile(tag)); + spdlog::info("[FIT]\tRunning the fitter..."); + fit_results[b].push_back(f.fit(theProbs[b], theParams[b], selection[b], tag)); + spdlog::info("Q2BIN={0:d}\tLLH={1:f}", b, f.likelihood()); + + //Stop the clock + timer.stop(startTime); + + //save signal fraction and event number for each bin and each pdf: + for(UInt_t n = 0; n < nPDFs; n++){ + f_sigs[b] .push_back(((fcnc::bu2kstarmumu_parameters *) theParams[b].at(n))->f_sig.get_value()); + f_sigserr[b].push_back(((fcnc::bu2kstarmumu_parameters *) theParams[b].at(n))->f_sig.get_error()); + evts_cntr[b].push_back(selection[b].at(n)->size()); + //integrate the background pdf over the range [opts.m_min; opts.m_max] to estimate the background contribution in each q2bin: + bkg_int_full_range[b].push_back(((fcnc::bu2kstarmumu_pdf*)theProbs[b].at(n))->integral_m_bkg_prob((fcnc::bu2kstarmumu_parameters*)theParams[b].at(n),B_MASS_LOW, B_MASS_HIGH)); + } + + + //Plot everything + bool sigRegion = true; //Plot only in the signal region + for(UInt_t n = 0; n < nPDFs; n++){ + tag = get_MassFit_label(fitReference, b,nBins, splitRuns, pars, pdf_idx.at(n)); + theOptions[n].plot_label = "LHCb data"; + theOptions[n].q2_label =q2_label(opts.TheQ2binsmin.at(b), opts.TheQ2binsmax.at(b)); + + if (nPDFs>1){ //If only one PDF, just plot the "added pdfs" + spdlog::info("[PLOT]\t"+theOptions[n].plot_label); + thePlotter[n]->plot_data((fcnc::bu2kstarmumu_pdf*)theProbs[b].at(n), + (fcnc::bu2kstarmumu_parameters*)theParams[b].at(n), + selection[b].at(n), get_MassFitPlot_path(),tag, sigRegion); + } + } + //Plot joint result + std::vector * prober = (std::vector *) & theProbs[b]; + std::vector * paramser = (std::vector *) & theParams[b]; + + tag = get_MassFit_label(fitReference, b,nBins, splitRuns, pars, pars.Run); + thePlotter[0]->plot_added_pdfs(prober, paramser, &selection[b], + get_MassFitPlot_path(), tag, sigRegion); + }//end bin loop + + //Plot the significances and yields in the fancy plot + //TODO: unhardcode the runs + if (!fitReference && nBins>1){ + std::string tag = get_MassFit_label(fitReference, -1,nBins, splitRuns, pars, 12); + spdlog::info("Saving yield plots into " + tag); + thePlotter[0]->plotYieldInQ2(true, theParams, theProbs, nPDFs, evts_cntr, get_MassFitPlot_path(), tag); + thePlotter[1]->plotYieldInQ2(false, theParams, theProbs, nPDFs, evts_cntr, get_MassFitPlot_path(), tag); + } + + //-------------------------------- + // Print & Save + //-------------------------------- + + //Print running time + timer.print(nBins); + + //Print all fit results + print_all_parameters(nBins, pdf_idx, theParams, spdlog::level::debug); + + //Save the fit results + for(unsigned int b = 0; b < nBins; b++){ + for(UInt_t i = 0; i < pdf_idx.size(); i++){ + std::vector * paramser = (std::vector *) & theParams[b]; + std::string results_file = get_MassFitResult_path()+ "fitresult_" + +get_MassFit_label(fitReference, b, nBins, splitRuns, pars, pars.Run)+ ".txt"; + paramser->at(i)->save_param_values(results_file); + } + } + + //Print signal yield in the terminal and to a tex file + if (!Blind){ + print_sig_yields(nBins, pdf_idx, evts_cntr, f_sigs, f_sigserr); + print_bkg_yields(nBins, pdf_idx, evts_cntr, f_sigs, f_sigserr); + } + print_sig_yields_tex(get_MassFit_label(fitReference, -1,nBins, + splitRuns, pars, pars.Run), + nBins, pdf_idx, &opts, evts_cntr, f_sigs, f_sigserr); + + + //Save results to root file + std::string results_file = final_result_name_mass(fitReference, nBins, splitRuns, pars, pars.Run); + save_results(results_file, nBins, pdf_idx, fit_results, theParams, true, &opts); + + //Close Latex file + myFile.close(); + + spdlog::info("[MASSFIT]\tMass fit finished."); + return 0; +} diff --git a/Code/FCNCFitter/sources/Run/massfit.hh b/Code/FCNCFitter/sources/Run/massfit.hh new file mode 100644 index 0000000..e26441a --- /dev/null +++ b/Code/FCNCFitter/sources/Run/massfit.hh @@ -0,0 +1,11 @@ +//Renata Kopecna + +#ifndef MASSFIT_H +#define MASSFIT_H + +#include +#include + +int massfit(fcnc::options opts, bool fitReference, bool splitRuns, basic_params pars); + +#endif // MASSFIT_H diff --git a/Code/FCNCFitter/sources/Run/mcfit.cc b/Code/FCNCFitter/sources/Run/mcfit.cc new file mode 100644 index 0000000..93b5ea0 --- /dev/null +++ b/Code/FCNCFitter/sources/Run/mcfit.cc @@ -0,0 +1,388 @@ +//Renata Kopecna + +#include "mcfit.hh" + +#include +#include +#include +#include +#include +#include +#include +#include + +int mcfit_4D(fcnc::options opts, bool fitReference, bool fitPHSP, basic_params params){ + + //-------------------------------- + // Sanity checks + //-------------------------------- + + if (params.Run != 1 && params.Run != 2 && params.Run != 12){ + spdlog::error("Wrong run selected! Please use either 1, 2 or 12 for fititng the MC!"); + return 1; + } + //-------------------------------- + // Set constants + //-------------------------------- + if(fitReference) spdlog::info("[MCFIT]\tFit reference channel: J/psi K*+"); //reference channel only + else spdlog::info("[MCFIT]\tFit signal MC");//signal MC only + + const bool Blind = false; //False as it is MC, HAS TO BE TRUE FOR DATA + const bool UseBinnedFit = true; //Use bins in q2, if false, nBins is forced to be one + const bool SimultaneousFit = true; //Simultanously fit all PDFs + const bool fixBMass = false; //Fix B mass to PDG value + const bool plotPulls = true; //Do you wanna pull plots with or without pulls? + + int prescale = 1; //The fraction of events to be kept + //Eg if prescale = 3, only a third of events will be kept + //This is not EXACTLY a third though, but a third from all the possible events, + //as this is taken from the loaded events, not from the selected events + //In an extreme case when eg prescale is 2, only MagDown is to be fitted and every second event + //is MagDown, all events would be still kept. + //To use all the events, set it to 1 + + //Scales for the fit parameters (meaning fit-ranges) + double PprimeRangeScale = 10.0; + double angleRange = +1.0; + if (params.usePprime) angleRange *= PprimeRangeScale; + double angleStepSize = 0.01; + + if (!UseBinnedFit){ + spdlog::info("Running an unbinned fit"); + opts.TheQ2binsmin = get_TheQ2binsmin(1,fitReference); + opts.TheQ2binsmax = get_TheQ2binsmax(1,fitReference); + } + const unsigned int nBins = opts.get_nQ2bins(); //unsigned because vector.size is unsigned + spdlog::debug("Using {0:d} q2 bins.", nBins); + + //-------------------------------- + // Set all options + //-------------------------------- + opts.use_mkpi = false; //5D fit + opts.fit_mkpi = false; //4D+1 fit + + opts.full_angular = (params.folding ==-1); + opts.folding = params.folding; + //TODO: this needs to be fixed, it is written like for idiots + if(opts.fit_mkpi || opts.use_mkpi){ + opts.only_Bmass = false; + opts.only_mass2DFit = fitReference; + } + bool dontFitAngles = fitReference; + + opts.swave = false; + opts.multiply_eff = true; //MC weights need to be taken into account + opts.weighted_fit = true; //Needed to plot the weights properly + opts.use_event_norm = false; //Used for convoluting the acceptance into pdf + + //Set the plot folder + opts.plot_folder = get_MCfitPlot_path(fitReference, fitPHSP); + + //Set the available PDFs: this depends on the selected Run for now, so if only one is selected, run over one pdf, if both, use two + std::vector pdf_idx; + if (params.Run == 1 || params.Run == 12) pdf_idx.push_back(1); + if (params.Run == 2 || params.Run == 12) pdf_idx.push_back(2); + + //-------------------------------- + // Load data + //-------------------------------- + spdlog::info("[MCFIT]\tLoading data..."); + std::vector>events; + + if (opts.run == 1 || opts.run == 12){ + events.push_back(fcnc::load_events(get_theFCNCpath(MC_dataset(fitReference,fitPHSP),1), "Events", -1)); + } + if (opts.run == 2 || opts.run == 12){ + events.push_back(fcnc::load_events(get_theFCNCpath(MC_dataset(fitReference,fitPHSP),2), "Events", -1)); + } + + + //check that the number of pdfs is the same as number of event vectors + if (pdf_idx.size() != events.size()){ + spdlog::error("Something went very wrong when loading the events and setting the pdfs."); + spdlog::error("The number of PDFs!= number of event vectors: {0:d} vs {1:d}",pdf_idx.size(), events.size()); + return 5; + } + //we are good to go, now; how many individual pdfs are used? + const UInt_t nPDFs = pdf_idx.size(); + + UInt_t N_tot = 0; + for (UInt_t n = 0; n < nPDFs; n++){ + spdlog::debug("Event vector {0:d}:\t"+(Blind?"Larger 1 ":std::to_string(events.at(n).size())),n); + if (events.at(n).size()==0){ + spdlog::error("Empty event vector!"); + return 404; + } + N_tot += events.at(n).size(); + } + spdlog::info("Total number of used events:\t{0:d}", N_tot); + + //Initialize all needed things for the fit + //current fitter, plotter, parameteres and pdfs: + fcnc::fitter f(&opts); + fcnc::folder fldr(&opts); + fcnc::options theOptions[nPDFs]; + fcnc::bu2kstarmumu_plotter * thePlotter[nPDFs]; + std::vector theParams [nBins]; + std::vector theProbs [nBins]; + std::vector< std::vector*> selection[nBins]; + + //Initialize common parameters //Includes sWave if opts.swave is on + std::vector common_params = param_string(opts, true); + if(SimultaneousFit) f.set_common_parameters(common_params); + spdlog::info("Shared parameters: " + convert_vector_to_string(common_params)); + + //-------------------------------- + // Read events + //-------------------------------- + + //Loop over PDFs and initialize parameters + for(unsigned n = 0; n < nPDFs; n++){ + opts.run = pdf_idx.at(n); //Set proper run to options + spdlog::debug("Run {0:d}", opts.run); + opts.name = get_MCfit_label(fitReference, fitPHSP, nBins, -1, SimultaneousFit, params, opts.run, opts.only_angles, dontFitAngles); + opts.update_angle_ranges(); //Set angles in options back to defaults + opts.update_efficiencies = true; //This ensures the acceptance weights to be taken into account. + //It needs to be set properly as the MC needs to take into account the MC-data weights and hence the weight multiplication is on. However, the weights are recalculated later on (see fitter::fit and fitter::init), so they need to be turned off after loading the efficiencies. + + //Set the label to MC + opts.plot_label = "LHCb MC"; + + //Loop over bins now + for(unsigned int b = 0; b < nBins; b++){ + opts.q2_min = opts.TheQ2binsmin.front(); + opts.q2_max = opts.TheQ2binsmax.back(); + + //Create parameter set + fcnc::bu2kstarmumu_parameters * leParameters = new fcnc::bu2kstarmumu_parameters(&opts); + //create PDF + fcnc::bu2kstarmumu_pdf * lePDF = new fcnc::bu2kstarmumu_pdf(&opts, leParameters); + + //Initialize basic parameters + //define center of q2bin as effective q2 + leParameters->eff_q2.init_fixed( bin_center_q2(opts,b)); + leParameters->f_sig.init_fixed(1.0); + + if (!opts.only_angles){ //If not fitting the angles ONLY, init the mass parameters + leParameters->init_mass_parameters(n,nBins,b,0.01); + leParameters->m_b.init(PDGMASS_B_PLUS, B_MASS_LOW, B_MASS_HIGH, fixBMass ? 0.0: 1.0); + if (!fitReference && !fitPHSP){ + std::string file = final_result_name_MC(params, 1, true, false, true, false, true); + leParameters->fix_param_from_rootfile(file, {"alpha_1","alpha_2","n_1","n_2"}, pdf_idx.at(n), 0); + } + leParameters->m_scale.init_fixed(1.0); //Scale of sigma between the signal/ref MC, used in the data mass fit + } + + if (!dontFitAngles){ + leParameters->init_angular_parameters(nBins,b,angleStepSize,angleRange, Blind); + } + + + //TODO: DELETE: only for testing the folding + //double FLinit[4] = {0.662,0.689,0.444,0.357}; + //if (params.folding == 4) leParameters->Fl.init_fixed(FLinit[b]);//,0.0,1.0,0.05); + //if (params.folding == 4) leParameters->S8.init_fixed(0.0); + if (!fitReference && !fitPHSP){ + std::string file = final_result_name_MC(params, 1, true, false, true, false, true); + leParameters->fix_param_from_rootfile(file, {"alpha_1","alpha_2","n_1","n_2"}, pdf_idx.at(n), 0); + } + //Kpi mass p-wave + if(opts.fit_mkpi || opts.use_mkpi){ + leParameters->init_mkpi_pWave_parameters(fitReference,0.001); + } + //make sure all configured values are also the start_value: + leParameters->take_current_as_start(); + + theParams[b].push_back(leParameters); + theProbs [b].push_back(lePDF); + spdlog::info("[PDF{0:d}]\tSaved PDF and parameters!", pdf_idx.at(n) ); + + //create vector with events according to the requested fits/pulls + std::vector *leEvents= new std::vector; + + //Loop over events + spdlog::debug("Loop over events"); + for_indexed(auto meas: events.at(n)){ + theOptions[n].update_angle_ranges(); //Update angle ranges based on the folding + //Reject events in the case prescale is used + if (prescale>1 && i%prescale!=0) continue; + //Select either magUp or magDown + if(params.polarity==1 && meas.magnet > 0) continue; + if(params.polarity==-1 && meas.magnet < 0) continue; + if(meas.q2 < opts.TheQ2binsmin.at(b) || meas.q2 > opts.TheQ2binsmax.at(b)) continue; + if(meas.mkpi < opts.mkpi_min || meas.mkpi > opts.mkpi_max) continue; + if(meas.m < B_MASS_LOW || meas.m > B_MASS_HIGH) continue; + if(!filterFldFour(&meas, &theOptions[n])) continue; //remove ctk events + if(!opts.full_angular) fldr.fold(&meas); + leEvents->push_back(meas); + } + + //Update efficiencies (aka take into account angular parametrization weights) ONCE + lePDF->load_coeffs_eff_phsp_4d(); + lePDF->update_cached_normalization(leParameters); + lePDF->update_cached_efficiencies(leParameters, leEvents); + opts.update_angle_ranges(); + spdlog::info("[PDF{0:d}]\tFinished selecting the events: {1:d}",n, leEvents->size()); + //save event vector in vector + selection[b].push_back(leEvents); + if(selection[b].back()->size() > 0){ + spdlog::info("[PDF{0:d}]\t[BIN{1:d}]\tDone!", n, b); + } + else{ + spdlog::critical("No events found for PDF={0:d} and q2 bin={1:d}. Exit!",n,b); + assert(0); + } + + } //End loop over bins + opts.update_efficiencies = false; //Prevent the weights to be applied several more times in fitter::fit + + theOptions[n] = opts; + //Allocate the plotter... sigh + thePlotter[n] = new fcnc::bu2kstarmumu_plotter(&theOptions[n]); + + }//end loop over PDFs + + //-------------------------------- + // FIT + //-------------------------------- + spdlog::info("[MCFIT]\tMC fit started."); + + //Measure the time for the fit: + runTime timer = runTime(); + + //Save the fit results + std::vectorfit_results[nBins]; + std::vectorf_sigs[nBins]; + std::vectorf_sigserr[nBins]; + std::vectorevts_cntr[nBins]; + + //fit all bins: + for(unsigned int b = 0; b < nBins; b++){ + + //Start the clock + timer.start(); + time_t startTime = time(0); + + spdlog::info("[START]\tStart the fit for bin #{0:d}", b); + + //Int for fit status + int fitresult = 0; + + if(!SimultaneousFit){ + for(UInt_t n = 0; n < nPDFs; n++){ + + //Delete the texFile + std::string tag = get_MCfit_label(fitReference, fitPHSP, + nBins, b, + SimultaneousFit, params, theOptions[n].run, + opts.only_angles, dontFitAngles); + + clear_Latex_noteFile(latex_fitterFile(tag)); + + spdlog::info("[FIT{0:d}]\tRunning the fitter...", n); + fitresult = f.fit(theProbs[b].at(n), theParams[b].at(n), selection[b].at(n),tag); + fit_results[b].push_back(fitresult); + } + } + else{ + spdlog::info("[FIT]\tFitting simultaenously...."); + //Delete the texFile + std::string tag = get_MCfit_label(fitReference, fitPHSP, + nBins, b, + SimultaneousFit, params, opts.run, + opts.only_angles, dontFitAngles); + clear_Latex_noteFile(latex_fitterFile(tag)); + for(UInt_t s = 0; s < selection[b].size(); s++)spdlog::info("PDF #{0:d}: {1:d}", pdf_idx.at(s), selection[b].at(s)->size()); + fitresult = f.fit(theProbs[b], theParams[b], selection[b],tag); + fit_results[b].push_back(fitresult); + spdlog::info("Q2BIN={0:d}\tLLH={1:f}", b, f.likelihood()); + if(params.likelyhood){ + spdlog::error("TODO."); + return 5; + } + if(params.FeldCous){ + spdlog::error("TODO."); + return 5; + } + } + + //Stop the clock + timer.stop(startTime); + + //Print the fit results + spdlog::info("[BIN{0:d}]:\tFitresult: {1:d}", b, fitresult); + + //save signal fraction and event number for each bin and each pdf: + for(UInt_t n = 0; n < nPDFs; n++){ + f_sigs[b] .push_back(((fcnc::bu2kstarmumu_parameters *) theParams[b].at(n))->f_sig.get_value()); + f_sigserr[b].push_back(((fcnc::bu2kstarmumu_parameters *) theParams[b].at(n))->f_sig.get_error()); + evts_cntr[b].push_back(selection[b].at(n)->size()); + } + + //Plot everything + for(UInt_t n = 0; n < nPDFs; n++){ + std::string eps_label = get_MCfit_label(fitReference, fitPHSP, + nBins, b, + SimultaneousFit, params, theOptions[n].run, + opts.only_angles, dontFitAngles); + theOptions[n].q2_label = q2_label(theOptions[n].TheQ2binsmin.at(b), theOptions[n].TheQ2binsmax.at(b)); + spdlog::info("[PLOT]\t"+eps_label); + thePlotter[n]->SetPulls(plotPulls); + thePlotter[n]->plot_data((fcnc::bu2kstarmumu_pdf*)theProbs[b].at(n), + (fcnc::bu2kstarmumu_parameters*)theParams[b].at(n), + selection[b].at(n), + get_MCfitPlot_path(fitReference, fitPHSP), eps_label, false); + } + + std::string eps_label = get_MCfit_label(fitReference, fitPHSP, + nBins, b, + SimultaneousFit, params, params.Run, + opts.only_angles, dontFitAngles); + if (!plotPulls) eps_label = eps_label+"_noPulls"; + + std::vector * prober = (std::vector *) & theProbs[b]; + std::vector * paramser = (std::vector *) & theParams[b]; + thePlotter[0]->SetPulls(plotPulls); + thePlotter[0]->plot_added_pdfs(prober, paramser, &selection[b], + get_MCfitPlot_path(fitReference, fitPHSP),eps_label, false); + + } //end bin loop + + + //-------------------------------- + // Print & Save + //-------------------------------- + + //Print running time + timer.print(nBins); + + //Print all fit results + print_all_parameters(nBins, pdf_idx, theParams, spdlog::level::debug); + + + //Save the fit results + for(unsigned int b = 0; b < nBins; b++){ + for(UInt_t i = 0; i < pdf_idx.size(); i++){ + std::vector * paramser = (std::vector *) & theParams[b]; + paramser->at(i)->save_param_values(finalResult_MCfit_txt(i,fitReference,fitPHSP, nBins, b, SimultaneousFit, params, params.Run, opts.only_angles, dontFitAngles)); + + } + } + + //Print signal yield in the terminal and to a tex file + if (!Blind) print_sig_yields(nBins, pdf_idx, evts_cntr, f_sigs, f_sigserr); + + print_sig_yields_tex(get_MCfit_label(fitReference, fitPHSP, + nBins, -1, + SimultaneousFit, params, params.Run, + opts.only_angles, dontFitAngles), + nBins, pdf_idx, theOptions, evts_cntr, f_sigs, f_sigserr); + + //Save results to root file + std::string results_file = final_result_name_MC(params, nBins, fitReference, fitPHSP, SimultaneousFit, opts.only_angles, dontFitAngles); + save_results(results_file, nBins, pdf_idx, fit_results, theParams, SimultaneousFit, &opts); + + spdlog::info("[MCFIT]\tMC fit finished."); + return 0; + +} diff --git a/Code/FCNCFitter/sources/Run/mcfit.hh b/Code/FCNCFitter/sources/Run/mcfit.hh new file mode 100644 index 0000000..fedbc88 --- /dev/null +++ b/Code/FCNCFitter/sources/Run/mcfit.hh @@ -0,0 +1,11 @@ +//Renata Kopecna + +#ifndef MCFIT_HH +#define MCFIT_HH + +#include +#include + +int mcfit_4D(fcnc::options opts, bool fitReference, bool fitPHSP, basic_params params); + +#endif // MCFIT_HH diff --git a/Code/FCNCFitter/sources/Run/momfit.cc b/Code/FCNCFitter/sources/Run/momfit.cc new file mode 100644 index 0000000..dc2e9d0 --- /dev/null +++ b/Code/FCNCFitter/sources/Run/momfit.cc @@ -0,0 +1,1324 @@ +//Renata Kopecna + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +//background coefficients, obtained from fits to the sideband data of the rare channel (David thinks) +//4 cause David had 4 PDFs +const double Bctl1[4] = { 0.11700, -0.0568, 0.0367, 0.0160}; +const double Bctl2[4] = {-0.0697, -0.1243, -0.0788, -0.1197}; +const double Bctk1[4] = { 0.0720, 0.4544, 0.0761, 0.2105}; +const double Bctk2[4] = { 0.1652, 0.2065, 0.1177, 0.1951}; + +//Obtained from MC //TODO //Taken from main fit, update when fixed +const double f_m_B[4] = {5282.32, 5282.08, 5278.57, 5279.48}; +const double f_lambda1[4] = {-0.00386, -0.00610, -0.00362, -0.00578}; +const double f_lambda2[4] = {-0.03320, -0.00120, -0.04600, -0.00100}; +const double f_alpha_1[4] = { 1.7910, 1.8000, 1.6510, 1.5400}; +const double f_alpha_2[4] = { 2.3200, 2.4300, 2.0100, 2.2500}; +const double f_n_1[4] = { 1.4400, 1.4900, 1.6800, 1.6100}; +const double f_n_2[4] = { 2.8900, 3.7000, 3.8700, 3.7000}; +const double f_sigma_1[4] = {14.8300, 15.4800, 14.8400, 14.4}; +const double f_sigma_2[4] = {14.0700, 13.1000, 15.6200, 13.3}; +const double f_f_CB[4] = { 0.6360, 0.3600, 0.3040, 0.6200}; +const double f_m_scale[4] = { 1.1814, 1.0648, 1.1547, 1.1168}; +//Obtained from MC //TODO //Taken from main fit, update when fixed +///including the first q2bin: //TODO: get from my MC +const std::vector FL_scale = {0.4836193455050577, 1.2251014138607774, 1.274499551405837, 1.1368614009399862}; + +//Obtained from MC //TODO //Taken from main fit, update when fixed +const std::vector FL_scale_toys = { //TODO Get from my MC! + 0.5, //scaled from average of bin 1-4 + 1.0 + 0.07 / (61.*4) * (61.+ 62.+ 96.+ 125.), + 1.0 + 0.12 / (62.*4) * (61.+ 62.+ 96.+ 125.), + 1.0 - 0.02 / (96.*4) * (61.+ 62.+ 96.+ 125.), + 1.0 - 0.17 / (125.*4) * (61.+ 62.+ 96.+ 125.), + 1.0,//evaluated by itself + 1.0 + 0.04 / (129. * 2) * (129. + 69.), + 1.0 - 0.04 / (69. * 2) * (129. + 69.), +}; + + + + +//TODO: not used at the moment, check for constants and everything before usage + + +int momfit(fcnc::options opts, + bool fitReference, bool fitSignalMC, bool fitData, bool blind, + bool Fit1bin, bool Fit2bins, bool FitAllbins){ + + if (fitReference) spdlog::info("[MOM]\t\tMoM from reference channel: J/psi K*+"); + // (jobs_to_do[7]) //reference channel only + if (fitSignalMC) spdlog::info("[MOM]\t\tMoM from signal fitSignalMC"); + //if(jobs_to_do[8]) //signal fitSignalMC only + if (fitData) spdlog::info("[MOM]\t\tMoM signal data"); + // if(jobs_to_do[9]) //signal data << FINAL FIT!! + //const bool blind = jobs_to_do[9]; + + //have extra option for the usage of binning: + const bool SimultaneousMoM = fitReference; + const bool SimultaneousFit = true; + const bool UseAccPerRun = true; + const bool UseAccPer2Years = true; + const bool LargeBinning = !fitSignalMC && !fitReference && !fitData; + const bool WeightedFit = true; + const bool OnlyBackground = false; + const bool OnlySignal = false; + const bool OneFit = !fitSignalMC && !fitReference && !SimultaneousFit; + const bool FitR = fitReference; + const bool SystematicsWithToys = opts.systematic == 0; + if (!fitSignalMC && SystematicsWithToys){ + spdlog::critical("Cannot run data AND generate toys for systematics!"); + return 2; //TODO: decide what error is for wrong parameters + } + const bool FitFinalToySamples = false; + const bool FSfrom2DLargeBins = !fitSignalMC && !fitReference && !LargeBinning && !SystematicsWithToys && !FitFinalToySamples; + + const bool UseExternalFS = true; + const bool FixFStoStart = false; + const bool FitOnlyMagDown = opts.job_id == 3 && !SystematicsWithToys; + const bool FitOnlyMagUp = opts.job_id == 4 && !SystematicsWithToys; + + const bool LargerMKpiRange = false; + + const bool NP = false; + + //TODO: big time, go through the couts and the constants here + if(!fitReference && !fitSignalMC) opts.plots_m_bins = 50; + + assert(!OneFit || !SimultaneousMoM); + + if(fitReference){ + opts.TheQ2binsmin = {8.68}; + opts.TheQ2binsmax = {10.09}; + } + else if(LargeBinning){ + opts.TheQ2binsmin = {1.0, 11.0, 15.0}; + opts.TheQ2binsmax = {8.0, 12.5, 19.0}; + } + if(fitSignalMC && !fitReference){ //Fit also Jpsi region in fitSignalMC + opts.TheQ2binsmin.push_back(8.68); + opts.TheQ2binsmax.push_back(10.09); + } + + if(LargerMKpiRange){ + opts.mkpi_min -= 50.; + opts.mkpi_max += 50.; + } + + opts.write_eps = !(FitOnlyMagDown || FitOnlyMagUp || SystematicsWithToys || FitFinalToySamples); + opts.write_C = !(FitOnlyMagDown || FitOnlyMagUp || SystematicsWithToys || FitFinalToySamples); + + //configurate for 2D mass fit to obtain sWeights + opts.only_mass2DFit = true; + opts.only_angles = false; + opts.only_Bmass = false; + opts.squared_hesse = !fitData; + opts.minos_errors = false; + opts.weighted_fit = WeightedFit; + opts.fit_mkpi = true; + opts.use_mkpi = false; + opts.generate_mkpi = true; + opts.simple_mkpi = false; + opts.isobar = false; + opts.shift_lh = false; + opts.swave = (opts.use_mkpi || opts.fit_mkpi) && !(fitSignalMC || OnlyBackground); + opts.extended_ml = !fitSignalMC && !OnlyBackground && !OnlySignal; //extended maximum likelyhood + //Needed for sWeights + + opts.fit_fl = !fitData && SystematicsWithToys; + opts.fit_afb = opts.fit_fl; + + opts.full_angular = true; + + //how many individual pdfs are used? + const UInt_t nPDFs = 2; + + std::vector< std::string > samplename; + samplename.push_back("Run1 DD"); //TODO + samplename.push_back("Run1 LL"); + samplename.push_back("Run2 DD"); + samplename.push_back("Run2 LL"); + + //load events from data tuple: + std::vectorevents[nPDFs]; + //TODO + if(FitFinalToySamples){ + events[0] = fcnc::load_events(get_finalToySamplePath(0,opts.job_id,fitReference), "Events", -1); //Run1 + events[1] = fcnc::load_events(get_finalToySamplePath(1,opts.job_id,fitReference), "Events", -1); //Run2 + } + else{ + events[0] = fcnc::load_events(get_theFCNCpath(fitSignalMC,1), "Events", -1); //Run1 + events[1] = fcnc::load_events(get_theFCNCpath(fitSignalMC,2), "Events", -1); //Run2 + } + + spdlog::info("Events:"); + for(UInt_t n = 0; n < nPDFs; n++){ + std::cout << samplename.at(n) << ":\t" << (blind ? "Larger 1 " : std::to_string(events[n].size())) << std::endl; + assert(events[n].size() || SystematicsWithToys); + } + + TRandom3 * rnd = new TRandom3(0); + + //determine number of bins: + const UInt_t nBins = opts.TheQ2binsmin.size(); + std::vectorfit_results[nBins]; + std::vectorfitted_FS[nBins]; + std::vectorfitted_FSerr[nBins]; + std::vectorfitted_FSerrUp[nBins]; + std::vectorfitted_FSerrDown[nBins]; + + //signal event number estimations: + double N_sig_Rare[8] = {101., 61., 62., 96., 125., 124., 129., 69.}; + double N_bkg_Rare[8] = {131., 206., 279., 358., 358., 247., 158., 93.}; + //estimation of how many events lie within each sub-set: Run I DD, Run I LL, Run II DD, Run II LL. taken from jpsi! + double ev_frac[4] = {0.14, 0.09, 0.46, 0.30}; + if(OneFit) + ev_frac[0] = 1.0; + + //TODO whyyyy is this all here + std::vector s1s, s1c, s2s, s2c, s3, s4, s5, s6s, s6c, s7, s8, s9; + if(nBins == 9){ + s1s = { 0.5010, 0.1660, 0.1270, 0.1760, 0.2570, 0.3910, 0.4670, 0.4930, 0.329}; + s1c = { 0.2450, 0.6996, 0.7993, 0.7384, 0.6414, 0.4201, 0.3513, 0.3344, 0.000}; + s2s = { 0.1448, 0.0749, 0.0514, 0.0662, 0.0900, 0.1449, 0.1620, 0.1662, 0.000}; + s2c = {-0.1953,-0.6639,-0.7774,-0.7254,-0.6334,-0.4171,-0.3497,-0.3332, 0.000}; + s3 = { 0.0110,-0.0030, 0.0010,-0.0100,-0.0330,-0.0520,-0.1460,-0.2240,-0.006}; + s4 = { 0.0050, 0.0100,-0.1140,-0.1970,-0.2530,-0.2620,-0.2910,-0.2980,-0.244}; + s5 = { 0.2330, 0.0730,-0.1630,-0.3100,-0.4130,-0.4430,-0.3410,-0.2570, 0.000}; + s6s = {-0.0650,-0.1950,-0.0860, 0.0950, 0.2930, 0.4920, 0.5410, 0.4650, 0.000}; + s6c = { 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.000}; + s7 = { 0.0030, 0.0350, 0.0120, 0.0080,-0.0110, 0.0150,-0.0140, 0.0130, 0.000}; + s8 = {-0.0050, 0.0060,-0.0040,-0.0050,-0.0120, 0.0160, 0.0010, 0.0060,-0.060}; + s9 = {-0.0220, 0.0010,-0.0020,-0.0090, 0.0130, 0.0010, 0.0100, 0.0000,-0.084}; + } + else if(nBins == 8){ + //results from signal channel generator level fitSignalMC fit + s1s = { 0.5120, 0.1800, 0.1370, 0.1930, 0.2750, 0.4170, 0.4840, 0.5030}; + s1c = { 0.2450, 0.6996, 0.7993, 0.7384, 0.6414, 0.4201, 0.3513, 0.3344}; + s2s = { 0.1448, 0.0749, 0.0514, 0.0662, 0.0900, 0.1449, 0.1620, 0.1662}; + s2c = {-0.1953,-0.6639,-0.7774,-0.7254,-0.6334,-0.4171,-0.3497,-0.3332}; + s3 = { 0.0000, 0.0020,-0.0080,-0.0120,-0.0240,-0.0620,-0.1520,-0.2330}; + s4 = { 0.0870, 0.0040,-0.1080,-0.1950,-0.2510,-0.2770,-0.2900,-0.3040}; + s5 = { 0.2440, 0.0950,-0.1590,-0.3050,-0.4140,-0.4210,-0.3400,-0.2490}; + s6s = {-0.1270,-0.2070,-0.0860, 0.0950, 0.3020, 0.5140, 0.5570, 0.4700}; + s6c = { 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000}; + s7 = {-0.0060,-0.0100,-0.0030, 0.0020, 0.0030,-0.0020,-0.0020, 0.0050}; + s8 = { 0.0010,-0.0030,-0.0040,-0.0030,-0.0010, 0.0030,-0.0010, 0.0030}; + s9 = {-0.0020, 0.0000, 0.0020, 0.0040,-0.0020,-0.0010,-0.0010, 0.0010}; + /* OLD MoM start values + s1s = { 0.5010, 0.1660, 0.1270, 0.1760, 0.2570, 0.3910, 0.4670, 0.4930}; + s1c = { 0.2450, 0.6996, 0.7993, 0.7384, 0.6414, 0.4201, 0.3513, 0.3344}; + s2s = { 0.1448, 0.0749, 0.0514, 0.0662, 0.0900, 0.1449, 0.1620, 0.1662}; + s2c = {-0.1953,-0.6639,-0.7774,-0.7254,-0.6334,-0.4171,-0.3497,-0.3332}; + s3 = { 0.0110,-0.0030, 0.0010,-0.0100,-0.0330,-0.0520,-0.1460,-0.2240}; + s4 = { 0.0050, 0.0100,-0.1140,-0.1970,-0.2530,-0.2620,-0.2910,-0.2980}; + s5 = { 0.2330, 0.0730,-0.1630,-0.3100,-0.4130,-0.4430,-0.3410,-0.2570}; + s6s = {-0.0650,-0.1950,-0.0860, 0.0950, 0.2930, 0.4920, 0.5410, 0.4650}; + s6c = { 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000}; + s7 = { 0.0030, 0.0350, 0.0120, 0.0080,-0.0110, 0.0150,-0.0140, 0.0130}; + s8 = {-0.0050, 0.0060,-0.0040,-0.0050,-0.0120, 0.0160, 0.0010, 0.0060}; + s9 = {-0.0220, 0.0010,-0.0020,-0.0090, 0.0130, 0.0010, 0.0100, 0.0000}; + */ + + //TODO whyyyy is this all here + if(NP){ + s1s = {0.5602306113691828,0.23270880313206915,0.1882591401081556,0.2360087282257996,0.3049337611889009,0.4271747118350757,0.49093645131734026,0.5057945417334112}; + s1c = { 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000}; + s2s = { 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000}; + s2c = { 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000}; + s3 = {0.010889127654682522,0.002826464227113492,-0.009846207821458525,-0.0236075131233653,-0.03873716522303356,-0.08541706129465602,-0.17283544777091792,-0.2508649715871772}; + s4 = {0.06515621731101214,-0.03441408879881635,-0.14972587209244403,-0.22058159609322783,-0.2569091889106349,-0.28043043274306023,-0.2933132627545414,-0.3090558271133447}; + s5 = {0.28355403122517436,0.15060676750257493,-0.08697300891551848,-0.2453363631814247,-0.3317290913621316,-0.37328734325703,-0.28988943793825117,-0.20704345542879504}; + s6s = {-0.14203502700533388,-0.2517350722752868,-0.12322680301923153,0.05716905988908093,0.22412264548364097,0.4666205500210169,0.48430363375918584,0.38863572446689215}; + s6c = { 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000}; + s7 = {-0.018795316409125306,-0.023477089751902755,-0.019670089562814908,-0.015167436307089688,-0.010845329740737182,-0.002747600804479865,-0.0017200885766387283,-0.0006988704922596641}; + s8 = {-0.010521697907580636,-0.008845120251655493,-0.005715190092060276,-0.004200375084315877,-0.0032359717141892687,0.0016256878486157777,0.0005880437600457862,0.00023165273472761083}; + s9 = {-0.0006861229900257304,-0.0006888890894988537,-0.0006222598407671807,-0.0005993069103744563,-0.0006186949055500562,0.0006613554952330075,0.0004840128898600523,0.0003040455330802454}; + } + } + else if(nBins == 3){ + s1s = { 0.329, 0.329, 0.329}; + s1c = { 0.0, 0.0, 0.0}; + s2s = { 0.0, 0.0, 0.0}; + s2c = { 0.0, 0.0, 0.0}; + s3 = {-0.006, -0.006, -0.006}; + s4 = {-0.244, -0.244, -0.244}; + s5 = {-0.005, -0.005, -0.005}; + s6s = {-0.002, -0.002, -0.002}; + s6c = { 0.0, 0.0, 0.0}; + s7 = { 0.000, 0.000, 0.000}; + s8 = {-0.060, -0.060, -0.060}; + s9 = {-0.084, -0.084, -0.084}; + } + else if(nBins == 2){ + s1s = { 0.1959, 0.4917}; + s1c = { 0.7441, 0.3447}; + s2s = { 0.0646, 0.1636}; + s2c = {-0.7217, -0.3432}; + s3 = {-0.0042, -0.1747}; + s4 = { 0.1033, 0.2929}; + s5 = {-0.1458, -0.3157}; + s6s = { 0.0652, -0.5338}; + s6c = { 0.0000, 0.0000}; + s7 = { 0.0340, -0.0000}; + s8 = {-0.0115, -0.0002}; + s9 = { 0.0003, 0.0003}; + } + else if(nBins == 1){ + s1s = { 0.329}; + s1c = { 0.0}; + s2s = { 0.0}; + s2c = { 0.0}; + s3 = {-0.006}; + s4 = {-0.244}; + s5 = {-0.005}; + s6s = {-0.002}; + s6c = { 0.0}; + s7 = { 0.000}; + s8 = {-0.060}; + s9 = {-0.084}; + } + else{ + spdlog::error("No init values found for S_i in binning scheme with number of q2 bins: {0:d}", nBins); + assert(0); + } + + //current fitter, plotter, parameteres and pdfs: + fcnc::fitter f(&opts); + fcnc::folder fldr(&opts); + + fcnc::options theOptions[nPDFs]; + fcnc::bu2kstarmumu_plotter * thePlotter[nPDFs]; + + std::vector theParams [nBins]; + std::vector the2DParams [nBins]; + std::vector theProbs [nBins]; + std::vector< std::vector* > selection[nBins]; + + std::vector pdf_idx; + pdf_idx.push_back(0); //Run1 DD + pdf_idx.push_back(1); //Run1 LL + pdf_idx.push_back(2); //Run2 DD + pdf_idx.push_back(3); //Run2 LL + + //set parameter FS common: + std::vector common_params; + common_params.push_back("FS"); + if(FitR) + common_params.push_back("R"); + if(!fitReference){ + common_params.push_back("gamkst"); + common_params.push_back("mkst"); + } + f.set_common_parameters(common_params); + + for(UInt_t n = 0; n < nPDFs; n++){ + theOptions[n] = opts; + theOptions[n].name = std::to_string(n+1); + theOptions[n].run = UseAccPerRun ? (n > 1 ? 2 : 1) : 12; + theOptions[n].DDLL = (n % 2 == 0) ? "DD" : "LL"; + theOptions[n].update_angle_ranges(); + + thePlotter[n] = new fcnc::bu2kstarmumu_plotter(&theOptions[n]); + } + + double sig_frac[nBins]; + unsigned int event_numbers[nBins][4]; + for(unsigned int b = 0; b < nBins; b++){ + for(unsigned int n = 0; n < 4; n++){ + //get event numbers and signal fraction from global function, given the total number of events + EventNumbers(b, n, sig_frac[b], event_numbers[b][n], 2597, nBins, 4); + if(OnlySignal) + event_numbers[b][n] *= sig_frac[b]; + } + } + + for(UInt_t b = 0; b < nBins; b++){ + selection[b].clear(); + for(UInt_t n = 0; n < nPDFs; n++){ + //create parameter sets: + fcnc::bu2kstarmumu_parameters * leParameters = new fcnc::bu2kstarmumu_parameters(&theOptions[n]); + + theOptions[n].q2_min = opts.TheQ2binsmin.at(b); + theOptions[n].q2_max = opts.TheQ2binsmax.at(b); + + //create PDFs + fcnc::bu2kstarmumu_pdf * lePDF = new fcnc::bu2kstarmumu_pdf(&theOptions[n], leParameters); + + //initiate parameters for mass fit + if(opts.extended_ml){ + if(fitSignalMC){ + spdlog::error("Never use extended_ml option for a pure signal sample, like in fitSignalMC!"); + assert(0); + } + if(OnlyBackground){ + spdlog::error("Never use extended_ml option for a pure background sample!"); + assert(0); + } + else{ + if((SystematicsWithToys || FitFinalToySamples) && !fitReference){ + leParameters->n_sig.init(event_numbers[b][n]*sig_frac[b], event_numbers[b][n]*sig_frac[b]*0.2, event_numbers[b][n]*sig_frac[b]*5., 0.1); + leParameters->n_bkg.init(event_numbers[b][n]*(1.-sig_frac[b]), event_numbers[b][n]*(1.-sig_frac[b])*0.2, event_numbers[b][n]*(1.-sig_frac[b])*5., 0.1); + leParameters->f_sig.init(sig_frac[b], 0.0, 1.0, 0.0); + } + else if(fitData && !LargeBinning){ + leParameters->n_sig.init(N_sig_Rare[b]*ev_frac[n], 0.0/*N_sig_Rare[b]*ev_frac[n]*0.2*/, N_sig_Rare[b]*ev_frac[n]*5., 0.1); + leParameters->n_bkg.init(N_bkg_Rare[b]*ev_frac[n], N_bkg_Rare[b]*ev_frac[n]*0.2, N_bkg_Rare[b]*ev_frac[n]*5., 0.1); + leParameters->f_sig.init(N_sig_Rare[b]*ev_frac[n]/(N_sig_Rare[b]*ev_frac[n]+N_bkg_Rare[b]*ev_frac[n]), 0.0, 1.0, 0.0); + } + else if(fitData && LargeBinning){ + leParameters->n_sig.init(100., 5., 5000., 0.1); + leParameters->n_bkg.init(100., 5., 5000., 0.1); + leParameters->f_sig.init(0.5, 0.0, 1.0, 0.0); + } + else{ + leParameters->n_sig.init(events[n].size() * 0.85, events[n].size() * 0.4, events[n].size() * 1.2, 0.1); + leParameters->n_bkg.init(events[n].size() * 0.15, events[n].size() * 0.01, events[n].size() * 0.5, 0.1); + leParameters->f_sig.init(0.5, 0.0, 1.0, 0.0); + } + } + } + else{ + if(fitSignalMC || OnlySignal) + leParameters->f_sig.init(1.0, 0.0, 1.0, 0.0); + else if(OnlyBackground){ + leParameters->f_sig.init(0.0, 0.0, 1.0, 0.0); + } + else + leParameters->f_sig.init(0.35, 0.0, 1.0, 0.01); + } + leParameters->m_b.init(f_m_B[n], B_MASS_LOW, B_MASS_HIGH, OnlyBackground ? 0.0 : 0.01); + if(opts.twotailedcrystalball) + leParameters->m_res_1.init(1.0, 0.0, 1.0, 0.0); + else + leParameters->m_res_1.init(f_f_CB[n], 0.0, 1.0, fitSignalMC ? 0.01 : 0.0); + if(leParameters->f_sig.get_value() != 1.0){ + if(fitData || true){ //only use single exponential for all cases + leParameters->fm_tau.init(1.0, 0.0, 1.0, 0.0); + leParameters->m_lambda.init(f_lambda1[n], -1.0e-2, -1.0e-6, 1.0e-6); + leParameters->m_lambda_2.init(f_lambda2[n], -1.0e-2, -1.0e-6, 0.0); + } + else{ + leParameters->fm_tau.init((n % 2 == 1) ? 1.0 : 0.8, 0.0, 1.0, (n % 2 == 1) ? 0.0 : 0.01); + leParameters->m_lambda.init(f_lambda1[n], -1.0e-1, -1.0e-6, 1.0e-6); + leParameters->m_lambda_2.init(f_lambda2[n], -1.0e-1, -1.0e-6, (n % 2 == 1) ? 0.0 : 1.0e-6); + } + leParameters->m_tau.init( 1./2.835e-3, 100.0, 1.0e+4, 0.0); + leParameters->m_tau_2.init(1./1.664e-3, 0.0, 1.0e+4, 0.0); + } + else{ + leParameters->fm_tau.init(0.8, 0.0, 1.0, 0.0); + leParameters->m_lambda.init(-2.835e-3, -1.0e-1, -1.0e-6, 0.0); + leParameters->m_lambda_2.init(-1.664e-4, -1.0e-1, -1.0e-6, 0.0); + leParameters->m_tau.init( 1./2.835e-3, 100.0, 1.0e+4, 0.0); + leParameters->m_tau_2.init(6.01e+2, 0.0, 1.0e+4, 0.0); + } + if(opts.twotailedcrystalball) + leParameters->m_sigma_1.init(f_sigma_1[n], 5.0, 50.0, ((fitReference || fitSignalMC) && !OnlyBackground) ? 0.01 : 0.0); + else{ + leParameters->m_sigma_1.init(f_sigma_1[n], 5.0, 50.0, ((fitReference || fitSignalMC) && !OnlyBackground) ? 0.01 : 0.0); + leParameters->m_sigma_2.init(f_sigma_2[n], 5.0, 50.0, ((fitReference || fitSignalMC) && !OnlyBackground) ? 0.01 : 0.0); + } + leParameters->alpha_1.init(f_alpha_1[n], 0.5, 5.0, fitSignalMC ? 0.0001 : 0.0); + leParameters->alpha_2.init(f_alpha_2[n], 0.5, 5.0, fitSignalMC ? 0.0001 : 0.0); + leParameters->n_1.init(f_n_1[n], 0.1, 50.0, fitSignalMC ? 0.001 : 0.0); + leParameters->n_2.init(f_n_2[n], 0.1, 50.0, fitSignalMC ? 0.001 : 0.0); + if(!fitReference && !fitSignalMC && !SystematicsWithToys) + leParameters->m_scale.init(f_m_scale[n], 0.0, 2.0, 0.0); + else + leParameters->m_scale.init(1.0, 0.0, 2.0, 0.0); + leParameters->eff_q2.init(0.5*(opts.TheQ2binsmin.at(b)+opts.TheQ2binsmax.at(b)), opts.TheQ2binsmin.front(), opts.TheQ2binsmax.back(), 0.0); + /* + if(!fitSignalMC && !fitReference){ + if(LargeBinning) + leParameters->load_only_Bmass_param_values("fitresult_SignalFit_fitSignalMC_SimultaneousFit_2Dfit_bin"+std::to_string(b)+"_pdf"+std::to_string(n)+".txt"); + else{ + if(leParameters->eff_q2() < 8.68) + leParameters->load_only_Bmass_param_values("fitresult_SignalFit_fitSignalMC_SimultaneousFit_2Dfit_bin2_pdf"+std::to_string(n)+".txt"); + else if(leParameters->eff_q2() > 15.0) + leParameters->load_only_Bmass_param_values("fitresult_SignalFit_fitSignalMC_SimultaneousFit_2Dfit_bin6_pdf"+std::to_string(n)+".txt"); + else + leParameters->load_only_Bmass_param_values("fitresult_SignalFit_fitSignalMC_SimultaneousFit_2Dfit_bin5_pdf"+std::to_string(n)+".txt"); + } + } +*/ + //initialize parameters to blind them! + //leParameters->Fl.init(3.0/4.0*(s1c.at(b)-s2c.at(b)/3.0), 0.0, 1.0, 0.0); + leParameters->Fl.init(1.0-4.0/3.0*s1s.at(b), 0.0, 1.0, 0.0); + leParameters->S1s.init(s1s.at(b), -1.0, 1.0, 0.0); + leParameters->S3.init(s3.at(b), -1.0, 1.0, 0.0); + leParameters->S4.init(s4.at(b), -1.0, 1.0, 0.0); + leParameters->S5.init(s5.at(b), -1.0, 1.0, 0.0); + leParameters->Afb.init(3.0/4.0*s6s.at(b), -0.75, 0.75, 0.0); + leParameters->S6s.init(s6s.at(b), -1.0, 1.0, 0.0); + leParameters->S7.init(s7.at(b), -1.0, 1.0, 0.0); + leParameters->S8.init(s8.at(b), -1.0, 1.0, 0.0); + leParameters->S9.init(s9.at(b), -1.0, 1.0, 0.0); + + leParameters->SS1.init(0.0, -1.0, 1.0, 0.0); + leParameters->SS2.init(0.0, -1.0, 1.0, 0.0); + leParameters->SS3.init(0.0, -1.0, 1.0, 0.0); + leParameters->SS4.init(0.0, -1.0, 1.0, 0.0); + leParameters->SS5.init(0.0, -1.0, 1.0, 0.0); + + if(blind){ + double blind_scale = 1.0; + leParameters->Fl.set_blinding(true, blind_scale, true); + leParameters->S1s.set_blinding(true, blind_scale, true); + leParameters->S3.set_blinding(true, blind_scale, true); + leParameters->S4.set_blinding(true, blind_scale, true); + leParameters->S5.set_blinding(true, blind_scale, true); + leParameters->Afb.set_blinding(true, blind_scale, true); + leParameters->S6s.set_blinding(true, blind_scale, true); + leParameters->S7.set_blinding(true, blind_scale, true); + leParameters->S8.set_blinding(true, blind_scale, true); + leParameters->S9.set_blinding(true, blind_scale, true); + } + + leParameters->FS .init(opts.swave ? 0.1*FL_scale[b] : 0.0, -1.0, 1.0, opts.swave ? 0.001 : 0.0); + if(opts.fit_mkpi || opts.use_mkpi){ + //p-wave + if(fitData) + leParameters->gammakstar.init(0.0503, 0.01, 0.10, 0.001, 0.01, true);//PDG value + else + leParameters->gammakstar.init(0.0503, 0.01, 0.10, OnlyBackground ? 0.0 : 0.001);//PDG value + leParameters->mkstar.init(PDGMASS_K_STAR_PLUS / 1000., 0.85, 1.0, OnlyBackground ? 0.0 : 0.001);//PDG value + //s-wave + leParameters->gammakstarplus.init(0.236, 0.1, 1.0, 0.0); //PDG value + leParameters->mkstarplus.init(1.41, 1.2, 1.6, 0.0); //PDG value + leParameters->asphase.init(TMath::Pi(), 0.0, 2.0*TMath::Pi(), 0.0); + leParameters->a.init(1.95, 0.001, 20.0, 0.0); + leParameters->r.init(1.78, 0.001, 10.0, 0.0); + leParameters->R.init(1.6, 0.0, 10.0, FitR ? 0.001 : 0.0); + //background parameter + if(leParameters->f_sig() != 1.0){ + leParameters->cbkgmkpi0.init(1.0, -1.0, 1.0, 0.0); + leParameters->cbkgmkpi1.init(0.1, -1.0, 1.0, 0.01); + leParameters->cbkgmkpi2.init(0.0, -1.0, 1.0, 0.0); + leParameters->cbkgmkpi3.init(0.0, -1.0, 1.0, 0.0); + leParameters->cbkgmkpi4.init(0.0, -1.0, 1.0, 0.0); + opts.mkpi_threshold = false; + leParameters->nthreshold.init(1.5, 0.0, 15.0, 0.0); + } + } + //background parameter //TODO loop //TODO nPDFs + if(leParameters->f_sig() != 1.0){ + leParameters->cbkgctl0.init(1.0, -1.0, 1.0, 0.0); + leParameters->cbkgctl1.init(Bctl1[n], -1.0, 1.0, 0.0); + leParameters->cbkgctl2.init(Bctl2[n], -1.0, 1.0, 0.0); + leParameters->cbkgctl3.init(0.0, -1.0, 1.0, 0.0); + leParameters->cbkgctl4.init(0.0, -1.0, 1.0, 0.0); + + leParameters->cbkgctk0.init(1.0, -1.0, 1.0, 0.0); + leParameters->cbkgctk1.init(Bctk1[n], -1.0, 1.0, 0.0); + leParameters->cbkgctk2.init(Bctk2[n], -1.0, 1.0, 0.0); + leParameters->cbkgctk3.init(0.0, -1.0, 1.0, 0.0); + leParameters->cbkgctk4.init(0.0, -1.0, 1.0, 0.0); + + leParameters->cbkgphi0.init(1.0, -1.0, 1.0, 0.0); + leParameters->cbkgphi1.init(0.0, -1.0, 1.0, 0.0); + leParameters->cbkgphi2.init(0.0, -1.0, 1.0, 0.0); + leParameters->cbkgphi3.init(0.0, -1.0, 1.0, 0.0); + leParameters->cbkgphi4.init(0.0, -1.0, 1.0, 0.0); + } + + if(SystematicsWithToys || FitFinalToySamples){ + fcnc::bu2kstarmumu_parameters * le2DParameters = new fcnc::bu2kstarmumu_parameters(&theOptions[n]); + le2DParameters->eff_q2.init(0.5*(opts.TheQ2binsmin.at(b)+opts.TheQ2binsmax.at(b)), opts.TheQ2binsmin.front(), opts.TheQ2binsmax.back(), 0.0); + + //initiate parameters for B mass fit + if(OnlySignal) + le2DParameters->f_sig.init(1.0, 0.0, 1.0, 0.0); + else + le2DParameters->f_sig.init(N_sig_Rare[b]*ev_frac[n]/(N_sig_Rare[b]*ev_frac[n]+N_bkg_Rare[b]*ev_frac[n]), 0.0, 1.0, 0.001); + le2DParameters->m_b.init(f_m_B[n], B_MASS_LOW, B_MASS_HIGH, 0.01); + if(opts.twotailedcrystalball) + le2DParameters->m_res_1.init(1.0, 0.0, 1.0, 0.0); + else + le2DParameters->m_res_1.init(f_f_CB[n], 0.0, 1.0, 0.0); + le2DParameters->fm_tau.init(1.0, 0.0, 1.0, 0.0); + le2DParameters->m_lambda.init(f_lambda1[n], -1.0e-1, -1.0e-6, 1.0e-6); + le2DParameters->m_lambda_2.init(f_lambda2[n], -1.0e-1, -1.0e-6, 0.0); + if(opts.twotailedcrystalball){ + le2DParameters->m_sigma_1.init(f_sigma_1[n], 5.0, 40.0, 0.0); + } + else{ + le2DParameters->m_sigma_1.init(f_sigma_1[n], 5.0, 40.0, 0.0); + le2DParameters->m_sigma_2.init(f_sigma_2[n], 5.0, 40.0, 0.0); + } + le2DParameters->alpha_1.init(f_alpha_1[n], 0.5, 5.0, 0.0); + le2DParameters->alpha_2.init(f_alpha_2[n], 0.5, 3.0, 0.0); + le2DParameters->n_1.init(f_n_1[n], 0.1, 15.0, 0.0); + le2DParameters->n_2.init(f_n_2[n], 0.1, 10.0, 0.0); + le2DParameters->m_scale.init(1.0, 0.0, 2.0, 0.0); + + //mK* + le2DParameters->gammakstar.init(0.0503, 0.01, 0.8, 0.0); //PDG value + le2DParameters->mkstar.init(PDGMASS_K_STAR_PLUS / 1000., 0.7, 1.2, 0.01); //PDG value + //s-wave + if(opts.swave) + le2DParameters->FS.init(0.063, -1.00, 1.00, 0.001); + else + le2DParameters->FS.init(0.0, -1.00, 1.00, 0.0); + le2DParameters->gammakstarplus.init(0.236, 0.1, 1.0, 0.0); //PDG value + le2DParameters->mkstarplus.init(1.41, 1.2, 1.6, 0.0); //PDG value + le2DParameters->asphase.init(TMath::Pi(), 0.0, 2.0*TMath::Pi(), 0.0); + le2DParameters->a.init(1.95, 0.0, 20.0, 0.0); + le2DParameters->r.init(1.78, 0.0, 10.0, 0.0); + le2DParameters->R.init(1.6, 0.0, 10.0, 0.0); + //background parameter + le2DParameters->cbkgmkpi0.init(1.0, -1.0, 1.0, 0.0); + le2DParameters->cbkgmkpi1.init(0.0, -1.0, 1.0, 0.01); + + the2DParams[b].push_back(le2DParameters); + } + + //define center of q2bin as effective q2: + lePDF->load_coeffs_eff_phsp_4d(); + lePDF->update_cached_normalization(leParameters); + + //save parameters and pdfs in vectors: + + bool include = false; + for(UInt_t m = 0; m < pdf_idx.size(); m++){ + if(n == pdf_idx.at(m)){ + include = true; + break; + } + } + if(include){ + theParams [b].push_back(leParameters); + theProbs [b].push_back(lePDF); + } + + spdlog::info("[PDF{0:d}]\tSaved PDF and parameters!", n); + + //create vector with events according to the requested fits/pulls + std::vector * leEvents = new std::vector; + + //choose events from the event vector and sort corresponding to q2bin or non-resonant: + UInt_t NNN = events[n].size(); + + //This randomly pre-selected list of events is used, if not all events are wanted: + std::vectoreee; + + for(UInt_t e = 0; e < NNN; e++){ + fcnc::event meas; + meas = events[n].at(e); + //if wanted, only choose events from within q2 bin + if(meas.q2 < opts.TheQ2binsmin.at(b) || meas.q2 > opts.TheQ2binsmax.at(b)) + continue; + if(meas.q2 > 0.98 && meas.q2 < 1.1)//exclude phi resonance + continue; + if(meas.m < opts.m_low || meas.m > opts.m_high) + continue; + if(OnlyBackground) + if(meas.m > 5230. && meas.m < 5330.)//exclude B peak + continue; + //crosscheck between mag up and mag down: + if(FitOnlyMagDown && meas.magnet > 0) + continue; + if(FitOnlyMagUp && meas.magnet < 0) + continue; + if(meas.costhetal < -1. || meas.costhetal > +1.){ + spdlog::warn("cos(theta_L) out of range: {0:f}", meas.costhetal); + continue; + } + if(meas.costhetak < -1. || meas.costhetak > +1.){ + spdlog::warn("cos(theta_K) out of range: {0:f}", meas.costhetak); + continue; + } + if(meas.phi < -TMath::Pi() || meas.phi > +TMath::Pi()){ + spdlog::warn("phi out of range: {0:f}", meas.phi); + continue; + } + if(meas.mkpi < opts.mkpi_min || meas.mkpi > opts.mkpi_max){ + spdlog::warn("m(Kpi) out of range: {0:f}", meas.mkpi); + continue; + } + leEvents->push_back(meas); + } + + if(SystematicsWithToys){ + leEvents->clear(); + fcnc::bu2kstarmumu_generator gen(&theOptions[n]); + UInt_t idx = pdf_idx.at(n); + if(UseAccPer2Years && theOptions[n].run == 2){ + theOptions[n].run = 21; + lePDF->load_coeffs_eff_phsp_4d(); + lePDF->update_cached_normalization(leParameters); + std::vector eves1516 = gen.generate(0.5 + event_numbers[b][idx] * (idx%2==0 ? 0.275 : 0.292) , leParameters, lePDF); + for(unsigned int k = 0; k < eves1516.size(); k++) + eves1516.at(k).year = 2016; + theOptions[n].run = 22; + lePDF->load_coeffs_eff_phsp_4d(); + lePDF->update_cached_normalization(leParameters); + std::vector eves1718 = gen.generate(0.5 + event_numbers[b][idx] * (idx%2==0 ? 0.725 : 0.708), leParameters, lePDF); + for(unsigned int k = 0; k < eves1718.size(); k++) + eves1718.at(k).year = 2018; + theOptions[n].run = 2; + leEvents->insert(leEvents->end(), eves1516.begin(), eves1516.end()); + leEvents->insert(leEvents->end(), eves1718.begin(), eves1718.end()); + } + else{ + lePDF->load_coeffs_eff_phsp_4d(); + lePDF->update_cached_normalization(leParameters); + std::vector genevents = gen.generate(0.5 + event_numbers[b][idx], leParameters, lePDF); + for(unsigned int k = 0; k < genevents.size(); k++) + genevents.at(k).year = (theOptions[idx].run == 2 ? 2016 : 2012); + leEvents->insert(leEvents->end(), genevents.begin(), genevents.end()); + } + } + + if(UseAccPer2Years && theOptions[n].run == 2){ + //split the Run2 data-set into two groups: [0]: 2015+16 [1]: 2017+18 + std::vector * Events_2015_2016 = new std::vector; + std::vector * Events_2017_2018 = new std::vector; + UInt_t nBefore = leEvents->size(); + + for(UInt_t e = 0; e < leEvents->size(); e++){ + fcnc::event meas = leEvents->at(e); + if(meas.year == 2015 || meas.year == 2016) + Events_2015_2016->push_back(meas); + else if(meas.year == 2017 || meas.year == 2018) + Events_2017_2018->push_back(meas); + else{ + spdlog::critical("Invalid year found in data-set of Run2: {0:d}", meas.year); + assert(0); + } + } + //update cached eff for 2015+16 and 2017+18 individually + theOptions[n].run = 21; + lePDF->load_coeffs_eff_phsp_4d(); + lePDF->update_cached_normalization(leParameters); + lePDF->update_cached_efficiencies(leParameters, Events_2015_2016); + + theOptions[n].run = 22; + lePDF->load_coeffs_eff_phsp_4d(); + lePDF->update_cached_normalization(leParameters); + lePDF->update_cached_efficiencies(leParameters, Events_2017_2018); + + //recombine both data-sets: + theOptions[n].run = 2; + leEvents->clear(); + leEvents->insert(leEvents->end(), Events_2015_2016->begin(), Events_2015_2016->end()); + leEvents->insert(leEvents->end(), Events_2017_2018->begin(), Events_2017_2018->end()); + + assert(nBefore == leEvents->size()); + } + else{ + lePDF->load_coeffs_eff_phsp_4d(); + lePDF->update_cached_normalization(leParameters); + lePDF->update_cached_efficiencies(leParameters, leEvents); + } + + if(include) + selection[b].push_back(leEvents); + + spdlog::info("[PDF{0:d}]\tFinished selecting {1:f} events!", n, leEvents->size()); + + } // end of PDF + } // end of q2 bins + + double FSfromLargeBins[3], dFSfromLargeBins[3]; + if((SystematicsWithToys || FitFinalToySamples) && !OnlySignal && !fitReference){ + //combine events to larger bins and fit before fitting all 8 bins: + int fit_results[3]; + std::vector< std::vector* > combinedEvents[3]; + bool ex_ml_buffer = theOptions[0].extended_ml; + for(unsigned int n = 0; n < nPDFs; n++){ + combinedEvents[0].push_back(new std::vector); + combinedEvents[0].back()->insert(combinedEvents[0].back()->end(), selection[1].at(n)->begin(), selection[1].at(n)->end()); + combinedEvents[0].back()->insert(combinedEvents[0].back()->end(), selection[2].at(n)->begin(), selection[2].at(n)->end()); + combinedEvents[0].back()->insert(combinedEvents[0].back()->end(), selection[3].at(n)->begin(), selection[3].at(n)->end()); + combinedEvents[0].back()->insert(combinedEvents[0].back()->end(), selection[4].at(n)->begin(), selection[4].at(n)->end()); + combinedEvents[1].push_back(new std::vector); + combinedEvents[1].back()->insert(combinedEvents[1].back()->end(), selection[5].at(n)->begin(), selection[5].at(n)->end()); + combinedEvents[2].push_back(new std::vector); + combinedEvents[2].back()->insert(combinedEvents[2].back()->end(), selection[6].at(n)->begin(), selection[6].at(n)->end()); + combinedEvents[2].back()->insert(combinedEvents[2].back()->end(), selection[7].at(n)->begin(), selection[7].at(n)->end()); + + theOptions[n].extended_ml = false; + + } + + //extract FS from this fit and constrain FS to this value: + for(int b = 0; b < 3; b++){ + fit_results[b] = f.fit(theProbs[b], the2DParams[b], combinedEvents[b]); + for(unsigned int n = 0; n < nPDFs; n++){ + fcnc::bu2kstarmumu_parameters * dieParameter = (fcnc::bu2kstarmumu_parameters *) the2DParams[b].at(n); + FSfromLargeBins[b] = dieParameter->FS.get_value(); + dFSfromLargeBins[b] = dieParameter->FS.get_error(); + spdlog::info("[LARGEBIN{0:d}][PDF{1:d}]\tFS = {2:f} +/- {3:f}",b, n, FSfromLargeBins[b], dFSfromLargeBins[b]); + } + } + if(false){ + TFile* fout = new TFile(("finalresult_OnlyToys"+std::to_string(opts.job_id)+"_2DfitLargeBins"+(LargerMKpiRange ? "_MediumMKpiRange" : "")+".root").c_str(), "RECREATE"); + fout->cd(); + int param_index = 0; + fcnc::bu2kstarmumu_parameters * dieParameter = (fcnc::bu2kstarmumu_parameters *) the2DParams[0].at(0); + for(UInt_t p = 0; p < dieParameter->nparameters(); p++){ + fcnc::parameter* param = dieParameter->get_parameter(p); + if(param->get_step_size() != 0.0){//skip constant parameters + std::string parname(param->get_name()); + std::string pardesc(param->get_description()); + + spdlog::info("Creating new TTree for parameter: " +parname); + + TTree* t = new TTree(parname.c_str(), pardesc.c_str()); + double q2a, q2b, value, error, error_up, error_down, start_value, nominal_value, nominal_error=0.0; + int pdf, bin, migrad, status_cov; + const unsigned int corr_max = param->correlations.size(); + double tmp_corr[corr_max]; + + t->Branch("pdf",&pdf,"pdf/I"); + t->Branch("bin",&bin,"bin/I"); + t->Branch("value",&value,"value/D"); + t->Branch("q2min",&q2a,"q2min/D"); + t->Branch("q2max",&q2b,"q2max/D"); + t->Branch("error",&error,"error/D"); + t->Branch("error_up",&error_up,"error_up/D"); + t->Branch("error_down",&error_down,"error_down/D"); + t->Branch("start_value",&start_value,"start_value/D"); + t->Branch("migrad",&migrad,"migrad/I"); + t->Branch("status_cov",&status_cov,"status_cov/I"); + t->Branch("nominal_value",&nominal_value,"nominal_value/D"); + t->Branch("nominal_error",&nominal_error,"nominal_error/D"); + t->Branch("index",¶m_index, "index/I"); + + std::stringstream corr_stream; + corr_stream << "correlations[" << corr_max << "]/D"; + t->Branch("correlations",&tmp_corr,corr_stream.str().c_str()); + + pdf = 1; + + for(UInt_t b = 0; b < 3; b++){ + fcnc::parameter* par = the2DParams[b].at(0)->get_parameter(p); + + UInt_t paridx = 0; + while(par->get_name() != parname.c_str()){ + par = the2DParams[b].at(0)->get_parameter(paridx); + paridx++; + if(paridx == the2DParams[b].at(0)->nparameters()){ + spdlog::warn("Parameter '"+parname+"' not found in PDF 0. Continue with next PDF."); + break; + } + } + if(paridx == the2DParams[b].at(0)->nparameters()) + break; + + bin = b; + q2a = opts.TheQ2binsmin[b]; + q2b = opts.TheQ2binsmax[b]; + value = par->get_value(); + error = par->get_error(); + error_up = par->get_error_up(); + error_down = par->get_error_down(); + start_value = par->get_start_value(); + nominal_value = par->get_start_value(); + migrad = fit_results[b] % 100; + status_cov = fit_results[b] / 100; + + for (unsigned int l = 0; l < corr_max; l++) + tmp_corr[l] = 0.0; + for (unsigned int l = 0; l < par->correlations.size(); l++) + tmp_corr[l] = par->correlations.at(l); + t->Fill(); + } + t->Write(); + delete t; + param_index++; + } + } + fout->Close(); + } + if(false){ + for(UInt_t b = 0; b < 3; b++){ + for(unsigned int n = 0; n < nPDFs; n++){ + std::cout << "|| BIN " << b << "\tPDF " << n << std::endl; + the2DParams[b].at(n)->print_parameters(false); + } + } + } + if(false){ + for(UInt_t b = 0; b < 3; b++){ + for(unsigned int n = 0; n < nPDFs; n++){ + fcnc::bu2kstarmumu_parameters * dieParameter = (fcnc::bu2kstarmumu_parameters *) the2DParams[b].at(n); + fcnc::bu2kstarmumu_pdf * leProb = (fcnc::bu2kstarmumu_pdf *) theProbs[b].at(n); + thePlotter[n]->plot_data(leProb, dieParameter, combinedEvents[b].at(n), get_MoMPlot_path(), "ToyMoM_LargeBins_bin"+std::to_string(b)+"_pdf"+std::to_string(n), true); + } + } + } + for(unsigned int n = 0; n < nPDFs; n++){ + theOptions[n].extended_ml = ex_ml_buffer; + } + } + + bool do_fit = !OnlySignal; + int fitresult = 0; + if(do_fit){ + for(UInt_t b = 0; b < nBins; b++){ + std::vector * AllEvents = new std::vector; + for(UInt_t n = 0; n < nPDFs; n++){ + if(SimultaneousFit){ + if(n == 0){ + fitresult = f.fit(theProbs[b], theParams[b], selection[b]); + } + } + else if(OneFit){ + if(n > 0) + continue; + AllEvents->clear(); + for(UInt_t nn = 0; nn < nPDFs; nn++) + AllEvents->insert(AllEvents->end(), selection[b].at(nn)->begin(), selection[b].at(nn)->end()); + fitresult = f.fit(theProbs[b].at(n), theParams[b].at(n), AllEvents); + } + else{ + fitresult = f.fit(theProbs[b].at(n), theParams[b].at(n), selection[b].at(n)); + } + fit_results[b].push_back(fitresult); + fcnc::bu2kstarmumu_parameters * leParameters = (fcnc::bu2kstarmumu_parameters *) theParams[b].at(n); + fcnc::bu2kstarmumu_pdf * leProb = (fcnc::bu2kstarmumu_pdf *) theProbs[b].at(n); + + if(!SimultaneousFit || n == 0){ + double fitted_fs = leParameters->FS.get_value(); + double fitted_dfs_up = leParameters->FS.get_error_up(); + double fitted_dfs_down = leParameters->FS.get_error_down(); + double fitted_dfs = leParameters->FS.get_error(); + if(opts.minos_errors) + fitted_dfs = std::max(fabs(fitted_dfs_up), fabs(fitted_dfs_down)); + if(fitSignalMC || !opts.swave){ + fitted_fs = 0.0; + fitted_dfs = 0.0; + } + else if(FSfrom2DLargeBins){ + if(leParameters->eff_q2() < 9.0){ + fitted_fs = 0.252622 * FL_scale[b]; + fitted_dfs = 0.103659 * FL_scale[b]; + } + else if(leParameters->eff_q2() < 15.0){ + fitted_fs = 0.013818 * FL_scale[b]; + fitted_dfs = 0.146519 * FL_scale[b]; + } + else{ + fitted_fs = 0.0164393 * FL_scale[b]; + fitted_dfs = 0.0895912 * FL_scale[b]; + } + } + else if((SystematicsWithToys || FitFinalToySamples) && !fitReference){//use FS obtained from the fit in the larger q2bins: + if(leParameters->eff_q2() < 9.0){ + fitted_fs = FSfromLargeBins[0] * FL_scale[b]; + fitted_dfs = dFSfromLargeBins[0] * FL_scale[b]; + } + else if(leParameters->eff_q2() < 15.0){ + fitted_fs = FSfromLargeBins[1] * FL_scale[b]; + fitted_dfs = dFSfromLargeBins[1] * FL_scale[b]; + } + else{ + fitted_fs = FSfromLargeBins[2] * FL_scale[b]; + fitted_dfs = dFSfromLargeBins[2] * FL_scale[b]; + } + } + std::cout << std::setprecision(5) << "FS: " << fitted_fs << "+/-" << fitted_dfs << std::endl; + fitted_FS[b].push_back(fitted_fs); + fitted_FSerr[b].push_back(fitted_dfs); + fitted_FSerrUp[b].push_back(fitted_dfs_up); + fitted_FSerrDown[b].push_back(fitted_dfs_down); + } + //plot fit projections of 2Dfit + std::ostringstream eps_label; + spdlog::info("[PLOT]\tStart configurations for plotting!"); + if(fitReference){ + eps_label << "JpsiFit"; + } + else if(fitSignalMC){ + eps_label << "FCNC_SignalfitSignalMC_fit_bin" << std::to_string(b); + } + else{ + eps_label << "FCNCfit_bin" << std::to_string(b); + } + if (LargeBinning) eps_label << "_LargeBins"; + else if(Fit2bins) eps_label << "_2BINS"; + else if(Fit1bin) eps_label << "_1BIN"; + else if(FitAllbins) eps_label << "_9BINS"; + + if(OneFit) eps_label << "_FullDataSet"; + else eps_label << (n % 2 == 0 ? "_DD_Run" : "_LL_Run") << std::to_string( (int) (1+n/2)); + + eps_label << "_MoM_2Dfit"; + theOptions[n].plot_label = "LHCb data"; + theOptions[n].q2_label = q2_label(theOptions[n].TheQ2binsmin.at(b),theOptions[n].TheQ2binsmax.at(b)); + if(opts.write_eps){ + std::cout << "[PLOT]\t" << eps_label.str() << std::endl; + if(OneFit) + thePlotter[n]->plot_data(leProb, leParameters, AllEvents, get_MoMPlot_path(), eps_label.str(), false); + else + thePlotter[n]->plot_data(leProb, leParameters, selection[b].at(n), get_MoMPlot_path(), eps_label.str(), false); + } + }//end loop PDFs + + if(SimultaneousFit){ + std::ostringstream eps_label; + spdlog::info("[PLOT]\tStart configurations for combined plotting!"); + if(fitReference){ + eps_label << "JpsiFit"; + } + else if(fitSignalMC){ + eps_label << "FCNC_SignalfitSignalMC_fit_bin" << std::to_string(b); + } + else{ + eps_label << "FCNCfit_bin" << std::to_string(b); + } + if (LargeBinning) eps_label << "_LargeBins"; + else if(Fit2bins) eps_label << "_2BINS"; + else if(Fit1bin) eps_label << "_1BIN"; + else if(FitAllbins) eps_label << "_9BINS"; + eps_label << "_AllPDFs"; + eps_label << "_MoM_2Dfit"; + std::vector * prober = (std::vector *) & theProbs[b]; + std::vector * paramser = (std::vector *) & theParams[b]; + thePlotter[0]->SetPulls(true); + thePlotter[0]->plot_added_pdfs(prober, paramser, & selection[b], + get_MoMPlot_path(), eps_label.str(), true); + thePlotter[0]->SetPulls(false); + eps_label << "_noPulls"; + thePlotter[0]->plot_added_pdfs(prober, paramser, & selection[b], + get_MoMPlot_path(), eps_label.str(), true); + } + }//end loop q2 bins + }//end do_fit + else{//fill vectors with nominal values, if fit was not done: + for(UInt_t b = 0; b < nBins; b++){ + for(UInt_t n = 0; n < nPDFs; n++){ + if(FixFStoStart) + fitted_FS[b].push_back( opts.swave ? 0.1*FL_scale[b] : 0.0); + else + fitted_FS[b].push_back(0.); + fitted_FSerr[b].push_back(0.); + fitted_FSerrUp[b].push_back(0.); + fitted_FSerrDown[b].push_back(0.); + } + fit_results[b].push_back(300); + } + } + + bool do_mom = !LargeBinning; + if(do_mom){ + for(UInt_t b = 0; b < nBins; b++){ + std::vector allEvents; + allEvents.clear(); + //assign sWeights: + if(!(fitSignalMC || OnlySignal) && do_fit){//pure signal and fitSignalMC don't need sWeights + if(OneFit){ + //for the combined fit, first add all events together and then apply sWeights according to first parameter idx + for(UInt_t n = 0; n < nPDFs; n++){ + spdlog::info("[MOM]\tCombine events into one set for bin={0:d} pdf={1:d}",b, n); + allEvents.insert(allEvents.end(), selection[b].at(n)->begin(), selection[b].at(n)->end()); + } + spdlog::info("[MOM]\tGet sWeights from fit for the full dataset of bin={0:d}",b); + fcnc::bu2kstarmumu_parameters * leParameters = (fcnc::bu2kstarmumu_parameters *) theParams[b].at(0); + fcnc::bu2kstarmumu_pdf * leProb = (fcnc::bu2kstarmumu_pdf *) theProbs[b].at(0); + spdlog::info("[MOM]\tGet combined sWeights from fit for bin={0:d}",b); + leProb->calculate_sweights(leParameters, &allEvents); + spdlog::info("[MOM]\tGet combined sWeights from fit for bin={0:d} ... DONE!",b); + } + else{ + //for individual mom, each sub-sets gets sWeights and no sub-sets are added together + for(UInt_t n = 0; n < nPDFs; n++){ + fcnc::bu2kstarmumu_parameters * leParameters = (fcnc::bu2kstarmumu_parameters *) theParams[b].at(n); + fcnc::bu2kstarmumu_pdf * leProb = (fcnc::bu2kstarmumu_pdf *) theProbs[b].at(n); + spdlog::info("[MOM]\tGet sWeights from fit for bin={0:d} pdf={1:d}",b, n); + leProb->calculate_sweights(leParameters, selection[b].at(n)); + spdlog::info("[MOM]\tGet sWeights from fit for bin={0:d} pdf={1:d} ...DONE.",b, n); + //for the simultaneous mom, first apply sWeights according to parameters[n], then add all events together + if(SimultaneousMoM){ + spdlog::info("[MOM]\tCombine events (after sWeights have been applied) into one set for bin={0:d} pdf={1:d}",b, n); + allEvents.insert(allEvents.end(), selection[b].at(n)->begin(), selection[b].at(n)->end()); + } + } + } + }//end of sWeight assignments + //extract and save angular moments: + if(SimultaneousMoM || SimultaneousFit || OneFit){//do MoM for the full dataset of this q2bin + std::vector mom(18, 0.0), obs(18, 0.0); + std::vector momcov(18*18, 0.0), obscov(18*18, 0.0); + spdlog::info("[MoM]\tGet moments from the combined dataset! bin={0:d}",b); + if(!allEvents.size()){ + for(UInt_t n = 0; n < nPDFs; n++){ + spdlog::info("[MOM]\tCombine events for MoM into one set for bin={0:d} pdf={1:d}",b, n); + allEvents.insert(allEvents.end(), selection[b].at(n)->begin(), selection[b].at(n)->end()); + } + } + fcnc::bu2kstarmumu_parameters * leParameters = (fcnc::bu2kstarmumu_parameters *) theParams[b].at(0); + fcnc::bu2kstarmumu_pdf * leProb = (fcnc::bu2kstarmumu_pdf *) theProbs[b].at(0); + leProb->get_moments(allEvents, mom, momcov); + spdlog::info("[MoM]\tConvert moments to angular observables for the combined dataset! bin={0:d}",b); + fcnc::moments_to_observables(rnd, mom, momcov, fitted_FS[b].at(0), fitted_FSerr[b].at(0), obs, obscov, FixFStoStart || UseExternalFS); + spdlog::info("[MoM]\tSave angular observables to parameters for the combined dataset! bin={0:d}",b); + leProb->save_moments_to_obs(leParameters, obs, obscov); + spdlog::info("[MoM]\tDone for the combined dataset of bin={0:d}",b); + } + else{//do MoM individually for each sub-set + for(UInt_t n = 0; n < nPDFs; n++){ + std::vector mom(18, 0.0), obs(18, 0.0);; + std::vector momcov(18*18, 0.0), obscov(18*18, 0.0); + spdlog::info("[MoM]\tGet moments from the combined dataset! bin={0:d} pdf={1:d}",b, n); + fcnc::bu2kstarmumu_parameters * leParameters = (fcnc::bu2kstarmumu_parameters *) theParams[b].at(n); + fcnc::bu2kstarmumu_pdf * leProb = (fcnc::bu2kstarmumu_pdf *) theProbs[b].at(n); + leProb->get_moments(*selection[b].at(n), mom, momcov); + spdlog::info("[MoM]\tConvert moments to angular observables for bin={0:d} pdf={1:d}",b, n); + fcnc::moments_to_observables(rnd, mom, momcov, fitted_FS[b].at(n), fitted_FSerr[b].at(n), obs, obscov, FixFStoStart || UseExternalFS); + spdlog::info("[MoM]\tSave angular observables to parameters for bin={0:d} pdf={1:d}",b, n); + leProb->save_moments_to_obs(leParameters, obs, obscov); + spdlog::info("[MoM]\tDone for bin={0:d} pdf={1:d}",b, n); + } + } + //plot all four PDFs: + for(UInt_t n = 0; n < nPDFs; n++){ + if((SimultaneousMoM || OneFit) && n > 0) + continue; + std::ostringstream qqbin; + std::ostringstream eps_label; + std::cout << "[PLOT]\tStart configurations for plotting!" << std::endl; + if(fitReference) eps_label << "JpsiFit"; + else if(fitSignalMC) eps_label << "FCNC_SignalfitSignalMC_fit_bin" << std::to_string(b); + else eps_label << "FCNCfit_bin" << std::to_string(b); + + if (LargeBinning) eps_label << "_LargeBins"; + else if(Fit2bins) eps_label << "_2BINS"; + else if(Fit1bin) eps_label << "_1BIN"; + else if(FitAllbins) eps_label << "_9BINS"; + + if(SimultaneousMoM || OneFit) eps_label << "_FullDataSet"; + else eps_label << (n % 2 == 0 ? "_DD_Run" : "_LL_Run") << std::to_string( (int) (1+n/2)); + eps_label << "_MoM"; + theOptions[n].plot_label = "LHCb data"; + theOptions[n].q2_label = q2_label(theOptions[n].TheQ2binsmin.at(b),theOptions[n].TheQ2binsmax.at(b)); + if(opts.write_eps){ + bool wf = theOptions[n].weighted_fit; + bool mf = theOptions[n].only_mass2DFit; + bool oa = theOptions[n].only_angles; + bool el = theOptions[n].extended_ml; + theOptions[n].weighted_fit = true; //only for the plotter + theOptions[n].only_mass2DFit = false; //only for the plotter + theOptions[n].only_angles = true; //only for the plotter + theOptions[n].extended_ml = false;//only for the plotter + std::cout << "[PLOT]\t" << eps_label.str() << std::endl; + if(SimultaneousMoM || OneFit) + thePlotter[n]->plot_data((fcnc::bu2kstarmumu_pdf*)theProbs[b].at(n), (fcnc::bu2kstarmumu_parameters*)theParams[b].at(n), &allEvents, get_MoMPlot_path(), eps_label.str(), true); + else + thePlotter[n]->plot_data((fcnc::bu2kstarmumu_pdf*)theProbs[b].at(n), (fcnc::bu2kstarmumu_parameters*)theParams[b].at(n), selection[b].at(n), get_MoMPlot_path(), eps_label.str(), true); + theOptions[n].weighted_fit = wf; + theOptions[n].only_mass2DFit = mf; + theOptions[n].only_angles = oa; + theOptions[n].extended_ml = el; + } + } //end loop PDFs + } //end loop over bins + } //end do_mom + + bool print_parameters = false; + //print and save-to-.txt of all parameters: + std::cout << std::endl; + std::cout << "==========================================" << std::endl; + std::cout << "|| PARAMETERS ||" << std::endl; + std::cout << "==========================================" << std::endl; + for(UInt_t b = 0; b < nBins; b++){ + for(UInt_t i = 0; i < (SimultaneousMoM || OneFit ? 1 : pdf_idx.size()); i++){ + if(print_parameters){ + std::cout << "|| BIN " << b << "\tPDF " << pdf_idx.at(i) << std::endl; + theParams[b].at(i)->print_parameters(false); + } + std::ostringstream oss; + oss << "momresult"; + if(fitReference) oss << "_JpsiFit"; + else oss << "_SignalFit"; + + if(fitSignalMC) oss << "_fitSignalMC"; + + if(SimultaneousFit) oss << "_SimultaneousFit"; + else oss << "_IndividualFit"; + oss << "_2Dfit"; + + if(!opts.full_angular) oss << "_folding" << opts.folding; + if(nBins > 1) oss << "_bin" << b; + + if (LargeBinning) oss << "_LargeBins"; + else if(Fit2bins) oss << "_2BINS"; + else if(Fit1bin) oss << "_1BIN"; + else if(FitAllbins) oss << "_9BINS"; + if(FitOnlyMagDown) oss << "_OnlyMagDown"; + if(FitOnlyMagUp) oss << "_OnlyMagUp"; + if(!(SimultaneousMoM || OneFit)) oss << "_pdf" << i; + oss << ".txt"; + std::vector * paramser = (std::vector *) & theParams[b]; + if(!(SystematicsWithToys || FitFinalToySamples)) + paramser->at(i)->save_param_values(oss.str()); + } + } + + //print all fitresults: + std::cout << std::endl; + std::cout << "==========================================" << std::endl; + std::cout << "|| FIT RESULTS ||" << std::endl; + std::cout << "==========================================" << std::endl; + if(SimultaneousFit) + std::cout << "|| BIN\t\tfit result\tF_S ||" << std::endl; + else + std::cout << "|| BIN\t\tPDF\t\tfit result\tF_S ||" << std::endl; + for(UInt_t b = 0; b < nBins; b++){ + if(SimultaneousFit || OneFit){ + if(opts.minos_errors) + printf("|| %d\t\t%d\t\t%f (+)%f\t (-)%f\t||\n", b, fit_results[b].at(0), fitted_FS[b].at(0), fitted_FSerrUp[b].at(0), fitted_FSerrDown[b].at(0)); + else + printf("|| %d\t\t%d\t\t%f +/- %f\t||\n", b, fit_results[b].at(0), fitted_FS[b].at(0), fitted_FSerr[b].at(0)); + } + else{ + for(UInt_t i = 0; i < pdf_idx.size(); i++){ + if(opts.minos_errors) + printf("|| %d\t\t%d\t\t%d\t\t%f (+)%f\t (-)%f\t||\n", b, pdf_idx.at(i), fit_results[b].at(i), fitted_FS[b].at(i), fitted_FSerr[b].at(i), fitted_FSerrDown[b].at(i)); + else + printf("|| %d\t\t%d\t\t%d\t\t%f +/- %f\t||\n", b, pdf_idx.at(i), fit_results[b].at(i), fitted_FS[b].at(i), fitted_FSerr[b].at(i)); + } + } + } + std::cout << std::endl; + + //save all values to TTree: + std::ostringstream sout; + sout << "finalresults_"; + if(fitSignalMC) sout << "fitSignalMC_"; + else if(fitReference) sout << "Jpsi_"; + + if(SystematicsWithToys) sout << "OnlyToys" << opts.job_id << "_"; + if(FitFinalToySamples) sout << "FinalToys" << opts.job_id << "_"; + if(FitOnlyMagDown) sout << "OnlyMagDown_"; + if(FitOnlyMagUp) sout << "OnlyMagUp_"; + if(LargeBinning) sout << "LargeBins_"; + if(NP) sout << "NP_"; + sout << "MoM.root"; + + TFile* fout = new TFile(sout.str().c_str(), "RECREATE"); + fout->cd(); + + int param_index = 0; + //loop over parameters: + UInt_t pdf_null_idx = (SimultaneousMoM || OneFit || SimultaneousFit ? 0 : nPDFs-1); + for(UInt_t p = 0; p < theParams[0].at(pdf_null_idx)->nparameters(); p++){ + fcnc::parameter* param = theParams[0].at(pdf_null_idx)->get_parameter(p); + if(param->get_step_size() != 0.0){//skip constant parameters + + std::string parname(param->get_name()); + std::string pardesc(param->get_description()); + + spdlog::info("Creating new TTree for parameter:"+ parname); + + TTree* t = new TTree(parname.c_str(), pardesc.c_str()); + + double q2a, q2b, value, error, error_up, error_down, start_value, nominal_value, nominal_error=0.0; + int pdf, bin, migrad, status_cov; + const unsigned int corr_max = param->correlations.size(); + double tmp_corr[corr_max]; + + t->Branch("pdf",&pdf,"pdf/I"); + t->Branch("bin",&bin,"bin/I"); + t->Branch("value",&value,"value/D"); + t->Branch("q2min",&q2a,"q2min/D"); + t->Branch("q2max",&q2b,"q2max/D"); + t->Branch("error",&error,"error/D"); + t->Branch("error_up",&error_up,"error_up/D"); + t->Branch("error_down",&error_down,"error_down/D"); + t->Branch("start_value",&start_value,"start_value/D"); + t->Branch("migrad",&migrad,"migrad/I"); + t->Branch("status_cov",&status_cov,"status_cov/I"); + t->Branch("nominal_value",&nominal_value,"nominal_value/D"); + t->Branch("nominal_error",&nominal_error,"nominal_error/D"); + t->Branch("index",¶m_index, "index/I"); + + std::stringstream corr_stream; + corr_stream << "correlations[" << corr_max << "]/D"; + t->Branch("correlations",&tmp_corr,corr_stream.str().c_str()); + + UInt_t startPDF = 0; + UInt_t stopPDF = pdf_idx.size(); + if(SimultaneousMoM) + startPDF = stopPDF - 1; + else if(OneFit) + stopPDF = 1; + + for(UInt_t i = startPDF; i < stopPDF; i++){ + + pdf = i + 1; + + for(UInt_t b = 0; b < nBins; b++){ + fcnc::parameter* par = theParams[b].at(i)->get_parameter(p); + + UInt_t paridx = 0; + while(par->get_name() != parname.c_str()){ + par = theParams[b].at(i)->get_parameter(paridx); + paridx++; + if(paridx == theParams[b].at(i)->nparameters()){ + spdlog::warn("Parameter '"+parname+"' not found in PDF{0:d}. Continue with next PDF.",i); + break; + } + } + if(paridx == theParams[b].at(i)->nparameters()) + break; + + bin = b; + q2a = opts.TheQ2binsmin[b]; + q2b = opts.TheQ2binsmax[b]; + value = par->get_value(); + error = par->get_error(); + error_up = par->get_error_up(); + error_down = par->get_error_down(); + start_value = par->get_start_value(); + nominal_value = par->get_start_value(); + if(SimultaneousFit){ + migrad = fit_results[b].at(0) % 100; + status_cov = fit_results[b].at(0) / 100; + } + else{ + migrad = fit_results[b].at(i) % 100; + status_cov = fit_results[b].at(i) / 100; + } + if (opts.minos_errors){ + if (error_up==0.0 && value < par->get_max()) + error_up = par->get_max() - value; + if (error_down==0.0 && value > par->get_min()) + error_down = par->get_min() - value;//needs to be negative + } + + for (unsigned int l = 0; l < corr_max; l++) + tmp_corr[l] = 0.0; + for (unsigned int l = 0; l < par->correlations.size(); l++) + tmp_corr[l] = par->correlations.at(l); + t->Fill(); + } + } + t->Write(); + delete t; + param_index++; + } + } + fout->Close(); + return 0; +} diff --git a/Code/FCNCFitter/sources/Run/momfit.hh b/Code/FCNCFitter/sources/Run/momfit.hh new file mode 100644 index 0000000..3634c83 --- /dev/null +++ b/Code/FCNCFitter/sources/Run/momfit.hh @@ -0,0 +1,15 @@ +//Renata Kopecna + +#ifndef MOMFIT_HH +#define MOMFIT_HH + +#include +////////////////////////// +// INIT VALUES FOR FITS // +////////////////////////// + +int momfit(fcnc::options opts, + bool fitReference, bool fitSignalMC, bool fitData, bool blind, + bool Fit1bin, bool Fit2bins, bool FitAllbins); + +#endif // MOMFIT_HH diff --git a/Code/FCNCFitter/sources/Run/multifit.cc b/Code/FCNCFitter/sources/Run/multifit.cc new file mode 100644 index 0000000..6114744 --- /dev/null +++ b/Code/FCNCFitter/sources/Run/multifit.cc @@ -0,0 +1,230 @@ +//Renata Kopecna + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace std; +using namespace fcnc; + +multifit::multifit(options* o): + opts(o) +{ + output = new TFile(("result" + opts->name + ".root").c_str(), "RECREATE"); +}; + +multifit::~multifit(){ + output->Write(); + output->Close(); + delete output; +}; + +void multifit::fit_gaussian(vector& values, double& gauss_mean, double& sigma_gauss_mean, double& gauss_width, double& sigma_gauss_width, double& chi_squared) const +{ + + double max = *max_element(std::begin(values), std::end(values)); + double min = *min_element(std::begin(values), std::end(values)); + + double mean=0.0; + double rms=0.0; + TTree* t = new TTree("tree", "pull values"); + double value; + TBranch *branch = t->Branch("value",&value,"value/D"); + for (unsigned int i = 0; i < values.size(); i++) { + value = values.at(i); + branch->Fill(); + t->Fill(); + mean += value/values.size(); + } + for (unsigned int i = 0; i < values.size(); i++){ + value = values.at(i); + rms += (value - mean)*(value - mean)/values.size(); + } + rms = sqrt(rms); + TF1* f1 = new TF1("f1", "gaus(0)/sqrt(2.0*3.1415926536)/abs([2])", min-5.0, max+5.0); + f1->SetParameters(1.0,mean,rms); + //f1->SetParLimits(0, 1.0, 1.0); + f1->FixParameter(0, 1.0); + t->UnbinnedFit("f1", "value"); + gauss_mean = f1->GetParameter(1); + sigma_gauss_mean = f1->GetParError(1); + gauss_width = f1->GetParameter(2); + sigma_gauss_width = f1->GetParError(2); + delete f1; + delete t; +}; + +void multifit::update_pull(parameter* p, vector& values, vector& errors, double& gauss_mean, double& sigma_gauss_mean, double& gauss_width, double& sigma_gauss_width, double& chi_squared, string appendix) const +{ + unsigned int runs=values.size(); + string parname(p->get_name()); + string descr(p->get_description()); + gStyle->SetOptStat(0); + gStyle->SetOptFit(0); + //finally the pull histo + TH1D* pull_histo = new TH1D((parname + "_pull_").c_str(), + (descr + " pull distribution;" + "(" + descr + + "^{fitted}-" + descr + + "^{generated})/#sigma").c_str(), + 50, -5.0, 5.0);//sensible for pulls + //fill histos + //this is done every time because the time is negligible + double start_value = p->get_start_value(); + vector pull_values; + for (unsigned int k=0; kFill(pull); + pull_values.push_back(pull); + } + } + fit_gaussian(pull_values, gauss_mean, sigma_gauss_mean, gauss_width, sigma_gauss_width, chi_squared); + + TCanvas *pull_canvas = new TCanvas((parname + "_pull_" + appendix).c_str(), "Bs Likelihood Analysis: Pull distribution",1600,1200); + pull_canvas->cd(); + pull_histo->Draw(); + TF1 *g = new TF1("g","[0]*exp(-(x-[1])*(x-[1])/2.0/[2]/[2])",-5.0,5.0); + + //for normalization: multiply with dx*histint = width/Nbins*histint + g->SetParameters(1.0/sqrt(2.0*TMath::Pi())/gauss_width*10.0/50.0*pull_histo->Integral(), gauss_mean, gauss_width); + g->Draw("same"); + TPaveText* text = new TPaveText(0.6,0.7,0.88,0.88,"NDC"); + text->SetFillColor(0); + std::ostringstream stream_mean; + stream_mean << "Mean: " << fixed << setprecision(3) << gauss_mean << "#pm" << sigma_gauss_mean; + std::ostringstream stream_width; + stream_width << "Width: " << fixed << setprecision(3) << gauss_width << "#pm" << sigma_gauss_width; + text->AddText(stream_mean.str().c_str()); + text->AddText(stream_width.str().c_str()); + text->Draw("same"); + + string afilename; //TODO: move to paths + if (appendix != "") afilename = "plots/pull_" + parname + "_" + appendix + ".eps"; + else afilename = "plots/pull_" + parname + ".eps"; + if (opts->write_eps)pull_canvas->Print(afilename.c_str(), "eps"); + output->cd(); + pull_canvas->Write(); + delete text; + delete g; + delete pull_histo; + delete pull_canvas; +} + +void multifit::update_value(parameter * p, vector& values, vector& errors, double& gauss_mean, double& sigma_gauss_mean, double& gauss_width, double& sigma_gauss_width, double& chi_squared, string appendix) const +{ + unsigned int runs=values.size(); + string parname(p->get_name()); + string descr(p->get_description()); + //first find min and max values + double max = *max_element(std::begin(values), std::end(values)); + double min = *min_element(std::begin(values), std::end(values)); + double width = max-min; + double hist_min = min - 0.5*width; + double hist_max = max + 0.5*width; + gStyle->SetOptStat(0); + gStyle->SetOptFit(0); + TH1D* value_histo = new TH1D((parname+"_values").c_str(), + (descr + ";" + descr).c_str(), + 50, hist_min, hist_max); + for (unsigned int k=0; kFill(values.at(k)); + } + + fit_gaussian(values, gauss_mean, sigma_gauss_mean, gauss_width, sigma_gauss_width, chi_squared); + TCanvas *value_canvas = new TCanvas((parname + "_value_" + appendix).c_str(), "Bs Likelihood Analysis: Value distribution",1600,1200); + value_canvas->cd(); + value_histo->Draw(); + TF1 *g = new TF1("g","[0]*exp(-(x-[1])*(x-[1])/2.0/[2]/[2])",-5.0,5.0); + g->SetParameters(1.0/sqrt(2.0*TMath::Pi())/gauss_width*(hist_max-hist_min)/50.0*value_histo->Integral(), gauss_mean, gauss_width); + g->Draw("same"); + + TPaveText* text = new TPaveText(0.6,0.7,0.88,0.88,"NDC"); + text->SetFillColor(0); + std::ostringstream stream_mean; + stream_mean << "Mean: " << fixed << setprecision(3) << gauss_mean << "#pm" << sigma_gauss_mean; + std::ostringstream stream_width; + stream_width << "Width: " << fixed << setprecision(3) << gauss_width << "#pm" << sigma_gauss_width; + text->AddText(stream_mean.str().c_str()); + text->AddText(stream_width.str().c_str()); + text->Draw("same"); + + //TODO: move + string afilename; + if (appendix != "") afilename = "plots/value_" + parname + "_" + appendix + ".eps"; + else afilename = "plots/value_" + parname + ".eps"; + if (opts->write_eps) value_canvas->Print(afilename.c_str(), "eps"); + output->cd(); + value_canvas->Write(); + delete text; + delete value_histo; + delete value_canvas; + delete g; +} + +void multifit::update_error(parameter* p, vector& values, vector& errors, double& gauss_mean, double& sigma_gauss_mean, double& gauss_width, double& sigma_gauss_width, double& chi_squared, string appendix) const +{ + unsigned int runs=values.size(); + string parname(p->get_name()); + string descr(p->get_description()); + //then find min and max errors + double max = *max_element(std::begin(errors), std::end(errors)); + double min = *min_element(std::begin(errors), std::end(errors)); + + double width = max - min; + double hist_min = min - 0.5*width; + double hist_max = max + 0.5*width; + gStyle->SetOptStat(0); + gStyle->SetOptFit(0); + TH1D* error_histo = new TH1D((parname+"_errors").c_str(), + ("#sigma(" + descr + ");#sigma(" + descr + ")").c_str(), + 100, hist_min, hist_max); + for (unsigned int k=0; kFill(errors.at(k)); + } + fit_gaussian(errors, gauss_mean, sigma_gauss_mean, gauss_width, sigma_gauss_width, chi_squared); + TCanvas *error_canvas = new TCanvas((parname + "_error_" + appendix).c_str(), "Bs Likelihood Analysis: Error distribution",1600,1200); + + error_canvas->cd(); + error_histo->Draw(); + TF1 *g = new TF1("g","[0]*exp(-(x-[1])*(x-[1])/2.0/[2]/[2])",-5.0,5.0); + g->SetParameters(1.0/sqrt(2.0*TMath::Pi())/gauss_width*(hist_max-hist_min)/100.0*error_histo->Integral(), gauss_mean, gauss_width); + g->Draw("same"); + TPaveText* text = new TPaveText(0.6,0.7,0.88,0.88,"NDC"); + text->SetFillColor(0); + std::ostringstream stream_mean; + stream_mean << "Mean: " << fixed << setprecision(3) << gauss_mean << "#pm" << sigma_gauss_mean; + std::ostringstream stream_width; + stream_width << "Width: " << fixed << setprecision(3) << gauss_width << "#pm" << sigma_gauss_width; + text->AddText(stream_mean.str().c_str()); + text->AddText(stream_width.str().c_str()); + text->Draw("same"); + + //TODO: move + string afilename; + + if (appendix != "") afilename = "plots/error_" + parname + "_" + appendix + ".eps"; + else afilename = "plots/error_" + parname + ".eps"; + + if (opts->write_eps) error_canvas->Print(afilename.c_str(), "eps"); + + output->cd(); + error_canvas->Write(); + delete text; + delete error_histo; + delete error_canvas; + delete g; +} diff --git a/Code/FCNCFitter/sources/Run/multifit.hh b/Code/FCNCFitter/sources/Run/multifit.hh new file mode 100644 index 0000000..5972675 --- /dev/null +++ b/Code/FCNCFitter/sources/Run/multifit.hh @@ -0,0 +1,44 @@ +//Renata Kopecna +/** + * @file multifit.hh + * @author Christoph Langenbruch + * @date 2009-03-18 + * + */ + +#ifndef MULTIFIT_H +#define MULTIFIT_H + +#include +#include +#include +#include + +namespace fcnc { + //Forward declaration + class parameter; + + +///base class for analysis classes which do multiple fits, e.g. toystudy +class multifit { +protected: + ///set of options + options* opts; + ///constructor + multifit(options* o); + ///destructor + virtual ~multifit(); + ///unbinned likelihood fit of gaussian + void fit_gaussian(std::vector& values, double& gauss_mean, double& sigma_gauss_mean, double& gauss_width, double& sigma_gauss_width, double& chi_squared) const; + ///fits a gaussian to the pull values + void update_pull(parameter* p, std::vector& values, std::vector& errors, double& gauss_mean, double& sigma_gauss_mean, double& gauss_width, double& sigma_gauss_width, double& chi_squared, std::string appendix="") const; + ///fits a gaussian to the values + void update_value(parameter* p, std::vector& values, std::vector& errors, double& gauss_mean, double& sigma_gauss_mean, double& gauss_width, double& sigma_gauss_width, double& chi_squared, std::string appendix="") const; + ///fits a gaussian to the errors + void update_error(parameter* p, std::vector& values, std::vector& errors, double& gauss_mean, double& sigma_gauss_mean, double& gauss_width, double& sigma_gauss_width, double& chi_squared, std::string appendix="") const; + TFile* output; +}; + +} + +#endif diff --git a/Code/FCNCFitter/sources/Run/pulls.cc b/Code/FCNCFitter/sources/Run/pulls.cc new file mode 100644 index 0000000..e4f94f7 --- /dev/null +++ b/Code/FCNCFitter/sources/Run/pulls.cc @@ -0,0 +1,628 @@ +//Renata Kopecna + + +#include + +#include +#include +#include + +#include "folder.hh" +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +////////////////////////// +// INIT VALUES FOR FITS // +////////////////////////// + + //Do they change anywhere or can I set them in a header? +//TODO replace by the parameters->init +double f_m_B[4] = {5282.32, 5282.08, 5278.57, 5279.48}; +double f_lambda1[4] = {-0.00386, -0.00610, -0.00362, -0.00578}; +double f_lambda2[4] = {-0.03320, -0.00120, -0.04600, -0.00100}; +double f_alpha_1[4] = { 1.7910, 1.8000, 1.6510, 1.5400}; +double f_alpha_2[4] = { 2.3200, 2.4300, 2.0100, 2.2500}; +double f_n_1[4] = { 1.4400, 1.4900, 1.6800, 1.6100}; +double f_n_2[4] = { 2.8900, 3.7000, 3.8700, 3.7000}; +double f_sigma_1[4] = {14.8300, 15.4800, 14.8400, 14.4}; +double f_sigma_2[4] = {14.0700, 13.1000, 15.6200, 13.3}; +double f_f_CB[4] = { 0.6360, 0.3600, 0.3040, 0.6200}; +double f_m_scale[4] = { 1.1814, 1.0648, 1.1547, 1.1168}; + + +//TODO posibly to be deleted so ignoring for now! +void do_pulls(fcnc::options opts, bool doToyPulls, bool doMCPulls, int job_id, double SwaveFraction, UInt_t nPulls, Double_t nToyEvents, UInt_t nMCEvents ,std::string angularsuffix, bool Fit1bin, bool Fit2bins, bool FitAllbins ){ //TODO: change to int and return some errors possibly + //TODO: figure out jobs_to_do and job_id, but there is no manipulation with it, so so far so good + //Why is it not opts.job_id? + if(doToyPulls)std::cout << "[INFO]\t\tGetting pull distributions and test fits from Toy Events!" << std::endl; + + //disable eps output if job_id is larger than -1. This is needed for HD cluster jobs: + if(job_id > -1)opts.write_eps = false; + + //have extra option for the usage of binning: + const bool UseBinnedFit = false; + + opts.fit_fl = false; + opts.fit_afb = false; + opts.only_angles = false; + opts.only_Bmass = false; + if(opts.only_Bmass) opts.only_angles = false; + + opts.use_angular_acc = true; + opts.use_weighted_bkg = true; + opts.fit_full_angular_bkg = true; + opts.always_generate_full_angular = true; + opts.weighted_fit = true; + + opts.swave = true; + opts.shift_lh = false; + + opts.squared_hesse = true; + opts.minos_errors = false; + + opts.generate_mkpi = true; + opts.fit_mkpi = false; + opts.use_mkpi = true; + opts.flat_bkg = false; + + //change the label of the produced plots: + opts.plot_label = "LHCb toys"; + + //SM + std::vector s1s, s1c, s2s, s2c, s3, s4, s5, s6s, s6c, s7, s8, s9; + std::vector f_signal, f_bckgnd, f_bckcoeff; + double f_sig_norm = 0.0; + std::vector events_per_bin; + + //determine number of bins: + const UInt_t nBins = UseBinnedFit ? opts.TheQ2binsmin.size() : 1; + if(!UseBinnedFit){ + opts.TheQ2binsmin = {8.68}; + opts.TheQ2binsmax = {10.09}; + } + + //create TTree to save pull values + double treeValue, treeStart, treeError, treeErrorUp, treeErrorDown; + UInt_t treeBin, treeFitNumber, treeFitResult, treeIndex; + + TTree * T = nullptr; + if(doToyPulls || doMCPulls){ + T = new TTree("PullTree", "PullTree"); + T->Branch("v", &treeValue, "v/D"); + T->Branch("i", &treeIndex, "i/i"); + T->Branch("s", &treeStart, "s/D"); + T->Branch("e", &treeError, "e/D"); + T->Branch("eu", &treeErrorUp, "eu/D"); + T->Branch("ed", &treeErrorDown, "ed/D"); + T->Branch("b", &treeBin , "b/i"); + T->Branch("f", &treeFitNumber, "f/i"); + T->Branch("r", &treeFitResult, "r/i"); + T->Branch("fs", &SwaveFraction, "fs/D"); + } + + //TODO: fix the name of the genLvl root file + basic_params params_genLvl = basic_params(); + params_genLvl.Run = 2; + params_genLvl.year = 2017; + params_genLvl.nBins = nBins; + std::string genPath = final_result_name_genLvlMC(params_genLvl, nBins, false, true, false); + + s1s = load_param_values_into_vector("S1s",genPath); + s3 = load_param_values_into_vector("S3", genPath); + s4 = load_param_values_into_vector("S4", genPath); + s5 = load_param_values_into_vector("S5", genPath); + s6s = load_param_values_into_vector("S6s",genPath); + s7 = load_param_values_into_vector("S7", genPath); + s8 = load_param_values_into_vector("S8", genPath); + s9 = load_param_values_into_vector("S9", genPath); + + if(UseBinnedFit){ + if(nBins == 8){ + f_signal = {101., 61., 62., 96., 125., 124., 129., 69.}; + f_bckgnd = {131., 206., 279., 358., 358., 247., 158., 93.}; + f_bckcoeff = {-0.0052, -0.0084, -0.0088, -0.0031, -0.0028, -0.0158, -0.0079, -0.0058}; //for notation: exp(lambda * x) + + //results from Signal channel generator level MC fits: + s1c = { 0.2450, 0.6996, 0.7993, 0.7384, 0.6414, 0.4201, 0.3513, 0.3344}; + s2s = { 0.1448, 0.0749, 0.0514, 0.0662, 0.0900, 0.1449, 0.1620, 0.1662}; + s2c = {-0.1953,-0.6639,-0.7774,-0.7254,-0.6334,-0.4171,-0.3497,-0.3332}; + s3 = { 0.0000, 0.0020,-0.0080,-0.0120,-0.0240,-0.0620,-0.1520,-0.2330}; + s4 = { 0.0870, 0.0040,-0.1080,-0.1950,-0.2510,-0.2770,-0.2900,-0.3040}; + s5 = { 0.2440, 0.0950,-0.1590,-0.3050,-0.4140,-0.4210,-0.3400,-0.2490}; + s6s = {-0.1270,-0.2070,-0.0860, 0.0950, 0.3020, 0.5140, 0.5570, 0.4700}; + s6c = { 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000}; + s7 = {-0.0060,-0.0100,-0.0030, 0.0020, 0.0030,-0.0020,-0.0020, 0.0050}; + s8 = { 0.0010,-0.0030,-0.0040,-0.0030,-0.0010, 0.0030,-0.0010, 0.0030}; + s9 = {-0.0020, 0.0000, 0.0020, 0.0040,-0.0020,-0.0010,-0.0010, 0.0010}; + + } + else if(nBins == 4){ + spdlog::error("YOU NEED TO UPDATE THESE FIRTS!"); + assert(0); + f_signal = {101., 61., 62., 96.}; + f_bckgnd = {131., 206., 279., 358.}; + f_bckcoeff = {-0.0052, -0.0084, -0.0088, -0.0031}; //for notation: exp(lambda * x) + + //results from Signal channel generator level MC fits: + s1s = { 0.5120, 0.1800, 0.1370, 0.1930}; + s1c = { 0.2450, 0.6996, 0.7993, 0.7384}; + s2s = { 0.1448, 0.0749, 0.0514, 0.0662}; + s2c = {-0.1953,-0.6639,-0.7774,-0.7254}; + s3 = { 0.0000, 0.0020,-0.0080,-0.0120}; + s4 = { 0.0870, 0.0040,-0.1080,-0.1950}; + s5 = { 0.2440, 0.0950,-0.1590,-0.3050}; + s6s = {-0.1270,-0.2070,-0.0860, 0.0950}; + s6c = { 0.0000, 0.0000, 0.0000, 0.0000}; + s7 = {-0.0060,-0.0100,-0.0030, 0.0020}; + s8 = { 0.0010,-0.0030,-0.0040,-0.0030}; + s9 = {-0.0020, 0.0000, 0.0020, 0.0040}; + } + else if(nBins == 2){ + f_signal = { 61.+ 62.+ 96.+125., 129.+69.}; + f_bckgnd = {206.+279.+358.+358., 158.+93.}; + f_bckcoeff = {-0.0064, -0.0065}; + + s1s = { 0.1959, 0.4917}; + s1c = { 0.7441, 0.3447}; + s2s = { 0.0646, 0.1636}; + s2c = {-0.7217, -0.3432}; + s3 = {-0.0042, -0.1747}; + s4 = { 0.1033, 0.2929}; + s5 = {-0.1458, -0.3157}; + s6s = { 0.0652, -0.5338}; + s6c = { 0.0000, 0.0000}; + s7 = { 0.0340, -0.0000}; + s8 = {-0.0115, -0.0002}; + s9 = { 0.0003, 0.0003}; + } + else { + spdlog::error("No SM values given for binning scheme with {0:d} q2 bins. Exit", nBins); + assert(0); + } + } + else{ + f_signal = {0.5}; + f_bckgnd = {0.5}; + f_bckcoeff = {-2.835e-3}; //for notation: exp(lambda * x) + s1s = { 0.2372}; + s1c = { 0.6863}; + s2s = { 0.0}; + s2c = {-0.6760}; + s3 = {-0.0107}; + s4 = { 0.2163}; + s5 = {-0.3806}; + s6s = {-0.1957}; + s6c = { 0.0}; + s7 = { 0.0290}; + s8 = {-0.0113}; + s9 = { 0.0003}; + } + + assert(f_signal.size() == f_bckgnd.size()); + f_sig_norm = std::accumulate(f_signal.begin(), f_signal.end(), 0.0) + + std::accumulate(f_bckgnd.begin(), f_bckgnd.end(), 0.0); + + for(UInt_t i = 0; i < f_signal.size(); i++){ + f_signal.at(i) /= f_sig_norm; + f_bckgnd.at(i) /= f_sig_norm; + } + + fcnc::folder fldr(&opts); + fcnc::fitter f(&opts); + fcnc::bu2kstarmumu_plotter thePlotter(&opts); + + std::vector< std::vector >theParameters; + std::vector< std::vector > thePDFs; + for(UInt_t c = 0; c < nBins; c++){ + //add vector of params to matrix: + std::vector params_per_bin; + params_per_bin.clear(); + theParameters.push_back(params_per_bin); + + //add vector of pdfs to matrix: + std::vector pdf_per_bin; + pdf_per_bin.clear(); + thePDFs.push_back(pdf_per_bin); + } + assert(theParameters.size() == nBins); + assert(thePDFs.size() == nBins); + + //pointers to current parameter, pdf and generator: + fcnc::bu2kstarmumu_parameters * params[nBins]; + fcnc::bu2kstarmumu_pdf * prob[nBins]; + fcnc::bu2kstarmumu_generator * gen = nullptr; + + std::vector fitresults; + std::vectorselection; + + //number of fits is either determined by the larger number of pulls or fits requested + UInt_t nFits = nPulls; + + //vectors to save values for pull plots: + std::vectorvar_indexs; + std::vector< std::vector< std::vector > >pull_values; + std::vector< std::vector< std::vector > >pull_errors; + std::vector< std::vector >pull_starts; + + + //initialize parameters, events and fitter for every FitTest: + for(UInt_t n = 0; n < nFits; n++){ + + //if binning is used, loop over the number of q2 bins, else only run loop once! + for(UInt_t b = 0; b < nBins; b++){ + + std::cout << std::endl; + std::cout << "****************************************" << std::endl; + std::cout << "[FIT]\t\tStarting fit >> " << n << " <<" << std::endl; + std::cout << "[FIT]\t\tIn bin >> " << b << " <<" << std::endl; + std::cout << "****************************************" << std::endl; + std::cout << std::endl; + + opts.swave = true; + + opts.q2_min = UseBinnedFit ? opts.TheQ2binsmin.at(b) : opts.TheQ2binsmin.front(); + opts.q2_max = UseBinnedFit ? opts.TheQ2binsmax.at(b) : opts.TheQ2binsmax.back(); + + if(n == 0){ + //initiate parameters for mass fit + params[b] = new fcnc::bu2kstarmumu_parameters(&opts); + params[b]->f_sig.init(f_signal.at(b)/(f_signal.at(b)+f_bckgnd.at(b)), 0.0, 1.0, 0.01); + if(params[b]->f_sig.get_value() == 0.0) + params[b]->m_b.init(PDGMASS_B, B_MASS_LOW, B_MASS_HIGH, 0.0); + else + params[b]->m_b.init(PDGMASS_B, B_MASS_LOW, B_MASS_HIGH, 0.01); + if(opts.twotailedcrystalball) + params[b]->m_res_1.init(1.0, 0.0, 1.0, 0.0); + else + params[b]->m_res_1.init(0.391, 0.0, 1.0, 0.0);// 0.01); + params[b]->fm_tau.init(1.0, 0.0, 1.0, 0.0); + if(opts.fit_lambda){ + if(params[b]->f_sig.get_value() == 1.0) + params[b]->m_lambda.init(f_bckcoeff.at(b), -1.0e-1, -1.0e-6, 0); + else + params[b]->m_lambda.init(f_bckcoeff.at(b), -1.0e-1, -1.0e-6, 1.0e-5); + params[b]->m_lambda_2.init(-1.664e-3, -1.0e-1, -1.0e-6, 0.0); + params[b]->m_tau.init( 1./2.835e-3, 100.0, 1.0e+4, 0.0); + params[b]->m_tau_2.init(1./1.664e-3, 0.0, 1.0e+4, 0.0); + } + else{ + params[b]->m_lambda.init(-1.0e-3, -1.0e-1, -1.0e-6, 0.0); + params[b]->m_lambda_2.init(-1.5e-3, -1.0e-1, -1.0e-6, 0.0); + params[b]->m_tau.init(-1./f_bckcoeff.at(b), 100.0, 1.0e+4, 1.0); + params[b]->m_tau_2.init(6.01e+2, 0.0, 1.0e+4, 0.0); + } + if(opts.twotailedcrystalball) + params[b]->m_sigma_1.init(f_sigma_1[n], 5.0, 200.0, 0.0);//, 0.1); + else{ + params[b]->m_sigma_1.init(f_sigma_1[n], 5.0, 200.0, 0.0);//, 0.1); + params[b]->m_sigma_2.init(f_sigma_2[n], 5.0, 200.0, 0.0);//, 0.1); + } + params[b]->alpha_1.init(f_alpha_1[n], 0.1, 10.0, 0.0);//, 0.15); + params[b]->alpha_2.init(f_alpha_2[n], 0.1, 10.0, 0.0);//, 0.20); + params[b]->n_1.init(f_n_1[n], 0.1, 15.0, 0.0);//, 2.0); + params[b]->n_2.init(f_n_2[n], 0.1, 10.0, 0.0);//, 0.16); + params[b]->m_scale.init(f_m_scale[n], 0.0, 2.0, 0.0); + + params[b]->load_only_Bmass_param_values("fitresult_SignalFit_MC_SimultaneousFit_2Dfit_bin"+std::to_string(b)+"_pdf"+std::to_string(n)+".txt"); + + //S-wave + double sWaveStepSize = 0.01; + params[b]->FS.init(SwaveFraction, 0.0, 1.0, sWaveStepSize); + + //B0 fit results + params[b]->SS1.init(-0.231, -1.0, 1.0, (opts.full_angular || opts.folding != 4 ? sWaveStepSize : 0.0)); + params[b]->SS2.init( 0.023, -1.0, 1.0, (opts.full_angular || opts.folding == 1 ? sWaveStepSize : 0.0)); + params[b]->SS3.init( 0.003, -1.0, 1.0, (opts.full_angular || opts.folding == 2 ? sWaveStepSize : 0.0)); + params[b]->SS4.init( 0.001, -1.0, 1.0, (opts.full_angular || opts.folding > 2 ? sWaveStepSize : 0.0)); + params[b]->SS5.init(-0.068, -1.0, 1.0, (opts.full_angular ? sWaveStepSize : 0.0)); + + if(opts.fit_mkpi || opts.use_mkpi){ + params[b]->gammakstar.init(0.0503, 0.01, 0.8, 0.001); //PDG value + params[b]->mkstar.init(PDGMASS_K_STAR_PLUS / 1000., 0.7, 1.2, 0.001); //PDG value + params[b]->gammakstarplus.init(0.236, 0.1, 1.0, 0.0); //PDG value + params[b]->mkstarplus.init(1.41, 1.2, 1.6, 0.0); //PDG value + params[b]->asphase.init(TMath::Pi(), 0.0, 2.0*TMath::Pi(), 0.0); + params[b]->a.init(1.95, 0.001, 20.0, 0.0); + params[b]->r.init(1.78, 0.001, 10.0, 0.0); + //background parameter + if(params[b]->f_sig() != 1.0){ + params[b]->cbkgmkpi0.init(1.0, -1.0, 1.0, 0.0); + params[b]->cbkgmkpi1.init(0.0, -1.0, 1.0, 0.01); + params[b]->cbkgmkpi2.init(0.0, -1.0, 1.0, 0.0); + params[b]->cbkgmkpi3.init(0.0, -1.0, 1.0, 0.0); + params[b]->cbkgmkpi4.init(0.0, -1.0, 1.0, 0.0); + opts.mkpi_threshold = false; + params[b]->nthreshold.init(1.5, 0.0, 15.0, 0.0); + } + } + + //define center of q2bin as effective q2: + params[b]->eff_q2.init((UseBinnedFit ? 0.5*(opts.TheQ2binsmin.at(b)+opts.TheQ2binsmax.at(b)) : 6.0), opts.TheQ2binsmin.front(), opts.TheQ2binsmax.back(), 0.0); + + //if only mass fit: do not active angles in fit, i.e. set stepsize to 0.0 + double angleStepSize = opts.only_Bmass ? 0.0 : 0.001; + if(params[b]->f_sig.get_value() == 0.0) + angleStepSize = 0.0; + if(opts.fit_fl) + //params[b]->Fl.init(3.0/4.0*(s1c[b]-s2c[b]/3.0), 0.0, 1.0, angleStepSize); + params[b]->Fl.init(1.0-4.0/3.0*s1s[b], 0.0, 1.0, angleStepSize); + else + params[b]->S1s.init(s1s[b], -1.0, 1.0, angleStepSize); + params[b]->S3.init(s3[b], -1.0, 1.0, angleStepSize/10.); + params[b]->S4.init(s4[b], -1.0, 1.0, (opts.full_angular || opts.folding == 1 ? angleStepSize : 0.0)); + params[b]->S5.init(s5[b], -1.0, 1.0, (opts.full_angular || opts.folding == 2 ? angleStepSize : 0.0)); + if(opts.fit_afb) + params[b]->Afb.init(3.0/4.0*s6s[b], -0.75, 0.75, (opts.full_angular || opts.folding == 0 ? angleStepSize: 0.0)); + else + params[b]->S6s.init(s6s[b], -1.0, 1.0, (opts.full_angular || opts.folding == 0 ? angleStepSize : 0.0)); + params[b]->S7.init(s7[b], -1.0, 1.0, (opts.full_angular || opts.folding == 3 ? angleStepSize/10. : 0.0)); + params[b]->S8.init(s8[b], -1.0, 1.0, (opts.full_angular || opts.folding == 4 ? angleStepSize/10. : 0.0)); + params[b]->S9.init(s9[b], -1.0, 1.0, (opts.full_angular || opts.folding == 0 ? angleStepSize/100. : 0.0)); + + if(!opts.flat_bkg){ + //ctl + params[b]->cbkgctl0.init(1.0, -1.0, 1.0, 0.0); + params[b]->cbkgctl2.init(0.0, -1.0, 1.0, 0.01); + params[b]->cbkgctl4.init(0.0, -1.0, 1.0, 0.0); + if(opts.full_angular || opts.folding == 0){ + params[b]->cbkgctl1.init(0.0, -1.0, 1.0, 0.01); + params[b]->cbkgctl3.init(0.0, -1.0, 1.0, 0.0); + } + else{ + params[b]->cbkgctl1.init(0.0, -1.0, 1.0, 0.0); + params[b]->cbkgctl3.init(0.0, -1.0, 1.0, 0.0); + } + + //ctk + params[b]->cbkgctk0.init(1.0, -1.0, 1.0, 0.0); + params[b]->cbkgctk2.init(0.05, -1.0, 1.0, 0.01); + params[b]->cbkgctk4.init(0.0, -1.0, 1.0, 0.0); + if(opts.full_angular || opts.folding != 4){ + params[b]->cbkgctk1.init(0.1, -1.0, 1.0, 0.01); + params[b]->cbkgctk3.init(0.0, -1.0, 1.0, 0.0); + } + else{ + params[b]->cbkgctk1.init(0.0, -1.0, 1.0, 0.0); + params[b]->cbkgctk3.init(0.0, -1.0, 1.0, 0.0); + } + + //phi + params[b]->cbkgphi0.init(1.0, -1.0, 1.0, 0.0); + params[b]->cbkgphi2.init(0.0, -1.0, 1.0, 0.0); + params[b]->cbkgphi4.init(0.0, -1.0, 1.0, 0.0); + if(opts.full_angular || opts.folding == 0 || opts.folding == 3 || opts.folding == 4){ + params[b]->cbkgphi1.init(0.0, -1.0, 1.0, 0.0); + params[b]->cbkgphi3.init(0.0, -1.0, 1.0, 0.0); + } + else{ + params[b]->cbkgphi1.init(0.0, -1.0, 1.0, 0.0); + params[b]->cbkgphi3.init(0.0, -1.0, 1.0, 0.0); + } + + params[b]->load_only_bckgnd_param_values(("fitresult_OnlyBckgnd_bin"+std::to_string(b)+".txt").c_str()); + + } + } + else{ + //S-wave + double sWaveStepSize = 0.01; + params[b]->FS.init(SwaveFraction, 0.0, 1.0, sWaveStepSize); + /* + //JPSI Fit results + params[b]->SS1.init( 0.549, -1.0, 1.0, (opts.full_angular || opts.folding != 4 ? sWaveStepSize : 0.0)); + params[b]->SS2.init(-0.128, -1.0, 1.0, (opts.full_angular || opts.folding == 1 ? sWaveStepSize : 0.0)); + params[b]->SS3.init( 0.003, -1.0, 1.0, (opts.full_angular || opts.folding == 2 ? sWaveStepSize : 0.0)); + params[b]->SS4.init(-0.006, -1.0, 1.0, (opts.full_angular || opts.folding > 2 ? sWaveStepSize : 0.0)); + params[b]->SS5.init(-0.149, -1.0, 1.0, (opts.full_angular ? sWaveStepSize : 0.0)); +*/ + + //B0 fit results + params[b]->SS1.init(-0.231, -1.0, 1.0, (opts.full_angular || opts.folding != 4 ? sWaveStepSize : 0.0)); + params[b]->SS2.init( 0.023, -1.0, 1.0, (opts.full_angular || opts.folding == 1 ? sWaveStepSize : 0.0)); + params[b]->SS3.init( 0.003, -1.0, 1.0, (opts.full_angular || opts.folding == 2 ? sWaveStepSize : 0.0)); + params[b]->SS4.init( 0.001, -1.0, 1.0, (opts.full_angular || opts.folding > 2 ? sWaveStepSize : 0.0)); + params[b]->SS5.init(-0.068, -1.0, 1.0, (opts.full_angular ? sWaveStepSize : 0.0)); + params[b]->reset_parameters(); + + } + + //create vectors to save parameter values for pull plots: + if(n == 0){ + if(doToyPulls || doMCPulls){ + UInt_t pp = 0; + for(UInt_t p = 0; p < params[b]->nparameters(); p++){ + if(params[b]->get_parameter(p)->get_step_size() != 0.0){ + if(b == 0){ + std::vector< std::vector >pulls_per_parameter; + pull_values.push_back(pulls_per_parameter); + + std::vector< std::vector >errors_per_parameter; + pull_errors.push_back(errors_per_parameter); + + std::vectorstarts_per_parameter; + pull_starts.push_back(starts_per_parameter); + + var_indexs.push_back(p); + } + //check that vectors have same size and that no alloc error occurs: + assert(pp < pull_values.size()); + assert(var_indexs.size() == pull_values.size()); + assert(pp < pull_errors.size()); + assert(var_indexs.size() == pull_errors.size()); + assert(pp < pull_starts.size()); + assert(var_indexs.size() == pull_starts.size()); + + //save vectors for values and start values to matrices + std::vectorpulls_per_param_per_bin; + pull_values.at(pp).push_back(pulls_per_param_per_bin); + std::vectorerrors_per_param_per_bin; + pull_errors.at(pp).push_back(errors_per_param_per_bin); + pull_starts.at(pp).push_back(params[b]->get_parameter(p)->get_start_value()); + + //increase parameter index: + pp++; + } + } + } + } + + //pdf + prob[b] = new fcnc::bu2kstarmumu_pdf(&opts, params[b]); + if(opts.use_angular_acc || opts.weighted_fit){ + prob[b]->load_coeffs_eff_phsp_4d(); + } + prob[b]->update_cached_normalization(params[b]); + + //create vector with events according to the requested fits/pulls + selection.clear(); + + Double_t nEvents = 0.; + + if(UseBinnedFit){ + nEvents *= f_signal.at(b)+f_bckgnd.at(b); + } + else + nEvents = nToyEvents; + + std::cout << "Generate " << nEvents << " events!" << std::endl; + gen = new fcnc::bu2kstarmumu_generator(&opts); + selection = gen->generate(nEvents, params[b], prob[b]); + //delete gen; + if(!opts.full_angular && opts.always_generate_full_angular){ + for(UInt_t ee = 0; ee < selection.size(); ee++){ + fldr.fold(&selection.at(ee)); + } + } + + //check if all angles are almost 0.0 + if(false){ + for(UInt_t i = 0; i < selection.size(); i++) + if((fabs(selection.at(i).costhetak) < 0.001) && (fabs(selection.at(i).costhetal) < 0.001) && (fabs(selection.at(i).phi) < 0.001)) + std::cout << "[WARNING]\tEvent" << i << "\tctk: " << selection.at(i).costhetak << "\tctl: " << selection.at(i).costhetal << "\tphi: " << selection.at(i).phi << std::endl; + } + + if(n == 0)events_per_bin.push_back(selection.size()); + + //deactive the S-wave for the fit! + /* + opts.swave = false; + params[b]->FS.init(0.0, 0.0, 1.0, 0.0); + params[b]->SS1.init( 0.0, -1.0, 1.0, 0.0); + params[b]->SS2.init( 0.0, -1.0, 1.0, 0.0); + params[b]->SS3.init( 0.0, -1.0, 1.0, 0.0); + params[b]->SS4.init( 0.0, -1.0, 1.0, 0.0); + params[b]->SS5.init( 0.0, -1.0, 1.0, 0.0); + */ + //set values to jpsi results for the fit! + params[b]->FS.init(0.0, 0.0, 1.0, 0.0); + params[b]->SS1.init( 0.549, -1.0, 1.0, 0.0); + params[b]->SS2.init(-0.128, -1.0, 1.0, 0.0); + params[b]->SS3.init( 0.003, -1.0, 1.0, 0.0); + params[b]->SS4.init(-0.006, -1.0, 1.0, 0.0); + params[b]->SS5.init(-0.149, -1.0, 1.0, 0.0); + + //make sure that the correct coefficients are chosen for the fit: + if(!opts.full_angular && (opts.use_angular_acc || opts.weighted_fit) && opts.always_generate_full_angular){ + prob[b]->load_coeffs_eff_phsp_4d(); + prob[b]->update_cached_normalization(params[b]); + } + + //fit the events: + bool do_fit = true; + int fitresult = 0; + if(do_fit){ + fitresult = f.fit(prob[b], params[b], &selection); + } + else{ //don't fit, just update the efficiencies + fitresult = 300; + if(opts.use_angular_acc || opts.weighted_fit){ + prob[b]->update_cached_efficiencies(params[b], &selection); + } + } + + fitresults.push_back(fitresult); + //nametag per bin! + std::string plotname; + plotname = "ToyGen_"+std::to_string(nToyEvents)+"ToyEvents_FS_"+std::to_string(SwaveFraction)+"_"; + + plotname.append(angularsuffix); + if(UseBinnedFit){ + plotname.append("_bin"+std::to_string(b)); + if(Fit1bin) + plotname.append("_1BIN"); + if(Fit2bins) + plotname.append("_2BINS"); + if(FitAllbins) + plotname.append("_9BINS"); + } + + //plot the current pdf with event data: + if(n == 0 && opts.write_eps){ + std::cout << "PLOT: " << selection.size() << " events" << std::endl; + thePlotter.plot_data(prob[b], params[b], &selection, get_PullPlot_path(), plotname+"_Fit"+std::to_string(n), true); + + //add pdfs for all binning: + thePDFs.at(b).push_back(prob[b]); + theParameters.at(b).push_back(params[b]); + + } + + //save param values to pull_values vector: + if(doToyPulls){ + for(UInt_t p = 0; p < var_indexs.size(); p++){ + int index = var_indexs.at(p); + + double val = params[b]->get_parameter(index)->get_value(); + double err = params[b]->get_parameter(index)->get_error(); + + pull_values.at(p).at(b).push_back(val); + pull_errors.at(p).at(b).push_back(err); + + //save values to tree: + treeValue = params[b]->get_parameter(index)->get_value(); + treeStart = params[b]->get_parameter(index)->get_start_value(); + treeError = params[b]->get_parameter(index)->get_error(); + treeErrorUp = params[b]->get_parameter(index)->get_error_up(); + treeErrorDown = params[b]->get_parameter(index)->get_error_down(); + + treeIndex = index; + treeBin = b; + treeFitNumber = n; + treeFitResult = fitresult; + + //treeVarName = params[b]->get_parameter(index)->get_name(); + //treeVarDesc = params[b]->get_parameter(index)->get_description(); + + T->Fill(); + + } + } + } + } + + //save TTree to .root file: + if(doToyPulls){ + TFile * F = new TFile(("PullResults_" + +std::to_string(job_id == -10 ? nMCEvents : nToyEvents) + +(job_id == -10 ? "_MC_" : "_Toys_") + +std::to_string(nPulls)+"_Fits_" + +angularsuffix + +"_F_S_"+std::to_string(SwaveFraction) + +(job_id >= 0 ? "_job"+std::to_string(job_id) : "") + +".root").c_str(), "RECREATE"); + F->cd(); + T->Write(); + F->Close(); + delete T; + } +} diff --git a/Code/FCNCFitter/sources/Run/pulls.hh b/Code/FCNCFitter/sources/Run/pulls.hh new file mode 100644 index 0000000..9c97dd1 --- /dev/null +++ b/Code/FCNCFitter/sources/Run/pulls.hh @@ -0,0 +1,11 @@ +//Renata Kopecna + + +#ifndef PULLS_HH +#define PULLS_HH + +#include + +void do_pulls(fcnc::options opts, bool doToyPulls, bool doMCPulls, int job_id , double SwaveFraction, UInt_t nPulls, Double_t nToyEvents, UInt_t nMCEvents, std::string angularsuffix, bool Fit1bin, bool Fit2bins, bool FitAllbins); + +#endif // PULLS_HH diff --git a/Code/FCNCFitter/sources/Run/toysfit.cc b/Code/FCNCFitter/sources/Run/toysfit.cc new file mode 100644 index 0000000..6162ac0 --- /dev/null +++ b/Code/FCNCFitter/sources/Run/toysfit.cc @@ -0,0 +1,487 @@ +//Renata Kopecna + +#include +#include +#include +#include +#include +#include +#include "generatetoys.hh" +#include +#include +#include +#include + +#include + +//Fit the toys and save results somewhere +int toysfit(fcnc::options opts, unsigned int nBins, bool fitReference, basic_params params, bool onlySig, bool onlyBkg){ + + opts.job_id = params.jobID; //Just to be sure + spdlog::info("[TOYSFIT]\t Starting fit with jobID {0:d}", opts.job_id); + + //actually fit the toy events + const bool do_fit = true; + if(!do_fit) spdlog::warn("Fitting of the toy sample is disabled. Set hardcoded 'do_fit' to true in toysfit.cc"); + //It is useful to save the generated toys in order to debug + const bool SaveTheToys = params.index==-1; + const bool SaveProjections = params.index==-1; + opts.plot_folder = get_ToysFitPlot_path(params); + const bool save_init = (params.index==-1 || params.jobID ==0); + if(!save_init)spdlog::warn("Saving the initialised parameters for the toy generation is disabled. Set hardcoded 'save_init' to true in toysfit.cc"); + + const bool bkgFromHighMass = true; + const bool bkgFromLowMass = false; + + const bool SimultaneousFit = true; + + //Fit ranges for angles + double angleStepSize = 0.01; + double PprimeRangeScale = 10.0; + double angleRange = 1.0; + if (params.usePprime) angleRange *= PprimeRangeScale; + + double swaveStepSize = 0.1; + + //Set what parameters to fix + fixConstr Bmass_FC(!fitReference || onlyBkg,false); //Fix/constrain B mass + fixConstr f_sig_FC(false,false); //Fix/constrain f_sig? + fixConstr ang_params_FC(false,false); //Fix/constrain angular parameters? + fixConstr mass_params_FC(true,false); //Fix/constrain mass parameters? + fixConstr bkg_ang_FC(false,false); //Fix/constrain angular background? + fixConstr bkg_Kpi_FC(false,false); //Fix/constrain Kst mass background? + fixConstr bkg_mass_FC(false, false); //Fix/constrain mass background? + //This boolean decides whether to fit the bkg with order of five or of two //TODO: Should be less hardcody + bool setCtkToTwo = !fitReference; + opts.bkg_order_costhetak = 5; + if(params.folding == 4 && !fitReference){ + setCtkToTwo = false; + opts.bkg_order_costhetak = 4; + } + opts.flat_bkg = false; + opts.fit_full_angular_bkg = true; //Do you want to fold also the bkg? + + //Init angular parameters according to SM (true) or previous measurements (false)? + opts.initSM = true; + + //Weighted fit + opts.weighted_fit = true; + + //Set s-wave parameters to fix + fixConstr gammakstar_FC(true,false); //Fix/constrain gammakstar + fixConstr gammakstarplus_FC(true,false); //Fix/constrain gammakstar + fixConstr sWave_FC(onlyBkg || !fitReference ,false); //Fix/constrain sWave parameters? + fixConstr FS_FC(onlyBkg || !fitReference,false); + //FS is fixed no matter what + //Fix to something else afterwards + bool changeFS = false; + + //Do or do not fit s-wave + opts.swave = !onlyBkg;//TODO + //Fit kpi or not + opts.fit_mkpi = opts.swave || onlyBkg; + + //Quick sanity checks + if (onlyBkg && onlySig){ + spdlog::error("Cannot have onlyBkg && onlySig! Returning."); + return 1; + } + + if (bkgFromHighMass && bkgFromLowMass){ + spdlog::error("Cannot have background taken only from upper and only from lower mass sideband at the same time! Returning."); + return 1; + } + + //Save plots? + opts.write_eps = SaveProjections; + opts.write_pdf = false; + //Plot less bins for signal channel as the stats are sad there + if (!fitReference) opts.plots_m_bins = 30; + //Plot less bins for signal channel as the stats are sad there + if (!fitReference) opts.plots_mkpi_bins = 20; + + //Fit both mass and angles, use lambda for bkg fit + opts.only_angles = false; + opts.only_Bmass = false; + opts.only_mkpi = false; + + //Use weights and squared hesse + opts.shift_lh = false; + opts.use_angular_acc = false; + opts.hesse_postrun = true; + opts.squared_hesse = true;//!(params.index == -1);// fitReference; + opts.minos_errors = false;//(params.index == -1); //!fitReference; + opts.multiply_eff = false; //Toy generated events have saved acceptance weights! + + //Fit angular BKG + opts.individual_penalties = false; //forces individual probabilities for sig and bkg to be positive + + //How would you like to fit mkpi? + opts.use_mkpi = false; + opts.simple_mkpi = false; + opts.isobar = false; + opts.generate_mkpi = opts.fit_mkpi || opts.use_mkpi; + + //Get names for the init parameters file and the fitted parameters file + const std::string results_file = final_result_name_toys(params.jobID,fitReference, nBins, SimultaneousFit, params, opts.run, opts.only_angles, opts.only_Bmass, onlySig, onlyBkg, bkgFromLowMass, bkgFromHighMass); + std::string params_file = init_params_name_toys(params.jobID,fitReference, nBins, SimultaneousFit, params, opts.run, opts.only_angles, opts.only_Bmass, onlySig, onlyBkg, bkgFromLowMass, bkgFromHighMass); + + if (existsTest(results_file) && params.index != -1){ + spdlog::warn("[SKIP]\t\tJob already run as root-file '"+results_file+"' exists, continue to next job!"); + return 0; + } + + //Set the available PDFs: this depends on the selected Run for now, so if only one is selected, run over one pdf, if both, use two + std::vector pdf_idx; + if (params.Run == 1 || params.Run == 12) pdf_idx.push_back(1); + if (params.Run == 2 || params.Run == 12) pdf_idx.push_back(2); + + //we are good to go, now; how many individual pdfs are used? + const UInt_t nPDFs = pdf_idx.size(); + + //current fitter, plotter, parameteres and pdfs: + fcnc::fitter f(&opts); + fcnc::options theOptions[nPDFs]; + fcnc::bu2kstarmumu_plotter * thePlotter[nPDFs]; + std::vector theParams [nBins]; + std::vector theProbs [nBins]; + std::vector< std::vector* > selection[nBins]; + + //Initialize common parameters + std::vector common_params = param_string(opts, false); //All the angular observables are shared + if(SimultaneousFit) f.set_common_parameters(common_params); + //-------------------------------- + // Read events + //-------------------------------- + + //Init vector for the events to be saved, in case required + std::vector eventsToSave; + + //Loop over PDFs and initialize parameters + for(unsigned n = 0; n < nPDFs; n++){ + unsigned int idx = pdf_idx.at(n); + opts.run = idx; //Set proper run to options + spdlog::debug("Run {0:d}", opts.run); + opts.name = get_ToysFit_label(params.jobID, fitReference, -1, nBins, SimultaneousFit, params, opts.run, opts.only_angles, opts.only_Bmass, onlySig, onlyBkg, bkgFromLowMass, bkgFromHighMass); + + opts.update_angle_ranges(); //Set angles in options back to defaults + opts.update_efficiencies = true; //This ensures the acceptance weights to be taken into account + opts.plot_label = "Toys"; + + //Get options separate for all PDFs + theOptions[n] = opts; + + for(UInt_t b = 0; b < nBins; b++){ + opts.q2_min = theOptions[n].TheQ2binsmin.front(); + opts.q2_max = theOptions[n].TheQ2binsmax.back(); + + //----------------------------------------- + // Initialize 1D parameters + //----------------------------------------- + + //create parameter sets: + fcnc::bu2kstarmumu_parameters * leParameters = new fcnc::bu2kstarmumu_parameters(&theOptions[n]); + + //create PDFs + fcnc::bu2kstarmumu_pdf * lePDF = new fcnc::bu2kstarmumu_pdf(&theOptions[n], leParameters); + + //cache the folding and set to -1 for loading mass parameters from non-folded fits to jpsi, MC, etc. + int cached_folding = params.folding; + params.folding = -1; + + //Inititalize q2 by hand + leParameters->eff_q2.init_fixed( bin_center_q2(theOptions[n],b)); + + //Init the fraction betweeen sig and bkg + if (onlySig) leParameters->f_sig.init_fixed(1.0); + else if (onlyBkg) leParameters->f_sig.init_fixed(0.0); + else{ //Or both, in that case load the f_sig from mass only fit + initialize_parameters_from_MassFit(leParameters,fitReference,idx,b,{"f_sig"},params,f_sig_FC); + } + + //**********************************// + // // + // Bmass // + // // + //**********************************// + + //Set the Bmass separatelly as it's range is important + std::string fileName_dataMass = final_result_name_mass(true, 1, true, params, params.Run); + leParameters->init_Bmass(fileName_dataMass,idx,0.5,Bmass_FC); + + + //Init B mass fit from Jpsi MC + if (!onlyBkg){ + initialize_parameters_from_MCfit(leParameters,true,idx,b, {"alpha_1","alpha_2","n_1","n_2"},params, mass_params_FC); + + //Init the ratio of sigmas in signal MC/reference MC + initialize_parameters_from_MassFit(leParameters,true,idx,b,{"m_sigma_1"},params,fixConstr(!fitReference,false)); + if (!fitReference){ + leParameters->m_scale.init_fixed(get_sigmaRatio_fromMC(params,nBins,b,pdf_idx.at(n))); + } + else{ + leParameters->m_scale.init_fixed(1.0); + } + } + + //Init the mass background from mass fit to reference for now + //TODO: set as a proper vector depending on using 2 lambdas or anything + if (!onlySig) initialize_parameters_from_MassFit(leParameters,fitReference,idx,b,{"m_lambda"},params,bkg_mass_FC); + + //**********************************// + // // + // Angles // + // // + //**********************************// + + //Init angular parameters from MC + if (!onlyBkg){ + if (opts.initSM){ + leParameters->init_angular_parameters(nBins,b,ang_params_FC.fix ? 0.0 : angleStepSize,1.0,false); //TODO: make it better + } + else{ + if (fitReference) leParameters->init_ang_parameters_fromRefDavid(b,1.0,0.01); + else initialize_parameters_from_MCfit(leParameters,false,idx,b,param_string(opts, true),params, ang_params_FC); + } + } + + + //Init the bkg parameters from the BKG fit file + if (!onlySig){ + if (opts.flat_bkg) leParameters->use_default_bkg(); + else{ + //First init the background for angles for all orders + initialize_parameters_from_BkgFit(leParameters, true, + bkgFromLowMass, bkgFromHighMass,false, 12,b, + PAR_BKG_STRING(-1,opts.bkg_order_costhetal,opts.bkg_order_costhetak), + params,fixConstr(true,false)); + //Now let float only the ones actually used by the folding + initialize_parameters_from_BkgFit(leParameters, true, + bkgFromLowMass, bkgFromHighMass,false, 12,b, + PAR_BKG_STRING(cached_folding,opts.bkg_order_costhetal,opts.bkg_order_costhetak), + params,bkg_ang_FC); + if (opts.bkg_order_costhetak>=3 && cached_folding!=4){ + leParameters->cbkgctk3.init(-2.25,-3.25,1.5,0.05); + } + //Then init the background for m_Kpi + if (opts.generate_mkpi){ + initialize_parameters_from_BkgFit(leParameters, true, + bkgFromLowMass, bkgFromHighMass, + true, 12, + b,param_string_bkg_mkpi(),params,bkg_Kpi_FC); + } + } + } + + //**********************************// + // // + // S wave and Kstar // + // // + //**********************************// + + //Init the Kstar mass fit + if(opts.generate_mkpi){ + //p-wave + leParameters->init_mkpi_pWave_parameters(fitReference,gammakstar_FC.fix ? 0.0:0.01); + //s-wave + if (opts.swave) leParameters->init_mkpi_sWave_parameters(fitReference,gammakstarplus_FC.fix ? 0.0:0.001); + } + if (opts.swave){ + leParameters->init_sWave_parameters(sWave_FC.fix ? 0.0 : swaveStepSize); + std::string RefMassFile = final_result_name_mass(true,1,true,params,params.Run); + if (!fitReference) leParameters->FS.init(0.25,-0.25,1.0,FS_FC.fix ? 0.0 : 0.1); + else leParameters->get_param_from_rootfile(RefMassFile, {"FS"}, idx, 0,FS_FC); + if (changeFS) leParameters->FS.set_constant(); + } + + //set folding back to configured value using the cached value from above: + params.folding = cached_folding; + + spdlog::info("[PDF{0:d}]\tSaved PDF and parameters!", n); + + //Save the events now + std::vector * leEvents = new std::vector; + if(theOptions[n].job_id >= 0){ + //Seed is opts->get_job_id()*opts->ncores+thread_id+12345 if opts->static_seed, else take from the internal clock backwards + std::vector evts = generateToys(params, b, pdf_idx.at(n), + leParameters,theOptions[n]); + //copy generated events to pointer vector object + leEvents->clear(); + //count the number of dismissed events: + unsigned int dismissed = 0; + for(auto evt: evts){ + theOptions[n].update_angle_ranges(); //Update angle ranges based on the folding + //filter events, that are outside the defined angular range: + if(!filterFldFour(&evt, &theOptions[n])){ //I don't think this should be here at all + dismissed++; + continue; + } + leEvents->push_back(evt); + } + spdlog::info("{0:d} generated events are outside the angular range and are dismissed from the sample", dismissed); + assert(leEvents->size()+dismissed == evts.size()); + } + else{ //Just load all events TODO + std::vector evts = fcnc::load_events("/home/lhcb/kopecna/B2KstarMuMu/code/ewp-Bplus2Kstmumu-AngAna/FCNCfitter/Toys/Toy_toyfit__JpsiFit_1BIN_Run12_SimultaneousFit_6.root","Events", -1); //copy generated events to pointer vector object + leEvents->clear(); + for(auto evt: evts)leEvents->push_back(evt); + assert(leEvents->size() == evts.size()); + } + + spdlog::info("[PDF{0:d}]\tFinished generating the events: {1:d}", n, leEvents->size()); + if (!onlySig && setCtkToTwo){ + theOptions[n].bkg_order_costhetak = 2; + leParameters->use_default_bkg(); + leParameters->init_angular_background_parameters(fitReference,0.01); + } + if (changeFS){ + leParameters->FS.init_fixed(0.0); + leParameters->SS1.init_fixed(0.0); + leParameters->SS2.init_fixed(0.0); + leParameters->SS3.init_fixed(0.0); + leParameters->SS4.init_fixed(0.0); + leParameters->SS5.init_fixed(0.0); + } + + leParameters->take_current_as_start(); + lePDF->load_coeffs_eff_phsp_4d(); + lePDF->update_cached_normalization(leParameters); + theParams [b].push_back(leParameters); + theProbs [b].push_back(lePDF); + lePDF->update_cached_efficiencies(leParameters, leEvents); + + if (SaveTheToys){ + //save all events into one vector, except for the fifth (extra wide bin) in the 5BIN scheme. this would be double counting events + if(!(nBins == 5 && b == 4))eventsToSave.insert(eventsToSave.end(),leEvents->begin(),leEvents->end()); + } + + //save event vector in vector + selection[b].push_back(leEvents); + } //end loop over bins + theOptions[n].update_efficiencies = false;//Prevent the weights to be applied several more times in fitter::fit + } //end loop over PDFs + + //validate correct saving to of all events: + for(unsigned n = 0; n < nPDFs; n++){ + for(unsigned int b = 0; b < nBins; b++){ + if(selection[b].at(n)->size() > 0){ + spdlog::info("[PDF{0:d}]\t[BIN{1:d}]\tDone!", n, b); + } + else{ + spdlog::critical("No events found for PDF={0:d} and q2-bin={1:d} Exit!", n, b); + assert(0); + } + } + } + spdlog::info("Finished configurating all parameters, defining all pdfs and generating all toy event samples:"); + + //If required to save the generated events, save them + if (SaveTheToys){ + std::string eventsFile = get_finalToys_file(fitReference,nBins,SimultaneousFit,params,params.Run); + replace(eventsFile,".root","_"+std::to_string(params.jobID)+".root"); //Add the number of the job to the file name + fcnc::save_events(eventsFile,eventsToSave); + } + //Save the initial toy values in a root file + + std::vectortmp[nBins]; //Create a vector array with zeros, so you can save init values before the fit + for(unsigned int b = 0; b < nBins; b++)tmp[b] = std::vector(nPDFs, 0); + if(save_init) save_results(params_file,nBins,pdf_idx,tmp,theParams,SimultaneousFit,&opts); + + //Save the fit results + std::vectorfit_results[nBins]; + + //fit all bins: + for(unsigned int b = 0; b < nBins; b++){ + spdlog::info(""); + spdlog::warn("[START]\tStart fit BIN{0:d}", b); + + //Int for fit status + int fitresult = 0; + + if(!SimultaneousFit){ + for(UInt_t n = 0; n < nPDFs; n++){ + + //Delete the texFile + std::string tag = get_ToysFit_label(params.jobID, fitReference, b, nBins, + false, params, opts.run, + opts.only_angles, opts.only_Bmass, + onlySig, onlyBkg, + bkgFromLowMass, bkgFromHighMass); + + spdlog::info("[FIT{0:d}]\tRunning the fitter...", n); + if(do_fit)fitresult = f.fit(theProbs[b].at(n), theParams[b].at(n), selection[b].at(n),tag); + fit_results[b].push_back(fitresult); + } + } + else{ + spdlog::info("[FIT]\tFitting simultaenously...."); + std::string tag = ""; + for(UInt_t n = 0; n < nPDFs; n++)for(UInt_t e = 0; e < selection[b].at(n)->size(); e++)spdlog::trace("Event for fitting: pdf={0:d}\t bin={1:d}\t evt={2:d}\t ctk={3:f}\t ctl={4:f}\t phi={5:f}\t m={6:f}\t mkpi={7:f}", n, b, e, selection[b].at(n)->at(e).costhetak, selection[b].at(n)->at(e).costhetal, selection[b].at(n)->at(e).phi, selection[b].at(n)->at(e).m, selection[b].at(n)->at(e).mkpi); + + if(do_fit)fitresult = f.fit(theProbs[b], theParams[b], selection[b], tag); + fit_results[b].push_back(fitresult); + spdlog::info("Q2BIN={0:d}: LLH={1:f}", b, f.likelihood()); + } + + //Print the fit results + spdlog::info("[BIN{0:d}]: Fitresult: {1:d}", b, fitresult); + spdlog::info(""); + } + + //Plot stuff if wanted + if (SaveProjections){ + //If needed, also save the projections for the toys + //plot each set of pdfs with the data points: + bool plotPulls = true; + for(UInt_t b = 0; b < nBins; b++){ + for(UInt_t n = 0; n < nPDFs; n++){ + thePlotter[n] = new fcnc::bu2kstarmumu_plotter(&theOptions[n]); + + //plot pdf and events: + std::string eps_label = get_ToysFit_label(params.jobID, fitReference, b, nBins, + SimultaneousFit, params, pdf_idx.at(n), + opts.only_angles, opts.only_Bmass, + onlySig, onlyBkg, + bkgFromLowMass, bkgFromHighMass); + + theOptions[n].plot_label = "Toys"; + + if (!fitReference) theOptions[n].plots_m_bins = 30; + if (!fitReference) theOptions[n].plots_mkpi_bins = 20; + theOptions[n].q2_label = q2_label(opts.TheQ2binsmin.at(b), opts.TheQ2binsmax.at(b)); + + spdlog::info("[PLOT]\t"+eps_label); + thePlotter[n]->SetPulls(plotPulls); + thePlotter[n]->plot_data((fcnc::bu2kstarmumu_pdf*)theProbs[b].at(n), (fcnc::bu2kstarmumu_parameters*)theParams[b].at(n), selection[b].at(n), get_ToysFitPlot_path(params), eps_label, true); + thePlotter[n]->plot_data((fcnc::bu2kstarmumu_pdf*)theProbs[b].at(n), (fcnc::bu2kstarmumu_parameters*)theParams[b].at(n), selection[b].at(n), get_ToysFitPlot_path(params), eps_label+"_incBkg", false); + + } + + std::vector * prober = (std::vector *) & theProbs[b]; + + std::string eps_label = get_ToysFit_label(params.jobID, fitReference, b, nBins, + SimultaneousFit, params, params.Run, + opts.only_angles, opts.only_Bmass, + onlySig, onlyBkg, + bkgFromLowMass, bkgFromHighMass); + std::vector * paramser = (std::vector *) & theParams[b]; + thePlotter[0]->SetPulls(plotPulls); + thePlotter[0]->plot_added_pdfs(prober, paramser, & selection[b], get_ToysFitPlot_path(params), eps_label, true); + thePlotter[0]->plot_added_pdfs(prober, paramser, & selection[b], get_ToysFitPlot_path(params), eps_label+"_incBkg", false); + }//end loop over bins + } + + spdlog::info("[TOYFIT] Fit status results:"); + if(SimultaneousFit){ + for(UInt_t b = 0; b < nBins; b++)spdlog::info("[BIN{0:d}]: {1:d}", b, fit_results[b].at(0)); + } + else{ + for(UInt_t b = 0; b < nBins; b++)for(UInt_t n = 0; n < nPDFs; n++)spdlog::info("[BIN{0:d}][PDF{1:d}]: {2:d}", b, n, fit_results[b].at(n)); + } + if (params.index == -1) print_all_parameters(nBins, pdf_idx, theParams, spdlog::level::info); + //saving results to root file + save_results(results_file,nBins,pdf_idx,fit_results,theParams,SimultaneousFit,&opts); + + spdlog::info("[TOYFIT] Finished."); + return 0; +} diff --git a/Code/FCNCFitter/sources/Run/toysfit.hh b/Code/FCNCFitter/sources/Run/toysfit.hh new file mode 100644 index 0000000..07fbe01 --- /dev/null +++ b/Code/FCNCFitter/sources/Run/toysfit.hh @@ -0,0 +1,11 @@ +//Renata Kopecna + +#ifndef TOYS_HH +#define TOYS_HH + +#include +#include + +int toysfit(fcnc::options opts, unsigned int nBins, bool fitReference, basic_params params, bool onlySig, bool onlyBkg); + +#endif // TOYS_HH diff --git a/Code/FCNCFitter/sources/Scripts/EvaluateToys.cc b/Code/FCNCFitter/sources/Scripts/EvaluateToys.cc new file mode 100644 index 0000000..a4eb69a --- /dev/null +++ b/Code/FCNCFitter/sources/Scripts/EvaluateToys.cc @@ -0,0 +1,759 @@ +//Renata Kopecna + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "EvaluateToys.hh" +#include +#include +#include "ScriptHelpers.hh" + +#include + +//This code is as broken as it gets, the string for latex names and var names should be in a struct so when one has to skip stuff one can also skip the name and value actually +//This way it is error prone and god knows whether it even saves everything properly +//And it should've been connected directly with the csv file... like... no wonder some stuff took that long before + +const bool UnbinnedFit = true; +const bool UseCellColor = true; +Int_t Idx = 0; + +const UInt_t nPDFs = 2; + +struct pullInfo{ + double sigma; + double sigmaErr; + double mean; + double meanErr; + double failRate; + pullInfo(){ + sigma = DEFAULT_TREE_VAL; + sigmaErr = DEFAULT_TREE_ERR; + mean = DEFAULT_TREE_VAL; + meanErr = DEFAULT_TREE_ERR; + failRate = DEFAULT_TREE_VAL; + } + pullInfo(double sig, double sigErr, double mu, double muErr, double rate){ + sigma = sig; + sigmaErr = sigErr; + mean = mu; + meanErr = muErr; + failRate = rate; + } +}; + +struct q2Bins{ + unsigned int nBins; + std::vector q2min; + std::vector q2max; + + q2Bins(basic_params params){ + nBins = params.nBins; + q2min = get_TheQ2binsmin(nBins, params.reference); + q2max = get_TheQ2binsmax(nBins, params.reference); + } +}; + +const std::vector> bkg_340 = {{47.0,57.0},{0.0,15.0},{-10.0,0.0},{-25.0,-10.0},{-5.0,5.0},{-5.0,3.0},{-48.0,-38.0}}; + +//draw legend to the pull plots +void drawLegend(TLatex * leg, double q2min, double q2max, pullInfo info, + int tot_fits, int oor_fits, int failed_fits){ + std::ostringstream bindescription; + //draw q2 bin + bindescription << std::setprecision(2) << std::fixed << "( " << q2min << " < q^{2} < " << q2max << " )"; + spdlog::trace(bindescription.str()); + leg->DrawLatex(0.21,0.88, bindescription.str().c_str()); + //draw mean value + std::ostringstream sMean; + sMean << std::fixed << std::setprecision(4) << std::fixed << info.mean << " #pm " << info.meanErr; + spdlog::trace(sMean.str()); + leg->DrawLatex(0.13,0.80, "#bf{mean:}"); + leg->DrawLatex(0.13,0.77, sMean.str().c_str()); + //draw sigma value + std::ostringstream sRMS; + sRMS << std::fixed << std::setprecision(4) << std::fixed << info.sigma << " #pm " << info.sigmaErr; + spdlog::trace(sRMS.str()); + leg->DrawLatex(0.13,0.73, "#bf{sigma:}"); + leg->DrawLatex(0.13,0.69, sRMS.str().c_str()); + //draw percentage of results in histo range + // + //std::ostringstream sInRange; + //sInRange << std::fixed << std::setprecision(1) << std::fixed << 100. * (tot_fits - oor_fits - failed_fits) / (tot_fits - failed_fits) << "% in range"; + //spdlog::trace(sInRange.str()); + //leg->DrawLatex(0.13,0.64, sInRange.str().c_str()); + //draw failRate + std::ostringstream sfailRate; + if(!UnbinnedFit){ + sfailRate << std::fixed << std::setprecision(1) << std::fixed << info.failRate << "% failed"; + spdlog::trace(sfailRate.str()); + leg->DrawLatex(0.13,0.59, sfailRate.str().c_str()); + } + return; + +} + +//function to load toy fit results of one angular observables and create pull (or residual) plots for each q2 bin. +//In this function the histogram is fitted using a single Gaussian bell shape. Either a standard binned fit or a RooFit unbinned fit +//weirdShape is there for the cases the fitter generates stuff with different parameters than it fits, eg different polynomial bkg description +std::vector eval_toys(std::string filename, std::string treename, basic_params params, + bool doPulls, double pullRange_low, double pullRange_high, int whichPDf){ + + const q2Bins bins(params); + + //configure TPad style format and suppress pop-up windows from TCanvas: + gROOT->SetBatch(kTRUE); + gROOT->SetStyle("Plain"); + TPad foo; + set_gStyle(); + gStyle->SetOptTitle(0); + gStyle->SetTitleFont(132, "t"); + gStyle->SetTextFont(132); + gStyle->SetEndErrorSize(10.0); + gErrorIgnoreLevel = kWarning; + RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR); + + + //start loading the values from the toy fit results root files: + std::vector tot_fits(bins.nBins, 0); //counter for total fits + std::vector oor_fits(bins.nBins, 0); //counter for fit results outside the histogram range (oor=out of range) + std::vector failed_fits(bins.nBins, 0); //counter for fits with non-300 fit result + + std::vector max_value(bins.nBins, -10.); + std::vector min_value(bins.nBins, +10.); + + std::vectorall_Values[bins.nBins]; + + //load chain with all results of bootstrapping + TChain * ch = new TChain(treename.c_str()); + Int_t nFiles = 0; + + //when wildcard [0-9] is used, add all files and the digits of the counter until no files are found + //[0-9] stands for any digit, i.e. the combination 'file_[0-9][0-9][0-9][0-9].root' would add all files from 'file_0000.root' to 'file_9999.root' + if(filename.find("[0-9]") != std::string::npos){ + Int_t addedFiles = 1; + while(addedFiles > 0){ + addedFiles = ch->Add(filename.c_str()); + //add another wildcard to the filename in order to search for files with job IDs in the next order of magnitude + filename.replace(filename.find("[0-9]"), 5, "[0-9][0-9]"); + //Can someone explain to me why the fuck shoudl this be needed? + //add the number of found files to the total number of files + nFiles += addedFiles; + } + } + else{ //if no wildcard '[0-9]' or the general wildcard '*' is used, simply add all files: + nFiles = ch->Add(filename.c_str()); + } + + //check that at least one file with at least one entry is found: + if(nFiles == 0){ + spdlog::error("No files found for name='"+filename+"'."); + return {}; + } + UInt_t nEntries = ch->GetEntries(); + if(nEntries == 0){ + spdlog::error("No entries found in files for tree='"+treename+"'."); + return {}; + } + //make sure that the number of entries is equivalent to the number of files times the number of q2 bins times the number of simultaneous PDFs + if(TMath::Abs((int)(nEntries/(nPDFs*bins.nBins))) != TMath::Abs(nFiles)){ + spdlog::error("Number of entries found in files for tree='"+treename+"' does not match the number of files."); + return {}; + } + spdlog::info("[LOAD]\t\tReading {0:d} events from {1:d} files for variable='{2:s}'.", nEntries, nFiles, treename); + + //link variables to branches + double startvalue= DEFAULT_TREE_VAL; //TODO: check the start_value of the parameter is not changed anywhere, as it isn't a const it is very likely it is changed + double value = DEFAULT_TREE_VAL; + double error = DEFAULT_TREE_ERR; + double errorup = DEFAULT_TREE_ERR; + double errordown = DEFAULT_TREE_ERR; + + int migrad = DEFAULT_TREE_INT; + int cov = DEFAULT_TREE_INT; + int bin = DEFAULT_TREE_INT; + int pdf = DEFAULT_TREE_INT; + + ch->SetBranchStatus("*",1); //TODO optimize + ch->SetBranchAddress("value", &value); + ch->SetBranchAddress("start_value", &startvalue); + ch->SetBranchAddress("error", &error); + ch->SetBranchAddress("error_up", &errorup); + ch->SetBranchAddress("error_down", &errordown); + ch->SetBranchAddress("migrad", &migrad); + ch->SetBranchAddress("status_cov", &cov); + ch->SetBranchAddress("bin", &bin); + ch->SetBranchAddress("pdf", &pdf); + + //create a new simple tree that used the calculated pull or residual value, in case that unbinned fit is selected + //this tree is used as input to the RooFitter + TTree * unbinnedTree = nullptr; + double x; //this variable is used for either the pull or residual value (depending on arg 'doPulls') + if(UnbinnedFit){ + unbinnedTree = new TTree("tmp_tree", "tmp_tree"); + unbinnedTree->Branch("value", &x); + unbinnedTree->Branch("bin", &bin); + } + //or else create histograms for the binned fit: + TH1D * h_pull[bins.nBins]; + TH1D * h_values[bins.nBins]; + + + double binwidth = doPulls ? 0.5 : 0.05;//0.05; + double xrange = doPulls ? 2.0*pullRange_high : 1.0;//2.0; + if(!UnbinnedFit){ + for(UInt_t b = 0; b < bins.nBins; b++){ //FUCK PEOPLE WHO DON'T DO BRACKETS + h_pull[b] = new TH1D((treename+"_bin"+std::to_string(b)).c_str(), + (treename+" in q^{2} bin #"+std::to_string(b)+(doPulls ? ";(x-x_{nomi.})/#sigma" : ";(x-x_{nomi.})")+";entries").c_str(), + 2*xrange/binwidth, -xrange, +xrange); + } + } + spdlog::debug("Finished initializing the histograms"); + + //load results from files: + for(UInt_t e = 0; e < nEntries; e++){ + //since all PDFs are saved in the TTree, only use 8(5) q2bins out of 32(10) for the KS0(pi0) channel + //Eeee... e? + //if(e%(bins.nBins*nPDFs) > (bins.nBins-1)) continue; + + ch->GetEntry(e); + + if(pdf != whichPDf) continue; + spdlog::trace("Parameter value at entry {0:d}: {1:f}", e, value); + all_Values[bin].push_back(value); + tot_fits.at(bin)++; + + //require convered migrad + if(migrad != 0){ + failed_fits.at(bin)++; + continue; + } + //require fitresult = 300 or 100 (or 200) + if(!(cov == 1 || cov == 3 || cov == 2)){ + failed_fits.at(bin)++; + continue; + } + + //derive residual and pull + double diff = value - startvalue; + if(error == 0. || isnan(error)){ + spdlog::error("[{0:s}][BIN{1:d}]{2:d}\tError equal to zero!", treename, bin, e); + return {}; + } + double pull = diff/error; + spdlog::trace("[{0:s}][BIN{1:d}]{2:d}\tdiff={3:f}\tpull={4:f}\terr={5:f}", treename, bin, e, diff, pull, error); + + if(UnbinnedFit){ + //assign pull or residual to 'x' and save in TTree + x = doPulls ? pull : diff; //x, pull and diff is never used? //TODO + unbinnedTree->Fill(); + } + else{//Binned fit + if(TMath::Abs(diff) <= xrange){ + if(doPulls){ + //fill pull to histogram: + h_pull[bin]->Fill(pull); + //determine range of pull values + max_value.at(bin) = std::max(max_value.at(bin),pull); + min_value.at(bin) = std::min(min_value.at(bin),pull); + } + else{ + h_pull[bin]->Fill(diff); + //determine range of diff values + max_value.at(bin) = std::max(max_value.at(bin),diff); + min_value.at(bin) = std::min(min_value.at(bin),diff); + } + } + else{ + oor_fits.at(bin)++; + } + } + + } + + spdlog::debug("Filled all histograms/TTrees with values of variable="+treename+"."); + spdlog::debug("Tree size="+treename+"."); + + //vectors to store the measured mean and widths of the pull(residual) distributions + std::vector allInfo; + + //init some nullptr RooFit objects, to make the compiler happy. (These two are needed later in the plotting of the histograms) + RooGaussian * roogaus[bins.nBins]; + RooDataSet * roodata[bins.nBins]; + RooRealVar * roovalue[bins.nBins]; + + for(UInt_t b = 0; b < bins.nBins; b++){ //loop over q2bins to fit all distributions + if(UnbinnedFit){ + //initialise RooFit objects for the unbinned fit: + RooRealVar * roomean, * roosigma, * roobin; + roovalue[b] = new RooRealVar("value", "value", pullRange_low, pullRange_high, ""); + roomean = new RooRealVar("mean", "mean", bin_center(pullRange_low,pullRange_high), pullRange_low, pullRange_high); + roosigma = new RooRealVar("sigma", "sigma", doPulls ? 0.85: 0.1, 0., 2.); + roobin = new RooRealVar("bin", "q2 bin", -1., 10.0, ""); + RooArgSet rooarg = RooArgSet(*roovalue[b]); + rooarg.add(*roobin); + roogaus[b] = new RooGaussian("RooGaus", "RooGaus", *roovalue[b], *roomean, *roosigma); + //RooFitResult * result = new RooFitResult("FitResult","FitResult"); + + spdlog::debug("Start fitting q2 bin {0:d} for par={1:s}.", b, treename); + roodata[b] = new RooDataSet("RooDataSet", "RooDataSet", unbinnedTree, rooarg, + ("abs(bin-"+std::to_string(b)+") < 0.1").c_str()); + spdlog::debug("Fit {0:d} events", roodata[b]->numEntries()); + if(roodata[b]->numEntries() == 0){ + spdlog::critical("Empty fit not possible for var={0:s} in q2bin={1:d}", treename, b); + assert(0); + } + int fitstatus = roogaus[b]->fitTo(*roodata[b], RooFit::Save(kTRUE),RooFit::PrintLevel(spdlog_trace()?1 : -1))->status(); + spdlog::debug("[{0:s}][BIN{1:d}]\tFitstatus={2:d}", treename, b, fitstatus); + allInfo.push_back(pullInfo(roosigma->getVal(),roosigma->getError(), + roomean->getVal(),roomean->getError(),fitstatus)); + }//end unbinned fit + else{//binned fit + double entries = h_pull[b]->Integral(); + bool dofit = entries > 10.0 && h_pull[b]->GetRMS(1) > 0.001; + spdlog::debug("var={0:s}\t q2bin={1:d}\t DOFIT={2:s}", treename, b, (dofit ? "TRUE" : "FALSE")); + + if(entries < 0.0){ + spdlog::warn("Negative entries for: q2bin={0:d}\t par={1:s}\t entries={2:d}", b, treename, entries); + } + + int fitstatus = 0.0; + if(tot_fits.at(b) > 0) fitstatus = (100.0 * failed_fits.at(b) / tot_fits.at(b)); + + if(dofit){ + double minfit = -xrange; + double maxfit = +xrange; + TF1 * fGauss = new TF1("theGaussian", "gaus(0)", minfit, maxfit); + fGauss->SetParameter(0, entries); + fGauss->SetParameter(1, h_pull[b]->GetXaxis()->GetBinCenter(h_pull[b]->GetMaximumBin())); + if(!doPulls){ + double mean_range = (treename.find("P") != std::string::npos || treename == "Fl") ? 0.05 : 0.01; + fGauss->SetParLimits(1, h_pull[b]->GetXaxis()->GetBinCenter(h_pull[b]->GetMaximumBin()) - mean_range, h_pull[b]->GetXaxis()->GetBinCenter(h_pull[b]->GetMaximumBin()) + mean_range); + } + fGauss->SetParameter(2, h_pull[b]->GetRMS(1)); + fGauss->SetParLimits(2, 0.0, doPulls ? 1.5 : 0.1); + fGauss->SetLineStyle(kDashed); + fGauss->SetLineColor(kMagenta - 3); + h_pull[b]->Fit(fGauss, "RQM+"); + //save values in a vector + allInfo.push_back(pullInfo(fGauss->GetParameter(2),fGauss->GetParError(2), + fGauss->GetParameter(1),fGauss->GetParError(1),fitstatus)); + } + else{//only use RMS and MEAN obtained by TH1F + allInfo.push_back(pullInfo(h_pull[b]->GetRMS(1),h_pull[b]->GetRMSError(1), + h_pull[b]->GetMean(1),h_pull[b]->GetMeanError(1),fitstatus)); + } + }//end of binned fit + }//end of loops of q2 bins + + + //save histogram with pulls (or residuals) and the value distributions to file + TCanvas* c1 = new TCanvas("c1", "c1", 1600, 1200); + c1->cd()->SetMargin(0.1,0.05,0.1,0.05); + for(UInt_t b = 0; b < bins.nBins; b++){ //loop over bins.nBins + spdlog::debug("Plotting bin {0:b}.",b); + + c1->cd(); + if(UnbinnedFit){ + RooPlot * rooframe = roovalue[b]->frame(); + roodata[b]->plotOn(rooframe); + roogaus[b]->plotOn(rooframe); + rooframe->Draw(); + } + else{ + h_pull[b]->Draw(); + } + + //initiliaze and format a legend: + TLatex * leg = getPrettyTex(0.07,13); + leg->SetTextColor(kBlack); + + //draw variable name + leg->DrawLatex(0.13,0.89, treename.c_str()); + leg->SetTextSize(0.04); + drawLegend(leg,bins.q2min.at(b) ,bins.q2max.at(b), + allInfo[b],tot_fits[b],oor_fits[b],failed_fits[b]); + c1->Print((get_ToyPullPlot_tag(b,treename,params,false,doPulls) +".eps").c_str(), "eps"); + if(!UnbinnedFit) delete h_pull[b]; + + double max = *max_element(all_Values[b].begin(), all_Values[b].end()); + double min = *min_element(all_Values[b].begin(), all_Values[b].end()); + + h_values[b] = new TH1D(treename.c_str(), + (treename+" in q^{2} bin #"+std::to_string(b)+";"+treename+";Entries").c_str(), + nFiles/5, min, max); + for (auto val: all_Values[b]){ + h_values[b]->Fill(val); + } + + + //save histogram with values to file + plotAndSave(h_values[b],treename,get_ToyPullPlot_tag(b,treename,params,true, false),"eps"); + + + }//end loop over q2 bins + + delete c1; + return allInfo; +} + +//print the results of the toy studies to latex tables: +int print_latex_tables(bool Pprimes, bool doPulls, std::vector< std::string> LaTeXnames, std::vector< std::vector > lePullInfo, const q2Bins bins, int jobID){ + if(lePullInfo.size() == 0){ + spdlog::error("No results found for widths of pull/residual distributrionn"); + return 1; + } + + //generate color palette: + TPad foo; + TColor::InitializeColors(); + Double_t stops[9] = { 0.0000, 0.1250, 0.2500, 0.3750, 0.5000, 0.6250, 0.7500, 0.8750, 1.0000}; + Double_t red[9] = { 55./255., 55./255., 55./255., 55./255., 55./255., 105./255., 155./255., 205./255., 255./255.}; + Double_t green[9] = { 55./255., 105./255., 155./255., 205./255., 255./255., 205./255., 155./255., 105./255., 55./255.}; + Double_t blue[9] = { 255./255., 205./255., 155./255., 105./255., 55./255., 55./255., 55./255., 55./255., 55./255.}; + Idx = TColor::CreateGradientColorTable(9, stops, red, green, blue, 255); + + //in what range should the colors be defined: + double colorrange[] = {doPulls ? 0.2 : (Pprimes ? 0.2 : 0.05), + doPulls ? 0.2 : (Pprimes ? 0.2 : 0.05), + UnbinnedFit ? 2. : 20.}; + std::vector tabnames = {"width", "mean"};//, (UnbinnedFit ? "fitstatus" : "failRate")}; + + clear_Latex_noteFile(latex_toyFile()+"_"+std::to_string(jobID)+std::string(doPulls?"":"_res")); //First make sure you don't append stuff + std::ofstream myFile; //TODO: fix the latex name file + open_Latex_noteFile(latex_toyFile()+"_"+std::to_string(jobID)+std::string(doPulls?"":"_res"), myFile); //open latex file + + for(unsigned int i = 0; i < tabnames.size(); i++){ + myFile << "\\begin{frame} \\footnotesize \\centering" << std::endl; + myFile << "\\begin{tabular}{|l|"; + for(unsigned int b = 0; b < bins.nBins; b++) myFile << "p{2.2cm}"; + myFile << "|}\\hline" << std::endl; + myFile << "\\textbf{" << tabnames[i] << "}"; + //for(unsigned int b = 0; b < bins.nBins; b++)myFile << "\t& " << b; + for(unsigned int b = 0; b < bins.nBins; b++)myFile << std::setprecision(2) << std::fixed << "\t&[" << bins.q2min.at(b) << "--" << bins.q2max.at(b) << "]"; + myFile << "\\\\" << std::endl; + myFile << "\\hline\\hline" << std::endl; + //TABLE CONTENT: + for(unsigned int v = 0; v < lePullInfo.size(); v++){ + if (lePullInfo.at(v).size()==0) continue; + myFile << "$" << LaTeXnames.at(v) << "$ "; + for(unsigned int b = 0; b < bins.nBins; b++){ + //get correct value for mean,sigma,failRate at q2bin and variable + double levalue = 0.0; + double leerror = 0.0; + if(i == 0){ + levalue = lePullInfo.at(v)[b].sigma; + leerror = lePullInfo.at(v)[b].sigmaErr; + } + else if(i == 1){ + levalue = lePullInfo.at(v)[b].mean; + leerror = lePullInfo.at(v)[b].meanErr; + } + else{ + levalue = lePullInfo.at(v)[b].failRate; //TODO + } + myFile << "\t&"; + //generate cell background color accordingly to the value: + if(UseCellColor){ + //TColor * colour = gROOT->GetColor(Idx + TMath::Min(254, (int) ((TMath::Abs((doPulls && i == 0 ? levalue - 1. : levalue))/2./colorrange[i]+0.5)*255.))); + int coloridx = ((doPulls && i == 0 ? levalue - 1.0 : levalue)/colorrange[i])*127; + if(coloridx < -127)coloridx = -127; + if(coloridx > 127)coloridx = 127; + TColor * colour = gROOT->GetColor(Idx + 127 + coloridx); + if(colour==nullptr)spdlog::error("Color with idx={0:d} not found", Idx + 127 + coloridx); + else{ + std::string leColour(colour->AsHexString()); + std::transform(leColour.begin(), leColour.end(),leColour.begin(), ::toupper); + myFile << "\\cellcolor[HTML]{" << leColour.substr(1,6) << "} "; + } + } + //draw cell content + myFile << "$"; + if(levalue>=0.0)myFile << "\\phantom{-}";//align columns by adding an invisible minus sign + myFile << std::setprecision(3) << std::fixed << levalue << " \\pm " << leerror << "$"; + } + myFile << "\\\\" << std::endl; + } + //END OF TABLE CONTENT + myFile << "\\hline" << std::endl; + myFile << "\\end{tabular}" << std::endl << std::endl; + myFile << "\\end{frame}" << std::endl; + } + myFile.close(); + return 0; +} + +void save2rootFile( basic_params params, std::vector< std::string> treeNames, std::vector< std::string> LaTeXnames, std::vector< std::vector > lePullInfo, const q2Bins bins){ + TFile * file = new TFile((get_ToyPullPlot_folder(params)+"pullResults.root").c_str(), "RECREATE"); + spdlog::debug("Opening "+std::string(file->GetPath())); + file->cd(); + for(UInt_t t = 0; t < treeNames.size(); t++){ + if (lePullInfo[t].size()==0) continue; + TTree * tree = new TTree(treeNames[t].c_str(), LaTeXnames[t].c_str()); + spdlog::debug("Saving tree "+ treeNames[t]); + double mean = DEFAULT_TREE_VAL; + double width = DEFAULT_TREE_ERR; + tree->Branch("mean", &mean, "mean/D"); + tree->Branch("width", &width, "width/D"); + for(UInt_t b = 0; b < bins.nBins; b++){ + mean = lePullInfo[t][b].mean; + width = lePullInfo[t][b].sigma; + spdlog::debug("mean:\t{0:f}",mean); + spdlog::debug("width:\t{0:f}",width); + tree->Fill(); + } + tree->Write(); + delete tree; + } + file->Close(); + delete file; +} + +const std::vectorcolorPallete = + {"0d3c7b","2b6d97","499eb3","67cfcf","85ffeb","7ce9c8","72d2a5","69b282", + "5FA55F", + "84BC70", "A8D281","CCE892","F0FEA2","DABF7A","C47F51","AE4029","970000"}; + +/* +const std::vectorcolorPallete = + {"93006A","751778","562D86","374494","185AA2","2A6D92","3C8081","4E9370", + "5FA55F", + "84BC70", "A8D281","CCE892","F0FEA2","DABF7A","C47F51","AE4029","970000"}; +*/ +/* +const std::vectorcolorPallete = + {"0d3c7b","0e5d85","0e7d8e","0f9d97","0fbda0","0cae7b","089f56","049031", + "00800B", + "3B9714", "76ae1d","b1c526","EBDB2e","d9a523","c76e17","B5370c","A30000"}; +*/ + +const std::vector colStops = {-1.000,-0.8750,-0.7500,-0.6250,-0.5000,-0.3750,-0.2500,-0.1250, + 0.0000, + 0.1250, 0.2500, 0.3750, 0.5000, 0.6250, 0.7500, 0.8750, 1.0000}; + +std::string getCol(double val){ + int len = colStops.size(); + for (int i = 0; i < len; i++){ + if (colStops[i+1]>val) return colorPallete[i]; + } + return colorPallete[len-1]; +} + +int save2texFileNew(std::vector< std::string> LaTeXnames, std::vector< std::vector > lePullInfo, const q2Bins bins, int jobID){ + if(lePullInfo.size() == 0){ + spdlog::error("No results found for widths of pull/residual distributrionn"); + return 1; + } + + std::vector tabnames = {"width", "mean"};//, (UnbinnedFit ? "fitstatus" : "failRate")}; + + clear_Latex_noteFile(latex_toyFile()+"_"+std::to_string(jobID)); //First make sure you don't append stuff + std::ofstream myFile; //TODO: fix the latex name file + open_Latex_noteFile(latex_toyFile()+"_"+std::to_string(jobID), myFile); //open latex file + + for(unsigned int i = 0; i < tabnames.size(); i++){ + myFile << "\\begin{frame} \\footnotesize \\centering" << std::endl; + myFile << "\\begin{tabular}{|l|"; + for(unsigned int b = 0; b < bins.nBins; b++) myFile << "p{2.2cm}"; + myFile << "|}\\hline" << std::endl; + myFile << "\\textbf{" << tabnames[i] << "}"; + //for(unsigned int b = 0; b < bins.nBins; b++)myFile << "\t& " << b; + for(unsigned int b = 0; b < bins.nBins; b++)myFile << std::setprecision(2) << std::fixed << "\t&[" << bins.q2min.at(b) << "--" << bins.q2max.at(b) << "]"; + myFile << "\\\\" << std::endl; + myFile << "\\hline\\hline" << std::endl; + //TABLE CONTENT: + for(unsigned int v = 0; v < lePullInfo.size(); v++){ + if (lePullInfo.at(v).size()==0) continue; + myFile << "$" << LaTeXnames.at(v) << "$ "; + for(unsigned int b = 0; b < bins.nBins; b++){ + //get correct value for mean,sigma,failRate at q2bin and variable + double levalue = 0.0; + double leerror = 0.0; + if(i == 0){ + levalue = lePullInfo.at(v)[b].sigma; + leerror = lePullInfo.at(v)[b].sigmaErr; + } + else if(i == 1){ + levalue = lePullInfo.at(v)[b].mean; + leerror = lePullInfo.at(v)[b].meanErr; + } + else{ + levalue = lePullInfo.at(v)[b].failRate; //TODO + } + myFile << "\t&"; + //generate cell background color accordingly to the value: + if(UseCellColor){ + if (i==0) myFile << "\\cellcolor[HTML]{" << getCol(levalue-1.0) << "} "; + else myFile << "\\cellcolor[HTML]{" << getCol(levalue) << "} "; + } + //draw cell content + myFile << "$"; + if(levalue>=0.0)myFile << "\\phantom{-}";//align columns by adding an invisible minus sign + myFile << std::setprecision(3) << std::fixed << levalue << " \\pm " << leerror << "$"; + } + myFile << "\\\\" << std::endl; + } + //END OF TABLE CONTENT + myFile << "\\hline" << std::endl; + myFile << "\\end{tabular}" << std::endl << std::endl; + myFile << "\\end{frame}" << std::endl; + } + myFile.close(); + return 0; +} + +//MAIN FUNCTION to run over all observables and q2bin. +//the function calls the loading and fitting function 'eval_toys()' +//then runs the print and save functions +int EvaluateToyStudy(const std::vector obs, const std::vector obs_latex, basic_params params, bool UseFolds, bool doPulls, bool Pprimes, bool onlySig, bool onlyBkg){ + + //define names of observables and which foldings are taken for which observable + std::vector folding_idx; + + if(Pprimes) folding_idx = {3, 3, 0, 0, 1, 2, 3, 4}; + else folding_idx = {3, 3, 1, 2, 0, 3, 4, 0}; + + std::vector weirdRangeJobs = {340, 343, 344, 349, 350, 353, 354, 355, 362, 379, 382, 497,558, 559, 560, 561, 562, 563}; //jobIDs with off pull ranges + double lowRange = -5.0; + double highRange = 5.0; + + std::vector ctkRange = {497, 558, 559, 560, 561, 562, 563, 566, 567, 568, 569, 570, 571, 620, 621, 622, 623, 624, 625, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648}; + + + //configure the path and tags of the toy study result files + std::string PPtag = Pprimes ? "_Pprimes" : ""; + std::string suffix = ""; //TODO + makeFolder(get_ToyPullPlot_folder(params)); + const q2Bins bins(params); + + //using this status for error propagation + std::vector< std::vector> leInfo = {}; + + for(UInt_t p = 0; p < obs.size(); p++){ + lowRange = -5.0; //Reset the ranges again in case + highRange = 5.0; + if(params.reference && ( isInVec(obs.at(p),ANG_OBS) || isInVec(obs.at(p),SWAVE))){ + lowRange = -1.0; //Reset the ranges again in case + highRange = 1.0; + } + if(params.reference && params.folding>-1 && ( isInVec(obs.at(p),ANG_OBS) || isInVec(obs.at(p),SWAVE))){ + lowRange = -0.5; //Reset the ranges again in case + highRange = 0.5; + } + if(params.reference && params.folding==4 && ( isInVec(obs.at(p),ANG_OBS) || isInVec(obs.at(p),SWAVE))){ + lowRange = -5.0; //TODO + highRange = 5.0; + } + if(params.reference && params.folding>-1 && obs.at(p)=="FS"){ + lowRange = -0.25; //Reset the ranges again in case + highRange = 0.25; + } + if(UseFolds)params.folding = folding_idx.at(p); + + //get a filename accordingly to the basic_params settings, then replace the number 1111 by the wildcard + //and then replace the folder ToysFit by the subfolder created by condor + std::string files = final_result_name_toys(1111, params.reference, params.nBins, true, params, params.Run, false, false, onlySig, onlyBkg, false, true); + replace(files, "1111", "*"); //integer replaced by a string * + replace(files, "ToysFit/", "ToysFit/"+std::to_string(params.jobID)+"/"); + spdlog::info("Read pdfs from file='"+files+"'"); + + //Set the range for weird pulls in ctk + if (isInVec(params.jobID, weirdRangeJobs) && p>7 && p<15){ //This is a dirty hack + lowRange = -50.0; + highRange = +50.0; + } + if ((params.jobID==503 || (params.jobID>=509 && params.jobID<=512)) && (p==11 || p ==12)){ //This is a dirty hack + lowRange = -50.0; + highRange = +50.0; + + } + + if ((params.jobID==551 && (p==1))){ //This is a dirty hack + leInfo.push_back({}); + continue; + } + if ((params.jobID==551 && (p==3))){ + lowRange = -10.0; + highRange = 0.0; + } + + if (params.jobID==566 && (p==9)){ //This is a dirty hack + leInfo.push_back({}); + continue; + } + + if (params.jobID==567 && (p==9)){ //This is a dirty hack + leInfo.push_back({}); + continue; + } + if (isInVec(params.jobID,ctkRange) && (p==8|| p==9)){ + lowRange = -5.0; + highRange = 15.0; + } + if (isInVec(params.jobID,ctkRange) && params.jobID>619 && (obs.at(p)=="cbkgctk1")){ + leInfo.push_back({}); + continue; //TODO WTF + lowRange = 10.0; + highRange = 30.0; + } + if (isInVec(params.jobID,ctkRange) && params.jobID>619 && (obs.at(p)=="cbkgctk2")){ + leInfo.push_back({}); + continue;//TODO WTF + lowRange = 20.0; + highRange = 45.0; + } + if (params.jobID==571 && (p==9)){ //This is a dirty hack + leInfo.push_back({}); + continue; + } + + if (params.jobID>619 && (obs.at(p)=="cbkgctl2")){ //This is a dirty hack + leInfo.push_back({}); + continue;//TODO, actually anythig below zero possible depending on the bin + lowRange = -15.0; + highRange = -5.0; + } + //if (params.jobID==637 && (obs.at(p)=="SS5")){ //This is a dirty hack + // continue; + //} + if (params.jobID==630 && (p==9)){ //This is a dirty hack + leInfo.push_back({}); + continue; + } + if (params.jobID==650 && (p==9)){ + leInfo.push_back({}); + continue; + } + //evalute the files for this observable and check the status + leInfo.push_back(eval_toys(files, obs.at(p), params, doPulls, lowRange, highRange, 1)); + } + + if (doPulls){ + //print results to latex table into 'cout' and save to a root file + if (params.reference) save2rootFile(params,obs, obs_latex,leInfo, bins); //This could be done for each value + return save2texFileNew(obs_latex,leInfo,bins,params.jobID); + } + else return print_latex_tables(params.usePprime,false,obs_latex,leInfo, bins, params.jobID); +} + + diff --git a/Code/FCNCFitter/sources/Scripts/EvaluateToys.hh b/Code/FCNCFitter/sources/Scripts/EvaluateToys.hh new file mode 100644 index 0000000..8a32b35 --- /dev/null +++ b/Code/FCNCFitter/sources/Scripts/EvaluateToys.hh @@ -0,0 +1,22 @@ +//Renata Kopecna + +#ifndef EVALUATETOYS_H +#define EVALUATETOYS_H + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int EvaluateToyStudy(const std::vector obs, const std::vector obs_latex, basic_params pars, bool UseFolds, bool doPulls, bool Pprimes, bool onlySig, bool onlyBkg); + +#endif // EVALUATETOYS_H diff --git a/Code/FCNCFitter/sources/Scripts/GenLvlvsMC.cc b/Code/FCNCFitter/sources/Scripts/GenLvlvsMC.cc new file mode 100644 index 0000000..b4fe8f8 --- /dev/null +++ b/Code/FCNCFitter/sources/Scripts/GenLvlvsMC.cc @@ -0,0 +1,431 @@ +//Renata Kopecna + + +#include "GenLvlvsMC.hh" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ScriptHelpers.hh" + +std::string plotPath(std::string observable, std::string tag){ + return PLOTS_PATH+"MCfit/"+ "GenLvl_vs_MC_" + observable + tag +".eps"; +} + +std::vector> DavidsGenLvl = { + { 0.5120, 0.1800, 0.1370, 0.1930, 0.2750, 0.4170, 0.4840, 0.5030}, //S1s + { 0.2450, 0.6996, 0.7993, 0.7384, 0.6414, 0.4201, 0.3513, 0.3344}, //S1c + { 0.1448, 0.0749, 0.0514, 0.0662, 0.0900, 0.1449, 0.1620, 0.1662}, //S2s + {-0.1953,-0.6639,-0.7774,-0.7254,-0.6334,-0.4171,-0.3497,-0.3332}, //S2c + { 0.0000, 0.0020,-0.0080,-0.0120,-0.0240,-0.0620,-0.1520,-0.2330}, //S3 + { 0.0870, 0.0040,-0.1080,-0.1950,-0.2510,-0.2770,-0.2900,-0.3040}, //S4 + { 0.2440, 0.0950,-0.1590,-0.3050,-0.4140,-0.4210,-0.3400,-0.2490}, //S5 + {-0.1270,-0.2070,-0.0860, 0.0950, 0.3020, 0.5140, 0.5570, 0.4700}, //S6s + { 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000}, //S6c + {-0.0060,-0.0100,-0.0030, 0.0020, 0.0030,-0.0020,-0.0020, 0.0050}, //S7 + { 0.0010,-0.0030,-0.0040,-0.0030,-0.0010, 0.0030,-0.0010, 0.0030}, //S8 + {-0.0020, 0.0000, 0.0020, 0.0040,-0.0020,-0.0010,-0.0010, 0.0010} //S9 + }; //I would kill for a dictionary in C++ now + +double getDavidsValue(std::string observable, int bin){ //Not the most efficienc implementation, but oh well, hard to live without numpy + if (observable == "Fl") return (1-4.0/3.0*DavidsGenLvl[0][bin]); + if (observable == "S1s") return DavidsGenLvl[0][bin]; + if (observable == "S1c") return DavidsGenLvl[1][bin]; + if (observable == "S2s") return DavidsGenLvl[2][bin]; + if (observable == "S2c") return DavidsGenLvl[3][bin]; + if (observable == "S3") return DavidsGenLvl[4][bin]; + if (observable == "S4") return DavidsGenLvl[5][bin]; + if (observable == "S5") return DavidsGenLvl[6][bin]; + if (observable == "S6s") return DavidsGenLvl[7][bin]; + if (observable == "Afb") return 3.0/4.0*DavidsGenLvl[7][bin]; + if (observable == "S6c") return DavidsGenLvl[8][bin]; + if (observable == "S7") return DavidsGenLvl[9][bin]; + if (observable == "S8") return DavidsGenLvl[10][bin]; + if (observable == "S9") return DavidsGenLvl[11][bin]; + + spdlog::critical("I don't know observable "+observable); + spdlog::critical("Throwing an error now."); + assert(0); + return 0; +} + +TGraphAsymmErrors* DavidsGenLvlGraph(std::string observable){ + int nBins = DavidsGenLvl[0].size(); //In case the vector above changes, this should be secure + std::vector q2min = get_TheQ2binsmin(nBins,false); + std::vector q2max = get_TheQ2binsmax(nBins,false); + + //Initilialize the TGraph + //Initialize it on purpose with 0 points; in case something goes wrong with nBins, this makes sure there are no segfaults + TGraphAsymmErrors* graph = new TGraphAsymmErrors(0); + + //Loop over bins to fill TGraph from DavidsGenLvl + for (int b = 0; b < nBins; b++){ + graph->SetPoint(graph->GetN(),bin_center_q2(q2min,q2max,b), getDavidsValue(observable,b)); + graph->SetPointError(graph->GetN()-1,bin_halfWidth_q2(q2min,q2max,b), bin_halfWidth_q2(q2min,q2max,b), 0, 0); + } + return graph; + +} + +int compareGenLvlMC(std::vector graphs, + std::vector legends, + std::vector color, + std::vector markerStyle, + std::string observable, std::string plotPath, + std::vector plotDiff){ //What two plots should be considered for plotting the "pulls"? Marked with 1 and 2, plotting 1-2 + + int idx_1 = find(plotDiff.begin(), plotDiff.end(), 1)-plotDiff.begin(); + int idx_2 = find(plotDiff.begin(), plotDiff.end(), 2)-plotDiff.begin(); + bool plotD = (idx_1 != int(graphs.size()) && idx_2 != int(graphs.size())); + spdlog::debug("plot diff? " + boolToString(plotD)); + spdlog::debug("Idx_1: {0:d}\tIdx_2: {1:d}", idx_1, idx_2); + + //Create a canvas + TCanvas *c_compare = new TCanvas("c_compare", "c_compare", 1600, 1200); + + const double pullHeight = 0.27; + const double pullFrameRange = 3.5; + TPad *pad1 = new TPad("pad1", "plot",0.0,pullHeight,1.0,1.0,0); + TPad *pad2 = new TPad("pad2", "pull",0.0,0.0,1.0,pullHeight,0); + if(plotD){ + pad1->Draw(); + pad2->Draw(); + pad1->SetBorderSize (0); + pad1->SetMargin(0.125,0.05,1e-6,1.25/(1.0 - pullHeight)); + pad1->SetTickx(); + pad1->SetTicky(); + pad1->cd(); + } + else{ + c_compare->cd(); + c_compare->SetMargin(0.125,0.05,0.1,0.1); + c_compare->SetTickx(); + c_compare->SetTicky(); + } + + + //Create an empty hist for the axes + TH1D* haxes = emptyHist(observable); + haxes->Draw("AXIS"); + + //Draw boxes for resonances + drawResonances(plotD ? pad1 : c_compare, obsv_range(observable)[0], obsv_range(observable)[1]); + + haxes->SetFillStyle(0); + haxes->Draw("AXIS SAME"); + + TLegend* leg = new TLegend(0.62,0.70,0.94,0.94); + leg->SetBorderSize(0); + leg->SetTextFont(132); + leg->SetFillColor(0); + + for_indexed(auto g: graphs){ + designTGraph(g, markerStyle[i], color[i]); + if (legends[i]!="") leg->AddEntry(g, legends[i].c_str()); + g->Draw("P"); + } + leg->Draw("SAME"); + + TH1D *diff = nullptr; + if (plotD){ //If there are no tags 1 and 2, don't do anything + pad2->Clear(); + pad2->SetMargin(0.125,0.05,0.1/ pullHeight, 1e-6); + pad2->SetTickx(); + pad2->cd(); + + std::string y_title = "Diff [#sigma]";//legends[idx_1] + "-" + legends[idx_2]; + diff = hist_graphDiff(graphs[idx_1],graphs[idx_2],pullFrameRange, y_title); + + double max = haxes->GetBinLowEdge(haxes->GetNbinsX()+1); + double min = haxes->GetBinLowEdge(1); + //I hate that I have to workaround ranges of an efin histogram + + TLine *sigmaUp_3 = threeSigmaLine(min,max, true); + TLine *sigmaLow_3 = threeSigmaLine(min,max, false); + TLine *sigmaUp_1 = oneSigmaLine(min,max, true); + TLine *sigmaLow_1 = oneSigmaLine(min,max, false); + design_pull(diff, 9011, 9011, pullHeight+0.1, pullFrameRange); + diff->GetYaxis()->SetNdivisions(110); + diff->Draw(""); + + sigmaUp_3->Draw("same"); + sigmaLow_3->Draw("same"); + sigmaUp_1->Draw("same"); + sigmaLow_1->Draw("same"); + } + + spdlog::info("Saving into "+ plotPath); + c_compare->Print(plotPath.c_str(), "eps"); + if (spdlog_debug()){ //When debugging save also the root file + replace(plotPath,".eps",".root"); + c_compare->Print(plotPath.c_str(), "root"); + } + + delete c_compare; + delete haxes; + delete diff; + return 0; + +} + +int plotComparison_Toy_GenVsMC(std::string observable, bool isRef){ + bool onlySig = false; + bool onlyBkg = false; + bool onlyAngles = false; + bool onlyMass = false; + bool bkgFromLowMass = false; + bool bkgFromHighMass = true; + + basic_params params_MC = basic_params(); + params_MC.Run = 12; + params_MC.nBins = isRef ? 1 : 4; + params_MC.reference = isRef; + + basic_params params_Toys = basic_params(); + params_Toys.Run = 12; + params_Toys.nBins = isRef ? 1 : 4; + params_Toys.reference = isRef; + + std::vector legends; + std::vector color; + std::vector markerStyle; + std::vector graphs; + std::vector difference; //makes a plot with difference of grpahs with a tag of 1-2 + //I shoudl write a class for this, but too much effort + + + //Add init parameters + std::string path = final_result_name_MC(params_MC, params_Toys.nBins, isRef, false, true, false, false); + graphs.push_back(get_TGraphFromFile(path,observable,isRef)); + legends.push_back("MC"); //Don't plot legend as it is same as sigMC + color.push_back(9012); + markerStyle.push_back(27); + difference.push_back(1); + + //Fill the toy init parameters + path = init_params_name_toys(1,isRef,params_Toys.nBins, true, params_Toys, params_Toys.Run, onlyAngles, onlyMass, onlySig, onlyBkg, bkgFromLowMass, bkgFromHighMass); + graphs.push_back(get_TGraphFromFile(path,observable,isRef)); + legends.push_back("Toy"); + color.push_back(9007); + markerStyle.push_back(34); + difference.push_back(2); + + std::string plotPath = PLOTS_PATH+"Toys/"+ "MC_vs_Init_" + observable +".eps"; + return compareGenLvlMC(graphs,legends,color,markerStyle,observable, plotPath, difference); + +} + +//This one compares the data-like fit to the init toy values +int plotComparison_Toy_InitVsAcutalFit(std::string observable, bool isRef){ + + bool onlySig = false; + bool onlyBkg = false; + bool onlyAngles = false; + bool onlyMass = false; + bool bkgFromLowMass = false; + bool bkgFromHighMass = false; + + double fractionOfStats = 1.0; + + basic_params params_Init= basic_params(); + params_Init.Run = 12; + params_Init.nBins = isRef ? 1 : 4; + params_Init.reference = isRef; + params_Init.jobID = -1; + + basic_params params_Fit= basic_params(); + params_Fit.Run = 12; + params_Fit.nBins = isRef ? 1 : 4; + params_Fit.reference = isRef; + + std::vector legends; + std::vector color; + std::vector markerStyle; + std::vector graphs; + std::vector difference; //makes a plot with difference of grpahs with a tag of 1-2 + //I shoudl write a class for this, but too much effort + + //Add init parameters + std::string paramFile = init_params_name_toys(-1,params_Init.reference, params_Init.nBins, true, params_Init, params_Init.Run, onlyAngles, onlyMass, onlySig, onlyBkg, bkgFromLowMass, bkgFromHighMass); + graphs.push_back(get_TGraphFromFile(paramFile,observable,isRef)); + legends.push_back("Init"); //Don't plot legend as it is same as sigMC + color.push_back(9012); + markerStyle.push_back(27); + difference.push_back(1); + + //Add fitted parameters + std::string fitFile = final_result_name(isRef, false, params_Fit, + true, params_Fit.nBins, params_Fit.Run, + true, fractionOfStats, + false, -1); + + graphs.push_back(get_TGraphFromFile(fitFile,observable,isRef)); + legends.push_back("Fit"); + color.push_back(9007); + markerStyle.push_back(34); + difference.push_back(2); + + std::string plotPath = PLOTS_PATH+"Toys/"+ "FinalToy_Init_vs_Fit_" + observable + std::string(isRef ? "_Ref" : "" )+".eps"; + return compareGenLvlMC(graphs,legends,color,markerStyle,observable, plotPath, difference); +} + + +int plotComparison_Toy_GenVsFit(std::string observable, bool isRef){ + + bool onlySig = false; + bool onlyBkg = false; + bool onlyAngles = false; + bool onlyMass = false; + bool bkgFromLowMass = false; + bool bkgFromHighMass = true; + + basic_params params_Init= basic_params(); + params_Init.Run = 12; + params_Init.nBins = isRef ? 1 : 4; + params_Init.reference = isRef; + + basic_params params_Fit= basic_params(); + params_Fit.Run = 12; + params_Fit.nBins = isRef ? 1 : 4; + params_Fit.reference = isRef; + + std::vector legends; + std::vector color; + std::vector markerStyle; + std::vector graphs; + std::vector difference; //makes a plot with difference of grpahs with a tag of 1-2 + //I shoudl write a class for this, but too much effort + + //Add init parameters + std::string path = init_params_name_toys(1,isRef,params_Init.nBins, true, params_Init, params_Init.Run, onlyAngles, onlyMass, onlySig, onlyBkg, bkgFromLowMass, bkgFromHighMass); + graphs.push_back(get_TGraphFromFile(path,observable,isRef)); + legends.push_back("Init"); //Don't plot legend as it is same as sigMC + color.push_back(9012); + markerStyle.push_back(27); + difference.push_back(1); + + //Add fitted parameters + path = final_result_name_toys(1,isRef,params_Fit.nBins, true, params_Fit, params_Fit.Run, onlyAngles, onlyMass, onlySig, onlyBkg, bkgFromLowMass, bkgFromHighMass); + graphs.push_back(get_TGraphFromFile(path,observable,isRef)); + legends.push_back("Fit"); + color.push_back(9007); + markerStyle.push_back(34); + difference.push_back(2); + + std::string plotPath = PLOTS_PATH+"Toys/"+ "Init_vs_Fit_" + observable + std::string(isRef ? "_Ref" : "" )+".eps"; + return compareGenLvlMC(graphs,legends,color,markerStyle,observable, plotPath, difference); +} + +int plotComparisonMCFolding(std::string observable){ + basic_params params_MC= basic_params(); + params_MC.Run = 12; + params_MC.nBins = 4; + params_MC.reference = false; + + std::vector legends; + std::vector color; + std::vector markerStyle; + std::vector graphs; + std::vector difference; //makes a plot with difference of grpahs with a tag of 1-2 + + for (int f = -1; f <5; f++){ + params_MC.folding = f; + if (f == -1) difference.push_back(1); + if (plotObsv(f,observable)){ + graphs.push_back(get_TGraphFromFile(final_result_name_MC(params_MC,params_MC.nBins, false, false, true, false, false),observable,false)); + legends.push_back("Fld " + std::to_string(f)); + color.push_back(9009+f); + markerStyle.push_back(25+f); + difference.push_back(2); + } + } + + std::string tag = ""; + std::string plotPath = PLOTS_PATH+"MCfit/"+ "Folding_" + observable + tag +".eps"; + + assert(!compareGenLvlMC(graphs,legends,color,markerStyle,observable, plotPath, difference)); + + return 0; +} + +int plotComparison(std::string observable){ + + basic_params params_genLvl = basic_params(); + params_genLvl.Run = 2; + params_genLvl.year = 2017; + params_genLvl.nBins = 8; + + bool PHSP = false; + + std::vector legends; + std::vector color; + std::vector markerStyle; + std::vector graphs; + std::vector difference; //makes a plot with difference of grpahs with a tag of 1-2 + //I shoudl write a class for this, but too much effort + + //First make a comparison between my and David's genLvl + //---------------------------------------------------// + //Add genLvl + graphs.push_back(get_TGraphFromFile(final_result_name_genLvlMC(params_genLvl, 8, PHSP, true, false),observable,false)); + legends.push_back("GenLvl MC"); //Don't plot legend as it is same as sigMC + color.push_back(9012); + markerStyle.push_back(27); + difference.push_back(1); + + //Fill David's results first + graphs.push_back(DavidsGenLvlGraph(observable)); + legends.push_back("David's GenLvl results"); + color.push_back(9007); + markerStyle.push_back(34); + difference.push_back(2); + + std::string tag = "_MyVsDavids"; + std::string plotPath = PLOTS_PATH+"MCfit/"+ "GenLvl_vs_MC_" + observable + tag +".eps"; + + assert(!compareGenLvlMC(graphs,legends,color,markerStyle,observable, plotPath, difference)); + + //Delete David's graphs + graphs.clear(); + legends.clear(); + color.clear(); + markerStyle.clear(); + difference.clear(); + //---------------------------------------------------// + //Compare my fit of genLvl mc and processed MC + //---------------------------------------------------// + //Add MC as it should be done + + basic_params params_MC= basic_params(); + params_MC.Run = 12; + params_MC.nBins = 4; + params_MC.reference = false; + + graphs.push_back(get_TGraphFromFile(final_result_name_MC(params_MC, 4, false, PHSP, true, false, false),observable,false)); + legends.push_back("LHCb simulation"); + color.push_back(9016); + markerStyle.push_back(24); + difference.push_back(1); + + //Add genLvl MC + params_genLvl.nBins = 4; + graphs.push_back(get_TGraphFromFile(final_result_name_genLvlMC(params_genLvl, 4, PHSP, true, false),observable,false)); + legends.push_back("Generator level"); + color.push_back(9010); + markerStyle.push_back(25); + difference.push_back(2); + + plotPath = PLOTS_PATH+"MCfit/"+ "GenLvl_vs_MC_" + observable + ".eps"; + return compareGenLvlMC(graphs,legends,color,markerStyle,observable, plotPath, difference); + //---------------------------------------------------// + +} diff --git a/Code/FCNCFitter/sources/Scripts/GenLvlvsMC.hh b/Code/FCNCFitter/sources/Scripts/GenLvlvsMC.hh new file mode 100644 index 0000000..2ab27cf --- /dev/null +++ b/Code/FCNCFitter/sources/Scripts/GenLvlvsMC.hh @@ -0,0 +1,22 @@ +//Renata Kopecna + +#ifndef GENLVLVSMC_H +#define GENLVLVSMC_H + + +#include +#include +#include +#include +#include + +//Used to plot the fit results of GenLvl MC vs processed MC +//Plots both signal and Jpsi, hence nBins is hardcoded to 5 and it reads both the fit of +//4 bins in MC + 1 bin in RefMC + +int plotComparison(std::string observable); +int plotComparison_Toy_GenVsFit(std::string observable, bool isRef); +int plotComparison_Toy_GenVsMC(std::string observable, bool isRef); +int plotComparison_Toy_InitVsAcutalFit(std::string observable, bool isRef); +int plotComparisonMCFolding(std::string observable); +#endif // GENLVLVSMC_H diff --git a/Code/FCNCFitter/sources/Scripts/GetMeanError.cc b/Code/FCNCFitter/sources/Scripts/GetMeanError.cc new file mode 100644 index 0000000..4cd65a0 --- /dev/null +++ b/Code/FCNCFitter/sources/Scripts/GetMeanError.cc @@ -0,0 +1,138 @@ +//Renata Kopecna + +#include +#include +#include +#include +#include + +#include "GetMeanError.hh" +#include +#include +#include "ScriptHelpers.hh" + + +std::vector getSM(std::string observable){ + + if (observable == "Fl") return {+0.248569008046490070, +0.2581971160208132000, +0.42526014659559220000, +0.49420669353506260000, +0.1850102996703149000}; //s1s + else if (observable == "S3") return {+0.000732569649322501, -0.0324523859139632900, -0.08563864422457230000, -0.18934424485647136000, -0.0130310503598977030}; //s3 + else if (observable == "S4") return {-0.028317693174889150, -0.2425837027660650600, -0.28116530113868093000, -0.29668531019781386000, -0.1468982883895949300}; //s4 + else if (observable == "S5") return {+0.035479698896675250, -0.3745017565795041000, -0.40726931726860705000, -0.30161750053585110000, -0.1915219985323076700}; //s5 + else if (observable == "Afb")return {-0.122319885918514240, +0.2473816826915200600, +0.52432045165541470000, +0.52106439209368990000, +0.0147578966169414490}; //s6s + else if (observable == "S7") return {-0.019468600975846337, -0.0105435770924197210, -0.00219285191192886900, -0.00119446595061885200, -0.0160492529928752330}; //s7 + else if (observable == "S8") return {-0.010192773160727949, -0.0043019891737210840, +0.00104987431866559550, +0.00027244645255727460, -0.0070279543261629670}; //s8 + else if (observable == "S9") return {-0.000756965302130655, -0.0006959911482550733, +0.00044741790607562027, +0.00026464193866571387, -0.0007199408885633002}; //s9 + else{ + spdlog::warn("Wrong observable, returning an empty vector"); + return {}; + } +} + +std::vector fixSM(std::string observable){ + std::vector tmp = {}; + for (auto val : getSM(observable)){ + if (observable == "Fl") tmp.push_back(round((1-4.0*val/3.0)*100.0)/100.0); + else if (observable=="Afb") tmp.push_back(round((3.0*val/4.0)*100.0)/100.0); + else tmp.push_back(round(val*100.0)/100.0); + } + return tmp; +} + +int loadAllFiles(std::string observable, basic_params params){ + //load chain with all results of bootstrapping + TChain * ch = new TChain(observable.c_str()); + + std::string files = final_result_name_toys(1111, params.reference, params.nBins, true, params, params.Run, false, false, false, false, false, true); + replace(files, "1111", "*"); //integer replaced by a string * + replace(files, "ToysFit/", "ToysFit/"+std::to_string(params.jobID)+"/"); + + spdlog::debug("Loading files: " + files); + + ch->Add(files.c_str()); + int nEntries = ch->GetEntries(); + spdlog::debug("Loaded {0:d} entries", nEntries); + if (nEntries == 0){ + spdlog::error("No files found!"); + return 404; + } + + //link variables to branches + + double value = DEFAULT_TREE_VAL; + double error = DEFAULT_TREE_ERR; + double errorup = DEFAULT_TREE_ERR; + double errordown = DEFAULT_TREE_ERR; + + int migrad = DEFAULT_TREE_INT; + int cov = DEFAULT_TREE_INT; + int bin = DEFAULT_TREE_INT; + int pdf = DEFAULT_TREE_INT; + + ch->SetBranchStatus("*",1); //TODO optimize + ch->SetBranchAddress("value", &value); + ch->SetBranchAddress("error", &error); + ch->SetBranchAddress("error_up", &errorup); + ch->SetBranchAddress("error_down", &errordown); + ch->SetBranchAddress("migrad", &migrad); + ch->SetBranchAddress("status_cov", &cov); + ch->SetBranchAddress("bin", &bin); + ch->SetBranchAddress("pdf", &pdf); + + const int nBins = params.nBins; + std::vector errors[nBins]; //Don't fill a histogram just yet, just put the values in a vector first + + //Loop over the entries and fill the vector + for (int iter = 0; iter < nEntries; iter++){ + ch->GetEntry(iter); + //require converged migrad + if (migrad!=0) continue; + //require fitresult = 300 or 100 (or 200) + if(!(cov == 1 || cov == 3 || cov == 2)) continue; + if (pdf == 1) continue; //Just take one pdf, as the values are shared + spdlog::trace("Parameter value at entry {0:d}: {1:f}", iter, value); + spdlog::trace("Parameter error at entry {0:d}: {1:f}", iter, error); + errors[bin].push_back(error); + } + + //Debug print in case + for (int b = 0; b < nBins; b++){ + spdlog::debug("Got {0:d} entries for bin {1:d}", errors[b].size(),b); + } + + //Now init a histogram for each bin and fill it + std::vector means; + for (int b = 0; b < nBins; b++){ + //Get the max and the min of the errors + double max = *max_element(errors[b].begin(), errors[b].end()); + double min = *min_element(errors[b].begin(), errors[b].end()); + if (min == max) continue; //If errors are all the same, it was fixed, so don't plot + //Easier than checking folding + if (max>1.0) max = 0.5; + if (min<0.01) min = 0.01; + //Create the TH1D for the errors + TH1D *h_errors = new TH1D(observable.c_str(), + (observable+" in q^{2} bin #"+std::to_string(b) + +";"+observable+";Entries").c_str(), + errors[b].size()/10, min, max); + //Fill the TH1D from the read vector + for (auto err: errors[b]) h_errors->Fill(err); + //Fit the distribution with a gaussia + TF1 *fit_func = new TF1("fit_func","gaus",min,max); + fit_func->SetParameters(h_errors->GetMaximum(), h_errors->GetMean(), h_errors->GetRMS() ); + h_errors->Fit("fit_func",spdlog_debug() ? "R" : "RQ"); + //Plot and save it + plotAndSave(h_errors,observable,"./"+observable+"_"+std::to_string(params.jobID)+"_"+std::to_string(b),"eps"); + //Save the mean to a vector so you can print it later + means.push_back(fit_func->GetParameter("Mean") ); + h_errors->Clear(); + } + if (means.size()>0){ + std::vectorvalSM = fixSM(observable); + std::cout << "$" << observable << "$\t"; + for_indexed (auto val: means) std::cout << " & $" << valSM[i] << " \\pm " << val << "$"; + std::cout << "\\\\" << std::endl; + } + return 0; + + +} diff --git a/Code/FCNCFitter/sources/Scripts/GetMeanError.hh b/Code/FCNCFitter/sources/Scripts/GetMeanError.hh new file mode 100644 index 0000000..5b38f01 --- /dev/null +++ b/Code/FCNCFitter/sources/Scripts/GetMeanError.hh @@ -0,0 +1,12 @@ +//Renata Kopecna + +#ifndef GETMEANERROR_HH +#define GETMEANERROR_HH + +#endif // GETMEANERROR_HH + +#include +#include +#include + +int loadAllFiles(std::string observable, basic_params params); diff --git a/Code/FCNCFitter/sources/Scripts/ReferencePlots.cc b/Code/FCNCFitter/sources/Scripts/ReferencePlots.cc new file mode 100644 index 0000000..3fc1740 --- /dev/null +++ b/Code/FCNCFitter/sources/Scripts/ReferencePlots.cc @@ -0,0 +1,294 @@ +//Renata Kopecna + + +#include "ReferencePlots.hh" + +#include + +#include "ScriptHelpers.hh" +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +const int oneSigma_RGB[3] = {34,136,51}; +const int twoSigma_RGB[3] = {170,170,0}; +const int threeSigma_RGB[3] = {238,22,136}; +const int moreSigma_RGB[3] = {204,51,17}; + +//TODO: make it into a texfile instead of a cout! + +const std::vector Davids = { + valErr(+0.572,0.005),//valErr(+0.321,0.004), + valErr(-0.002,0.007), + valErr(-0.246,0.008), + valErr(-0.003,0.008), + valErr(-0.002,0.005),//valErr(-0.003,0.006), + valErr(-0.001,0.008), + valErr(-0.063,0.008), + valErr(-0.084,0.007) +}; +const std::vector Belles = { + valErr(+0.604,0.015),//valErr(+0.297,0.011), + valErr(-0.018,0.017), + valErr(-0.255,0.010), + valErr(0.0,0.0), + valErr(0.0,0.0), + valErr(0.0,0.0), + valErr(-0.037,0.018), + valErr(-0.041,0.016) +}; +const std::vector BaBars = { + valErr(+0.556,0.009),//valErr(+0.333,0.007), + valErr(+0.011,0.011), + valErr(-0.237,0.007), + valErr(0.0,0.0), + valErr(0.0,0.0), + valErr(0.0,0.0), + valErr(-0.058,0.015), + valErr(-0.095,0.014) +}; +const std::vector B0s = { + valErr(+0.572,0.008),//valErr(+0.321,0.006), + valErr(-0.013,0.010), + valErr(-0.250,0.006), + valErr(0.0,0.0), + valErr(0.0,0.0), + valErr(0.0,0.0), + valErr(-0.048,0.007), + valErr(-0.084,0.006) +}; + +std::vectorgetSigma(std::vector vec_a, std::vector vec_b){ + if (vec_a.size() != vec_b.size()){ + spdlog::error("Two valErr vectors have different lenghts! Abort."); + assert(0); + } + std::vectorsigs; + for_indexed(auto a: vec_a){ + sigs.push_back(sigmaAway(a,vec_b[i])); + } + return sigs; +} + +std::vectorgetSigmaColor(std::vectorvec_sigma){ + std::vector tmp; + for(auto sigma: vec_sigma){ + if (fabs(sigma) < 1.0) tmp.push_back(oneSigma_RGB); + else if (fabs(sigma) < 2.0) tmp.push_back(twoSigma_RGB); + else if (fabs(sigma) < 3.0) tmp.push_back(threeSigma_RGB); + else tmp.push_back(moreSigma_RGB); + } + return tmp; +} + +std::string getSigmaColor_str(double sigma){ + if (fabs(sigma) < 1.0) return "\\cellcolor{oneSigma}"; + else if (fabs(sigma) < 2.0) return "\\cellcolor{twoSigmas}"; + else if (fabs(sigma) < 3.0) return"\\cellcolor{threeSigmas}"; + else return "\\cellcolor{moreSigmas}"; +} + +std::vectorgetSigmaColor_strVec(std::vectorvec_sigma){ + std::vector tmp; + for(auto sigma: vec_sigma) tmp.push_back(getSigmaColor_str(sigma)); + return tmp; +} +double getCorrectedError(std::string name, double err, int jobID){ //For now, no bins, cause it is used anyhow only for reference //TODO + + basic_params tmpParams; //This is dumb, but no time + tmpParams.jobID = jobID; + + std::string fileName = get_ToyPullPlot_folder(tmpParams)+"pullResults.root"; + spdlog::info("Opening " + fileName); + TFile* file = new TFile(fileName.c_str(), "READ"); + + if (!file->GetListOfKeys()->Contains(name.c_str())){ + spdlog::critical("Wrong tree name " + name + "! Abort."); + assert(0); + } + //Get the tree and set the branches to active + TTree* tree = (TTree*)file->Get(name.c_str()); + tree->SetBranchStatus("*",1); //Activate all branches + double width = DEFAULT_TREE_ERR; + double mean = DEFAULT_TREE_VAL; + + tree->SetBranchAddress("width", &width); + tree->SetBranchAddress("mean", &mean); + + tree->GetEntry(0); + file->Close(); + + //get_param_valueError_from_rootfile() + + return err*width; +} + +int plotComparisonFull(){ + spdlog::debug("Starting with printing the values for RefChan measurement in a nice table."); + double fractionOfStats = 1.0; + + basic_params params_Fit= basic_params(); + params_Fit.Run = 12; + params_Fit.nBins = 1; + params_Fit.reference =true; + std::string fitFile = final_result_name(true, false, params_Fit, + true, 1, params_Fit.Run, + false, fractionOfStats, + false, -1); + + std::vector myValues; + spdlog::debug("Filling my values into a vector"); + for (auto obs: ANG_OBS){ + //The easiest rounding in c++ + double err = get_param_error_from_rootfile(fitFile, obs, 1,0); + //The easiest rounding in c++ + err = round(getCorrectedError(obs,err,649)*1000.0)/1000.0; //TODO + double val = round(get_param_value_from_rootfile(fitFile, obs, 1,0)*1000.0)/1000.0; + myValues.push_back(valErr(val,err)); + } + std::vectorcol_Davids = getSigmaColor_strVec(getSigma(myValues,Davids)); + std::vectorcol_Belles = getSigmaColor_strVec(getSigma(myValues,Belles)); + std::vectorcol_BaBars = getSigmaColor_strVec(getSigma(myValues,BaBars)); + std::vectorcol_B0s = getSigmaColor_strVec( getSigma(myValues,B0s)); + + std::cout << "\\begin{table}[]" << std::endl; + std::cout << "\\begin{tabular}{llllll}" << std::endl; + std::cout << " & this fit & \\lhcb \\Bu & Belle (\\Bu) & BaBar (\\Bu + \\Bd) & \\lhcb \\Bd \\\\\\hline" << std::endl; + for_indexed(auto myVal: myValues){ + std::cout << std::setprecision(3) << "$" << ANG_OBS_TLaTeX[i] << "$"; + std::cout << " & " << myVal.val << "$\\pm$" < myValues; + spdlog::debug("Filling my values into a vector"); + for (auto obs: ANG_OBS){ + double err = get_param_error_from_rootfile(fitFile, obs, 1,0); + //The easiest rounding in c++ + err = round(getCorrectedError(obs,err,649)*1000.0)/1000.0; //TODO + double val = round(get_param_value_from_rootfile(fitFile, obs, 1,0)*1000.0)/1000.0; + myValues.push_back(valErr(val,err)); + } + std::vectorsig_Davids = getSigma(myValues,Davids); + std::vectorsig_Belles = getSigma(myValues,Belles); + std::vectorsig_BaBars = getSigma(myValues,BaBars); + std::vectorsig_B0s = getSigma(myValues,B0s); + + std::cout << "\\begin{table}[]" << std::endl; + std::cout << "\\begin{tabular}{l|llll}" << std::endl; + std::cout << " & \\lhcb \\Bu & Belle (\\Bu) & BaBar (\\Bu + \\Bd) & \\lhcb \\Bd \\\\\\hline" << std::endl; + //for_indexed(auto myVal: myValues){ //TODO remove: yields warning in compilation due to unused 'myVals' + for(UInt_t i = 0; i < sig_Davids.size(); i++){ + std::cout << std::setprecision(2) << "$" << ANG_OBS_TLaTeX[i] << "$"; + std::cout << " & " << sig_Davids[i]; + std::cout << " & " << sig_Belles[i]; + std::cout << " & " << sig_BaBars[i]; + std::cout << " & " << sig_B0s[i]; + std::cout << "\\\\" << std::endl; + } + + std::cout << " \\end{tabular}" << std::endl; + std::cout << " \\end{table}" << std::endl; + + return 0; +} + + diff --git a/Code/FCNCFitter/sources/Scripts/ReferencePlots.hh b/Code/FCNCFitter/sources/Scripts/ReferencePlots.hh new file mode 100644 index 0000000..89498e9 --- /dev/null +++ b/Code/FCNCFitter/sources/Scripts/ReferencePlots.hh @@ -0,0 +1,10 @@ +//Renata Kopecna + +#ifndef REFERENCEPLOTS_HH +#define REFERENCEPLOTS_HH + +int plotComparisonFull(); +int foldingTable(); +int plotComparisonSigmas(); + +#endif // REFERENCEPLOTS_HH diff --git a/Code/FCNCFitter/sources/Scripts/RunningScripts.cc b/Code/FCNCFitter/sources/Scripts/RunningScripts.cc new file mode 100644 index 0000000..6ac7896 --- /dev/null +++ b/Code/FCNCFitter/sources/Scripts/RunningScripts.cc @@ -0,0 +1,73 @@ +//Renata Kopecna + + +#include "RunningScripts.hh" +#include +#include + +#include "ScriptHelpers.hh" + +int runWhatever(basic_params pars, basic_actions acts){ + int status = 0; + + + for (auto obs: ANG_OBS){ + plotComparison(obs); + plotComparisonMCFolding(obs); + } + + + // plotComparisonFull(); + // plotComparisonSigmas(); + // foldingTable(); + //return loadAllFiles("S3",pars); + //return loadAllFiles("Fl",pars); + + //for(auto obs: ANG_OBS) loadAllFiles(obs,pars); + return 0; + + + + bool toyEval = true; + bool loopFolds = pars.folding == 5; + bool onlySig = isInVec(pars.jobID,{531, 532, 533, 534, 535, 536, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595}); + bool onlyBkg = isInVec(pars.jobID,{546, 547, 548, 549, 550, 551}); + bool sWave = isInVec(pars.jobID,{496, 497, 498, 531, 532, 533, 534, 535, 536, 558, 559, 560, 561, 562, 563, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650}); + bool bMass = isInVec(pars.jobID,{496, 497, 498, 572, 573, 574, 575, 576, 577, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 626, 627, 628, 629, 649, 650}); + if(toyEval){ + //bool doPulls = true; + std::vector variables = {}; + std::vector names = {}; + if(!onlyBkg){ + variables = merge_two_vecs(variables,ANG_OBS); + names = merge_two_vecs(names,ANG_OBS_TLaTeX); + } + if(false){ + variables = merge_two_vecs(variables,P_OBS); + names = merge_two_vecs(names,P_OBS_TLaTeX); + } + if(false){ + variables = merge_two_vecs(variables,MASS_OBS); + names = merge_two_vecs(names,MASS_OBS_TLaTeX); + } + if(!onlySig){ + variables = merge_two_vecs(variables,BKG_OBS); + names = merge_two_vecs(names,BKG_OBS_TLaTeX); + } + if (sWave){ + variables = merge_two_vecs(variables,SWAVE); + names = merge_two_vecs(names,SWAVE_TLaTeX); + } + if (bMass || pars.reference){ + variables = merge_two_vecs(variables,{"m_b"}); + names = merge_two_vecs(names,{"m_{B^{+}}"}); + } + if (pars.reference){ + variables = merge_two_vecs(variables,{"m_sigma_1"}); + names = merge_two_vecs(names,{"\\sigma_{1}"}); + } + return EvaluateToyStudy(variables, names, pars, loopFolds, true, false, onlySig, onlyBkg) + EvaluateToyStudy(variables, names, pars, loopFolds, false, false, onlySig, onlyBkg); + } + return status; +} + diff --git a/Code/FCNCFitter/sources/Scripts/RunningScripts.hh b/Code/FCNCFitter/sources/Scripts/RunningScripts.hh new file mode 100644 index 0000000..0275ade --- /dev/null +++ b/Code/FCNCFitter/sources/Scripts/RunningScripts.hh @@ -0,0 +1,14 @@ +//Renata Kopecna + + +#ifndef RUNNINGSCRIPTS_HH +#define RUNNINGSCRIPTS_HH + +#include "GenLvlvsMC.hh" +#include "EvaluateToys.hh" +#include +#include "ReferencePlots.hh" +#include "GetMeanError.hh" + +int runWhatever(basic_params pars, basic_actions acts); +#endif // RUNNINGSCRIPTS_HH diff --git a/Code/FCNCFitter/sources/Scripts/ScriptHelpers.cc b/Code/FCNCFitter/sources/Scripts/ScriptHelpers.cc new file mode 100644 index 0000000..a89274f --- /dev/null +++ b/Code/FCNCFitter/sources/Scripts/ScriptHelpers.cc @@ -0,0 +1,215 @@ +//Renata Kopecna + + +#include "ScriptHelpers.hh" +#include +#include +#include +#include +#include +#include + +#include + +//Takes two valErr and returns the difference in sigmas +double sigmaAway(valErr a, valErr b){ + double diff = a.val - b.val; + double effErr = sqrt(pow(a.err,2)+pow(b.err,2)); + return effErr == 0 ? 0 : diff/effErr; +} + +//Returns true if the observable is measured in certain folding +bool plotObsv(int folding, std::string obs){ + if (obs == "Fl" || obs == "S3") return true; //FL and S3 always there + + switch(folding){ + case -1: return true; + case 0: + if (obs == "Afb") return true; + else if (obs == "S9") return true; + else return false; + case 1: + if (obs == "S4") return true; + else return false; + case 2: + if (obs == "S5") return true; + else return false; + case 3: + if (obs == "S7") return true; + else return false; + case 4: + if (obs == "S8") return true; + else return false; + } + return false; +} + +std::vector obsv_range(std::string parName){ + if (parName == "S1s") return {+0.0, +1.0}; + if (parName == "Fl") return {+0.0, +1.0}; + if (parName == "S3") return {-0.5, +0.3}; + if (parName == "S4") return {-0.5, +0.3}; + if (parName == "S5") return {-0.5, +0.3}; + if (parName == "Afb") return {-0.2, +1.0}; + if (parName == "S7") return {-0.25, +0.25}; + if (parName == "S8") return {-0.25, +0.30}; + if (parName == "S9") return {-0.25, +0.25}; + + //mass fit + if (parName == "m_b") return {PDGMASS_B-10,PDGMASS_B+10}; + if (parName == "m_sigma_1") return {20.0, 40.0}; + if (parName == "alpha_1") return {0.5, 2.5}; + if (parName == "alpha_2") return {0.5, 1.5}; + if (parName == "n_1") return {0.1, 15.0}; + if (parName == "n_2") return {5.0, 15.0}; + if (parName == "m_lambda") return {-0.1, -0.00001}; + if (parName == "f_sig") return {0.0, 1.0}; + + + //angular bkg + if (parName == "cbkgctl0") return {-10.0, 10.0}; + if (parName == "cbkgctl1") return {-10.0, 10.0}; + if (parName == "cbkgctl2") return {-10.0, 10.0}; + if (parName == "cbkgctl3") return {-10.0, 10.0}; + if (parName == "cbkgctl4") return {-10.0, 10.0}; + if (parName == "cbkgctk0") return {-10.0, 10.0}; + if (parName == "cbkgctk1") return {-10.0, 10.0}; + if (parName == "cbkgctk2") return {-10.0, 10.0}; + if (parName == "cbkgctk3") return {-10.0, 10.0}; + if (parName == "cbkgctk4") return {-10.0, 10.0}; + if (parName == "cbkgctk5") return {-10.0, 10.0}; + if (parName == "cbkgctk6") return {-10.0, 10.0}; + if (parName == "cbkgphi0") return {-10.0, 10.0}; + if (parName == "cbkgphi1") return {-10.0, 10.0}; + if (parName == "cbkgphi2") return {-10.0, 10.0}; + if (parName == "cbkgphi3") return {-10.0, 10.0}; + if (parName == "cbkgphi4") return {-10.0, 10.0}; + if (parName == "cbkgmkpi0") return {-10.0, 10.0}; + if (parName == "cbkgmkpi1") return {-10.0, 10.0}; + if (parName == "cbkgmkpi2") return {-10.0, 10.0}; + if (parName == "cbkgmkpi3") return {-10.0, 10.0}; + if (parName == "cbkgmkpi4") return {-10.0, 10.0}; + + spdlog::critical("Wrong parameter tree name! Setting range to default -1.0, 1.0"); + return {-1.0,1.0}; +} + + +void designTGraph(TGraphAsymmErrors *g, int markerStyle, int color){ + g->SetLineColor(color); + g->SetMarkerColor(color); + g->SetLineWidth(2); + g->SetMarkerStyle(markerStyle); + g->SetMarkerSize(3); + g->SetFillColor(0); + g->SetFillStyle(0); +} +TH1D *emptyHist(std::string observable, double min, double max, int nBins){ + TH1D* haxes = new TH1D("haxes", std::string(";#it{q}^{2} ["+GeVc_2()+"];"+observable).c_str(), nBins, Q2_MIN_RANGE, Q2_MAX_RANGE_B0); + haxes->SetMinimum(min); + haxes->SetMaximum(max); + haxes->SetTitleSize(0.06, "XY"); + haxes->SetLabelSize(0.05, "XY"); + return haxes; +} + +TH1D *emptyHist(std::string observable){ + double min = obsv_range(observable)[0]; //Set the range for each parameter + double max = obsv_range(observable)[1]; //Needs to run twice but whatever + return (emptyHist(observable,min,max,100)); +} + + +TGraphAsymmErrors* get_TGraphFromFile(std::string fileName, std::string observable, bool isRef){ + //Open file + spdlog::info("Opening " + fileName); + TFile* file = new TFile(fileName.c_str(), "READ"); + if (!file->GetListOfKeys()->Contains(observable.c_str())){ + spdlog::critical("Wrong tree name " + observable + "! Abort."); + assert(0); + } + + TTree* tree = (TTree*)file->Get(observable.c_str()); + tree->SetBranchStatus("*",1); //Activate all branches + + //Read the q2 bins + int totBins = DEFAULT_TREE_VAL; + tree->SetBranchAddress("totBins", &totBins); + tree->GetEntry(0); + + std::vector q2min = get_TheQ2binsmin(totBins,isRef); + std::vector q2max = get_TheQ2binsmax(totBins,isRef); + + //Initilialize the TGraph + //Initialize it on purpose with 0 points; in case something goes wrong with totBins, this makes sure there are no segfaults + TGraphAsymmErrors* graph = new TGraphAsymmErrors(0); + + //Loop over nBins that are saved in the tree + for (int b = 0; b < totBins; b++){ + double value = DEFAULT_TREE_VAL; + double error = DEFAULT_TREE_ERR; + double errorup = DEFAULT_TREE_ERR; + double errordown= DEFAULT_TREE_ERR; + int migrad = DEFAULT_TREE_INT; + int cov = DEFAULT_TREE_INT; + + tree->SetBranchAddress("value", &value); + tree->SetBranchAddress("error", &error); + tree->SetBranchAddress("error_up", &errorup); + tree->SetBranchAddress("error_down", &errordown); + tree->SetBranchAddress("migrad", &migrad); + tree->SetBranchAddress("status_cov", &cov); + tree->GetEntry(b); + + //if opts.hesse is non-active, use error for both error_up and error_down + if(errordown == DEFAULT_TREE_ERR) errordown = error; + if(errorup == DEFAULT_TREE_ERR) errorup = error; + + //Set point in TGraph + spdlog::debug("Setting point in bin {0:d} in Tgraph {1:s}", b, graph->GetName()); + spdlog::debug("bin center {0:f}, value {1:f}", bin_center_q2(q2min,q2max,b), value); + spdlog::debug("bin width {0:f}, err up {1:f}, err down {2:f}", + bin_halfWidth_q2(q2min,q2max,b), fabs(errordown), fabs(errorup)); + graph->SetPoint(graph->GetN(),bin_center_q2(q2min,q2max,b), value); + graph->SetPointError(graph->GetN()-1,bin_halfWidth_q2(q2min,q2max,b), bin_halfWidth_q2(q2min,q2max,b), fabs(errordown), fabs(errorup)); + + } //loop over bins + + spdlog::debug("Graph filled."); + file->Close(); + + return graph; +} + + +TH1D* hist_graphDiff(TGraphAsymmErrors* graph_a, TGraphAsymmErrors* graph_b, + double range, std::string title){ + //Check they have the same number of points + int n_points = graph_a->GetN(); + if (n_points!= graph_b->GetN()){ + spdlog::error("The input graphs have different number of points!"); + spdlog::error("Graph a: {0:d}\tGraph b: {1:d}", n_points, graph_b->GetN()); + assert(0); + } + //Technically one shoudl check matching x-axis values, but screw that + + TH1D* hist = emptyHist(title,-range,range,1000); + //Make a histogram with the difference + + for (int p = 0; pGetY()[p] - graph_b->GetY()[p]; + double effErr = 0; + if (val > 0) effErr = sqrt(pow(graph_a->GetErrorYlow(p),2) +pow(graph_b->GetErrorYhigh(p),2)); + else effErr = sqrt(pow(graph_a->GetErrorYhigh(p),2)+pow(graph_b->GetErrorYlow(p),2)); + double low_edge = hist->GetXaxis()->FindBin(graph_a->GetX()[p]-graph_a->GetErrorXlow(p)); + double high_edge = hist->GetXaxis()->FindBin(graph_a->GetX()[p]+graph_a->GetErrorXhigh(p)); + spdlog::debug("low_edge {0:d}", low_edge); + spdlog::debug("high_edge {0:d}", high_edge); + for (int b = low_edge+1; bSetBinContent(b,effErr == 0 ? 0 : val/effErr); + } + } + + return hist; +} + diff --git a/Code/FCNCFitter/sources/Scripts/ScriptHelpers.hh b/Code/FCNCFitter/sources/Scripts/ScriptHelpers.hh new file mode 100644 index 0000000..438d412 --- /dev/null +++ b/Code/FCNCFitter/sources/Scripts/ScriptHelpers.hh @@ -0,0 +1,64 @@ +//Renata Kopecna + +#ifndef SCRIPTHELPERS_HH +#define SCRIPTHELPERS_HH + +#include +#include +#include + + +const std::vector ANG_OBS = {"Fl","S3","S4","S5","Afb","S7","S8","S9"}; //lenght=8 +const std::vector ANG_OBS_TLaTeX = {"F_{L}", "S_{3}","S_{4}", "S_{5}", "A_{FB}","S_{7}", "S_{8}","S_{9}"}; + +const std::vector P_OBS = {"Fl", "P1", "P2", "P3", "P4", "P5", "P6", "P8"}; +const std::vector P_OBS_TLaTeX = {"F_{L}", "P_{1}", "P_{2}", "P_{3}", "P_{4}^{\\prime}", "P_{5}^{\\prime}", "P_{6}^{\\prime}", "P_{8}^{\\prime}"}; + +const std::vector MASS_OBS = {"m_b","m_sigma_1","alpha_1","alpha_2","n_1","n_2"}; +const std::vector MASS_OBS_TLaTeX = {"m_{B^{+}}", "\\sigma_{1}", "\\alpha_{1}", "\\alpha_{2}", "n_{1}", "n_{2}"}; + +//TODO: make it based on the order of the polynomial //TODO: change according to the final order +const std::vector BKG_OBS = {"cbkgctk1", "cbkgctk2", "cbkgctk3", "cbkgctk4", "cbkgctk5", + "cbkgctl1", "cbkgctl2", + "m_lambda","f_sig"};//lenght=9 +const std::vector BKG_OBS_TLaTeX = {"c_{bkg}^{1}(cos\\Theta_{K})", "c_{bkg}^{2}(cos\\Theta_{K})", "c_{bkg}^{3}(cos\\Theta_{K})", "c_{bkg}^{4}(cos\\Theta_{K})", "c_{bkg}^{5}(cos\\Theta_{K})", + "c_{bkg}^{1}(cos\\Theta_{L})", "c_{bkg}^{2}(cos\\Theta_{L})", + "\\lambda_\\mathrm{m}","f_{sig}"}; + +const std::vector SWAVE = {"FS","SS1","SS2","SS3","SS4","SS5"};//lenght=6 +const std::vector SWAVE_TLaTeX = {"F_{S}","S_{S1}","S_{S2}","S_{S3}","S_{S4}","S_{S5}"}; + + +struct valErr{ //For easier saving of David's, Belle's, BaBar's and B0's analysis + double val = 0.0; + double err = 0.0; + //Constructor + valErr(double v, double err): + val(v), err(err){}; + //assignment operator: + valErr operator=(const valErr ve){ + val = ve.val; + err = ve.err; + return *this; + } +}; + +//Takes two valErr and returns the difference ins sigmas +double sigmaAway(valErr a, valErr b); + +//Returns true if the observable is measured in certain folding +bool plotObsv(int folding, std::string obs); + +std::vector obsv_range(std::string parName); + +void designTGraph(TGraphAsymmErrors *g, int markerStyle, int color); + +//Returns and empty histogram so the axes are plotted +TH1D *emptyHist(std::string observable, double min, double max, int nBins); +TH1D *emptyHist(std::string observable); + +TGraphAsymmErrors* get_TGraphFromFile(std::string fileName, std::string observable, bool isRef); + +TH1D* hist_graphDiff(TGraphAsymmErrors* graph_a, TGraphAsymmErrors* graph_b, + double range, std::string title); +#endif // SCRIPTHELPERS_HH diff --git a/Code/FCNCFitter/sources/help.cc b/Code/FCNCFitter/sources/help.cc new file mode 100644 index 0000000..e6d89cf --- /dev/null +++ b/Code/FCNCFitter/sources/help.cc @@ -0,0 +1,128 @@ +//Renata Kopecna + +#include +#include +#include + +void print_help(){ + spdlog::set_level(spdlog::level::debug); + spdlog::set_pattern("%^[HELP]%$ %v"); + spdlog::debug( "//--------------------------------------------------------------------------\\\\" ); + spdlog::debug( "|| FCNC fitter to determine angular coefficients of B+ --> K*+ mu mu. ||" ); + spdlog::debug( "\\\\--------------------------------------------------------------------------//" ); + spdlog::debug( " Please set the following options:" ); + spdlog::debug( "- - - - - - - - - - - - - - - - -" ); + spdlog::debug( "- - - - - - MANDATORY - - - - - -" ); + spdlog::debug( "- - - - - - - - - - - - - - - - -" ); + spdlog::debug( " -r : Select Run number" ); + spdlog::debug( " 0 : Optional, use when running per year." ); + spdlog::debug( " 1, 2 : Run only on Run 1 or 2" ); + spdlog::debug( " 12 : Run on both Runs." ); + + spdlog::debug( " 21 : Run on 15+16." ); + spdlog::debug( " 22 : Run on 17+18." ); + spdlog::debug( " -y : Select year" ); + + spdlog::debug( "- - - - - - - - - - - - - - - - -" ); + spdlog::debug( "- - - - - - OPTIONAL - - - - - -" ); + spdlog::debug( "- - - - - - - - - - - - - - - - -" ); + spdlog::debug( " -a : Get angular resolution." ); + spdlog::debug( " -b : Run on a certain numbers of q2 bin." ); + spdlog::debug( " -c : Get angular corrections." ); + spdlog::debug( " -d : Set dataset"); + spdlog::debug( " 0 : Data"); + spdlog::debug( " 1 : Signal MC"); + spdlog::debug( " 2 : Ref MC"); + spdlog::debug( " 3 : PHSP"); + spdlog::debug( " 4 : Generator level MC"); + spdlog::debug( " 5 : Boosted generator level MC"); + spdlog::debug( " -e : Set number of events to be used." ); + spdlog::debug( " -f : Run a fit." ); + + spdlog::debug( " 0 : Background only fit"); + spdlog::debug( " 1 : Complete fit"); + spdlog::debug( " 2 : Mass fit"); + spdlog::debug( " 3 : Method of moments"); + spdlog::debug( " 4 : MC fit"); + spdlog::debug( " 5 : Generator level fit"); + spdlog::debug( " 6 : "); + spdlog::debug( " -g : Use folding of angles. Five possibilities use range [0-4]" ); + spdlog::debug( " : [0]: phi' = phi + pi for phi < 0" ); + spdlog::debug( " : [1]: phi' = -phi for phi < 0" ); + spdlog::debug( " phi' = pi - phi for ctl < 0 " ); + spdlog::debug( " ctl' = -ctl for ctl < 0 " ); + spdlog::debug( " : [2]: phi' = -phi for phi < 0" ); + spdlog::debug( " ctl' = -ctl for ctl < 0 " ); + spdlog::debug( " : [3]: phi' = pi - phi for phi > pi/2" ); + spdlog::debug( " phi' = -pi - phi for phi < -pi/2 " ); + spdlog::debug( " ctl' = -ctl for ctl < 0 " ); + spdlog::debug( " : [4]: phi' = pi - phi for phi > pi/2" ); + spdlog::debug( " phi' = -pi - phi for phi < -pi/2 " ); + spdlog::debug( " ctk' = -ctk for ctk < 0 " ); + spdlog::debug( " ctl' = -ctl for ctl < 0 " ); + spdlog::debug( " -h : Print this help :)" ); + + spdlog::debug( " -i : index. " ); //TODO + spdlog::debug( " in combination with angCorr, it scans the corrections. " ); + spdlog::debug( " in combination with -f 4, it sets the polarity: 1 is up, 2 is down. " ); + + spdlog::debug( " -j : job index. Usage to be added" ); //TODO + spdlog::debug( " -k : Converting events. Needs specification of a year/run and dataset." ); + spdlog::debug( " -l : Likelihood profile scans." ); + spdlog::debug( " -m : Getting pulls from MC" ); + spdlog::debug( " -n : Set number of toys." ); + spdlog::debug( " -o : Run feldman cousins." ); + spdlog::debug( " -p : Use P' instead of S-observables." ); + spdlog::debug( " -q : Use Jpsi Q2 region" ); + + spdlog::debug( " -t : Get pulls fro toys." ); + spdlog::debug( " -u : Set number q2 bins to be used." ); + spdlog::debug( " -v : Set verbosity levels. Default is info." ); + spdlog::debug( " 0 : Trace" ); + spdlog::debug( " 1 : Debug" ); + spdlog::debug( " 2 : Info" ); + spdlog::debug( " 3 : Warn" ); + spdlog::debug( " 4 : Error" ); + spdlog::debug( " 5 : Critical" ); + + spdlog::debug( " -w : Does nothing for now." ); + spdlog::debug( " -x : Runs whatever script you decide from Scripts/. This is due to ROOT trying to compile everything when it really doesn't need to and running it standalone would be a pain in the ass." ); + + spdlog::debug( " -z : Testing flag." ); + + spdlog::debug( "- - - - - - - - - - - - - - - - -" ); + spdlog::debug( "- - - - - - SYSTEMATICS - - - - -" ); + spdlog::debug( "- - - - - - - - - - - - - - - - -" ); + spdlog::debug( " -s : Run systematic study number #ID" ); + spdlog::debug( " 1 : Bootstrapping of PHSP MC" ); + spdlog::debug( " 2 : Perform fit with non-symmetric acceptance in ctl" ); + spdlog::debug( " 3 : Increase Legendre poly order by 2 for PHSP MC" ); + spdlog::debug( " 4 : Randomly change PHSP MC reweighting wihtin it's uncertainties" ); + spdlog::debug( " 5 : Check non-homogeneous FS distributions in q2" ); + spdlog::debug( " 6 : Vary angles (ctk, ctl and phi) within the angular resoluation" ); + spdlog::debug( " 7 : Generate toy events with double-gaussian profile and fit with CB" ); + spdlog::debug( " 8 : Systematic study on angular background model, add 10\% contribution of higher order" ); + spdlog::debug( " 9 : Investigate systematic effects due to trigger selection" ); + spdlog::debug( " 10 : Reweight PHSP MC according to pion PT disagreement in DD" ); + spdlog::debug( " 11 : Background systematic for mimicing the B0 -> KS mu mu veto" ); + reset_spdlog(); // back to default format + +} + +void print_errorCodes(){ + + spdlog::set_level(spdlog::level::err); + spdlog::set_pattern("%^[HELP]%$ %v"); + spdlog::error( "//-----------------------------\\\\"); + spdlog::error( "|| Possible error codes: ||"); + spdlog::error( "\\\\-----------------------------//"); + + spdlog::error( " 0 : Everything is okay!" ); + spdlog::error( " 1 : Something is wrong with (parsing) the input options!" ); + spdlog::error( " 2 : Something is wrong with addition options in the fitter!" ); + spdlog::error( " 3 : Wrong tree/parameter name!" ); + spdlog::error( " 4 : Wrong array/vector lenght!" ); + spdlog::error( " 5 : Missing implementation" ); + spdlog::error( " 404 : Something is not found!" ); + reset_spdlog(); // back to default format +} diff --git a/Code/FCNCFitter/sources/help.hh b/Code/FCNCFitter/sources/help.hh new file mode 100644 index 0000000..65807b3 --- /dev/null +++ b/Code/FCNCFitter/sources/help.hh @@ -0,0 +1,10 @@ +//Renata Kopecna + +#ifndef HELP_HH +#define HELP_HH + +#include + +void print_help(); +void print_errorCodes(); +#endif // HELP_HH diff --git a/Code/FCNCFitter/sources/parse.cc b/Code/FCNCFitter/sources/parse.cc new file mode 100644 index 0000000..083847e --- /dev/null +++ b/Code/FCNCFitter/sources/parse.cc @@ -0,0 +1,227 @@ +//Renata Kopecna + +#include "parse.hh" + +#include +#include +#include +#include +#include +//--------------------------------------// +// Helpers for parsing the options // +//--------------------------------------// + +int parseOpts(int argc, char *argv[], basic_params &par, basic_actions &act, int nMCEvents){ + + int opt = 0; + + //Check if there are any arguments + if(argc > 1){ + spdlog::info("Got a total of {0:d} input options.", argc); + } + else{ + spdlog::error("No arguments given to the program. Use '-h' to see options. Exit..."); + return 1; + } + + //Loop over all arguments and set par and act accordingly + //no questionmark: value afterwards, questionamrk = bool + while((opt = getopt(argc, argv, "a?:b:c?:d:e:f:g:h?:i:j:k?:l?:m?:o:p?:q?:r:s:t?:u:v:w?:x?:y:z:")) != -1){ + switch(opt) { + case 'a': //action: do angular resolution + spdlog::info("Get angular resolutions!"); + act.angRes = true; + break; + case 'b': + par.bin = atoi(optarg); + spdlog::info("Running on q2 bin ", par.bin); + break; + case 'c': + spdlog::info("Get angular corrections!"); + //par.dataset = 3; //Always use MC //Not needed, as PHSP is hardcoded in the corrections obvsly + act.angCorr = true; + break; + case 'd': + par.dataset = atoi(optarg); + if (par.dataset < 0 || par.dataset > 5){ + spdlog::error("Dataset can be only 0 - 5!"); + spdlog::info("0 for signal data"); + spdlog::info("1 for signal MC, 2 for Jpsi MC"); + spdlog::info("3 for PHSP"); + spdlog::info("4 for PHSP genLVL MC"); + spdlog::info("5 for signal genLvl MC"); + return 1; + } + else{ + spdlog::info("Using dataset {0:d}", par.dataset); + } + break; + case 'e': + par.nEvents = atoi(optarg); + spdlog::info("Running on {0:d} events.", par.nEvents); + break; + case 'f': + act.fitType = atoi(optarg); + if (act.fitType < 0 || act.fitType > 6){ + spdlog::error("Fit option can be only 0 - 6!"); + return 1; + } + else{ + spdlog::info("Fitting with option {0:d}!", act.fitType); + } + break; + case 'g': + par.folding = atoi(optarg); + if (par.folding < 0 || par.folding > 5){ + spdlog::error("Use only folding 0 - 4. Plus option 5 for looping over all foldings."); + return 1; + } + spdlog::info("Using folding {0:d}.", par.folding); + break; + case 'h': + print_help(); + print_errorCodes(); + return 0; + case 'i': + par.index = atoi(optarg); + spdlog::info("Using index {0:d}.", par.index); + break; + case 'j': + par.jobID = atoi(optarg); + spdlog::info("Using job index {0:d}.", par.jobID); + break; + case 'k': + spdlog::info("Convert events!"); + spdlog::info("Don't forget to specify what year/run/dataset."); + act.convert = true; + break; + case 'l': + spdlog::info("Likelyhood profiles on!"); + par.likelyhood = true; + break; + case 'm': + spdlog::info("Getting pulls from MC"); + act.pullsMC = true; + break; + case 'o': + spdlog::info("Feldman cousins!"); + par.FeldCous = true; + break; + case 'p': + spdlog::info("Using P' instead of S!"); + par.usePprime = true; + break; + case 'q': + spdlog::info("Looking into reference channel!"); + par.reference = true; + break; + case 'r': + par.Run = atoi(optarg); + if(par.Run != 0 && par.Run != 1 && par.Run != 2 && par.Run != 12 && par.Run != 21 && par.Run != 22){ + spdlog::error("Used incorrect input as Run number! Can be 1, 2, 12, 21, 22 or 0 in case of per-year running."); + return 1; + } + else{ + spdlog::info("Use data of Run {0:d}", par.Run); + } + break; + case 's': + act.systematics = atoi(optarg); + spdlog::info("Systematic study {0:d}.", act.systematics); + break; + case 't': + act.pullsToys = true; + spdlog::info("Getting pulls from toys"); + break; + case 'u': + par.nBins = atoi(optarg); + spdlog::info("Number of used q2 bins: {0:d}.", par.nBins); + if (par.nBins != 0 && par.nBins != 1 && par.nBins != 2 && par.nBins !=4 && par.nBins !=5 + && par.nBins !=8 && par.nBins !=9){ //I hope that is all :D + spdlog::error("Wrong number of bins! Can be either 1, 2, 4 or 5 (or 8)!"); + return 1; + } + break; + case 'v': + par.verbosity = atoi(optarg); //Set verbosity level + break; + case 'w': + act.genToys = true; //Fit generated toys. It requires -e to be set! + break; + case 'x': + act.script = true; //Run whatever script you like + spdlog::info("Running whatever is defined in RunningScripts"); + break; + case 'y': + par.year = atoi(optarg); + spdlog::info("Running on year {0:d}.", par.year); + par.Run = 0; //Set Run=0 so it is clear what is used + break; + case 'z': + par.testInt = atoi(optarg); + spdlog::info("testInt: {0:d}.", par.testInt); + break; + } + } + return 0; + //parse the options + +} + +int checkYear(basic_params par){ + if (par.Run == -1 && par.year == -1){ + spdlog::error("I need run/years specified!"); + return 1; + } + else return 0; +} + +int checkDataset(basic_params par){ + if (par.dataset == -1){ + spdlog::error("I need dataset specified!"); + return 1; + } + if (par.dataset == 2){ + par.reference = true; + } + return 0; +} + +int checkOpts(basic_params &par, basic_actions &act){ + //TODO: enhance as you add more options to act + if (act.angRes){ //-a + if (checkYear(par) == 1) return 1; + } + if (act.angCorr){ //-c + if (par.index != -1){ //-i, means to scan the corrections + act.angCorrScan = true; + act.angCorr = false; + } + } + if (act.convert){ + if (checkYear(par) == 1) return 1; + if (checkDataset(par) == 1) return 1; + } + if (act.fitType != -1){ + if (checkYear(par) == 1) return 1; + if (checkDataset(par) == 1) return 1; + } + if (act.fitType == 4){ //Check if dataset is not data + if (par.dataset == 0) return 1; + //If MC fit, i can set the polarity, useful for checks + if (par.index == 1) par.polarity = 1; + if (par.index == 2) par.polarity = -1; + } + if (par.nBins == -1){ + spdlog::warn("Number of bins in q2 is not set! Using default settings of {0:d} bins!",NBINS_DEFAULT); + par.nBins = NBINS_DEFAULT; + } + if (act.genToys){ + if (par.nEvents == -1){ + spdlog::warn("Number of events ot be generated is not set! Using default settings of 100 events!"); + par.nEvents = 100; //Generate a default number of toy events + } + } + return 0; +} + diff --git a/Code/FCNCFitter/sources/parse.hh b/Code/FCNCFitter/sources/parse.hh new file mode 100644 index 0000000..89ed421 --- /dev/null +++ b/Code/FCNCFitter/sources/parse.hh @@ -0,0 +1,112 @@ +//Renata Kopecna + + +#ifndef PARSEOPTS_HH +#define PARSEOPTS_HH + +//TODO: toys +//TODO: this should probably be a class instead of a struct + +//parameters +//b Bin #b +//d Dataset; 0 :data, 1 MC, ... +//g FoldinG +//e number of Events +//i,j general purpose indices +//l get likelihood profiles of final fit? +//p Use P' instead of S +//r Run: 0/1/2/12/21/22 +//n number of toys +//o feLdmanCousins +//u Number of bins +//v Verbosity +//y Year: 2011, 2012, 2015, 2016, 2017, 2018 +//z Used for testing stuff in case one needs an extra parameter to tune or so + +struct basic_params{ + int bin; + int dataset; + int folding; + int index; + int jobID; + bool likelyhood; + bool FeldCous; + bool usePprime; + bool reference; + int Run; + int year; + int nEvents; + int nBins; + int verbosity; + int testInt; + int polarity; + + basic_params(){ + bin = -1; + dataset = -1; + folding = -1; + index = -1; + jobID = -1; + Run = -1; + year = -1; + nEvents = -1; + nBins = -1; + likelyhood = false; + FeldCous = false; + usePprime = false; + reference = false; + verbosity = 2; + testInt = -1; + polarity = 0; + } +}; + +//Actions +//a angular resolution +//c angular Correction +//f fit: + //0: bkg only (0 signals :) (only ang fit!) + //1: Full fit (2D+4D) + //2: 2D mass fit + //3: MoM + //4: 4D MC fit (B mass+angles in bins of q2) + //5: GenLvlFit +//h Get help +//k convert Events +//m pulls from MC +//s systematics +//t pulls from toys + +struct basic_actions{ + bool angRes; + bool angCorr; //Use generic index i to set whether it is a scan or not + bool angCorrScan; + bool convert; + int fitType; + bool getHelp; + int systematics; + bool genToys; + bool pullsToys; + bool pullsMC; + bool script; + + basic_actions(){ + fitType = -1; + systematics = -1; + angCorrScan = false; + angRes = false; + angCorr = false; + convert = false; + getHelp = false; + genToys = false; + pullsToys = false; + pullsMC = false; + script = false; + } +}; + + +int parseOpts(int argc, char *argv[], basic_params &par, basic_actions &act, int nMCEvents); +int checkOpts(basic_params &par, basic_actions &act); + +#endif // PARSEOPTS_HH diff --git a/Code/FCNCFitter/sources/paths.cc b/Code/FCNCFitter/sources/paths.cc new file mode 100644 index 0000000..d916f79 --- /dev/null +++ b/Code/FCNCFitter/sources/paths.cc @@ -0,0 +1,593 @@ +//Renata Kopecna + +#include +#include +#include +#include "Helpers/helpers.hh" + +//=====================================// +// Paths for datsets // +//=====================================// + +std::string datapath(){ //Returns the path where the data is stored based on the server/user + char cwd[256]; + if (getcwd(cwd, sizeof(cwd)) != NULL) { + spdlog::debug("CURRENT DATA DIRECTORY: "+std::string(cwd)); + if(strstr(cwd, "kopecna")){ + if(strstr(cwd, "cern")) return "TODO/ADD/PATH/TO/FILES/ON/LXPLUS";//for lxplus //TODO @Renata + if(strstr(cwd, "home")) return "/home/lhcb/kopecna/B2KstarMuMu_clean/Data/Tuples/";//for HD servers + } + if(strstr(cwd, "dgerick")){ + if(strstr(cwd, "cern")) return "/afs/cern.ch/work/d/dgerick/b2kmm/data/";//for lxplus + if(strstr(cwd, "work")) return "/home/lhcb/kopecna/B2KstarMuMu_clean/Data/Tuples/";//for HD servers + } + if(strstr(cwd, "condor")) return "/afs/cern.ch/work/d/dgerick/b2kmm/data/";//for condor + } + //default value: + spdlog::warn("None of the expected data paths are found! Setting workpath to the default \n /home/lhcb/kopecna/B2KstarMuMu_clean/Data/Tuples/"); + return "/home/lhcb/kopecna/B2KstarMuMu_clean/Data/Tuples/"; +} + +std::string workpath(){ //Returns the path where the program is executed based on the server/user + char cwd[256]; + if (getcwd(cwd, sizeof(cwd)) != NULL) { + spdlog::debug("CURRENT WORKING DIRECTORY: "+std::string(cwd)); + if(strstr(cwd, "kopecna")){ + if(strstr(cwd, "cern")) return "TODO/ADD/PATH/TO/FCNCFITTER/ON/LXPLUS";//for lxplus //TODO @Renata + if(strstr(cwd, "home")) return "/home/lhcb/kopecna/B2KstarMuMu_clean/Code/FCNCFitter/";//for HD servers + } + if(strstr(cwd, "dgerick")){ + if(strstr(cwd, "cern")) return "/afs/cern.ch/work/d/dgerick/b2kmm/";//for lxplus + if(strstr(cwd, "work")) return "/home/lhcb/kopecna/B2KstarMuMu_clean/Code/FCNCFitter/";//for HD servers + } + if(strstr(cwd, "condor")) return "/afs/cern.ch/work/d/dgerick/b2kmm/";//for condor + } + //default value + spdlog::warn("None of the expected workpaths are found! Setting workpath to the default \n /home/lhcb/kopecna/B2KstarMuMu_clean/Code/FCNCFitter/"); + return "/home/lhcb/kopecna/B2KstarMuMu_clean/Code/FCNCFitter/"; +} + +std::string get_folderName_from_jobID(int dataset, std::string decayName){ + if(dataset == 0) return "Data/"+ decayName+ "_"; + else if(dataset == 1) return "MC/"+ decayName + "_MC"; + else if(dataset == 2) return "MC/"+ decayName + "_RefMC"; + else if(dataset == 3) return "PHSP/"+ decayName + "_PHSP"; + else if(dataset == 4 || dataset == 5) return ""; + else { + spdlog::error("Invalid index for conversion function given: {0:d}", dataset); + assert(0); + } +} + +std::string getSelectedTuplePath(int dataset, int run, int year){ + if (dataset==4) return "/home/lhcb/kopecna/B2KstarMuMu_clean/Data/Tuples/PHSP/EvtGen/AtRest/MCTruth_PHSP.root"; + else if (dataset ==5) return "/home/lhcb/kopecna/B2KstarMuMu_clean/Data/Tuples/MC/EvtGen/AtRest/MCTruth.root"; + else return DATA_PATH + get_folderName_from_jobID(dataset, DECAY_NAME) +"_BDToutputSelection_Run"+std::to_string(run)+"_" +std::to_string(year)+".root"; +} + +std::string get_theFCNCpath(int dataset, int run){ + //standard output for [0]: data, [1]: signal MC, [2]: reference channel MC, [3]: phase-space MC, [4]: genLevelMC + + UInt_t loadingRun = (run > 20) ? 2 : run; + std::string theFCNCpath = DATA_PATH + + DECAY_NAME + + "_Run"+std::to_string(loadingRun); + if (dataset == 0) return theFCNCpath + "_FCNC.root"; + if (dataset == 1) return theFCNCpath + "_MC_FCNC.root"; + if (dataset == 2) return theFCNCpath + "_RefMC_FCNC.root"; + if (dataset == 3) return theFCNCpath + "_PHSP_FCNC.root"; + if (dataset == 4) return theFCNCpath + "_PHSP_EvtGen_FCNC.root"; + if (dataset == 5) return theFCNCpath + "_MC_EvtGen_FCNC.root"; + return ""; +} + +std::string get_finalToySamplePath(int nPDF, int job_id, bool fitReference){ + return std::string("FinalToySample_")+(fitReference ? "Jpsi_" : "")+std::to_string(job_id)+"_PDF"+std::to_string(nPDF)+".root"; + +} + +//=====================================// +// Paths for angular parametrization // +//=====================================// + +std::string get_angCorrPath(bool test){ + if (test) return PLOTS_PATH + "/angular/test/"; + else return PLOTS_PATH + "/angular/"; +} +std::string coeffs_eff_phsp_4D(fcnc::options *opts){ + std::string filename = COEFFS_PATH+"Coeffs_" + + DECAY_NAME + "_" + + "Run" + std::to_string(opts->run) + + ((opts->angacccorrperyear && opts->year != -1) ? "_"+std::to_string(opts->year) : "") + // + (opts->full_angular ? "" : "_folding"+std::to_string(opts->folding)) + + (opts->systematic == 1 ? "_bs"+std::to_string(opts->job_id) : "") + + (opts->systematic == 2 ? "_sym_ctl" : "") + + (opts->systematic == 3 ? "_"+std::to_string(opts->orderincrease)+"moreOrders" : "") + + (opts->systematic == 4 ? "_dw"+std::to_string(opts->job_id) : "") + + (opts->systematic == 9 ? "_trg" : "") + + (opts->systematic == 10 ? "_ksPT" : "") + +".txt"; + return filename; +} + +//=====================================// +// Paths for angular resolution // +//=====================================// + +std::string get_angResoFolder_path(){ + return PLOTS_PATH+"angReso/"; +} +std::string get_angResoPlot_path(std::string angle, int year, std::string format){ + return get_angResoFolder_path() + "/Reso_"+angle+"_"+std::to_string(year) + "." + format; +} + +//=====================================// +// Paths for fit results // +//=====================================// +std::string subfolder_path(bool Ref){ + if (Ref) return "Jpsi/"; + else return "Signal/"; +} + +std::string get_MainFitPlot_path(){ + return PLOTS_PATH+"MainFit/"; +} + +std::string get_MCfitPlot_path(){ + return PLOTS_PATH+"MCfit/"; +} + +std::string get_scan_path(){ + return PLOTS_PATH+"Scans/"; +} + +std::string get_MCfitPlot_path(bool Ref, bool PHSP){ + if (PHSP){ + return get_MCfitPlot_path()+"/PHSP/" + subfolder_path(Ref); + } + else{ + return get_MCfitPlot_path() + subfolder_path(Ref); + } +} +std::string get_genLvlFitPlot_path(bool PHSP){ + if (PHSP) return PLOTS_PATH+"GenLvlFit/PHSP/"; + else return PLOTS_PATH+"GenLvlFit/"; +} + +std::string get_MoMPlot_path(){ + return PLOTS_PATH+"MoMFit/"; +} + +std::string get_GenLvlPlot_path(){ + return PLOTS_PATH+"GenLvlFit/"; +} +std::string get_PullPlot_path(){ + return PLOTS_PATH+"Pulls/"; +} + +std::string get_JpsiSimFit2D_path(int idx, bool pPrimes){ //TODO + return FIT_RESULTS_PATH+"fitresult_JpsiFit_SimultaneousFit_2Dfit_pdf"+std::to_string(idx)+ + std::string(pPrimes ? "_Pprimes" : "") + ".txt"; +} + +std::string get_SigMCSimFit2D_path(int idx, int bin){ //TODO + return FIT_RESULTS_PATH+"/fitresult_SignalFit_MC_SimultaneousFit_2Dfit_bin"+std::to_string(bin)+"_pdf"+std::to_string(idx)+".txt"; +} + +std::string get_param_scan_path(std::string name, bool error){ + return get_scan_path() + + std::string(error ? "error_" : "value_") + + name + ".eps"; +} + +//=====================================// +// Fit result tags // +//=====================================// +std::string tag_bin(int nBinsToFit){ + std::ostringstream label; + if(nBinsToFit==1) label << "_1BIN"; + else if(nBinsToFit==NBINS_DEFAULT) label << "_ALLBINS"; + else label << "_" << nBinsToFit << "BINS"; + return label.str(); +} +std::string tag_bin(int nBinsToFit, int bin){ + std::ostringstream label; + label << tag_bin(nBinsToFit); + label << std::string(bin == -1 ? "" : ("_bin" + std::to_string(bin))); + //TODO: check what bin == -1 does + return label.str(); +} +std::string tag_Run(int Run){ + return "_Run" + std::to_string(Run); +} +std::string tag_OnlyOneRun(int Run){ + if (Run == 1) return "_OnlyRun1"; + if (Run == 2) return "_OnlyRun2"; + else return tag_Run(Run); +} +std::string tag_Run(int Run, int effRun){ + if (effRun == Run) return tag_OnlyOneRun(Run); + else return tag_Run(effRun); +} +std::string tag_OnlyOnePolarity(int polarity){ + if(polarity==-1) return "_OnlyMagDown"; + if(polarity==+1) return "_OnlyMagUp"; + else return ""; +} +std::string tag_massSideband(bool lowMass, bool highMass){ + if(lowMass) return ("_LowBmass"); + if(highMass) return ("_HighBmass"); + else return ""; +} +std::string tag_sample_blind(basic_params params){ + return tag_OnlyOneRun(params.Run)+ + tag_OnlyOnePolarity(params.polarity); +} +std::string tag_sample_blind(int Run, int polarity){ + return tag_OnlyOneRun(Run)+ + tag_OnlyOnePolarity(polarity); +}; +std::string tag_datasample(bool fitReference, bool fitMC, bool fitPHSP){ + std::ostringstream label; + if(fitMC) label << "_MC"; + if(fitPHSP) label << "_PHSP"; + if(fitReference) label << "_JpsiFit"; + else label << "_SignalFit"; + return label.str(); +} + +std::string tag_folding(int folding){ + if(folding!=-1) return "_folding" + std::to_string(folding); + else return ""; +} +std::string tag_observables(bool usePprime){ + if(usePprime) return "_Pprimes"; + else return ""; +} +std::string tag_simFit(bool SimultaneousFit){ + if(SimultaneousFit) return "_SimultaneousFit"; + else return "_IndividualFit"; +} +std::string tag_splitFit(bool splitRuns){ + if(splitRuns) return ""; + else return "_BothRuns"; +} +std::string tag_partialFit(bool onlyAng, bool onlyMass){ + if (onlyAng) return "_OnlyAngles"; + else if (onlyMass) return "_OnlyMass"; + else return ""; +} +std::string tag_onlyBkgSig(bool onlySig, bool onlyBkg){ + if (onlySig) return "_OnlySignal"; + else if (onlyBkg) return "_OnlyBackground"; + else return ""; +} +std::string tag_jobID(int jobID){ + if (jobID == -1) return ""; + else return "_" + std::to_string(jobID) + "_"; //Add _ for easy identification of the id in case of some script needed +} + +std::string tag_systematics(int systematics, int moreOrders = 0){ + switch (systematics){ + case -1: return ""; + case 1: return "_bs"; + case 2: return "_sym_ctl"; + case 3: return "_"+std::to_string(moreOrders)+"moreOrders"; + case 4: return "_dw"; + case 5: return "_rndFS"; + case 6: return "_angreso"; + case 7: return "_mm"; + case 8: return "_angbkg"; + case 9: return "_trggr"; + case 10: return "_kspt"; + case 11: return "_bkg_veto"; + } + return "_WrongSystematics"; //If nada, return an emergency name (and not empty string, because that means no systematics +} + +std::string tag_statFraction(double frac){ + if (frac==1.0) return ""; + else return "_statFrac" + std::to_string(frac); + //TODO: add Jpsi with rare stats +} + +//---------------------------------------------------------------------------- +// Paths for main fit +//---------------------------------------------------------------------------- +std::string get_MainFitResult_path(){ + return FIT_RESULTS_PATH+"MainFit/"; +} + +std::string final_result_name(bool fitReference, bool fitSignalMC, basic_params params, + bool simFit, int nBinsToFit, int effRun, + bool FitFinalToySamples, double statFrac, + bool NP, int systematics){ + return get_MainFitResult_path() + "fitresult" + + tag_datasample(fitReference, fitSignalMC, false) + + tag_bin(nBinsToFit,-1) + + tag_simFit(simFit) + + tag_folding(params.folding) + + tag_observables(params.usePprime) + + tag_Run(params.Run, effRun) + + tag_OnlyOnePolarity(params.polarity) + + tag_systematics(systematics) + + tag_statFraction(statFrac) + + std::string(FitFinalToySamples ? "_FinalToys" : "") + + tag_jobID(params.jobID) + + std::string(NP ? "_NP" : "") + + ".root"; + +} + + +std::string get_eps_label(bool fitReference, bool fitSignalMC, bool fitPHSP, + bool FitFinalToySamples, + int nBinsToFit, int bin, + int polarity, + bool SimultaneousFit, fcnc::options opts){ + return tag_datasample( fitReference, fitSignalMC, fitPHSP).erase(0,1) + + std::string(FitFinalToySamples ? "_FinalToys" : "") + + tag_bin(nBinsToFit,bin) + + tag_simFit(SimultaneousFit) + + tag_folding(opts.folding) + + tag_observables(opts.fit_pprimes) + + tag_sample_blind(opts.run, polarity); + +} + +std::string get_eps_label(bool fitReference, bool fitSignalMC, bool fitPHSP, + bool FitFinalToySamples, + int nBinsToFit, int bin, + bool SimultaneousFit, basic_params params){ + return tag_datasample( fitReference, fitSignalMC, fitPHSP).erase(0,1) + + std::string(FitFinalToySamples ? "_FinalToys" : "") + + tag_bin(nBinsToFit,bin) + + tag_simFit(SimultaneousFit) + + tag_folding(params.folding) + + tag_observables(params.usePprime) + + tag_sample_blind(params); +} + + +//---------------------------------------------------------------------------- +// Paths for MC fit +//---------------------------------------------------------------------------- +std::string get_MCfit_label(bool fitReference, bool fitPHSP, + int nBinsToFit, int bin, + bool simFit, + basic_params params, int effRun, + bool onlyAng, bool onlyMass){ + //eff Run is there in case of plotting the results separately for each run when doing a simultaneous fit in ti + + return tag_datasample(fitReference,true,fitPHSP).erase(0,1) + + tag_bin(nBinsToFit,bin) + + tag_simFit(simFit) + + tag_folding(onlyMass ? -1 : params.folding) + + tag_observables(params.usePprime) + + tag_Run(params.Run, effRun) + + tag_OnlyOnePolarity(params.polarity) + + tag_partialFit(onlyAng,onlyMass); +} + +std::string finalResult_MCfit_txt(int nPDF, bool fitReference, bool fitPHSP, + int nBinsToFit, int bin, + bool simFit, + basic_params params, int effRun, + bool onlyAng, bool onlyMass){ + return FIT_RESULTS_PATH + + "MCfit/fitresult_" + + get_MCfit_label(fitReference, fitPHSP, + nBinsToFit, bin, + simFit, params, effRun, + onlyAng, onlyMass) + + "_pdf" + std::to_string(nPDF) + ".txt"; +} + + +std::string final_result_name_MC(basic_params params, int nBins, bool fitReference, bool fitPHSP, bool simFit, bool onlyAng, bool onlyMass){ + return FIT_RESULTS_PATH + +"MCfit/finalresult_" + + get_MCfit_label(fitReference, fitPHSP, + nBins, -1, + simFit, params, params.Run, + onlyAng,onlyMass) + + ".root"; +} +//---------------------------------------------------------------------------- +// Paths for GenLvl MC fit +//---------------------------------------------------------------------------- +std::string get_genLvlFit_label(bool fitPHSP, int nBinsToFit, int bin, basic_params params, + bool onlyAng, bool onlyMass){ + return "genLvl" + tag_datasample(false,true,fitPHSP) + + tag_bin(nBinsToFit,bin) + + tag_folding(params.folding) + + tag_observables(params.usePprime) + + tag_partialFit(onlyAng,onlyMass); +} + +std::string finalResult_genLvlMCfit_txt(bool fitPHSP, + int nBinsToFit, int bin, + basic_params params, + bool onlyAng, bool onlyMass){ + return FIT_RESULTS_PATH + + "GenLvlFit/fitresult_" + + get_genLvlFit_label(fitPHSP,nBinsToFit, bin, params, onlyAng, onlyMass) + + "_pdf.txt"; +} + +std::string final_result_name_genLvlMC(basic_params params, int nBins, bool fitPHSP, + bool onlyAng, bool onlyMass){ + return FIT_RESULTS_PATH + +"GenLvlFit/finalresult_" + + get_genLvlFit_label(fitPHSP, nBins, -1, params, onlyAng,onlyMass) + + ".root"; +} + + +//---------------------------------------------------------------------------- +// Paths for bkg fit +//---------------------------------------------------------------------------- +std::string get_bkgFitPlot_path(){ + return PLOTS_PATH+"bkgFit/"; +} + +std::string get_bkgFitResult_path(){ + return FIT_RESULTS_PATH+"bkgFit/"; +} + +std::string get_bkg_tag(int bin, int nBins, bool fitReference, bool lowMass, bool highMass, bool fitKpi, basic_params params){ + return "Bckgnd" + + tag_datasample(fitReference,false, false) + + tag_bin(nBins,bin) + + tag_Run(params.Run) + + tag_OnlyOnePolarity(params.polarity) + + tag_massSideband(lowMass,highMass) + + tag_folding(params.folding) + + std::string(fitKpi ? "_Kpi" : ""); +} + +std::string get_bkgCorrPlot_path(std::string ang1, std::string ang2, int bin, int nBins, bool fitReference, bool lowMass, bool highMass, bool fitKpi, basic_params params){ + return get_bkgFitPlot_path() + +"Background_Correlation_"+ang1+"_"+ang2+"_" + +get_bkg_tag(bin, nBins,fitReference, lowMass, highMass, fitKpi, params) + +".eps"; +} + +std::string final_result_name_bkg(int nBins, bool fitReference, bool lowMass, bool highMass, bool fitKpi, basic_params params){ + + return get_bkgFitResult_path() + "finalresult_" + +get_bkg_tag(-1, nBins,fitReference, lowMass, highMass, fitKpi, params) + + ".root"; + +} + +//---------------------------------------------------------------------------- +// Paths for mass fit +//---------------------------------------------------------------------------- +std::string get_MassFitPlot_path(){ + return PLOTS_PATH+"MassFit/"; +} +std::string get_MassFitResult_path(){ + return FIT_RESULTS_PATH+"MassFit/"; +} + +std::string get_MassFit_label(bool fitReference, int bin, int nBins, bool splitRuns, basic_params params, int effRun){ + //eff Run is there in case of plotting the results separately for each run when doing a simultaneous fit in ti + return "massfit" + tag_datasample(fitReference,false, false) + + tag_bin(nBins,bin) + + tag_splitFit(splitRuns) + + tag_observables(params.usePprime) + + tag_Run(params.Run, effRun) + + tag_OnlyOnePolarity(params.polarity); +} + +std::string final_result_name_mass(bool fitReference, int nBins, bool splitRuns, basic_params params, int effRun){ + + return get_MassFitResult_path() + "finalresult_" + +get_MassFit_label(fitReference, -1, nBins, splitRuns, params, effRun) + + ".root"; +} + +//---------------------------------------------------------------------------- +// Paths for toys fit +//---------------------------------------------------------------------------- + +std::string get_ToysFitPlot_path(basic_params params){ + if(params.index > -1){ + std::string name = PLOTS_PATH + "Toys/" + std::to_string(params.index) + "/"; + if(!existsTest(name))makeFolder(name); + return name; + } + return PLOTS_PATH+"Toys/"; +} + +std::string get_ToysFitResult_path(basic_params params){ + //create a subfolder in fitResults/Toys/ whenever the index option is set: + if(params.index > -1){ + std::string name = FIT_RESULTS_PATH + "ToysFit/" + std::to_string(params.index) + "/"; + if(!existsTest(name))makeFolder(name); + return name; + } + return FIT_RESULTS_PATH+"ToysFit/"; +} + + +std::string get_ToysFit_label(int jobID, bool fitReference, int bin, int nBins, bool simFit, basic_params params, int effRun, bool onlyAng, bool onlyMass, bool onlySig, bool onlyBkg, bool lowMass, bool highMass){ + + //eff Run is there in case of plotting the results separately for each run when doing a simultaneous fit + return "toyfit_" + + tag_jobID(jobID) + + tag_datasample(fitReference,false, false) + + tag_onlyBkgSig(onlySig,onlyBkg) + + tag_partialFit(onlyAng,onlyMass) + + tag_bin(nBins,bin) + + tag_Run(params.Run, effRun) + + tag_simFit(simFit) + + tag_folding(params.folding) + + tag_observables(params.usePprime) + + tag_massSideband(lowMass,highMass) + + tag_OnlyOnePolarity(params.polarity); +} + +std::string final_result_name_toys(int jobID, bool fitReference, int nBins, bool simFit, basic_params params, int effRun, bool onlyAng, bool onlyMass, bool onlySig, bool onlyBkg, bool lowMass, bool highMass){ + + return get_ToysFitResult_path(params) + "finalresult_" + +get_ToysFit_label(jobID, fitReference, -1, nBins, simFit, params, effRun, onlyAng, onlyMass, onlySig, onlyBkg, lowMass, highMass) + + ".root"; +} + +std::string init_params_name_toys(int jobID, bool fitReference, int nBins, bool simFit, basic_params params, int effRun, bool onlyAng, bool onlyMass, bool onlySig, bool onlyBkg, bool lowMass, bool highMass){ + + return get_ToysFitResult_path(params) + "initParams_" + +get_ToysFit_label(jobID, fitReference, -1, nBins, simFit, params, effRun, onlyAng, onlyMass, onlySig, onlyBkg, lowMass, highMass) + + ".root"; +} + + +std::string get_finalToys_file(bool fitReference, int nBins, bool simFit, basic_params params, int effRun){ + return TOYS_PATH + "Toy_" + +get_ToysFit_label(-1, fitReference, -1, nBins, simFit, params, effRun, false, false, false, false, false, false) + + ".root"; +} + +std::string get_ToyPullPlot_folder( basic_params params){ + return get_ToysFitPlot_path(params) + +"/"+std::to_string(params.jobID)+"/"; +} + +std::string get_ToyPullPlot_tag(int bin, std::string varName, basic_params params, bool dist, bool pull){ + return get_ToyPullPlot_folder(params) + + varName + + "_bin"+std::to_string(bin) //FUCKING KILL ME + + (dist ? "_dist" : (pull ? "_Pulls" : "_Res")); +} + + +//=====================================// +// Paths for Latex couts // +//=====================================// +//THIS IS TODO, BIG TIME + +std::string get_Latex_noteFile(std::string tag){ + return LATEX_PATH + "latex_couts"+tag+".tex"; +} + +std::string latex_fitterFile(std::string index){ + return "_fit_" + index; +} +std::string latex_toyFile(){ + return "_toy"; +} +std::string latex_params(){ + return "_params"; +} +std::string latex_paramScan(){ + return "_paramsScan"; +} +std::string latex_bkgFit(){ + return "_bkgFit"; +} +std::string latex_massFit(){ + return "_massFit"; +} + diff --git a/Code/FCNCFitter/sources/paths.hh b/Code/FCNCFitter/sources/paths.hh new file mode 100644 index 0000000..e7f3ce0 --- /dev/null +++ b/Code/FCNCFitter/sources/paths.hh @@ -0,0 +1,204 @@ +//Renata Kopecna + +#ifndef PATHS_HH +#define PATHS_HH +#include +#include + +#include +#include + + +//=====================================// +// Main folder paths // +//=====================================// + +std::string datapath(); //Returns the path where the data is stored based on the server/user +std::string workpath(); //Returns the path where the program is executed based on the server/user + +const std::string DATA_PATH = datapath(); +const std::string FIT_RESULTS_PATH = workpath()+"fitResults/"; +const std::string PLOTS_PATH = workpath()+"plots/"; +const std::string TOYS_PATH = workpath()+"Toys/"; +const std::string COEFFS_PATH = workpath()+"Coeffs/"; +const std::string LATEX_PATH = workpath()+"LaTeXfiles/"; + +//=====================================// +// Paths for datsets // +//=====================================// + +std::string getSelectedTuplePath(int dataset, int run, int year); +std::string get_theFCNCpath(int dataset, int run); +std::string get_finalToySamplePath(int nPDF, int job_id, bool fitReference); + +//=====================================// +// Paths for angular parametrization // +//=====================================// + +namespace fcnc { //Forward declaration, fully defined in options.hh + class options; +} +std::string get_angCorrPath(bool test); +std::string coeffs_eff_phsp_4D(fcnc::options *opts); + + +//=====================================// +// Paths for angular resolution // +//=====================================// +std::string get_angResoPlot_path(std::string angle, int year, std::string format); + +//=====================================// +// Paths for fit results // +//=====================================// + +std::string get_MainFitPlot_path(); +std::string get_MCfitPlot_path(bool Ref, bool PHSP); +std::string get_genLvlFitPlot_path(bool PHSP); +std::string get_MoMPlot_path(); +std::string get_GenLvlPlot_path(); +std::string get_PullPlot_path(); +std::string get_ToysFitResult_path(basic_params params); +std::string get_MainFitResult_path(); + +std::string get_JpsiSimFit2D_path(int idx, bool pPrimes); +std::string get_SigMCSimFit2D_path(int idx, int bin); +std::string get_param_scan_path(std::string name, bool error); +//=====================================// +// Fit result tags // +//=====================================// +std::string tag_bin(int nBinsToFit); +std::string tag_bin(int nBinsToFit, int bin); +std::string tag_Run(int Run); +std::string tag_datasample(bool fitReference, bool fitMC, bool fitPHSP); +std::string tag_sample_blind(basic_params params); +std::string tag_sample_blind(bool FitOnlyRun1, bool FitOnlyRun2, + bool FitOnlyMagDown, bool FitOnlyMagUp); + + +std::string final_result_name(bool fitReference, bool fitSignalMC, basic_params params, + bool simFit, int nBinsToFit, int effRun, + bool FitFinalToySamples, double statFrac, + bool NP, int systematics); + +std::string get_eps_label(bool fitReference, bool fitSignalMC, bool fitPHSP, + bool FitFinalToySamples, + int nBinsToFit, int bin, + int polarity, + bool SimultaneousFit, fcnc::options opts); + +std::string get_eps_label(bool fitReference, bool fitSignalMC, bool fitPHSP, + bool FitFinalToySamples, + int nBinsToFit, int bin, + bool SimultaneousFit, basic_params params); + +// if bin == -1, no specific bin number is printed +//-------------------------------------------------------------- +std::string get_MCfit_label(bool fitReference, bool fitPHSP, + int nBinsToFit, int bin, + bool simFit, + basic_params params, int effRun, + bool onlyAng, bool onlyMass); + +std::string finalResult_MCfit_txt(int nPDF, bool fitReference, bool fitPHSP, + int nBinsToFit, int bin, + bool simFit, + basic_params params, int effRun, + bool onlyAng, bool onlyMass); +std::string final_result_name_MC(basic_params params, int nBins, + bool fitReference, bool fitPHSP, bool simFit, + bool onlyAng, bool onlyMass); + +//-------------------------------------------------------------- +std::string get_genLvlFit_label(bool fitPHSP, + int nBinsToFit, int bin, + basic_params params, + bool onlyAng, bool onlyMass); +std::string finalResult_genLvlMCfit_txt(bool fitPHSP, + int nBinsToFit, int bin, + basic_params params, + bool onlyAng, bool onlyMass); +std::string final_result_name_genLvlMC(basic_params params, int nBins, bool fitPHSP, + bool onlyAng, bool onlyMass); +//-------------------------------------------------------------- +std::string get_bkgFitPlot_path(); +std::string get_bkgFitResult_path(); + +std::string get_bkg_tag(int bin, int nBins, + bool fitReference, + bool lowMass, bool highMass, + bool fitKpi, basic_params params); +std::string get_bkgCorrPlot_path(std::string ang1, std::string ang2, + int bin, int nBins, + bool fitReference, + bool lowMass, bool highMass, + bool fitKpi, basic_params params); + +std::string final_result_name_bkg(int nBins, + bool fitReference, + bool lowMass, bool highMass, + bool fitKpi, basic_params params); + + +//-------------------------------------------------------------- +std::string get_MassFitPlot_path(); +std::string get_MassFitResult_path(); +std::string get_MassFit_label(bool fitReference, + int bin, int nBins, + bool splitRuns, basic_params params, + int effRun); +std::string final_result_name_mass(bool fitReference, int nBins, + bool splitRuns, + basic_params params, int effRun); +//-------------------------------------------------------------- + +std::string get_ToysFitPlot_path(basic_params params); +std::string get_ToysFit_label(int jobID, bool fitReference, + int bin, int nBins, + bool simFit, basic_params params, int effRun, + bool onlyAng, bool onlyMass, + bool onlySig, bool onlyBkg, + bool lowMass, bool highMass); + +std::string final_result_name_toys(int jobID, bool fitReference, + int nBins, bool simFit, + basic_params params, int effRun, + bool onlyAng, bool onlyMass, + bool onlySig, bool onlyBkg, + bool lowMass, bool highMass); + +std::string init_params_name_toys(int jobID, bool fitReference, + int nBins, bool simFit, + basic_params params, int effRun, + bool onlyAng, bool onlyMass, + bool onlySig, bool onlyBkg, + bool lowMass, bool highMass); + +std::string get_finalToys_file(bool fitReference, int nBins, + bool simFit, + basic_params params, int effRun); + + +std::string get_ToyPullPlot_folder( basic_params params); +std::string get_ToyPullPlot_tag(int bin, std::string varName, basic_params params, bool dist, bool pull); +//-------------------------------------------------------------- + + +//=====================================// +// Paths for Latex couts // +//=====================================// + +//File used for capturing latex output such as parameter tables +//The file is handled by function in helpers.cc +//Technically should be a class but I'm feeling lazy +std::string get_Latex_noteFile(std::string tag); + +std::string latex_fitterFile(std::string index); +std::string latex_toyFile(); +std::string latex_params(); +std::string latex_paramScan(); +std::string latex_bkgFit(); +std::string latex_massFit(); + + + +#endif // PATHS_HH diff --git a/Code/FCNCFitter/sources/tests.cc b/Code/FCNCFitter/sources/tests.cc new file mode 100644 index 0000000..a1fbe6a --- /dev/null +++ b/Code/FCNCFitter/sources/tests.cc @@ -0,0 +1,781 @@ +//Renata Kopecna + + +#include "tests.hh" + +#include +#include + +//TODO: go through what is needed +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fcnc { + +void test_integrals(){ + spdlog::debug("Starting Test"); + //sin test + unsigned int nbins=100; + for (unsigned int i = 0; i < nbins; i++) + { + double x = -1.0 + 2.0*i/double(nbins); + double a = integral_x_to_n_times_sin_x_2(x, 0); + double b = 0.5*(x-0.5*sin(2.0*x)); + if (fabs(a-b) > 1.0e-8) + { + std::cout << a; + std::cout << " != "; + std::cout << b; + std::cout << std::endl; + } + } + for (unsigned int i = 0; i < nbins; i++) + { + double x = -1.0 + 2.0*i/double(nbins); + double a = integral_x_to_n_times_sin_x_2(x, 1); + double b = -(2*x*sin(2*x)+cos(2*x)-2*x*x)/8; + if (fabs(a-b) > 1.0e-8) + { + std::cout << a; + std::cout << " != "; + std::cout << b; + std::cout << std::endl; + } + } + for (unsigned int i = 0; i < nbins; i++) + { + double x = -1.0 + 2.0*i/double(nbins); + double a = integral_x_to_n_times_sin_x_2(x, 2); + double b = -((6*x*x-3)*sin(2*x)+6*x*cos(2*x)-4*x*x*x)/24; + if (fabs(a-b) > 1.0e-8) + { + std::cout << a; + std::cout << " != "; + std::cout << b; + std::cout << std::endl; + } + } + for (unsigned int i = 0; i < nbins; i++) + { + double x = -1.0 + 2.0*i/double(nbins); + double a = integral_x_to_n_times_sin_x_2(x, 3); + double b = -((4*x*x*x-6*x)*sin(2*x)+(6*x*x-3)*cos(2*x)-2*x*x*x*x)/16; + if (fabs(a-b) > 1.0e-8) + { + std::cout << a; + std::cout << " != "; + std::cout << b; + std::cout << std::endl; + } + } + for (unsigned int i = 0; i < nbins; i++) + { + double x = -1.0 + 2.0*i/double(nbins); + double a = integral_x_to_n_times_sin_x_2(x, 1); + double b = -(2*x*sin(2*x)+cos(2*x)-2*x*x)/8; + if (fabs(a-b) > 1.0e-8) + { + std::cout << a; + std::cout << " != "; + std::cout << b; + std::cout << std::endl; + } + } + //cos test + for (unsigned int i = 0; i < nbins; i++) + { + double x = -1.0 + 2.0*i/double(nbins); + double a = integral_x_to_n_times_cos_x_2(x, 0); + double b = (sin(2.0*x)*0.5+x)*0.5; + if (fabs(a-b) > 1.0e-8) + { + std::cout << a; + std::cout << " != "; + std::cout << b; + std::cout << std::endl; + } + } + std::vector res; + chebyshev(0.43, 13, res); + for (unsigned int i = 0; i < 14; i++) + { + if (fabs(res.at(i) - chebyshev(0.43,i)) > 1.0e-8){ + spdlog::debug("CHEBYSHEV: {0:f} != {1:f}", res.at(i), chebyshev(0.43,i)); + } + } + legendre(0.43, 13, res); + for (unsigned int i = 0; i < 14; i++) + { + if (fabs(res.at(i) - ROOT::Math::legendre(i, 0.43)) > 1.0e-8){ + spdlog::debug("LEGENDREPOLY {0:d}: {1:f} != {2:f}", i, res.at(i), ROOT::Math::legendre(i, 0.43)); + } + } + + spdlog::debug("Finished Test"); +} + +void test_legendre() +{ + spdlog::debug("Starting Test"); + TRandom3 rnd; + TCanvas *canvas = new TCanvas("canvas", "canvas",1600,1200); + canvas->cd(); + unsigned int nbins = 200; + TH1D * data = new TH1D("data", "data", nbins, -1.0, 1.0); + for (unsigned int i =0; i<200000; i++){ + data->Fill(rnd.Gaus(0.0,0.5)); + bool finished = false; + double x; + while (!finished){ + x = rnd.Rndm(); + if (rnd.Rndm() < x){ + x = x*2.0-1.0; + finished = true; + } + } + data->Fill(x); + } + //data->FillRandom("gaus", 200000); + data->Draw("e"); + + unsigned int n = 20; + + std::vector l; + double dv = 2.0/nbins; + std::vector coeffs(n+1, 0.0); + for (unsigned int j=0; jGetBinContent(j+1); + for (unsigned int i = 0; iSetBinContent(j+1, y); + } + interpol->SetLineColor(2); + interpol->Draw("same l"); + + TH1D * pol1d = new TH1D("pol1d", "pol1d", nbins, -1.0, 1.0); + std::vector poly_coeffs; + for (unsigned int i=0; iSetBinContent(j+1, y); + } + pol1d->SetLineColor(3); + pol1d->SetLineStyle(2); + pol1d->Draw("same l"); + + canvas->Update(); + canvas->Print("legendre.eps", "eps"); + delete data; + delete interpol; + delete pol1d; + delete canvas; +} + +void test_legendre_2pi() +{ + TRandom3 rnd; + TCanvas *canvas = new TCanvas("canvas", "canvas",1600,1200) ; + canvas->cd(); + unsigned int nbins = 200; + TH1D * data = new TH1D("data", "data", nbins, -TMath::Pi(), TMath::Pi()); + for (unsigned int i =0; i<200000; i++) + { + data->Fill(rnd.Gaus(0.0,0.5)); + bool finished = false; + double x; + while (!finished) + { + x = rnd.Rndm(); + if (rnd.Rndm() < x) + { + x = x*2.0*TMath::Pi()-TMath::Pi(); + finished = true; + } + } + data->Fill(x); + } + //data->FillRandom("gaus", 200000); + data->Draw("e"); + + unsigned int n = 20; + + std::vector l; + double dv = 2.0/nbins; + std::vector coeffs(n+1, 0.0); + for (unsigned int j=0; jGetBinContent(j+1); + for (unsigned int i = 0; iSetBinContent(j+1, y); + } + interpol->SetLineColor(2); + interpol->Draw("same l"); + + TH1D * pol1d = new TH1D("pol1d", "pol1d", nbins, -TMath::Pi(), +TMath::Pi()); + std::vector poly_coeffs; + for (unsigned int i=0; iSetBinContent(j+1, y); + } + pol1d->SetLineColor(3); + pol1d->SetLineStyle(2); + pol1d->Draw("same l"); + + canvas->Update(); + canvas->Print("legendre2pi.eps", "eps"); + delete data; + delete interpol; + delete pol1d; + delete canvas; +} + +void test_chebyshev() +{ + TRandom3 rnd; + TCanvas *canvas = new TCanvas("canvas", "canvas",1600,1200) ; + canvas->cd(); + unsigned int nbins = 200; + TH1D * data = new TH1D("data", "data", nbins, -1.0, 1.0); + for (unsigned int i =0; i<200000; i++) + { + data->Fill(rnd.Gaus(0.0,0.5)); + bool finished = false; + double x; + while (!finished) + { + x = rnd.Rndm(); + if (rnd.Rndm() < x) + { + x = x*2.0-1.0; + finished = true; + } + } + data->Fill(x); + } + //data->FillRandom("gaus", 200000); + data->Draw("e"); + + unsigned int n = 20; + + std::vector l; + double dv = 2.0/nbins; + std::vector coeffs(n+1, 0.0); + for (unsigned int j=0; jGetBinContent(j+1); + for (unsigned int i = 0; iSetBinContent(j+1, y); + } + interpol->SetLineColor(2); + interpol->Draw("same l"); + + canvas->Update(); + canvas->Print("chebyshev.eps", "eps"); + delete data; + delete interpol; + //delete pol1d; + delete canvas; +} + +void test_legendre_2d() +{ + gStyle->SetPalette(1); + TRandom3 rnd; + TCanvas *canvas = new TCanvas("canvas", "canvas",1600,1200) ; + canvas->cd(); + unsigned int nbins = 200; + TH2D * data = new TH2D("data", "data", nbins, -1.0, 1.0, nbins, -1.0, 1.0); + for (unsigned int i =0; i<1000000; i++) + { + //double r = rnd.Gaus(0.7,0.2); + //double phi = rnd.Rndm() * 2.0 * TMath::Pi(); + //data->Fill(fabs(r)*cos(phi),fabs(r)*sin(phi)); + data->Fill(rnd.Gaus(-0.1,0.3), rnd.Gaus(-0.1,0.3)); + data->Fill(rnd.Gaus(0.5,0.3), rnd.Gaus(0.5,0.3)); + } + //data->FillRandom("gaus", 200000); + data->Draw("colz"); + canvas->Update(); + canvas->Print("2d.eps", "eps"); + unsigned int n = 10; + std::vector legendre_x, legendre_y; + double dv = 2.0/nbins*2.0/nbins; + std::vector< std::vector > coeffs(n+1, std::vector(n+1, 0.0)); + for (unsigned int i=0; iGetBinContent(i+1,j+1); + //orthonormal_legendre(x, n, legendre_x); + //orthonormal_legendre(y, n, legendre_y); + legendre(x, n, legendre_x); + legendre(y, n, legendre_y); + for (unsigned int l = 0; lSetBinContent(i+1, j+1, z); + } + } + //calculate chi^2 + double chi2 = 0.0; + for (unsigned int i=0; iGetBinContent(i+1, j+1); + double dd = data->GetBinError(i+1, j+1); + double f = interpol->GetBinContent(i+1, j+1); + if (dd != 0.0) + chi2 += (d-f)*(d-f)/dd/dd; + } + } + spdlog::debug("Found a chi^2 of {0:f with {1:d} bins.", chi2, nbins*nbins); + //cleanup + interpol->Draw("colz"); + canvas->Update(); + canvas->Print("2dinter.eps", "eps"); + delete data; + delete interpol; + delete canvas; +} + +/** This function tests the different versions of the complex error function. + * Unfortunately the complex error function is not yet in the standard c library. + **/ +void test_errf() +{ + gStyle->SetPalette(1); + unsigned int divisions=1000; + double min=-10.0; + double max=+10.0; + TH2D* real_1 = new TH2D("real_1", "real part", divisions, min, max, divisions, min, max); + real_1->SetMinimum(-20.0); + real_1->SetMaximum(+20.0); + TH2D* imaginary_1 = new TH2D("imaginary_1", "imaginary part", divisions, min, max, divisions, min, max); + imaginary_1->SetMinimum(-20.0); + imaginary_1->SetMaximum(+20.0); + TH2D* real_2 = new TH2D("real_2", "real part", divisions, min, max, divisions, min, max); + TH2D* imaginary_2 = new TH2D("imaginary_2", "imaginary part", divisions, min, max, divisions, min, max); + TH2D* real_3 = new TH2D("real_3", "real part", divisions, min, max, divisions, min, max); + TH2D* imaginary_3 = new TH2D("imaginary_3", "imaginary part", divisions, min, max, divisions, min, max); + double r, i; + std::complex result, arg; + for (unsigned int re = 0; re < divisions; re++) + for (unsigned int im = 0; im < divisions; im++) + { + r = min + (max - min)/divisions*re; + i = min + (max - min)/divisions*im; + arg = std::complex(r, i); + result = 1.0-cErrF(arg); + //if (!std::isnan(result.real())) + real_1->SetBinContent(re, im, result.real()); + imaginary_1->SetBinContent(re, im, result.imag()); + result = 1.0-cErrF_2(arg); + //if (!std::isnan(result.real())) + real_2->SetBinContent(re, im, result.real()); + imaginary_2->SetBinContent(re, im, result.imag()); + result = 1.0-cErrF_3(arg); + //if (!std::isnan(result.real())) + real_3->SetBinContent(re, im, result.real()); + imaginary_3->SetBinContent(re, im, result.imag()); + } + + TCanvas *canvas_1 = new TCanvas("canvas_1", "canvas 1",1600,1200) ; + canvas_1->Divide(2,1); + canvas_1->cd(1); + real_1->Draw("COLZ"); + canvas_1->cd(2); + imaginary_1->Draw("COLZ"); + canvas_1->Update(); + canvas_1->Print("error_1.eps", "eps"); + + TCanvas *canvas_2 = new TCanvas("canvas_2", "canvas 2",1600,1200) ; + canvas_2->Divide(2,1); + canvas_2->cd(1); + real_2->Draw("COLZ"); + canvas_2->cd(2); + imaginary_2->Draw("COLZ"); + canvas_2->Update(); + canvas_2->Print("error_2.eps", "eps"); + + TCanvas *canvas_3 = new TCanvas("canvas_3", "canvas 3",1600,1200) ; + canvas_3->Divide(2,1); + canvas_3->cd(1); + real_3->Draw("COLZ"); + canvas_3->cd(2); + imaginary_3->Draw("COLZ"); + canvas_3->Update(); + canvas_3->Print("error_3.eps", "eps"); + + TH2D* real_12 = new TH2D((*real_1) / (*real_2)); + TH2D* imaginary_12 = new TH2D((*imaginary_1) / (*imaginary_2)); + TCanvas *canvas_12 = new TCanvas("canvas_12", "canvas 1 - 2",1600,1200) ; + canvas_12->Divide(2,1); + canvas_12->cd(1); + real_12->Draw("COLZ"); + canvas_12->cd(2); + imaginary_12->Draw("COLZ"); + canvas_12->Update(); + canvas_12->Print("error_1_over_2.eps", "eps"); + + TH2D* real_23 = new TH2D((*real_2) / (*real_3)); + TH2D* imaginary_23 = new TH2D((*imaginary_2) / (*imaginary_3)); + TCanvas *canvas_23 = new TCanvas("canvas_23", "canvas 1 - 2",1600,1200) ; + canvas_23->Divide(2,1); + canvas_23->cd(1); + real_23->Draw("COLZ"); + canvas_23->cd(2); + imaginary_23->Draw("COLZ"); + canvas_23->Update(); + canvas_23->Print("error_2_over_3.eps", "eps"); + + TH2D* real_13 = new TH2D((*real_1) / (*real_3)); + TH2D* imaginary_13 = new TH2D((*imaginary_1) / (*imaginary_3)); + TCanvas *canvas_13 = new TCanvas("canvas_13", "canvas 1 - 2",1600,1200) ; + canvas_13->Divide(2,1); + canvas_13->cd(1); + real_13->Draw("COLZ"); + canvas_13->cd(2); + imaginary_13->Draw("COLZ"); + canvas_13->Update(); + canvas_13->Print("error_1_over_3.eps", "eps"); + +} + + +void test_convolutions() +{ + gStyle->SetPalette(1); + gStyle->SetOptFit(0); + gStyle->SetOptStat(0); + + unsigned int divisions=1000; + double min=-TMath::Pi(); + double max=+2.0*TMath::Pi(); + TH1D* conv_sin = new TH1D("conv_sin", "", divisions, min, max); + TH1D* conv_cos = new TH1D("conv_cos", "", divisions, min, max); + TH1D* conv_sin_2 = new TH1D("conv_sin_2", "", divisions, min, max); + TH1D* conv_cos_2 = new TH1D("conv_cos_2", "", divisions, min, max); + TH1D* conv_2_sin = new TH1D("conv_2_sin", "", divisions, min, max); + TH1D* conv_2_cos = new TH1D("conv_2_cos", "", divisions, min, max); + + TH1D* conv_cos_2_sin = new TH1D("conv_cos_2_sin", "", divisions, min, max); + TH1D* conv_sin_3 = new TH1D("conv_sin_3", "", divisions, min, max); + TH1D* conv_2_sin_sin = new TH1D("conv_2_sin_sin", "", divisions, min, max); + + double sigma = 0.03; + for (unsigned int i = 0; i < divisions; i++) + { + double angle = min+(max - min)/double(divisions)*i; + conv_sin->SetBinContent(i+1, convoluted_sin(angle, sigma)); + conv_cos->SetBinContent(i+1, convoluted_cos(angle, sigma)); + conv_sin_2->SetBinContent(i+1, convoluted_sin_2(angle, sigma)); + conv_cos_2->SetBinContent(i+1, convoluted_cos_2(angle, sigma)); + conv_2_sin->SetBinContent(i+1, convoluted_2_sin(angle, sigma)); + conv_2_cos->SetBinContent(i+1, convoluted_2_cos(angle, sigma)); + + conv_cos_2_sin->SetBinContent(i+1, convoluted_cos_2_sin(angle, sigma)); + conv_sin_3->SetBinContent(i+1, convoluted_sin_3(angle, sigma)); + //std::cout << convoluted_sin_3(angle, sigma) << std::endl; + conv_2_sin_sin->SetBinContent(i+1, convoluted_2_sin_sin(angle, sigma)); + + } + + conv_sin->SetLineColor(2); + conv_cos->SetLineColor(3); + conv_sin_2->SetLineColor(4); + conv_cos_2->SetLineColor(5); + conv_2_sin->SetLineColor(6); + conv_2_cos->SetLineColor(7); + conv_cos_2_sin->SetLineColor(8); + conv_sin_3->SetLineColor(9); + conv_2_sin_sin->SetLineColor(15); + + TCanvas *canvas = new TCanvas("canvas", "canvas",1600,1200) ; + canvas->cd(); + conv_sin->SetMinimum(-1.0); + conv_sin->SetMaximum(1.0); + conv_sin->Draw(); + conv_cos->Draw("same"); + conv_sin_2->Draw("same"); + conv_cos_2->Draw("same"); + conv_2_sin->Draw("same"); + conv_2_cos->Draw("same"); + conv_cos_2_sin->Draw("same"); + conv_sin_3->Draw("same"); + conv_2_sin_sin->Draw("same"); + TLegend* conv_legend = new TLegend(0.7,0.6,0.9,0.9); + conv_legend->AddEntry(conv_sin, "sin #Theta", "L"); + conv_legend->AddEntry(conv_cos, "cos #Theta", "L"); + conv_legend->AddEntry(conv_sin_2, "sin #Theta^{2}", "L"); + conv_legend->AddEntry(conv_cos_2, "cos #Theta^{2}", "L"); + conv_legend->AddEntry(conv_2_sin, "sin 2#Theta", "L"); + conv_legend->AddEntry(conv_2_cos, "cos 2#Theta", "L"); + conv_legend->AddEntry(conv_cos_2_sin, "cos #Theta^{2} sin #Theta", "L"); + conv_legend->AddEntry(conv_sin_3, "sin #Theta ^{3}", "L"); + conv_legend->AddEntry(conv_2_sin_sin, "sin 2#Theta sin #Theta", "L"); + conv_legend->Draw(); + canvas->Print("convolutions.eps", "eps"); + + delete conv_sin; + delete conv_cos; + delete conv_sin_2; + delete conv_cos_2; + delete conv_2_sin; + delete conv_2_cos; + delete conv_cos_2_sin; + delete conv_sin_3; + delete conv_2_sin_sin; + + delete canvas; + + TH1D* conv_cos_2_a = new TH1D("conv_cos_2_a", "", divisions, -1.0, +1.0); + TH1D* conv_cos_2_b = new TH1D("conv_cos_2_b", "", divisions, -1.0, +1.0); + TH1D* conv_cos_2_c = new TH1D("conv_cos_2_c", "", divisions, -1.0, +1.0); + TH1D* conv_cos_2_d = new TH1D("conv_cos_2_d", "", divisions, -1.0, +1.0); + TH1D* conv_cos_2_e = new TH1D("conv_cos_2_e", "", divisions, -1.0, +1.0); + conv_cos_2_a->SetMinimum(-1.0); + conv_cos_2_a->SetMaximum(1.0); + for (unsigned int i = 0; i < divisions; i++) + { + double cos_theta = -1.0 + 2.0/divisions*(i+0.5); + double angle = acos(cos_theta); + conv_cos_2_a->SetBinContent(i+1, cos_theta*cos_theta); + conv_cos_2_b->SetBinContent(i+1, convoluted_cos_2(angle, sigma)); + conv_cos_2_c->SetBinContent(i+1, convoluted_cos_2(angle, sigma) + +convoluted_cos_2(-angle, sigma) + +convoluted_cos_2(2.0*TMath::Pi()-angle, sigma)); + conv_cos_2_d->SetBinContent(i+1,1.0/sin(angle)*convoluted_cos_2_sin(angle, sigma)); + conv_cos_2_e->SetBinContent(i+1,1.0/sin(angle)*(convoluted_cos_2_sin(angle, sigma) + +convoluted_cos_2_sin(-angle, sigma) + +convoluted_cos_2_sin(2.0*TMath::Pi()-angle, sigma) + )); + } + + TCanvas *canvas2 = new TCanvas("canvas2", "canvas",1600,1200); + canvas2->cd(); + conv_cos_2_b->SetLineColor(2); + conv_cos_2_c->SetLineColor(3); + conv_cos_2_d->SetLineColor(4); + conv_cos_2_e->SetLineColor(5); + conv_cos_2_a->Draw(); + conv_cos_2_b->Draw("same"); + conv_cos_2_c->Draw("same"); + conv_cos_2_d->Draw("same"); + conv_cos_2_e->Draw("same"); + canvas2->Print("overcos.eps", "eps"); + delete conv_cos_2_a; + delete conv_cos_2_b; + delete conv_cos_2_c; + delete conv_cos_2_d; + delete conv_cos_2_e; + delete canvas2; +} + +void test_int_convolutions() +{ + gStyle->SetPalette(1); + gStyle->SetOptFit(0); + gStyle->SetOptStat(0); + + unsigned int divisions=1000; + double min=-TMath::Pi(); + double max=+2.0*TMath::Pi(); + TH1D* conv_sin = new TH1D("conv_sin", "", divisions, min, max); + TH1D* conv_cos = new TH1D("conv_cos", "", divisions, min, max); + TH1D* conv_sin_2 = new TH1D("conv_sin_2", "", divisions, min, max); + TH1D* conv_cos_2 = new TH1D("conv_cos_2", "", divisions, min, max); + TH1D* conv_2_sin = new TH1D("conv_2_sin", "", divisions, min, max); + TH1D* conv_2_cos = new TH1D("conv_2_cos", "", divisions, min, max); + + TH1D* conv_cos_2_sin = new TH1D("conv_cos_2_sin", "", divisions, min, max); + TH1D* conv_sin_3 = new TH1D("conv_sin_3", "", divisions, min, max); + TH1D* conv_2_sin_sin = new TH1D("conv_2_sin_sin", "", divisions, min, max); + + double sigma = 0.03; + for (unsigned int i = 0; i < divisions; i++) + { + double angle = min+(max - min)/double(divisions)*i; + conv_sin->SetBinContent(i+1, int_convoluted_sin(angle, sigma)-int_convoluted_sin(min, sigma)); + + // conv_cos->SetBinContent(i+1, convoluted_cos(angle, sigma)); + conv_sin_2->SetBinContent(i+1, int_convoluted_sin_2(angle, sigma) - int_convoluted_sin_2(min, sigma)); + // conv_cos_2->SetBinContent(i+1, convoluted_cos_2(angle, sigma)); + conv_2_sin->SetBinContent(i+1, int_convoluted_2_sin(angle, sigma)-int_convoluted_2_sin(min, sigma)); + // conv_2_cos->SetBinContent(i+1, convoluted_2_cos(angle, sigma)); + + conv_cos_2_sin->SetBinContent(i+1, int_convoluted_cos_2_sin(angle, sigma) - int_convoluted_cos_2_sin(min, sigma)); + conv_sin_3->SetBinContent(i+1, int_convoluted_sin_3(angle, sigma)-int_convoluted_sin_3(min, sigma)); + conv_2_sin_sin->SetBinContent(i+1, int_convoluted_2_sin_sin(angle, sigma) - int_convoluted_2_sin_sin(min, sigma)); + } + + conv_sin->SetLineColor(2); + conv_cos->SetLineColor(3); + conv_sin_2->SetLineColor(4); + conv_cos_2->SetLineColor(5); + conv_2_sin->SetLineColor(6); + conv_2_cos->SetLineColor(7); + conv_cos_2_sin->SetLineColor(8); + conv_sin_3->SetLineColor(9); + conv_2_sin_sin->SetLineColor(15); + + TCanvas *canvas = new TCanvas("canvas", "canvas",1600,1200) ; + canvas->cd(); + conv_sin->SetMinimum(-0.5); + conv_sin->SetMaximum(3.0); + conv_sin->Draw(); + + // conv_cos->Draw("same"); + conv_sin_2->Draw("same"); + // conv_cos_2->Draw("same"); + conv_2_sin->Draw("same"); + // conv_2_cos->Draw("same"); + conv_cos_2_sin->Draw("same"); + conv_sin_3->Draw("same"); + conv_2_sin_sin->Draw("same"); + TLegend* conv_legend = new TLegend(0.7,0.6,0.9,0.9); + conv_legend->AddEntry(conv_sin, "sin #Theta", "L"); + conv_legend->AddEntry(conv_cos, "cos #Theta", "L"); + conv_legend->AddEntry(conv_sin_2, "sin #Theta^{2}", "L"); + conv_legend->AddEntry(conv_cos_2, "cos #Theta^{2}", "L"); + conv_legend->AddEntry(conv_2_sin, "sin 2#Theta", "L"); + conv_legend->AddEntry(conv_2_cos, "cos 2#Theta", "L"); + conv_legend->AddEntry(conv_cos_2_sin, "cos #Theta^{2} sin #Theta", "L"); + conv_legend->AddEntry(conv_sin_3, "sin #Theta ^{3}", "L"); + conv_legend->AddEntry(conv_2_sin_sin, "sin 2#Theta sin #Theta", "L"); + conv_legend->Draw(); + canvas->Print("int_convolutions.eps", "eps"); + + delete conv_sin; + delete conv_cos; + delete conv_sin_2; + delete conv_cos_2; + delete conv_2_sin; + delete conv_2_cos; + delete conv_cos_2_sin; + delete conv_sin_3; + delete conv_2_sin_sin; + delete canvas; +} + + +} diff --git a/Code/FCNCFitter/sources/tests.hh b/Code/FCNCFitter/sources/tests.hh new file mode 100644 index 0000000..fbcf9a9 --- /dev/null +++ b/Code/FCNCFitter/sources/tests.hh @@ -0,0 +1,25 @@ +//Renata Kopecna + +#ifndef TESTS_HH +#define TESTS_HH + + +namespace fcnc { + + + void test_legendre(); + void test_legendre_2pi(); + void test_legendre_2d(); + void test_chebyshev(); + void test_integrals(); + + ///compares the different implementations of the complex error function + void test_errf(); + void test_convolutions(); + void test_int_convolutions(); + + +} + + +#endif // TESTS_HH diff --git a/Code/FCNCFitter/systematic_overview_Kshort.dat b/Code/FCNCFitter/systematic_overview_Kshort.dat new file mode 100644 index 0000000..84ea76a --- /dev/null +++ b/Code/FCNCFitter/systematic_overview_Kshort.dat @@ -0,0 +1,13 @@ +idx name static_seed +0 nominal no +1 bootstrapping yes +2 symmetric ctl no +3 2 more orders no +4 random weights yes +5 random FS yes +6 angular reso. yes +7 mass model no +8 ang background no +9 trigger no +10 pion pt no +11 bkg veto no diff --git a/Code/FCNCFitter/testCpp.cc b/Code/FCNCFitter/testCpp.cc new file mode 100644 index 0000000..6e08716 --- /dev/null +++ b/Code/FCNCFitter/testCpp.cc @@ -0,0 +1,73 @@ + +#include +#include +#include +#include +#include +#include +#include + + +//Compile with g++ -std=c++11 testCpp.cc -o test; ./test +std::string convert_vector_to_string(std::vector myVector){ + std::stringstream ss; + copy(myVector.begin(), myVector.end(), std::ostream_iterator(ss, " ")); + std::string s = ss.str(); + return s.substr(0, s.length()-1); // get rid of the trailing space +} + + +int try_getObservable(std::string observable, TFile* file){ + if (!file->GetListOfKeys()->Contains(observable.c_str())){ + //Also check if Fl<->S1s and A_FB<->S6s is available + if (observable == "Fl") return 10+try_getObservable("S1s",file); + if (observable == "S1s") return 20+try_getObservable("Fl",file); + if (observable == "Afb") return 30+try_getObservable("S6s",file); + if (observable == "S6s") return 40+try_getObservable("Afb",file); + return 0; + } + else return 1; +} + +std::vector load_param_values_into_vector(std::string paramName, std::string fileName){ + //There is a function for this in bu2kstarmumu_parameters.cc, but that is inherited from parameters, therefore a parameter class needs to be created for this + //That would be tedious, so there is a new class that opens the root file with results and reads it from a tree directly into an array + + //Create the vector that will be returned + std::vector output; + + //Open file + std::cout << "Opening " << fileName <Get(paramName.c_str()); + //Activate only needed branches + tree->SetBranchStatus("*",0); + tree->SetBranchStatus("value",1); + double value = 0; + tree->SetBranchAddress("value", &value); + + //Loop over nBins that are saved in the tree + + for (int wait = 0; wait < 10; wait++){ //Make the code stall for a bit + for (int b = 0; b < tree->GetEntries(); b++){ + tree->GetEntry(b); + output.push_back(value); + } + } + std::cout << convert_vector_to_string(output) << std::endl; + return output; +} + +using namespace std; //I know it is not safe, but ef it +int main() { + cout << "Hello World!" << endl; + load_param_values_into_vector("S3", +"/home/lhcb/kopecna/B2KstarMuMu/code/ewp-Bplus2Kstmumu-AngAna/FCNCfitter/fitResults/GenLvlFit/finalresultgenLvl_MC_SignalFit_ALLBINS_OnlyAngles.root"); +} + diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2011MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2011MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2011MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2011MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2011MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2011MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2011MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2011MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2011MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2011MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2011MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2011MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2012MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2012MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2012MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2012MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2012MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2012MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2012MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2012MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2012MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2012MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2012MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2012MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2015MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2015MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2015MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2015MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2015MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2015MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2015MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2015MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2015MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2015MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2015MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2015MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2016MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2016MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2016MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2016MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2016MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2016MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2016MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2016MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2016MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2016MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2016MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstJpsi/.imap/2016MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2011MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2011MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2011MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2011MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2011MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2011MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2011MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2011MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2011MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2011MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2011MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2011MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2012MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2012MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2012MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2012MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2012MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2012MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2012MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2012MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2012MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2012MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2012MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2012MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2015MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2015MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2015MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2015MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2015MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2015MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2015MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2015MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2015MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2015MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2015MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2015MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2016MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2016MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2016MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2016MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2016MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2016MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2016MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2016MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2016MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2016MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2016MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/B0toKstMuMu/.imap/2016MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoK1Jpsi/.imap/2012MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoK1Jpsi/.imap/2012MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoK1Jpsi/.imap/2012MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoK1Jpsi/.imap/2012MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoK1Jpsi/.imap/2012MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoK1Jpsi/.imap/2012MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoK1Jpsi/.imap/2012MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoK1Jpsi/.imap/2012MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoK1Jpsi/.imap/2012MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoK1Jpsi/.imap/2012MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoK1Jpsi/.imap/2012MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoK1Jpsi/.imap/2012MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2011MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2011MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2011MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2011MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2011MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2011MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2011MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2011MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2011MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2011MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2011MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2011MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2012MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2012MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2012MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2012MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2012MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2012MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2012MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2012MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2012MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2012MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2012MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoK1MuMu/.imap/2012MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2011MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2011MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2011MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2011MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2011MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2011MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2011MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2011MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2011MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2011MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2011MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2011MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2012MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2012MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2012MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2012MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2012MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2012MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2012MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2012MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2012MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2012MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2012MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstJpsi/.imap/2012MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2011MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2011MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2011MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2011MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2011MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2011MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2011MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2011MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2011MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2011MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2011MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2011MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2012MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2012MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2012MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2012MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2012MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2012MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2012MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2012MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2012MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2012MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2012MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2012MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2015MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2015MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2015MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2015MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2015MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2015MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2015MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2015MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2015MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2015MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2015MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2015MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2016MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2016MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2016MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2016MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2016MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2016MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2016MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2016MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2016MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2016MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2016MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoKstMuMu/.imap/2016MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2011MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2011MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2011MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2011MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2011MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2011MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2011MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2011MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2011MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2011MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2011MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2011MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2012MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2012MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2012MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2012MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2012MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2012MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2012MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2012MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2012MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2012MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2012MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2012MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2015MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2015MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2015MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2015MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2015MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2015MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2015MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2015MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2015MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2015MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2015MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2015MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2016MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2016MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2016MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2016MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2016MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2016MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2016MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2016MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2016MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2016MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2016MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/BtoXJpsi/.imap/2016MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2011MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2011MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2011MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2011MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2011MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2011MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2011MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2011MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2011MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2011MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2011MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2011MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2012MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2012MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2012MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2012MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2012MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2012MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2012MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2012MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2012MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2012MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2012MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2012MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2015MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2015MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2015MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2015MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2015MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2015MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2015MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2015MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2015MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2015MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2015MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2015MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2016MagDown_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2016MagDown_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2016MagDown_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2016MagDown_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2016MagDown_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2016MagDown_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2016MagUp_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2016MagUp_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2016MagUp_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2016MagUp_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2016MagUp_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/Backgrounds/PHSP/.imap/2016MagUp_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2011Down_PHSP_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2011Down_PHSP_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2011Down_PHSP_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2011Down_PHSP_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2011Down_PHSP_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2011Down_PHSP_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2011Up_PHSP_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2011Up_PHSP_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2011Up_PHSP_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2011Up_PHSP_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2011Up_PHSP_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2011Up_PHSP_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2012Down_PHSP_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2012Down_PHSP_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2012Down_PHSP_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2012Down_PHSP_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2012Down_PHSP_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2012Down_PHSP_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2012Up_PHSP_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2012Up_PHSP_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2012Up_PHSP_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2012Up_PHSP_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2012Up_PHSP_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2012Up_PHSP_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2015Down_PHSP_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2015Down_PHSP_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2015Down_PHSP_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2015Down_PHSP_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2015Down_PHSP_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2015Down_PHSP_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2015Up_PHSP_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2015Up_PHSP_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2015Up_PHSP_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2015Up_PHSP_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2015Up_PHSP_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2015Up_PHSP_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2016Down_PHSP_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2016Down_PHSP_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2016Down_PHSP_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2016Down_PHSP_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2016Down_PHSP_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2016Down_PHSP_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2016Up_PHSP_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2016Up_PHSP_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2016Up_PHSP_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2016Up_PHSP_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2016Up_PHSP_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2016Up_PHSP_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2017Down_PHSP_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2017Down_PHSP_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2017Down_PHSP_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2017Down_PHSP_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2017Down_PHSP_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2017Down_PHSP_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2017Up_PHSP_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2017Up_PHSP_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2017Up_PHSP_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2017Up_PHSP_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2017Up_PHSP_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2017Up_PHSP_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2018Down_PHSP_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2018Down_PHSP_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2018Down_PHSP_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2018Down_PHSP_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2018Down_PHSP_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2018Down_PHSP_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2018Up_PHSP_Kplus.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2018Up_PHSP_Kplus.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2018Up_PHSP_Kplus.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/PHSP/.imap/2018Up_PHSP_Kshort.py/dovecot.index.log b/Code/Ganga/OptionFiles/PHSP/.imap/2018Up_PHSP_Kshort.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/PHSP/.imap/2018Up_PHSP_Kshort.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/ScriptForScripts.py b/Code/Ganga/OptionFiles/ScriptForScripts.py index d3b9899..78de94b 100644 --- a/Code/Ganga/OptionFiles/ScriptForScripts.py +++ b/Code/Ganga/OptionFiles/ScriptForScripts.py @@ -59,27 +59,27 @@ YearList = ['2011','2012','2015','2016','2017','2018'] for Type in DataTypeList: for Year in YearList: for Polarity in PolarityList: - for Ref in Type['reference']: - for Channel in Type['channel']: - ScriptName = "./optfiles/%s/%s/%s%s_%s%s.py" % (Type['name'],Ref['string'],Year, Polarity['string'],Type['name'],Channel['string']) - f1 = open(ScriptName, 'w') - f1.write( '############# Global settings\n' ) - f1.write( 'runFilters = False\n' ) - f1.write( 'reference = %s\n' % Ref['bool'] ) - f1.write( 'phsp = %s\n' % Type['phsp'] ) - f1.write( 'BkgStudy = %s\n' % Type['BkgStudy'] ) - f1.write( 'data = %s\n' % Type['data'] ) - f1.write( 'down = %s\n' % Polarity['bool'] ) - f1.write( 'year = "%s"\n'%Year ) - f1.write( 'stream = "%s"\n' % Type['stream'] ) - f1.write( 'line = "%s"\n\n'% Type['line'] ) - f1.write( '#subdecay chains\n' ) - f1.write( 'KShortPiPlus = %s\n' % Channel['boolKshort'] ) - f1.write( 'KplusPi0Merged = False\n') #% Channel['boolKplus'] ) - f1.write( 'KplusPi0Resolved = %s\n\n\n'% Channel['boolKplus'] ) + for Ref in Type['reference']: + for Channel in Type['channel']: + ScriptName = "./optfiles/%s/%s/%s%s_%s%s.py" % (Type['name'],Ref['string'],Year, Polarity['string'],Type['name'],Channel['string']) + f1 = open(ScriptName, 'w') + f1.write( '############# Global settings\n' ) + f1.write( 'runFilters = False\n' ) + f1.write( 'reference = %s\n' % Ref['bool'] ) + f1.write( 'phsp = %s\n' % Type['phsp'] ) + f1.write( 'BkgStudy = %s\n' % Type['BkgStudy'] ) + f1.write( 'data = %s\n' % Type['data'] ) + f1.write( 'down = %s\n' % Polarity['bool'] ) + f1.write( 'year = "%s"\n'%Year ) + f1.write( 'stream = "%s"\n' % Type['stream'] ) + f1.write( 'line = "%s"\n\n'% Type['line'] ) + f1.write( '#subdecay chains\n' ) + f1.write( 'KShortPiPlus = %s\n' % Channel['boolKshort'] ) + f1.write( 'KplusPi0Merged = False\n') #% Channel['boolKplus'] ) + f1.write( 'KplusPi0Resolved = %s\n\n\n'% Channel['boolKplus'] ) - f = open('./optfiles/BasicOptfile.py') - for line in f.readlines(): - f1.write(line) - f.close() - f1.close() + f = open('./optfiles/BasicOptfile.py') + for line in f.readlines(): + f1.write(line) + f.close() + f1.close() diff --git a/Code/Ganga/OptionFiles/data/.imap/2011Down_data.py/dovecot.index.log b/Code/Ganga/OptionFiles/data/.imap/2011Down_data.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/data/.imap/2011Down_data.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/data/.imap/2011Up_data.py/dovecot.index.log b/Code/Ganga/OptionFiles/data/.imap/2011Up_data.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/data/.imap/2011Up_data.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/data/.imap/2012Down_data.py/dovecot.index.log b/Code/Ganga/OptionFiles/data/.imap/2012Down_data.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/data/.imap/2012Down_data.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/data/.imap/2012Up_data.py/dovecot.index.log b/Code/Ganga/OptionFiles/data/.imap/2012Up_data.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/data/.imap/2012Up_data.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/data/.imap/2015Down_data.py/dovecot.index.log b/Code/Ganga/OptionFiles/data/.imap/2015Down_data.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/data/.imap/2015Down_data.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/data/.imap/2015Up_data.py/dovecot.index.log b/Code/Ganga/OptionFiles/data/.imap/2015Up_data.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/data/.imap/2015Up_data.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/data/.imap/2016Down_data.py/dovecot.index.log b/Code/Ganga/OptionFiles/data/.imap/2016Down_data.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/data/.imap/2016Down_data.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/data/.imap/2016Up_data.py/dovecot.index.log b/Code/Ganga/OptionFiles/data/.imap/2016Up_data.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/data/.imap/2016Up_data.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/data/.imap/2017Down_data.py/dovecot.index.log b/Code/Ganga/OptionFiles/data/.imap/2017Down_data.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/data/.imap/2017Down_data.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/data/.imap/2017Up_data.py/dovecot.index.log b/Code/Ganga/OptionFiles/data/.imap/2017Up_data.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/data/.imap/2017Up_data.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/data/.imap/2018Down_data.py/dovecot.index.log b/Code/Ganga/OptionFiles/data/.imap/2018Down_data.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/data/.imap/2018Down_data.py/dovecot.index.log and /dev/null differ diff --git a/Code/Ganga/OptionFiles/data/.imap/2018Up_data.py/dovecot.index.log b/Code/Ganga/OptionFiles/data/.imap/2018Up_data.py/dovecot.index.log deleted file mode 100644 index c041f78..0000000 Binary files a/Code/Ganga/OptionFiles/data/.imap/2018Up_data.py/dovecot.index.log and /dev/null differ