test_OnOff_latest.py

Brun Francois, 10/06/2016 05:14 PM

Download (22.7 KB)

 
1
#! /Applications/Anaconda/bin/python
2
# ====================================================================
3
# This script tests the ON-OFF analysis functionality of the gammalib
4
# ====================================================================
5

    
6
from ctools import *
7
from gammalib import *
8
from math import *
9
from cscripts import obsutils
10

    
11
import os
12
import glob
13
import sys
14

    
15
import numpy
16

    
17
# ======================== #
18
# Setup single observation #
19
# ======================== #
20
def single_obs(pntdir, tstart=0.0, duration=1800.0, deadc=0.95, \
21
            emin=0.1, emax=100.0, rad=5.0, \
22
            irf="South_50h", caldb="prod2", id="000000", instrument="CTA"):
23
    """
24
    Returns a single CTA observation.
25

26
    Parameters:
27
     pntdir   - Pointing direction [GSkyDir]
28
    Keywords:
29
     tstart     - Start time [seconds] (default: 0.0)
30
     duration   - Duration of observation [seconds] (default: 1800.0)
31
     deadc      - Deadtime correction factor (default: 0.95)
32
     emin       - Minimum event energy [TeV] (default: 0.1)
33
     emax       - Maximum event energy [TeV] (default: 100.0)
34
     rad        - ROI radius used for analysis [deg] (default: 5.0)
35
     irf        - Instrument response function (default: cta_dummy_irf)
36
     caldb      - Calibration database path (default: "dummy")
37
     id         - Run identifier (default: "000000")
38
     instrument - Intrument (default: "CTA")
39
    """
40
    # Allocate CTA observation
41
    obs_cta = GCTAObservation()
42

    
43
    # Set calibration database
44
    db = GCaldb()
45
    if (os.path.isdir(caldb)):
46
        db.rootdir(caldb)
47
    else:
48
        db.open("cta", caldb)
49

    
50
    # Set pointing direction
51
    pnt = GCTAPointing()
52
    pnt.dir(pntdir)
53
    obs_cta.pointing(pnt)
54

    
55
    # Set ROI
56
    roi     = GCTARoi()
57
    instdir = GCTAInstDir()
58
    instdir.dir(pntdir)
59
    roi.centre(instdir)
60
    roi.radius(rad)
61

    
62
    # Set GTI
63
    gti = GGti()
64
    gti.append(GTime(tstart), GTime(tstart+duration))
65

    
66
    # Set energy boundaries
67
    ebounds = GEbounds(GEnergy(emin, "TeV"), \
68
                                GEnergy(emax, "TeV"))
69

    
70
    # Allocate event list
71
    events = GCTAEventList()
72
    events.roi(roi)
73
    events.gti(gti)
74
    events.ebounds(ebounds)
75
    obs_cta.events(events)
76

    
77
    # Set instrument response
78
    obs_cta.response(irf, db)
79

    
80
    # Set ontime, livetime, and deadtime correction factor
81
    obs_cta.ontime(duration)
82
    obs_cta.livetime(duration*deadc)
83
    obs_cta.deadc(deadc)
84
    obs_cta.id(id)
85

    
86
    # Return CTA observation
87
    return obs_cta
88

    
89

    
90
# ======================================== #
91
# Add CTA background model to observations #
92
# ======================================== #
93
def add_background_model(models,name="Background",instru="CTA",id="",bgd_file="",bgd_sigma=0.0):
94
    
95
    """
96
    Add CTA background model to a model container.
97

98
    Parameters:
99
     models - a model container
100
     bgd_file - file function for background spectral dependence
101
     bgd_sigma - sigma parameter for the gaussian offset angle dependence of the background rate
102
    """
103
    
104
    # Gaussian radial dependence model
105
    if bgd_sigma > 0.0:
106
        
107
        # Spatial part
108
        bgd_radial = GCTAModelRadialGauss(bgd_sigma)
109
    
110
        # Spectral part
111
        if len(bgd_file) > 0:
