Week 10: A wrapper is born

What I completed this week:

  • Continued working on the signal to noise functions pull request to synphot
    • Changed function names from howell_snr to ccd_snr and exptime_from_howell_snr to exptime_from_ccd_snr, which are more descriptive/informative
    • The units returned by ccd_snr are now dimensionless
  • Began writing a synphot wrapper. This work in progress PR is a bit of an embarrassing mess right now, but I’m envisioning something where you can initiate a class with the source spectrum of an object, give a telescope diameter, and boom, you can get attributes like SNR, countrate, exptime, etc… :
>>> from synphot.spectrum import SourceSpectrum
>>> from synphot.wrapper import Observe
>>> import astropy.units as u

>>> tele_diameter = 1 * u.m
>>> source_spec = SourceSpectrum(...)
>>> some_observation = Observe(source_spec, tele_diameter)

>>> some_observation.countrate
1e6 ct/s
>>> some_observation.snr
100
...

The observation can be customized by setting a bandpass, giving a desired SNR (to get a required exposure time), providing the quantum efficiency of the CCD or an atmospheric transmission model, etc.

But I’m not really sure if attributes are the best way to get these, er, “attributes” of the observation. Maybe argument-less methods would be better, e.g. some_observation.snr()? That might make it easier to alter some parameters like exposure time without having to create a new object… Anyway, this week has been full of thoughts like these.

How I kind of feel writing this. Something good will come together soon, I’m sure

This week’s goals:

  • Take a look at telescopy and astroplan and think how they, along with synspec and any higher order functions we come up with, can be merged

Longer term goals:

Week 9: synspec and other thoughts

What I completed this week:

  • Traveled to Seattle, where I’ll be for the rest of the summer
  • Added documentation on the signal to noise ratio (SNR) functions to the synphot docs
  • Integrated the SNR functions into the synphot tutorials I’ve been working on
  • Checked that the binned photometry (aka spectroscopy) is functioning correctly by comparing the count rate for the HAT-P-11 source spectrum and to the countrate for the binned spectrum (i.e. the “synspec” spectrum).
    The count rate for the binned spectrum is only %0.06 greater than the source spectrum’s, so I think it’s safe to say that synphot‘s binned photometry is behaving how we want it to.
  • Wrote a rough draft of what could be the synspec aspect of a higher function (see “Longer term goals” below)
I also took my dog to the groomers and I haven’t stopped squealing since

This week’s goals:

  • (minor) Fix units in SNR functions
  • Spend time with the notebook tutorials I’ve written and think about any higher order functions that could make their functionalities more streamlined
  • Take a look at telescopy and astroplan and think how they, along with synspec and any higher order functions we come up with, can be merged

Longer term goals:

  • Some thoughts on a possible deliverable, copied from my Slack message to the team:

So I’ve been thinking a bit more about how to incorporate synthetic spectroscopy into a package for synthetic photometry, and I’ve come full circle back to “telescopy”. At our last meeting we talked about writing a kind of wrapper for the synphot concepts covered in the tutorials, and I’m wondering if telescopy can be that wrapper.

Where synphot has a wide range of functionality, perhaps telescopy could be a package which utilizes synphot for a more “streamlined” purpose, for example “telescopy: a package for estimating the exposure time needed to obtain x-SNR with y-instrument”, where y-instrument could be either photometric or spectroscopic in nature.

The problem of this which we’ve discussed before is that we would be creating “yet another package”. But it would be a solution which provides both a wrapper and a synspec resource while avoiding the whole “why is there a synthetic spectroscopy generator inside of a synthetic photometry package??” confusion.

Week 8: More synspec and SNR

What I completed this week:

  • Made a pull request to synphot for implementing the signal-to-noise calculators that I wrote last week. I forgot to mention in my blog post last week that writing this module was a really useful exercise for me because I was introduced to so many new things! Like:
    • writing tests for pytest (and using the assert_quantity_allclose function from astropy.tests.helper)
    • python decorators (and how to ensure parameters are given in compatible units with astropy.units.quantity_input)
    • “duck typing” and the hasatrr() function
    • private functions
    • citing references in the docstring in the “astropythonic” way
    • a little bit of Sphinx documentation syntax
Me every day as a GSoC student
  • Wrote the first-draft of a “synspec” (synthetic spectroscopy) example. To simulate spectroscopy, I essentially create a custom waveset derived from some spectral resolution R and use synphot to bin the flux accordingly. There are a couple of things I’m unsure about though:
    • Does the binning done by synphot do (for all intents and purposes) the same thing as a real spectrometer? I haven’t done much work with spectroscopy so the mechanics are a little mysterious to me…
    • The spectral resolution R is defined to be R = λ / Δ λ , but what is the “correct” way of constructing an array of wavelengths according to this resolution? Do we keep R constant over the range of wavelengths (in which case Δ λ changes for each wavelength), or do we keep Δ λ constant and have a range of R over the wavelength range? For example, if we have an instrument which ranges from 0.3 – 1.1 microns with a spectral resolution of R = 1000, then either:
      • We let Δ λ change from 0.0003 to 0.0011 microns over the wavelength range
      • We define R = 1000 to be the resolution at the center of the waveset, (0.7 microns), which gives Δ λ = 0.0007 microns. Then for a constant Δ λ, the range of R is [430, 1600] (how it’s done in the current version of synspec)
  • Started working on the astroquery pull request for querying the SVO filter service, borrowing heavily from tynt (no need to reinvent the wheel).

