void CreateBkgTemplates(float XMIN, float XMAX, TString OUTPATH, bool MERGE) { gROOT->ProcessLineSync(".x ../common/styleCMSTDR.C"); gROOT->ForceStyle(); RooMsgService::instance().setSilentMode(kTRUE); for(int i=0;i<2;i++) { RooMsgService::instance().setStreamStatus(i,kFALSE); } const int NSEL(2); if (!MERGE) {const int NCAT[NSEL] = {4,3};} else {const int NCAT[NSEL] = {4,2};} if (!MERGE) {const double MVA_BND[NSEL][NCAT[0]+1] = {{-0.6,0.0,0.7,0.84,1},{-0.1,0.4,0.8,1}};} else {const double MVA_BND[NSEL][NCAT[0]+1] = {{-0.6,0.0,0.7,0.84,1},{-0.1,0.4,1}};} float LUMI[2] = {19784,18281}; TString SELECTION[2] = {"NOM","VBF"}; TString SELNAME[2] = {"NOM","PRK"}; TString MASS_VAR[2] = {"mbbReg[1]","mbbReg[2]"}; TString TRIG_WT[2] = {"trigWtNOM[1]","trigWtVBF"}; TString PATH("flat/"); TFile *inf[9]; TTree *tr; TH1F *hMbb[9],*hMbbYield[9],*hPass; TH1F *hZ,*hW,*hTT,*hST,*hTop; TH1F *hZYield,*hWYield,*hTTYield,*hSTYield,*hTopYield; char name[1000]; float LUMI; float XSEC[9] = {56.4,11.1,3.79,30.7,11.1,1.76,245.8,650,1.2*1205}; RooDataHist *roohist_Z[5],*roohist_T[5]; RooRealVar *kJES[10],*kJER[10]; RooWorkspace *w = new RooWorkspace("w","workspace"); TString tMERGE = MERGE ? "_CATmerge56" : ""; //RooRealVar x("mbbReg","mbbReg",XMIN,XMAX); int counter(0); for(int isel=0;isel<NSEL;isel++) { inf[0] = TFile::Open(PATH+"Fit_T_t-channel_sel"+SELECTION[isel]+".root"); inf[1] = TFile::Open(PATH+"Fit_T_tW-channel_sel"+SELECTION[isel]+".root"); inf[2] = TFile::Open(PATH+"Fit_T_s-channel_sel"+SELECTION[isel]+".root"); inf[3] = TFile::Open(PATH+"Fit_Tbar_t-channel_sel"+SELECTION[isel]+".root"); inf[4] = TFile::Open(PATH+"Fit_Tbar_tW-channel_sel"+SELECTION[isel]+".root"); inf[5] = TFile::Open(PATH+"Fit_Tbar_s-channel_sel"+SELECTION[isel]+".root"); inf[6] = TFile::Open(PATH+"Fit_TTJets_sel"+SELECTION[isel]+".root"); inf[7] = TFile::Open(PATH+"Fit_ZJets_sel"+SELECTION[isel]+".root"); inf[8] = TFile::Open(PATH+"Fit_WJets_sel"+SELECTION[isel]+".root"); TCanvas *canZ = new TCanvas("canZ_"+SELECTION[isel],"canZ_"+SELECTION[isel],900,600); TCanvas *canT = new TCanvas("canT_"+SELECTION[isel],"canT_"+SELECTION[isel],900,600); canZ->Divide(2,2); canT->Divide(2,2); TCanvas *can = new TCanvas(); sprintf(name,"CMS_vbfbb_scale_mbb_sel%s",SELECTION[isel].Data()); kJES[isel] = new RooRealVar(name,name,1.0); sprintf(name,"CMS_vbfbb_res_mbb_sel%s",SELECTION[isel].Data()); kJER[isel] = new RooRealVar(name,name,1.0); kJES[isel]->setConstant(kTRUE); kJER[isel]->setConstant(kTRUE); for(int icat=0;icat<NCAT[isel];icat++) { if (MERGE && SELECTION[isel]=="VBF" && icat==1) counter = 56; /* sprintf(name,"CMS_vbfbb_scale_mbb_CAT%d",counter); kJES[counter] = new RooRealVar(name,name,1.0); sprintf(name,"CMS_vbbb_res_mbb_CAT%d",counter); kJER[counter] = new RooRealVar(name,name,1.0); kJES[counter]->setConstant(kTRUE); kJER[counter]->setConstant(kTRUE); */ for(int i=0;i<9;i++) { hPass = (TH1F*)inf[i]->Get("TriggerPass"); sprintf(name,"Hbb/events",icat); tr = (TTree*)inf[i]->Get(name); sprintf(name,"puWt[0]*%s*(mva%s>%1.2f && mva%s<=%1.2f)",TRIG_WT[isel].Data(),SELECTION[isel].Data(),MVA_BND[isel][icat],SELECTION[isel].Data(),MVA_BND[isel][icat+1]); TCut cut(name); int NBINS(20); //if (icat > 1 && icat<=2) NBINS = 20; if (icat > 2) NBINS = 12; sprintf(name,"hMbb%d_sel%s_CAT%d",i,SELECTION[isel].Data(),icat); hMbb[i] = new TH1F(name,name,NBINS,XMIN,XMAX); hMbb[i]->Sumw2(); can->cd(); tr->Draw(MASS_VAR[isel]+">>"+hMbb[i]->GetName(),cut); sprintf(name,"hMbbYield%d_sel%s_CAT%d",i,SELECTION[isel].Data(),icat); hMbbYield[i] = new TH1F(name,name,NBINS,XMIN,XMAX); hMbbYield[i]->Sumw2(); tr->Draw(MASS_VAR[isel]+">>"+hMbbYield[i]->GetName(),cut); hMbbYield[i]->Scale(LUMI[isel]*XSEC[i]/hPass->GetBinContent(1)); } hZ = (TH1F*)hMbb[7]->Clone("Z"); hW = (TH1F*)hMbb[8]->Clone("W"); hTT = (TH1F*)hMbb[6]->Clone("TT"); hST = (TH1F*)hMbb[0]->Clone("ST"); hST->Add(hMbb[1]); hST->Add(hMbb[2]); hST->Add(hMbb[3]); hST->Add(hMbb[4]); hST->Add(hMbb[5]); hTop = (TH1F*)hTT->Clone("Top"); hTop->Add(hST); //hZ->Add(hW); hZYield = (TH1F*)hMbbYield[7]->Clone("ZYield"); hWYield = (TH1F*)hMbbYield[8]->Clone("WYield"); hTTYield = (TH1F*)hMbbYield[6]->Clone("TTYield"); hSTYield = (TH1F*)hMbbYield[0]->Clone("STYield"); hSTYield->Add(hMbbYield[1]); hSTYield->Add(hMbbYield[2]); hSTYield->Add(hMbbYield[3]); hSTYield->Add(hMbbYield[4]); hSTYield->Add(hMbbYield[5]); hTopYield = (TH1F*)hTTYield->Clone("TopYield"); hTopYield->Add(hSTYield); hZYield->Add(hWYield); RooRealVar x("mbbReg_"+TString::Format("CAT%d",counter),"mbbReg_"+TString::Format("CAT%d",counter),XMIN,XMAX); sprintf(name,"yield_ZJets_CAT%d",counter); RooRealVar *YieldZ = new RooRealVar(name,name,hZYield->Integral()); sprintf(name,"yield_WJets_CAT%d",counter); RooRealVar *YieldW = new RooRealVar(name,name,hWYield->Integral()); sprintf(name,"yield_Top_CAT%d",counter); RooRealVar *YieldT = new RooRealVar(name,name,hTopYield->Integral()); sprintf(name,"yield_TT_CAT%d",counter); RooRealVar *YieldTT = new RooRealVar(name,name,hTTYield->Integral()); sprintf(name,"yield_ST_CAT%d",counter); RooRealVar *YieldST = new RooRealVar(name,name,hSTYield->Integral()); sprintf(name,"roohist_Z_CAT%d",counter); roohist_Z[icat] = new RooDataHist(name,name,x,hZ); sprintf(name,"Z_mean_CAT%d",counter); RooRealVar mZ(name,name,95,80,110); sprintf(name,"Z_sigma_CAT%d",counter); RooRealVar sZ(name,name,12,9,20); sprintf(name,"Z_mean_shifted_CAT%d",counter); RooFormulaVar mZShift(name,"@0*@1",RooArgList(mZ,*(kJES[isel]))); sprintf(name,"Z_sigma_shifted_CAT%d",counter); RooFormulaVar sZShift(name,"@0*@1",RooArgList(sZ,*(kJER[isel]))); sprintf(name,"Z_a_CAT%d",counter); RooRealVar aZ(name,name,-1,-10,10); sprintf(name,"Z_n_CAT%d",counter); RooRealVar nZ(name,name,1,0,10); RooRealVar Zb0("Z_b0_CAT"+TString::Format("%d",counter),"Z_b0_CAT"+TString::Format("%d",counter),0.5,0,1.); RooRealVar Zb1("Z_b1_CAT"+TString::Format("%d",counter),"Z_b1_CAT"+TString::Format("%d",counter),0.5,0,1.); RooRealVar Zb2("Z_b2_CAT"+TString::Format("%d",counter),"Z_b2_CAT"+TString::Format("%d",counter),0.5,0,1.); RooBernstein Zbkg("Z_bkg_CAT"+TString::Format("%d",counter),"Z_bkg_CAT"+TString::Format("%d",counter),x,RooArgSet(Zb0,Zb1,Zb2)); RooRealVar fZsig("fZsig_CAT"+TString::Format("%d",counter),"fZsig_CAT"+TString::Format("%d",counter),0.7,0.,1.); RooCBShape Zcore("Zcore_CAT"+TString::Format("%d",counter),"Zcore_CAT"+TString::Format("%d",counter),x,mZShift,sZShift,aZ,nZ); RooAddPdf modelZ("Z_model_CAT"+TString::Format("%d",counter),"Z_model_CAT"+TString::Format("%d",counter),RooArgList(Zcore,Zbkg),fZsig); RooFitResult *resZ = modelZ.fitTo(*roohist_Z[icat],RooFit::Save(),RooFit::SumW2Error(kFALSE),"q"); canZ->cd(icat+1); RooPlot* frame = x.frame(); roohist_Z[icat]->plotOn(frame); modelZ.plotOn(frame,RooFit::LineWidth(2)); frame->GetXaxis()->SetTitle("M_{bb} (GeV)"); frame->Draw(); TPaveText *pave = new TPaveText(0.7,0.76,0.9,0.9,"NDC"); pave->SetTextAlign(11); pave->SetFillColor(0); pave->SetBorderSize(0); pave->SetTextFont(62); pave->SetTextSize(0.045); pave->AddText(TString::Format("%s selection",SELNAME[isel].Data())); pave->AddText(TString::Format("CAT%d",counter)); TText *lastline = pave->AddText("Z template"); pave->SetY1NDC(pave->GetY2NDC()-0.055*3); TPaveText *paveorig = (TPaveText*)pave->Clone(); paveorig->Draw(); sprintf(name,"roohist_T_CAT%d",counter); if (icat < 3) { roohist_T[icat] = new RooDataHist(name,name,x,hTopYield); } else { roohist_T[icat] = new RooDataHist(name,name,x,hSTYield); } sprintf(name,"Top_mean_CAT%d",counter); RooRealVar mT(name,name,130,0,200); sprintf(name,"Top_sigma_CAT%d",counter); RooRealVar sT(name,name,50,0,200); sprintf(name,"Top_mean_shifted_CAT%d",counter); RooFormulaVar mTShift(name,"@0*@1",RooArgList(mT,*(kJES[isel]))); sprintf(name,"Top_sigma_shifted_CAT%d",counter); RooFormulaVar sTShift(name,"@0*@1",RooArgList(sT,*(kJER[isel]))); sprintf(name,"Top_model_CAT%d",counter); RooGaussian *modelT = new RooGaussian(name,name,x,mTShift,sTShift); RooFitResult *resT = modelT->fitTo(*roohist_T[icat],Save(),SumW2Error(kTRUE),"q"); /* TF1 *tmp_func = new TF1("tmpFunc","gaus",XMIN,XMAX); tmp_func->SetParameters(1,a0.getVal(),a1.getVal()); if (icat < 3) { float norm = tmp_func->Integral(XMIN,XMAX)/hTopYield->GetBinWidth(1); tmp_func->SetParameter(0,hTopYield->Integral()/norm); } else { float norm = tmp_func->Integral(XMIN,XMAX)/hSTYield->GetBinWidth(1); tmp_func->SetParameter(0,hSTYield->Integral()/norm); } */ canT->cd(icat+1); RooPlot* frame = x.frame(); roohist_T[icat]->plotOn(frame); modelT->plotOn(frame,RooFit::LineWidth(2)); //modelT->plotOn(frame,VisualizeError(*resT,1,kTRUE),FillColor(kGray),MoveToBack()); frame->GetXaxis()->SetTitle("M_{bb} (GeV)"); frame->Draw(); //tmp_func->Draw("sameL"); lastline->SetTitle("Top template"); pave->Draw(); mZ.setConstant(kTRUE); sZ.setConstant(kTRUE); aZ.setConstant(kTRUE); nZ.setConstant(kTRUE); Zb0.setConstant(kTRUE); Zb1.setConstant(kTRUE); Zb2.setConstant(kTRUE); fZsig.setConstant(kTRUE); mT.setConstant(kTRUE); sT.setConstant(kTRUE); w->import(modelZ); w->import(*modelT); w->import(*YieldZ); w->import(*YieldT); w->import(*YieldTT); w->import(*YieldST); YieldZ->Print(); YieldW->Print(); YieldT->Print(); YieldTT->Print(); YieldST->Print(); counter++; }// category loop system(TString::Format("[ ! -d %s/ ] && mkdir %s/",OUTPATH.Data(),OUTPATH.Data()).Data()); system(TString::Format("[ ! -d %s/plots ] && mkdir %s/plots",OUTPATH.Data(),OUTPATH.Data()).Data()); system(TString::Format("[ ! -d %s/plots/bkgTemplates ] && mkdir %s/plots/bkgTemplates",OUTPATH.Data(),OUTPATH.Data()).Data()); TString FULLPATH(OUTPATH+"/plots/bkgTemplates"); canT->SaveAs(TString::Format("%s/%s.png",FULLPATH.Data(),canT->GetName())); canZ->SaveAs(TString::Format("%s/%s.png",FULLPATH.Data(),canZ->GetName())); canT->SaveAs(TString::Format("%s/%s.pdf",FULLPATH.Data(),canT->GetName())); canZ->SaveAs(TString::Format("%s/%s.pdf",FULLPATH.Data(),canZ->GetName())); delete can; }// selection loop system(TString::Format("[ ! -d %s/ ] && mkdir %s/",OUTPATH.Data(),OUTPATH.Data()).Data()); system(TString::Format("[ ! -d %s/output ] && mkdir %s/output",OUTPATH.Data(),OUTPATH.Data()).Data()); w->Print(); w->writeToFile(TString::Format("%s/output/bkg_shapes_workspace%s.root",OUTPATH.Data(),tMERGE.Data()).Data()); }
void FitLeptonResponseModels(const string Label = "ZZ", Int_t Option = 0, Int_t PtBin = -1, Int_t EtaBin = -1) { string label = Label; if (Label != "") label = "_" + Label; TFile *fileInput = new TFile(("FakeRate" + label + ".root").c_str(), "READ"); //******************************************************** // Bins //******************************************************** const UInt_t NPtBins = 4; const UInt_t NEtaBins = 3; double ptBins[NPtBins+1] = { 5, 7, 10, 15, 25 }; double etaBins[NEtaBins+1] = { 0.0, 1.2, 2.2, 2.4 }; //******************************************************** // Output //******************************************************** TFile *fileOutput = new TFile(("FakeMuonPtResolutionModel" + label + ".root").c_str(), "UPDATE"); TH2F* GaussParamArray_Muons_mean = (TH2F*)fileOutput->Get("GaussParamArray_Muons_mean"); TH2F* GaussParamArray_Muons_sigma = (TH2F*)fileOutput->Get("GaussParamArray_Muons_sigma"); if (!GaussParamArray_Muons_mean) { GaussParamArray_Muons_mean = new TH2F( "GaussParamArray_Muons_mean", "", NPtBins, 0, NPtBins, NEtaBins, 0, NEtaBins); for (uint i=0; i < NPtBins+2; ++i) { for (uint j=0; j < NEtaBins+2; ++j) { GaussParamArray_Muons_mean->SetBinContent(i,j,0.0); } } } if (!GaussParamArray_Muons_sigma) { GaussParamArray_Muons_sigma = new TH2F( "GaussParamArray_Muons_sigma", "", NPtBins, 0, NPtBins, NEtaBins, 0, NEtaBins); for (uint i=0; i < NPtBins+2; ++i) { for (uint j=0; j < NEtaBins+2; ++j) { GaussParamArray_Muons_sigma->SetBinContent(i,j,0.0); } } } for (uint i=0; i < NPtBins+2; ++i) { for (uint j=0; j < NEtaBins+2; ++j) { if (i >= 1 && ( j >= 1 && j <= NEtaBins )) { } else { GaussParamArray_Muons_mean->SetBinContent(i,j,0); GaussParamArray_Muons_sigma->SetBinContent(i,j,0); } } } //******************************************************** // Fit for resolution function //******************************************************** for (uint i=0; i < NPtBins+2; ++i) { for (uint j=0; j < NEtaBins+2; ++j) { if (PtBin >= 0 && EtaBin >= 0) { if (!(i==PtBin && j==EtaBin)) continue; } TH1F* hist = (TH1F*)fileInput->Get(Form("LeptonPtResolution_Muons_PtBin%d_EtaBin%d",i,j)); assert(hist); RooRealVar leptonPtRes("leptonPtRes","leptonPtRes",-1.0,0.25); leptonPtRes.setRange("range",-1.00,0.25); leptonPtRes.setBins(100); RooDataHist *data=0; data = new RooDataHist("data","data",RooArgSet(leptonPtRes),hist); RooRealVar *mean = new RooRealVar("mean","mean",-0.25,-10,10); RooRealVar *sigma = new RooRealVar("sigma","sigma",0.05,0.00001,0.5); RooGaussian *model = new RooGaussian("LeptonPtResModel","LeptonPtResModel",leptonPtRes,*mean,*sigma); RooFitResult *fitResult=0; fitResult = model->fitTo(*data, RooFit::Binned(true), RooFit::Strategy(1), RooFit::Save()); cout << "Fitted parameters\n"; cout << mean->getVal() << endl; cout << sigma->getVal() << endl; if (i >= 1 && ( j >= 1 && j <= NEtaBins )) { GaussParamArray_Muons_mean->SetBinContent(i,j,mean->getVal()); GaussParamArray_Muons_sigma->SetBinContent(i,j,sigma->getVal()); } else { GaussParamArray_Muons_mean->SetBinContent(i,j,0); GaussParamArray_Muons_sigma->SetBinContent(i,j,0); } //Save Workspace RooWorkspace *w = new RooWorkspace(Form("LeptonPtResolutionModel_Muons_PtBin%d_EtaBin%d",i,j),Form("LeptonPtResolutionModel_Muons_PtBin%d_EtaBin%d",i,j)); w->import(*model); w->import(*data); //w->Print(); //Make Plot RooPlot *frame = leptonPtRes.frame(RooFit::Bins(100)); data->plotOn(frame,RooFit::MarkerStyle(kFullCircle),RooFit::MarkerSize(0.8),RooFit::DrawOption("ZP")); model->plotOn(frame); TCanvas *cv = new TCanvas("cv","cv",800,600); frame->Draw(); cv->SaveAs(Form("LeptonPtResolution_Muons%s_PtBin%d_EtaBin%d.gif",label.c_str(),i,j)); fileOutput->WriteTObject(model, Form("LeptonPtResolutionModel_Muons_PtBin%d_EtaBin%d",i,j), "WriteDelete"); fileOutput->WriteTObject(cv, Form("LeptonPtResolutionFit_Muons_PtBin%d_EtaBin%d",i,j), "WriteDelete"); fileOutput->WriteTObject(w, w->GetName(), "WriteDelete"); fileOutput->WriteTObject(GaussParamArray_Muons_mean, "GaussParamArray_Muons_mean", "WriteDelete"); fileOutput->WriteTObject(GaussParamArray_Muons_sigma, "GaussParamArray_Muons_sigma", "WriteDelete"); } } //******************************************************** // Produce output lookup table //******************************************************** ofstream outf_e("FakeMuonResponseMap.h"); outf_e << "UInt_t FindFakeMuonResponseBin( double value, double bins[], UInt_t nbins) {" << endl; outf_e << " UInt_t nbinboundaries = nbins+1;" << endl; outf_e << " UInt_t bin = 0;" << endl; outf_e << " for (uint i=0; i < nbinboundaries; ++i) {" << endl; outf_e << " if (i < nbinboundaries-1) {" << endl; outf_e << " if (value >= bins[i] && value < bins[i+1]) {" << endl; outf_e << " bin = i+1;" << endl; outf_e << " break;" << endl; outf_e << " }" << endl; outf_e << " } else if (i == nbinboundaries-1) {" << endl; outf_e << " if (value >= bins[i]) {" << endl; outf_e << " bin = nbinboundaries;" << endl; outf_e << " break;" << endl; outf_e << " }" << endl; outf_e << " } " << endl; outf_e << " }" << endl; outf_e << " return bin;" << endl; outf_e << "}" << endl; outf_e << endl; outf_e << endl; outf_e << "Double_t GetMuonResponseMeanPtEta(Double_t Pt, Double_t Eta) {" << endl; outf_e << endl; outf_e << " Double_t ptBins[" << NPtBins+1 << "] = {"; for (uint i=0; i < NPtBins+1; ++i) { outf_e << ptBins[i]; if (i < NPtBins) { outf_e << ","; } } outf_e << "};\n"; outf_e << " Double_t etaBins[" << NEtaBins+1 << "] = {"; for (uint i=0; i < NEtaBins+1; ++i) { outf_e << etaBins[i]; if (i < NEtaBins) { outf_e << ","; } } outf_e << "};\n"; outf_e << endl; outf_e << endl; outf_e << " Double_t ResponseMean[" << NPtBins+2 << "][" << NEtaBins+2 << "] = {"; outf_e << endl; for (uint i=0; i < NPtBins+2; ++i) { outf_e << " {"; for (uint j=0; j < NEtaBins+2; ++j) { outf_e << GaussParamArray_Muons_mean->GetBinContent(i,j); if (j< NEtaBins+1) { outf_e << ","; } } if (i< NPtBins+1) { outf_e << " },"; } else { outf_e << "}"; } outf_e << endl; } outf_e << " };" << endl; outf_e << endl; outf_e << endl; outf_e << " Int_t tmpPtBin = FindFakeMuonResponseBin( Pt , ptBins, " << NPtBins << ");" << endl; outf_e << " Int_t tmpEtaBin = FindFakeMuonResponseBin( Eta , etaBins, " << NEtaBins << ");" << endl; outf_e << " return ResponseMean[tmpPtBin][tmpEtaBin];" << endl; outf_e << "}" << endl; outf_e << endl; outf_e << endl; outf_e << "Double_t GetMuonResponseSigmaPtEta(Double_t Pt, Double_t Eta) {" << endl; outf_e << endl; outf_e << " Double_t ptBins[" << NPtBins+1 << "] = {"; for (uint i=0; i < NPtBins+1; ++i) { outf_e << ptBins[i]; if (i < NPtBins) { outf_e << ","; } } outf_e << "};\n"; outf_e << " Double_t etaBins[" << NEtaBins+1 << "] = {"; for (uint i=0; i < NEtaBins+1; ++i) { outf_e << etaBins[i]; if (i < NEtaBins) { outf_e << ","; } } outf_e << "};\n"; outf_e << endl; outf_e << endl; outf_e << " Double_t ResponseSigma[" << NPtBins+2 << "][" << NEtaBins+2 << "] = {"; outf_e << endl; for (uint i=0; i < NPtBins+2; ++i) { outf_e << " {"; for (uint j=0; j < NEtaBins+2; ++j) { outf_e << GaussParamArray_Muons_sigma->GetBinContent(i,j); if (j< NEtaBins+1) { outf_e << ","; } } if (i< NPtBins+1) { outf_e << " },"; } else { outf_e << "}"; } outf_e << endl; } outf_e << " };" << endl; outf_e << endl; outf_e << endl; outf_e << " Int_t tmpPtBin = FindFakeMuonResponseBin( Pt , ptBins, " << NPtBins << ");" << endl; outf_e << " Int_t tmpEtaBin = FindFakeMuonResponseBin( Eta , etaBins, " << NEtaBins << ");" << endl; outf_e << " return ResponseSigma[tmpPtBin][tmpEtaBin];" << endl; outf_e << "}" << endl; outf_e.close(); fileInput->Close(); delete fileInput; fileOutput->Close(); gBenchmark->Show("WWTemplate"); }