diff --git a/ChangeLog b/ChangeLog index 57ad70b..c1e231f 100755 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,11 @@ -2021-03-05 +2021-04-30 * Version 2.0.0 released ======================== + Add ASCL shields to "About" page (#3630) + Use file function constructor in csspec (#3626) + Add BINS method to csspec (#3606) Add hidden "fix_spat" parameter to cttsmap (#3562) Add optimizer setter to ctlikelihood base class Add Sphinx tutorials test script (#3510) @@ -15,6 +18,16 @@ Add support of rectangular On/Off regions (#3248) +2021-04-28 + + * Bug fix version 1.7.4 released + ================================ + + Add conda activation and deactivation scripts for csh (#3628) + Replace spectral model by file function in csspec (#3624) + Update csinfo script (#3623) + + 2020-12-02 * Bug fix version 1.7.3 released diff --git a/Makefile.am b/Makefile.am index 4f9db82..bd1df1c 100755 --- a/Makefile.am +++ b/Makefile.am @@ -33,9 +33,11 @@ pkgconfig_DATA = ctools.pc # Conda activate directory condaactivatedir = $(sysconfdir)/conda/activate.d -condaactivate_DATA = dev/01-ctools-activate.sh +condaactivate_DATA = dev/01-ctools-activate.sh \ + dev/01-ctools-activate.csh condadeactivatedir = $(sysconfdir)/conda/deactivate.d -condadeactivate_DATA = dev/00-ctools-deactivate.sh +condadeactivate_DATA = dev/00-ctools-deactivate.sh \ + dev/00-ctools-deactivate.csh # Manual pages to install man_MANS = @@ -55,6 +57,7 @@ EXTRA_DIST = README.md \ doc/Doxyfile doc/source \ dev/testreport.py \ dev/01-ctools-activate.sh dev/00-ctools-deactivate.sh \ + dev/01-ctools-activate.csh dev/00-ctools-deactivate.csh \ dev/conda.recipe/build.sh \ dev/conda.recipe/conda_build_config.yaml \ dev/conda.recipe/meta.yaml.in diff --git a/NEWS b/NEWS index 1f43670..cc92779 100755 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ New Features and Important Changes in ctools 2.0.0 -5 March 2021 +30 April 2021 Introduction @@ -16,6 +16,8 @@ None Documentation ------------- +Add Astrophysics Source Code Library (ASCL) shields to "About" page (#3630). + Add test/tutorials.py script and check-tutorial target to test the code in the Sphinx tutorials (#3510). @@ -285,7 +287,12 @@ None csspec - Generates Spectral Energy Distribution ----------------------------------------------- -None +The GModelSpectralFunc spectral model constructor is now used to convert any +spectral model into a file function before spectral model fitting (#3626). + +Added BINS method that replaces the spectral model by a bin function that is +implemented by the GammaLib class GModelSpectralBins. Using a bin function +assures that spectral points are statistically independent (#3606). cssrcdetect - Detects sources in sky map diff --git a/README.md b/README.md index 5a87f6a..89f17ce 100755 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ctools information ================== -* Version: 2.0.0.dev (5 March 2021) +* Version: 2.0.0.dev (30 April 2021) * GammaLib dependency: 2.0.0.dev [![Build Status](https://cta-jenkins.irap.omp.eu/buildStatus/icon?job=ctools-integrate-os)](https://cta-jenkins.irap.omp.eu/job/ctools-integrate-os/) @@ -127,8 +127,8 @@ the following: $ conda install ctools -Unix Installation -================= +Linux Installation +================== To build and install ctools, simply type the following: $ ./configure @@ -161,14 +161,14 @@ ctools was correctly built. Make sure that all tests were successful. Macintosh OS X Installation ============================ -ctools is known to work on various flavors of OS X. To cope with +ctools is known to work on various flavors of Mac OS. To cope with different system versions and architectures, there are two Mac specific configure options: $ ./configure --enable-universalsdk[=PATH] creates a universal build of ctools. The optional argument specifies -which OSX SDK should be used to perform the build. This defaults to +which MacOS SDK should be used to perform the build. This defaults to "/Developer/SDKs/MacOSX.10.4u.sdk". Specify "/" when building on a 10.5 system or higher, especially when building 64-bit code. @@ -221,7 +221,8 @@ shared library (see "Known problems" below). Windows Installation ==================== -There have been no efforts so far to compile ctools under Windows. +On Windows ctools needs to be installed into a virtual machine running +a Linux distribution. Testing diff --git a/cscripts/csinfo.py b/cscripts/csinfo.py index 6e0281f..fcd7bae 100755 --- a/cscripts/csinfo.py +++ b/cscripts/csinfo.py @@ -2,7 +2,7 @@ # ========================================================================== # Print info about Gammalib / ctools to the console # -# Copyright (C) 2015-2016 Christoph Deil +# Copyright (C) 2015-2021 Christoph Deil # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -32,10 +32,13 @@ CTOOL_LIST = """ ctedispcube Generates energy dispersion cube cterror Calculates likelihood profile errors ctexpcube Generates exposure cube + ctfindvar Search for source variability ctlike Performs maximum likelihood fitting ctmapcube Generates a map cube ctmodel Computes model counts cube ctobssim Simulate CTA observations + ctphase Computes the phase of each event + ctprob Computes event probability for a given model ctpsfcube Generates point spread function cube ctselect Selects event data ctskymap Generates sky map @@ -47,20 +50,31 @@ CTOOL_LIST = """ # `doc/source/users/reference_manual/index.rst` # and needs to be manually updated and kept in sync CSCRIPT_LIST = """ + csbkgmodel Generates background model for 3D analysis cscaldb Lists available instrument response functions + csebins Generates energy boundaries for stacked analysis cslightcrv Computes lightcurve csinfo Checks ctools and GammaLib installations csmodelinfo Shows model container content csmodelmerge Merges several model containers into one file + csmodelselect Select models from model definition file + csmodelsois Generate map cube from subset of models csobsdef Generates observation definition file csobsinfo Shows observation container content + csobsselect Select observations from observation definition file + csphagen Generates PHA, ARF, RMF files based on source/background regions + csphasecrv Computes phase curve cspull Generates pull distribution csresmap Generates residual map + csresspec Generates residual spectrum + csscs Performs spectral component separation cssens Computes CTA sensitivity csspec Computes spectral points + cssrcdetect Detects sources in sky map cstsdist Generates TS distribution + cstsmapmerge Merges slices from Test Statistic map computations cstsmapsplit Creates commands to split the Test Statistic map computations - cstsmapmerge Merges slices from Test Statistic map computations\n + csviscube Computes visibility cube\n csobs2caldb Creates a caldb entry from an input observation csroot2caldb Creates a caldb entry from a ROOT performance file csiactdata Shows information about IACT data available on the user machine diff --git a/cscripts/csphagen.py b/cscripts/csphagen.py index 9ffd6f7..e39a3ca 100755 --- a/cscripts/csphagen.py +++ b/cscripts/csphagen.py @@ -614,7 +614,8 @@ class csphagen(ctools.csobservation): msg = ' Skip because the number %d of regions' \ 'for background estimation not overlapping ' \ 'with the exclusion region is smaller than ' \ - '"bkgregmin"=%d.' % (bkg_reg.size(), self['bkgregmin'].integer()) + '"bkgregmin"=%d.' % \ + (regions.size(), self['bkgregmin'].integer()) self._log_string(gammalib.NORMAL, msg) regions = gammalib.GSkyRegions() diff --git a/cscripts/csspec.par b/cscripts/csspec.par index e333e97..4edbbae 100755 --- a/cscripts/csspec.par +++ b/cscripts/csspec.par @@ -31,7 +31,7 @@ outfile, f, a, spectrum.fits,,, "Output spectrum file" # # Script parameters #================== -method, s, a, AUTO,SLICE|NODES|AUTO,, "Spectrum generation method" +method, s, a, AUTO,SLICE|NODES|BINS|AUTO,, "Spectrum generation method" ebinalg, s, a, LOG,FILE|LIN|LOG|POW,, "Algorithm for defining energy bins" emin, r, a, 0.1,,, "Start value for first energy bin in TeV" emax, r, a, 100.0,,, "Stop value for last energy bin in TeV" @@ -43,6 +43,7 @@ calc_ts, b, h, yes,,, "Compute TS value in each bin" calc_ulim, b, h, yes,,, "Compute upper limit in each bin" fix_srcs, b, h, yes,,, "Fix other skymodel parameters" fix_bkg, b, h, no,,, "Fix background parameters" +bingamma, r, h, -2.0,,, "Spectral index for BINS method" dll_sigstep, r, h, 0.0,0.0,100.0, "Step size in standard deviations for log-like profiles" dll_sigmax, r, h, 5.0,1.0,100.0, "Maximum number of standard deviations for log-like profiles" dll_freenodes, b, h, no,,, "Free nodes not being fit when computing log-like profiles" diff --git a/cscripts/csspec.py b/cscripts/csspec.py index b8e854e..8f70550 100755 --- a/cscripts/csspec.py +++ b/cscripts/csspec.py @@ -20,6 +20,7 @@ # ========================================================================== import sys import math +import tempfile # Kludge for file function generation import gammalib import ctools from cscripts import mputils @@ -144,9 +145,9 @@ class csspec(ctools.csobservation): n_cta = n_unbinned + n_binned + n_onoff n_other = self.obs().size() - n_cta - # If spectrum method is not "NODES" then set spectrum method and - # script mode according to type of observations - if self._method != 'NODES': + # If spectrum method is not "NODES" or 'BINS" then set spectrum method + # and script mode according to type of observations + if self._method != 'NODES' and self._method != 'BINS': if n_other > 0: self._method = 'NODES' else: @@ -178,6 +179,7 @@ class csspec(ctools.csobservation): self['calc_ts'].boolean() self['fix_bkg'].boolean() self['fix_srcs'].boolean() + self['bingamma'].real() # Setup dlog-likelihood parameters self['dll_sigstep'].real() @@ -213,10 +215,10 @@ class csspec(ctools.csobservation): elif n_other > 0: if self._method == 'SLICE': msg = 'Selected "SLICE" method but none of the observations ' \ - 'is a CTA observation. Please select "AUTO" or "NODES" ' \ - 'if no CTA observation is provided.' + 'is a CTA observation. Please select "AUTO", "NODES" ' \ + 'or "BINS" if no CTA observation is provided.' raise RuntimeError(msg) - else: + elif self._method == 'AUTO': self._method = 'NODES' # Log selected spectrum method @@ -366,6 +368,18 @@ class csspec(ctools.csobservation): ' Fixing "'+par.name()+'"') par.fix() + # Convert spectral model into a file function. The file + # function is logarithmically sampled in energy, with with + # 20 times the number of spectral bins + nbins = self._ebounds.size() + num = nbins * 50 + energies = gammalib.GEnergies(num, self._ebounds.emin(0), + self._ebounds.emax(nbins-1)) + spectral = gammalib.GModelSpectralFunc(model.spectral(), energies) + model.spectral(spectral) + self._log_string(gammalib.EXPLICIT, ' Converting spectral model ' + 'into file function') + # Free the normalisation parameter which is assumed to be # the first spectral parameter normpar = model.spectral()[0] @@ -456,6 +470,64 @@ class csspec(ctools.csobservation): # Return return + def _set_replace_src_spectrum_by_bins(self): + """ + Replace source spectrum by bin function + """ + # Initialise model container + models = gammalib.GModels() + + # Loop over model containers + for model in self.obs().models(): + + # If we deal with source model then replace the spectral model + # by a bin function + if model.name() == self['srcname'].string(): + + # Get spectral bins index + bingamma = self['bingamma'].real() + + # Setup spectral bin function + spectrum = gammalib.GModelSpectralBins(model.spectral(), + self._ebounds, + bingamma) + spectrum.autoscale() + + # Make sure that all bins are positive. Autoscale all + # parameters so that their nominal value is unity. + for i in range(spectrum.bins()): + name = 'Intensity%d' % i + par = spectrum[name] + par.autoscale() + value = par.value() + minimum = 1.0e-20 * value + if minimum <= 0.0: + minimum = 1.0e-20 + if minimum < value: + value = minimum + par.value(value) + par.min(minimum) + + # Set spectral component of source model + model.spectral(spectrum) + + # Make sure that TS computation is disabled (makes computation + # faster) + model.tscalc(False) + + # Append model + models.append(model) + + # ... otherwise just append model + else: + models.append(model) + + # Put new model in observation containers + self.obs().models(models) + + # Return + return + def _select_onoff_obs(self, obs, emin, emax): """ Select an energy interval from one CTA On/Off observation @@ -854,8 +926,8 @@ class csspec(ctools.csobservation): # Write model results for explicit chatter level self._log_string(gammalib.EXPLICIT, str(like.obs().models())) - # Loop over all nodes - for i in range(spectrum.nodes()): + # Loop over all nodes or bins + for i in range(self._ebounds.size()): # Get energy boundaries emin = self._ebounds.emin(i) @@ -878,23 +950,26 @@ class csspec(ctools.csobservation): # Convert differential flux and flux error to nuFnu norm = elogmean.MeV() * elogmean.MeV() * gammalib.MeV2erg - result['flux'] = spectrum[i*2+1].value() - result['e2dnde'] = spectrum[i*2+1].value() * norm - result['flux_err'] = spectrum[i*2+1].error() + result['flux'] = spectrum.intensity(i) + result['e2dnde'] = spectrum.intensity(i) * norm + result['flux_err'] = spectrum.error(i) # Compute upper flux limit ulimit_value = -1.0 - parname = 'Intensity%d' % i + parname = 'Intensity%d' % i # Compute delta log-likelihood if self['dll_sigstep'].real() > 0.0: # Extract the normalization scan values - (norm_scan, dlogL, loglike) = self._profile_logL(like.copy(), parname, elogmean) + (norm_scan, dlogL, loglike) = self._profile_logL(like.copy(), + parname, + elogmean) result['norm_scan'] = norm_scan result['dloglike'] = dlogL result['logL'] = loglike + # Compute upper flux limit if self['calc_ulim'].boolean(): # Logging information @@ -938,7 +1013,7 @@ class csspec(ctools.csobservation): # Set intensity of node to tiny value by scaling the value # by a factor 1e-8. - par = obs.models()[self['srcname'].string()].spectral()[i*2+1] + par = obs.models()[self['srcname'].string()].spectral()[parname] par.autoscale() par.factor_min(1.0e-8) par.factor_value(1.0e-8) @@ -1006,10 +1081,11 @@ class csspec(ctools.csobservation): source.tscalc(False) # Fix all parameters in the spectral model - if (self._method != 'NODES') or (not self['dll_freenodes'].boolean()): + if (self._method != 'NODES' and self._method != 'BINS') or \ + (not self['dll_freenodes'].boolean()): for par in spectral: par.fix() - + # Re-compute the log-likelihood like.run() loglike = like.obs().logL() @@ -1137,7 +1213,7 @@ class csspec(ctools.csobservation): table.append(dnde) table.append(TSvalues) table.append(Npred_values) - + # Define the SED type table.card('SED_TYPE', 'norm,e2dnde,dnde,npred', 'SED type') @@ -1197,6 +1273,15 @@ class csspec(ctools.csobservation): # Fit model results = self._fit_model() + # Case C: "BINS" method + elif self._method == 'BINS': + + # Replace source spectrum by bins function + self._set_replace_src_spectrum_by_bins() + + # Fit model + results = self._fit_model() + # Create FITS file self._create_fits(results) diff --git a/ctools.pc.in b/ctools.pc.in index 1c37d89..18099a3 100755 --- a/ctools.pc.in +++ b/ctools.pc.in @@ -8,7 +8,7 @@ Description: CTA science analysis tools URL: http://cta.irap.omp.eu/ctools Version: @VERSION@ Requires: -Requires.private: gammalib == @VERSION@ +Requires.private: gammalib = @VERSION@ Conflicts: Cflags: -I${includedir}/ctools @OPENMP_CXXFLAGS@ Libs: -L${libdir} -lctools diff --git a/dev/00-ctools-deactivate.csh b/dev/00-ctools-deactivate.csh new file mode 100644 index 0000000..245fec7 --- /dev/null +++ b/dev/00-ctools-deactivate.csh @@ -0,0 +1,4 @@ +#!/bin/csh + +unsetenv CTOOLS +unsetenv CALDB diff --git a/dev/01-ctools-activate.csh b/dev/01-ctools-activate.csh new file mode 100644 index 0000000..16ce2f5 --- /dev/null +++ b/dev/01-ctools-activate.csh @@ -0,0 +1,7 @@ +#!/bin/csh + +setenv CTOOLS ${CONDA_PREFIX} +source ${CTOOLS}/bin/ctools-init.csh +unsetenv PYTHONPATH +unsetenv LD_LIBRARY_PATH +unsetenv DYLD_LIBRARY_PATH diff --git a/doc/source/_static/logo-cyfronet.png b/doc/source/_static/logo-cyfronet.png new file mode 100644 index 0000000..69573f8 --- /dev/null +++ b/doc/source/_static/logo-cyfronet.png diff --git a/doc/source/_static/logo-desy.png b/doc/source/_static/logo-desy.png new file mode 100644 index 0000000..28929fc --- /dev/null +++ b/doc/source/_static/logo-desy.png diff --git a/doc/source/_static/logo-ecap.jpg b/doc/source/_static/logo-ecap.jpg new file mode 100644 index 0000000..80f8114 --- /dev/null +++ b/doc/source/_static/logo-ecap.jpg diff --git a/doc/source/_static/logo-irap.png b/doc/source/_static/logo-irap.png new file mode 100644 index 0000000..a6d04e4 --- /dev/null +++ b/doc/source/_static/logo-irap.png diff --git a/doc/source/_static/logo-lapp.png b/doc/source/_static/logo-lapp.png new file mode 100644 index 0000000..dd25bea --- /dev/null +++ b/doc/source/_static/logo-lapp.png diff --git a/doc/source/_static/logo-lupm.png b/doc/source/_static/logo-lupm.png new file mode 100644 index 0000000..8ce26ee --- /dev/null +++ b/doc/source/_static/logo-lupm.png diff --git a/doc/source/_static/logo-mpik.png b/doc/source/_static/logo-mpik.png new file mode 100644 index 0000000..58605dc --- /dev/null +++ b/doc/source/_static/logo-mpik.png diff --git a/doc/source/_templates/index.html b/doc/source/_templates/index.html index 1ee65ce..96b2666 100755 --- a/doc/source/_templates/index.html +++ b/doc/source/_templates/index.html @@ -16,14 +16,35 @@ is supported as well. {%endtrans%}

{%trans%} ctools are based on GammaLib, a versatile toolbox for the scientific analysis of astronomical gamma-ray data. Besides CTA, GammaLib supports the analysis of H.E.S.S., MAGIC, VERITAS, -Fermi/LAT, COMPTEL and INTEGRAL/SPI data. GammaLib supports in particular the +Fermi/LAT, CGRO/COMPTEL and INTEGRAL/SPI data. GammaLib supports in particular the combination of data from different instruments in a true joint multi-wavelength analysis that consistently handles the response of each instrument. An interface -to virtual observatory ressources does also exist. +to virtual observatory resources does also exist. {%endtrans%}

-

{%trans%} ctools are developed by a team of enthousiastic gamma-ray -astronomers with support from engineers. We regularily organise +

{%trans%} ctools are developed by a community of enthousiastic gamma-ray +astronomers with support from engineers. The lead institute is

+ + + + + +
IRAP
+ +

As of today there have been contributions by the following institutions:

+ + + + + + + + + + +
DESYECAPMPIKCyfronetLAPPLUPM
+ +

We regularily organise coding sprints where key developers but also newcomers meet to discuss the developments and next steps, and advance with the coding of the software. diff --git a/doc/source/about.rst b/doc/source/about.rst index d67ecd3..2a33cfc 100755 --- a/doc/source/about.rst +++ b/doc/source/about.rst @@ -16,11 +16,11 @@ Creation of shell or Python scripts and pipelines is supported as well. ctools are based on GammaLib, a versatile toolbox for the scientific analysis of astronomical gamma-ray data. Besides CTA, GammaLib supports the analysis of H.E.S.S., MAGIC, VERITAS, -Fermi/LAT, COMPTEL and INTEGRAL/SPI data. +Fermi/LAT, CGRO/COMPTEL and INTEGRAL/SPI data. GammaLib supports in particular the combination of data from different instruments in a true joint multi-wavelength analysis that consistently handles the response of each instrument. -An interface to virtual observatory ressources does also exist. +An interface to virtual observatory resources does also exist. ctools are developed by a team of enthousiastic gamma-ray astronomers with support from engineers. We regularily organise @@ -40,20 +40,29 @@ to include the formal reference L. Gerard, A. Schulz, P. Martin, D. Sanchez, S. Ohm, T. Hassan, and S. Brau-Nogue, 2016, A&A, 593, A1 `_ -in your paper as well as the identifiers -`ascl:1601.005 `_ and -`ascl:1110.007 `_ of the ctools and GammaLib -packages in the Astrophysics Source Code Library (ASCL). -You can also reference ctools via +in your paper as well as the Astrophysics Source Code Library (ASCL) identifiers + +.. image:: https://img.shields.io/badge/ascl-1601.005-blue.svg?colorB=262255 + :target: http://ascl.net/1601.005 + +for ctools and + +.. image:: https://img.shields.io/badge/ascl-1110.007-blue.svg?colorB=262255 + :target: http://ascl.net/1110.007 + +for GammaLib. You may also reference the softwares by their Digital Object +Identifiers (DOI) on Zenodo, which are .. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.3265423.svg :target: https://doi.org/10.5281/zenodo.3265423 -and GammaLib via +for ctools and .. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.3265404.svg :target: https://doi.org/10.5281/zenodo.3265404 +for GammaLib. + In addition please add the following acknowledgment: *This research made use of ctools, a community-developed analysis package diff --git a/doc/source/admin/download.rst b/doc/source/admin/download.rst index d3dc9b0..0450cb8 100755 --- a/doc/source/admin/download.rst +++ b/doc/source/admin/download.rst @@ -3,7 +3,7 @@ Download ======== -The latest ctools release is ``ctools-1.7.3`` (2 December 2020). +The latest ctools release is ``ctools-1.7.4`` (28 April 2021). Below a table of ctools releases. Please read the :ref:`sec_release` to learn more about new features and corrected bugs in a given release. @@ -23,6 +23,9 @@ learn more about new features and corrected bugs in a given release. * - ctools - gammalib - Mac OS (10.7+) binary disk image + * - `1.7.4 `_ + - `1.7.4 `_ + - `ctools-1.7.4-macosx10.7.dmg `_ * - `1.7.3 `_ - `1.7.3 `_ - `ctools-1.7.3-macosx10.7.dmg `_ diff --git a/doc/source/admin/install_conda.rst b/doc/source/admin/install_conda.rst index f5d3e7e..7b2830c 100644 --- a/doc/source/admin/install_conda.rst +++ b/doc/source/admin/install_conda.rst @@ -36,8 +36,8 @@ Installing .. code-block:: bash - $ conda create -n myenv python=2.7 # or e.g. python=3.5 - $ source activate myenv + $ conda create -n myenv python=3.5 # or one of the following Python versions: 2.7, 3.5, 3.6, 3.7, 3.8 + $ conda activate myenv (myenv) $ - Install pre-compiled ctools conda package from Anaconda cloud with: @@ -53,7 +53,7 @@ Installing .. code-block:: bash - (myenv) $ source activate myenv + (myenv) $ conda activate myenv Testing diff --git a/doc/source/admin/release_history/1.7.4.rst b/doc/source/admin/release_history/1.7.4.rst new file mode 100644 index 0000000..d521f3b --- /dev/null +++ b/doc/source/admin/release_history/1.7.4.rst @@ -0,0 +1,18 @@ +.. _1.7.4: + +ctools 1.7.4 release (28 April 2021) +==================================== + +Overview +-------- + +ctools 1.7.4 is a bug fix release for ctools release 1.7. + +The following bugs were fixed: + +* [`3628 `_] - + Add conda activation and deactivation scripts for csh +* [`3624 `_] - + Replace spectral model by file function in :ref:`csspec` +* [`3623 `_] - + Update csinfo script diff --git a/doc/source/admin/release_history/2.0.rst b/doc/source/admin/release_history/2.0.rst index 5c1ab24..272f7d3 100644 --- a/doc/source/admin/release_history/2.0.rst +++ b/doc/source/admin/release_history/2.0.rst @@ -1,7 +1,7 @@ .. _2.0: -ctools 2.0 release (5 March 2021) -================================= +ctools 2.0 release (30 April 2021) +================================== Overview -------- @@ -24,6 +24,12 @@ Bug fixes Improvements ------------ +* [`3630 `_] - + Add ASCL shields to **About** page +* [`3626 `_] - + Use file function constructor in csspec +* [`3606 `_] - + Add ``BINS`` method to :ref:`csspec` * [`3562 `_] - Add hidden ``fix_spat`` parameter to :ref:`cttsmap` * Add optimizer setter to ``ctlikelihood`` base class. diff --git a/doc/source/admin/release_history/index.rst b/doc/source/admin/release_history/index.rst index 5149ff4..719e79c 100755 --- a/doc/source/admin/release_history/index.rst +++ b/doc/source/admin/release_history/index.rst @@ -7,6 +7,7 @@ Release History :maxdepth: 1 ctools 2.0 <2.0> + ctools 1.7.4 <1.7.4> ctools 1.7.3 <1.7.3> ctools 1.7.2 <1.7.2> ctools 1.7.1 <1.7.1> diff --git a/doc/source/develop/releasing/index.rst b/doc/source/develop/releasing/index.rst index 869a5ba..59851bc 100755 --- a/doc/source/develop/releasing/index.rst +++ b/doc/source/develop/releasing/index.rst @@ -21,4 +21,5 @@ To create a new ctools release you have to go through the following steps: * added unit tests for all new code * added a page about the software changes to the release history * updated the User documentation if necessary + * updated the csinfo script if necessary diff --git a/doc/source/users/reference_manual/csspec.rst b/doc/source/users/reference_manual/csspec.rst index 2557e8d..5e5b981 100755 --- a/doc/source/users/reference_manual/csspec.rst +++ b/doc/source/users/reference_manual/csspec.rst @@ -19,15 +19,29 @@ significance of the source detection. Optionally, it also computes an upper flux limit that is particularly useful in case that the source is not significantly detected within a spectral bin (hidden parameter ``calc_ulim``). -There are two fundamental methods to run the script depending on the value of -the ``method`` parameter. If ``method=SLICE`` the energy interval defined by the -``emin`` and ``emax`` parameters is divided into a number of energy bins and an -independent maximum likelihood fit is performed in each of the energy bins, -while if ``method=NODES`` the spectral model will be replaced by a node function -that will be fit to all data. The latter is particularly useful if non-CTA data -should be fitted such as data from Fermi/LAT or COMPTEL. By default, ``method`` is -set to ``AUTO`` which will automatically select the method based on the input data. -For CTA-only observations ``SLICE`` will be used, otherwise ``NODES`` will be used. +There are three fundamental methods to run the script depending on the value of +the ``method`` parameter, ``SLICE``, ``BINS`` and ``NODES``. + +If ``method=SLICE`` the energy interval defined by the ``emin`` and ``emax`` +parameters is divided into a number of energy bins and an independent maximum +likelihood fit is performed in each of the energy bins. In order to cope with +all kinds of spectral models, including composite spectra, input spectrum will +be converted into a file function, with the normalisation of the file function +being the fit parameter for each energy bin. This implies that spectral +components are merged into a single function using the model parameters that +are specified in the input model. + +If ``method=BINS`` the spectral model will be replaced by a bin function that +will be fit to all data, with ``method=NODES`` the spectral model will be replaced +by a node function. The advantage of ``BINS`` over ``NODES`` is that with ``BINS`` +the spectral flux points are statistically independent, while with ``NODES`` the +underlying spectral model connects spectral flux points using a piecewise power +law. Both methods are particularly useful if non-CTA data should be fitted such +as data from Fermi/LAT, CGRO/COMPTEL or INTEGRAL/SPI. + +By default, ``method`` is set to ``AUTO`` which will automatically select the +method based on the input data. For CTA-only observations ``SLICE`` will be used, +otherwise ``NODES`` will be used. The spectral binning is either defined by a FITS file containing the energy boundaries of each bin (option ``ebinalg=FILE``) or as ``enumbins`` bins spread @@ -54,9 +68,6 @@ the fitted flux and flux error, the Test Statistics value (option ``calc_ts=yes``), the upper flux limit (option ``calc_ulim=yes``) and the predicted number of events (only for unbinned data). -.. warning:: - The upper limit computation is not yet implemented for the ``NODES`` method. - General parameters ------------------ @@ -95,13 +106,17 @@ General parameters ``outfile [file]`` Output spectrum FITS file. -``method [string]`` +``method [string]`` Spectrum generation method. - ``SLICE`` will slice energy interval into ``enumbins`` independent bins, - ``NODES`` will replace spectral model by node function with ``enumbins`` - nodes, and ``AUTO`` will automatically select the method based on the input - data. For CTA-only observations ``SLICE`` will be used, otherwise ``NODES`` - will be used. + ``SLICE`` will slice the energy interval into ``enumbins`` independent + bins, + ``NODES`` will replace the spectral model by a node function with + ``enumbins`` nodes, + ``BINS`` will replace the spectral model by a bin function with + ``enumbins`` nodes, + and ``AUTO`` will automatically select the method based on the input + data. If ``AUTO`` is selected and there are only CTA observations + then ``SLICE`` will be used, otherwise ``NODES`` will be used. ``ebinalg [string]`` Algorithm for defining energy bins. For ``FILE``, the energy bins are defined @@ -151,6 +166,10 @@ General parameters ``(fix_bkg = no) [boolean]`` Fix background model parameters? +``(bingamma = -2.0) [real]`` + Spectral index for ``BINS`` method. Within each spectral bin a power law + will be assumed with the specified spectral index. + ``(dll_sigstep = 0) [real]`` Step size in standard deviations for log-like profiles. Note this value determines the number of steps to use. diff --git a/examples/show_spectrum.py b/examples/show_spectrum.py index 0b91071..ddd015a 100755 --- a/examples/show_spectrum.py +++ b/examples/show_spectrum.py @@ -2,7 +2,7 @@ # ========================================================================== # Display spectrum generated by csspec # -# Copyright (C) 2015-2020 Juergen Knoedlseder +# Copyright (C) 2015-2021 Juergen Knoedlseder # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,6 +18,7 @@ # along with this program. If not, see . # # ========================================================================== +import os import sys try: import matplotlib.pyplot as plt @@ -70,7 +71,7 @@ def get_spectrum_fits(fits): ---------- fits : `~gammalib.GFits` Spectral GFits object - + Returns ------- spec : dict @@ -168,7 +169,7 @@ def get_spectrum_fits(fits): # ========================= # # Plot delta log-likelihood # # ========================= # -def plot_dloglike(spec): +def plot_dloglike(ax, spec): """ Plot delta log-likelihood @@ -187,7 +188,7 @@ def plot_dloglike(spec): # Compute the logarithmic center of each bin fluxpnts = 10 ** ((y_bounds[1:]+y_bounds[:-1]) / 2.0) - + # Scale the boundaries on the grid y_bounds = 10 ** y_bounds @@ -201,12 +202,12 @@ def plot_dloglike(spec): dll_hist = [[row[i] for row in dll_hist] for i in range(steps)] # Plot the likelihood profiles - plt.pcolormesh(np.array(spec['engs_scan']), y_bounds, - np.array(dll_hist), vmin=-10.0, vmax=0.0, - cmap='Reds', alpha=0.9) - cbar = plt.colorbar() + c = ax.pcolormesh(np.array(spec['engs_scan']), y_bounds, + np.array(dll_hist), vmin=-10.0, vmax=0.0, + cmap='Reds', alpha=0.9) + cbar = plt.colorbar(c) cbar.set_label(r'$\Delta$ log-likelihood') - plt.grid() + ax.grid() # Return return @@ -229,27 +230,48 @@ def plot_spectrum(filename, plotfile): # Get spectrum parameters spec = get_spectrum_file(filename) + # Set energy scale of spectrum + if max(spec['energies']+spec['ul_energies']) < 1.0e-3: + xlabel = 'Energy (MeV)' + conv = 1.0e6 + elif max(spec['energies']) < 1.0: + xlabel = 'Energy (GeV)' + conv = 1.0e3 + else: + xlabel = 'Energy (TeV)' + conv = 1.0 + if conv != 1.0: + spec['energies'] = [e * 1.0e6 for e in spec['energies']] + spec['ed_engs'] = [e * 1.0e6 for e in spec['ed_engs']] + spec['eu_engs'] = [e * 1.0e6 for e in spec['eu_engs']] + spec['ul_energies'] = [e * 1.0e6 for e in spec['ul_energies']] + spec['ul_ed_engs'] = [e * 1.0e6 for e in spec['ul_ed_engs']] + spec['ul_eu_engs'] = [e * 1.0e6 for e in spec['ul_eu_engs']] + # Create the plot - plt.figure() - plt.loglog() - plt.grid() - plt.xlabel('Energy (TeV)') - plt.ylabel(r'E$^2$ $\times$ dN/dE (erg cm$^{-2}$ s$^{-1}$)') + fig = plt.figure() + fig.subplots_adjust(left=0.17, right=0.98, top=0.92, bottom=0.10) + ax = fig.add_subplot(111) + ax.loglog() + ax.grid() + ax.set_xlabel(xlabel) + ax.set_ylabel(r'E$^2$ $\times$ dN/dE (erg cm$^{-2}$ s$^{-1}$)') + ax.set_title(os.path.basename(filename)) # Plot the spectrum - plt.errorbar(spec['energies'], spec['flux'], + ax.errorbar(spec['energies'], spec['flux'], yerr=spec['e_flux'], xerr=[spec['ed_engs'], spec['eu_engs']], fmt='ro') # Plot upper limits if len(spec['ul_energies']) > 0: - plt.errorbar(spec['ul_energies'], spec['ul_flux'], yerr=spec['yerr'], + ax.errorbar(spec['ul_energies'], spec['ul_flux'], yerr=spec['yerr'], xerr=[spec['ul_ed_engs'], spec['ul_eu_engs']], uplims=True, fmt='ro') # Plot log-likelihood profiles if len(spec['dll_scan']) > 0: - plot_dloglike(spec) + plot_dloglike(ax, spec) # Show figure if len(plotfile) > 0: diff --git a/sonar-project.properties b/sonar-project.properties index 91387e8..b2293d8 100755 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -21,7 +21,7 @@ sonar.cxx.missingIncludeWarnings=False # Exclusions sonar.exclusions=src/template/cscript_test.py,src/template/ctool_test.py,cscripts/tests/**,pyext/build/**,pyext/ctools/tools.py,pyext/ctools/*_wrap.cpp,pyext/ctools/tests/**,dev/**,doc/**,test/dev/** -sonar.coverage.exclusions=src/template/**,test/science_verification.py,test/test_examples.py,test/test_mputils.py,pyext/setup.py +sonar.coverage.exclusions=src/template/**,test/science_verification.py,test/test_examples.py,test/test_mputils.py,test/tutorials.py,pyext/setup.py sonar.cpd.exclusions=examples/**,test/**,pyext/ctools/tools.py # C++ configuration diff --git a/test/test_cttsmap.py b/test/test_cttsmap.py index 6f664b4..e1d439a 100755 --- a/test/test_cttsmap.py +++ b/test/test_cttsmap.py @@ -2,7 +2,7 @@ # ========================================================================== # This scripts performs unit tests for the cttsmap tool # -# Copyright (C) 2014-2018 Juergen Knoedlseder +# Copyright (C) 2014-2021 Juergen Knoedlseder # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -175,12 +175,13 @@ class Test(test): # Execute copy of cttsmap tool again, now with a higher chatter # level than before - cpy_tsmap['binmin'] = 0 - cpy_tsmap['binmax'] = 1 - cpy_tsmap['outmap'] = 'cttsmap_py2.fits' - cpy_tsmap['logfile'] = 'cttsmap_py2.log' - cpy_tsmap['chatter'] = 3 - cpy_tsmap['publish'] = True + cpy_tsmap['binmin'] = 0 + cpy_tsmap['binmax'] = 1 + cpy_tsmap['fix_spat'] = True + cpy_tsmap['outmap'] = 'cttsmap_py2.fits' + cpy_tsmap['logfile'] = 'cttsmap_py2.log' + cpy_tsmap['chatter'] = 3 + cpy_tsmap['publish'] = True cpy_tsmap.logFileOpen() # Needed to get a new log file cpy_tsmap.execute()