Commit 9600793a6504cb003846a40731fec91b2d33b0df

Authored by Luigi Tibaldo
1 parent e231d0c0

added test unit

cscripts/csscs.py
@@ -18,12 +18,12 @@ @@ -18,12 +18,12 @@
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 # 19 #
20 # ========================================================================== 20 # ==========================================================================
21 -import sys  
22 -import gammalib  
23 import ctools 21 import ctools
  22 +import gammalib
  23 +import math
  24 +import sys
24 from cscripts import mputils 25 from cscripts import mputils
25 from cscripts import obsutils 26 from cscripts import obsutils
26 -import math  
27 27
28 28
29 # ================= # 29 # ================= #
@@ -53,7 +53,8 @@ class csscs(ctools.csobservation): @@ -53,7 +53,8 @@ class csscs(ctools.csobservation):
53 self._srcnames = [] 53 self._srcnames = []
54 self._method = None 54 self._method = None
55 self._fits = None 55 self._fits = None
56 - self._excl_reg_map = None # Exclusion region map for on/off analysis 56 + self._excl_reg_map = None # Exclusion region map for on/off analysis
  57 + self._excl_reg_name = None
57 58
58 # Return 59 # Return
59 return 60 return
@@ -70,12 +71,13 @@ class csscs(ctools.csobservation): @@ -70,12 +71,13 @@ class csscs(ctools.csobservation):
70 """ 71 """
71 # Set pickled dictionary 72 # Set pickled dictionary
72 # Set pickled dictionary 73 # Set pickled dictionary
73 - state = {'base' : ctools.csobservation.__getstate__(self),  
74 - 'nthreads' : self._nthreads,  
75 - 'method' : self._method,  
76 - 'srcnames' : self._srcnames,  
77 - 'fits' : self._fits,  
78 - 'excl_reg_map' : self._excl_reg_map} 74 + state = {'base': ctools.csobservation.__getstate__(self),
  75 + 'nthreads': self._nthreads,
  76 + 'method': self._method,
  77 + 'srcnames': self._srcnames,
  78 + 'fits': self._fits,
  79 + 'excl_reg_map': self._excl_reg_map,
  80 + 'excl_reg_name' : self._excl_reg_name}
79 81
80 # Return pickled dictionary 82 # Return pickled dictionary
81 return state 83 return state
@@ -96,11 +98,11 @@ class csscs(ctools.csobservation): @@ -96,11 +98,11 @@ class csscs(ctools.csobservation):
96 self._method = state['method'] 98 self._method = state['method']
97 self._fits = state['fits'] 99 self._fits = state['fits']
98 self._excl_reg_map = state['excl_reg_map'] 100 self._excl_reg_map = state['excl_reg_map']
  101 + self._excl_reg_name = state['excl_reg_name']
99 102
100 # Return 103 # Return
101 return 104 return
102 105
103 -  
104 # Private methods 106 # Private methods
105 def _get_onoff_parameters(self): 107 def _get_onoff_parameters(self):
106 """ 108 """
@@ -117,8 +119,8 @@ class csscs(ctools.csobservation): @@ -117,8 +119,8 @@ class csscs(ctools.csobservation):
117 # Exclusion map set and is not empty 119 # Exclusion map set and is not empty
118 pass 120 pass
119 elif self['inexclusion'].is_valid(): 121 elif self['inexclusion'].is_valid():
120 - inexclusion = self['inexclusion'].filename()  
121 - self._excl_reg_map = gammalib.GSkyRegionMap(inexclusion) 122 + self._excl_reg_name = self['inexclusion'].filename()
  123 + self._excl_reg_map = gammalib.GSkyRegionMap(self._excl_reg_name)
122 else: 124 else:
123 msg = 'csscs in On/Off mode requires input exclusion region.' 125 msg = 'csscs in On/Off mode requires input exclusion region.'
124 raise RuntimeError(msg) 126 raise RuntimeError(msg)
@@ -150,8 +152,8 @@ class csscs(ctools.csobservation): @@ -150,8 +152,8 @@ class csscs(ctools.csobservation):
150 # Collect number of unbinned, binned and On/Off observations in 152 # Collect number of unbinned, binned and On/Off observations in
151 # observation container 153 # observation container
152 n_unbinned = 0 154 n_unbinned = 0
153 - n_binned = 0  
154 - n_onoff = 0 155 + n_binned = 0
  156 + n_onoff = 0
