diff --git a/docs/examples/ecliptic_scan.py b/docs/examples/ecliptic_scan.py index 6b29eb4..6b621f3 100644 --- a/docs/examples/ecliptic_scan.py +++ b/docs/examples/ecliptic_scan.py @@ -2,21 +2,24 @@ import matplotlib.pyplot as plt import numpy as np from astropy.coordinates import BarycentricMeanEcliptic, SkyCoord -from astropy.time import Time +from astropy.time import Time, TimeDelta from zodipy import Model model = Model(30 * u.micron) -# Longitude and Latitude values corresponding to a scan through the eclitpic plane lats = np.linspace(-90, 90, 100) * u.deg lons = np.zeros_like(lats) +t0 = Time("2022-06-14") +dt = TimeDelta(1, format="sec") +obstimes = t0 + np.arange(lats.size) * dt + coords = SkyCoord( lons, lats, frame=BarycentricMeanEcliptic, - obstime=Time("2022-06-14"), + obstime=obstimes, ) emission = model.evaluate(coords) diff --git a/docs/img/ecliptic_scan.png b/docs/img/ecliptic_scan.png index 1ed4112..a858d06 100644 Binary files a/docs/img/ecliptic_scan.png and b/docs/img/ecliptic_scan.png differ diff --git a/docs/index.md b/docs/index.md index 01d130b..0b95177 100644 --- a/docs/index.md +++ b/docs/index.md @@ -14,7 +14,8 @@ [![DOI](https://zenodo.org/badge/394929213.svg)](https://zenodo.org/doi/10.5281/zenodo.10999611) [![DOI](https://joss.theoj.org/papers/10.21105/joss.06648/status.svg)](https://doi.org/10.21105/joss.06648) -ZodiPy is an [Astropy-affiliated](https://www.astropy.org/affiliated/) package for simulating zodiacal light in intensity for arbitrary Solar system observers. +ZodiPy is an [Astropy-affiliated](https://www.astropy.org/affiliated/) package for simulating +zodiacal light in intensity for arbitrary solar system observers. ![ZodiPy Logo](img/zodipy_map.png) ## A simple example @@ -28,18 +29,17 @@ import zodipy # Initialize a zodiacal light model at a wavelength/frequency or over a bandpass model = zodipy.Model(25*u.micron) -# Use Astropy's `SkyCoord` to specify coordinate +# Use Astropy's `SkyCoord` object to specify coordinates lon = [10, 10.1, 10.2] * u.deg lat = [90, 89, 88] * u.deg obstimes = Time(["2022-01-01 12:00:00", "2022-01-01 12:01:00", "2022-01-01 12:02:00"]) - skycoord = SkyCoord(lon, lat, obstime=obstimes, frame="galactic") -# Compute the zodiacal light as seen from Earth -emission = model.evaluate(skycoord, obspos="earth") +# Evaluate the zodiacal light model +emission = model.evaluate(skycoord) print(emission) #> [27.52410841 27.66572294 27.81251906] MJy / sr ``` -For more information on using ZodiPy, see [the usage section](usage.md). +For more information on using ZodiPy, see the [usage section](usage.md). diff --git a/docs/install.md b/docs/install.md index 7c960ec..cb02be5 100644 --- a/docs/install.md +++ b/docs/install.md @@ -10,7 +10,7 @@ pip install zodipy ## Dependencies -ZodiPy has the following dependencies: +ZodiPy has the following dependencies (these are automatically downloaded when using pip): - [Astropy](https://www.astropy.org) (>= 5.0.1) - [NumPy](https://numpy.org) diff --git a/docs/introduction.md b/docs/introduction.md index 335820d..990fd6e 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -1,8 +1,12 @@ # Introduction -ZodiPy is a Python package for zodiacal light simulations. Its purpose is to provide the astrophysics and cosmology communities with an easy-to-use and accessible interface to existing zodiacal light models in Python, assisting in astrophysical data analysis and zodiacal light forecasting for future experiments. +ZodiPy is a Python package for zodiacal light simulations. Its purpose is to provide the +astrophysics and cosmology communities with an easy-to-use and accessible interface to existing +zodiacal light models in Python, assisting in astrophysical data analysis and zodiacal light +forecasting for future experiments. -For other zodiacal light tools, see [Zodiacal Light Models on LAMBDA](https://lambda.gsfc.nasa.gov/product/foreground/fg_models.html). +For other zodiacal light tools, see +[Zodiacal Light Models on LAMBDA](https://lambda.gsfc.nasa.gov/product/foreground/fg_models.html). ## Supported zodiacal light models @@ -13,9 +17,11 @@ For other zodiacal light tools, see [Zodiacal Light Models on LAMBDA](https://la - Planck 2018 [`"planck18"`] ([Planck Collaboration et al. 2020](https://ui.adsabs.harvard.edu/abs/2020A&A...641A...3P)) - Odegard [`"odegard"`] ([Odegard et al. 2019](https://ui.adsabs.harvard.edu/abs/2019ApJ...877...40O/abstract)) -The names in the brackets are the string representations used in the `zodipy.Model` object to select the model. +The names in the brackets are the string representations used in the [`Model`][zodipy.Model] object +to select the model. -If you see a missing model or wish to add a new one, please open an issue on GitHub. Contributors are very welcome! +If you see a missing model or wish to add a new one, please feel free to open an issue on GitHub. +Contributors are very welcome! ## Related scientific papers diff --git a/docs/reference.md b/docs/reference.md index 02643d6..082baae 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -1,3 +1,3 @@ # Reference -::: zodipy.Model \ No newline at end of file +::: zodipy \ No newline at end of file diff --git a/docs/usage.md b/docs/usage.md index b0a9f65..4934f3f 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -1,19 +1,24 @@ !!! warning "Breaking API changes in `v1.0.0`" - From version `v1.0.0` the `get_emission_ang` and `get_emission_pix` methods are deprecated and removed. See the section on [HEALPix maps](usage.md#healpix-maps) for an example of how to make simulations from HEALPix pixel indices. These are changes following the integration of ZodiPy into the Astropy ecosystem. + In version `v1.0.0` the `get_emission_*` and `get_binned_emission_*` methods were deprecated + and removed. Users wanting to simulate zodiacal light directly from HEALPix pixel indices should + see the [HEALPix](usage.md#healpix) section under [examples](usage/#examples). -As an Astropy-affiliated package, ZodiPy is highly integrated with the astropy ecosystem. -To make zodiacal light simulations, the `astropy.units`, `astropy.coordinates`, and `astropy.time` modules are used to provide user input. The coordinates for which ZodiPy will simulate the zodiacal light is specified in through the `astropy.coordinates.SkyCoord` object. Using ZodiPy is very simple and the user will only interact with *one* object `zodipy.Model`, which has *one* method `evaluate`. +As an Astropy-affiliated package, ZodiPy is highly integrated with the Astropy ecosystem, +particularly with the [`astropy.units`](https://docs.astropy.org/en/stable/units/), +[`astropy.coordinates`](https://docs.astropy.org/en/stable/coordinates/index.html), and +[`astropy.time`](https://docs.astropy.org/en/stable/time/index.html) modules. -## Initializing Zodipy -### Working with the `Model` class -The interface to ZodiPy is the `zodipy.Model` class +## Initializing a zodiacal light model +To make zodiacal light simulations we must first import and initialize a zodiacal light model ```py hl_lines="2 4" import astropy.units as u import zodipy model = zodipy.Model(25 * u.micron) ``` -It has *one* required positional argument `x`, which represents a center wavelength/frequency or the points of an empirical bandpass. If `x` represents the points of a bandpass, the `weights` argument must also be provided +The [`zodipy.Model`][zodipy.Model] object has *one* required positional argument, `x`, which can +either represent a center wavelength/frequency or the points of an empirical bandpass. If `x` +represents the points of an instrument bandpass, the `weights` argument must also be provided ```py hl_lines="4 5 7" import astropy.units as u import zodipy @@ -24,22 +29,45 @@ weights = [0.2, 0.4, 0.3, 0.1] model = zodipy.Model(points, weights=weights) ``` -ZodiPy supports several zodiacal light models (see the [introduction](introduction.md) page for more information regarding the supported models), which are all valid in wavelength/frequency ranges. By default, the `Model` object will initialize using the DIRBE model. To select a different model, we specify the keyword argument `name` +ZodiPy supports [several zodiacal light models](introduction.md) valid at different +wavelength/frequency ranges. By default, a [`Model`][zodipy.Model] will initialize on the +[DIRBE model](https://ui.adsabs.harvard.edu/abs/1998ApJ...508...44K/abstract). To select another +model, for instance the [Planck 2013 model](https://ui.adsabs.harvard.edu/abs/2014A%26A...571A..14P/metrics) , +we need to specify the `name` keyword in the model constructor ```py hl_lines="4" import astropy.units as u import zodipy -model = zodipy.Model(25 * u.micron, name="planck18") +model = zodipy.Model(25 * u.micron, name="planck13") ``` -## Simulating zodiacal light -To make zodiacal light simulations ZodiPy needs to know three things: 1) Sky coordinates for which to simulate zodiacal light; 2) The position of the observer to know where the vertex of the rays is positioned; and 3) the time of observation, used to query the position of Earth. -### The SkyCoord object -The sky coordinates for which to simulate zodiacal light is given to ZodiPy using Astropy's `astropy.coordinates.SkyCoord` object. Users unfamiliar with the `SkyCoord` object should visit the [official Astropy documentation](https://docs.astropy.org/en/stable/coordinates/index.html) before using ZodiPy to learn the basics. - - -For a single observation in galactic coordinates, the `SkyCoord` object may look something like -```py hl_lines="2 5 6 7 8 9 10" +Other possible keyword arguments to the [`zodipy.Model`][zodipy.Model] are `gauss_quad_degree`, +which determines the number of discrete points evaluated along each line-of-sight, `extrapolate`, +which, if set to `True`, uses linear interpolation to extrapolate the frequency/wavelength dependent +model parameters allowing the model to be evaluated outside of it's original bounds, and finally, +`ephemeris`, which one can use to specify the +[solar system ephemeris](https://docs.astropy.org/en/stable/coordinates/solarsystem.html). used to +compute the position of the Earth and optionally the observer. + +## Evaluating a zodiacal light model +To make zodiacal light simulations ZodiPy needs some inputs data from the user: + +1. **Sky coordinates**. Provided through Astropy's +[`SkyCoord`](https://docs.astropy.org/en/stable/api/astropy.coordinates.SkyCoord.html) object. +2. **Time of observeration(s)**. Also provided in the +[`SkyCoord`](https://docs.astropy.org/en/stable/api/astropy.coordinates.SkyCoord.html) object. +3. **Position(s) of the observer**. Provided in a separate argument when evaluating the model. + +### The [`SkyCoord`](https://docs.astropy.org/en/stable/api/astropy.coordinates.SkyCoord.html) object +Users unfamiliar with Astropy's +[`SkyCoord`](https://docs.astropy.org/en/stable/api/astropy.coordinates.SkyCoord.html) should first +visit the [official Astropy docs](https://docs.astropy.org/en/stable/api/astropy.coordinates.SkyCoord.html) +to learn the basics. + +For a single observation in galactic coordinates, the +[`SkyCoord`](https://docs.astropy.org/en/stable/api/astropy.coordinates.SkyCoord.html) object may +look something like the following: +```py hl_lines="2 3 5 6 7 8 9 10" import astropy.units as u from astropy.coordinates import SkyCoord from astropy.time import Time @@ -48,11 +76,22 @@ skycoord = SkyCoord( 40 * u.deg, 60 * u.deg, obstime=Time("2020-01-01"), - frame="galactic" ) ``` -The `obstime` keyword is mandatory, and is given by an `astropy.time.Time` object, which can represent time in many formats, including Julian and modified Julian dates (see the [Astropy documentation](https://docs.astropy.org/en/stable/time/)). -Correspondingly for several observations, each with their own `obstime` input: +where the coordinates here are specified as longitude and latitude values. Note that the +[`SkyCoord`](https://docs.astropy.org/en/stable/api/astropy.coordinates.SkyCoord.html) object is very +flexible and supports many +[different formats](https://docs.astropy.org/en/stable/coordinates/skycoord.html#examples) for the +coordinates. + +The `obstime` keyword is mandatory and is given by the Astropy +[`Time`](https://docs.astropy.org/en/stable/time/ref_api.html#module-astropy.time) object, which can + represent time in many formats, including regular and modified Julian dates (see the + [`Time` docs](https://docs.astropy.org/en/stable/time/) for more information). + +For several observations, each with their own `obstime` input, the +[`SkyCoord`](https://docs.astropy.org/en/stable/api/astropy.coordinates.SkyCoord.html) may instead +look like the following: ```py hl_lines="6 7 8" import astropy.units as u from astropy.coordinates import SkyCoord @@ -62,58 +101,58 @@ skycoord = SkyCoord( [40, 41, 42] * u.deg, [60, 59, 58] * u.deg, obstime=Time(["2020-01-01", "2020-01-02", "2020-01-03"]), - frame="galactic" ) ``` -If a single value is given for `obstime`, all coordinates are assumed to be viewed instantaneously at that time from a single position in the Solar system. Otherwise, each coordinate must have its own `obstime` value. +If a single value is given for `obstime`, all coordinates are assumed to be viewed instantaneously +at that time from a single position in the solar system. Otherwise, each coordinate must have its +own `obstime` value. + +The sky coordinates should represent observer-centric coordinates. The observer-position is +therefore required to compute the line-of-sight integrals, but this is provided not in the +[`SkyCoord`](https://docs.astropy.org/en/stable/api/astropy.coordinates.SkyCoord.html) object, but + rather in the [`evaluate`][zodipy.Model.evaluate] method, which we will see soon. + +The coordinate frame in the +[`SkyCoord`](https://docs.astropy.org/en/stable/api/astropy.coordinates.SkyCoord.html) object +defaults to the [`ICRS`](https://docs.astropy.org/en/stable/api/astropy.coordinates.ICRS.html) frame, +but can be changed by providing the `frame` keyword argument: +```py hl_lines="9" +import astropy.units as u +from astropy.coordinates import SkyCoord +from astropy.time import Time -The sky coordinates should represent observer-centric coordinates. The observer-position is therefore required to compute the line-of-sight integrals, but this is provided not in the `SkyCoord` object, but rather in the `evaluate` method which we will see soon. +skycoord = SkyCoord( + [40, 41, 42] * u.deg, + [60, 59, 58] * u.deg, + obstime=Time(["2020-01-01", "2020-01-02", "2020-01-03"]), + frame="galactic", +) +``` -Common coordinate frames are the Ecliptic, Galactic, and Celestial frames ("E", "G", "C" in `healpy`), which can be specified through string representations: +Common coordinate frames are the Ecliptic, Galactic, and Celestial frames (these are represented as +"E", "G", "C" in [`healpy`](https://healpy.readthedocs.io/en/latest/)), which can be specified +either through string representations: - `"barycentricmeanecliptic"` (Ecliptic) - `"galactic"` (Galactic) - `"icrs"` (Celestial) -or using the frame objects imported from `astropy.coordinates`: +or through frame objects imported from `astropy.coordinates`: -- `BarycentricMeanEcliptic` -- `Galactic` -- `ICRS` +- [`BarycentricMeanEcliptic`](https://docs.astropy.org/en/stable/api/astropy.coordinates.BarycentricMeanEcliptic.html) +- [`Galactic`](https://docs.astropy.org/en/stable/api/astropy.coordinates.Galactic.html) +- [`ICRS`](https://docs.astropy.org/en/stable/api/astropy.coordinates.ICRS.html) !!! info "Notes on coordinate frames" - While the above listed built-in Astropy frames do *not* represent observer-centric coordinate frames, - we still use these to specify the frame rotation, which is required internally as the model is evaluated in - ecliptic coordinates. - -In the following, we show three sets of observations in all three coordinate frames -```py hl_lines="2 9 15 21" -import astropy.units as u -from astropy.coordinates import SkyCoord, BarycentricMeanEcliptic, Galactic, ICRS -from astropy.time import Time - -skycoord_ecliptic = SkyCoord( - 40 * u.deg, - 60 * u.deg, - obstime=Time("2020-01-01"), - frame=BarycentricMeanEcliptic -) -skycoord_galactic = SkyCoord( - 203 * u.deg, - 10 * u.deg, - obstime=Time("2020-01-01"), - frame=Galactic -) -skycoord_celestial = SkyCoord( - 12 * u.deg, - 40 * u.deg, - obstime=Time("2020-01-01"), - frame=ICRS -) -``` + Note that these built-in Astropy frames do not inherently represent observer-centric coordinate + frames. However this is fine, since we only need to know the rotation of the coordinates with + respect to the ecliptic plane (internally, the coordinates are manually shifted to heliocentric + coordinates using the `obspos` value)- -### The `evaluate` method -The zodiacal light is evaluated by providing the `SkyCoord` object to the `zodipy.Model.evaluate` method. +### The [`evaluate`][zodipy.Model.evaluate] method +The zodiacal light is evaluated by providing the +[`SkyCoord`](https://docs.astropy.org/en/stable/api/astropy.coordinates.SkyCoord.html) object to the +[`evaluate`][zodipy.Model.evaluate] method. ```py hl_lines="15" import astropy.units as u @@ -134,7 +173,11 @@ emission = model.evaluate(skycoord) print(emission) # ``` -By default, the observer is assumed to be the center of the Earth. The position of the observer can be explicitly provided as the keyword argument `obspos` in the `evaluate` method +By default, the observer is assumed to be the center of the Earth. In this case the Earth position is +computed internally using Astropy's +[solar system ephemeris](https://docs.astropy.org/en/stable/coordinates/solarsystem.html). +The position of the observer can be explicitly provided through the keyword argument `obspos` in the + [`evaluate`][zodipy.Model.evaluate] method ```py hl_lines="15 19" import astropy.units as u @@ -159,41 +202,35 @@ emission = model.evaluate(skycoord, obspos=[0.87, -0.53, 0.001] * u.AU) print(emission) # ``` -This argument accepts both a string representing a body recognized by `astropy.coordinates.solar_system_ephemeris` (see the Astropy [documentation](https://docs.astropy.org/en/stable/api/astropy.coordinates.solar_system_ephemeris.html)), or a heliocentric ecliptic cartesian position. +This argument accepts both a string representing a body recognized by the +[solar system ephemeris](https://docs.astropy.org/en/stable/coordinates/solarsystem.html), or a +heliocentric ecliptic cartesian position. -Similar to with the `obstime` attribute in the `SkyCoord` object, the `obspos` keyword have shape `(3,)` or `(3, ncoords)`. If a string representation of a body is used, with several values `obstime` ZodiPy will internally compute a position for each coordinate. +Similar to with the `obstime` attribute in the +[`SkyCoord`](https://docs.astropy.org/en/stable/api/astropy.coordinates.SkyCoord.html) object, the +value provided to the `obspos` keyword must have shape `(3,)` or `(3, ncoords)`, where `ncoords` is +the number of coordinates in the +[`SkyCoord`](https://docs.astropy.org/en/stable/api/astropy.coordinates.SkyCoord.html) object. ### Multiprocessing -ZodiPy will distribute the input coordinates to cores if the keyword argument `nprocesses` in the `evaluate` method is `nprocesses >= 1` using Python's `multiprocessing` module. -```py hl_lines="1 17" -import multiprocessing +ZodiPy will distribute the input coordinates to available cores using Python's +[`multiprocessing`](https://docs.python.org/3/library/multiprocessing.html) module if the keyword +argument `nprocesses` in the [`evaluate`][zodipy.Model.evaluate] method is greater or equal to 1. -import astropy.units as u -from astropy.coordinates import SkyCoord -from astropy.time import Time -import zodipy - -model = zodipy.Model(25 * u.micron) +```py +import multiprocessing -skycoord = SkyCoord( - 40 * u.deg, - 60 * u.deg, - obstime=Time("2020-01-01"), - frame="galactic" -) +nprocesses = multiprocessing.cpu_count() # 8 cores -emission = model.evaluate(skycoord, nprocesses=multiprocessing.cpu_count()) +emission = model.evaluate(skycoord, nprocesses=nprocesses) ``` -!!! tip - For all available optional keyword arguments in `zodipy.Model` see [the API reference](reference.md#zodipy.zodipy.Model). - ## Examples -### Emission along an Ecliptic scan -In the following, we simulate a scan across the Ecliptic plane +### Zodiacal light along an Ecliptic scan +In the following, we simulate a scan across the Ecliptic plane: ``` py title="ecliptic_scan.py" {!examples/ecliptic_scan.py!} @@ -202,8 +239,12 @@ In the following, we simulate a scan across the Ecliptic plane ![Ecliptic scan profile](img/ecliptic_scan.png) -### HEALPix maps -We can use [healpy](https://healpy.readthedocs.io/en/latest/) or [Astropy-healpix](https://astropy-healpix.readthedocs.io/en/latest/) to create a `SkyCoord` object directly from a HEALPIx pixelization +### HEALPix +We can use [healpy](https://healpy.readthedocs.io/en/latest/) or +[Astropy-healpix](https://astropy-healpix.readthedocs.io/en/latest/) to create a +[`SkyCoord`](https://docs.astropy.org/en/stable/api/astropy.coordinates.SkyCoord.html) object +directly from a HEALPix pixelization. In the following two examples, we produce an instantaneous map +of the sky in HEALPix representation: === "healpy" @@ -220,7 +261,8 @@ We can use [healpy](https://healpy.readthedocs.io/en/latest/) or [Astropy-healpi ![HEALPix map](img/healpix_map.png) ### Component-wise zodiacal light -We can return the zodiacal light for each component by using setting the keyword argument `return_comps` to `True` +We can return the zodiacal light for each component by using setting the keyword argument +`return_comps` to `True` in the [`evaluate`][zodipy.Model.evaluate] method: ``` py title="component_maps.py" {!examples/component_maps.py!} ``` @@ -229,7 +271,8 @@ We can return the zodiacal light for each component by using setting the keyword ### Visualizing the interplanetary dust distribution -We can visualize the number density of a supported zodiacal light model by using the `grid_number_density` function +We can visualize the number density of a supported zodiacal light model by using the +[`grid_number_density`][zodipy.grid_number_density] function ``` py title="number_density.py" {!examples/number_density.py!} ``` diff --git a/zodipy/model.py b/zodipy/model.py index 33a3d46..c24517b 100644 --- a/zodipy/model.py +++ b/zodipy/model.py @@ -35,7 +35,7 @@ class Model: def __init__( self, - x: units.Quantity, + x: units.Quantity[units.micron | units.GHz], *, weights: npt.ArrayLike | None = None, name: str = "dirbe", @@ -43,25 +43,27 @@ def __init__( extrapolate: bool = False, ephemeris: str = "builtin", ) -> None: - """Initialize the ZodiPy model interface. + """Initialize a zodiacal light model. Args: - x: Wavelength or frequency. If `x` is a sequence, it is assumed to be a the points - corresponding to a bandpass and the corresponding `weights` must be provided. - weights: Bandpass weights corresponding the the frequencies or wavelengths in `x`. The + x: Wavelength or frequency. If `x` is a sequence it is assumed to be a the points + corresponding to an instrument bandpass and the corresponding `weights` argument + must be provided. + weights: Bandpass weights corresponding the the frequencies/wavelengths in `x`. The weights are assumed to represent a normalized instrument response in units of - spectral radiance (Jy/sr). - name: Zodiacal light model to use for the simulations. For a list of available models, - see https://cosmoglobe.github.io/zodipy/introduction/. Defaults to 'dirbe'. - gauss_quad_degree: Order of the Gaussian-legendre quadrature used to evaluate the - line-of-sight integrals in the simulations. Default is 50 points. + spectral radiance [Jy/sr]. + name: Zodiacal light model to use. See the + [docs](https://cosmoglobe.github.io/zodipy/introduction/) for list of available + models. Defaults to 'dirbe'. + gauss_quad_degree: Order of the Gaussian-legendre quadrature representing the number of + discrete points along each line-of-sight. Default is 50 points. extrapolate: If `True` all spectral quantities in the selected model are extrapolated to - the requested frequencies or wavelengths. If `False`, an exception is raised on - requested values of `x` outside of the valid model range. Default is `False`. - ephemeris: Ephemeris used in `astropy.coordinates.solar_system_ephemeris` to compute the - positions of the observer and Earth. Defaults to 'builtin'. See the + the requested frequencies/wavelengths. Else, an exception is raised on values of `x` + outside of the valid model range. Default is `False`. + ephemeris: Ephemeris used in Astropy's `solar_system_ephemeris` to compute the positions + of Earth and optionally the observer. See the [Astropy documentation](https://docs.astropy.org/en/stable/coordinates/solarsystem.html) - for available ephemerides. + for all available ephemerides. Defaults to 'builtin'. """ try: @@ -118,34 +120,35 @@ def evaluate( self, skycoord: coords.SkyCoord, *, - obspos: units.Quantity | str = "earth", + obspos: units.Quantity[units.AU] | str = "earth", return_comps: bool = False, nprocesses: int = 1, ) -> units.Quantity[units.MJy / units.sr]: """Return the simulated zodiacal light. - The zodiacal light is simulated for a single, or a sequence of observations. If a single - `obspos` and `obstime` is provided for multiple coordinates, all coordinates are assumed to - be observed from that position at that time. Otherwise, each coordinate is simulated from - the corresponding observer position and time. + The zodiacal light is simulated for all sky coordinates present in the `skycoord` argument. + If an obstime and obspos value is not provided for each coordinate value, all coordinates + are assumed to be observed at an instant from the same position. Args: - skycoord: `astropy.coordinates.SkyCoord` object representing the coordinates or - observations for which to simulate the zodiacal light. The `frame` and `obstime` - attributes of the `SkyCoord` object must be set. The `obstime` attribute must be - specified, and correspond to a single, or a sequence of observational times with - length matching the number of coordinates. The frame must be convertible to the + skycoord: `astropy.coordinates.SkyCoord` object representing the coordinates for which + to simulate the zodiacal light. The `obstime` attribute must be specified, and + correspond to a either a single, or a sequence of observational times, one for each + coordinate in `skycoord`. The coordinate frame, provided through the `frame` keyword + in the the `astropy.coordinates.SkyCoord` object (defaults to + `astropy.coordinates.ICRS`), must be convertible to the `astropy.coordinates.BarycentricMeanEcliptic` frame. - obspos: The heliocentric ecliptic position of the observer, or a string representing - an observer in the `astropy.coordinates.solar_system_ephemeris`. If an explicit - position is given, it must either be a single, or a sequence of positions with - shape matching the number of coordinates Defaults to 'earth'. - return_comps: If True, the emission is returned component-wise. Defaults to False. + obspos: The heliocentric ecliptic position of the observer, or a string representing an + observer supported by the `astropy.coordinates.solar_system_ephemeris`. If an + explicit position is given, it must either be a single, or a sequence of positions, + one for each coordinate. Defaults to 'earth'. + return_comps: If `True`, the emission is returned component-wise. Defaults to `False`. nprocesses: Number of cores to use. If `nprocesses >= 1`, the line-of-sight integrals - are parallelized using the `multiprocessing` module. Defaults to 1. + are distributed and computed in parallel using the `multiprocessing` module. + Defaults to 1. Returns: - emission: Simulated zodiacal light in units of 'MJy/sr'. + emission: Simulated zodiacal light [MJy/sr]. """ try: @@ -296,25 +299,22 @@ def _init_ipd_model_partials(self) -> None: self._number_density_partials = get_partial_number_density_func(comps=self._ipd_model.comps) def get_parameters(self) -> dict: - """Return a dictionary containing the interplanetary dust model parameters. - - This method is mainly meant to be used to fit or sample zodiacal light models. + """Return a dictionary containing the zodiacal light model parameters. Returns: - parameters: Dictionary of parameters of the interplanetary dust model. + parameters: Zodiacal light model parameter dict. """ return self._ipd_model.to_dict() def update_parameters(self, parameters: dict) -> None: - """Update the interplanetary dust model parameters. + """Update the zodiacal light model parameters from a parameter dictionary. - This method is mainly meant to be used to fit or sample zodiacal light models. + The structure of the input dictionary must match that of the output of the `get_parameters` + method. Args: - parameters: Dictionary of parameters to update. The keys must be the names - of the parameters as defined in the model. To get the parameters dict - of an existing model, use the`get_parameters` method of an initialized - `zodipy.Model`. + parameters: Zodiacal light model parameter dict. + """ _dict = parameters.copy() _dict["comps"] = {} diff --git a/zodipy/number_density.py b/zodipy/number_density.py index e3d9ae9..9252320 100644 --- a/zodipy/number_density.py +++ b/zodipy/number_density.py @@ -479,21 +479,21 @@ def update_partial_earth_pos( def grid_number_density( - x: units.Quantity, - y: units.Quantity, - z: units.Quantity, + x: units.Quantity[units.AU], + y: units.Quantity[units.AU], + z: units.Quantity[units.AU], obstime: time.Time, - name: str = "DIRBE", + name: str = "dirbe", ephemeris: str = "builtin", ) -> npt.NDArray[np.float64]: - """Return the tabulated densities of the zodiacal components for a given grid. + """Return the component-wise tabulated densities of the zodiacal components for a given grid. Args: - x: Cartesian mesh grid x-coordinates. - y: Cartesian mesh grid y-coordinates. - z: Cartesian mesh grid z-coordinates. - obstime: Time of observation. - name: Interplanetary dust model to select. Default is 'DIRBE'. + x: x-coordinates of a cartesian mesh grid. + y: y-coordinates of a cartesian mesh grid. + z: z-coordinates of a cartesian mesh grid. + obstime: Time of observation. Required to compute the Earth position. + name: Zodiacal light model to use. Default is 'dirbe'. ephemeris: Solar system ephemeris to use. Default is 'builtin'. Returns: @@ -505,7 +505,6 @@ def grid_number_density( grid = np.asarray(np.meshgrid(x, y, z)) earthpos_xyz = get_earthpos_inst(obstime, ephemeris=ephemeris) - # Prepare attributes and variables for broadcasting with the grid # broadcasting reshapes for comp in ipd_model.comps.values():