112
            bgd_spectrum = GModelSpectralFunc(bgd_file,1.0)
113
        else:
114
            pivot_nrj=GEnergy(1.0e6, "MeV")
115
            bgd_spectrum = GModelSpectralPlaw(1.0e-6, -2.0, pivot_nrj)
116
            bgd_spectrum["Prefactor"].value(61.8e-6)
117
            bgd_spectrum["Prefactor"].scale(1.0e-6)
118
            bgd_spectrum["PivotEnergy"].value(1.0)
119
            bgd_spectrum["PivotEnergy"].scale(1.0e6)
120
            bgd_spectrum["Index"].value(-1.85)
121
            bgd_spectrum["Index"].scale(1.0)
122
    
123
            # Full model
124
            bgd_model = GCTAModelRadialAcceptance(bgd_radial, bgd_spectrum)
125
    
126
    # IRF-defined model
127
    else:
128
        
129
            # Spectral model
130
            pivot_nrj=GEnergy(1.0e6, "MeV")
131
            bgd_spectrum = GModelSpectralPlaw(1.0e-6, -2.0, pivot_nrj)
132
            bgd_spectrum["Prefactor"].value(1.0)
133
            bgd_spectrum["Prefactor"].scale(1.0)
134
            bgd_spectrum["PivotEnergy"].value(1.0)
135
            bgd_spectrum["PivotEnergy"].scale(1.0e6)
136
            bgd_spectrum["Index"].value(0.0)
137
            bgd_spectrum["Index"].scale(1.0)
138
            
139
            # Full model
140
            bgd_model = GCTAModelIrfBackground(bgd_spectrum)
141
    
142
    # Set other background properties
143
    if (len(name) > 0):
144
        bgd_model.name(name)
145
    else:
146
        bgd_model.name("Background")
147
    if (len(instru) > 0):
148
        bgd_model.instruments(instru)
149
    else:
150
        bgd_model.instruments("CTA")
151
    if (len(id) > 0):
152
        bgd_model.ids(id)
153
    
154
    # By default, set model to be fitted
155
    if (len(bgd_file) > 0):
156
        bgd_model['Normalization'].free()
157
    else:
158
        bgd_model['Prefactor'].free()
159
        bgd_model['Index'].free()
160
    
161
    # Add background model to container
162
    models.append(bgd_model)
163
    
164
    # Return model container
165
    return models
166

    
167

    
168
# =========================== #
169
# Set any general type source #
170
# =========================== #
171
def add_source_model(models, name, ra, dec, coord='CEL', \
172
                     skymap='', specfile='', \
173
                     flux=5.7e-16, index=-2.5, pivot=3.0e5, \
174
                     type="point", sigma=1.0, radius=1.0, width=0.1, \
175
                     nnode=0, emin=1.0, emax=10.0, \
176
                     pivot_scale=1e6, flux_scale=1.0e-16):
177
    """
178
    Adds a single point-source with power-law spectrum to a model container.
179
    The default is crab-like.
180

181
    Parameters:
182
     models - a model container
183
     name   - Unique source name
184
     ra     - RA of source location [deg]
185
     dec    - Declination of source location [deg]
186
    Keywords:
187
     flux   - Source flux density in 1.0e-16 ph/cm2/s/MeV
188
     index  - Source spectral index
189
     pivot  - Pivot energy in TeV
190
     type   - Source spatial model
191
     sigma/radius/width  - Spatial model parameters
192
     nnode  - Number of nodes (if > 0, spectral model is a node function)
193
    """
194
    
195
    # Set source spectral model
196
    if (nnode > 0) and (emin != emax):
197
        spectrum = GModelSpectralNodes()
198
        dloge=log10(emax/emin)/nnode
199
        logemin=math.log10(emin)
200
        spectrum.reserve(nnode)
201
        for i in range(nnode):
202
                    enode = GEnergy()
203
                    enode.TeV(10.0**(logemin+(i+0.5)*dloge))