155 for obs in self.obs(): 157 for obs in self.obs():
156 if obs.classname() == 'GCTAObservation': 158 if obs.classname() == 'GCTAObservation':
157 if obs.eventtype() == 'CountsCube': 159 if obs.eventtype() == 'CountsCube':
@@ -160,16 +162,16 @@ class csscs(ctools.csobservation): @@ -160,16 +162,16 @@ class csscs(ctools.csobservation):
160 n_unbinned += 1 162 n_unbinned += 1
161 elif obs.classname() == 'GCTAOnOffObservation': 163 elif obs.classname() == 'GCTAOnOffObservation':
162 n_onoff += 1 164 n_onoff += 1
163 - n_cta = n_unbinned + n_binned + n_onoff 165 + n_cta = n_unbinned + n_binned + n_onoff
164 n_other = self.obs().size() - n_cta 166 n_other = self.obs().size() - n_cta
165 167
166 # Check if there are On/Off or non-IACT observations 168 # Check if there are On/Off or non-IACT observations
167 if n_onoff > 0 or n_other > 0: 169 if n_onoff > 0 or n_other > 0:
168 - msg = 'On/Off or non-CTA observations found. '\ 170 + msg = 'On/Off or non-CTA observations found. ' \
169 'csscs does not support this type of observations.' 171 'csscs does not support this type of observations.'
170 raise RuntimeError(msg) 172 raise RuntimeError(msg)
171 # Otherwise check if there is a mix of binned and unbinned 173 # Otherwise check if there is a mix of binned and unbinned
172 - elif n_unbinned > 0 and n_binned>0: 174 + elif n_unbinned > 0 and n_binned > 0:
173 msg = 'Mix of unbinned and binned CTA observations ' \ 175 msg = 'Mix of unbinned and binned CTA observations ' \
174 'found in observation container. csscs does not ' \ 176 'found in observation container. csscs does not ' \
175 'support this mix.' 177 'support this mix.'
@@ -228,7 +230,7 @@ class csscs(ctools.csobservation): @@ -228,7 +230,7 @@ class csscs(ctools.csobservation):
228 # Loop over models and verify if model is of type GModelSky 230 # Loop over models and verify if model is of type GModelSky
229 for model in self.obs().models(): 231 for model in self.obs().models():
230 if model.classname() == 'GModelSky': 232 if model.classname() == 'GModelSky':
231 - nsources +=1 233 + nsources += 1
232 # If there are background gamma-ray sources in the model 234 # If there are background gamma-ray sources in the model
233 # throw runtime error 235 # throw runtime error
234 if nsources > len(self._srcnames): 236 if nsources > len(self._srcnames):
@@ -327,7 +329,7 @@ class csscs(ctools.csobservation): @@ -327,7 +329,7 @@ class csscs(ctools.csobservation):
327 # Free the normalisation parameter which is assumed to be 329 # Free the normalisation parameter which is assumed to be
328 # the first spectral parameter 330 # the first spectral parameter
329 if normpar.is_fixed(): 331 if normpar.is_fixed():
330 - self._log_string(gammalib.EXPLICIT, ' Freeing "'+normpar.name()+'"') 332 + self._log_string(gammalib.EXPLICIT, ' Freeing "' + normpar.name() + '"')
331 normpar.free() 333 normpar.free()
332 334
333 # Optionally compute Test Statistic value 335 # Optionally compute Test Statistic value
@@ -338,7 +340,7 @@ class csscs(ctools.csobservation): @@ -338,7 +340,7 @@ class csscs(ctools.csobservation):
338 elif self['fix_bkg'].boolean() and not model.classname() == 'GModelSky': 340 elif self['fix_bkg'].boolean() and not model.classname() == 'GModelSky':
339 341
340 if normpar.is_free(): 342 if normpar.is_free():
341 - self._log_string(gammalib.EXPLICIT, ' Fixing "'+normpar.name()+'"') 343 + self._log_string(gammalib.EXPLICIT, ' Fixing "' + normpar.name() + '"')
342 normpar.fix() 344 normpar.fix()
343 345
344 346
@@ -346,13 +348,13 @@ class csscs(ctools.csobservation): @@ -346,13 +348,13 @@ class csscs(ctools.csobservation):
346 elif self['fix_srcs'].boolean() and model.classname() == 'GModelSky': 348 elif self['fix_srcs'].boolean() and model.classname() == 'GModelSky':
347 349
348 if normpar.is_free(): 350 if normpar.is_free():
349 - self._log_string(gammalib.EXPLICIT, ' Fixing "'+normpar.name()+'"') 351 + self._log_string(gammalib.EXPLICIT, ' Fixing "' + normpar.name() + '"')
350 normpar.fix() 352 normpar.fix()
351 353
352 # Return 354 # Return
353 return 355 return
354 356
355 - def _mask_cube(self,obs,ra,dec,rad): 357 + def _mask_cube(self, obs, ra, dec, rad):
356 """ 358 """
357 Mask cube observation 359 Mask cube observation
358 360
@@ -392,7 +394,7 @@ class csscs(ctools.csobservation): @@ -392,7 +394,7 @@ class csscs(ctools.csobservation):
392 # Return 394 # Return
393 return new_obs 395 return new_obs
394 396
395 - def _mask_evlist(self,obs,ra,dec,rad): 397 + def _mask_evlist(self, obs, ra, dec, rad):
396 """ 398 """
397 Mask event list 399 Mask event list
398 400
@@ -434,7 +436,7 @@ class csscs(ctools.csobservation): @@ -434,7 +436,7 @@ class csscs(ctools.csobservation):
434 # Return 436 # Return
435 return new_obs 437 return new_obs
436 438
437 - def _mask_observations(self,ra,dec,rad): 439 + def _mask_observations(self, ra, dec, rad):
438 """ 440 """
439 Create observations restricted to circular ROI 441 Create observations restricted to circular ROI
440 442
@@ -457,14 +459,14 @@ class csscs(ctools.csobservation): @@ -457,14 +459,14 @@ class csscs(ctools.csobservation):
457 elif self._method == 'BINNED': 459 elif self._method == 'BINNED':
458 new_obs = self._mask_cube(self.obs(), ra, dec, rad) 460 new_obs = self._mask_cube(self.obs(), ra, dec, rad)
459 elif self._method == 'ONOFF': 461 elif self._method == 'ONOFF':
460 - new_obs = obsutils.get_onoff_obs(self,self.obs(),nthreads=1,  
461 - ra = ra, dec = dec,  
462 - srcname = self._srcnames[0]) 462 + new_obs = obsutils.get_onoff_obs(self, self.obs(), nthreads=1,
  463 + ra=ra, dec=dec,
  464 + srcname=self._srcnames[0])
463 465
464 # Return 466 # Return
465 return new_obs 467 return new_obs
466 468
467 - def _pixel_analysis(self,inx): 469 + def _pixel_analysis(self, inx):
468 """ 470 """
469 Performs analysis over the region of interest 471 Performs analysis over the region of interest
470 corresponding to a single pixel of output map 472 corresponding to a single pixel of output map
@@ -487,25 +489,25 @@ class csscs(ctools.csobservation): @@ -487,25 +489,25 @@ class csscs(ctools.csobservation):
487 dec = pixdir.dec_deg() 489 dec = pixdir.dec_deg()
488 490
489 # Write header for spatial bin 491 # Write header for spatial bin
490 - msg = 'Spatial bin (%d) centred on (R.A.,Dec) = (%f,%f) deg' % (inx,ra,dec) 492 + msg = 'Spatial bin (%d) centred on (R.A.,Dec) = (%f,%f) deg' % (inx, ra, dec)
491 self._log_header2(gammalib.TERSE, msg) 493 self._log_header2(gammalib.TERSE, msg)
492 494
493 # Initialize results 495 # Initialize results
494 result = {} 496 result = {}
495 for name in self._srcnames: 497 for name in self._srcnames:
496 - result[name] = {'flux' : 0.0, 498 + result[name] = {'flux': 0.0,
497 'flux_err': 0.0, 499 'flux_err': 0.0,
498 - 'TS' : 0.0,  
499 - 'ulimit' : -1.0} 500 + 'TS': 0.0,
  501 + 'ulimit': -1.0}
500 502
501 # Mask observations 503 # Mask observations
502 self._log_header3(gammalib.NORMAL, 'Masking observations') 504 self._log_header3(gammalib.NORMAL, 'Masking observations')
503 - masked_obs = self._mask_observations(ra,dec,self['rad'].real()) 505 + masked_obs = self._mask_observations(ra, dec, self['rad'].real())
504 506
505 # Set up likelihood analysis 507 # Set up likelihood analysis
506 self._log_header3(gammalib.NORMAL, 'Performing fit in region') 508 self._log_header3(gammalib.NORMAL, 'Performing fit in region')
507 like = ctools.ctlike(masked_obs) 509 like = ctools.ctlike(masked_obs)
508 - like['edisp'] = self['edisp'].boolean() 510 + like['edisp'] = self['edisp'].boolean()
509 like['nthreads'] = 1 # Avoids OpenMP conflict 511 like['nthreads'] = 1 # Avoids OpenMP conflict
510 512
511 # If chatter level is verbose and debugging is requested then 513 # If chatter level is verbose and debugging is requested then
@@ -522,10 +524,10 @@ class csscs(ctools.csobservation): @@ -522,10 +524,10 @@ class csscs(ctools.csobservation):
522 # Prepare objects for flux extraction 524 # Prepare objects for flux extraction
523 # ROI 525 # ROI
524 centre = gammalib.GSkyDir() 526 centre = gammalib.GSkyDir()
525 - centre.radec_deg(ra,dec)  
526 - roi = gammalib.GSkyRegionCircle(centre,self['rad'].real()) 527 + centre.radec_deg(ra, dec)
  528 + roi = gammalib.GSkyRegionCircle(centre, self['rad'].real())
