Skip to content

Commit

Permalink
Add test_spectrum
Browse files Browse the repository at this point in the history
This concludes the refactoring of TARDISSpectrum.

The syntax for the dummy to_hdf was slightly changed to match the syntax of pandas
to_hdf() methods. That means the 'name' parameter was removed as there
is no reason for the function do decide where it should save to and the
path is now a required argument.
  • Loading branch information
yeganer committed Jun 6, 2017
1 parent 9e45a76 commit 6cd9bdb
Show file tree
Hide file tree
Showing 3 changed files with 263 additions and 66 deletions.
16 changes: 6 additions & 10 deletions tardis/montecarlo/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,12 @@ class MontecarloRunner(object):

def __init__(self, seed, spectrum_frequency, virtual_spectrum_range,
sigma_thomson, enable_reflective_inner_boundary,
inner_boundary_albedo, line_interaction_type, distance=None):
inner_boundary_albedo, line_interaction_type):

self.seed = seed
self.packet_source = packet_source.BlackBodySimpleSource(seed)
self.spectrum_frequency = spectrum_frequency
self.virtual_spectrum_range = virtual_spectrum_range
self.distance = distance
self.sigma_thomson = sigma_thomson
self.enable_reflective_inner_boundary = enable_reflective_inner_boundary
self.inner_boundary_albedo = inner_boundary_albedo
Expand Down Expand Up @@ -99,15 +98,13 @@ def _initialize_packets(self, T, no_of_packets, no_of_virtual_packets=None):
def spectrum(self):
return TARDISSpectrum(
self.spectrum_frequency,
self.montecarlo_emitted_luminosity,
self.distance)
self.montecarlo_emitted_luminosity)

@property
def spectrum_reabsorbed(self):
return TARDISSpectrum(
self.spectrum_frequency,
self.montecarlo_reabsorbed_luminosity,
self.distance)
self.montecarlo_reabsorbed_luminosity)

@property
def spectrum_virtual(self):
Expand All @@ -118,8 +115,7 @@ def spectrum_virtual(self):

return TARDISSpectrum(
self.spectrum_frequency,
self.montecarlo_virtual_luminosity,
self.distance)
self.montecarlo_virtual_luminosity)

def run(self, model, plasma, no_of_packets, no_of_virtual_packets=0, nthreads=1,last_run=False):
"""
Expand Down Expand Up @@ -394,5 +390,5 @@ def from_config(cls, config):
sigma_thomson=sigma_thomson,
enable_reflective_inner_boundary=config.montecarlo.enable_reflective_inner_boundary,
inner_boundary_albedo=config.montecarlo.inner_boundary_albedo,
line_interaction_type=config.plasma.line_interaction_type,
distance=config.supernova.get('distance', None))
line_interaction_type=config.plasma.line_interaction_type
)
115 changes: 59 additions & 56 deletions tardis/montecarlo/spectrum.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import os
import numpy as np
from astropy import constants, units as u

from tardis.io.util import to_hdf
from astropy import units as u


def require_field(name):
def _require_field(f):
def wrapper(self, *args, **kwargs):
if not getattr(self, name, None):
raise AttributeError(
'{} is required as attribute of {} to calculate {}'.format(
'{} is required as attribute of'
'{} to calculate {}'.format(
name,
self.__class__.__name__,
f.__name__
Expand All @@ -24,51 +23,72 @@ def wrapper(self, *args, **kwargs):

class TARDISSpectrum(object):
"""
TARDIS Spectrum object
"""

def __init__(self, frequency, luminosity, distance=None):
self.distance = distance
TARDISSpectrum(_frequency, luminosity)
self._frequency = frequency
self.delta_frequency = frequency[1] - frequency[0]
self.wavelength = self.frequency.to('angstrom', u.spectral())
_frequency: astropy.units.Quantity with unit 'Hz' or a length
These are bin edges of frequency or wavelenght bins for the spectrum.
self._luminosity = luminosity
luminosity: astropy.units.Quantity with unit Energy per second
The luminosity in each bin of the spectrum.
self.luminosity_density_nu = (
luminosity / self.delta_frequency).to('erg / (s Hz)')
self.luminosity_density_lambda = u.Quantity(
self.f_nu_to_f_lambda(self.luminosity_density_nu.value),
'erg / (s Angstrom)'
)

if self.distance is not None:
self._flux_nu = (
self.luminosity_density_nu /
(4 * np.pi * self.distance.to('cm')**2))
After manually adding a distance attribute, the properties 'flux_nu' and
'flux_lambda' become available
"""

self._flux_lambda = u.Quantity(
self.f_nu_to_f_lambda(self.flux_nu.value),
'erg / (s Angstrom cm^2)'
def __init__(self, _frequency, luminosity):
if not _frequency.shape[0] == luminosity.shape[0] + 1:
raise ValueError(
"shape of '_frequency' and 'luminosity' are not compatible"
": '{}' and '{}'".format(
_frequency.shape[0],
luminosity.shape[0])
)
self._frequency = _frequency.to('Hz', u.spectral())
self.luminosity = luminosity.to('erg / s')

@property
def frequency(self):
return self._frequency[:-1]

@property
def delta_frequency(self):
return self.frequency[1] - self.frequency[0]

@property
def wavelength(self):
return self.frequency.to('angstrom', u.spectral())

@property
def luminosity_density_nu(self):
return (self.luminosity / self.delta_frequency).to('erg / (s Hz)')

@property
def luminosity_density_lambda(self):
return self.f_nu_to_f_lambda(
self.luminosity_density_nu,
)

@property
@require_field('distance')
def flux_nu(self):
return self._flux_nu
return self.luminosity_to_flux(
self.luminosity_density_nu,
self.distance)

@property
@require_field('distance')
def flux_lambda(self):
return self._flux_lambda
return self.luminosity_to_flux(
self.luminosity_density_lambda,
self.distance
)

@staticmethod
def luminosity_to_flux(luminosity, distance):
return luminosity / (4 * np.pi * distance.to('cm')**2)

def f_nu_to_f_lambda(self, f_nu):
return f_nu * self.frequency.value**2 / constants.c.cgs.value / 1e8
return f_nu * self.frequency / self.wavelength

def plot(self, ax, mode='wavelength'):
if mode == 'wavelength':
Expand All @@ -80,32 +100,15 @@ def to_ascii(self, fname, mode='luminosity_density'):
if mode == 'luminosity_density':
np.savetxt(fname, zip(self.wavelength.value, self.luminosity_density_lambda.value))
elif mode == 'flux':
np.savetxt(fname, zip(self.wavelength.value, self.flux_lambda.value))
np.savetxt(
fname,
zip(self.wavelength.value, self.flux_lambda.value))
else:
raise NotImplementedError('only mode "luminosity_density" and "flux" are implemented')

def to_hdf(self, path_or_buf, path='', name=''):
"""
Store the spectrum to an HDF structure.
Parameters
----------
path_or_buf
Path or buffer to the HDF store
path : str
Path inside the HDF store to store the spectrum
name : str, optional
A different name than 'spectrum', if needed.
Returns
-------
None
"""
if not name:
name = 'spectrum'
spectrum_path = os.path.join(path, name)
properties = ['luminosity_density_nu', 'delta_frequency', 'wavelength',
'luminosity_density_lambda']
to_hdf(path_or_buf, spectrum_path, {name: getattr(self, name) for name
in properties})
def to_hdf(self, path_or_buf, path):
pass

@classmethod
def from_hdf(cls, path_or_buf, path):
pass
Loading

0 comments on commit 6cd9bdb

Please sign in to comment.