204
                    inode=flux*(enode.MeV()/pivot)**(index)
205
                    spectrum.append(enode, inode)
206
                    spectrum[i*2].scale(pivot_scale)
207
                    spectrum[i*2].fix()
208
                    spectrum[i*2+1].scale(flux_scale)
209
                    spectrum[i*2+1].free()    
210
    # Set source spectral model
211
    elif (len(specfile) > 0):
212
        spectrum = GModelSpectralFunc(specfile)
213
        spectrum["Normalization"].value(1.0)
214
        spectrum["Normalization"].free()
215
    else:
216
        pivot_nrj=GEnergy()
217
        pivot_nrj.TeV(pivot*pivot_scale/1e6)
218
        spectrum = GModelSpectralPlaw(flux, index,pivot_nrj)
219
        spectrum["Prefactor"].scale(flux_scale)
220
        spectrum["Prefactor"].value(flux)
221
        spectrum["Prefactor"].free()
222
        spectrum["PivotEnergy"].scale(pivot_scale)
223
        spectrum["PivotEnergy"].value(pivot)
224
        spectrum["Index"].value(index)
225
        spectrum["Index"].scale(1.0)
226
        spectrum["Index"].free()        
227
        
228
    # Set source spatial model
229
    location = GSkyDir()
230
    if (coord == 'CEL'):
231
        location.radec_deg(ra, dec)
232
    else:
233
        location.lb_deg(ra, dec)    
234
    if (len(skymap) > 0):
235
        spatial = GModelSpatialDiffuseMap(skymap,1.0)
236
        source = GModelSky(spatial, spectrum)
237
        spatial[0].free()
238
    elif type == "point":
239
        spatial = GModelSpatialPointSource(location)
240
        spatial[0].free()
241
        spatial[1].free()
242
        source  = GModelSky(spatial, spectrum)
243
    elif type == "gauss":
244
        radial = GModelSpatialRadialGauss(location, sigma)
245
        radial[0].free()
246
        radial[1].free()
247
        radial[2].free()
248
        source = GModelSky(radial, spectrum)
249
    elif type == "disk":
250
        radial = GModelSpatialRadialDisk(location, radius)
251
        radial[0].free()
252
        radial[1].free()
253
        radial[2].free()
254
        source = GModelSky(radial, spectrum)
255
    elif type == "shell":
256
        radial = GModelSpatialRadialShell(location, radius, width)
257
        radial[0].free()
258
        radial[1].free()
259
        radial[2].free()
260
        radial[3].free()
261
        source = GModelSky(radial, spectrum)
262
    else:
263
        print "ERROR: Unknown source type '"+type+"'."
264
        return None
265
    
266
    # Set source name
267
    source.name(name)
268
    
269
    # Append source model to model container
270
    models.append(source)
271
    
272
    # Return source
273
    return models
274

    
275
# ======================================== #
276
# Set the fit parameters for a given model #
277
# ======================================== #
278
def set_fit_param(model, parname=[], parfit=[], parval=[]):
279
    """
280
    Set the fit parameters for a given model
281
    
282
    Arguments
283
    - model: a model container
284
    - parname: array of parameters names
285
    - parfit: array of fit/fix flags (True=fit,False=fix)
286
    - parval: array of initial/fix parameters values
287
    
288
    Notes
289
    - Arrays should have same numbers of elements
290
    - A way to not set a value but just the fit/fix flag is to pass/leave parval empty
291
    - If among several parameters some values must be set and others not, separate these and call the function two times
292
    """
293

    
294
    # Count/check number of parameters to be set
295
    if (len(parname) != len(parfit)):
296
        print "Incorrect input. Fit parameters not set or modified."
297
        return 0
298
    else:
299
        num_toset=len(parname)
300
                    
301
    # Loop over parameters
302
    for i in range(model.size()):
303
        name=model[i].name()
304
        if (name in parname):
305
            # Get index of matching name
306
            i_par=parname.index(name)
307
            # Set the parameter to be fix/free