527 # Energy boundaries 529 # Energy boundaries
528 - emin = gammalib.GEnergy(self['emin'].real(),'TeV') 530 + emin = gammalib.GEnergy(self['emin'].real(), 'TeV')
529 emax = gammalib.GEnergy(self['emax'].real(), 'TeV') 531 emax = gammalib.GEnergy(self['emax'].real(), 'TeV')
530 532
531 # Continue only if log-likelihood is non-zero 533 # Continue only if log-likelihood is non-zero
@@ -539,11 +541,12 @@ class csscs(ctools.csobservation): @@ -539,11 +541,12 @@ class csscs(ctools.csobservation):
539 541
540 # Get flux 542 # Get flux
541 # Integrate spectral model between emin and emax 543 # Integrate spectral model between emin and emax
542 - flux = source.spectral().flux(emin,emax) 544 + flux = source.spectral().flux(emin, emax)
543 # Calculate correction factor 545 # Calculate correction factor
544 # Spatial model flux over ROI divided by ROI solid angle 546 # Spatial model flux over ROI divided by ROI solid angle
545 corr_factor = source.spatial().flux(roi) 547 corr_factor = source.spatial().flux(roi)
546 - corr_factor /= gammalib.twopi * (1 - math.cos(math.radians(self['rad'].real()))) 548 + corr_factor /= gammalib.twopi * (
  549 + 1 - math.cos(math.radians(self['rad'].real())))
547 # Multiply flux by correction factor 550 # Multiply flux by correction factor
548 flux *= corr_factor 551 flux *= corr_factor
549 result[name]['flux'] = flux 552 result[name]['flux'] = flux
@@ -555,7 +558,7 @@ class csscs(ctools.csobservation): @@ -555,7 +558,7 @@ class csscs(ctools.csobservation):
555 # Relative error on flux is same as on normalization 558 # Relative error on flux is same as on normalization
556 # Avoid zero division error 559 # Avoid zero division error
557 if normpar.value() > 0.: 560 if normpar.value() > 0.:
558 - flux_error = flux * normpar.error()/normpar.value() 561 + flux_error = flux * normpar.error() / normpar.value()
559 else: 562 else:
560 flux_error = 0. 563 flux_error = 0.
561 result[name]['flux_error'] = flux_error 564 result[name]['flux_error'] = flux_error
@@ -591,58 +594,57 @@ class csscs(ctools.csobservation): @@ -591,58 +594,57 @@ class csscs(ctools.csobservation):
591 result[name]['ulimit'] = ulimit_value 594 result[name]['ulimit'] = ulimit_value
592 except: 595 except:
593 self._log_string(gammalib.NORMAL, 'Upper limit ' 596 self._log_string(gammalib.NORMAL, 'Upper limit '
594 - 'calculation failed.') 597 + 'calculation failed.')
595 598
596 599
597 else: 600 else:
598 value = 'Likelihood is zero. Bin is skipped.' 601 value = 'Likelihood is zero. Bin is skipped.'
599 - self._log_value(gammalib.TERSE, '(R.A.,Dec) = (%f,%f) deg' % (ra,dec), value) 602 + self._log_value(gammalib.TERSE, '(R.A.,Dec) = (%f,%f) deg' % (ra, dec), value)
600 603
601 # Return result 604 # Return result
602 return result 605 return result
603 606
604 - def _write_hdu_keywords(self,hdu, is_flux = False): 607 + def _write_hdu_keywords(self, hdu, is_flux=False):
605 """ 608 """
606 Append cards to HDU 609 Append cards to HDU
607 610
608 Parameters 611 Parameters
609 ---------- 612 ----------
610 - hdu : `dict` HDU 613 + hdu : `~gammalib.GFitsHDU` HDU
611 """ 614 """
612 615
613 # Flux units 616 # Flux units
614 if is_flux: 617 if is_flux:
615 - hdu.card('BUNIT', 'ph/cm2/s/sr' , 'Photon flux') 618 + hdu.card('BUNIT', 'ph/cm2/s/sr', 'Photon flux')
616 619
617 # Minimum and maximum energy 620 # Minimum and maximum energy
618 - hdu.card("E_MIN", self['emin'].real(), "[TeV] Lower energy boundary")  
619 - hdu.card("E_MAX", self['emax'].real(), "[TeV] Upper energy boundary")  
620 - hdu.card("EUNIT", "TeV", "Units for E_MIN and E_MAX") 621 + hdu.card("E_MIN", self['emin'].real(), "[TeV] Lower energy boundary")
  622 + hdu.card("E_MAX", self['emax'].real(), "[TeV] Upper energy boundary")
  623 + hdu.card("EUNIT", "TeV", "Units for E_MIN and E_MAX")
621 624
622 # ROI size 625 # ROI size
623 - hdu.card('ROISZ', self['rad'].real() , 626 + hdu.card('ROISZ', self['rad'].real(),
624 '[deg] Size of ROI used for component separation') 627 '[deg] Size of ROI used for component separation')
625 628
626 # Analysis method 629 # Analysis method
627 - hdu.card('METHOD',self._method, 'Analysis method') 630 + hdu.card('METHOD', self._method, 'Analysis method')
628 631
629 # For On/Off log information 632 # For On/Off log information
630 if self._method == 'ONOFF': 633 if self._method == 'ONOFF':
631 634
632 # Exclusion map 635 # Exclusion map
633 - if (self._excl_reg_map is not None) and self['inexclusion'].is_valid():  
634 - hdu.card("EXCLMAP", self['inexclusion'].filename().url(), "Exclusion map name") 636 + if self._excl_reg_name is not None:
  637 + hdu.card("EXCLMAP", self._excl_reg_name.url(), "Exclusion map name")
