diff --git a/.travis.yml b/.travis.yml index dd9a1a9b..2b2a81e7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,8 +26,8 @@ env: - PYTHON_VERSION=3.6 - NUMPY_VERSION=1.13 - ASTROPY_VERSION=stable - - CONDA_DEPENDENCIES='pytest pip Cython jinja2 pyyaml scipy matplotlib h5py mock sphinx_rtd_theme' - - PIP_DEPENDENCIES='emcee corner' + - CONDA_DEPENDENCIES='pytest pip Cython jinja2 pyyaml scipy matplotlib h5py mock sphinx_rtd_theme traitlets' + - PIP_DEPENDENCIES='emcee corner numtraits' matrix: - PYTHON_VERSION=2.7 SETUP_CMD='egg_info' diff --git a/CHANGES.rst b/CHANGES.rst index a3538c2d..f08e598b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,9 @@ 0.9 (unreleased) ---------------- +- Added the `ProtonSynchrotron` class to compute synchrotron radiation from + proton populations. + 0.8.3 (2018-11-27) ------------------ diff --git a/appveyor.yml b/appveyor.yml index b71f1ef1..7356fb77 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,8 +14,8 @@ environment: PYTHON_ARCH: "64" # needs to be set for CMD_IN_ENV to succeed. If a mix # of 32 bit and 64 bit builds are needed, move this # to the matrix section. - CONDA_DEPENDENCIES: "pytest pip Cython jinja2 pyyaml scipy matplotlib h5py mock sphinx_rtd_theme" - PIP_DEPENDENCIES: "emcee" + CONDA_DEPENDENCIES: "pytest pip Cython jinja2 pyyaml scipy matplotlib h5py mock sphinx_rtd_theme traitlets" + PIP_DEPENDENCIES: "emcee numtraits" ASTROPY_VERSION: "stable" matrix: diff --git a/naima/models.py b/naima/models.py index d8238bc9..dbb989f2 100644 --- a/naima/models.py +++ b/naima/models.py @@ -16,11 +16,20 @@ validate_array, validate_physical_type, ) -from .radiative import Synchrotron, InverseCompton, PionDecay, Bremsstrahlung +from .radiative import ( + Synchrotron, + ElectronSynchrotron, + ProtonSynchrotron, + InverseCompton, + PionDecay, + Bremsstrahlung, +) from .model_utils import memoize __all__ = [ "Synchrotron", + "ElectronSynchrotron", + "ProtonSynchrotron", "InverseCompton", "PionDecay", "Bremsstrahlung", diff --git a/naima/radiative.py b/naima/radiative.py index 40fe77f9..245c5d6f 100644 --- a/naima/radiative.py +++ b/naima/radiative.py @@ -7,6 +7,10 @@ unicode_literals, ) import numpy as np + +from numtraits import NumericalTrait +from traitlets import HasTraits, Int, observe + from .extern.validator import ( validate_scalar, validate_array, @@ -95,6 +99,17 @@ def __init__(self, particle_distribution): physical_type="differential energy", ) + def _spectrum(self, photon_energy): + """ + Compute photon spectrum. Implemented in subclasses + + Parameters + ---------- + photon_energy : :class:`~astropy.units.Quantity` instance + Photon energy array. + """ + raise NotImplementedError + @memoize def flux(self, photon_energy, distance=1 * u.kpc): """Differential flux at a given distance from the source. @@ -148,13 +163,18 @@ def sed(self, photon_energy, distance=1 * u.kpc): return sed -class BaseElectron(BaseRadiative): - """Implements gam and nelec properties in addition to the BaseRadiative methods +class BaseLorentzFactor(BaseRadiative): + """ + Implements gam and npart properties in addition to the BaseRadiative + methods """ - def __init__(self, particle_distribution): - super(BaseElectron, self).__init__(particle_distribution) - self.param_names = ["Eemin", "Eemax", "nEed"] + def __init__(self, particle_distribution, mass): + super(BaseLorentzFactor, self).__init__(particle_distribution) + self.param_names = ["gmin", "gmax", "ngd"] + mass = validate_scalar("mass", mass, physical_type="mass") + self.mc2 = (mass * c ** 2).cgs + self.mc2_unit = u.Unit(self.mc2) self._memoize = True self._cache = {} self._queue = [] @@ -163,71 +183,72 @@ def __init__(self, particle_distribution): def _gam(self): """ Lorentz factor array """ - log10gmin = np.log10(self.Eemin / mec2).value - log10gmax = np.log10(self.Eemax / mec2).value + log10gmin = np.log10(self.gmin) + log10gmax = np.log10(self.gmax) return np.logspace( - log10gmin, log10gmax, int(self.nEed * (log10gmax - log10gmin)) + log10gmin, log10gmax, int(self.ngd * (log10gmax - log10gmin)) ) @property - def _nelec(self): + def _npart(self): """ Particles per unit lorentz factor """ - pd = self.particle_distribution(self._gam * mec2) - return pd.to(1 / mec2_unit).value + pd = self.particle_distribution(self._gam * self.mc2) + return pd.to(1 / self.mc2_unit).value @property - def We(self): - """ Total energy in electrons used for the radiative calculation + def _W(self): + """ Total energy in particles used for the radiative calculation """ - We = trapz_loglog(self._gam * self._nelec, self._gam * mec2) - return We + gam = self._gam + return trapz_loglog(gam * self._npart, gam * self.mc2) - def compute_We(self, Eemin=None, Eemax=None): - """ Total energy in electrons between energies Eemin and Eemax + def _compute_W(self, Emin=None, Emax=None): + """ Total energy in particles between energies Emin and Emax Parameters ---------- Eemin : :class:`~astropy.units.Quantity` float, optional - Minimum electron energy for energy content calculation. + Minimum particle energy for energy content calculation. Eemax : :class:`~astropy.units.Quantity` float, optional - Maximum electron energy for energy content calculation. + Maximum particle energy for energy content calculation. """ - if Eemin is None and Eemax is None: - We = self.We + if Emin is None and Emax is None: + W = self._W else: - if Eemax is None: - Eemax = self.Eemax - if Eemin is None: - Eemin = self.Eemin + if Emin is None: + Emin = self.gmin * self.mc2 + if Emax is None: + Emax = self.gmax * self.mc2 - log10gmin = np.log10(Eemin / mec2).value - log10gmax = np.log10(Eemax / mec2).value + log10gmin = np.log10(Emin / self.mc2).value + log10gmax = np.log10(Emax / self.mc2).value gam = np.logspace( - log10gmin, log10gmax, int(self.nEed * (log10gmax - log10gmin)) - ) - nelec = ( - self.particle_distribution(gam * mec2).to(1 / mec2_unit).value + log10gmin, log10gmax, int(self.ngd * (log10gmax - log10gmin)) ) - We = trapz_loglog(gam * nelec, gam * mec2) - return We + pd = self.particle_distribution(gam * self.mc2) + npart = pd.to(1 / self.mc2_unit).value - def set_We(self, We, Eemin=None, Eemax=None, amplitude_name=None): - """ Normalize particle distribution so that the total energy in electrons - between Eemin and Eemax is We + W = trapz_loglog(gam * npart, gam * self.mc2) + + return W + + def _set_W(self, W, Emin=None, Emax=None, amplitude_name=None): + """ Normalize particle distribution so that the total energy in + particles between Emin and Emax is W Parameters ---------- - We : :class:`~astropy.units.Quantity` float - Desired energy in electrons. + W : :class:`~astropy.units.Quantity` float + Desired energy in particles. - Eemin : :class:`~astropy.units.Quantity` float, optional - Minimum electron energy for energy content calculation. + Emin : :class:`~astropy.units.Quantity` float, optional + Minimum particle energy for energy content calculation. - Eemax : :class:`~astropy.units.Quantity` float, optional - Maximum electron energy for energy content calculation. + Emax : :class:`~astropy.units.Quantity` float, optional + Maximum particle energy for energy content calculation. amplitude_name : str, optional Name of the amplitude parameter of the particle distribution. It @@ -235,72 +256,165 @@ def set_We(self, We, Eemin=None, Eemax=None, amplitude_name=None): Defaults to ``amplitude``. """ - We = validate_scalar("We", We, physical_type="energy") - oldWe = self.compute_We(Eemin=Eemin, Eemax=Eemax) + W = validate_scalar("W", W, physical_type="energy") + oldW = self._compute_W(Emin=Emin, Emax=Emax) + factor = (W / oldW).decompose() if amplitude_name is None: try: - self.particle_distribution.amplitude *= ( - We / oldWe - ).decompose() + self.particle_distribution.amplitude *= factor except AttributeError: log.error( "The particle distribution does not have an attribute" " called amplitude to modify its normalization: you can" - " set the name with the amplitude_name parameter of set_We" + " set the name with the amplitude_name parameter of set_W" ) else: oldampl = getattr(self.particle_distribution, amplitude_name) setattr( - self.particle_distribution, - amplitude_name, - oldampl * (We / oldWe).decompose(), + self.particle_distribution, amplitude_name, oldampl * factor ) -class Synchrotron(BaseElectron): - """Synchrotron emission from an electron population. +class BaseElectron(BaseLorentzFactor, HasTraits): + """ + Sets particle mass of BaseLorentzFactor to the electron mass + """ - This class uses the approximation of the synchrotron emissivity in a - random magnetic field of Aharonian, Kelner, and Prosekin 2010, PhysRev D - 82, 3002 (`arXiv:1006.1045 `_). + def __init__(self, particle_distribution): + super(BaseElectron, self).__init__(particle_distribution, mass=m_e) - Parameters - ---------- - particle_distribution : function - Particle distribution function, taking electron energies as a - `~astropy.units.Quantity` array or float, and returning the particle - energy density in units of number of electrons per unit energy as a - `~astropy.units.Quantity` array or float. + Eemin = NumericalTrait(convertible_to=u.erg) + Eemax = NumericalTrait(convertible_to=u.erg) + nEed = Int() - B : :class:`~astropy.units.Quantity` float instance, optional - Isotropic magnetic field strength. Default: equipartition - with CMB (3.24e-6 G) + @observe("Eemin") + def _handle_Eemin(self, change): + self.gmin = float(change["new"] / self.mc2) - Other parameters - ---------------- - Eemin : :class:`~astropy.units.Quantity` float instance, optional - Minimum electron energy for the electron distribution. Default is 1 - GeV. + @observe("Eemax") + def _handle_Eemax(self, change): + self.gmax = float(change["new"] / self.mc2) - Eemax : :class:`~astropy.units.Quantity` float instance, optional - Maximum electron energy for the electron distribution. Default is 510 - TeV. + @observe("nEed") + def _handle_nEed(self, change): + self.ngd = change["new"] - nEed : scalar - Number of points per decade in energy for the electron energy and - distribution arrays. Default is 100. + @property + def We(self): + """ Total energy in particles used for the radiative calculation + """ + return self._W + + def set_We(self, We, Eemin=None, Eemax=None, amplitude_name=None): + """ Normalize particle distribution so that the total energy in + electrons between `Eemin` and `Eemax` is `We` + + Parameters + ---------- + We : :class:`~astropy.units.Quantity` float + Desired energy in electrons. + + Eemin : :class:`~astropy.units.Quantity` float, optional + Minimum electron energy for energy content calculation. + + Eemax : :class:`~astropy.units.Quantity` float, optional + Maximum electron energy for energy content calculation. + + amplitude_name : str, optional + Name of the amplitude parameter of the particle distribution. It + must be accesible as an attribute of the distribution function. + Defaults to ``amplitude``. + """ + return self._set_W( + We, Emin=Eemin, Emax=Eemax, amplitude_name=amplitude_name + ) + + def compute_We(self, Eemin=None, Eemax=None): + """ Total energy in electrons between energies Emin and Emax + + Parameters + ---------- + Eemin : :class:`~astropy.units.Quantity` float, optional + Minimum electron energy for energy content calculation. + + Eemax : :class:`~astropy.units.Quantity` float, optional + Maximum electron energy for energy content calculation. + """ + return self._compute_W(Emin=Eemin, Emax=Eemax) + + +class BaseLorentzProton(BaseLorentzFactor, HasTraits): + """ + Sets particle mass of BaseLorentzFactor to the proton mass """ - def __init__(self, particle_distribution, B=3.24e-6 * u.G, **kwargs): - super(Synchrotron, self).__init__(particle_distribution) - self.B = validate_scalar("B", B, physical_type="magnetic flux density") - self.Eemin = 1 * u.GeV - self.Eemax = 1e9 * mec2 - self.nEed = 100 - self.param_names += ["B"] - self.__dict__.update(**kwargs) + def __init__(self, particle_distribution): + super(BaseLorentzProton, self).__init__( + particle_distribution, mass=m_p + ) + + Epmin = NumericalTrait(convertible_to=u.erg) + Epmax = NumericalTrait(convertible_to=u.erg) + nEpd = Int() + + @observe("Epmin") + def _handle_Epmin(self, change): + self.gmin = float(change["new"] / self.mc2) + + @observe("Epmax") + def _handle_Epmax(self, change): + self.gmax = float(change["new"] / self.mc2) + + @observe("nEpd") + def _handle_nEpd(self, change): + self.ngd = change["new"] + + @property + def Wp(self): + """ Total energy in particles used for the radiative calculation + """ + return self._W + + def set_Wp(self, Wp, Epmin=None, Epmax=None, amplitude_name=None): + """ Normalize particle distribution so that the total energy in + protons between `Epmin` and `Epmax` is `Wp` + + Parameters + ---------- + Wp : :class:`~astropy.units.Quantity` float + Desired energy in protons. + + Epmin : :class:`~astropy.units.Quantity` float, optional + Minimum proton energy for energy content calculation. + + Epmax : :class:`~astropy.units.Quantity` float, optional + Maximum proton energy for energy content calculation. + + amplitude_name : str, optional + Name of the amplitude parameter of the particle distribution. It + must be accesible as an attribute of the distribution function. + Defaults to ``amplitude``. + """ + return self._set_W( + Wp, Emin=Epmin, Emax=Epmax, amplitude_name=amplitude_name + ) + + def compute_Wp(self, Epmin=None, Epmax=None): + """ Total energy in protons between energies Emin and Emax + + Parameters + ---------- + Epmin : :class:`~astropy.units.Quantity` float, optional + Minimum proton energy for energy content calculation. + Epmax : :class:`~astropy.units.Quantity` float, optional + Maximum proton energy for energy content calculation. + """ + return self._compute_W(Emin=Epmin, Emax=Epmax) + + +class BaseSynchrotron(BaseLorentzFactor): def _spectrum(self, photon_energy): """Compute intrinsic synchrotron differential spectrum for energies in ``photon_energy`` @@ -342,8 +456,7 @@ def Gtilde(x): CS1_1 = ( 2 * np.pi - * m_e.cgs.value - * c.cgs.value ** 2 + * self.mc2.cgs.value * hbar.cgs.value * outspecene.to("erg").value ) @@ -357,13 +470,13 @@ def Gtilde(x): * self.B.to("G").value * self._gam ** 2 ) - Ec /= 2 * (m_e * c).cgs.value + Ec /= 2 * (self.mc2 / c).cgs.value EgEc = outspecene.to("erg").value / np.vstack(Ec) dNdE = CS1 * Gtilde(EgEc) # return units spec = ( - trapz_loglog(np.vstack(self._nelec) * dNdE, self._gam, axis=0) + trapz_loglog(np.vstack(self._npart) * dNdE, self._gam, axis=0) / u.s / u.erg ) @@ -372,6 +485,99 @@ def Gtilde(x): return spec +class ElectronSynchrotron(BaseElectron, BaseSynchrotron): + """Synchrotron emission from an electron population. + + This class uses the approximation of the synchrotron emissivity in a + random magnetic field of Aharonian, Kelner, and Prosekin 2010, PhysRev D + 82, 3002 (`arXiv:1006.1045 `_). + + Parameters + ---------- + particle_distribution : function + Particle distribution function, taking electron energies as a + `~astropy.units.Quantity` array or float, and returning the particle + energy density in units of number of electrons per unit energy as a + `~astropy.units.Quantity` array or float. + + B : :class:`~astropy.units.Quantity` float instance, optional + Isotropic magnetic field strength. Default: equipartition + with CMB (3.24e-6 G) + + Other parameters + ---------------- + Eemin : :class:`~astropy.units.Quantity` float instance, optional + Minimum electron energy for the electron distribution. Default is 1 + GeV. + + Eemax : :class:`~astropy.units.Quantity` float instance, optional + Maximum electron energy for the electron distribution. Default is 510 + TeV. + + nEed : scalar + Number of points per decade in energy for the electron energy and + distribution arrays. Default is 100. + """ + + def __init__(self, particle_distribution, B=3.24e-6 * u.G, **kwargs): + super(ElectronSynchrotron, self).__init__(particle_distribution) + self.B = validate_scalar("B", B, physical_type="magnetic flux density") + self.Eemin = 1 * u.GeV + self.Eemax = (1e9 * m_e * c ** 2).to(u.TeV) + self.nEed = 100 + self.param_names += ["B"] + for key, value in kwargs.items(): + setattr(self, key, value) + + +class Synchrotron(ElectronSynchrotron): + pass + + +class ProtonSynchrotron(BaseLorentzProton, BaseSynchrotron): + """Synchrotron emission from a proton population. + + This class uses the approximation of the synchrotron emissivity in a + random magnetic field of Aharonian, Kelner, and Prosekin 2010, PhysRev D + 82, 3002 (`arXiv:1006.1045 `_). + + Parameters + ---------- + particle_distribution : function + Particle distribution function, taking proton energies as a + `~astropy.units.Quantity` array or float, and returning the particle + energy density in units of number of protons per unit energy as a + `~astropy.units.Quantity` array or float. + + B : :class:`~astropy.units.Quantity` float instance, optional + Isotropic magnetic field strength. Default: equipartition + with CMB (3.24e-6 G) + + Other parameters + ---------------- + Epmin : :class:`~astropy.units.Quantity` float instance, optional + Minimum proton energy for the proton distribution. Default is 1 + GeV. + + Epmax : :class:`~astropy.units.Quantity` float instance, optional + Maximum proton energy for the proton distribution. Default is 1 PeV. + + nEpd : scalar + Number of points per decade in energy for the proton energy and + distribution arrays. Default is 100. + """ + + def __init__(self, particle_distribution, B=3.24e-6 * u.G, **kwargs): + super(ProtonSynchrotron, self).__init__(particle_distribution) + self.B = validate_scalar("B", B, physical_type="magnetic flux density") + self.Epmin = 1 * u.GeV + self.Epmax = 1 * u.PeV + self.nEpd = 100 + self.param_names += ["B"] + for key, value in kwargs.items(): + setattr(self, key, value) + + def G12(x, a): """ Eqs 20, 24, 25 of Khangulyan et al (2014) @@ -459,7 +665,8 @@ def __init__( self.Eemax = 1e9 * mec2 self.nEed = 100 self.param_names += ["seed_photon_fields"] - self.__dict__.update(**kwargs) + for key, value in kwargs.items(): + setattr(self, key, value) @staticmethod def _process_input_seed(seed_photon_fields): @@ -735,7 +942,7 @@ def _calc_specic(self, seed, outspecene): Eph, ) - lum = uf * Eph * trapz_loglog(self._nelec * gamint, self._gam) + lum = uf * Eph * trapz_loglog(self._npart * gamint, self._gam) lum = lum * u.Unit("1/s") return lum / outspecene # return differential spectrum in 1/s/eV @@ -893,7 +1100,8 @@ def __init__(self, particle_distribution, n0=1 / u.cm ** 3, **kwargs): self.weight_ee = np.sum(Z * X) self.weight_ep = np.sum(Z ** 2 * X) self.param_names += ["n0", "weight_ee", "weight_ep"] - self.__dict__.update(**kwargs) + for key, value in kwargs.items(): + setattr(self, key, value) @staticmethod def _sigma_1(gam, eps): @@ -1009,7 +1217,7 @@ def _emiss_ee(self, Eph): gam = np.vstack(self._gam) # compute integral with electron distribution emiss = c.cgs * trapz_loglog( - np.vstack(self._nelec) * self._sigma_ee(gam, Eph), + np.vstack(self._npart) * self._sigma_ee(gam, Eph), self._gam, axis=0, ) @@ -1026,7 +1234,7 @@ def _emiss_ep(self, Eph): eps = (Eph / mec2).decompose().value # compute integral with electron distribution emiss = c.cgs * trapz_loglog( - np.vstack(self._nelec) * self._sigma_ep(gam, eps), + np.vstack(self._npart) * self._sigma_ep(gam, eps), self._gam, axis=0, ).to(u.cm ** 2 / Eph.unit) diff --git a/naima/tests/test_models.py b/naima/tests/test_models.py index e094927c..920c6cda 100644 --- a/naima/tests/test_models.py +++ b/naima/tests/test_models.py @@ -6,6 +6,8 @@ from astropy.extern import six from astropy.modeling.blackbody import blackbody_nu +from traitlets import TraitError + from ..utils import trapz_loglog from ..models import ( Bremsstrahlung, @@ -70,7 +72,7 @@ def particle_dists(): @pytest.mark.skipif("not HAS_SCIPY") -def test_synchrotron_lum(particle_dists): +def test_electron_synchrotron_lum(particle_dists): """ test sync calculation """ @@ -107,6 +109,65 @@ def test_synchrotron_lum(particle_dists): assert_allclose(lsy.value, 31374131.90312505) +@pytest.mark.skipif("not HAS_SCIPY") +def test_proton_synchrotron_lum(particle_dists): + """ + test sync calculation + """ + from ..models import ProtonSynchrotron + + ECPL, PL, BPL = particle_dists + + # lum_ref = [0.00025231296225663107, 0.03316715765695228, + # 0.00044597089198025806] + # We_ref = [5064124672.902273, 11551172166.866821, 926633861.2898524] + + Wps = [] + lsys = [] + for pdist in particle_dists: + sy = ProtonSynchrotron(pdist, **proton_properties) + + Wps.append(sy.Wp.to("erg").value) + + lsy = trapz_loglog(sy.flux(energy, 0) * energy, energy).to("erg/s") + assert lsy.unit == u.erg / u.s + lsys.append(lsy.value) + + print(lsys) + print(Wps) + # assert_allclose(lsys, lum_ref) + # assert_allclose(Wes, We_ref) + + sy = ProtonSynchrotron(ECPL, B=1 * u.G, **proton_properties) + sy.flux(data) + sy.flux(data2) + + lsy = trapz_loglog(sy.flux(energy, 0) * energy, energy).to("erg/s") + assert lsy.unit == u.erg / u.s + print(lsy) + # assert_allclose(lsy.value, 31374131.90312505) + + +@pytest.mark.skipif("not HAS_SCIPY") +def test_synchrotron_traits(particle_dists): + from ..models import Synchrotron + + ECPL, _, _ = particle_dists + sy = Synchrotron(ECPL, Eemin=1 * u.GeV, Eemax=1 * u.PeV) + + sy.Eemin = 1 * u.TeV + assert sy.gmin == float(1 * u.TeV / (m_e * c ** 2)) + + sy.Eemax = 100 * u.TeV + assert sy.gmax == float(100 * u.TeV / (m_e * c ** 2)) + + sy.nEed = 10 + assert sy.ngd == 10 + + with pytest.raises(TraitError): + sy.Eemin = 10 * u.m + + @pytest.mark.skipif("not HAS_SCIPY") def test_bolometric_luminosity(particle_dists): """ @@ -131,9 +192,7 @@ def test_compute_We(particle_dists): ECPL, PL, BPL = particle_dists sy = Synchrotron(ECPL, B=1 * u.G, **electron_properties) - Eemin, Eemax = 10 * u.GeV, 100 * u.TeV - sy.compute_We() sy.compute_We(Eemin=Eemin) sy.compute_We(Eemax=Eemax) @@ -149,7 +208,9 @@ def test_compute_We(particle_dists): @pytest.mark.skipif("not HAS_SCIPY") -def test_set_We(particle_dists): +@pytest.mark.parametrize("Eemin", [1 * u.GeV, 10 * u.GeV, None]) +@pytest.mark.parametrize("Eemax", [100 * u.TeV, None]) +def test_set_We(particle_dists, Eemin, Eemax): """ test sync calculation """ @@ -161,18 +222,15 @@ def test_set_We(particle_dists): W = 1e49 * u.erg - Eemax = 100 * u.TeV - for Eemin in [1 * u.GeV, 10 * u.GeV, None]: - for Eemax in [100 * u.TeV, None]: - sy.set_We(W, Eemin, Eemax) - assert_allclose(W, sy.compute_We(Eemin, Eemax)) - sy.set_We(W, Eemin, Eemax, amplitude_name="amplitude") - assert_allclose(W, sy.compute_We(Eemin, Eemax)) - - pp.set_Wp(W, Eemin, Eemax) - assert_allclose(W, pp.compute_Wp(Eemin, Eemax)) - pp.set_Wp(W, Eemin, Eemax, amplitude_name="amplitude") - assert_allclose(W, pp.compute_Wp(Eemin, Eemax)) + sy.set_We(W, Eemin, Eemax) + assert_allclose(W, sy.compute_We(Eemin, Eemax)) + sy.set_We(W, Eemin, Eemax, amplitude_name="amplitude") + assert_allclose(W, sy.compute_We(Eemin, Eemax)) + + pp.set_Wp(W, Eemin, Eemax) + assert_allclose(W, pp.compute_Wp(Eemin, Eemax)) + pp.set_Wp(W, Eemin, Eemax, amplitude_name="amplitude") + assert_allclose(W, pp.compute_Wp(Eemin, Eemax)) with pytest.raises(AttributeError): sy.set_We(W, amplitude_name="norm") diff --git a/setup.py b/setup.py index 4f689ab8..7b9a6688 100644 --- a/setup.py +++ b/setup.py @@ -97,12 +97,14 @@ install_requires = ( [ "astropy>=1.0.2", - "emcee>=2.2.0", "corner", - "matplotlib", - "scipy", + "emcee>=2.2.0", "h5py", + "matplotlib", + "numtraits", "pyyaml", + "scipy", + "traitlets", ], )