go-hep.org/x/hep@v0.38.1/fads/cmd/fads-app/main.go (about) 1 // Copyright ©2017 The go-hep Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // fads-app is a command that runs a simple ATLAS-like detector simulation, 6 // modelled after the C++ Delphes ATLAS data-card. 7 // 8 // Example: 9 // 10 // $> fads-app -help 11 // Usage: fads-app [options] <hepmc-input-file> 12 // 13 // ex: 14 // $ fads-app -l=INFO -evtmax=-1 ./testdata/hepmc.data 15 // 16 // options: 17 // -cpu-prof 18 // enable CPU profiling 19 // -evtmax int 20 // number of events to process (default -1) 21 // -l string 22 // log level (DEBUG|INFO|WARN|ERROR) (default "INFO") 23 // -nprocs int 24 // number of concurrent events to process (default -1) 25 // -o string 26 // name of output events file (default "data.rio") 27 // -trace string 28 // path to file where to store traces 29 // 30 // $> fads-app ./testdata/hepmc.data 31 // ::: fads-app... 32 // app INFO workers done: 1/4 33 // app INFO workers done: 2/4 34 // app INFO workers done: 3/4 35 // app INFO workers done: 4/4 36 // app INFO cpu: 340.092148ms 37 // app INFO mem: alloc: 17963 kB 38 // app INFO mem: tot-alloc: 35590 kB 39 // app INFO mem: n-mallocs: 55399 40 // app INFO mem: n-frees: 54777 41 // app INFO mem: gc-pauses: 2 ms 42 // ::: fads-app... [done] (time=343.533436ms) 43 package main 44 45 import ( 46 "flag" 47 "fmt" 48 "log" 49 "math" 50 "os" 51 "reflect" 52 "runtime/pprof" 53 "runtime/trace" 54 "time" 55 56 "go-hep.org/x/hep/fads" 57 "go-hep.org/x/hep/fastjet" 58 "go-hep.org/x/hep/fwk" 59 "go-hep.org/x/hep/fwk/job" 60 "go-hep.org/x/hep/fwk/rio" 61 "go-hep.org/x/hep/hepmc" 62 ) 63 64 var ( 65 lvl = flag.String("l", "INFO", "log level (DEBUG|INFO|WARN|ERROR)") 66 evtmax = flag.Int("evtmax", -1, "number of events to process") 67 nprocs = flag.Int("nprocs", -1, "number of concurrent events to process") 68 cpuprof = flag.Bool("cpu-prof", false, "enable CPU profiling") 69 ptrace = flag.String("trace", "", "path to file where to store traces") 70 output = flag.String("o", "data.rio", "name of output events file") 71 72 abs = math.Abs 73 sqrt = math.Sqrt 74 pow = math.Pow 75 tanh = math.Tanh 76 ) 77 78 func main() { 79 flag.Usage = func() { 80 fmt.Fprintf(os.Stderr, `Usage: fads-app [options] <hepmc-input-file> 81 82 ex: 83 $ fads-app -l=INFO -evtmax=-1 ./testdata/hepmc.data 84 85 options: 86 `, 87 ) 88 flag.PrintDefaults() 89 } 90 91 flag.Parse() 92 93 start := time.Now() 94 95 fmt.Printf("::: fads-app...\n") 96 if *cpuprof { 97 f, err := os.Create("cpu.prof") 98 if err != nil { 99 panic(err) 100 } 101 defer f.Close() 102 err = pprof.StartCPUProfile(f) 103 if err != nil { 104 log.Fatalf("could not start CPU profile: %+v", err) 105 } 106 defer pprof.StopCPUProfile() 107 } 108 109 if *ptrace != "" { 110 f, err := os.Create(*ptrace) 111 if err != nil { 112 log.Fatalf( 113 "error creating trace-file [%s]: %v\n", 114 *ptrace, 115 err, 116 ) 117 } 118 defer f.Close() 119 err = trace.Start(f) 120 if err != nil { 121 log.Fatalf( 122 "error starting runtime/trace: %v\n", 123 err, 124 ) 125 } 126 defer trace.Stop() 127 } 128 129 app := job.New(job.P{ 130 "EvtMax": int64(*evtmax), 131 "NProcs": *nprocs, 132 "MsgLevel": job.MsgLevel(*lvl), 133 }) 134 135 // propagate particles in cylinder 136 app.Create(job.C{ 137 Type: "go-hep.org/x/hep/fads.Propagator", 138 Name: "pprop", 139 Props: job.P{ 140 "Input": "/fads/StableParticles", 141 "Output": "/fads/pprop/StableParticles", 142 "ChargedHadrons": "/fads/pprop/ChargedHadrons", 143 "Electrons": "/fads/pprop/Electrons", 144 "Muons": "/fads/pprop/Muons", 145 146 // radius of the magnetic field coverage, in meters 147 "Radius": 1.15, 148 // half-length of the magnetic field coverage, in meters 149 "HalfLength": 3.51, 150 // magnetic field 151 "Bz": 2.0, 152 }, 153 }) 154 155 input := "testdata/hepmc.data" 156 //input := "testdata/full.hepmc.data" 157 if flag.NArg() > 0 { 158 input = flag.Arg(0) 159 } 160 161 // read HepMC data 162 app.Create(job.C{ 163 Type: "go-hep.org/x/hep/fwk.InputStream", 164 Name: "hepmc-streamer", 165 Props: job.P{ 166 "Ports": []fwk.Port{ 167 { 168 Name: "/fads/McEvent", 169 Type: reflect.TypeOf(hepmc.Event{}), 170 }, 171 }, 172 "Streamer": &fads.HepMcStreamer{ 173 Name: input, 174 }, 175 }, 176 }) 177 178 // transform HepMC data into fads collection 179 app.Create(job.C{ 180 Type: "go-hep.org/x/hep/fads.HepMcReader", 181 Name: "hepmcreader", 182 Props: job.P{ 183 "Input": "/fads/McEvent", 184 }, 185 }) 186 187 // charged hadron tracking efficiency 188 app.Create(job.C{ 189 Type: "go-hep.org/x/hep/fads.Efficiency", 190 Name: "charged-hadron-trk-eff", 191 Props: job.P{ 192 "Input": "/fads/pprop/ChargedHadrons", 193 "Output": "/fads/charged-hadron-trk-eff/ChargedHadrons", 194 "Eff": func(eta, pt float64) float64 { 195 switch { 196 case (pt <= 0.1): 197 return (0.00) 198 case (math.Abs(eta) <= 1.5) && (pt > 0.1 && pt <= 1.0): 199 return (0.70) 200 case (math.Abs(eta) <= 1.5) && (pt > 1.0): 201 return (0.95) 202 case (math.Abs(eta) > 1.5 && math.Abs(eta) <= 2.5) && (pt > 0.1 && pt <= 1.0): 203 return (0.60) 204 case (math.Abs(eta) > 1.5 && math.Abs(eta) <= 2.5) && (pt > 1.0): 205 return (0.85) 206 case (math.Abs(eta) > 2.5): 207 return (0.00) 208 } 209 210 return 0 211 }, 212 }, 213 }) 214 215 // electron tracking efficiency 216 app.Create(job.C{ 217 Type: "go-hep.org/x/hep/fads.Efficiency", 218 Name: "electron-trk-eff", 219 Props: job.P{ 220 "Input": "/fads/pprop/Electrons", 221 "Output": "/fads/electron-trk-eff/Electrons", 222 "Eff": func(eta, pt float64) float64 { 223 switch { 224 case pt <= 0.1: 225 return 0 226 case math.Abs(eta) <= 1.5 && (pt > 0.1 && pt <= 1.0): 227 return 0.70 228 case math.Abs(eta) <= 1.5 && (pt > 1.0 && pt <= 100): 229 return 0.95 230 case (math.Abs(eta) <= 1.5) && (pt > 100): 231 return 0.99 232 case (math.Abs(eta) > 1.5 && math.Abs(eta) <= 2.5) && (pt > 0.1 && pt <= 1.0): 233 return 0.50 234 case (math.Abs(eta) > 1.5 && math.Abs(eta) <= 2.5) && (pt > 1.0 && pt <= 100): 235 return 0.83 236 case (math.Abs(eta) > 1.5 && math.Abs(eta) <= 2.5) && (pt > 100): 237 return 0.90 238 case (math.Abs(eta) > 2.5): 239 return 0 240 } 241 242 return 0 243 }, 244 }, 245 }) 246 247 // muon tracking efficiency 248 app.Create(job.C{ 249 Type: "go-hep.org/x/hep/fads.Efficiency", 250 Name: "muon-trk-eff", 251 Props: job.P{ 252 "Input": "/fads/pprop/Muons", 253 "Output": "/fads/muon-trk-eff/Muons", 254 "Eff": func(eta, pt float64) float64 { 255 switch { 256 case (pt <= 0.1): 257 return 0.00 258 case (math.Abs(eta) <= 1.5) && (pt > 0.1 && pt <= 1.0): 259 return (0.75) 260 case (math.Abs(eta) <= 1.5) && (pt > 1.0): 261 return (0.99) 262 case (math.Abs(eta) > 1.5 && math.Abs(eta) <= 2.5) && (pt > 0.1 && pt <= 1.0): 263 return (0.70) 264 case (math.Abs(eta) > 1.5 && math.Abs(eta) <= 2.5) && (pt > 1.0): 265 return (0.98) 266 case (math.Abs(eta) > 2.5): 267 return (0.00) 268 } 269 270 return 0 271 }, 272 }, 273 }) 274 275 // momentum resolution for charged tracks 276 app.Create(job.C{ 277 Type: "go-hep.org/x/hep/fads.MomentumSmearing", 278 Name: "charged-hadron-mom-smearing", 279 Props: job.P{ 280 "Input": "/fads/charged-hadron-trk-eff/ChargedHadrons", 281 "Output": "/fads/charged-hadron-mom-smearing/ChargedHadrons", 282 "Resolution": func(eta, pt float64) float64 { 283 switch { 284 case (abs(eta) <= 1.5) && (pt > 0.1 && pt <= 1.0): 285 return 0.02 286 case (abs(eta) <= 1.5) && (pt > 1.0 && pt <= 1.0e1): 287 return (0.01) 288 case (abs(eta) <= 1.5) && (pt > 1.0e1 && pt <= 2.0e2): 289 return (0.03) 290 case (abs(eta) <= 1.5) && (pt > 2.0e2): 291 return (0.05) 292 case (abs(eta) > 1.5 && abs(eta) <= 2.5) && (pt > 0.1 && pt <= 1.0): 293 return (0.03) 294 case (abs(eta) > 1.5 && abs(eta) <= 2.5) && (pt > 1.0 && pt <= 1.0e1): 295 return (0.02) 296 case (abs(eta) > 1.5 && abs(eta) <= 2.5) && (pt > 1.0e1 && pt <= 2.0e2): 297 return (0.04) 298 case (abs(eta) > 1.5 && abs(eta) <= 2.5) && (pt > 2.0e2): 299 return (0.05) 300 } 301 return 0 302 }, 303 }, 304 }) 305 306 // energy resolution for electrons 307 app.Create(job.C{ 308 Type: "go-hep.org/x/hep/fads.EnergySmearing", 309 Name: "electron-ene-smearing", 310 Props: job.P{ 311 "Input": "/fads/electron-trk-eff/Electrons", 312 "Output": "/fads/electron-ene-smearing/Electrons", 313 "Resolution": func(eta, ene float64) float64 { 314 switch { 315 case (abs(eta) <= 2.5) && (ene > 0.1 && ene <= 2.5e1): 316 return (ene * 0.015) 317 case (abs(eta) <= 2.5) && (ene > 2.5e1): 318 return sqrt(pow(ene*0.005, 2) + ene*pow(0.05, 2) + pow(0.25, 2)) 319 case (abs(eta) > 2.5 && abs(eta) <= 3.0): 320 return sqrt(pow(ene*0.005, 2) + ene*pow(0.05, 2) + pow(0.25, 2)) 321 case (abs(eta) > 3.0 && abs(eta) <= 5.0): 322 return sqrt(pow(ene*0.107, 2) + ene*pow(2.08, 2)) 323 } 324 325 return 0 326 }, 327 }, 328 }) 329 330 // momentum resolution for muons 331 app.Create(job.C{ 332 Type: "go-hep.org/x/hep/fads.MomentumSmearing", 333 Name: "muon-mom-smearing", 334 Props: job.P{ 335 "Input": "/fads/muon-trk-eff/Muons", 336 "Output": "/fads/muon-mom-smearing/Muons", 337 "Resolution": func(eta, pt float64) float64 { 338 switch { 339 case (abs(eta) <= 1.5) && (pt > 0.1 && pt <= 1.0): 340 return (0.03) 341 case (abs(eta) <= 1.5) && (pt > 1.0 && pt <= 5.0e1): 342 return (0.03) 343 case (abs(eta) <= 1.5) && (pt > 5.0e1 && pt <= 1.0e2): 344 return (0.04) 345 case (abs(eta) <= 1.5) && (pt > 1.0e2): 346 return (0.07) 347 case (abs(eta) > 1.5 && abs(eta) <= 2.5) && (pt > 0.1 && pt <= 1.0): 348 return (0.04) 349 case (abs(eta) > 1.5 && abs(eta) <= 2.5) && (pt > 1.0 && pt <= 5.0e1): 350 return (0.04) 351 case (abs(eta) > 1.5 && abs(eta) <= 2.5) && (pt > 5.0e1 && pt <= 1.0e2): 352 return (0.05) 353 case (abs(eta) > 1.5 && abs(eta) <= 2.5) && (pt > 1.0e2): 354 return (0.10) 355 } 356 return 0 357 }, 358 }, 359 }) 360 361 // track merger 362 app.Create(job.C{ 363 Type: "go-hep.org/x/hep/fads.Merger", 364 Name: "track-merger", 365 Props: job.P{ 366 "Inputs": []string{ 367 "/fads/charged-hadron-mom-smearing/ChargedHadrons", 368 "/fads/electron-ene-smearing/Electrons", 369 "/fads/muon-mom-smearing/Muons", 370 }, 371 "Output": "/fads/track-merger/tracks", 372 "MomentumOutput": "/fads/track-merger/momentum", 373 "EnergyOutput": "/fads/track-merger/energy", 374 }, 375 }) 376 377 phi10 := make([]float64, 0, 37) 378 for i := -18; i <= 18; i++ { 379 phi10 = append(phi10, float64(i)*math.Pi/18.0) 380 } 381 382 phi20 := make([]float64, 0, 19) 383 for i := -9; i <= 9; i++ { 384 phi20 = append(phi20, float64(i)*math.Pi/9.0) 385 } 386 387 // calorimeter 388 app.Create(job.C{ 389 Type: "go-hep.org/x/hep/fads.Calorimeter", 390 Name: "calo", 391 Props: job.P{ 392 "Particles": "/fads/pprop/StableParticles", 393 "Tracks": "/fads/track-merger/tracks", 394 "Towers": "/fads/calo/towers", 395 "Photons": "/fads/calo/photons", 396 "EFlowTracks": "/fads/calo/eflowtracks", 397 "EFlowTowers": "/fads/calo/eflowtowers", 398 399 "EtaPhiBins": fads.NewEtaPhiGrid( 400 []fads.EtaPhiBin{ 401 // 10-degrees towers: 0 <= |eta| <= 3.2 402 { 403 EtaBins: []float64{ 404 -3.2, 405 -2.5, -2.4, -2.3, -2.2, -2.1, -2.0, 406 -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, 407 -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1, +0.0, 408 +0.1, +0.2, +0.3, +0.4, +0.5, +0.6, +0.7, +0.8, +0.9, 409 +1.0, +1.1, +1.2, +1.3, +1.4, +1.5, +1.6, +1.7, +1.8, +1.9, 410 +2.0, +2.1, +2.2, +2.3, +2.4, +2.5, +2.6, 411 +3.3, 412 }, 413 PhiBins: phi10, 414 }, 415 416 // 20-degrees towers: 2.8 <= |eta| <= 4.9 417 { 418 EtaBins: []float64{ 419 -4.9, -4.7, -4.5, -4.3, -4.1, 420 -3.9, -3.7, -3.5, -3.3, -3.0, 421 -2.8, -2.6, 422 +2.8, +3.0, +3.2, +3.5, +3.7, +3.9, 423 +4.1, +4.3, +4.5, +4.7, +4.9, 424 }, 425 PhiBins: phi20, 426 }, 427 }, 428 ), 429 430 // default energy fractions: abs(pid) -> {ECal, HCal} 431 "EnergyFraction": map[int]fads.EneFrac{ 432 0: { 433 ECal: 0, 434 HCal: 1, 435 }, 436 // energy fractions for ele,gamma and pi0 437 11: {ECal: 1, HCal: 0}, 438 22: {ECal: 1, HCal: 0}, 439 111: {ECal: 1, HCal: 0}, 440 // energy fractions for muons, neutrinos and neutralinos 441 12: {ECal: 0.0, HCal: 0.0}, 442 13: {ECal: 0.0, HCal: 0.0}, 443 14: {ECal: 0.0, HCal: 0.0}, 444 16: {ECal: 0.0, HCal: 0.0}, 445 1000022: {ECal: 0.0, HCal: 0.0}, 446 1000023: {ECal: 0.0, HCal: 0.0}, 447 1000025: {ECal: 0.0, HCal: 0.0}, 448 1000035: {ECal: 0.0, HCal: 0.0}, 449 1000045: {ECal: 0.0, HCal: 0.0}, 450 // energy fractions for K0short and Lambda 451 310: {ECal: 0.3, HCal: 0.7}, 452 3122: {ECal: 0.3, HCal: 0.7}, 453 }, 454 455 // ecal resolution (eta and energy) 456 // http://arxiv.org/pdf/physics/0608012v1 jinst8_08_s08003 457 // http://villaolmo.mib.infn.it/ICATPP9th_2005/Calorimetry/Schram.p.pdf 458 // http://www.physics.utoronto.ca/~krieger/procs/ComoProceedings.pdf 459 "ECalResolution": func(eta, ene float64) float64 { 460 switch { 461 case (abs(eta) <= 3.2): 462 return sqrt(pow(ene, 2)*pow(0.0017, 2) + ene*pow(0.101, 2)) 463 464 case (abs(eta) > 3.2 && abs(eta) <= 4.9): 465 return sqrt(pow(ene, 2)*pow(0.0350, 2) + ene*pow(0.285, 2)) 466 } 467 return 0 468 }, 469 470 // hcal resolution (eta and energy) 471 // http://arxiv.org/pdf/hep-ex/0004009v1 472 // http://villaolmo.mib.infn.it/ICATPP9th_2005/Calorimetry/Schram.p.pdf 473 "HCalResolution": func(eta, ene float64) float64 { 474 switch { 475 case (abs(eta) <= 1.7): 476 return sqrt(pow(ene, 2)*pow(0.0302, 2) + ene*pow(0.5205, 2) + pow(1.59, 2)) 477 case (abs(eta) > 1.7 && abs(eta) <= 3.2): 478 return sqrt(pow(ene, 2)*pow(0.0500, 2) + ene*pow(0.706, 2)) 479 case (abs(eta) > 3.2 && abs(eta) <= 4.9): 480 return sqrt(pow(ene, 2)*pow(0.9420, 2) + ene*pow(0.075, 2)) 481 } 482 return 0 483 }, 484 }, 485 }) 486 487 // eflow merger 488 app.Create(job.C{ 489 Type: "go-hep.org/x/hep/fads.Merger", 490 Name: "eflow-merger", 491 Props: job.P{ 492 "Inputs": []string{ 493 "/fads/calo/eflowtracks", 494 "/fads/calo/eflowtowers", 495 }, 496 "Output": "/fads/eflow-merger/eflow", 497 "MomentumOutput": "/fads/eflow-merger/momentum", 498 "EnergyOutput": "/fads/eflow-merger/energy", 499 }, 500 }) 501 502 // photon efficiency 503 app.Create(job.C{ 504 Type: "go-hep.org/x/hep/fads.Efficiency", 505 Name: "photon-eff", 506 Props: job.P{ 507 "Input": "/fads/calo/photons", 508 "Output": "/fads/photon-eff/photons", 509 "Eff": func(eta, pt float64) float64 { 510 switch { 511 case (pt <= 10.0): 512 return 0.00 513 case (abs(eta) <= 1.5) && (pt > 10.0): 514 return 0.95 515 case (abs(eta) > 1.5 && abs(eta) <= 2.5) && (pt > 10.0): 516 return 0.85 517 case (abs(eta) > 2.5): 518 return 0.00 519 } 520 521 return 0 522 }, 523 }, 524 }) 525 526 // photon isolation 527 app.Create(job.C{ 528 Type: "go-hep.org/x/hep/fads.Isolation", 529 Name: "photon-iso", 530 Props: job.P{ 531 "Candidates": "/fads/photon-eff/photons", 532 "Isolations": "/fads/eflow-merger/eflow", 533 "Output": "/fads/photon-iso/photons", 534 535 "DeltaRMax": 0.5, 536 "PtMin": 0.5, 537 "PtRatioMax": 0.1, 538 }, 539 }) 540 541 // electron efficiency 542 app.Create(job.C{ 543 Type: "go-hep.org/x/hep/fads.Efficiency", 544 Name: "electron-eff", 545 Props: job.P{ 546 "Input": "/fads/electron-ene-smearing/Electrons", 547 "Output": "/fads/electron-eff/electrons", 548 "Eff": func(eta, pt float64) float64 { 549 switch { 550 case (pt <= 10.0): 551 return (0.00) 552 case (abs(eta) <= 1.5) && (pt > 10.0): 553 return (0.95) 554 case (abs(eta) > 1.5 && abs(eta) <= 2.5) && (pt > 10.0): 555 return (0.85) 556 case (abs(eta) > 2.5): 557 return (0.00) 558 } 559 return 0 560 }, 561 }, 562 }) 563 564 // electron isolation 565 app.Create(job.C{ 566 Type: "go-hep.org/x/hep/fads.Isolation", 567 Name: "electron-iso", 568 Props: job.P{ 569 "Candidates": "/fads/electron-eff/electrons", 570 "Isolations": "/fads/eflow-merger/eflow", 571 "Output": "/fads/electron-iso/electrons", 572 573 "DeltaRMax": 0.5, 574 "PtMin": 0.5, 575 "PtRatioMax": 0.1, 576 }, 577 }) 578 579 // muon efficiency 580 app.Create(job.C{ 581 Type: "go-hep.org/x/hep/fads.Efficiency", 582 Name: "muon-eff", 583 Props: job.P{ 584 "Input": "/fads/muon-mom-smearing/Muons", 585 "Output": "/fads/muon-eff/muons", 586 "Eff": func(eta, pt float64) float64 { 587 switch { 588 case (pt <= 10.0): 589 return (0.00) 590 case (abs(eta) <= 1.5) && (pt > 10.0): 591 return (0.95) 592 case (abs(eta) > 1.5 && abs(eta) <= 2.7) && (pt > 10.0): 593 return (0.85) 594 case (abs(eta) > 2.7): 595 return (0.00) 596 } 597 return 0 598 }, 599 }, 600 }) 601 602 // muon isolation 603 app.Create(job.C{ 604 Type: "go-hep.org/x/hep/fads.Isolation", 605 Name: "muon-iso", 606 Props: job.P{ 607 "Candidates": "/fads/muon-eff/muons", 608 "Isolations": "/fads/eflow-merger/eflow", 609 "Output": "/fads/muon-iso/muons", 610 611 "DeltaRMax": 0.5, 612 "PtMin": 0.5, 613 "PtRatioMax": 0.1, 614 }, 615 }) 616 617 // missing-et merger 618 app.Create(job.C{ 619 Type: "go-hep.org/x/hep/fads.Merger", 620 Name: "missing-et", 621 Props: job.P{ 622 "Inputs": []string{ 623 "/fads/calo/eflowtracks", 624 "/fads/calo/eflowtowers", 625 }, 626 "Output": "/fads/missing-et", 627 "MomentumOutput": "/fads/missing-et/momentum", 628 "EnergyOutput": "/fads/missing-et/energy", 629 }, 630 }) 631 632 // mc truth jet finder 633 app.Create(job.C{ 634 Type: "go-hep.org/x/hep/fads.FastJetFinder", 635 Name: "mc-jet-finder", 636 Props: job.P{ 637 "Input": "/fads/StableParticles", 638 "Output": "/fads/mc-jet-finder/jets", 639 "Rho": "/fads/mc-jet-finder/rho", 640 641 "JetAlgorithm": fastjet.AntiKtAlgorithm, 642 "ParameterR": 0.6, 643 644 "JetPtMin": 20.0, 645 }, 646 }) 647 648 // jet finder 649 app.Create(job.C{ 650 Type: "go-hep.org/x/hep/fads.FastJetFinder", 651 Name: "fastjet-finder", 652 Props: job.P{ 653 "Input": "/fads/calo/towers", 654 "Output": "/fads/fastjet-finder/jets", 655 "Rho": "/fads/fastjet-finder/rho", 656 657 "JetAlgorithm": fastjet.AntiKtAlgorithm, 658 "ParameterR": 0.6, 659 660 "JetPtMin": 20.0, 661 }, 662 }) 663 664 // jet energy scale 665 app.Create(job.C{ 666 Type: "go-hep.org/x/hep/fads.EnergyScale", 667 Name: "jet-ene-scale", 668 Props: job.P{ 669 "Input": "/fads/fastjet-finder/jets", 670 "Output": "/fads/jet-ene-scale/jets", 671 "Scale": func(eta, pt float64) float64 { return 1.08 }, 672 }, 673 }) 674 675 // b-tagging 676 app.Create(job.C{ 677 Type: "go-hep.org/x/hep/fads.BTagging", 678 Name: "btag", 679 Props: job.P{ 680 "Partons": "/fads/Partons", 681 "Jets": "/fads/jet-ene-scale/jets", 682 "Output": "/fads/btag/jets", 683 684 "BitNumber": uint(0), 685 "DeltaR": 0.5, 686 "PartonPtMin": 1.0, 687 "PartonEtaMax": 2.5, 688 689 // efficiency formula: [pdg-code] -> (pt,eta) 690 // pdg-code: the highest PDG code of a quark or gluon inside a DeltaR-cone 691 // around the jet axis 692 // gluon's pdg-code has the lowest priority. 693 "Eff": map[int]func(pt, eta float64) float64{ 694 // default efficiency (mis-identification rate) 695 0: func(pt, eta float64) float64 { return 0.001 }, 696 697 // efficiency for c-jets (mis-identification rate) 698 4: func(pt, eta float64) float64 { 699 switch { 700 case pt <= 15.0: 701 return (0.000) 702 703 case (abs(eta) <= 1.2) && (pt > 15.0): 704 return (0.2 * tanh(pt*0.03-0.4)) 705 706 case (abs(eta) > 1.2 && abs(eta) <= 2.5) && (pt > 15.0): 707 return (0.1 * tanh(pt*0.03-0.4)) 708 709 case (abs(eta) > 2.5): 710 return (0.000) 711 } 712 return 0 713 }, 714 715 // efficiency for b-jets 716 5: func(pt, eta float64) float64 { 717 switch { 718 case (pt <= 15.0): 719 return (0.000) 720 case (abs(eta) <= 1.2) && (pt > 15.0): 721 return (0.5 * tanh(pt*0.03-0.4)) 722 case (abs(eta) > 1.2 && abs(eta) <= 2.5) && (pt > 15.0): 723 return (0.4 * tanh(pt*0.03-0.4)) 724 case (abs(eta) > 2.5): 725 return (0.000) 726 } 727 return 0 728 }, 729 }, 730 }, 731 }) 732 733 // tau-tagging 734 app.Create(job.C{ 735 Type: "go-hep.org/x/hep/fads.TauTagging", 736 Name: "tau-tag", 737 Props: job.P{ 738 "Particles": "/fads/AllParticles", 739 "Partons": "/fads/Partons", 740 "Jets": "/fads/btag/jets", 741 "Output": "/fads/tau-tag/jets", 742 743 "DeltaR": 0.5, 744 "TauPtMin": 1.0, 745 "TauEtaMax": 2.5, 746 747 // efficiency formula: [pdg-code] -> (pt,eta) 748 "Eff": map[int]func(pt, eta float64) float64{ 749 // default efficiency (mis-identification rate) 750 0: func(pt, eta float64) float64 { return 0.001 }, 751 752 // efficiency for tau-jets 753 15: func(pt, eta float64) float64 { return 0.4 }, 754 }, 755 }, 756 }) 757 758 // find uniquely identified photons/electrons/taus/jets 759 app.Create(job.C{ 760 Type: "go-hep.org/x/hep/fads.UniqueObjectFinder", 761 Name: "uobj-finder", 762 Props: job.P{ 763 "Keys": []fads.ObjPair{ 764 { 765 In: "/fads/photon-iso/photons", 766 Out: "/fads/uobj-finder/photons", 767 }, 768 { 769 In: "/fads/electron-iso/electrons", 770 Out: "/fads/uobj-finder/electrons", 771 }, 772 { 773 In: "/fads/muon-iso/muons", 774 Out: "/fads/uobj-finder/muons", 775 }, 776 { 777 In: "/fads/tau-tag/jets", 778 Out: "/fads/uobj-finder/jets", 779 }, 780 }, 781 }, 782 }) 783 784 // scalar HT merger 785 app.Create(job.C{ 786 Type: "go-hep.org/x/hep/fads.Merger", 787 Name: "scalar-ht", 788 Props: job.P{ 789 "Inputs": []string{ 790 "/fads/uobj-finder/jets", 791 "/fads/uobj-finder/electrons", 792 "/fads/uobj-finder/photons", 793 "/fads/uobj-finder/muons", 794 }, 795 "Output": "/fads/scalar-ht", 796 "MomentumOutput": "/fads/scalar-ht/momentum", 797 "EnergyOutput": "/fads/scalar-ht/energy", 798 }, 799 }) 800 801 // output 802 app.Create(job.C{ 803 Type: "go-hep.org/x/hep/fwk.OutputStream", 804 Name: "rio-output", 805 Props: job.P{ 806 "Ports": []fwk.Port{ 807 { 808 Name: "/fads/McEvent", 809 Type: reflect.TypeOf(hepmc.Event{}), 810 }, 811 { 812 Name: "/fads/uobj-finder/jets", 813 Type: reflect.TypeOf([]fads.Candidate{}), 814 }, 815 { 816 Name: "/fads/uobj-finder/electrons", 817 Type: reflect.TypeOf([]fads.Candidate{}), 818 }, 819 { 820 Name: "/fads/uobj-finder/photons", 821 Type: reflect.TypeOf([]fads.Candidate{}), 822 }, 823 { 824 Name: "/fads/uobj-finder/muons", 825 Type: reflect.TypeOf([]fads.Candidate{}), 826 }, 827 }, 828 "Streamer": &rio.OutputStreamer{ 829 Name: *output, 830 }, 831 }, 832 }) 833 834 app.Run() 835 fmt.Printf("::: fads-app... [done] (time=%v)\n", time.Since(start)) 836 }