Commit b621fc01d46c65b11690a49d0767c8a935081683

Authored by Luigi Tibaldo
1 parent acab87bd

added upper limit computation

cscripts/csscs.par
@@ -27,7 +27,7 @@ caldb, s, a, prod2,,, "Calibration database" @@ -27,7 +27,7 @@ caldb, s, a, prod2,,, "Calibration database"
27 irf, s, a, South_0.5h,,, "Instrument response function" 27 irf, s, a, South_0.5h,,, "Instrument response function"
28 inexclusion, f, a, NONE,,, "Exclusion regions TODO: add meaningful default" 28 inexclusion, f, a, NONE,,, "Exclusion regions TODO: add meaningful default"
29 edisp, b, h, no,,, "Apply energy dispersion?" 29 edisp, b, h, no,,, "Apply energy dispersion?"
30 -outfile, f, a, map.fits,,, "Output map" 30 +outfile, f, a, maps.fits,,, "Output maps"
31 31
32 # 32 #
33 # Script parameters 33 # Script parameters
@@ -56,9 +56,9 @@ etruemin, r, h, 0.01,,, "Minimum true energy (TeV)" @@ -56,9 +56,9 @@ etruemin, r, h, 0.01,,, "Minimum true energy (TeV)"
56 etruemax, r, h, 300.0,,, "Maximum true energy (TeV)" 56 etruemax, r, h, 300.0,,, "Maximum true energy (TeV)"
57 etruebins, i, h, 30,,, "Number of bins per decade for true energy bins" 57 etruebins, i, h, 30,,, "Number of bins per decade for true energy bins"
58 calc_ts, b, h, yes,,, "Compute TS value in each bin" 58 calc_ts, b, h, yes,,, "Compute TS value in each bin"
59 -calc_ulim, b, h, yes,,, "Compute upper limit in each bin"  
60 -fix_srcs, b, h, yes,,, "Fix other skymodel parameters"  
61 -fix_bkg, b, h, no,,, "Fix background parameters" 59 +calc_ulim, b, h, no,,, "Compute upper limit in each bin"
  60 +fix_srcs, b, h, yes,,, "Fix other skymodel normalisations"
  61 +fix_bkg, b, h, no,,, "Fix background normalisation"
62 62
63 # 63 #
64 # Standard parameters 64 # Standard parameters
cscripts/csscs.py
@@ -498,7 +498,7 @@ class csscs(ctools.csobservation): @@ -498,7 +498,7 @@ class csscs(ctools.csobservation):
498 result[name] = {'flux' : 0.0, 498 result[name] = {'flux' : 0.0,
499 'flux_err': 0.0, 499 'flux_err': 0.0,
500 'TS' : 0.0, 500 'TS' : 0.0,
501 - 'ulimit' : 0.0} 501 + 'ulimit' : -1.0}
502 502
503 # Mask observations 503 # Mask observations
504 self._log_header3(gammalib.EXPLICIT, 'Masking observations') 504 self._log_header3(gammalib.EXPLICIT, 'Masking observations')
@@ -542,10 +542,12 @@ class csscs(ctools.csobservation): @@ -542,10 +542,12 @@ class csscs(ctools.csobservation):
542 # Get flux 542 # Get flux
543 # Integrate spectral model between emin and emax 543 # Integrate spectral model between emin and emax
544 flux = source.spectral().flux(emin,emax) 544 flux = source.spectral().flux(emin,emax)
545 - # Multiply by flux from spatial component in ROI  
546 - flux *= source.spatial().flux(roi)  
547 - # Divide by solid angle of ROI  
548 - flux /= gammalib.twopi * (1 - math.cos(math.radians(self['rad'].real()))) 545 + # Calculate correction factor
  546 + # Spatial model flux over ROI divided by ROI solid angle
  547 + corr_factor = source.spatial().flux(roi)
  548 + corr_factor /= gammalib.twopi * (1 - math.cos(math.radians(self['rad'].real())))
  549 + # Multiply flux by correction factor
  550 + flux *= corr_factor