635 638
636 # Model background? 639 # Model background?
637 - hdu.card("BKGMODEL", self['use_model_bkg'].boolean(),'Use background model?') 640 + hdu.card("BKGMODEL", self['use_model_bkg'].boolean(), 'Use background model?')
638 641
639 # Fit statistic 642 # Fit statistic
640 - hdu.card("STAT", self['statistic'].string(),'Fit statistic') 643 + hdu.card("STAT", self['statistic'].string(), 'Fit statistic')
641 644
642 return 645 return
643 646
644 -  
645 - def _fill_fits(self,results): 647 + def _fill_fits(self, results):
646 """ 648 """
647 Fill FITS object to store the results 649 Fill FITS object to store the results
648 650
@@ -674,27 +676,29 @@ class csscs(ctools.csobservation): @@ -674,27 +676,29 @@ class csscs(ctools.csobservation):
674 676
675 # Loop over pixels and fill maps 677 # Loop over pixels and fill maps
676 for inx in range(fmap.npix()): 678 for inx in range(fmap.npix()):
677 -  
678 # Fill maps 679 # Fill maps
679 - fmap[inx,0] = results[inx][name]['flux'] 680 + fmap[inx, 0] = results[inx][name]['flux']
680 errmap[inx, 0] = results[inx][name]['flux_error'] 681 errmap[inx, 0] = results[inx][name]['flux_error']
681 tsmap[inx, 0] = results[inx][name]['TS'] 682 tsmap[inx, 0] = results[inx][name]['TS']
682 ulmap[inx, 0] = results[inx][name]['ulimit'] 683 ulmap[inx, 0] = results[inx][name]['ulimit']
683 684
  685 + # Uppercase name to adhere to gammalib convention
  686 + Name = gammalib.toupper(name)
  687 +
684 # Write maps to Fits 688 # Write maps to Fits
685 - fhdu = fmap.write(fits, name + ' FLUX')  
686 - self._write_hdu_keywords(fhdu,is_flux=True)  
687 - errhdu = errmap.write(fits, name + ' FLUX ERROR') 689 + fhdu = fmap.write(fits, Name + ' FLUX')
  690 + self._write_hdu_keywords(fhdu, is_flux=True)
  691 + errhdu = errmap.write(fits, Name + ' FLUX ERROR')
688 self._write_hdu_keywords(errhdu, is_flux=True) 692 self._write_hdu_keywords(errhdu, is_flux=True)
689 693
690 # If requested write TS map to fits 694 # If requested write TS map to fits
691 if self['calc_ts'].boolean(): 695 if self['calc_ts'].boolean():
692 - tshdu = tsmap.write(fits, name + ' TS') 696 + tshdu = tsmap.write(fits, Name + ' TS')
693 self._write_hdu_keywords(tshdu) 697 self._write_hdu_keywords(tshdu)
694 698
695 # If requested write upper limit map to fits 699 # If requested write upper limit map to fits
696 if self['calc_ulim'].boolean(): 700 if self['calc_ulim'].boolean():
697 - ulhdu = ulmap.write(fits, name + ' FLUX UPPER LIMIT') 701 + ulhdu = ulmap.write(fits, Name + ' FLUX UPPER LIMIT')
698 self._write_hdu_keywords(ulhdu, is_flux=True) 702 self._write_hdu_keywords(ulhdu, is_flux=True)
699 703
700 # Return 704 # Return
@@ -725,11 +729,13 @@ class csscs(ctools.csobservation): @@ -725,11 +729,13 @@ class csscs(ctools.csobservation):
725 skymap = None 729 skymap = None
726 730
727 # Proceed only if fits has been filled 731 # Proceed only if fits has been filled
728 - if self._fits != None: 732 + if self._fits != None:
729 # Check that the name is in the list of target sources 733 # Check that the name is in the list of target sources
730 if name in self._srcnames: 734 if name in self._srcnames:
  735 + # Uppercase name
  736 + Name = gammalib.toupper(name)
731 # Assemble HDU name 737 # Assemble HDU name
732 - hduname = name + ' ' + quantity 738 + hduname = Name + ' ' + quantity
733 # Try to fetch HDU 739 # Try to fetch HDU
734 try: 740 try:
735 hdu = self._fits[hduname] 741 hdu = self._fits[hduname]
@@ -747,7 +753,6 @@ class csscs(ctools.csobservation): @@ -747,7 +753,6 @@ class csscs(ctools.csobservation):
747 # Return 753 # Return
748 return skymap 754 return skymap
749 755
750 -  
751 # Public methods 756 # Public methods
752 def run(self): 757 def run(self):
753 """ 758 """
@@ -773,8 +778,8 @@ class csscs(ctools.csobservation): @@ -773,8 +778,8 @@ class csscs(ctools.csobservation):
773 if self._nthreads > 1: 778 if self._nthreads > 1:
774 779
775 # Compute values in pixels 780 # Compute values in pixels
776 - args = [(self, '_pixel_analysis', i)  
777 - for i in range(npix)] 781 + args = [(self, '_pixel_analysis', i)
  782 + for i in range(npix)]