308
            if (parfit[i_par]):
309
                model[name].free()
310
            else:
311
                model[name].fix()
312
            # Optionally set the value
313
            if (len(parval) > 0): 
314
                model[name].value(parval[i_par])
315

    
316
    # Exit point
317
    return model
318

    
319

    
320
# ===================== #
321
# Simulate observations #
322
# ===================== #
323
def sim(obs, log=False, debug=False, chatter=2, edisp=False, seed=0, nbins=0,
324
        binsz=0.05, npix=200, proj="TAN", coord="GAL", outfile=""):
325
    """
326
    Simulate events for all observations in the container.
327

328
    Parameters:
329
     obs   - Observation container
330
    Keywords:
331
     log   - Create log file(s)
332
     debug - Create console dump?
333
     edisp - Apply energy dispersion?
334
     seed  - Seed value for simulations (default: 0)
335
     nbins - Number of energy bins (default: 0=unbinned)
336
     binsz - Pixel size for binned simulation (deg/pixel)
337
     npix  - Number of pixels in X and Y for binned simulation
338
    """
339

    
340
    # Allocate ctobssim application and set parameters
341
    sim = ctobssim(obs)
342
    sim["seed"] = seed
343
    sim["edisp"] = edisp
344
    sim["outevents"] = outfile
345

    
346
    # Optionally open the log file
347
    if log:
348
        sim.logFileOpen()
349

    
350
    # Optionally switch-on debugging model
351
    if debug:
352
        sim["debug"] = True
353

    
354
    # Set chatter level
355
    sim["chatter"] = chatter
356

    
357
    # Run ctobssim application. This will loop over all observations in the
358
    # container and simulation the events for each observation. Note that
359
    # events are not added together, they still apply to each observation
360
    # separately.
361
    sim.run()
362

    
363
    # Binned option?
364
    if nbins > 0:
365

    
366
        # Determine common energy boundaries for observations
367
        emin = None
368
        emax = None
369
        for run in sim.obs():
370
            run_emin = run.events().ebounds().emin().TeV()
371
            run_emax = run.events().ebounds().emax().TeV()
372
            if emin == None:
373
                emin = run_emin
374
            elif run_emin > emin:
375
                emin = run_emin
376
            if emax == None:
377
                emax = run_emax
378
            elif run_emax > emax:
379
                emax = run_emax
380

    
381
        # Allocate ctbin application and set parameters
382
        bin = ctbin(sim.obs())
383
        bin["ebinalg"] = "LOG"
384
        bin["emin"] = emin
385
        bin["emax"] = emax
386
        bin["enumbins"] = nbins
387
        bin["usepnt"] = True # Use pointing for map centre
388
        bin["nxpix"] = npix
389
        bin["nypix"] = npix
390
        bin["binsz"] = binsz
391
        bin["coordsys"] = coord
392
        bin["proj"] = proj
393

    
394
        # Optionally open the log file
395
        if log:
396
            bin.logFileOpen()
397

    
398
        # Optionally switch-on debugging model
399
        if debug:
400
            bin["debug"] = True
401

    
402
        # Set chatter level
403
        bin["chatter"] = chatter
404

    
405
        # Run ctbin application. This will loop over all observations in
406
        # the container and bin the events in counts maps
407
        bin.run()
408

    
409
        # Make a deep copy of the observation that will be returned
410
        # (the ctbin object will go out of scope one the function is
411
        # left)
412
        obs = bin.obs().copy()
413

    
414
    else:
415

    
416
        # Make a deep copy of the observation that will be returned
417
        # (the ctobssim object will go out of scope one the function is
418
        # left)
419
        obs = sim.obs().copy()
420
        
421
    # Optionally save file
422
    if (len(outfile) > 0):
423
        sim.save()
424
        
425
    # Delete the simulation
426
    del sim
427

    
428
    # Return observation container
429
    return obs
430

    
431

    
432
# =================== #
433
# Make a simple model #
434
# =================== #
435
def make_simple_model(models,name,ra,dec,flux,idx):
436
    