549 result[name]['flux'] = flux 551 result[name]['flux'] = flux
550 552
551 # Get flux error 553 # Get flux error
@@ -564,8 +566,35 @@ class csscs(ctools.csobservation): @@ -564,8 +566,35 @@ class csscs(ctools.csobservation):
564 if self['calc_ts'].boolean(): 566 if self['calc_ts'].boolean():
565 result[name]['TS'] = source.ts() 567 result[name]['TS'] = source.ts()
566 568
567 - # Upper limit  
568 - # TODO 569 + # If requested compute upper flux limit
  570 + if self['calc_ulim'].boolean():
  571 +
  572 + # Logging information
  573 + self._log_header3(gammalib.EXPLICIT,
  574 + 'Computing upper limit for source ' + name)
  575 +
  576 + # Create upper limit object
  577 + ulimit = ctools.ctulimit(like.obs())
  578 + ulimit['srcname'] = name
  579 + ulimit['emin'] = self['emin'].real()
  580 + ulimit['emax'] = self['emax'].real()
  581 +
  582 + # If chatter level is verbose and debugging is requested
  583 + # then switch also on the debug model in ctulimit
  584 + if self._logVerbose() and self._logDebug():
  585 + ulimit['debug'] = True
  586 +
  587 + # Try to run upper limit and catch exceptions
  588 + try:
  589 + ulimit.run()
  590 + ulimit_value = ulimit.flux_ulimit()
  591 + # Multiply by correction factor to get flux per solid angle in ROI
  592 + ulimit_value *= corr_factor
  593 + result[name]['ulimit'] = ulimit_value
  594 + except:
  595 + self._log_string(gammalib.EXPLICIT, 'Upper limit '
  596 + 'calculation failed.')
  597 +
569 598
570 else: 599 else:
571 value = 'Likelihood is zero. Bin is skipped.' 600 value = 'Likelihood is zero. Bin is skipped.'
@@ -604,24 +633,22 @@ class csscs(ctools.csobservation): @@ -604,24 +633,22 @@ class csscs(ctools.csobservation):
604 # Loop over target sources 633 # Loop over target sources
605 for s, name in enumerate(self._srcnames): 634 for s, name in enumerate(self._srcnames):
606 635
607 - # Create minimal set of skymaps to store fluxes and flux errors 636 + # Create skymaps to store results
  637 + # Maps for TS and upper limits created and filled to avoid if statements
  638 + # Will not be saved in the end if not requested
608 fmap = self._create_map() 639 fmap = self._create_map()
609 errmap = self._create_map() 640 errmap = self._create_map()
610 -  
611 - #Create map for TS  
612 - if self['calc_ts'].boolean():  
613 - tsmap = self._create_map() 641 + tsmap = self._create_map()
  642 + ulmap = self._create_map()
614 643
615 # Loop over pixels and fill maps 644 # Loop over pixels and fill maps
616 for inx in range(fmap.npix()): 645 for inx in range(fmap.npix()):
617 646
618 - # Fill flux and flux error 647 + # Fill maps
619 fmap[inx,0] = results[inx][name]['flux'] 648 fmap[inx,0] = results[inx][name]['flux']
620 errmap[inx, 0] = results[inx][name]['flux_error'] 649 errmap[inx, 0] = results[inx][name]['flux_error']
621 -  
622 - # If requested fill TS  
623 - if self['calc_ts'].boolean():  
624 - tsmap[inx, 0] = results[inx][name]['TS'] 650 + tsmap[inx, 0] = results[inx][name]['TS']
  651 + ulmap[inx, 0] = results[inx][name]['ulimit']
625 652
626 # Write maps to Fits 653 # Write maps to Fits
627 fhdu = fmap.write(fits, name + ' FLUX') 654 fhdu = fmap.write(fits, name + ' FLUX')
@@ -638,6 +665,12 @@ class csscs(ctools.csobservation): @@ -638,6 +665,12 @@ class csscs(ctools.csobservation):
638 tshdu = tsmap.write(fits, name + ' TS') 665 tshdu = tsmap.write(fits, name + ' TS')
639 tshdu.header().append(roiszcard) 666 tshdu.header().append(roiszcard)
640 667
  668 + # If requested write upper limit map to fits
  669 + if self['calc_ulim'].boolean():
  670 + ulhdu = ulmap.write(fits, name + ' FLUX UPPER LIMIT')
  671 + ulhdu.header().append(fcard)
  672 + ulhdu.header().append(roiszcard)
  673 +
641 # Return 674 # Return
642 return fits 675 return fits
643 676