Commit 152493f86c0342a85aabb0c88ee0da2b2856d5e9
Merge branch 'integration' into 1920-fix-cslightcrv
# Conflicts: # NEWS
Showing
13 changed files
with
517 additions
and
69 deletions
NEWS
| 1 | 1 | New Features and Important Changes in ctools 1.2.0 |
| 2 | 2 | |
| 3 | -12 December 2016 | |
| 3 | +26 January 2017 | |
| 4 | 4 | |
| 5 | 5 | |
| 6 | 6 | Introduction |
| ... | ... | @@ -195,6 +195,9 @@ in particular the "PhotonFlux" and "EnergyFlux" names (#1832). |
| 195 | 195 | |
| 196 | 196 | The class now derives from ctlikelihood (#1828). |
| 197 | 197 | |
| 198 | +The tool now makes sure that the intensity parameter of the source of interest | |
| 199 | +is free in the model optimisation that preceeds the upper limit computation. | |
| 200 | + | |
| 198 | 201 | |
| 199 | 202 | cterror - Likelihood profile error computation |
| 200 | 203 | ---------------------------------------------- |
| ... | ... | @@ -235,10 +238,14 @@ Add cssrcdetect script to detect sources in a sky map (#1617). |
| 235 | 238 | The "ds9file" parameters were changed to "outds9file" to be consistent with |
| 236 | 239 | the naming conventions. |
| 237 | 240 | |
| 241 | +Improve the upper limit computation in the cslightcrv script. Now all source | |
| 242 | +parameters, except the source intensity, are set to the initial values given | |
| 243 | +in the model definition file for upper limit computation. | |
| 244 | + | |
| 238 | 245 | |
| 239 | 246 | Examples |
| 240 | 247 | -------- |
| 241 | -None | |
| 248 | +Add show_lightcurve script to display a light curve. | |
| 242 | 249 | |
| 243 | 250 | |
| 244 | 251 | caldb | ... | ... |
cscripts/Makefile.am
| ... | ... | @@ -166,6 +166,7 @@ testdata = $(top_srcdir)/test/data/crab.xml \ |
| 166 | 166 | $(top_srcdir)/test/data/sensitivity_integral.dat \ |
| 167 | 167 | $(top_srcdir)/test/data/skymap.fits \ |
| 168 | 168 | $(top_srcdir)/test/data/spectrum.fits \ |
| 169 | + $(top_srcdir)/test/data/lightcurve.fits \ | |
| 169 | 170 | $(top_srcdir)/test/data/ts.dat \ |
| 170 | 171 | $(top_srcdir)/test/data/models_spatial.xml \ |
| 171 | 172 | $(top_srcdir)/test/data/models_spectral.xml \ | ... | ... |
cscripts/cslightcrv.py
| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | # ========================================================================== |
| 3 | 3 | # Generates a lightcurve. |
| 4 | 4 | # |
| 5 | -# Copyright (C) 2014-2016 Michael Mayer | |
| 5 | +# Copyright (C) 2014-2017 Michael Mayer | |
| 6 | 6 | # |
| 7 | 7 | # This program is free software: you can redistribute it and/or modify |
| 8 | 8 | # it under the terms of the GNU General Public License as published by |
| ... | ... | @@ -69,7 +69,7 @@ class cslightcrv(ctools.cscript): |
| 69 | 69 | """ |
| 70 | 70 | # Set name |
| 71 | 71 | self._name = 'cslightcrv' |
| 72 | - self._version = '1.2.0' | |
| 72 | + self._version = '1.3.0' | |
| 73 | 73 | |
| 74 | 74 | # Initialise some members |
| 75 | 75 | self._srcname = '' |
| ... | ... | @@ -335,18 +335,26 @@ class cslightcrv(ctools.cscript): |
| 335 | 335 | table.append(ts) |
| 336 | 336 | |
| 337 | 337 | # Append upper limit column "UpperLimit" |
| 338 | - ulimit = gammalib.GFitsTableDoubleCol('UpperLimit', nrows) | |
| 339 | - ulimit.unit('ph/cm2/s') | |
| 338 | + ul_diff = gammalib.GFitsTableDoubleCol('DiffUpperLimit', nrows) | |
| 339 | + ul_flux = gammalib.GFitsTableDoubleCol('FluxUpperLimit', nrows) | |
| 340 | + ul_eflux = gammalib.GFitsTableDoubleCol('EFluxUpperLimit', nrows) | |
| 341 | + ul_diff.unit('ph/cm2/s/MeV') | |
| 342 | + ul_flux.unit('ph/cm2/s') | |
| 343 | + ul_eflux.unit('erg/cm2/s') | |
| 340 | 344 | for i, result in enumerate(results): |
| 341 | - ulimit[i] = result['ulimit'] | |
| 342 | - table.append(ulimit) | |
| 345 | + ul_diff[i] = result['ul_diff'] | |
| 346 | + ul_flux[i] = result['ul_flux'] | |
| 347 | + ul_eflux[i] = result['ul_eflux'] | |
| 348 | + table.append(ul_diff) | |
| 349 | + table.append(ul_flux) | |
| 350 | + table.append(ul_eflux) | |
| 343 | 351 | |
| 344 | 352 | # Return table |
| 345 | 353 | return table |
| 346 | 354 | |
| 347 | 355 | def _compute_ulimit(self, obs): |
| 348 | 356 | """ |
| 349 | - Computes upper flux limit | |
| 357 | + Computes upper limit | |
| 350 | 358 | |
| 351 | 359 | Parameters |
| 352 | 360 | ---------- |
| ... | ... | @@ -355,35 +363,57 @@ class cslightcrv(ctools.cscript): |
| 355 | 363 | |
| 356 | 364 | Returns |
| 357 | 365 | ------- |
| 358 | - ulimit : float | |
| 359 | - Upper flux limit (-1.0 of not computed) | |
| 366 | + ul_diff, ul_flux, ul_eflux : tuple of float | |
| 367 | + Upper limits, -1.0 of not computed | |
| 360 | 368 | """ |
| 361 | 369 | # Initialise upper flux limit |
| 362 | - ulimit_value = -1.0 | |
| 363 | - | |
| 370 | + ul_diff = -1.0 | |
| 371 | + ul_flux = -1.0 | |
| 372 | + ul_eflux = -1.0 | |
| 373 | + | |
| 364 | 374 | # Perform computation only if requested |
| 365 | 375 | if self['calc_ulim'].boolean(): |
| 366 | 376 | |
| 367 | 377 | # Write header in logger |
| 368 | 378 | if self._logExplicit(): |
| 369 | - self._log.header3('Computing upper flux limit') | |
| 370 | - | |
| 371 | - # Create upper limit object | |
| 372 | - ulimit = ctools.ctulimit(obs) | |
| 373 | - ulimit['srcname'] = self._srcname | |
| 374 | - ulimit['eref'] = 1.0 | |
| 375 | - | |
| 376 | - # Try to run upper limit and catch any exceptions | |
| 379 | + self._log.header3('Computing upper limit') | |
| 380 | + | |
| 381 | + # Create copy of observations | |
| 382 | + cpy_obs = obs.copy() | |
| 383 | + | |
| 384 | + # Fix parameters of source of interest in copy of observations. | |
| 385 | + # This assures that the original spectral parameters and position | |
| 386 | + # are used in the upper limit search. The ctulimit tool makes sure | |
| 387 | + # that the flux parameter is freed when needed. | |
| 388 | + source = cpy_obs.models()[self._srcname] | |
| 389 | + for par in source: | |
| 390 | + if par.is_free(): | |
| 391 | + par.fix() | |
| 392 | + | |
| 393 | + # Create instance of upper limit tool | |
| 394 | + ulimit = ctools.ctulimit(cpy_obs) | |
| 395 | + ulimit['srcname'] = self._srcname | |
| 396 | + ulimit['eref'] = 1.0 | |
| 397 | + ulimit['emin'] = self['emin'].real() | |
| 398 | + ulimit['emax'] = self['emax'].real() | |
| 399 | + ulimit['sigma_min'] = 0.0 | |
| 400 | + ulimit['sigma_max'] = 3.0 | |
| 401 | + | |
| 402 | + # Try to run upper limit tool and catch any exceptions | |
| 377 | 403 | try: |
| 378 | 404 | ulimit.run() |
| 379 | - ulimit_value = ulimit.flux_ulimit() | |
| 405 | + ul_diff = ulimit.diff_ulimit() | |
| 406 | + ul_flux = ulimit.flux_ulimit() | |
| 407 | + ul_eflux = ulimit.eflux_ulimit() | |
| 380 | 408 | except: |
| 381 | 409 | if self._logTerse(): |
| 382 | - self._log('Upper limit flux calculation failed.\n') | |
| 383 | - ulimit_value = -1.0 | |
| 410 | + self._log('Upper limit calculation failed.\n') | |
| 411 | + ul_diff = -1.0 | |
| 412 | + ul_flux = -1.0 | |
| 413 | + ul_eflux = -1.0 | |
| 384 | 414 | |
| 385 | - # Return upper limit | |
| 386 | - return ulimit_value | |
| 415 | + # Return upper limit tuple | |
| 416 | + return ul_diff, ul_flux, ul_eflux | |
| 387 | 417 | |
| 388 | 418 | def _bin_observation(self, obs): |
| 389 | 419 | """ |
| ... | ... | @@ -517,7 +547,9 @@ class cslightcrv(ctools.cscript): |
| 517 | 547 | result = {'mjd': tmean.mjd(), |
| 518 | 548 | 'e_mjd': twidth / gammalib.sec_in_day, |
| 519 | 549 | 'ts': 0.0, |
| 520 | - 'ulimit': 0.0, | |
| 550 | + 'ul_diff': 0.0, | |
| 551 | + 'ul_flux': 0.0, | |
| 552 | + 'ul_eflux': 0.0, | |
| 521 | 553 | 'pars': pars, |
| 522 | 554 | 'values': {}} |
| 523 | 555 | |
| ... | ... | @@ -581,9 +613,12 @@ class cslightcrv(ctools.cscript): |
| 581 | 613 | result['values']['e_'+par] = source[par].error() |
| 582 | 614 | |
| 583 | 615 | # Calculate upper limit (-1 if not computed) |
| 584 | - ulimit_value = self._compute_ulimit(like.obs()) | |
| 585 | - if ulimit_value > 0.0: | |
| 586 | - result['ulimit'] = ulimit_value | |
| 616 | + #ul_diff, ul_flux, ul_eflux = self._compute_ulimit(like.obs()) | |
| 617 | + ul_diff, ul_flux, ul_eflux = self._compute_ulimit(obs) | |
| 618 | + if ul_diff > 0.0: | |
| 619 | + result['ul_diff'] = ul_diff | |
| 620 | + result['ul_flux'] = ul_flux | |
| 621 | + result['ul_eflux'] = ul_eflux | |
| 587 | 622 | |
| 588 | 623 | # Extract Test Statistic value |
| 589 | 624 | if self['calc_ts'].boolean(): |
| ... | ... | @@ -601,9 +636,13 @@ class cslightcrv(ctools.cscript): |
| 601 | 636 | unit = source[par].unit() |
| 602 | 637 | self._log_value(gammalib.NORMAL, par, |
| 603 | 638 | str(value)+' +/- '+str(error)+' '+unit) |
| 604 | - if result['ulimit'] > 0.0: | |
| 639 | + if ul_diff > 0.0: | |
| 640 | + self._log_value(gammalib.NORMAL, 'Upper flux limit', | |
| 641 | + str(result['ul_diff'])+' ph/cm2/s/MeV') | |
| 642 | + self._log_value(gammalib.NORMAL, 'Upper flux limit', | |
| 643 | + str(result['ul_flux'])+' ph/cm2/s') | |
| 605 | 644 | self._log_value(gammalib.NORMAL, 'Upper flux limit', |
| 606 | - str(result['ulimit'])+' ph/cm2/s') | |
| 645 | + str(result['ul_eflux'])+' erg/cm2/s') | |
| 607 | 646 | if self['calc_ts'].boolean(): |
| 608 | 647 | self._log_value(gammalib.NORMAL, 'Test Statistic', result['ts']) |
| 609 | 648 | ... | ... |
cscripts/csroot2caldb.py
| ... | ... | @@ -146,7 +146,7 @@ class csroot2caldb(ctools.cscript): |
| 146 | 146 | def _make_dirs(self, version, irf): |
| 147 | 147 | """ |
| 148 | 148 | Generate CALDB directory structure for one observation identifier |
| 149 | - | |
| 149 | + | |
| 150 | 150 | The structure is given by |
| 151 | 151 | |
| 152 | 152 | data/<tel>/<inst>/bcf/<obsid> |
| ... | ... | @@ -227,7 +227,7 @@ class csroot2caldb(ctools.cscript): |
| 227 | 227 | def _open(self, irf, ds): |
| 228 | 228 | """ |
| 229 | 229 | Open existing or create new calibration |
| 230 | - | |
| 230 | + | |
| 231 | 231 | The actual version will put all calibrations in the same file, although |
| 232 | 232 | each part of the response function will have its own logical name. We |
| 233 | 233 | can thus easily modify the script to put each calibration information |
| ... | ... | @@ -322,7 +322,7 @@ class csroot2caldb(ctools.cscript): |
| 322 | 322 | def _open_hdu(self, fits, extname, name, doc, irf): |
| 323 | 323 | """ |
| 324 | 324 | Open HDU |
| 325 | - | |
| 325 | + | |
| 326 | 326 | Opens a FITS binary table with given "extname". If HDU does not exist |
| 327 | 327 | in the FITS file it will be created and appended to the FITS file. |
| 328 | 328 | |
| ... | ... | @@ -534,10 +534,9 @@ class csroot2caldb(ctools.cscript): |
| 534 | 534 | def _root2ea(self, tfile, irf, ds): |
| 535 | 535 | """ |
| 536 | 536 | Translate ROOT to CALDB effective area extension |
| 537 | - | |
| 537 | + | |
| 538 | 538 | The following ROOT histograms are used: |
| 539 | 539 | - EffectiveAreaEtrue_offaxis -> EFFAREA |
| 540 | - - EffectiveArea_offaxis -> EFFAREA_RECO | |
| 541 | 540 | |
| 542 | 541 | Parameters |
| 543 | 542 | ---------- |
| ... | ... | @@ -555,16 +554,13 @@ class csroot2caldb(ctools.cscript): |
| 555 | 554 | |
| 556 | 555 | # Get relevant ROOT histograms |
| 557 | 556 | etrue = tfile.Get('EffectiveAreaEtrue_offaxis') |
| 558 | - ereco = tfile.Get('EffectiveArea_offaxis') | |
| 559 | 557 | |
| 560 | 558 | # If requested then normalize the 2D histogram on the on-axis 1D |
| 561 | 559 | # histogram. This assures that the 2D histogram has the same on-axis |
| 562 | 560 | # effective area dependence as the 1D histogram. |
| 563 | 561 | if self['norm1d'].boolean(): |
| 564 | 562 | etrue_1D = tfile.Get('EffectiveAreaEtrue') |
| 565 | - ereco_1D = tfile.Get('EffectiveArea') | |
| 566 | 563 | self._renorm_onaxis(etrue, etrue_1D) |
| 567 | - self._renorm_onaxis(ereco, ereco_1D) | |
| 568 | 564 | |
| 569 | 565 | # If requested then rebin the effective area Etrue histogram. This |
| 570 | 566 | # increases the number of bins by a factor 10. |
| ... | ... | @@ -589,17 +585,6 @@ class csroot2caldb(ctools.cscript): |
| 589 | 585 | for ieng in range(neng): |
| 590 | 586 | value = etrue.GetBinContent(ieng+1,ioff+1) * eascale |
| 591 | 587 | etrue.SetBinContent(ieng+1,ioff+1,value) |
| 592 | - neng = ereco.GetXaxis().GetNbins() | |
| 593 | - noffset = ereco.GetYaxis().GetNbins() | |
| 594 | - for ioff in range(noffset): | |
| 595 | - for ieng in range(neng): | |
| 596 | - value = ereco.GetBinContent(ieng+1,ioff+1) * eascale | |
| 597 | - ereco.SetBinContent(ieng+1,ioff+1,value) | |
| 598 | - | |
| 599 | - # Set boundaries (use Ereco boundaries) | |
| 600 | - #bounds = self._make_2D(ereco, ds['HDU_EA'], None, 'm2') | |
| 601 | - #for b in bounds: | |
| 602 | - # irf['EA_BOUNDS'].append(b) | |
| 603 | 588 | |
| 604 | 589 | # Write boundary keywords |
| 605 | 590 | self._set_cif_keywords(ds['HDU_EA'], irf['EA_NAME'], |
| ... | ... | @@ -608,16 +593,13 @@ class csroot2caldb(ctools.cscript): |
| 608 | 593 | # Create "EFFAREA" data column |
| 609 | 594 | self._make_2D(etrue, ds['HDU_EA'], 'EFFAREA', 'm2') |
| 610 | 595 | |
| 611 | - # Create "EFFAREA_RECO" data column | |
| 612 | - self._make_2D(ereco, ds['HDU_EA'], 'EFFAREA_RECO', 'm2') | |
| 613 | - | |
| 614 | 596 | # Return |
| 615 | 597 | return |
| 616 | 598 | |
| 617 | 599 | def _root2psf(self, tfile, irf, ds): |
| 618 | 600 | """ |
| 619 | 601 | Translate ROOT to CALDB point spread function extension |
| 620 | - | |
| 602 | + | |
| 621 | 603 | Parameters |
| 622 | 604 | ---------- |
| 623 | 605 | tfile : `~ROOT.TFile` |
| ... | ... | @@ -646,7 +628,7 @@ class csroot2caldb(ctools.cscript): |
| 646 | 628 | def _root2psf_gauss(self, tfile, irf, ds): |
| 647 | 629 | """ |
| 648 | 630 | Translate ROOT to CALDB point spread function extension |
| 649 | - | |
| 631 | + | |
| 650 | 632 | The following ROOT histograms are used: |
| 651 | 633 | - 1/(2*pi*SIGMA_1) -> SCALE |
| 652 | 634 | - AngRes_offaxis -> SIGMA_1 (scaling: 1/0.8) |
| ... | ... | @@ -729,7 +711,7 @@ class csroot2caldb(ctools.cscript): |
| 729 | 711 | def _root2psf_king(self, tfile, irf, ds): |
| 730 | 712 | """ |
| 731 | 713 | Translate ROOT to CALDB point spread function extension |
| 732 | - | |
| 714 | + | |
| 733 | 715 | The following ROOT histograms are used: |
| 734 | 716 | - AngRes_offaxis |
| 735 | 717 | - AngRes80_offaxis |
| ... | ... | @@ -853,7 +835,7 @@ class csroot2caldb(ctools.cscript): |
| 853 | 835 | def _root2edisp(self, tfile, irf, ds): |
| 854 | 836 | """ |
| 855 | 837 | Translate ROOT to CALDB energy dispersion extension |
| 856 | - | |
| 838 | + | |
| 857 | 839 | The following ROOT histograms are used: |
| 858 | 840 | - EestOverEtrue_offaxis -> MATRIX |
| 859 | 841 | |
| ... | ... | @@ -892,7 +874,7 @@ class csroot2caldb(ctools.cscript): |
| 892 | 874 | def _root2bgd(self, tfile, irf, ds): |
| 893 | 875 | """ |
| 894 | 876 | Translate ROOT to CALDB background extension. |
| 895 | - | |
| 877 | + | |
| 896 | 878 | The following ROOT histograms are used: |
| 897 | 879 | - BGRatePerSqDeg_offaxis -> BGD |
| 898 | 880 | |
| ... | ... | @@ -945,7 +927,7 @@ class csroot2caldb(ctools.cscript): |
| 945 | 927 | def _append_column_axis(self, hdu, name, unit, axis, log=False): |
| 946 | 928 | """ |
| 947 | 929 | Append column of ROOT axis values to HDU |
| 948 | - | |
| 930 | + | |
| 949 | 931 | Parameters |
| 950 | 932 | ---------- |
| 951 | 933 | hdu : `~gammalib.GFitsHDU` |
| ... | ... | @@ -991,7 +973,7 @@ class csroot2caldb(ctools.cscript): |
| 991 | 973 | def _append_column_values(self, hdu, name, unit, values): |
| 992 | 974 | """ |
| 993 | 975 | Append column of values to HDU |
| 994 | - | |
| 976 | + | |
| 995 | 977 | Parameters |
| 996 | 978 | ---------- |
| 997 | 979 | hdu : `~gammalib.GFitsHDU` |
| ... | ... | @@ -1089,7 +1071,7 @@ class csroot2caldb(ctools.cscript): |
| 1089 | 1071 | for ioff in range(noffset): |
| 1090 | 1072 | value = hist2D_copy.GetBinContent(ieng+1,ioff+1) / onaxis |
| 1091 | 1073 | hist2D_copy.SetBinContent(ieng+1,ioff+1,value) |
| 1092 | - | |
| 1074 | + | |
| 1093 | 1075 | # Put back the energy dependence |
| 1094 | 1076 | for ieng in range(neng): |
| 1095 | 1077 | onaxis = hist1D.GetBinContent(ieng+1) |
| ... | ... | @@ -1324,7 +1306,7 @@ class csroot2caldb(ctools.cscript): |
| 1324 | 1306 | def _make_2D(self, array, hdu, name, unit, scale=1.0): |
| 1325 | 1307 | """ |
| 1326 | 1308 | Make 2D data column as function of energy and offset angle |
| 1327 | - | |
| 1309 | + | |
| 1328 | 1310 | If the HDU has already the energy and offset angle columns, this method |
| 1329 | 1311 | will simply add another data column. If name==None, the method will not |
| 1330 | 1312 | append any data column. |
| ... | ... | @@ -1381,7 +1363,7 @@ class csroot2caldb(ctools.cscript): |
| 1381 | 1363 | def _make_3D(self, array, hdu, name, unit): |
| 1382 | 1364 | """ |
| 1383 | 1365 | Make 3D data column as function of DETX, DETY and energy |
| 1384 | - | |
| 1366 | + | |
| 1385 | 1367 | If the HDU has already the energy and offset angle columns, this method |
| 1386 | 1368 | will simply add another data column. If name==None, the method will not |
| 1387 | 1369 | append any data column. |
| ... | ... | @@ -1471,7 +1453,7 @@ class csroot2caldb(ctools.cscript): |
| 1471 | 1453 | def _make_3D_migra(self, array, hdu, name, unit, scale=1.0): |
| 1472 | 1454 | """ |
| 1473 | 1455 | Make 3D data column as function of ETRUE, MIGRA and THETA |
| 1474 | - | |
| 1456 | + | |
| 1475 | 1457 | If the HDU has already the energy and offset angle columns, this method |
| 1476 | 1458 | will simply add another data column. If name==None, the method will not |
| 1477 | 1459 | append any data column. | ... | ... |
dev/macosx-package.sh
0 → 100755
| 1 | +#!/bin/bash -f | |
| 2 | +# ========================================================================== | |
| 3 | +# ctools Mac OS X package creation | |
| 4 | +# | |
| 5 | +# Copyright (C) 2017 Sylvie Brau-Nogué | |
| 6 | +# | |
| 7 | +# This program is free software: you can redistribute it and/or modify | |
| 8 | +# it under the terms of the GNU General Public License as published by | |
| 9 | +# the Free Software Foundation, either version 3 of the License, or | |
| 10 | +# (at your option) any later version. | |
| 11 | +# | |
| 12 | +# This program is distributed in the hope that it will be useful, | |
| 13 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | +# GNU General Public License for more details. | |
| 16 | +# | |
| 17 | +# You should have received a copy of the GNU General Public License | |
| 18 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 19 | +# | |
| 20 | +# ========================================================================== | |
| 21 | + | |
| 22 | +# ============================================= # | |
| 23 | +# Get ctools/GammaLib version from command line # | |
| 24 | +# ============================================= # | |
| 25 | +if [ $# -ne 1 ] ; then | |
| 26 | + echo "Please specify ctools/GammaLib version in the form x.y.z" | |
| 27 | + exit 1 | |
| 28 | +fi | |
| 29 | +VERSION=$1 | |
| 30 | + | |
| 31 | + | |
| 32 | +# =============================== # | |
| 33 | +# Set software component versions # | |
| 34 | +# =============================== # | |
| 35 | +CFITSIO=cfitsio3410 | |
| 36 | +NCURSES=ncurses-6.0 | |
| 37 | +READLINE=readline-7.0 | |
| 38 | +GAMMALIB=gammalib-$VERSION | |
| 39 | +CTOOLS=ctools-$VERSION | |
| 40 | + | |
| 41 | + | |
| 42 | +# ============== # | |
| 43 | +# Set parameters # | |
| 44 | +# ============== # | |
| 45 | +WRKDIR=$PWD/osxpackage | |
| 46 | +INSTALLDIR=$WRKDIR/install | |
| 47 | +SRCDIR=$WRKDIR/src | |
| 48 | +PKGDIR=$WRKDIR/pkg | |
| 49 | +PRODDIR=$WRKDIR/prod | |
| 50 | +PLISTFILE=$PKGDIR/$CTOOLS-components.plist | |
| 51 | +DISTFILE=$PRODDIR/$CTOOLS.dist | |
| 52 | +DMGFILE=$WRKDIR/$CTOOLS-macosx10.7.dmg | |
| 53 | + | |
| 54 | + | |
| 55 | +# ====================== # | |
| 56 | +# Clean package creation # | |
| 57 | +# ====================== # | |
| 58 | +rm -rf $INSTALLDIR | |
| 59 | +rm -rf $PKGDIR | |
| 60 | +rm -rf $PRODDIR | |
| 61 | +rm -rf $DMGFILE | |
| 62 | + | |
| 63 | + | |
| 64 | +# ============================= # | |
| 65 | +# Create package directory tree # | |
| 66 | +# ============================= # | |
| 67 | +mkdir -p $SRCDIR | |
| 68 | +mkdir -p $PKGDIR | |
| 69 | +mkdir -p $PRODDIR | |
| 70 | + | |
| 71 | + | |
| 72 | +# Make sure that wget is installed | |
| 73 | +# TODO: If not installed, execute "brew install wget" | |
| 74 | + | |
| 75 | + | |
| 76 | +# =============== # | |
| 77 | +# Install ncurses # | |
| 78 | +# =============== # | |
| 79 | +cd $SRCDIR | |
| 80 | +if [ ! -d "$NCURSES" ]; then | |
| 81 | + wget https://ftp.gnu.org/pub/gnu/ncurses/$NCURSES.tar.gz | |
| 82 | + tar xvfz $NCURSES.tar.gz | |
| 83 | +fi | |
| 84 | +cd $NCURSES | |
| 85 | +./configure --prefix=$INSTALLDIR --with-shared | |
| 86 | +make | |
| 87 | +make install | |
| 88 | + | |
| 89 | + | |
| 90 | +# ================ # | |
| 91 | +# Install readline # | |
| 92 | +# ================ # | |
| 93 | +cd $SRCDIR | |
| 94 | +if [ ! -d "$READLINE" ]; then | |
| 95 | + wget https://ftp.gnu.org/pub/gnu/readline/$READLINE.tar.gz | |
| 96 | + tar xvfz $READLINE.tar.gz | |
| 97 | +fi | |
| 98 | +cd $READLINE | |
| 99 | +./configure --prefix=$INSTALLDIR | |
| 100 | +make | |
| 101 | +make install | |
| 102 | + | |
| 103 | + | |
| 104 | +# =============== # | |
| 105 | +# Install cfitsio # | |
| 106 | +# =============== # | |
| 107 | +cd $SRCDIR | |
| 108 | +if [ ! -d "cfitsio" ]; then | |
| 109 | + wget http://heasarc.gsfc.nasa.gov/FTP/software/fitsio/c/$CFITSIO.tar.gz | |
| 110 | + tar xvfz $CFITSIO.tar.gz | |
| 111 | +fi | |
| 112 | +cd cfitsio | |
| 113 | +./configure --prefix=$INSTALLDIR | |
| 114 | +make shared | |
| 115 | +make install | |
| 116 | + | |
| 117 | + | |
| 118 | +# ================ # | |
| 119 | +# Install GammaLib # | |
| 120 | +# ================ # | |
| 121 | +cd $SRCDIR | |
| 122 | +if [ ! -d "$GAMMALIB" ]; then | |
| 123 | + wget http://cta.irap.omp.eu/ctools/releases/gammalib/$GAMMALIB.tar.gz | |
| 124 | + tar xvfz $GAMMALIB.tar.gz | |
| 125 | +fi | |
| 126 | +cd $GAMMALIB | |
| 127 | +./configure --prefix=$INSTALLDIR | |
| 128 | +make | |
| 129 | +make install | |
| 130 | + | |
| 131 | + | |
| 132 | +# ============== # | |
| 133 | +# Install ctools # | |
| 134 | +# ============== # | |
| 135 | +cd $SRCDIR | |
| 136 | +if [ ! -d "$CTOOLS" ]; then | |
| 137 | + wget http://cta.irap.omp.eu/ctools/releases/ctools/$CTOOLS.tar.gz | |
| 138 | + tar xvfz $CTOOLS.tar.gz | |
| 139 | +fi | |
| 140 | +cd $CTOOLS | |
| 141 | +./configure --prefix=$INSTALLDIR | |
| 142 | +make | |
| 143 | +make install | |
| 144 | + | |
| 145 | + | |
| 146 | +# ====================== # | |
| 147 | +# Build Mac OS X package # | |
| 148 | +# ====================== # | |
| 149 | +pkgbuild --analyze --root $INSTALLDIR $PLISTFILE | |
| 150 | +pkgbuild --identifier cta.irap.omp.eu.ctools.pkg \ | |
| 151 | + --version $VERSION \ | |
| 152 | + --root $INSTALLDIR \ | |
| 153 | + --install-location /usr/local/gamma \ | |
| 154 | + --component-plist $PLISTFILE \ | |
| 155 | + $PKGDIR/$CTOOLS.pkg | |
| 156 | + | |
| 157 | + | |
| 158 | +# ====================== # | |
| 159 | +# Build Mac OS X product # | |
| 160 | +# ====================== # | |
| 161 | +# Analyse existing package | |
| 162 | +productbuild --synthesize \ | |
| 163 | + --package $PKGDIR/$CTOOLS.pkg \ | |
| 164 | + $DISTFILE | |
| 165 | + | |
| 166 | +# Add information to dist file | |
| 167 | +sed -i '' '$ i \ | |
| 168 | +<license file="COPYING"/>\ | |
| 169 | +<title>'$CTOOLS'</title>\ | |
| 170 | +<organization>irap.omp.eu</organization>\ | |
| 171 | +<description>CTA Science Analysis Tools</description>\ | |
| 172 | +' "$PRODDIR/$CTOOLS.dist" | |
| 173 | + | |
| 174 | +# Build product | |
| 175 | +productbuild --distribution $DISTFILE \ | |
| 176 | + --version $VERSION \ | |
| 177 | + --resources $SRCDIR/$CTOOLS \ | |
| 178 | + --package-path $PKGDIR \ | |
| 179 | + $PRODDIR/$CTOOLS.pkg | |
| 180 | + | |
| 181 | +# Add additional files to production folder | |
| 182 | +cp $SRCDIR/$CTOOLS/COPYING $PRODDIR/License.txt | |
| 183 | + | |
| 184 | +# Add ReadMe | |
| 185 | +/bin/cat <<EOM >$PRODDIR/ReadMe.txt | |
| 186 | +This package will install | |
| 187 | + | |
| 188 | + ctools-$VERSION and gammalib-$VERSION | |
| 189 | + | |
| 190 | +for Mac OS X 10.7 or later. | |
| 191 | + | |
| 192 | +Installation requires approximately 260 MB of disk space. The package | |
| 193 | +will be installed in the directory /usr/local/gamma, hence you need | |
| 194 | +administrator privileges to do the install. | |
| 195 | + | |
| 196 | +Simply click on the installer package and follow the instructions. | |
| 197 | +The installation will take less than one minute. | |
| 198 | + | |
| 199 | +After installing the package, you have to initialise the ctools | |
| 200 | +environment. This will be done by invoking an initialisation script | |
| 201 | +that can be found in the /usr/local/gamma/bin directory. | |
| 202 | + | |
| 203 | +To invoke this script you need to add the following to your .bashrc | |
| 204 | +or $HOME/.profile script: | |
| 205 | + | |
| 206 | + export CTOOLS=/usr/local/gamma | |
| 207 | + source \$CTOOLS/bin/gammalib-init.sh | |
| 208 | + | |
| 209 | +If you use C shell or a variant then add the following to your | |
| 210 | +.cshrc or .tcshrc script: | |
| 211 | + | |
| 212 | + setenv CTOOLS /usr/local/gamma | |
| 213 | + source \$CTOOLS/bin/gammalib-init.csh | |
| 214 | + | |
| 215 | +More information on ctools can be found at | |
| 216 | +http://cta.irap.omp.eu/ctools/. | |
| 217 | + | |
| 218 | +If you encounter problems in installing or using this package, please | |
| 219 | +send your error report to jurgen.knodlseder@irap.omp.eu. In your report, | |
| 220 | +please specify your Mac OS X version and Python version and the problem | |
| 221 | +you're facing. | |
| 222 | +EOM | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | +# ==================== # | |
| 227 | +# Create Mac OS X disk # | |
| 228 | +# ==================== # | |
| 229 | +hdiutil create -volname $CTOOLS \ | |
| 230 | + -srcfolder $PRODDIR/$CTOOLS.pkg \ | |
| 231 | + -srcfolder $PRODDIR/License.txt \ | |
| 232 | + -srcfolder $PRODDIR/ReadMe.txt \ | |
| 233 | + $DMGFILE | ... | ... |
examples/Makefile.am
examples/README.md
| ... | ... | @@ -70,5 +70,8 @@ the ctools. |
| 70 | 70 | `show_spectrum.py` |
| 71 | 71 | > Displays spectrum generated by the csspec script. |
| 72 | 72 | |
| 73 | +`show_lightcurve.py` | |
| 74 | +> Displays lightcurve generated by the cslightcrv script. | |
| 75 | + | |
| 73 | 76 | `show_ts_distribution.py` |
| 74 | 77 | > Displays Test Statistic histograms generated using the cstsdist script. | ... | ... |
examples/show_lightcurve.py
0 → 100755
| 1 | +#! /usr/bin/env python | |
| 2 | +# ========================================================================== | |
| 3 | +# Display lightcurve generated by cslightcrv | |
| 4 | +# | |
| 5 | +# Copyright (C) 2017 Juergen Knoedlseder | |
| 6 | +# | |
| 7 | +# This program is free software: you can redistribute it and/or modify | |
| 8 | +# it under the terms of the GNU General Public License as published by | |
| 9 | +# the Free Software Foundation, either version 3 of the License, or | |
| 10 | +# (at your option) any later version. | |
| 11 | +# | |
| 12 | +# This program is distributed in the hope that it will be useful, | |
| 13 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 15 | +# GNU General Public License for more details. | |
| 16 | +# | |
| 17 | +# You should have received a copy of the GNU General Public License | |
| 18 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 19 | +# | |
| 20 | +# ========================================================================== | |
| 21 | +import sys | |
| 22 | +import gammalib | |
| 23 | +import cscripts | |
| 24 | +try: | |
| 25 | + import matplotlib.pyplot as plt | |
| 26 | + plt.figure() | |
| 27 | + plt.close() | |
| 28 | +except (ImportError, RuntimeError): | |
| 29 | + print('This script needs the "matplotlib" module') | |
| 30 | + sys.exit() | |
| 31 | + | |
| 32 | + | |
| 33 | +# =============== # | |
| 34 | +# Plot lightcurve # | |
| 35 | +# =============== # | |
| 36 | +def plot_lightcurve(filename, plotfile): | |
| 37 | + """ | |
| 38 | + Plot lightcurve | |
| 39 | + | |
| 40 | + Parameters | |
| 41 | + ---------- | |
| 42 | + filename : str | |
| 43 | + Name of lightcurve FITS file | |
| 44 | + plotfile : str | |
| 45 | + Plot file name | |
| 46 | + """ | |
| 47 | + # Read spectrum file | |
| 48 | + fits = gammalib.GFits(filename) | |
| 49 | + table = fits.table(1) | |
| 50 | + c_mjd = table['MJD'] | |
| 51 | + c_emjd = table['e_MJD'] | |
| 52 | + c_flux = table['EnergyFlux'] | |
| 53 | + c_eflux = table['e_EnergyFlux'] | |
| 54 | + c_ts = table['TS'] | |
| 55 | + c_upper = table['EFluxUpperLimit'] | |
| 56 | + | |
| 57 | + # Initialise arrays to be filled | |
| 58 | + mjd = [] | |
| 59 | + e_mjd = [] | |
| 60 | + flux = [] | |
| 61 | + e_flux = [] | |
| 62 | + ul_mjd = [] | |
| 63 | + ul_e_mjd = [] | |
| 64 | + ul_flux = [] | |
| 65 | + ul_e_flux = [] | |
| 66 | + | |
| 67 | + # Loop over rows of the file | |
| 68 | + nrows = table.nrows() | |
| 69 | + for row in range(nrows): | |
| 70 | + | |
| 71 | + # Get Test Statistic, flux and flux error | |
| 72 | + ts = c_ts.real(row) | |
| 73 | + flx = c_flux.real(row) | |
| 74 | + e_flx = c_eflux.real(row) | |
| 75 | + | |
| 76 | + # If Test Statistic is larger than 9 and twice the flux error is | |
| 77 | + # smaller than the flux, then append flux point ... | |
| 78 | + if ts > 9.0 and 2.0*e_flx < flx: | |
| 79 | + mjd.append(c_mjd.real(row)) | |
| 80 | + e_mjd.append(c_emjd.real(row)) | |
| 81 | + flux.append(c_flux.real(row)) | |
| 82 | + e_flux.append(c_eflux.real(row)) | |
| 83 | + | |
| 84 | + # ... otherwise append upper limit | |
| 85 | + else: | |
| 86 | + ul_mjd.append(c_mjd.real(row)) | |
| 87 | + ul_e_mjd.append(c_emjd.real(row)) | |
| 88 | + ul_flux.append(c_upper.real(row)) | |
| 89 | + ul_e_flux.append(0.5*c_upper.real(row)) | |
| 90 | + | |
| 91 | + # Plot the spectrum | |
| 92 | + plt.figure() | |
| 93 | + plt.semilogy() | |
| 94 | + plt.grid() | |
| 95 | + plt.errorbar(mjd, flux, yerr=e_flux, xerr=[e_mjd, e_mjd], | |
| 96 | + fmt='ro') | |
| 97 | + plt.errorbar(ul_mjd, ul_flux, xerr=[ul_e_mjd, ul_e_mjd], | |
| 98 | + yerr=ul_e_flux, uplims=True, fmt='ro') | |
| 99 | + plt.xlabel('MJD (days)') | |
| 100 | + plt.ylabel(r'E $\times$ dN/dE (erg cm$^{-2}$ s$^{-1}$)') | |
| 101 | + | |
| 102 | + # Show figure | |
| 103 | + if len(plotfile) > 0: | |
| 104 | + plt.savefig(plotfile) | |
| 105 | + else: | |
| 106 | + plt.show() | |
| 107 | + | |
| 108 | + # Return | |
| 109 | + return | |
| 110 | + | |
| 111 | + | |
| 112 | +# =============== # | |
| 113 | +# Show lightcurve # | |
| 114 | +# =============== # | |
| 115 | +def show_lightcurve(): | |
| 116 | + """ | |
| 117 | + Show lightcurve | |
| 118 | + """ | |
| 119 | + # Set usage string | |
| 120 | + usage = 'show_lightcurve.py [-p plotfile] [file]' | |
| 121 | + | |
| 122 | + # Set default options | |
| 123 | + options = [{'option': '-p', 'value': ''}] | |
| 124 | + | |
| 125 | + # Get arguments and options from command line arguments | |
| 126 | + args, options = cscripts.ioutils.get_args_options(options, usage) | |
| 127 | + | |
| 128 | + # Extract script parameters from options | |
| 129 | + plotfile = options[0]['value'] | |
| 130 | + | |
| 131 | + # Plot lightcurve | |
| 132 | + plot_lightcurve(args[0], plotfile) | |
| 133 | + | |
| 134 | + # Return | |
| 135 | + return | |
| 136 | + | |
| 137 | + | |
| 138 | +# ======================== # | |
| 139 | +# Main routine entry point # | |
| 140 | +# ======================== # | |
| 141 | +if __name__ == '__main__': | |
| 142 | + | |
| 143 | + # Show lightcurve | |
| 144 | + show_lightcurve() | ... | ... |
examples/show_spectrum.py
src/ctulimit/ctulimit.cpp
| ... | ... | @@ -248,6 +248,9 @@ void ctulimit::run(void) |
| 248 | 248 | // Write header into logger |
| 249 | 249 | log_header1(TERSE, "Compute best-fit likelihood"); |
| 250 | 250 | |
| 251 | + // Make sure that requested model parameters is free | |
| 252 | + m_model_par->free(); | |
| 253 | + | |
| 251 | 254 | // Optimize and save best log-likelihood |
| 252 | 255 | m_obs.optimize(m_opt); |
| 253 | 256 | m_obs.errors(m_opt); |
| ... | ... | @@ -610,6 +613,9 @@ void ctulimit::ulimit_bisection(const double& min, const double& max) |
| 610 | 613 | if (std::abs(eval_mid) < m_tol) { |
| 611 | 614 | break; |
| 612 | 615 | } |
| 616 | + if (std::abs(wrk_max-wrk_min) < m_tol) { | |
| 617 | + break; | |
| 618 | + } | |
| 613 | 619 | |
| 614 | 620 | // Change boundaries for further iteration |
| 615 | 621 | if (eval_mid > 0.0) { | ... | ... |
test/data/lightcurve.fits
0 → 100644
No preview for this file type
test/test_cslightcrv.py
| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | # ========================================================================== |
| 3 | 3 | # This scripts performs unit tests for the cslightcrv script. |
| 4 | 4 | # |
| 5 | -# Copyright (C) 2016 Juergen Knoedlseder | |
| 5 | +# Copyright (C) 2016-2017 Juergen Knoedlseder | |
| 6 | 6 | # |
| 7 | 7 | # This program is free software: you can redistribute it and/or modify |
| 8 | 8 | # it under the terms of the GNU General Public License as published by |
| ... | ... | @@ -239,7 +239,8 @@ class Test(test): |
| 239 | 239 | """ |
| 240 | 240 | # Expected column names |
| 241 | 241 | cols = ['MJD', 'e_MJD', 'Prefactor', 'e_Prefactor', |
| 242 | - 'Index', 'e_Index', 'TS', 'UpperLimit'] | |
| 242 | + 'Index', 'e_Index', 'TS', 'DiffUpperLimit', | |
| 243 | + 'FluxUpperLimit', 'EFluxUpperLimit'] | |
| 243 | 244 | |
| 244 | 245 | # Open FITS file |
| 245 | 246 | fits = gammalib.GFits(filename) | ... | ... |
test/test_examples.py.in
| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | # ========================================================================== |
| 3 | 3 | # Performs unit tests for the ctools example scripts |
| 4 | 4 | # |
| 5 | -# Copyright (C) 2016 Juergen Knoedlseder | |
| 5 | +# Copyright (C) 2016-2017 Juergen Knoedlseder | |
| 6 | 6 | # |
| 7 | 7 | # This program is free software: you can redistribute it and/or modify |
| 8 | 8 | # it under the terms of the GNU General Public License as published by |
| ... | ... | @@ -128,6 +128,8 @@ class Test(gammalib.GPythonTestSuite): |
| 128 | 128 | 'Test show_sensitivity.py') |
| 129 | 129 | self.append(self.test_show_spectrum, |
| 130 | 130 | 'Test show_spectrum.py') |
| 131 | + self.append(self.test_show_lightcurve, | |
| 132 | + 'Test show_lightcurve.py') | |
| 131 | 133 | self.append(self.test_show_ts_distribution, |
| 132 | 134 | 'Test ts_distribution.py') |
| 133 | 135 | self.append(self.test_show_obs, |
| ... | ... | @@ -401,6 +403,20 @@ class Test(gammalib.GPythonTestSuite): |
| 401 | 403 | # Return |
| 402 | 404 | return |
| 403 | 405 | |
| 406 | + # Test show_lightcurve | |
| 407 | + def test_show_lightcurve(self): | |
| 408 | + """ | |
| 409 | + Test show_lightcurve | |
| 410 | + """ | |
| 411 | + # Set arguments | |
| 412 | + args = '-p example_show_lightcurve.eps %s/lightcurve.fits' % self._datadir | |
| 413 | + | |
| 414 | + # Execute script | |
| 415 | + self._execute_python('show_lightcurve', args=args) | |
| 416 | + | |
| 417 | + # Return | |
| 418 | + return | |
| 419 | + | |
| 404 | 420 | # Test show_ts_distribution |
| 405 | 421 | def test_show_ts_distribution(self): |
| 406 | 422 | """ | ... | ... |