437
    # Add background model (one for each pointing)
438
    models = add_background_model(models,bgd_sigma=0.0,instru='CTA',id="0001",name="Background left")
439
    set_fit_param(models["Background left"],parname=['Sigma','Normalization','Prefactor','Index'],parfit=[False,True,True,False])
440
    models = add_background_model(models,bgd_sigma=0.0,instru='CTA',id="0002",name="Background right")
441
    set_fit_param(models["Background right"],parname=['Sigma','Normalization','Prefactor','Index'],parfit=[False,True,True,False])
442
    
443
    # Add source model
444
    models = add_source_model(models, name, ra, dec, flux=flux, index=idx, pivot=1.0e6, type="point", pivot_scale=1e6, flux_scale=1.0e-16)
445
    set_fit_param(models["Test source"],parname=['Prefactor','Index','RA','DEC'],parfit=[True,True,False,False])
446
    
447
    # Exit
448
    return models
449

    
450
# ====================================== #
451
# Make a simple model for On-Off fitting #
452
# ====================================== #
453
def make_simple_model_onoff_fit(models,name,ra,dec,flux,idx):
454
    
455
    # Add background model (one for each pointing)
456
    # Have to use the instrument "CTAOnOff" to make it work
457
    models = add_background_model(models,bgd_sigma=0.0,instru='CTAOnOff',id="0001",name="Background left")
458
    set_fit_param(models["Background left"],parname=['Sigma','Normalization','Prefactor','Index'],parfit=[False,True,True,False])
459
    models = add_background_model(models,bgd_sigma=0.0,instru='CTAOnOff',id="0002",name="Background right")
460
    set_fit_param(models["Background right"],parname=['Sigma','Normalization','Prefactor','Index'],parfit=[False,True,True,False])
461
    
462
    # Add source model
463
    models = add_source_model(models, name, ra, dec, flux=flux, index=idx, pivot=1.0e6, type="point", pivot_scale=1e6, flux_scale=1.0e-16)
464
    set_fit_param(models["Test source"],parname=['Prefactor','Index','RA','DEC'],parfit=[True,True,False,False])
465
    
466
    # Exit
467
    return models
468
    
469

    
470
# =================== #
471
# Make a simple model #
472
# =================== #
473
def reset_simple_model(models,ra,dec,flux,idx):
474
    
475
    # Add background model (one for each pointing)
476
    set_fit_param(models["Background left"],parname=['Sigma','Normalization','Prefactor','Index'],parfit=[False,True,True,False],parval=[4.0,1.0,1.0,0.0])
477
    set_fit_param(models["Background right"],parname=['Sigma','Normalization','Prefactor','Index'],parfit=[False,True,True,False],parval=[4.0,1.0,1.0,0.0])
478
    set_fit_param(models["Test source"],parname=['Prefactor','Index','RA','DEC'],parfit=[True,True,False,False],parval=[flux,idx,ra,dec])
479
    
480
    # Exit
481
    return models
482

    
483

    
484
# ===================== #
485
# Print out fit results #
486
# ===================== #
487
def print_fit_results(obslist):
488
    
489
    # Print
490
    print "Background left prefactor: %.3e +/- %.3e " % (obslist.models()["Background left"]['Prefactor'].value(),obslist.models()["Background left"]['Prefactor'].error())
491
    print "Background left index: %.3e +/- %.3e " % (obslist.models()["Background left"]['Index'].value(),obslist.models()["Background left"]['Index'].error())
492
    print "Background right prefactor: %.3e +/- %.3e " % (obslist.models()["Background right"]['Prefactor'].value(),obslist.models()["Background right"]['Prefactor'].error())
493
    print "Background right index: %.3e +/- %.3e " % (obslist.models()["Background right"]['Index'].value(),obslist.models()["Background right"]['Index'].error())
494
    print "Source prefactor: %.3e +/- %.3e " % (obslist.models()["Test source"]['Prefactor'].value(),obslist.models()["Test source"]['Prefactor'].error())