This week’s goals:

  • Finish the synphot SNR pull request by adding to the docs
  • Adding SNR functionality into the other examples
  • Continue working on synspec
    • To check that the binned photometry (aka spectroscopy) is functioning correctly, we can compute the counts for a source spectrum and compare to the counts for the spectroscopized(?) spectrum. Then if they are the same within some error we can rest easier.
    • As it is now, we set a constant Δ λ and allow R to vary accordingly. Add functionality such that the user can either set a constant Δ λ and not worry about what R is, or they can give a specific R and not worry about what Δ λ is.
  • Submit the astroquery PR once it has been reviewed by mentors

Longer term goals:

  • Make 4-5 notebooks which explore different use cases in order to get an idea of how we want to implement any changes or enhancements to synphot:
    1. Model spectrum -> Synthetic photometry
      • Ground-based example: existing APO notebook
      • Space-based example: existing APO notebook + Kepler
    2. Empirical spectrum -> Synthetic photometry
      • Example: Galaxy with high H-alpha emission observed by SDSS
    3. Model spectrum -> synthetic spectroscopy
      • Example: Observations of a G dwarf with CHEOPS at R~1k vs 100k – what count rates do you get?
    4. Empirical spectrum -> synthetic spectroscopy
      • Possible example: Some HII region spectrum -> how many hours to a S/N of X
  • Make a pull request to synphot for the signal-to-noise predictor
  • Create a pull request to Astroquery to enable queries to the filter VO service for filter transmittance curves
  • Think about whether we want to add a higher-level function which takes the telescope params and target and spits out a SNR

Weeks 6 and 7: Synspec and SNR

What I completed these last two weeks:

  • Trying to solve the offset problem for example 2:
    • Do the same analysis for multiple objects. Is the systematic error still there?
      The systematic error persists strongly for both objects, as you can see in the Figure 1 below. So it’s not object-specific, and I think this also means it’s not weather related (assuming the two objects were observed on different nights).
    • Plot bandpasses on top of spectrum
      Figure 2 shows spectra of both objects ontop of the bandpasses, where we’ve removed the u ad z bands because they don’t fully overlap with the spectrum, which resulted in underestimated magnitudes for the u and z bands since synphot has to guess what the spectrum looks like to fill in the gaps. Other than that, I can’t see a reason why the filter models would be responsible for the systematic offset.
    • How systematic is this offset? Plot the fractional error in each band to see.
      Figure 3 shows the fractional error between the synphot fluxes and the observed fluxes. The offset isn’t quite as systematic as I thought, since the three objects are affected to different degrees. Could this mean that the error *is* weather related…?
    • Add a “boring” elliptical galaxy for comparison.
      The offset persists for the elliptical galaxy, and is in the same ballpark as the others in terms of fractional error. I’m still unsure why synphot would be overestimating the photometric flux…
Figure 1. Photometry of two different H-alpha emission galaxies and one elliptical galaxy observed by SDSS, with a persistant systematic offset between synphot fluxes and observed fluxes.
Figure 2. Spectra of three objects in relation to the bandpass models.
Figure 3. Fractional error between the synphot fluxes and the observed fluxes in each band.
  • Wrote a signal-to-noise predictor based on “the CCD equation” in Steve Howell’s “Handbook of CCD Astronomy”, 2000. I would like to make a pull request to implement this into synphot, possibly as a method on Observation, e.g.:
>>> from synphot.observation import Observation
>>> import astropy.units as u
...
>>> observation = Observation(spectrum, bandpass)
>>> countrate = observation.countrate()
>>> counts = countrate * 10 * u.s
>>> snr = observation.snr(counts)
>>> snr
42
  • Also wrote a function which returns the exposure time needed to reach a desired signal to noise ratio.
    • I’m not really sure what to name it, exposure_time_from_snr() seems too long…
    • In the case where the error due to the background estimation and gain are significant, solving for t can not be done analytically, so I use scipy.optimize.fsolve to solve it numerically. However, fsolve doesn’t preserve quantity types, so I have to add some annoying conditional statements to convert t back to a quantity… is there a better way to do this?

This week’s goals:

  • Make a pull request to synphot for the signal-to-noise predictor
  • Begin working on “synspec” (synthetic spectroscopy)
    • Is there an easy way to use synphot for synthetic spectroscopy?
    • See how long each run takes – ideally it should be fast, for people who want to run this on thousands of spectra

Longer term goals:

  • Make 4-5 notebooks which explore different use cases in order to get an idea of how we want to implement any changes or enhancements to synphot:
    1. Model spectrum -> Synthetic photometry
      • Ground-based example: existing APO notebook
      • Space-based example: existing APO notebook + Kepler
    2. Empirical spectrum -> Synthetic photometry
      • Example: Galaxy with high H-alpha emission observed by SDSS
    3. Model spectrum -> synthetic spectroscopy
      • Example: Observations of a G dwarf with CHEOPS at R~1k vs 100k – what count rates do you get?
    4. Empirical spectrum -> synthetic spectroscopy
      • Possible example: Some HII region spectrum -> how many hours to a S/N of X
  • Make a pull request to synphot for the signal-to-noise predictor
  • Create a pull request to Astroquery to enable queries to the filter VO service for filter transmittance curves Is this still on the table given tynt‘s existence?
Oh and it was also the 4th of July sometime in between the coding