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 27 irf, s, a, South_0.5h,,, "Instrument response function"
28 28 inexclusion, f, a, NONE,,, "Exclusion regions TODO: add meaningful default"
29 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 33 # Script parameters
... ... @@ -56,9 +56,9 @@ etruemin, r, h, 0.01,,, "Minimum true energy (TeV)"
56 56 etruemax, r, h, 300.0,,, "Maximum true energy (TeV)"
57 57 etruebins, i, h, 30,,, "Number of bins per decade for true energy bins"
58 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 64 # Standard parameters
... ...
cscripts/csscs.py
... ... @@ -498,7 +498,7 @@ class csscs(ctools.csobservation):
498 498 result[name] = {'flux' : 0.0,
499 499 'flux_err': 0.0,
500 500 'TS' : 0.0,
501   - 'ulimit' : 0.0}
  501 + 'ulimit' : -1.0}
502 502  
503 503 # Mask observations
504 504 self._log_header3(gammalib.EXPLICIT, 'Masking observations')
... ... @@ -542,10 +542,12 @@ class csscs(ctools.csobservation):
542 542 # Get flux
543 543 # Integrate spectral model between emin and emax
544 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 551 result[name]['flux'] = flux
550 552  
551 553 # Get flux error
... ... @@ -564,8 +566,35 @@ class csscs(ctools.csobservation):
564 566 if self['calc_ts'].boolean():
565 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 599 else:
571 600 value = 'Likelihood is zero. Bin is skipped.'
... ... @@ -604,24 +633,22 @@ class csscs(ctools.csobservation):
604 633 # Loop over target sources
605 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 639 fmap = self._create_map()
609 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 644 # Loop over pixels and fill maps
616 645 for inx in range(fmap.npix()):
617 646  
618   - # Fill flux and flux error
  647 + # Fill maps
619 648 fmap[inx,0] = results[inx][name]['flux']
620 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 653 # Write maps to Fits
627 654 fhdu = fmap.write(fits, name + ' FLUX')
... ... @@ -638,6 +665,12 @@ class csscs(ctools.csobservation):
638 665 tshdu = tsmap.write(fits, name + ' TS')
639 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 674 # Return
642 675 return fits
643 676  
... ...