495
    print "Source index: %.3e +/- %.3e " % (obslist.models()["Test source"]['Index'].value(),obslist.models()["Test source"]['Index'].error())
496
    print "Fit ended with value %.3e and status %d after %d iterations." % (opt.value(),opt.status(),opt.iter())
497
    
498
    # Exit
499
    return
500
    
501

    
502
#=====================#
503
# Routine entry point #
504
#=====================#
505
if __name__ == '__main__':
506

    
507
    """
508
    Aims:
509
    This script tests the ON-OFF analysis functionality of the gammalib
510
    
511
    Arguments:
512
    - None
513
    
514
    Notes:
515
    - Hard-coded source, observations, and regions (more flexible script later...)
516
    - Approximate method to set OFF regions (works only on equator)
517
    - Have to set up path to data base (db and irf)
518
    - Source flux set as flux density at 1TeV
519
    """
520
    
521
    # Job parameters
522
    # CTA
523
    db="prod2"
524
    irf="South_50h"
525
    bgd=""
526
    rsp_sigma=4.0
527
    bgd_sigma=4.0
528
    duration=1800.0
529
    rad=5.0
530
    # Energy
531
    emin=0.1
532
    emax=100.0
533
    nbins=9
534
    nnodes=5
535
    # Source
536
    name="Test source"
537
    ra=0.0
538
    dec=0.0
539
    flux=5.0e-17
540
    idx=-2.5
541
    dflux=1.5  # Offset factor by which true value is rescaled before fit
542
    didx=0.3   # Offset factor by which true value is rescaled before fit
543
    # ON-OFF
544
    onshift=1.0
545
    onsize=0.3
546
    noff=3
547
    # Others
548
    chatter=4
549
    seed=10
550
    Check=True
551

    
552
    print 'Got params...'
553
    
554
    # Create observation container
555
    obslist = GObservations()
556
    print 'Create observation container...'
557
    
558
    # Add two offset observations
559
    leftdir = GSkyDir()
560
    leftdir.radec_deg(ra+onshift, dec)
561
    obs_left=single_obs(leftdir, tstart=0.0, duration=duration, deadc=0.95, \
562
                   emin=emin, emax=emax, rad=rad, \
563
                   irf=irf, caldb=db, id="000000", instrument="CTA")
564
    obs_left.name("Left")
565
    obs_left.id("0001")
566
    obslist.append(obs_left)
567
    rightdir = GSkyDir()
568
    rightdir.radec_deg(ra-onshift, dec)
569
    obs_right=single_obs(rightdir, tstart=0.0, duration=duration, deadc=0.95, \
570
                   emin=emin, emax=emax, rad=rad, \
571
                   irf=irf, caldb=db, id="000000", instrument="CTA")
572
    obs_right.name("Right")
573
    obs_right.id("0002")
574
    obslist.append(obs_right)
575
    print 'Add two offset observations...'
576
    
577
    # Create a model container
578
    models = GModels()   
579
    models_onoff_fit = GModels()   
580

    
581
    # Make a simple model for two observations
582
    models = make_simple_model(models,name,ra,dec,flux,idx)
583
    models_onoff_fit = make_simple_model_onoff_fit(models_onoff_fit,name,ra,dec,flux*dflux,idx-didx)
584
    # Add model to the container
585
    obslist.models(models)
586
    obslist.models().save("sim_model.xml")
587
    print 'Added model to the container...'    
588

    
589
    # Make event list
590
    obslist = sim(obslist, log=False, debug=False, chatter=chatter, edisp=False, seed=seed, nbins=0, outfile='onoff_events.xml')
591
    print 'Made event list...'    
592
    
593
    # Define ON region
594
    ondir = GSkyDir()
595
    ondir.radec_deg(ra,dec)
596
    on = GSkyRegions()
597
    onreg=GSkyRegionCircle(ondir,onsize)
598
    on.append(onreg)
599
    on.save("on_regions.reg")
