def read_fits_spectrum1d(filename, dispersion_unit=None, flux_unit=None): """ 1D reader for spectra in FITS format. This function determines what format the FITS file is in, and attempts to read the Spectrum. This reader just uses the primary extension in a FITS file and reads the data and header from that. It will return a Spectrum1D object if the data is linear, or a list of Spectrum1D objects if the data format is multi-spec Parameters ---------- filename : str FITS filename dispersion_unit : ~astropy.unit.Unit, optional unit of the dispersion axis - will overwrite possible information given in the FITS keywords default = None flux_unit : ~astropy.unit.Unit, optional unit of the flux Raises -------- NotImplementedError If the format can't be read currently """ if dispersion_unit: dispersion_unit = u.Unit(dispersion_unit) data = fits.getdata(filename) header = fits.getheader(filename) wcs_info = FITSWCSSpectrum(header) if wcs_info.naxis == 1: wcs = read_fits_wcs_linear1d(wcs_info, dispersion_unit=dispersion_unit) return Spectrum1D(data, wcs=wcs) elif wcs_info.naxis == 2 and \ wcs_info.affine_transform_dict['ctype'] == ["MULTISPE", "MULTISPE"]: multi_wcs = multispec_wcs_reader(wcs_info, dispersion_unit=dispersion_unit) multispec = [] for spectrum_data, spectrum_wcs in zip(data, multi_wcs.values()): multispec.append( Spectrum1D(spectrum_data, wcs=spectrum_wcs)) return multispec elif wcs_info.naxis == 3 and \ wcs_info.affine_transform_dict['ctype'] == ["LINEAR","LINEAR","LINEAR"]: wcs = read_fits_wcs_linear1d(wcs_info, dispersion_unit=dispersion_unit) equispec = [] for i in range(data.shape[0]): equispec.append( Spectrum1D(data[i][0], wcs=wcs)) return equispec elif wcs_info.naxis == 3 and \ wcs_info.affine_transform_dict['ctype'] == ["MULTISPE", "MULTISPE","LINEAR"]: multi_wcs = multispec_wcs_reader(wcs_info, dispersion_unit=dispersion_unit) multispec = [] for j in range(data.shape[1]): equispec = [] for i in range(data.shape[0]): equispec.append( Spectrum1D(data[i][j], wcs=list(multi_wcs.values())[j])) multispec.append(equispec) return multispec else: raise NotImplementedError("Either the FITS file does not represent a 1D" " spectrum or the format isn't supported yet")
def test_fermi_isotropic(): filename = "$GAMMAPY_DATA/fermi_3fhl/iso_P8R2_SOURCE_V6_v06.txt" model = TableModel.read_fermi_isotropic_model(filename) assert_quantity_allclose( model(50 * u.GeV), 1.463 * u.Unit("1e-13 MeV-1 cm-2 s-1 sr-1"), rtol=1e-3 )
def unit(self, val): self._unit = u.Unit(val)
def read_file_spectrum(file, wave_units=q.um, flux_units=q.erg / q.s / q.cm**2 / q.AA, survey=None): """Create a spectrum from an ASCII, XML, or FITS file Parameters ---------- file: str The path to the file wave_units: str, astropy.units.quantity.Quantity The wavelength units flux_units: str, astropy.units.quantity.Quantity, None The flux units survey: str The name of the survey, ['SDSS'] Returns ------- list The [wavelength, flux, error] of the file spectrum with units """ # Read the fits data... if file.endswith('.fits'): if file.endswith('.fits'): data, head = fits.getdata(file, header=True) elif survey == 'SDSS': raw, head = fits.getdata(file, header=True) flux_units = 1E-17 * q.erg / q.s / q.cm**2 / q.AA wave_units = q.AA log_w = head['COEFF0'] + head['COEFF1'] * np.arange(len(raw.flux)) data = [10**log_w, raw.flux, raw.ivar] # Check if it is a recarray elif isinstance(raw, fits.fitsrec.FITS_rec): # Check if it's an SDSS spectrum raw = fits.getdata(file, ext=ext) data = raw['WAVELENGTH'], raw['FLUX'], raw['ERROR'] # Otherwise just an array else: print("Sorry, I cannot read the file at", file) # ...or the ascii data... elif file.endswith('.txt'): data = np.genfromtxt(file, unpack=True) # ...or the VO Table elif file.endswith('.xml'): vot = vo.parse_single_table(file) data = np.array([list(i) for i in vot.array]).T else: raise IOError('The file needs to be ASCII, XML, or FITS.') # Make sure units are astropy quantities if isinstance(wave_units, str): wave_units = q.Unit(wave_units) if isinstance(flux_units, str): flux_units = q.Unit(flux_units) # Sanity check for wave_units if data[0].min() > 100 and wave_units == q.um: print( "WARNING: Your wavelength range ({} - {}) looks like Angstroms. Are you sure it's {}?" .format(data[0].min(), data[0].max(), wave_units)) # Apply units wave = data[0] * wave_units flux = data[1] * (flux_units or 1.) if len(data) > 2: unc = data[2] * (flux_units or 1.) else: unc = None return [wave, flux, unc]
datastore = DataStore.from_dir("$HESS_DATA") src=SkyCoord.from_name(name) sep=SkyCoord.separation(src,datastore.obs_table.pointing_radec) srcruns=(datastore.obs_table[sep<2.0*u.deg]) obsid=srcruns['OBS_ID'].data mylist=datastore.obs_list((obsid[0],)) # Define obs parameters livetime_src = 10.0 * u.hr livetime = mylist[0].observation_live_time_duration offset = SkyCoord.separation(mylist[0].pointing_radec,src) lo_threshold = 0.1 * u.TeV hi_threshold = 60 * u.TeV # Define spectral model index = 2.0 * u.Unit('') amplitude = 2.5 * 1e-10 * u.Unit('cm-2 s-1 TeV-1') reference = 1 * u.TeV model = PowerLaw(index=index, amplitude=amplitude, reference=reference) #do a user defined model too! edisp=mylist[0].edisp.to_energy_dispersion(offset=offset) aeff=mylist[0].aeff.to_effective_area_table(offset=offset) aeff.lo_threshold = lo_threshold aeff.hi_threshold = hi_threshold
import pytest import numpy as np from astropy.wcs import WCS from astropy import units as u from astropy.io import fits from ..spectral_cube import SpectralCube from .helpers import assert_allclose # the back of the book dv = 3e-2 * u.Unit('m/s') dy = 2e-5 * u.Unit('deg') dx = 1e-5 * u.Unit('deg') data_unit = u.dimensionless_unscaled m0v = np.array([[27, 30, 33], [36, 39, 42], [45, 48, 51]]) * data_unit * dv m0y = np.array([[9, 12, 15], [36, 39, 42], [63, 66, 69]]) * data_unit * dy m0x = np.array([[3, 12, 21], [30, 39, 48], [57, 66, 75]]) * data_unit * dx # M1V is a special case, where we return the actual coordinate m1v = np.array([[1.66666667, 1.6, 1.54545455], [1.5, 1.46153846, 1.42857143], [1.4, 1.375, 1.35294118]]) * dv + 2 * u.Unit('m/s') m1y = np.array([[1.66666667, 1.5, 1.4], [1.16666667, 1.15384615, 1.14285714], [1.0952381, 1.09090909, 1.08695652]]) * dy m1x = np.array([[1.66666667, 1.16666667, 1.0952381], [1.06666667, 1.05128205, 1.04166667], [1.03508772, 1.03030303, 1.02666667]]) * dx m2v = np.array([[0.22222222, 0.30666667, 0.36914601], [0.41666667, 0.45364892, 0.4829932],
def evaluate(x): return np.exp(x * u.Unit('1 / TeV'))
def afrho2fluxd(wave, afrho, rap, geom, sun=None, unit=u.Unit('W/(m2 um)'), bandpass=None): """Convert A(th)frho to flux density. See A'Hearn et al. (1984) for the definition of Afrho. Parameters ---------- wave : Quantity The wavelength of the measurement. afrho : Quantity The Afrho parameter. rap : Quanitity The aperture radius. May be angular size or projected linear size at the distance of the comet. geom : dictionary of Quantities or ephem.Geom The observing geometry via keywords `rh`, `delta`. sun : Quantity, optional Use this value for the solar flux density at 1 AU, or `None` to use `calib.solar_flux`. unit : Unit, optional Unit to pass to `calib.solar_flux`. bandpass : dict, optional Instead of using `sun`, set to a dictionary of keywords to pass, along with the solar spectrum, to `util.bandpass`. Returns ------- fluxd : Quantity The flux density of the comet. Notes ----- Farnham, Schleicher, and A'Hearn (2000), Hale-Bopp filter set: UC = 0.3449 * u.um, qUC = 2.716e17 -> 908.9 * u.Unit('W/m2/um') BC = 0.4453 * u.um, qBC = 1.276e17 -> 1934 * u.Unit('W/m2/um') GC = 0.5259 * u.um, qGC = 1.341e17 -> 1841 * u.Unit('W/m2/um') RC = 0.7133 * u.um, qRC = 1.975e17 -> 1250 * u.Unit('W/m2/um') """ from . import util from . import calib # parameter check assert wave.unit.is_equivalent(u.um) assert afrho.unit.is_equivalent(u.um) assert geom['rh'].unit.is_equivalent(u.um) assert geom['delta'].unit.is_equivalent(u.um) if rap.unit.is_equivalent(u.cm): rho = rap.to(afrho.unit) elif rap.unit.is_equivalent(u.arcsec): rho = geom['delta'].to(afrho.unit) * rap.to(u.rad).value else: raise ValueError("rap must have angular or length units.") if sun is None: assert unit.is_equivalent('W/(m2 um)', u.spectral_density(wave)) if bandpass is None: sun = calib.solar_flux(wave, unit=unit) else: sw, sf = calib.e490(smooth=True, unit=unit) sun = util.bandpass(sw.to(u.um).value, sf.value, **bandpass)[1] sun *= unit else: assert sun.unit.is_equivalent('W/(m2 um)', u.spectral_density(wave)) fluxd = (afrho * rho * sun * (1 * u.au / geom['rh'])**2 / 4. / geom['delta']**2) return fluxd.to(unit)
def afrho2Q(Afrho, rap, geom, k, v1, u1=-0.5, u2=-1.0, Ap=0.05, rho_g=1 * u.Unit('g/cm3'), arange=[0.1, 1e4] * u.um): """Convert Afrho to dust production rate. The conversion assumes Afrho is measured within the 1/rho regime, and allows for a size-dependent expansion speed, and power-law size distributions. Q = 2 / (rho pi) \int_a0^a1 n(a) m(a) v(a) da where rho is the projected linear aperture radius at the distance of the comet, the particle radii range from a0 to a1, n(a) is the differential size distribution, m(a) is the mass of a grain with radius a, v(a) is the expansion speed of a grain with radius a. Parameters ---------- Afrho : Quantity The Afrho value (at a phase angle of 0 deg). rap : Quantity The angular or linear raidus of the projected aperture within which `Afrho` was measured. geom : dictionary of Quantity The observation geometry via keywords `rh`, `delta`. k : float The power-law slope of the differential size distribution. v1 : Quantity The expansion speed of 1 micron radius grains ejected at 1 AU from the sun. u1, u2 : float, optional Defines the relationship between expansion speed, grain radius, and heliocentric distance: v = v1 a^{u1} rh^{u2}. Ap : float, optional The geometric albedo of the dust at the same wavelength as `Afrho` is measured. rho_g : Quantity, optional The dust grain density. arange : Quanitity array, optional The minimum and maximum grain sizes in the coma. Returns ------- Q : Quantity The dust mass production rate. """ from scipy.integrate import quad from numpy import pi Afrho = u.Quantity(Afrho, u.m) rh = u.Quantity(geom['rh'], u.au) delta = u.Quantity(geom['delta'], u.au) try: rho = u.Quantity(rap, u.m) except u.UnitsError: try: rho = (u.Quantity(rap, u.arcsec) * 725e3 * u.m / u.arcsec / u.au * delta) except u.UnitsError: print 'rap must have units of length or angluar size.' raise v1 = u.Quantity(v1, u.m / u.s) rho_g = u.Quantity(rho_g, u.kg / u.m**3) arange = u.Quantity(arange, u.m) A = 4 * Ap cs = pi * quad(lambda a: a**(2 + k), *arange.value)[0] * u.m**2 N = (Afrho * pi * rho / A / cs).decompose().value q = (4 * pi / 3 * rho_g * v1 * (rh / (1 * u.au))**u2 * 1e6**u1 * quad(lambda a: a**(k + 3 + u1), *arange.value)[0] * u.m**3) Q = (N * 2 / pi / rho * q).to(u.kg / u.s) return Q
spin_2y = data['spin2y'][j] spin_2z = data['spin2z'][j] iota = data['inclination'][j] phase = data['coa_phase'][j] distance = data['distance'][j] time = float(data['geocent_end_time'][j] + \ data['geocent_end_time_ns'][j] * 1.0e-9) pol = data['polarization'][j] lon = data['longitude'][j] lat = data['latitude'][j] lambda_1 = 0.0 lambda_2 = lambdas[j] # convert longitude and latitude (in radians) to RA, DEC (in radians) t = at.Time(time, format='gps') sc = ac.SkyCoord(lon, lat, obstime=t, unit=au.Unit('rad')) ra = sc.ra.rad dec = sc.dec.rad # convert LALInference spin parameters into form desired by # waveform generators converted = inverse_transform_precessing_spins(iota, spin_1x, spin_1y, \ spin_1z, spin_2x, spin_2y, \ spin_2z, mass_1, mass_2, \ reference_frequency, phase) theta_jn, phi_jl, tilt_1, tilt_2, phi_12, a_1, a_2 = converted # We are going to inject a binary neutron star waveform. We first establish a # dictionary of parameters that includes all of the different waveform # parameters, including masses of the black hole (mass_1) and NS (mass_2), # spins of both objects (a, tilt, phi), and deformabilities (lambdas,
def fluxd(self, observer, date, wave, rap=1.0 * u.arcsec, reflected=True, thermal=True, nucleus=True, coma=True, ltt=False, unit=u.Unit('W / (m2 um)'), **kwargs): """Total flux density as seen by an observer. Parameters ---------- observer : SolarSysObject The observer. date : string, float, astropy Time, datetime The time of the observation in any format acceptable to `observer`. wave : Quantity The wavelengths to compute `fluxd`. rap : Quantity, optional The aperture radius, angular or projected distance at the comet. reflected : bool, optional If `True` include the reflected light model. thermal : bool, optional If `True` include the thermal emission model. nucleus : bool, optional If `True` include the nucleus. coma : bool, optional If `True` include the coma. ltt : bool, optional Set to `True` to correct the object's position for light travel time. unit : astropy Unit The return unit, must be flux density. Returns ------- fluxd : Quantity """ fluxd = np.zeros(np.size(wave.value)) * unit if nucleus: fluxd += self.nucleus.fluxd(observer, date, wave, reflected=reflected, thermal=thermal, unit=unit) if coma: fluxd += self.coma.fluxd(observer, date, wave, rap=rap, reflected=reflected, thermal=thermal, unit=unit) return fluxd
def test_detector_units(name): # just check that such a unit exists and doesn't evaluate to False assert units.Unit(name)
from astropy import units from ..units import parse_unit __author__ = 'Duncan Macleod <*****@*****.**>' @pytest.mark.parametrize('arg, unit', [ (None, None), (units.m, units.m), ('meter', units.m), ('Volts', units.V), ('Meters/Second', units.m / units.s), ('Amp', units.ampere), ('MPC', units.megaparsec), ('degrees_C', units.Unit('Celsius')), ('DegC', units.Unit('Celsius')), ('degrees_F', units.Unit('Fahrenheit')), ]) def test_parse_unit(arg, unit): assert parse_unit(arg, parse_strict='silent') == unit def test_parse_unit_strict(): # check that errors get raise appropriately with pytest.raises(ValueError) as exc: parse_unit('metre', parse_strict='raise') # check that warnings get posted, and a custom NamedUnit gets returned with pytest.warns(units.UnitsWarning) as exc: u = parse_unit('metre', parse_strict='warn')
def __init__(self, wave, trans, wave_unit=u.AA, trans_unit=u.dimensionless_unscaled, normalize=False, name=None, trim_level=None): wave = np.asarray(wave, dtype=np.float64) trans = np.asarray(trans, dtype=np.float64) if wave.shape != trans.shape: raise ValueError('shape of wave and trans must match') if wave.ndim != 1: raise ValueError('only 1-d arrays supported') # Ensure that units are actually units and not quantities, so that # `to` method returns a float and not a Quantity. wave_unit = u.Unit(wave_unit) trans_unit = u.Unit(trans_unit) if wave_unit != u.AA: wave = wave_unit.to(u.AA, wave, u.spectral()) # If transmission is in units of inverse energy, convert to # unitless transmission: # # (transmitted photons / incident photons) = # (photon energy) * (transmitted photons / incident energy) # # where photon energy = h * c / lambda if trans_unit != u.dimensionless_unscaled: trans = (HC_ERG_AA / wave) * trans_unit.to(u.erg**-1, trans) # Check that values are monotonically increasing. # We could sort them, but if this happens, it is more likely a user # error or faulty bandpass definition. So we leave it to the user to # sort them. if not np.all(np.ediff1d(wave) > 0.): raise ValueError('bandpass wavelength values must be monotonically' ' increasing when supplied in wavelength or ' 'decreasing when supplied in energy/frequency.') if normalize: trans /= np.max(trans) # Trim "out-of-band" transmission if trim_level is not None: s = slice_exclude_below(trans, np.max(trans) * trim_level, grow=1) wave = wave[s] trans = trans[s] # if more than one leading or trailing transmissions are zero, we # can remove them. if ((trans[0] == 0.0 and trans[1] == 0.0) or (trans[-1] == 0.0 and trans[-2] == 0.0)): i = 0 while i < len(trans) and trans[i] == 0.0: i += 1 if i == len(trans): raise ValueError('all zero transmission') j = len(trans) - 1 while j >= 0 and trans[j] == 0.0: j -= 1 # back out to include a single zero if i > 0: i -= 1 if j < len(trans) - 1: j += 1 wave = wave[i:j+1] trans = trans[i:j+1] self.wave = wave self.trans = trans # Set up interpolation. # This appears to be the fastest-evaluating interpolant in # scipy.interpolate. self._tck = splrep(self.wave, self.trans, k=1) self.name = name
# ---------------------------- astropy.units # http://docs.astropy.org/en/stable/units/ import astropy.units as u # defining a quantity: a value with a unit print(1 * u.m) print(type(1 * u.m)) # or... print(1 * u.Unit('m')) print(type(1 * u.Unit('m'))) # units can be used as you would expect: # you can form multiplicative units (in this case a velocity) a = 1 * u.m / u.s print(a) # # but you cannot add quantities with different units # print(1*u.m + 2*u.s) # units propagate properly through most astropy function and the basic # numpy functions import numpy as np b = 2 * u.m * u.m print(b**2) print(np.sqrt(b)) # in case the function cannot deal with units, you can strip the quantity print(a.unit)
# Licensed under a 3-clause BSD style license - see LICENSE.rst from __future__ import absolute_import, division, print_function, unicode_literals from collections import OrderedDict from numpy.testing import assert_allclose import pytest from astropy import units as u from ...utils.testing import requires_data, requires_dependency from ...utils.testing import assert_quantity_allclose from ..gammacat import SourceCatalogGammaCat from ..gammacat import GammaCatResource, GammaCatResourceIndex SOURCES = [ { 'name': 'Vela X', 'spec_type': 'ecpl', 'dnde_1TeV': 1.36e-11 * u.Unit('cm-2 s-1 TeV-1'), 'dnde_1TeV_err': 7.531e-13 * u.Unit('cm-2 s-1 TeV-1'), 'flux_1TeV': 2.104e-11 * u.Unit('cm-2 s-1'), 'flux_1TeV_err': 1.973e-12 * u.Unit('cm-2 s-1'), 'eflux_1_10TeV': 9.265778680255336e-11 * u.Unit('erg cm-2 s-1'), 'eflux_1_10TeV_err': 9.590978299538194e-12 * u.Unit('erg cm-2 s-1'), 'n_flux_points': 24, 'is_pointlike': False, 'spatial_model': 'SkyGaussian', }, { 'name': 'HESS J1848-018', 'spec_type': 'pl', 'dnde_1TeV': 3.7e-12 * u.Unit('cm-2 s-1 TeV-1'), 'dnde_1TeV_err': 4e-13 * u.Unit('cm-2 s-1 TeV-1'), 'flux_1TeV': 2.056e-12 * u.Unit('cm-2 s-1'),
def plot_spectra(sampler, mle_result, fit_range=[0.03, 30] * u.TeV, min_sample=50): joint_model = Log10Parabola( amplitude=3.78 * 1e-11 * u.Unit('cm-2 s-1 TeV-1'), reference=1 * u.Unit('TeV'), alpha=2.49 * u.Unit(''), beta=0.22 * u.Unit(''), ) joint_model.plot(energy_range=fit_range, energy_power=2, color='black', label='joint') r = np.median(sampler.chain[:, min_sample:, :3], axis=(0, 1)) fitted_model = Log10Parabola( amplitude=r[0] * 1e-11 * u.Unit('cm-2 s-1 TeV-1'), reference=1 * u.Unit('TeV'), alpha=r[1] * u.Unit(''), beta=r[2] * u.Unit(''), ) fitted_model.plot(energy_range=fit_range, energy_power=2, color='crimson', label='mcmc') mle_model = Log10Parabola( amplitude=mle_result.x[0] * 1e-11 * u.Unit('cm-2 s-1 TeV-1'), reference=1 * u.Unit('TeV'), alpha=mle_result.x[1] * u.Unit(''), beta=mle_result.x[2] * u.Unit(''), ) mle_model.plot(energy_range=fit_range, energy_power=2, color='orange', ls='--', label='mle') fact_model = Log10Parabola( amplitude=3.47 * 1e-11 * u.Unit('cm-2 s-1 TeV-1'), reference=1 * u.Unit('TeV'), alpha=2.56 * u.Unit(''), beta=0.4 * u.Unit(''), ) fact_model.plot(energy_range=fit_range, energy_power=2, color='gray', label='fact') magic_model = Log10Parabola( amplitude=4.20 * 1e-11 * u.Unit('cm-2 s-1 TeV-1'), reference=1 * u.Unit('TeV'), alpha=2.58 * u.Unit(''), beta=0.43 * u.Unit(''), ) magic_model.plot(energy_range=fit_range, energy_power=2, color='gray', ls='--', label='magic') CrabSpectrum(reference='meyer').model.plot(energy_range=[0.01, 100] * u.TeV, energy_power=2, color='black', ls=':')
def get_model(self, identifier, unit=None, ext="fits"): '''Get a specific model by its identifier :param identifier: a :class:`~pdrtpy.measurement.Measurement` ID. It can be an intensity or a ratio, #,habing_unit,draine_unit,mathis_unit e.g., "CII_158","CI_609/FIR" :type identifier: str :returns: The model matching the identifier :rtype: :class:`~pdrtpy.measurement.Measurement` :raises: KeyError if identifier not found in this ModelSet ''' if identifier not in self.table["ratio"]: raise KeyError(f"{identifier} is not in this ModelSet") d = model_dir() _thefile = d + self._tabrow["path"] + self.table.loc[identifier][ "filename"] + "." + ext _title = self._table.loc[identifier]['title'] if unit is None: # make a guess at the unit if '/' in identifier: unit = self._default_unit["ratio"] modeltype = "ratio" else: unit = self._default_unit['intensity'] modeltype = "intensity" else: if unit == u.dimensionless_unscaled: modeltype = "ratio" else: modeltype = "intensity" _model = Measurement.read(_thefile, title=_title, unit=unit, identifier=identifier) _wcs = _model.wcs _model.header["MODELTYP"] = modeltype _model.modeltype = modeltype #@todo this is messy. clean up by doing if wcs.. first? if self.is_wk2006 or self.name == "smc": # fix WK2006 model headerslisthd if _wcs.wcs.cunit[0] == "": _model.header["CUNIT1"] = "cm^-3" _wcs.wcs.cunit[0] = u.Unit("cm^-3") else: _model.header["CUNIT1"] = str(_wcs.wcs.cunit[0]) if _wcs.wcs.cunit[1] == "": _model.header["CUNIT2"] = "Habing" # Raises UnitScaleError: # "The FITS unit format is not able to represent scales that are not powers of 10. Multiply your data by 1.600000e-03." # This causes all sorts of downstream problems. Workaround in LineRatioFit.read_models(). #_model.wcs.wcs.cunit[1] = habing_unit elif self.code == "KOSMA-tau": # fix KosmaTau model headers if _wcs.wcs.cunit[0] == "": _model.header["CUNIT1"] = "cm^-3" _wcs.wcs.cunit[0] = u.Unit("cm^-3") else: _model.header["CUNIT1"] = str(_wcs.wcs.cunit[0]) if _wcs.wcs.cunit[1] == "": _model.header["CUNIT2"] = "Draine" else: _model.header["CUNIT2"] = str(_wcs.wcs.cunit[1]) else: # copy wcs cunit to header. used later. _model.header["CUNIT1"] = str(_wcs.wcs.cunit[0]) _model.header["CUNIT2"] = str(_wcs.wcs.cunit[1]) return _model
def calculate_flux(trace, percentiles=[16, 50, 84]): norm = 1 * u.Unit('km-2 s-1 TeV-1') flux = (trace['expected_counts'][:, :] * norm).to_value( 1 / (u.TeV * u.s * u.cm**2)) return np.percentile(flux, q=percentiles, axis=0)
def vue_fit_model_to_cube(self, *args, **kwargs): data = self.app.data_collection[self._selected_data_label] # First, ensure that the selected data is cube-like. It is possible # that the user has selected a pre-existing 1d data object. if data.ndim != 3: snackbar_message = SnackbarMessage( f"Selected data {self._selected_data_label} is not cube-like", color='error', sender=self) self.hub.broadcast(snackbar_message) return # Get the primary data component attribute = data.main_components[0] component = data.get_component(attribute) temp_values = data.get_data(attribute) # Transpose the axis order values = np.moveaxis(temp_values, 0, -1) * u.Unit(component.units) # We manually create a Spectrum1D object from the flux information # in the cube we select wcs = data.coords.sub([WCSSUB_SPECTRAL]) spec = Spectrum1D(flux=values, wcs=wcs) # TODO: in vuetify >2.3, timeout should be set to -1 to keep open # indefinitely snackbar_message = SnackbarMessage( "Fitting model to cube...", loading=True, timeout=0, sender=self) self.hub.broadcast(snackbar_message) fitted_model, fitted_spectrum = fit_model_to_spectrum( spec, self._initialized_models.values(), self.model_equation, run_fitter=True) # Transpose the axis order back values = np.moveaxis(fitted_spectrum.flux.value, -1, 0) count = max(map(lambda s: int(next(iter(re.findall("\d$", s)), 0)), self.data_collection.labels)) + 1 label = f"{self.model_label} [Cube] {count}" # Create new glue data object output_cube = Data(label=label, coords=data.coords) output_cube['flux'] = values output_cube.get_component('flux').units = \ fitted_spectrum.flux.unit.to_string() # Add to data collection self.app.data_collection.append(output_cube) snackbar_message = SnackbarMessage( "Finished cube fitting", color='success', loading=False, sender=self) self.hub.broadcast(snackbar_message)
def integral(self, xmin, xmax): return np.exp(xmax * u.Unit('1 / TeV')) - np.exp( xmin * u.Unit('1 / TeV'))
def table_model(): energy = MapAxis.from_energy_bounds(0.1 * u.TeV, 100 * u.TeV, 1000).center model = PowerLawSpectralModel( index=2.3, amplitude="4 cm-2 s-1 TeV-1", reference="1 TeV" ) dnde = model(energy) return TemplateSpectralModel(energy, dnde, 1) TEST_MODELS = [ dict( name="powerlaw", model=PowerLawSpectralModel( index=2.3 * u.Unit(""), amplitude=4 / u.cm ** 2 / u.s / u.TeV, reference=1 * u.TeV, ), val_at_2TeV=u.Quantity(4 * 2.0 ** (-2.3), "cm-2 s-1 TeV-1"), integral_1_10TeV=u.Quantity(2.9227116204223784, "cm-2 s-1"), eflux_1_10TeV=u.Quantity(6.650836884969039, "TeV cm-2 s-1"), ), dict( name="powerlaw", model=PowerLawSpectralModel( index=2 * u.Unit(""), amplitude=4 / u.cm ** 2 / u.s / u.TeV, reference=1 * u.TeV, ), val_at_2TeV=u.Quantity(1.0, "cm-2 s-1 TeV-1"),
from math import * from astropy import constants as cts from astropy import units as u from astropy.constants import G, M_earth, R_earth mu = G.value*M_earth.value Re = R_earth.value rad_earth= 6378.13 # Radius r_test = np.array([Re + 600.0*1000, 0, 50]) v_test = np.array([0, 6.5 * 1000, 0]) t = 0 M_fact= 7.292115E-5 mu_Sun = cts.GM_sun.to(u.Unit('au3 / day2')).value F= 1 / 298.257223563 # WGS-84 mu_Earth = cts.GM_earth.to(u.Unit('km3 / s2')).value def julian_day_from_utc(utc_time): """Returns julian day. """ return days_since_2000(utc_time) + 2451545 def cartesian_to_spherical(data): ''' Takes as an input a data set containing points in cartesian format (time, x, y, z) and returns the computed
def test_ecpl_integrate(): # regression test to check the numerical integration for small energy bins ecpl = ExpCutoffPowerLawSpectralModel() value = ecpl.integral(1 * u.TeV, 1.1 * u.TeV) assert_quantity_allclose(value, 8.380761e-14 * u.Unit("s-1 cm-2"))
energy = energy_edges.log_centers index = 2.3 * u.Unit("") amplitude = 4 / u.cm ** 2 / u.s / u.TeV reference = 1 * u.TeV pl = PowerLaw(index, amplitude, reference) flux = pl(energy) return TableModel(energy, flux, 1 * u.Unit("")) TEST_MODELS = [ dict( name="powerlaw", model=PowerLaw( index=2.3 * u.Unit(""), amplitude=4 / u.cm ** 2 / u.s / u.TeV, reference=1 * u.TeV, ), val_at_2TeV=u.Quantity(4 * 2.0 ** (-2.3), "cm-2 s-1 TeV-1"), integral_1_10TeV=u.Quantity(2.9227116204223784, "cm-2 s-1"), eflux_1_10TeV=u.Quantity(6.650836884969039, "TeV cm-2 s-1"), ), dict( name="powerlaw", model=PowerLaw( index=2 * u.Unit(""), amplitude=4 / u.cm ** 2 / u.s / u.TeV, reference=1 * u.TeV, ), val_at_2TeV=u.Quantity(1.0, "cm-2 s-1 TeV-1"),
def evaluate(x): return np.exp(x * u.Unit("1 / TeV"))
def from_columns(cls, columns, names, units=None, meta={}, **kwargs): """Create `~sbpy.data.DataClass` object from a sequence. If that sequence is one-dimensional, it is interpreted as a single column; if the sequence is two-dimensional, it is interpreted as a sequence of columns. Parameters ---------- columns: list, `~numpy.ndarray`, tuple, or `~astropy.units.Quantity` Data that will be ingested in `DataClass` object. A one-dimensional sequence is interpreted as a single column. A two-dimensional sequence is interpreted as a sequence of columns, each of which must have the same length. names: str or list-like Field names, must have the same number of names as data columns. Please note that in order to make use of :ref:`fieldnames` and to ensure compatibility with sbpy functionality, the field names chosen must be in the list of :ref:`field name list`. units: str or list-like, optional Unit labels (as provided by `~astropy.units.Unit`) in which the data provided in ``columns`` will be stored in the underlying table. If None, the units as provided by ``columns`` are used. If the units provided in ``units`` differ from those used in ``columns``, ``columns`` will be transformed to the units provided in ``units``. Must have the same length as ``names`` and the individual data columns in ``columns``. Default: None meta: dictionary, optional Meta data that will be stored in the data table. Default: empty dictionary kwargs: additional keyword arguments, optional Additional keyword arguments that will be passed on to `~astropy.table.QTable` in the creation of the underlying data table. Returns ------- `DataClass` object Examples -------- The following example creates a single-column `~sbpy.data.Ephem` object. >>> from sbpy.data import Ephem >>> import astropy.units as u >>> eph = Ephem.from_columns([1, 2, 3, 4]*u.au, ... names='a') >>> eph <QTable length=4> a AU float64 ------- 1.0 2.0 3.0 4.0 This example creates a two-column `~sbpy.data.Ephem` object in which units are assigned using the optional ``units`` keyword argument. >>> eph = Ephem.from_columns([[1, 2, 3, 4], ... [90, 50, 30, 10]], ... names=['r', 'alpha'], ... units=['au', 'deg']) >>> eph <QTable length=4> r alpha AU deg float64 float64 ------- ------- 1.0 90.0 2.0 50.0 3.0 30.0 4.0 10.0 If units are provided in ``columns`` and ``units``, those units in ``columns`` will be transformed into those units in ``units`` on a per-column basis. >>> eph = Ephem.from_columns([[1, 2, 3, 4]*u.au, ... [90, 50, 30, 10]*u.deg], ... names=['r', 'alpha'], ... units=['km', 'rad']) >>> eph <QTable length=4> r alpha km rad float64 float64 ------------------ ------------------- 149597870.7 1.5707963267948966 299195741.4 0.8726646259971648 448793612.09999996 0.5235987755982988 598391482.8 0.17453292519943295 """ # turn single column name to a list if isinstance(names, str): names = [names] # turn single column to a list if not iterable(columns[0]): columns = [columns] elif isinstance(columns[0], (str, bytes)): columns = [columns] if units is not None: if all([isinstance(col, u.Quantity) for col in columns]): # if all columns have units, transform to `units` columns = [ val.to(unit) for val, unit in list(zip(columns, units)) ] else: # if columns has no units, apply `units` columns = [ val * u.Unit(unit) if unit is not None else val for val, unit in list(zip(columns, units)) ] self = cls() self._table = QTable(columns, names=names, meta=meta, **kwargs) return self
def integral(self, xmin, xmax, **kwargs): return np.exp(xmax * u.Unit("1 / TeV")) - np.exp( xmin * u.Unit("1 / TeV"))
def test_velocities(self): assert self.model.v_inner.unit == u.Unit('cm/s') assert_almost_equal(self.model.v_inner[0].to(u.km / u.s).value, 9000)
def read_table_fits(input, hdu=None, astropy_native=False, memmap=False, character_as_bytes=True): """ Read a Table object from an FITS file If the ``astropy_native`` argument is ``True``, then input FITS columns which are representations of an astropy core object will be converted to that class and stored in the ``Table`` as "mixin columns". Currently this is limited to FITS columns which adhere to the FITS Time standard, in which case they will be converted to a `~astropy.time.Time` column in the output table. Parameters ---------- input : str or file-like object or compatible `astropy.io.fits` HDU object If a string, the filename to read the table from. If a file object, or a compatible HDU object, the object to extract the table from. The following `astropy.io.fits` HDU objects can be used as input: - :class:`~astropy.io.fits.hdu.table.TableHDU` - :class:`~astropy.io.fits.hdu.table.BinTableHDU` - :class:`~astropy.io.fits.hdu.table.GroupsHDU` - :class:`~astropy.io.fits.hdu.hdulist.HDUList` hdu : int or str, optional The HDU to read the table from. astropy_native : bool, optional Read in FITS columns as native astropy objects where possible instead of standard Table Column objects. Default is False. memmap : bool, optional Whether to use memory mapping, which accesses data on disk as needed. If you are only accessing part of the data, this is often more efficient. If you want to access all the values in the table, and you are able to fit the table in memory, you may be better off leaving memory mapping off. However, if your table would not fit in memory, you should set this to `True`. character_as_bytes : bool, optional If `True`, string columns are stored as Numpy byte arrays (dtype ``S``) and are converted on-the-fly to unicode strings when accessing individual elements. If you need to use Numpy unicode arrays (dtype ``U``) internally, you should set this to `False`, but note that this will use more memory. If set to `False`, string columns will not be memory-mapped even if ``memmap`` is `True`. """ if isinstance(input, HDUList): # Parse all table objects tables = dict() for ihdu, hdu_item in enumerate(input): if isinstance(hdu_item, (TableHDU, BinTableHDU, GroupsHDU)): tables[ihdu] = hdu_item if len(tables) > 1: if hdu is None: warnings.warn("hdu= was not specified but multiple tables" " are present, reading in first available" f" table (hdu={first(tables)})", AstropyUserWarning) hdu = first(tables) # hdu might not be an integer, so we first need to convert it # to the correct HDU index hdu = input.index_of(hdu) if hdu in tables: table = tables[hdu] else: raise ValueError(f"No table found in hdu={hdu}") elif len(tables) == 1: if hdu is not None: msg = None try: hdi = input.index_of(hdu) except KeyError: msg = f"Specified hdu={hdu} not found" else: if hdi >= len(input): msg = f"Specified hdu={hdu} not found" elif hdi not in tables: msg = f"No table found in specified hdu={hdu}" if msg is not None: warnings.warn(f"{msg}, reading in first available table " f"(hdu={first(tables)}) instead. This will" " result in an error in future versions!", AstropyDeprecationWarning) table = tables[first(tables)] else: raise ValueError("No table found") elif isinstance(input, (TableHDU, BinTableHDU, GroupsHDU)): table = input else: hdulist = fits_open(input, character_as_bytes=character_as_bytes, memmap=memmap) try: return read_table_fits(hdulist, hdu=hdu, astropy_native=astropy_native) finally: hdulist.close() # Check if table is masked masked = any(col.null is not None for col in table.columns) # TODO: in future, it may make more sense to do this column-by-column, # rather than via the structured array. # In the loop below we access the data using data[col.name] rather than # col.array to make sure that the data is scaled correctly if needed. data = table.data columns = [] for col in data.columns: # Set column data if masked: column = MaskedColumn(data=data[col.name], name=col.name, copy=False) if col.null is not None: column.set_fill_value(col.null) column.mask[column.data == col.null] = True else: column = Column(data=data[col.name], name=col.name, copy=False) # Copy over units if col.unit is not None: column.unit = u.Unit(col.unit, format='fits', parse_strict='silent') # Copy over display format if col.disp is not None: column.format = _fortran_to_python_format(col.disp) columns.append(column) # Create Table object t = Table(columns, masked=masked, copy=False) # TODO: deal properly with unsigned integers hdr = table.header if astropy_native: # Avoid circular imports, and also only import if necessary. from .fitstime import fits_to_time hdr = fits_to_time(hdr, t) for key, value, comment in hdr.cards: if key in ['COMMENT', 'HISTORY']: # Convert to io.ascii format if key == 'COMMENT': key = 'comments' if key in t.meta: t.meta[key].append(value) else: t.meta[key] = [value] elif key in t.meta: # key is duplicate if isinstance(t.meta[key], list): t.meta[key].append(value) else: t.meta[key] = [t.meta[key], value] elif is_column_keyword(key) or key in REMOVE_KEYWORDS: pass else: t.meta[key] = value # TODO: implement masking # Decode any mixin columns that have been stored as standard Columns. t = _decode_mixins(t) return t