778 poolresults = mputils.process(self._nthreads, mputils.mpfunc, args) 783 poolresults = mputils.process(self._nthreads, mputils.mpfunc, args)
779 784
780 # Construct results 785 # Construct results
@@ -804,7 +809,6 @@ class csscs(ctools.csobservation): @@ -804,7 +809,6 @@ class csscs(ctools.csobservation):
804 809
805 # Continue only if FITS file is valid 810 # Continue only if FITS file is valid
806 if self._fits != None: 811 if self._fits != None:
807 -  
808 # Get outmap parameter 812 # Get outmap parameter
809 outfile = self['outfile'].filename() 813 outfile = self['outfile'].filename()
810 814
@@ -850,7 +854,7 @@ class csscs(ctools.csobservation): @@ -850,7 +854,7 @@ class csscs(ctools.csobservation):
850 # Return 854 # Return
851 return self._fits 855 return self._fits
852 856
853 - def flux(self,name): 857 + def flux(self, name):
854 """ 858 """
855 Return flux skymap 859 Return flux skymap
856 860
@@ -865,11 +869,11 @@ class csscs(ctools.csobservation): @@ -865,11 +869,11 @@ class csscs(ctools.csobservation):
865 Flux skymap 869 Flux skymap
866 """ 870 """
867 871
868 - skymap = self._get_skymap(name,'FLUX') 872 + skymap = self._get_skymap(name, 'FLUX')
869 873
870 return skymap 874 return skymap
871 875
872 - def flux_error(self,name): 876 + def flux_error(self, name):
873 """ 877 """
874 Return flux error skymap 878 Return flux error skymap
875 879
@@ -884,11 +888,11 @@ class csscs(ctools.csobservation): @@ -884,11 +888,11 @@ class csscs(ctools.csobservation):
884 Flux error skymap 888 Flux error skymap
885 """ 889 """
886 890
887 - skymap = self._get_skymap(name,'FLUX ERROR') 891 + skymap = self._get_skymap(name, 'FLUX ERROR')
888 892
889 return skymap 893 return skymap
890 894
891 - def ts(self,name): 895 + def ts(self, name):
892 """ 896 """
893 Return TS skymap 897 Return TS skymap
894 898
@@ -905,7 +909,7 @@ class csscs(ctools.csobservation): @@ -905,7 +909,7 @@ class csscs(ctools.csobservation):
905 909
906 # Check that TS computation is requested 910 # Check that TS computation is requested
907 if self['calc_ts'].boolean(): 911 if self['calc_ts'].boolean():
908 - skymap = self._get_skymap(name,'TS') 912 + skymap = self._get_skymap(name, 'TS')
909 # Otherwise throw error 913 # Otherwise throw error
910 else: 914 else:
911 msg = 'TS computation not requested. ' \ 915 msg = 'TS computation not requested. ' \
@@ -915,7 +919,7 @@ class csscs(ctools.csobservation): @@ -915,7 +919,7 @@ class csscs(ctools.csobservation):
915 919
916 return skymap 920 return skymap
917 921
918 - def ulimit(self,name): 922 + def ulimit(self, name):
919 """ 923 """
920 Return flux upper limit skymap 924 Return flux upper limit skymap
921 925
@@ -932,7 +936,7 @@ class csscs(ctools.csobservation): @@ -932,7 +936,7 @@ class csscs(ctools.csobservation):
932 936
933 # Check that upper limit computation is requested 937 # Check that upper limit computation is requested
934 if self['calc_ulim'].boolean(): 938 if self['calc_ulim'].boolean():
935 - skymap = self._get_skymap(name,'FLUX UPPER LIMIT') 939 + skymap = self._get_skymap(name, 'FLUX UPPER LIMIT')
936 # Otherwise throw error 940 # Otherwise throw error
937 else: 941 else:
938 msg = 'Upper limit computation not requested. ' \ 942 msg = 'Upper limit computation not requested. ' \
@@ -940,7 +944,6 @@ class csscs(ctools.csobservation): @@ -940,7 +944,6 @@ class csscs(ctools.csobservation):
940 'to obtain upper limit.' 944 'to obtain upper limit.'
941 raise RuntimeError(msg) 945 raise RuntimeError(msg)
942 946
943 -  
944 return skymap 947 return skymap
945 948
946 949
@@ -948,7 +951,6 @@ class csscs(ctools.csobservation): @@ -948,7 +951,6 @@ class csscs(ctools.csobservation):
948 # Main routine entry point # 951 # Main routine entry point #
949 # ======================== # 952 # ======================== #
950 if __name__ == '__main__': 953 if __name__ == '__main__':
951 -  
952 # Create instance of application 954 # Create instance of application
953 app = csscs(sys.argv) 955 app = csscs(sys.argv)
954 956
cscripts/obsutils.py
@@ -775,18 +775,14 @@ def get_onoff_obs(cls, obs, nthreads=0, ra = None, dec = None, srcname = &#39;&#39;): @@ -775,18 +775,14 @@ def get_onoff_obs(cls, obs, nthreads=0, ra = None, dec = None, srcname = &#39;&#39;):
775 775
776 # Initialise inmodel, inexclusion and use_model_bkg 776 # Initialise inmodel, inexclusion and use_model_bkg
777 inmodel = 'NONE' 777 inmodel = 'NONE'
778 - inexclusion = 'NONE'  
779 use_model_bkg = True 778 use_model_bkg = True
780 779
781 - # Set inmodel, srcname, inexclusion and use_model_bkg if they are available 780 + # Set inmodel, srcname, and use_model_bkg if they are available
782 if cls.has_par('inmodel') and obs.models().size() == 0: 781 if cls.has_par('inmodel') and obs.models().size() == 0:
783 if cls['inmodel'].is_valid(): 782 if cls['inmodel'].is_valid():
784 inmodel = cls['inmodel'].value() 783 inmodel = cls['inmodel'].value()
785 if srcname == '' and cls.has_par('srcname'): 784 if srcname == '' and cls.has_par('srcname'):
786 srcname = cls['srcname'].value() 785 srcname = cls['srcname'].value()
787 - if cls.has_par('inexclusion'):  
788 - if cls['inexclusion'].is_valid():  
789 - inexclusion = cls['inexclusion'].value()  
790 if cls.has_par('use_model_bkg'): 786 if cls.has_par('use_model_bkg'):
791 use_model_bkg = cls['use_model_bkg'].boolean() 787 use_model_bkg = cls['use_model_bkg'].boolean()
792 788
@@ -794,7 +790,6 @@ def get_onoff_obs(cls, obs, nthreads=0, ra = None, dec = None, srcname = &#39;&#39;): @@ -794,7 +790,6 @@ def get_onoff_obs(cls, obs, nthreads=0, ra = None, dec = None, srcname = &#39;&#39;):
794 phagen = cscripts.csphagen(obs) 790 phagen = cscripts.csphagen(obs)
795 phagen['inmodel'] = inmodel 791 phagen['inmodel'] = inmodel
796 phagen['srcname'] = srcname 792 phagen['srcname'] = srcname
797 - phagen['inexclusion'] = inexclusion  
798 phagen['emin'] = cls['emin'].real() 793 phagen['emin'] = cls['emin'].real()
799 phagen['emax'] = cls['emax'].real() 794 phagen['emax'] = cls['emax'].real()
800 phagen['enumbins'] = cls['enumbins'].integer() 795 phagen['enumbins'] = cls['enumbins'].integer()
@@ -830,13 +825,21 @@ def get_onoff_obs(cls, obs, nthreads=0, ra = None, dec = None, srcname = &#39;&#39;): @@ -830,13 +825,21 @@ def get_onoff_obs(cls, obs, nthreads=0, ra = None, dec = None, srcname = &#39;&#39;):
830 phagen['debug'] = cls['debug'].boolean() 825 phagen['debug'] = cls['debug'].boolean()
831 phagen['nthreads'] = nthreads 826 phagen['nthreads'] = nthreads
832 827
833 - # Pipe exclusion map 828 + # Pipe exclusion map in memory
834 if hasattr(cls, 'exclusion_map'): 829 if hasattr(cls, 'exclusion_map'):
835 exclusion_map = cls.exclusion_map() 830 exclusion_map = cls.exclusion_map()
836 if exclusion_map is not None: 831 if exclusion_map is not None:
837 phagen.exclusion_map(exclusion_map) 832 phagen.exclusion_map(exclusion_map)
  833 + # Otherwise try to read it as user parameter
  834 + elif cls.has_par('inexclusion'):
  835 + if cls['inexclusion'].is_valid():
  836 + inexclusion = cls['inexclusion'].value()
  837 + phagen['inexclusion'] = inexclusion
  838 + # Otherwise set to None
  839 + else:
  840 + phagen['inexclusion'] = 'NONE'
838 841
839 - # Run csphagen 842 + # Run csphagen
840 phagen.run() 843 phagen.run()
841 844
842 # Clone resulting observation container 845 # Clone resulting observation container
test/test_csscs.py
@@ -18,9 +18,9 @@ @@ -18,9 +18,9 @@
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 # 19 #
20 # ========================================================================== 20 # ==========================================================================
21 -import os  
22 -import gammalib  
23 import cscripts 21 import cscripts
  22 +import gammalib
  23 +import os
24 from testing import test 24 from testing import test
25 25
26 26
@@ -43,6 +43,15 @@ class Test(test): @@ -43,6 +43,15 @@ class Test(test):
43 # Call base class constructor 43 # Call base class constructor
44 test.__init__(self) 44 test.__init__(self)
45 45
  46 + # Set test datasets and parameters
  47 + self._evs_offaxis = self._datadir + '/crab_offaxis1.fits'
  48 + self._exclusion = self._datadir + '/crab_exclusion.fits'
  49 + self._expcube = self._datadir + '/crab_expcube.fits'
  50 + self._psfcube = self._datadir + '/crab_psfcube.fits'
  51 + self._bkgcube = self._datadir + '/crab_bkgcube.fits'
  52 + self._bkgmodel = self._datadir + '/crab_bkgcube.xml'
  53 + self._edispcube = self._datadir + '/crab_edispcube.fits'
  54 +
46 # Return 55 # Return
47 return 56 return
48 57
@@ -71,11 +80,38 @@ class Test(test): @@ -71,11 +80,38 @@ class Test(test):
71 csscs = self._script('csscs') 80 csscs = self._script('csscs')
72 81
73 # Setup csscs command 82 # Setup csscs command
74 - cmd = csscs+' logfile="csscs_cmd1.log" chatter=1' 83 + cmd = csscs + ' inobs="' + self._cntcube + '"' + \
  84 + ' expcube="' + self._expcube + '"' + \
  85 + ' psfcube="' + self._psfcube + '"' + \
  86 + ' bkgcube="' + self._bkgcube + '"' + \
  87 + ' inmodel="' + self._bkgmodel + '"' + \
  88 + ' srcnames="Crab"' + \
  89 + ' emin=1. emax=100.0 nxpix=2 nypix=2' + \
  90 + ' binsz=0.1 coordsys="CEL" proj="CAR"' + \
  91 + ' xref=83.63 yref=22.01 rad=0.2' + \
  92 + ' outfile="csscs_cmd1.fits"' + \
  93 + ' logfile="csscs_cmd1.log" chatter=1'
75 94
76 # Check if execution was successful 95 # Check if execution was successful
77 self.test_value(self._execute(cmd), 0, 96 self.test_value(self._execute(cmd), 0,
78 - 'Check successful execution from command line') 97 + 'Check successful execution from command line')
  98 +
  99 + # Setup csscs command
  100 + cmd = csscs + ' inobs="' + self._cntcube + '"' + \
  101 + ' expcube="' + self._expcube + '"' + \
  102 + ' psfcube="' + self._psfcube + '"' + \
  103 + ' bkgcube="' + self._bkgcube + '"' + \
  104 + ' inmodel="' + self._bkgmodel + '"' + \
  105 + ' srcnames="Crab;source_that_is_not_in_the_model"' + \
  106 + ' emin=1. emax=100.0 nxpix=2 nypix=2' + \
  107 + ' binsz=0.1 coordsys="CEL" proj="CAR"' + \
  108 + ' xref=83.63 yref=22.01 rad=0.2' + \
  109 + ' outfile="csscs_cmd1.fits"' + \
  110 + ' logfile="csscs_cmd1.log" chatter=1'
  111 +
  112 + # Check if execution failed
  113 + self.test_assert(self._execute(cmd, success=False) != 0,
  114 + 'Check invalid source name when executed from command line')
79 115
80 # Check csscs --help 116 # Check csscs --help
81 self._check_help(csscs) 117 self._check_help(csscs)
@@ -93,24 +129,266 @@ class Test(test): @@ -93,24 +129,266 @@ class Test(test):
93 129
94 # Check that saving does not nothing 130 # Check that saving does not nothing
95 script['logfile'] = 'csscs_py0.log' 131 script['logfile'] = 'csscs_py0.log'
  132 + script['outfile'] = 'csscs_py0.fits'
96 script.logFileOpen() 133 script.logFileOpen()
97 script.save() 134 script.save()
98 self.test_assert(not os.path.isfile('csscs_py0.fits'), 135 self.test_assert(not os.path.isfile('csscs_py0.fits'),
99 - 'Check that no FITS file has been created') 136 + 'Check that no FITS file has been created')
100 137
101 # Check that clearing does not lead to an exception or segfault 138 # Check that clearing does not lead to an exception or segfault
102 script.clear() 139 script.clear()
103 140
104 - # Now set csscs parameters 141 + # Set up csscs for simple binned analysis
105 script['logfile'] = 'csscs_py1.log' 142 script['logfile'] = 'csscs_py1.log'
  143 + script['inobs'] = self._cntcube
  144 + script['expcube'] = self._expcube
  145 + script['psfcube'] = self._psfcube
  146 + script['bkgcube'] = self._bkgcube
  147 + script['inmodel'] = self._bkgmodel
  148 + script['srcnames'] = 'Crab'
  149 + script['emin'] = 1.
  150 + script['emax'] = 100.
  151 + script['nxpix'] = 2
  152 + script['nypix'] = 2
  153 + script['binsz'] = 0.1
  154 + script['coordsys'] = 'CEL'
  155 + script['proj'] = 'CAR'
  156 + script['xref'] = 83.63
  157 + script['yref'] = 22.01
  158 + script['rad'] = 0.2
  159 + script['outfile'] = 'csscs_py1.fits'
  160 + script['chatter'] = 4
  161 +
  162 + # Run csscs script and save results
  163 + script.logFileOpen()
  164 + script.execute()
  165 +
  166 + # Check result
  167 + self._check_result_file('csscs_py1.fits')
  168 +
  169 + # Set up for same test without TS computation
  170 + script = cscripts.csscs()
  171 + script['logfile'] = 'csscs_py2.log'
  172 + script['inobs'] = self._cntcube
  173 + script['expcube'] = self._expcube
  174 + script['psfcube'] = self._psfcube
  175 + script['bkgcube'] = self._bkgcube
  176 + script['inmodel'] = self._bkgmodel
  177 + script['srcnames'] = 'Crab'
  178 + script['emin'] = 1.
  179 + script['emax'] = 100.
  180 + script['nxpix'] = 2
  181 + script['nypix'] = 2
  182 + script['binsz'] = 0.1
  183 + script['coordsys'] = 'CEL'
  184 + script['proj'] = 'CAR'
  185 + script['xref'] = 83.63
  186 + script['yref'] = 22.01
  187 + script['rad'] = 0.2
  188 + script['calc_ts'] = False
  189 + script['outfile'] = 'csscs_py2.fits'
  190 + script['chatter'] = 2
  191 +
  192 + # Run csscs script and save results
  193 + script.logFileOpen()
  194 + script.execute()
  195 +
  196 + # Check result
  197 + self._check_result_file('csscs_py2.fits', calc_ts=False)
  198 +
  199 + # # Set up for same test with upper limit computation
  200 + script = cscripts.csscs()
  201 + script['logfile'] = 'csscs_py3.log'
  202 + script['inobs'] = self._cntcube
  203 + script['expcube'] = self._expcube
  204 + script['psfcube'] = self._psfcube
  205 + script['bkgcube'] = self._bkgcube
  206 + script['inmodel'] = self._bkgmodel
  207 + script['srcnames'] = 'Crab'
  208 + script['emin'] = 1.
  209 + script['emax'] = 100.
  210 + script['nxpix'] = 2
  211 + script['nypix'] = 2
  212 + script['binsz'] = 0.1
  213 + script['coordsys'] = 'CEL'
  214 + script['proj'] = 'CAR'
  215 + script['xref'] = 83.63
  216 + script['yref'] = 22.01
  217 + script['rad'] = 0.2
  218 + script['calc_ts'] = True
  219 + script['calc_ulim'] = True
  220 + script['outfile'] = 'csscs_py3.fits'
  221 + script['chatter'] = 2
  222 +
  223 + # Run csscs script and save results
  224 + script.logFileOpen()
  225 + script.execute()
  226 +
  227 + # Check result
  228 + self._check_result_file('csscs_py3.fits', calc_ulim=True)
  229 +
  230 + # # Check that results can be piped in memory
  231 + self._check_results_mem(script, calc_ulim=True)
  232 +
  233 + # Set up for test without multiprocessing
  234 + script = cscripts.csscs()
  235 + script['logfile'] = 'csscs_py4.log'
  236 + script['inobs'] = self._cntcube
  237 + script['expcube'] = self._expcube
  238 + script['psfcube'] = self._psfcube
  239 + script['bkgcube'] = self._bkgcube
  240 + script['inmodel'] = self._bkgmodel
  241 + script['srcnames'] = 'Crab'
  242 + script['emin'] = 1.
  243 + script['emax'] = 100.
  244 + script['nxpix'] = 2
  245 + script['nypix'] = 2
  246 + script['binsz'] = 0.1
  247 + script['coordsys'] = 'CEL'
  248 + script['proj'] = 'CAR'
  249 + script['xref'] = 83.63
  250 + script['yref'] = 22.01
  251 + script['rad'] = 0.2
  252 + script['outfile'] = 'csscs_py4.fits'
  253 + script['nthreads'] = 1
  254 + script['chatter'] = 2
  255 +
  256 + # Run csscs script and save results
  257 + script.logFileOpen()
  258 + script.execute()
  259 +
  260 + # Check result
  261 + self._check_result_file('csscs_py4.fits')
  262 +
  263 + # Set up for test with energy dispersion
  264 + script = cscripts.csscs()
  265 + script['logfile'] = 'csscs_py5.log'
  266 + script['inobs'] = self._cntcube
  267 + script['expcube'] = self._expcube
  268 + script['psfcube'] = self._psfcube
  269 + script['bkgcube'] = self._bkgcube
  270 + script['edisp'] = True
  271 + script['edispcube'] = self._edispcube
  272 + script['inmodel'] = self._bkgmodel
  273 + script['srcnames'] = 'Crab'
  274 + script['emin'] = 1.
  275 + script['emax'] = 100.
  276 + script['nxpix'] = 2
  277 + script['nypix'] = 2
  278 + script['binsz'] = 0.1
  279 + script['coordsys'] = 'CEL'
  280 + script['proj'] = 'CAR'
  281 + script['xref'] = 83.63
  282 + script['yref'] = 22.01
  283 + script['rad'] = 0.2
  284 + script['outfile'] = 'csscs_py5.fits'
  285 + script['chatter'] = 2
  286 +
  287 + # Run csscs script and save results
  288 + script.logFileOpen()
  289 + script.execute()
  290 +
  291 + # Check result
  292 + self._check_result_file('csscs_py5.fits')
  293 +
  294 + # TODO: test unbinned analysis
  295 +
  296 + # Set up for test in On/Off mode with background model
  297 + script = cscripts.csscs()
  298 + script['logfile'] = 'csscs_py6.log'
  299 + script['inobs'] = self._evs_offaxis
  300 + script['caldb'] = self._caldb
  301 + script['irf'] = self._irf
  302 + script['inmodel'] = self._model
  303 + script['srcnames'] = 'Crab'
  304 + script['emin'] = 1.
  305 + script['emax'] = 100.
  306 + script['nxpix'] = 2
  307 + script['nypix'] = 2
  308 + script['binsz'] = 0.1
  309 + script['coordsys'] = 'CEL'
  310 + script['proj'] = 'CAR'
  311 + script['xref'] = 83.63
  312 + script['yref'] = 22.01
  313 + script['rad'] = 0.2
  314 + script['method'] = 'ONOFF'
  315 + script['inexclusion'] = self._exclusion
  316 + script['enumbins'] = 2
  317 + script['outfile'] = 'csscs_py6.fits'
  318 + script['chatter'] = 2
  319 +
  320 + # Run csscs script and save results
  321 + script.logFileOpen()
  322 + script.execute()
  323 +
  324 + # Check result
  325 + self._check_result_file('csscs_py6.fits')
  326 +
  327 + # Same test with exclusion map piped in memory
  328 + script = cscripts.csscs()
  329 + script['logfile'] = 'csscs_py7.log'
  330 + script['inobs'] = self._evs_offaxis
  331 + script['caldb'] = self._caldb
  332 + script['irf'] = self._irf
  333 + script['inmodel'] = self._model
  334 + script['srcnames'] = 'Crab'
  335 + script['emin'] = 1.
  336 + script['emax'] = 100.
  337 + script['nxpix'] = 2
  338 + script['nypix'] = 2
  339 + script['binsz'] = 0.1
  340 + script['coordsys'] = 'CEL'
  341 + script['proj'] = 'CAR'
  342 + script['xref'] = 83.63
  343 + script['yref'] = 22.01
  344 + script['rad'] = 0.2
  345 + script['method'] = 'ONOFF'
  346 + script['enumbins'] = 2
  347 + script['outfile'] = 'csscs_py7.fits'
  348 + script['chatter'] = 2
  349 +
  350 + # Set exclusion map
  351 + exclmap = gammalib.GSkyRegionMap(self._exclusion)
  352 + script.exclusion_map(exclmap)
  353 +
  354 + # Run csscs script and save results
  355 + script.logFileOpen()
  356 + script.execute()
  357 +
  358 + # Check result
  359 + self._check_result_file('csscs_py7.fits')
  360 +
  361 + # Set up for test in On/Off mode without background model
  362 + script = cscripts.csscs()
  363 + script['logfile'] = 'csscs_py8.log'
  364 + script['inobs'] = self._evs_offaxis
  365 + script['caldb'] = self._caldb
  366 + script['irf'] = self._irf
  367 + script['inmodel'] = self._model
  368 + script['srcnames'] = 'Crab'
  369 + script['emin'] = 1.
  370 + script['emax'] = 100.
  371 + script['nxpix'] = 2
  372 + script['nypix'] = 2
  373 + script['binsz'] = 0.1
  374 + script['coordsys'] = 'CEL'
  375 + script['proj'] = 'CAR'
  376 + script['xref'] = 83.63
  377 + script['yref'] = 22.01
  378 + script['rad'] = 0.2
  379 + script['method'] = 'ONOFF'
  380 + script['use_model_bkg'] = False
  381 + script['inexclusion'] = self._exclusion
  382 + script['enumbins'] = 2
  383 + script['outfile'] = 'csscs_py8.fits'
106 script['chatter'] = 2 384 script['chatter'] = 2
107 385
108 - # Run csscs script 386 + # Run csscs script and save results
109 script.logFileOpen() 387 script.logFileOpen()
110 - script.run() 388 + script.execute()
111 389
112 # Check result 390 # Check result
113 - self._check_result(script) 391 + self._check_result_file('csscs_py8.fits')
114 392
115 # Return 393 # Return
116 return 394 return
@@ -126,32 +404,150 @@ class Test(test): @@ -126,32 +404,150 @@ class Test(test):
126 # Setup script for pickling text 404 # Setup script for pickling text
127 script = cscripts.csscs() 405 script = cscripts.csscs()
128 script['logfile'] = 'csscs_py1_pickle.log' 406 script['logfile'] = 'csscs_py1_pickle.log'
  407 + script['inobs'] = self._cntcube
  408 + script['expcube'] = self._expcube
  409 + script['psfcube'] = self._psfcube
  410 + script['bkgcube'] = self._bkgcube
  411 + script['inmodel'] = self._bkgmodel
  412 + script['srcnames'] = 'Crab'
  413 + script['emin'] = 1.
  414 + script['emax'] = 100.
  415 + script['nxpix'] = 2
  416 + script['nypix'] = 2
  417 + script['binsz'] = 0.1
  418 + script['coordsys'] = 'CEL'
  419 + script['proj'] = 'CAR'
  420 + script['xref'] = 83.63
  421 + script['yref'] = 22.01
  422 + script['rad'] = 0.2
  423 + script['outfile'] = 'csscs_py1_pickle.fits'
129 script['chatter'] = 2 424 script['chatter'] = 2
130 425
131 # Perform pickeling tests of filled class 426 # Perform pickeling tests of filled class
132 obj = self._pickeling(script) 427 obj = self._pickeling(script)
133 428
134 # Run csscs script and save result 429 # Run csscs script and save result
135 - obj.logFileOpen() # Make sure we get a log file  
136 - obj.run()  
137 - obj.save() 430 + obj.logFileOpen() # Make sure we get a log file
  431 + obj.execute()
138 432
139 - # TODO: Check result file 433 + # Check result file
  434 + self._check_result_file('csscs_py1_pickle.fits')
140 435
141 # Return 436 # Return
142 return 437 return
143 438
144 - # Check csscs result  
145 - def _check_result(self, script): 439 + # Check access to results in memory'
  440 + def _check_results_mem(self, script, srcnames=['Crab'], nx=2, ny=2, calc_ts=True,
  441 + calc_ulim=False):
146 """ 442 """
147 - Check content of script 443 + Check results in memory
148 444
149 Parameters 445 Parameters
150 ---------- 446 ----------
151 script : `~cscripts.csscs` 447 script : `~cscripts.csscs`
152 - csscs instance 448 + csscs object
  449 + srcnames : list, optional
  450 + Source names
  451 + nx : int, optional
  452 + Number of X pixels
  453 + ny : int, optional
  454 + Number of Y pixels
  455 + calc_ts : bool, optional
  456 + Check TS HDU
  457 + calc_ulim : bool, optional
  458 + Check upper limit HDU
  459 + """
  460 +
  461 + # Check that the entire fits container can be extracted
  462 + fits = script.fits()
  463 + # Dump to disk and verify
  464 + fits.saveto('csscs_py3_mem.fits', True)
  465 + self._check_result_file('csscs_py3_mem.fits', srcnames=srcnames, nx=nx, ny=ny,
  466 + calc_ts=calc_ts, calc_ulim=calc_ulim)
  467 +
  468 + # Now check direct access in memory for skymaps
  469 + # Loop over sources
  470 + for name in srcnames:
  471 + # Check flux map
  472 + skymap = script.flux(name)
  473 + self._check_map(skymap, nx=nx, ny=ny)
  474 + # Check flux error map
  475 + skymap = script.flux_error(name)
  476 + self._check_map(skymap, nx=nx, ny=ny)
  477 + # If requested check TS map
  478 + if calc_ts:
  479 + skymap = script.ts(name)
  480 + self._check_map(skymap, nx=nx, ny=ny)
  481 + # If requested check upper limit map
  482 + if calc_ulim:
  483 + skymap = script.ulimit(name)
  484 + self._check_map(skymap, nx=nx, ny=ny)
  485 +
  486 + return
  487 +
  488 + # Check result file
  489 + def _check_result_file(self, filename, srcnames=['Crab'], nx=2, ny=2,
  490 + calc_ts=True, calc_ulim=False):
  491 + """
  492 + Check result file
  493 +
  494 + Parameters
  495 + ----------
  496 + filename : str
  497 + Sky map file name
  498 + srcnames : list, optional
  499 + Source names
  500 + nx : int, optional
  501 + Number of X pixels
  502 + ny : int, optional
  503 + Number of Y pixels
  504 + calc_ts : bool, optional
  505 + Check TS HDU
  506 + calc_ulim : bool, optional
  507 + Check upper limit HDU
  508 + """
  509 +
  510 + print('ho', calc_ts)
  511 + # Loop over source names
  512 + for name in srcnames:
  513 + # Check flux map
  514 + skymap = gammalib.GSkyMap(filename + '[' + name + ' FLUX]')
  515 + self._check_map(skymap, nx=nx, ny=ny)
  516 + # Check flux error map
  517 + skymap = gammalib.GSkyMap(filename + '[' + name + ' FLUX ERROR]')
  518 + self._check_map(skymap, nx=nx, ny=ny)
  519 + # If requested check TS map
  520 + if calc_ts:
  521 + print('hoho')
  522 + skymap = gammalib.GSkyMap(filename + '[' + name + ' TS]')
  523 + self._check_map(skymap, nx=nx, ny=ny)
  524 + # If requested check upper limit map
  525 + if calc_ulim:
  526 + skymap = gammalib.GSkyMap(filename + '[' + name + ' FLUX UPPER LIMIT]')
  527 + self._check_map(skymap, nx=nx, ny=ny)
  528 +
  529 + # Return
  530 + return
  531 +
  532 + # Check sky map
  533 + def _check_map(self, skymap, nx=2, ny=2):
153 """ 534 """
154 - # TODO: Implement test on script result 535 + Check sky map
  536 +
  537 + Parameters
  538 + ----------
  539 + skymap : `~gammalib.GSkyMap`
  540 + Sky map
  541 + nx : int, optional
  542 + Number of X pixels
  543 + ny : int, optional
  544 + Number of Y pixels
  545 + """
  546 +
  547 + # Check dimensions
  548 + self.test_value(skymap.nmaps(), 1, 'Check number of maps')
  549 + self.test_value(skymap.nx(), nx, 'Check for number of X pixels')
  550 + self.test_value(skymap.ny(), ny, 'Check for number of Y pixels')
155 551
156 # Return 552 # Return
157 return 553 return