600
    print 'On regions created...'    
601

    
602
    # Define OFF regions
603
    offleft = GSkyRegions()
604
    offright = GSkyRegions()
605
    for i in range(noff):
606
        phi=(i+1)*360./(noff+1.0)
607
        # Left pointing  
608
        offdir = GSkyDir(leftdir)       
609
        offdir.rotate_deg(phi-90., onshift)
610
        offreg=GSkyRegionCircle(offdir, onsize)
611
        offleft.append(offreg)
612
        # Right pointing
613
        offdir = GSkyDir(rightdir)       
614
        offdir.rotate_deg(phi+90.0, onshift)       
615
        offreg=GSkyRegionCircle(offdir, onsize)
616
        offright.append(offreg)
617
       
618
    offleft.save("off_left_regions.reg")
619
    offright.save("off_right_regions.reg")
620
    print 'Off regions created...'    
621

    
622
    # Create ON-OFF analysis object
623
    onofflist = GObservations()#GCTAOnOffObservations()
624
    
625
    # Define energy binning
626
    etrue = GEbounds(nbins, GEnergy(emin, "TeV"), GEnergy(emax, "TeV"))
627
    ereco = GEbounds(nbins, GEnergy(emin, "TeV"), GEnergy(emax, "TeV"))
628
    
629
    # Append ON-OFF observations
630
    obs_left=obslist[0]
631
    obs_right=obslist[1]
632
    obsl=GCTAOnOffObservation(obs_left, etrue, ereco, on, offleft)
633
    obsl.name("Left")
634
    obsl.id("0001")
635
    onofflist.append(obsl)
636
    obsr=GCTAOnOffObservation(obs_right, etrue, ereco, on, offright)
637
    obsr.name("Right")
638
    obsr.id("0002")
639
    onofflist.append(obsr)
640
        
641
    # Save ON-OFF observations
642
    onofflist.save("onoffobservations.xml")
643
        
644
    # Check times
645
    if Check:
646
        print "Observation %s with %.1fs ON time" % (onofflist[0].name(),onofflist[0].ontime())
647
        print "Observation %s with %.1fs ON time" % (onofflist[1].name(),onofflist[1].ontime())   
648
        # Check spectra
649
        print '\nLeft'
650
        for i in range(nbins):
651
                print "ON counts %d - OFF counts %d" % (onofflist[0].on_spec()[i],onofflist[0].off_spec()[i])
652
        print '\nRight'
653
        for i in range(nbins):
654
                print "ON counts %d - OFF counts %d" % (onofflist[1].on_spec()[i],onofflist[1].off_spec()[i])
655
        print '\n'   
656
       
657
    # Reset model container and append it to observation list
658
    models_onoff_fit=reset_simple_model(models_onoff_fit,ra,dec,dflux*flux,idx-didx)
659
    onofflist.models(models_onoff_fit)
660
    
661
    # Set optimizer and logger
662
    log=GLog('fit_onoff.log',True)
663
    log.chatter(chatter)
664
    opt=GOptimizerLM(log)
665
    
666
    # Optimize for ON-OFF analysis
667
    print '\nON-OFF fitting...'
668
    onofflist.optimize(opt)
669
    onofflist.errors(opt)
670
    print_fit_results(onofflist)
671
    
672
    # Free memory
673
    del opt
674
    del log
675
         
676
    # Reset model container and append it to observation list
677
    models=reset_simple_model(models,ra,dec,dflux*flux,idx-didx)
678
    obslist.models(models)
679
    
680
    # Set optimizer and logger
681
    log=GLog('fit_unbinned.log',True)
682
    log.chatter(chatter)
683
    opt=GOptimizerLM(log)
684
    
685
    # Optimize for Fermi-style analysis
686
    print '\nUnbinned fitting...'
687
    obslist.optimize(opt)
688
    obslist.errors(opt)
689
    print_fit_results(obslist)
690
    
691
    # Free memory
692
    del opt
693
    del log
694
    
695