112 Get parameters from parfile and setup the observation
115 if self.obs().is_empty():
116 self._require_inobs(
'csspec::get_parameters()')
117 self.obs(self._get_observations())
120 self._set_obs_statistic(gammalib.toupper(self[
'statistic'].string()))
123 if self.obs().
models().is_empty():
124 self.obs().
models(self[
'inmodel'].filename())
127 self[
'srcname'].string()
130 self.
_method = self[
'method'].string()
137 for obs
in self.obs():
138 if obs.classname() ==
'GCTAObservation':
139 if obs.eventtype() ==
'CountsCube':
143 elif obs.classname() ==
'GCTAOnOffObservation':
145 n_cta = n_unbinned + n_binned + n_onoff
146 n_other = self.obs().size() - n_cta
154 if n_unbinned == 0
and n_binned != 0
and n_onoff == 0:
157 elif n_unbinned == 0
and n_binned == 0
and n_onoff != 0:
160 elif n_unbinned == 0
and n_binned != 0
and n_onoff != 0:
161 msg =
'Mix of binned and On/Off CTA observations found ' \
162 'in observation container. csscript does not support ' \
164 raise RuntimeError(msg)
165 elif n_unbinned != 0
and (n_binned != 0
or n_onoff != 0):
166 msg =
'Mix of unbinned and binned or On/Off CTA observations ' \
167 'found in observation container. csscript does not ' \
169 raise RuntimeError(msg)
170 elif n_unbinned != 0:
177 self[
'edisp'].boolean()
178 self[
'calc_ts'].boolean()
179 self[
'calc_ulim'].boolean()
180 self[
'confidence'].real()
181 self[
'fix_bkg'].boolean()
182 self[
'fix_srcs'].boolean()
183 self[
'bingamma'].real()
186 self[
'dll_sigstep'].real()
187 self[
'dll_sigmax'].real()
188 self[
'dll_freenodes'].boolean()
191 if self._read_ahead():
192 self[
'outfile'].filename()
195 self._log_parameters(gammalib.TERSE)
201 self._log_header1(gammalib.TERSE,
'Spectrum method')
202 self._log_value(gammalib.TERSE,
'Unbinned CTA observations', n_unbinned)
203 self._log_value(gammalib.TERSE,
'Binned CTA observations', n_binned)
204 self._log_value(gammalib.TERSE,
'On/off CTA observations', n_onoff)
205 self._log_value(gammalib.TERSE,
'Other observations', n_other)
211 if n_cta > 0
and n_other > 0
and self.
_method ==
'SLICE':
218 msg =
'Selected "SLICE" method but none of the observations ' \
219 'is a CTA observation. Please select "AUTO", "NODES" ' \
220 'or "BINS" if no CTA observation is provided.'
221 raise RuntimeError(msg)
226 self._log_value(gammalib.TERSE,
'Selected spectrum method', self.
_method)
230 self._log_string(gammalib.TERSE,
' WARNING: Only CTA observation '
231 'can be handled with the "SLICE" method, all '
232 'non-CTA observation will be ignored.')
239 Set energy boundaries
249 ebounds = self._create_ebounds()
257 cube_ebounds = self.obs()[0].events().ebounds()
259 cube_ebounds = self.obs()[0].rmf().emeasured()
263 for i
in range(ebounds.size()):
267 emin = ebounds.emin(i).TeV() * 0.999
268 emax = ebounds.emax(i).TeV() * 1.001
276 for k
in range(cube_ebounds.size()):
277 if cube_ebounds.emin(k).TeV() >= emin
and \
278 cube_ebounds.emax(k).TeV() <= emax:
279 emin_value = cube_ebounds.emin(k).TeV()
285 for k
in range(cube_ebounds.size()):
286 if cube_ebounds.emin(k).TeV() >= emin
and \
287 cube_ebounds.emax(k).TeV() <= emax:
288 emax_value = cube_ebounds.emax(k).TeV()
294 self.
_ebounds.append(gammalib.GEnergy(emin_value,
'TeV'),
295 gammalib.GEnergy(emax_value,
'TeV'))
299 msg =
'Energy range ['+str(cube_ebounds.emin())+ \
300 ', '+str(cube_ebounds.emax())+
'] of counts '+ \
301 'cube does not overlap with specified energy '+ \
303 str(ebounds.emin())+
', '+str(ebounds.emax())+
'].'+ \
304 ' Specify overlapping energy range.'
305 raise RuntimeError(msg)
309 self.
_ebounds = self._create_ebounds()
319 self._log_header1(gammalib.TERSE,
'Spectral binning')
323 cube_ebounds = self.obs()[0].events().ebounds()
324 value =
'%s - %s' % (str(cube_ebounds.emin()),
325 str(cube_ebounds.emax()))
326 self._log_value(gammalib.TERSE,
'Counts cube energy range', value)
330 etrue = self.obs()[0].rmf().etrue()
331 ereco = self.obs()[0].rmf().emeasured()
332 vtrue =
'%s - %s' % (str(etrue.emin()), str(etrue.emax()))
333 vreco =
'%s - %s' % (str(ereco.emin()), str(ereco.emax()))
334 self._log_value(gammalib.TERSE,
'RMF true energy range', vtrue)
335 self._log_value(gammalib.TERSE,
'RMF measured energy range', vreco)
338 for i
in range(self.
_ebounds.size()):
339 value =
'%s - %s' % (str(self.
_ebounds.emin(i)),
341 self._log_value(gammalib.TERSE,
'Bin %d' % (i+1), value)
348 Adjust model parameters
351 self._log_header1(gammalib.TERSE,
'Adjust model parameters')
354 for model
in self.obs().
models():
360 self._log_header3(gammalib.NORMAL, model.name())
363 if model.name() == self[
'srcname'].string():
368 self._log_string(gammalib.NORMAL,
369 ' Fixing "'+par.name()+
'"')
378 self._log_string(gammalib.NORMAL,
' Converting spectral model '
379 'into file function')
382 energies = gammalib.GEnergies(num, self.
_ebounds.emin(0),
385 spectral = gammalib.GModelSpectralFunc()
386 spectral.reserve(num)
388 for energy
in energies:
389 value = model.spectral().eval(energy)
391 if last_value != 0.0:
392 new_value = last_value
395 self._log_string(gammalib.NORMAL,
396 ' Spectrum('+str(energy)+
')='+str(value)+
'. '
397 'Set value to '+str(new_value)+
'.')
399 spectral.append(energy, value)
401 model.spectral(spectral)
405 normpar = model.spectral()[0]
406 if normpar.is_fixed():
407 self._log_string(gammalib.NORMAL,
408 ' Freeing "'+normpar.name()+
'"')
412 if self[
'calc_ts'].boolean():
416 elif self[
'fix_bkg'].boolean()
and \
417 not model.classname() ==
'GModelSky':
420 self._log_string(gammalib.NORMAL,
421 ' Fixing "'+par.name()+
'"')
425 elif self[
'fix_srcs'].boolean()
and \
426 model.classname() ==
'GModelSky':
429 self._log_string(gammalib.NORMAL,
430 ' Fixing "'+par.name()+
'"')
553 Select an energy interval from one CTA On/Off observation
557 obs : `~gammalib.GCTAOnOffObservation`
559 emin : `~gammalib.GEnergy()`
561 emax : `~gammalib.GEnergy()`
566 obs : `~gammalib.GCTAOnOffObservation`
567 CTA On/Off observation
572 etrue = obs.rmf().etrue()
573 ereco = gammalib.GEbounds()
574 itrue = [i
for i
in range(obs.rmf().etrue().size())]
576 for i
in range(obs.rmf().emeasured().size()):
577 ereco_bin_min = obs.rmf().emeasured().emin(i)
578 ereco_bin_max = obs.rmf().emeasured().emax(i)
579 if ereco_bin_min * 1.001 >= emin
and ereco_bin_max * 0.999 <= emax:
580 ereco.append(ereco_bin_min, ereco_bin_max)
584 pha_on = gammalib.GPha(ereco)
585 pha_off = gammalib.GPha(ereco)
586 pha_on.exposure(obs.on_spec().exposure())
587 pha_off.exposure(obs.on_spec().exposure())
588 for idst, isrc
in enumerate(ireco):
590 pha_on[idst] = obs.on_spec()[isrc]
591 pha_on.areascal(idst, obs.on_spec().areascal(isrc))
592 pha_on.backscal(idst, obs.on_spec().backscal(isrc))
594 pha_off[idst] = obs.off_spec()[isrc]
595 pha_off.areascal(idst, obs.off_spec().areascal(isrc))
596 pha_off.backscal(idst, obs.off_spec().backscal(isrc))
599 pha_backresp = obs.off_spec()[
'BACKRESP']
601 for idst, isrc
in enumerate(ireco):
602 backresp.append(pha_backresp[isrc])
603 pha_off.append(
'BACKRESP', backresp)
606 arf = gammalib.GArf(etrue)
607 for idst, isrc
in enumerate(itrue):
608 arf[idst] = obs.arf()[isrc]
611 rmf = gammalib.GRmf(etrue, ereco)
612 for idst_true, isrc_true
in enumerate(itrue):
613 for idst_reco, isrc_reco
in enumerate(ireco):
614 rmf[idst_true, idst_reco] = obs.rmf()[isrc_true, isrc_reco]
618 statistic = obs.statistic()
619 instrument = obs.instrument()
620 obs = gammalib.GCTAOnOffObservation(pha_on, pha_off, arf, rmf)
622 obs.statistic(statistic)
623 obs.instrument(instrument)
630 Select observations for energy interval
634 emin : `~gammalib.GEnergy()`
636 emax : `~gammalib.GEnergy()`
641 obs : `~gammalib.GObservations`
642 Observation container
648 self._log_header3(gammalib.EXPLICIT,
'Filtering cube')
651 cubemask = ctools.ctcubemask(self.obs())
652 cubemask[
'regfile'] =
'NONE'
653 cubemask[
'ra'] =
'UNDEFINED'
654 cubemask[
'dec'] =
'UNDEFINED'
655 cubemask[
'rad'] =
'UNDEFINED'
656 cubemask[
'emin'] = emin.TeV()
657 cubemask[
'emax'] = emax.TeV()
661 if self._logVerbose()
and self._logDebug():
662 cubemask[
'debug'] =
True
668 obs = cubemask.obs().copy()
674 self._log_header3(gammalib.EXPLICIT,
'Filtering PHA, ARF and RMF')
677 obs = gammalib.GObservations()
681 for run
in self.obs():
682 if run.classname() ==
'GCTAOnOffObservation':
686 obs.models(self.obs().
models())
692 self._log_header3(gammalib.EXPLICIT,
'Selecting events')
695 select = ctools.ctselect(self.obs())
696 select[
'ra'] =
'UNDEFINED'
697 select[
'dec'] =
'UNDEFINED'
698 select[
'rad'] =
'UNDEFINED'
699 select[
'emin'] = emin.TeV()
700 select[
'emax'] = emax.TeV()
701 select[
'tmin'] =
'UNDEFINED'
702 select[
'tmax'] =
'UNDEFINED'
706 if self._logVerbose()
and self._logDebug():
707 select[
'debug'] =
True
713 obs = select.obs().copy()
720 Fit data for one energy bin
730 Dictionary with fit results
734 self._log_header2(gammalib.EXPLICIT,
'Energy bin ' + str(i + 1))
739 elogmean = self.
_ebounds.elogmean(i)
740 e_scale = elogmean.MeV() * elogmean.MeV() * gammalib.MeV2erg
746 result = {
'energy': elogmean.TeV(),
747 'energy_low': (elogmean - emin).TeV(),
748 'energy_high': (emax - elogmean).TeV(),
760 self._log_header3(gammalib.EXPLICIT,
'Performing fit in energy bin')
763 like = ctools.ctlike(obs)
764 like[
'edisp'] = self[
'edisp'].boolean()
769 if self._logVerbose()
and self._logDebug():
776 self._log_string(gammalib.EXPLICIT, str(like.obs().
models()))
779 if like.obs().logL() != 0.0:
782 fitted_models = like.obs().
models()
783 source = fitted_models[self[
'srcname'].string()]
786 if self[
'dll_sigstep'].real() > 0.0:
789 parname = source.spectral()[0].name()
790 (norm_scan, dlogL, loglike) = self.
_profile_logL(like.copy(), parname, elogmean)
791 result[
'norm_scan'] = norm_scan
792 result[
'dloglike'] = dlogL
793 result[
'logL'] = loglike
796 if self[
'calc_ts'].boolean():
797 result[
'TS'] = source.ts()
801 for observation
in like.obs():
802 result[
'Npred'] += observation.npred(source)
806 if self[
'calc_ulim'].boolean():
809 self._log_header3(gammalib.EXPLICIT,
810 'Computing upper limit for energy bin')
813 ulimit = ctools.ctulimit(like.obs())
814 ulimit[
'srcname'] = self[
'srcname'].string()
815 ulimit[
'eref'] = elogmean.TeV()
816 ulimit[
'confidence'] = self[
'confidence'].real()
820 if self._logVerbose()
and self._logDebug():
821 ulimit[
'debug'] =
True
826 ulimit_value = ulimit.diff_ulimit()
828 self._log_string(gammalib.EXPLICIT,
'Upper limit '
829 'calculation failed.')
833 if ulimit_value > 0.0:
834 result[
'ulimit'] = ulimit_value
837 fitted_flux = source.spectral().eval(elogmean)
838 parvalue = source.spectral()[0].value()
840 rel_error = source.spectral()[0].error() / parvalue
841 e_flux = fitted_flux * rel_error
847 if source.spatial().classname() ==
'GModelSpatialDiffuseCube':
848 region = gammalib.GSkyRegionCircle(0.0, 0.0, 180.0)
849 source.spatial().mc_cone(region)
850 norm = source.spatial().
spectrum().eval(elogmean)
855 result[
'flux'] = fitted_flux
856 result[
'e2dnde'] = fitted_flux * e_scale
857 result[
'flux_err'] = e_flux
860 value =
'%e +/- %e' % (result[
'e2dnde'], result[
'flux_err']*e_scale)
861 if self[
'calc_ulim'].boolean()
and result[
'ulimit'] > 0.0:
862 value +=
' [< %e]' % (result[
'ulimit']*e_scale)
863 value +=
' erg/cm2/s'
864 if self[
'calc_ts'].boolean()
and result[
'TS'] > 0.0:
865 value +=
' (TS = %.3f)' % (result[
'TS'])
866 self._log_value(gammalib.TERSE,
'Bin '+str(i+1), value)
871 value =
'Likelihood is zero. Bin is skipped.'
872 self._log_value(gammalib.TERSE,
'Bin '+str(i+1), value)
879 Fit model to energy bins
883 results : list of dict
884 List of dictionaries with fit results
887 self._log_header1(gammalib.TERSE,
'Generate spectrum')
888 self._log_string(gammalib.TERSE, str(self.
_ebounds))
897 args = [(self,
'_fit_energy_bin', i)
898 for i
in range(self.
_ebounds.size())]
899 poolresults = mputils.process(self.
_nthreads, mputils.mpfunc, args)
902 for i
in range(self.
_ebounds.size()):
903 results.append(poolresults[i][0])
904 self._log_string(gammalib.TERSE, poolresults[i][1][
'log'],
False)
908 for i
in range(self.
_ebounds.size()):
914 results.append(result)
921 Fit model to observations
925 results : list of dict
926 List of dictionaries with fit results
929 self._log_header1(gammalib.TERSE,
'Generate spectrum')
932 self._log_header3(gammalib.EXPLICIT,
'Performing model fit')
935 like = ctools.ctlike(self.obs())
936 like[
'edisp'] = self[
'edisp'].boolean()
943 model = like.obs().
models()[self[
'srcname'].string()]
944 spectrum = model.spectral()
945 logL0 = like.obs().logL()
948 self._log_string(gammalib.EXPLICIT, str(like.obs().
models()))
951 for i
in range(self.
_ebounds.size()):
956 elogmean = self.
_ebounds.elogmean(i)
959 result = {
'energy': elogmean.TeV(),
960 'energy_low': (elogmean - emin).TeV(),
961 'energy_high': (emax - elogmean).TeV(),
973 norm = elogmean.MeV() * elogmean.MeV() * gammalib.MeV2erg
974 result[
'flux'] = spectrum.intensity(i)
975 result[
'e2dnde'] = spectrum.intensity(i) * norm
976 result[
'flux_err'] = spectrum.error(i)
980 parname =
'Intensity%d' % i
983 if self[
'dll_sigstep'].real() > 0.0:
986 (norm_scan, dlogL, loglike) = self.
_profile_logL(like.copy(),
989 result[
'norm_scan'] = norm_scan
990 result[
'dloglike'] = dlogL
991 result[
'logL'] = loglike
994 if self[
'calc_ulim'].boolean():
997 self._log_header3(gammalib.EXPLICIT,
998 'Computing upper limit for node energy %f TeV' %
1002 obs = like.obs().copy()
1005 spectral = obs.models()[self[
'srcname'].string()].spectral()
1006 for par
in spectral:
1010 ulimit = ctools.ctulimit(obs)
1011 ulimit[
'srcname'] = self[
'srcname'].string()
1012 ulimit[
'parname'] = parname
1013 ulimit[
'eref'] = elogmean.TeV()
1014 ulimit[
'confidence'] = self[
'confidence'].real()
1015 ulimit[
'tol'] = 1.0e-3
1020 ulimit_value = ulimit.diff_ulimit()
1022 self._log_string(gammalib.EXPLICIT,
'Upper limit '
1023 'calculation failed.')
1027 if ulimit_value > 0.0:
1028 result[
'ulimit'] = ulimit_value
1031 if self[
'calc_ts'].boolean():
1034 obs = like.obs().copy()
1038 par = obs.models()[self[
'srcname'].string()].spectral()[parname]
1040 par.factor_min(1.0e-8)
1041 par.factor_value(1.0e-8)
1046 tslike = ctools.ctlike(obs)
1047 tslike[
'edisp'] = self[
'edisp'].boolean()
1051 model = tslike.obs().
models()[self[
'srcname'].string()]
1052 logL1 = tslike.obs().logL()
1053 result[
'TS'] = 2.0 * (logL1 - logL0)
1056 value =
'%e +/- %e' % (result[
'e2dnde'], result[
'flux_err']*norm)
1057 if self[
'calc_ulim'].boolean()
and result[
'ulimit'] > 0.0:
1058 value +=
' [< %e]' % (result[
'ulimit']*norm)
1059 value +=
' erg/cm2/s'
1060 if self[
'calc_ts'].boolean()
and result[
'TS'] > 0.0:
1061 value +=
' (TS = %.3f)' % (result[
'TS'])
1062 self._log_value(gammalib.TERSE,
'Bin '+str(i+1), value)
1065 results.append(result)
1072 Computes the delta log-likelihood profile in a single energy bin
1076 like : `~ctools.ctlike()`
1077 ctlike fitter containing prefit model
1079 Name of the spectral parameter to be fit
1080 elogmean : `~gammalib.GEnergy()`
1081 Energy at which the model is to be evaluated
1086 Normalization values
1087 dloglike_scan : list
1088 Computed loglikelihood values
1090 Computed reference log-likelihood for dloglike_scan
1093 dll_sigmax = self[
'dll_sigmax'].real()
1094 dll_sigstep = self[
'dll_sigstep'].real()
1095 sigsteps = int(2 * (dll_sigmax/dll_sigstep) + 1)
1098 source = like.obs().
models()[self[
'srcname'].string()]
1099 spectral = source.spectral()
1100 flux_par = spectral[parname]
1101 norm = flux_par.value()
1102 norm_err = flux_par.error()
1103 source.tscalc(
False)
1107 (
not self[
'dll_freenodes'].boolean()):
1108 for par
in spectral:
1113 loglike = like.obs().logL()
1120 ref_norm = spectral.eval(elogmean)
1123 log_norm = math.log10(norm)
1124 if (norm_err > 0.0)
and (norm > norm_err):
1125 log_step = log_norm - math.log10(norm-norm_err)
1126 log_start = log_norm - (sigsteps/2) * log_step
1130 log_start = log_norm
1131 if log_start > -24.0:
1133 log_step = (-14.0 - log_start) / (sigsteps-1)
1134 norm_vals = [10.0 ** (log_start + i*log_step)
for i
in range(sigsteps)]
1137 flux_par.factor_min(0.0)
1138 flux_par.factor_max(1e30)
1139 for new_norm
in norm_vals:
1140 flux_par.value(new_norm)
1146 dloglike.append(loglike - like.obs().logL())
1148 norm_scan.append(spectral.eval(elogmean))
1150 norm_scan.append(new_norm)
1153 return (norm_scan, dloglike, -loglike)
1161 results : list of dict
1162 List of result dictionaries
1166 ncols = len(results[0][
'norm_scan'])
1167 energy = gammalib.GFitsTableDoubleCol(
'e_ref', nrows)
1168 energy_low = gammalib.GFitsTableDoubleCol(
'e_min', nrows)
1169 energy_high = gammalib.GFitsTableDoubleCol(
'e_max', nrows)
1170 norm = gammalib.GFitsTableDoubleCol(
'norm', nrows)
1171 norm_err = gammalib.GFitsTableDoubleCol(
'norm_err', nrows)
1172 norm_ul = gammalib.GFitsTableDoubleCol(
'norm_ul', nrows)
1173 e2dnde = gammalib.GFitsTableDoubleCol(
'ref_e2dnde', nrows)
1174 dnde = gammalib.GFitsTableDoubleCol(
'ref_dnde', nrows)
1175 Npred_values = gammalib.GFitsTableDoubleCol(
'ref_npred', nrows)
1176 TSvalues = gammalib.GFitsTableDoubleCol(
'ts', nrows)
1177 loglike = gammalib.GFitsTableDoubleCol(
'loglike', nrows)
1178 norm_scan = gammalib.GFitsTableDoubleCol(
'norm_scan', nrows, ncols)
1179 dloglike_scan= gammalib.GFitsTableDoubleCol(
'dloglike_scan', nrows, ncols)
1181 energy_low.unit(
'TeV')
1182 energy_high.unit(
'TeV')
1186 e2dnde.unit(
'erg/cm2/s')
1187 dnde.unit(
'counts/MeV/cm2/s')
1188 Npred_values.unit(
'counts')
1191 dloglike_scan.unit(
'')
1194 for i, result
in enumerate(results):
1195 energy[i] = result[
'energy']
1196 energy_low[i] = result[
'energy_low']
1197 energy_high[i] = result[
'energy_high']
1199 if result[
'flux'] != 0.0:
1200 norm_err[i] = result[
'flux_err'] / result[
'flux']
1201 norm_ul[i] = result[
'ulimit'] / result[
'flux']
1205 e2dnde[i] = result[
'e2dnde']
1206 dnde[i] = result[
'flux']
1207 Npred_values[i] = result[
'Npred']
1208 TSvalues[i] = result[
'TS']
1209 loglike[i] = result[
'logL']
1212 for fbin
in range(ncols):
1213 dloglike_scan[i,fbin] = result[
'dloglike'][fbin]
1214 if result[
'flux'] != 0.0:
1215 norm_scan[i,fbin] = result[
'norm_scan'][fbin] / result[
'flux']
1217 norm_scan[i,fbin] = 0.0
1220 table = gammalib.GFitsBinTable(nrows)
1221 table.extname(
'SPECTRUM')
1224 table.card(
'INSTRUME',
'CTA',
'Name of Instrument')
1225 table.card(
'TELESCOP',
'CTA',
'Name of Telescope')
1228 table.append(energy)
1229 table.append(energy_low)
1230 table.append(energy_high)
1232 table.append(norm_err)
1233 table.append(norm_ul)
1234 table.append(e2dnde)
1236 table.append(TSvalues)
1237 table.append(Npred_values)
1240 table.card(
'SED_TYPE',
'norm,e2dnde,dnde,npred',
'SED type')
1241 table.card(
'UL_CONF', self[
'confidence'].real(),
'Confidence level of upper limits')
1245 table.card(
'SED_TYPE').value(
'likelihood,e2dnde,dnde,npred')
1246 table.append(loglike)
1247 table.append(norm_scan)
1248 table.append(dloglike_scan)
1254 table.card(
'OBJECT', self[
'srcname'].string(),
'Source name')
1255 table.card(
'METHOD', self.
_method,
'Spectrum generation method')
1257 table.card(
'BINGAMMA', self[
'bingamma'].real(),
'Spectral index for BINS method')
1258 table.card(
'STAT', self[
'statistic'].string(),
'Optimization statistic')
1259 table.card(
'EDISP', self[
'edisp'].boolean(),
'Use energy dispersion?')
1260 table.card(
'CALCULIM', self[
'calc_ulim'].boolean(),
'Upper limits computation')
1261 table.card(
'CALCTS', self[
'calc_ts'].boolean(),
'Test statistic computation')
1262 table.card(
'FIXBKG', self[
'fix_bkg'].boolean(),
'Fix background parameters')
1263 table.card(
'FIXSRCS', self[
'fix_srcs'].boolean(),
'Fix other source parameters')
1266 self.
_fits = gammalib.GFits()
1267 self.
_fits.append(table)