def _observe_through_filter(bp, B, unit): if not synphot: raise AstropyWarning('synphot is required for bandpass filtering.') obs = Observation(B, bp) wave = obs.effective_wavelength() fluxd = obs.effstim(unit) return wave, fluxd
def __init__(self, *args, **kwargs): from warnings import warn from astropy.utils.exceptions import AstropyWarning warn( AstropyWarning('The AltAz class currently does not support any ' 'transformations. In a future version, it will ' 'support the standard IAU2000 AltAz<->ICRS ' 'transformations.')) super(AltAz, self).__init__(*args, **kwargs)
def _planck(Tscale, T, eph): """Planck function and temperature for dust thermal emission.""" if not synphot: raise AstropyWarning( 'synphot is required for blackbody calculations') if T is None: T = Tscale * 278 / np.sqrt(eph['rh'] / u.au) * u.K # Does not include the factor of pi: return SourceSpectrum(BlackBody1D, temperature=T)
def open(cls): """If the configuration setting ``astropy.utils.iers.conf.auto_download`` is set to True (default), then open a recent version of the IERS-A table with predictions for UT1-UTC and polar motion out to approximately one year from now. If the available version of this file is older than ``astropy.utils.iers.conf.auto_max_age`` days old (or non-existent) then it will be downloaded over the network and cached. If the configuration setting ``astropy.utils.iers.conf.auto_download`` is set to False then ``astropy.utils.iers.IERS()`` is returned. This is normally the IERS-B table that is supplied with astropy. On the first call in a session, the table will be memoized (in the ``iers_table`` class attribute), and further calls to ``open`` will return this stored table. Returns ------- `~astropy.table.QTable` instance With IERS (Earth rotation) data columns """ if not conf.auto_download: cls.iers_table = IERS_B.open() return cls.iers_table all_urls = (conf.iers_auto_url, conf.iers_auto_url_mirror) if cls.iers_table is not None: # If the URL has changed, we need to redownload the file, so we # should ignore the internally cached version. if cls.iers_table.meta.get('data_url') in all_urls: return cls.iers_table try: filename = download_file(all_urls[0], sources=all_urls, cache=True) except Exception as err: # Issue a warning here, perhaps user is offline. An exception # will be raised downstream when actually trying to interpolate # predictive values. warn(AstropyWarning( f'failed to download {" and ".join(all_urls)}, ' f'using local IERS-B: {err}')) cls.iers_table = IERS_B.open() return cls.iers_table cls.iers_table = cls.read(file=filename) cls.iers_table.meta['data_url'] = all_urls[0] return cls.iers_table
def _integrate_volume_density(self, rho, epsabs=1.49e-8): """Integrate volume density along the line of sight. Parameters ---------- rho : `~astropy.units.Quantity` Projected distance of the region of interest on the plane of the sky in units of length. epsabs : float, int, optional Absolute and relative error tolerance for integrals. See `scipy.integrate.quad`. Returns ------- sigma : float Coma column density along the line of sight at a distance rho. """ if not scipy: raise AstropyWarning( 'scipy is required for integrating volume density.') if not rho.unit.is_equivalent(u.m): raise ValueError('rho must have units of length.') def f(s): r = np.sqrt(rho.to(u.km).value**2 + s**2) n = self.volume_density(r * u.km) * u.km return n.decompose().value # Using an upper limit of integration than 1e9 m makes the # integral divergent # sigma, err = quad(f, 0, np.inf, epsabs=epsabs) sigma, err = quad(f, 0, np.max((1.e6, 10 * rho.to(u.km).value)), epsabs=epsabs) # spherically symmetric coma sigma *= 2 return sigma
def test_import_error_in_warning_logging(): """ Regression test for https://github.com/astropy/astropy/issues/2671 This test actually puts a goofy fake module into ``sys.modules`` to test this problem. """ class FakeModule: def __getattr__(self, attr): raise ImportError('_showwarning should ignore any exceptions ' 'here') log.enable_warnings_logging() sys.modules['<test fake module>'] = FakeModule() try: warnings.showwarning(AstropyWarning('Regression test for #2671'), AstropyWarning, '<this is only a test>', 1) finally: del sys.modules['<test fake module>']
def _refresh_table_as_needed(self, mjd): """Potentially update the IERS table in place depending on the requested time values in ``mjd`` and the time span of the table. For IERS_Auto the behavior is that the table is refreshed from the IERS server if both the following apply: - Any of the requested IERS values are predictive. The IERS-A table contains predictive data out for a year after the available definitive values. - The first predictive values are at least ``conf.auto_max_age days`` old. In other words the IERS-A table was created by IERS long enough ago that it can be considered stale for predictions. """ max_input_mjd = np.max(mjd) now_mjd = self.time_now.mjd # IERS-A table contains predictive data out for a year after # the available definitive values. fpi = self.meta['predictive_index'] predictive_mjd = self.meta['predictive_mjd'] # Update table in place if necessary auto_max_age = _none_to_float(conf.auto_max_age) # If auto_max_age is smaller than IERS update time then repeated downloads may # occur without getting updated values (giving a IERSStaleWarning). if auto_max_age < 10: raise ValueError('IERS auto_max_age configuration value must be larger than 10 days') if (max_input_mjd > predictive_mjd and (now_mjd - predictive_mjd) > auto_max_age): all_urls = (conf.iers_auto_url, conf.iers_auto_url_mirror) # Get the latest version try: filename = download_file( all_urls[0], sources=all_urls, cache="update") except Exception as err: # Issue a warning here, perhaps user is offline. An exception # will be raised downstream when actually trying to interpolate # predictive values. warn(AstropyWarning( f'failed to download {" and ".join(all_urls)}: {err}.\n' 'A coordinate or time-related ' 'calculation might be compromised or fail because the dates are ' 'not covered by the available IERS file. See the ' '"IERS data access" section of the astropy documentation ' 'for additional information on working offline.')) return new_table = self.__class__.read(file=filename) new_table.meta['data_url'] = str(all_urls[0]) # New table has new values? if new_table['MJD'][-1] > self['MJD'][-1]: # Replace *replace* current values from the first predictive index through # the end of the current table. This replacement is much faster than just # deleting all rows and then using add_row for the whole duration. new_fpi = np.searchsorted(new_table['MJD'].value, predictive_mjd, side='right') n_replace = len(self) - fpi self[fpi:] = new_table[new_fpi:new_fpi + n_replace] # Sanity check for continuity if new_table['MJD'][new_fpi + n_replace] - self['MJD'][-1] != 1.0 * u.d: raise ValueError('unexpected gap in MJD when refreshing IERS table') # Now add new rows in place for row in new_table[new_fpi + n_replace:]: self.add_row(row) self.meta.update(new_table.meta) else: warn(IERSStaleWarning( 'IERS_Auto predictive values are older than {} days but downloading ' 'the latest table did not find newer values'.format(conf.auto_max_age)))
def _K1(self, x): """Modified Bessel function of 2nd kind, 1st order.""" if not scipy: raise AstropyWarning('scipy is not present, cannot continue.') return special.k1(x.decompose().value)
def _iK0(self, x): """Integral of the modified Bessel function of 2nd kind, 0th order.""" if not scipy: raise AstropyWarning('scipy is not present, cannot continue.') return special.iti0k0(x.decompose().value)[1]
def _integrate_column_density(self, aper, epsabs=1.49e-8): """Integrate column density over an aperture. Parameters ---------- aper : `~sbpy.activity.Aperture` Aperture, in units of length. epsabs : float, int, optional Absolute and relative error tolerance for integrals. See `~scipy.integrate.quad` (circular, annular, Gaussian) and `~scipy.integrate.dblquad` (rectangular) for details. """ if not scipy: raise AstropyWarning( 'scipy is required for integrating column density') if not aper.dim.unit.is_equivalent(u.m): raise ValueError('aper must have units of length') if isinstance(aper, CircularAperture): # integrate in polar coordinates def f(rho): x = rho * self.column_density(rho * u.km) * u.km**2 return x.decompose().value N, err = quad(f, 0, aper.radius.to(u.km).value, epsabs=epsabs) N *= 2 * np.pi elif isinstance(aper, AnnularAperture): # integrate in polar coordinates def f(rho): x = rho * self.column_density(rho * u.km) * u.km**2 return x.decompose().value N, err = quad(f, aper.shape[0].to(u.km).value, aper.shape[1].to(u.km).value, epsabs=epsabs) N *= 2 * np.pi elif isinstance(aper, RectangularAperture): # integrate in polar coordinates def f(rho, th): x = rho * self.column_density(rho * u.km) * u.km**2 return x.decompose().value shape = aper.shape.to(u.km).value # first "octant"; g and h are the limits of the # integration of rho def g(th): return 0 def h(th): return shape[0] / 2 / np.cos(th) th = np.arctan(shape[1] / shape[0]) N1, err1 = dblquad(f, 0, th, g, h, epsabs=epsabs) # second "octant" def g(th): return 0 def h(th): return shape[1] / 2 / np.cos(th) th = np.arctan(shape[0] / shape[1]) N2, err2 = dblquad(f, 0, th, g, h, epsabs=epsabs) # N1 + N2 constitute 1/4th of the rectangle N = 4 * (N1 + N2) elif isinstance(aper, GaussianAperture): # integrate in polar coordinates def f(rho): return (rho * aper(rho * u.km).value * self.column_density(rho * u.km).to(u.km**-2).value) N, err = quad(f, 0, np.inf, epsabs=epsabs) N *= 2 * np.pi return N
def spectral_density_vega(wfb): """Flux density equivalencies with Vega-based magnitude systems. Requires `~synphot`. Uses the default `sbpy` Vega spectrum. Vega is assumed to have an apparent magnitude of 0 in the ``VEGAmag`` system, and 0.03 in the Johnson-Morgan, ``JMmag``, system [Joh66, BM12]_. Parameters ---------- wfb : `~astropy.units.Quantity`, `~synphot.SpectralElement`, string Wavelength, frequency, or a bandpass of the corresponding flux density being converted. See :func:`~synphot.SpectralElement.from_filter()` for possible bandpass names. Returns ------- eqv : list List of equivalencies. Examples -------- >>> import astropy.units as u >>> from sbpy.units import spectral_density_vega, VEGAmag >>> m = 0 * VEGAmag >>> fluxd = m.to(u.Jy, spectral_density_vega(5500 * u.AA)) >>> fluxd.value # doctest: +FLOAT_CMP 3578.9571538333985 References ---------- [Joh66] Johnson et al. 1966, Commun. Lunar Planet. Lab. 4, 99 [BM12] Bessell & Murphy 2012, PASP 124, 140-157 """ # warn rather than raise an exception so that code that uses # spectral_density_vega when it doesn't need it will still run. try: import synphot except ImportError: warn( AstropyWarning('synphot required for Vega-based magnitude' ' conversions.')) return [] vega = Vega.from_default() if isinstance(wfb, u.Quantity): wav = wfb fnu0 = vega(wfb, unit='W/(m2 Hz)') flam0 = vega(wfb, unit='W/(m2 um)') elif isinstance(wfb, (synphot.SpectralElement, str)): fnu0 = vega.filt(wfb, unit='W/(m2 Hz)')[1] flam0 = vega.filt(wfb, unit='W/(m2 um)')[1] return [(fnu0.unit, VEGA, lambda x: x / fnu0.value, lambda x: x * fnu0.value), (flam0.unit, VEGA, lambda x: x / flam0.value, lambda x: x * flam0.value)]
def phase_HalleyMarcus(phase): """Halley-Marcus composite dust phase function. Uses `~scipy.interpolate` for spline interpolation, otherwise uses linear interpolation from `~numpy.interp`. Parameters ---------- phase : `~astropy.units.Quantity`, `~astropy.coordinate.Angle` Phase angle. Returns ------- Phi : float, `~np.ndarray` Notes ----- The Halley-Marcus phase function was first used by Schleicher and Bair (2011), but only described in detail by Schleicher and Marcus (May 2010) online at: http://asteroid.lowell.edu/comet/dustphase.html "To distinguish this curve from others, we designate this as the HM phase function, for the sources of the two components: Halley and Marcus, where the Halley curve for smaller phase angles comes from our previous work (Schleicher et al. 1998) while Joe Marcus has fit a Henyey-Greenstein function to a variety of mid- and large-phase angle data sets (Marcus 2007); see here for details. Note that we do not consider our composite curve to be a definitive result, but rather appropriate for performing first-order adjustments to dust measurements for changing phase angle." References ---------- Schleicher & Bair 2011, AJ 141, 177. Schleicher, Millis, & Birch 1998, Icarus 132, 397-417. Marcus 2007, International Comets Quarterly 29, 39-66. Examples -------- >>> from sbpy.activity import phase_HalleyMarcus >>> import astropy.units as u >>> phase_HalleyMarcus(0 * u.deg) # doctest: +FLOAT_CMP 1.0 >>> phase_HalleyMarcus(15 * u.deg) # doctest: +FLOAT_CMP 5.8720e-01 """ bib.register( 'activity.dust.phase_HalleyMarcus', { 'Halley phase function': '1998Icar..132..397S', 'Marcus phase function': '2007ICQ....29...39M' } ) th = np.arange(181) ph = np.array( [1.0000e+00, 9.5960e-01, 9.2170e-01, 8.8590e-01, 8.5220e-01, 8.2050e-01, 7.9060e-01, 7.6240e-01, 7.3580e-01, 7.1070e-01, 6.8710e-01, 6.6470e-01, 6.4360e-01, 6.2370e-01, 6.0490e-01, 5.8720e-01, 5.7040e-01, 5.5460e-01, 5.3960e-01, 5.2550e-01, 5.1220e-01, 4.9960e-01, 4.8770e-01, 4.7650e-01, 4.6590e-01, 4.5590e-01, 4.4650e-01, 4.3770e-01, 4.2930e-01, 4.2150e-01, 4.1420e-01, 4.0730e-01, 4.0090e-01, 3.9490e-01, 3.8930e-01, 3.8400e-01, 3.7920e-01, 3.7470e-01, 3.7060e-01, 3.6680e-01, 3.6340e-01, 3.6030e-01, 3.5750e-01, 3.5400e-01, 3.5090e-01, 3.4820e-01, 3.4580e-01, 3.4380e-01, 3.4210e-01, 3.4070e-01, 3.3970e-01, 3.3890e-01, 3.3850e-01, 3.3830e-01, 3.3850e-01, 3.3890e-01, 3.3960e-01, 3.4050e-01, 3.4180e-01, 3.4320e-01, 3.4500e-01, 3.4700e-01, 3.4930e-01, 3.5180e-01, 3.5460e-01, 3.5760e-01, 3.6090e-01, 3.6450e-01, 3.6830e-01, 3.7240e-01, 3.7680e-01, 3.8150e-01, 3.8650e-01, 3.9170e-01, 3.9730e-01, 4.0320e-01, 4.0940e-01, 4.1590e-01, 4.2280e-01, 4.3000e-01, 4.3760e-01, 4.4560e-01, 4.5400e-01, 4.6270e-01, 4.7200e-01, 4.8160e-01, 4.9180e-01, 5.0240e-01, 5.1360e-01, 5.2530e-01, 5.3750e-01, 5.5040e-01, 5.6380e-01, 5.7800e-01, 5.9280e-01, 6.0840e-01, 6.2470e-01, 6.4190e-01, 6.5990e-01, 6.7880e-01, 6.9870e-01, 7.1960e-01, 7.4160e-01, 7.6480e-01, 7.8920e-01, 8.1490e-01, 8.4200e-01, 8.7060e-01, 9.0080e-01, 9.3270e-01, 9.6640e-01, 1.0021e+00, 1.0399e+00, 1.0799e+00, 1.1223e+00, 1.1673e+00, 1.2151e+00, 1.2659e+00, 1.3200e+00, 1.3776e+00, 1.4389e+00, 1.5045e+00, 1.5744e+00, 1.6493e+00, 1.7294e+00, 1.8153e+00, 1.9075e+00, 2.0066e+00, 2.1132e+00, 2.2281e+00, 2.3521e+00, 2.4861e+00, 2.6312e+00, 2.7884e+00, 2.9592e+00, 3.1450e+00, 3.3474e+00, 3.5685e+00, 3.8104e+00, 4.0755e+00, 4.3669e+00, 4.6877e+00, 5.0418e+00, 5.4336e+00, 5.8682e+00, 6.3518e+00, 6.8912e+00, 7.4948e+00, 8.1724e+00, 8.9355e+00, 9.7981e+00, 1.0777e+01, 1.1891e+01, 1.3166e+01, 1.4631e+01, 1.6322e+01, 1.8283e+01, 2.0570e+01, 2.3252e+01, 2.6418e+01, 3.0177e+01, 3.4672e+01, 4.0086e+01, 4.6659e+01, 5.4704e+01, 6.4637e+01, 7.7015e+01, 9.2587e+01, 1.1237e+02, 1.3775e+02, 1.7060e+02, 2.1348e+02, 2.6973e+02, 3.4359e+02, 4.3989e+02, 5.6292e+02, 7.1363e+02, 8.8448e+02, 1.0533e+03, 1.1822e+03, 1.2312e+03]) _phase = np.abs(u.Quantity(phase, 'deg').value) if scipy: Phi = splev(_phase, splrep(th, ph)) else: warn(AstropyWarning( 'scipy is not present, using linear interpolation.')) Phi = np.interp(_phase, th, ph) if np.iterable(_phase): Phi = np.array(Phi).reshape(np.shape(_phase)) else: Phi = float(Phi) return Phi
# Licensed under a 3-clause BSD style license - see LICENSE.rst import os from warnings import warn from astropy.utils.exceptions import AstropyWarning try: from ginga.misc.Bunch import Bunch except ImportError: warn( AstropyWarning( 'ginga is not present: sbpy.ginga_plugins will not run.')) Bunch = None # path to these plugins p_path = os.path.split(__file__)[0] def setup_cometaryenhancements(): spec = Bunch(path=os.path.join(p_path, 'CometaryEnhancements.py'), module='CometaryEnhancements', klass='CometaryEnhancements', workspace='dialogs') return spec
With sbpy installed, this plugin should be automatically discovered by Ginga and available in the Operations menu. """ import os from warnings import warn import numpy as np from astropy.utils.exceptions import AstropyWarning try: from ginga.GingaPlugin import LocalPlugin from ginga.gw import Widgets except ImportError: warn(AstropyWarning( 'ginga is not present: CometaryEnhancements will not run.' )) class LocalPlugin: pass Widgets = None try: import photutils except ImportError: warn(AstropyWarning( 'photutils is not present: CometaryEnhancements centroiding disabled.' )) photutils = None from sbpy.imageanalysis import CometaryEnhancement