Commit 56501d1eec6814ec9e4a9bb644d6a534c09981fa
1 parent
e6c90a83
Correct sensitivity computation in cssens and show proper column in show_sensitivity.py.
Showing
3 changed files
with
75 additions
and
75 deletions
examples/show_sensitivity.py
| ... | ... | @@ -99,7 +99,7 @@ def show_sensitivity(sensitivity, filename): |
| 99 | 99 | plt.grid() |
| 100 | 100 | |
| 101 | 101 | # Show differential sensitivity |
| 102 | - plt.plot(sensitivity['energy'], sensitivity['eflux'], 'ro-') | |
| 102 | + plt.plot(sensitivity['energy'], sensitivity['sensitivity'], 'ro-') | |
| 103 | 103 | |
| 104 | 104 | # Set labels |
| 105 | 105 | plt.xlabel("Energy (TeV)") | ... | ... |
pyext/ctools/obsutils.py
| ... | ... | @@ -26,7 +26,7 @@ import math |
| 26 | 26 | # ===================== # |
| 27 | 27 | # Simulate observations # |
| 28 | 28 | # ===================== # |
| 29 | -def sim(obs, log=False, debug=False, edisp=False, seed=0, nbins=0, | |
| 29 | +def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, nbins=0, | |
| 30 | 30 | binsz=0.05, npix=200, proj="TAN", coord="GAL"): |
| 31 | 31 | """ |
| 32 | 32 | Simulate events for all observations in the container. |
| ... | ... | @@ -55,6 +55,9 @@ def sim(obs, log=False, debug=False, edisp=False, seed=0, nbins=0, |
| 55 | 55 | # Optionally switch-on debugging model |
| 56 | 56 | if debug: |
| 57 | 57 | sim["debug"].boolean(True) |
| 58 | + | |
| 59 | + # Set chatter level | |
| 60 | + sim["chatter"].chatter = chatter | |
| 58 | 61 | |
| 59 | 62 | # Run ctobssim application. This will loop over all observations in the |
| 60 | 63 | # container and simulation the events for each observation. Note that |
| ... | ... | @@ -101,6 +104,9 @@ def sim(obs, log=False, debug=False, edisp=False, seed=0, nbins=0, |
| 101 | 104 | if debug: |
| 102 | 105 | bin["debug"].boolean(True) |
| 103 | 106 | |
| 107 | + # Set chatter level | |
| 108 | + bin["chatter"].chatter = chatter | |
| 109 | + | |
| 104 | 110 | # Run ctbin application. This will loop over all observations in |
| 105 | 111 | # the container and bin the events in counts maps |
| 106 | 112 | bin.run() |
| ... | ... | @@ -127,7 +133,7 @@ def sim(obs, log=False, debug=False, edisp=False, seed=0, nbins=0, |
| 127 | 133 | # ================ # |
| 128 | 134 | # Fit observations # |
| 129 | 135 | # ================ # |
| 130 | -def fit(obs, log=False, debug=False, edisp=False): | |
| 136 | +def fit(obs, log=False, debug=False, chatter=2, edisp=False): | |
| 131 | 137 | """ |
| 132 | 138 | Perform maximum likelihood fitting of observations in the container. |
| 133 | 139 | |
| ... | ... | @@ -148,6 +154,9 @@ def fit(obs, log=False, debug=False, edisp=False): |
| 148 | 154 | # Optionally switch-on debugging model |
| 149 | 155 | if debug: |
| 150 | 156 | like["debug"].boolean(True) |
| 157 | + | |
| 158 | + # Set chatter level | |
| 159 | + like["chatter"].chatter = chatter | |
| 151 | 160 | |
| 152 | 161 | # Optionally apply energy dispersion |
| 153 | 162 | like["edisp"].boolean(edisp) | ... | ... |
scripts/cssens.py
| ... | ... | @@ -200,7 +200,8 @@ class cssens(ctools.cscript): |
| 200 | 200 | self.log("\n") |
| 201 | 201 | |
| 202 | 202 | # Initialise script |
| 203 | - colnames = ['loge', 'emin', 'emax', 'crab', 'pflux', 'eflux', 'diffSens'] | |
| 203 | + colnames = ['loge', 'emin', 'emax', 'crab_flux', 'photon_flux', \ | |
| 204 | + 'energy_flux', 'sensitivity'] | |
| 204 | 205 | results = [] |
| 205 | 206 | |
| 206 | 207 | # Initialise models |
| ... | ... | @@ -412,18 +413,10 @@ class cssens(ctools.cscript): |
| 412 | 413 | # Set energy boundaries |
| 413 | 414 | self.set_obs_ebounds(emin, emax) |
| 414 | 415 | |
| 415 | - # Determine energy boundaries from first observation in | |
| 416 | - # the container | |
| 417 | - #for run in obs: | |
| 418 | - # emin = run.events().ebounds().emin() | |
| 419 | - # emax = run.events().ebounds().emax() | |
| 420 | - # loge = math.log10(math.sqrt(emin.TeV()*emax.TeV())) | |
| 421 | - # erg_mean = math.pow(10.0, loge) * tev2erg | |
| 422 | - # erg_width = (emax.TeV()-emin.TeV()) * tev2erg | |
| 423 | - # break | |
| 416 | + # Determine energy boundaries from first observation in the container | |
| 424 | 417 | loge = math.log10(math.sqrt(emin.TeV()*emax.TeV())) |
| 425 | - erg_mean = math.pow(10.0, loge) * tev2erg | |
| 426 | - erg_width = (emax.TeV()-emin.TeV()) * tev2erg | |
| 418 | + e_mean = math.pow(10.0, loge) | |
| 419 | + erg_mean = e_mean * tev2erg | |
| 427 | 420 | |
| 428 | 421 | # Compute Crab unit (this is the factor with which the Prefactor needs |
| 429 | 422 | # to be multiplied to get 1 Crab |
| ... | ... | @@ -446,12 +439,12 @@ class cssens(ctools.cscript): |
| 446 | 439 | self.log("\n") |
| 447 | 440 | |
| 448 | 441 | # Initialise loop |
| 449 | - flux_value = [] | |
| 450 | - pflux_value = [] | |
| 451 | - eflux_value = [] | |
| 452 | - diffSens_value = [] | |
| 453 | - iter = 0 | |
| 454 | - test_cflux = 0.1 # This is the initial test flux in Crab units (100 mCrab) | |
| 442 | + crab_flux_value = [] | |
| 443 | + photon_flux_value = [] | |
| 444 | + energy_flux_value = [] | |
| 445 | + sensitivity_value = [] | |
| 446 | + iter = 0 | |
| 447 | + test_crab_flux = 0.1 # Initial test flux in Crab units (100 mCrab) | |
| 455 | 448 | |
| 456 | 449 | # Loop until we break |
| 457 | 450 | while True: |
| ... | ... | @@ -463,13 +456,13 @@ class cssens(ctools.cscript): |
| 463 | 456 | if self.logExplicit(): |
| 464 | 457 | self.log.header2("Iteration "+str(iter)) |
| 465 | 458 | |
| 466 | - # Set test flux | |
| 459 | + # Set source model. crab_prefactor is the Prefactor that | |
| 460 | + # corresponds to 1 Crab | |
| 467 | 461 | src_model = full_model.copy() |
| 468 | 462 | crab_prefactor = src_model[self.m_srcname]['Prefactor'].value() * crab_unit |
| 469 | - src_model[self.m_srcname]['Prefactor'].value(crab_prefactor * test_cflux) | |
| 463 | + src_model[self.m_srcname]['Prefactor'].value(crab_prefactor * test_crab_flux) | |
| 470 | 464 | obs.models(src_model) |
| 471 | 465 | |
| 472 | - | |
| 473 | 466 | # Simulate events |
| 474 | 467 | sim = obsutils.sim(obs, nbins=self.m_enumbins, seed=iter, \ |
| 475 | 468 | binsz=self.m_binsz, npix=self.m_npix, \ |
| ... | ... | @@ -572,48 +565,45 @@ class cssens(ctools.cscript): |
| 572 | 565 | continue |
| 573 | 566 | |
| 574 | 567 | # Get fitted Crab, photon and energy fluxes |
| 575 | - cflux = result_all[self.m_srcname]['Prefactor'].value() / crab_prefactor | |
| 576 | - cflux_err = result_all[self.m_srcname]['Prefactor'].error() / crab_prefactor | |
| 577 | - pflux = result_all[self.m_srcname].spectral().flux(emin, emax) | |
| 578 | - eflux = result_all[self.m_srcname].spectral().eflux(emin, emax) | |
| 568 | + crab_flux = result_all[self.m_srcname]['Prefactor'].value() / crab_prefactor | |
| 569 | + crab_flux_err = result_all[self.m_srcname]['Prefactor'].error() / crab_prefactor | |
| 570 | + photon_flux = result_all[self.m_srcname].spectral().flux(emin, emax) | |
| 571 | + energy_flux = result_all[self.m_srcname].spectral().eflux(emin, emax) | |
| 579 | 572 | |
| 580 | - # Compute differential sensitivity | |
| 581 | - diffSens = pflux / erg_width * erg_mean*erg_mean | |
| 573 | + # Compute differential sensitivity in unit erg/cm2/s | |
| 574 | + energy = gammalib.GEnergy(e_mean, "TeV") | |
| 575 | + time = gammalib.GTime() | |
| 576 | + sensitivity = result_all[self.m_srcname].spectral().eval(energy, time) * \ | |
| 577 | + erg_mean*erg_mean * 1.0e6 | |
| 582 | 578 | |
| 583 | 579 | # Compute flux correction factor based on average TS |
| 584 | 580 | correct = 1.0 |
| 585 | 581 | if ts > 0: |
| 586 | 582 | correct = math.sqrt(self.m_ts_thres/ts) |
| 587 | - #if self.m_use_ts: | |
| 588 | - # if ts > 0: | |
| 589 | - # correct = math.sqrt(self.m_ts_thres/ts) | |
| 590 | - #else: | |
| 591 | - # if cflux > 0 and cflux_err > 0: | |
| 592 | - # correct = math.sqrt(self.m_ts_thres)/(cflux/cflux_err) | |
| 593 | 583 | |
| 594 | 584 | # Compute extrapolated fluxes |
| 595 | - flux = correct * cflux | |
| 596 | - pflux = correct * pflux | |
| 597 | - eflux = correct * eflux | |
| 598 | - diffSens = correct * diffSens | |
| 599 | - flux_value.append(flux) | |
| 600 | - pflux_value.append(pflux) | |
| 601 | - eflux_value.append(eflux) | |
| 602 | - diffSens_value.append(diffSens) | |
| 585 | + crab_flux = correct * crab_flux | |
| 586 | + photon_flux = correct * photon_flux | |
| 587 | + energy_flux = correct * energy_flux | |
| 588 | + sensitivity = correct * sensitivity | |
| 589 | + crab_flux_value.append(crab_flux) | |
| 590 | + photon_flux_value.append(photon_flux) | |
| 591 | + energy_flux_value.append(energy_flux) | |
| 592 | + sensitivity_value.append(sensitivity) | |
| 603 | 593 | |
| 604 | 594 | # Write background and test source fit results |
| 605 | 595 | if self.logExplicit(): |
| 606 | 596 | self.log.parformat("Photon flux") |
| 607 | - self.log(pflux) | |
| 597 | + self.log(photon_flux) | |
| 608 | 598 | self.log(" ph/cm2/s\n") |
| 609 | 599 | self.log.parformat("Energy flux") |
| 610 | - self.log(eflux) | |
| 600 | + self.log(energy_flux) | |
| 611 | 601 | self.log(" erg/cm2/s\n") |
| 612 | 602 | self.log.parformat("Crab flux") |
| 613 | - self.log(cflux*1000.0) | |
| 603 | + self.log(crab_flux*1000.0) | |
| 614 | 604 | self.log(" mCrab\n") |
| 615 | 605 | self.log.parformat("Differential sensitivity") |
| 616 | - self.log(diffSens) | |
| 606 | + self.log(sensitivity) | |
| 617 | 607 | self.log(" erg/cm2/s\n") |
| 618 | 608 | for model in result_all: |
| 619 | 609 | self.log.parformat("Model") |
| ... | ... | @@ -629,40 +619,40 @@ class cssens(ctools.cscript): |
| 629 | 619 | self.log("corr=") |
| 630 | 620 | self.log(correct) |
| 631 | 621 | self.log(" ") |
| 632 | - self.log(pflux) | |
| 622 | + self.log(photon_flux) | |
| 633 | 623 | self.log(" ph/cm2/s = ") |
| 634 | - self.log(eflux) | |
| 624 | + self.log(energy_flux) | |
| 635 | 625 | self.log(" erg/cm2/s = ") |
| 636 | - self.log(cflux*1000.0) | |
| 626 | + self.log(crab_flux*1000.0) | |
| 637 | 627 | self.log(" mCrab = ") |
| 638 | - self.log(diffSens) | |
| 628 | + self.log(sensitivity) | |
| 639 | 629 | self.log(" erg/cm2/s\n") |
| 640 | 630 | |
| 641 | 631 | # Compute sliding average of extrapolated fitted prefactor, |
| 642 | 632 | # photon and energy flux. This damps out fluctuations and |
| 643 | 633 | # improves convergence |
| 644 | - flux = 0.0 | |
| 645 | - pflux = 0.0 | |
| 646 | - eflux = 0.0 | |
| 647 | - diffSens = 0.0 | |
| 648 | - num = 0.0 | |
| 634 | + crab_flux = 0.0 | |
| 635 | + photon_flux = 0.0 | |
| 636 | + energy_flux = 0.0 | |
| 637 | + sensitivity = 0.0 | |
| 638 | + num = 0.0 | |
| 649 | 639 | for k in range(self.m_num_avg): |
| 650 | - inx = len(flux_value) - k - 1 | |
| 640 | + inx = len(crab_flux_value) - k - 1 | |
| 651 | 641 | if inx >= 0: |
| 652 | - flux += flux_value[inx] | |
| 653 | - pflux += pflux_value[inx] | |
| 654 | - eflux += eflux_value[inx] | |
| 655 | - diffSens += diffSens_value[inx] | |
| 642 | + crab_flux += crab_flux_value[inx] | |
| 643 | + photon_flux += photon_flux_value[inx] | |
| 644 | + energy_flux += energy_flux_value[inx] | |
| 645 | + sensitivity += sensitivity_value[inx] | |
| 656 | 646 | num += 1.0 |
| 657 | - flux /= num | |
| 658 | - pflux /= num | |
| 659 | - eflux /= num | |
| 660 | - diffSens /= num | |
| 647 | + crab_flux /= num | |
| 648 | + photon_flux /= num | |
| 649 | + energy_flux /= num | |
| 650 | + sensitivity /= num | |
| 661 | 651 | |
| 662 | 652 | # Compare average flux to last average |
| 663 | 653 | if iter > self.m_num_avg: |
| 664 | - if test_cflux > 0: | |
| 665 | - ratio = flux/test_cflux | |
| 654 | + if test_crab_flux > 0: | |
| 655 | + ratio = crab_flux/test_crab_flux | |
| 666 | 656 | |
| 667 | 657 | # We have 2 convergence criteria: |
| 668 | 658 | # 1. The average flux does not change |
| ... | ... | @@ -678,7 +668,7 @@ class cssens(ctools.cscript): |
| 678 | 668 | break |
| 679 | 669 | |
| 680 | 670 | # Use average for next iteration |
| 681 | - test_cflux = flux | |
| 671 | + test_crab_flux = crab_flux | |
| 682 | 672 | |
| 683 | 673 | # Exit loop if number of trials exhausted |
| 684 | 674 | if (iter >= self.m_max_iter): |
| ... | ... | @@ -693,16 +683,16 @@ class cssens(ctools.cscript): |
| 693 | 683 | self.log(ts) |
| 694 | 684 | self.log("\n") |
| 695 | 685 | self.log.parformat("Photon flux") |
| 696 | - self.log(pflux) | |
| 686 | + self.log(photon_flux) | |
| 697 | 687 | self.log(" ph/cm2/s\n") |
| 698 | 688 | self.log.parformat("Energy flux") |
| 699 | - self.log(eflux) | |
| 689 | + self.log(energy_flux) | |
| 700 | 690 | self.log(" erg/cm2/s\n") |
| 701 | 691 | self.log.parformat("Crab flux") |
| 702 | - self.log(cflux*1000.0) | |
| 692 | + self.log(crab_flux*1000.0) | |
| 703 | 693 | self.log(" mCrab\n") |
| 704 | 694 | self.log.parformat("Differential sensitivity") |
| 705 | - self.log(diffSens) | |
| 695 | + self.log(sensitivity) | |
| 706 | 696 | self.log(" erg/cm2/s\n") |
| 707 | 697 | self.log.parformat("Number of simulated events") |
| 708 | 698 | self.log(nevents) |
| ... | ... | @@ -736,8 +726,9 @@ class cssens(ctools.cscript): |
| 736 | 726 | |
| 737 | 727 | # Store result |
| 738 | 728 | result = {'loge': loge, 'emin': emin.TeV(), 'emax': emax.TeV(), \ |
| 739 | - 'crab': flux, 'pflux': pflux, 'eflux': eflux, \ | |
| 740 | - 'diffSens': diffSens} | |
| 729 | + 'crab_flux': crab_flux, 'photon_flux': photon_flux, \ | |
| 730 | + 'energy_flux': energy_flux, \ | |
| 731 | + 'sensitivity': sensitivity} | |
| 741 | 732 | |
| 742 | 733 | # Return result |
| 743 | 734 | return result | ... | ... |