Skip to content

Add multi-wavelength spectroscopy tutorial#203

Closed
aditya-pandey-dev wants to merge 19 commits into
JuliaAstro:mainfrom
aditya-pandey-dev:add-spectroscopy-tutorial
Closed

Add multi-wavelength spectroscopy tutorial#203
aditya-pandey-dev wants to merge 19 commits into
JuliaAstro:mainfrom
aditya-pandey-dev:add-spectroscopy-tutorial

Conversation

@aditya-pandey-dev
Copy link
Copy Markdown

@aditya-pandey-dev aditya-pandey-dev commented Mar 20, 2026

Closes #202

What's included

A new tutorial at docs/src/tutorials/multi-wavelength-spectroscopy.md covering a realistic end-to-end spectroscopy workflow:

  1. Loading a real SDSS DR14 spectrum from a FITS binary table (FITSIO.jl)
  2. Attaching physical units — Å, erg/s/cm²/Å (Unitful + UnitfulAstro)
  3. Fλ ↔ Fν conversion (Jansky)
  4. Dust extinction with CCM89, OD94, CAL00 laws (DustExtinction.jl)
  5. Spectral axis inspection via spectral_axis / flux_axis (Spectra.jl)
  6. Automatic uncertainty propagation (Measurements.jl)
  7. Synthetic blackbody spectra at 4 temperatures
  8. Spectral arithmetic — sky subtraction, scaling
  9. Cosmological redshift + luminosity distances (Cosmology.jl)

Testing

Includes test/test_tutorial.jl — a standalone verification script:

julia --project=docs/ test/test_tutorial.jl

All 5 dependency tests pass on Julia 1.12.5

Packages exercised

Spectra.jl, FITSIO.jl, DustExtinction.jl, UnitfulAstro.jl, Measurements.jl, Cosmology.jl, Plots.jl

Notes

  • Code blocks use plain julia fences (not @example) since Spectra.jl
    is installed from GitHub and not yet in the General registry
  • continuum() is referenced as a planned future feature with a link to
    Towards SpectrumBase.jl SpectrumBase.jl#41
  • [compat] bounds added for all new registered dependencies

Adds an end-to-end spectroscopy tutorial covering:
- Loading real SDSS spectra from FITS files (FITSIO.jl)
- Physical units and Fλ↔Fν conversions (Unitful + UnitfulAstro)
- Dust extinction with CCM89, OD94, CAL00 laws (DustExtinction.jl)
- Spectral axis inspection via spectral_axis/flux_axis (Spectra.jl)
- Automatic uncertainty propagation (Measurements.jl)
- Synthetic blackbody spectra generation (Spectra.jl)
- Spectral arithmetic: sky subtraction and scaling
- Cosmological redshift and luminosity distances (Cosmology.jl)

Includes test/test_tutorial.jl — standalone verification script.
Updates docs/Project.toml with [compat] bounds for all new deps.

Closes JuliaAstro#202
DustExtinction='0.6, 1' excluded v0.11.x (current release),
creating an unsolvable constraint with FITSIO 0.17 in CI.
Tutorial uses plain julia code blocks (not @example), so
docs build environment does not need to install tutorial
dependencies. Extra packages were causing CI resolution
failures in the JuliaAstroDocs test suite.
The CI test runner picks up all .jl files in test/ and tries
to execute them. test_tutorial.jl requires packages not present
in the test environment, causing JuliaAstroDocs to error.

Users can run the tutorial locally by installing the packages
listed in the tutorial's Packages section.
@aditya-pandey-dev
Copy link
Copy Markdown
Author

@icweaver can you check the PR. What changes should I do?

Copy link
Copy Markdown
Member

@cgarling cgarling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting example, thanks for the PR. I made some specific comments/suggestions below, here is some high-level feedback:

  • It would be nice to have this run on CI so the output can be displayed. Could you expand on why you can't use @example here? I thought that if you setup the doc build environment correctly there shouldn't be a problem with importing Spectra.jl even if it isn't in the General registry yet (i.e., using [sources] to set the url in the Project.toml).
  • Mostly you are dealing with flux density units in this example so we should make the associated plot labels "Flux Density" rather than "Flux" for clarity
  • I would try to be more consistent with using units when constructing the wavelength / flux density vectors, some places where you are constructing blackbody spectra you are not putting units on the wavelengths/temperatures and I think we want to encourage the use of units
  • I think that blackbody returns radiance units so you may need to calculate the luminosity density as L_lam​(lambda) = 4 \pi^2 R^2 B​(lambda,T) where R is the radius of the spherical blackbody (say 1 solar radius) and B(lambda, T) is what blackbody returns. It would be good to check this and amend the blackbody docstring to be more descriptive.
  • We are mostly using Makie.jl for plotting in our documentation now, idk if anyone has strong feelings on this. I don't mind using Plots.jl but would probably prefer makie

Comment thread docs/src/tutorials/multi-wavelength-spectroscopy.md Outdated
Comment thread docs/src/tutorials/multi-wavelength-spectroscopy.md Outdated
Comment thread docs/src/tutorials/multi-wavelength-spectroscopy.md Outdated
Comment thread docs/src/tutorials/multi-wavelength-spectroscopy.md Outdated
Comment thread docs/src/tutorials/multi-wavelength-spectroscopy.md Outdated
Comment thread docs/src/tutorials/multi-wavelength-spectroscopy.md Outdated
Comment thread docs/src/tutorials/multi-wavelength-spectroscopy.md Outdated
Comment thread docs/src/tutorials/multi-wavelength-spectroscopy.md Outdated
Comment thread docs/src/tutorials/multi-wavelength-spectroscopy.md Outdated
aditya-pandey-dev added 7 commits March 31, 2026 14:51
- @example blocks for CI + Spectra via [sources] in Project.toml
- Flux -> Flux Density in all plot ylabels
- Units on wave_bb, wave_synth (.* u"angstrom"), temperatures (u"K")
- L_lam = 4pi^2 * R^2 * B(lambda,T) correct luminosity formula
- SDSS ivar column for real Measurements uncertainties
- F_obs = L*(1+z)/(4pi*d_L^2) correct cosmological formula
- Plots.jl -> CairoMakie throughout
- SFD98Map with ICRSCoords -> GalCoords conversion
- Replace synthetic galaxy spectrum with real SDSS plate 1323 data
- Use FITS ivar column for real per-pixel σ = 1/√ivar uncertainties
- Addresses mentor comment: use Measurements with actual SDSS error column
@aditya-pandey-dev
Copy link
Copy Markdown
Author

@cgarling I've added Spectra.jl to docs/Project.toml via
[sources]. However, @example blocks still can't run on CI
because the tutorial makes network calls:

  1. Downloads a real SDSS FITS file (~50 MB)
  2. SFD98Map() downloads dust map tiles (~120 MB)
    So i think there are two suitable options : (a) Keep plain julia blocks with a note explaining network
    dependency (b) Split into @example (synthetic/offline parts) + plain
    julia (network parts)
    Which approach would you prefer?

@cgarling
Copy link
Copy Markdown
Member

cgarling commented Apr 8, 2026

I do Github Actions with network dependencies pretty frequently (e.g., through DataDeps.jl) and can't recall any issues. What exactly is the problem CI is creating, are you hitting a firewall (Github won't let you access external URLs)?

Copy link
Copy Markdown
Member

@cgarling cgarling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update, good progress! More comments below

Comment thread docs/src/tutorials/multi-wavelength-spectroscopy.md
Comment thread docs/src/tutorials/multi-wavelength-spectroscopy.md Outdated
Comment thread docs/src/tutorials/multi-wavelength-spectroscopy.md
Comment thread docs/src/tutorials/multi-wavelength-spectroscopy.md Outdated
Comment thread docs/src/tutorials/multi-wavelength-spectroscopy.md Outdated
Comment thread docs/src/tutorials/multi-wavelength-spectroscopy.md
Comment on lines +182 to +195
fig4, ax4 = lines(ustrip.(wave_rest), ustrip.(bb_rest.flux);
label = "z = 0", color = :black,
axis = (xlabel = "Wavelength (Å)",
ylabel = "Flux Density (erg s⁻¹ cm⁻² Å⁻¹)",
title = "Cosmological Surface-Brightness Dimming"))

for (z, col) in zip([0.5, 1.0, 2.0], [:blue, :green, :red])
d_L = uconvert(u"cm", luminosity_dist(cosmo, z))
w_obs = wave_rest .* (1 + z)
F_obs = L_lam .* (1 + z) ./ (4π .* d_L.^2)
lines!(ax4, ustrip.(w_obs), ustrip.(F_obs); label = "z = $z", color = col)
end
axislegend(ax4, position = :rt)
fig4
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fig4, ax4 = lines(ustrip.(wave_rest), ustrip.(bb_rest.flux);
label = "z = 0", color = :black,
axis = (xlabel = "Wavelength (Å)",
ylabel = "Flux Density (erg s⁻¹ cm⁻² Å⁻¹)",
title = "Cosmological Surface-Brightness Dimming"))
for (z, col) in zip([0.5, 1.0, 2.0], [:blue, :green, :red])
d_L = uconvert(u"cm", luminosity_dist(cosmo, z))
w_obs = wave_rest .* (1 + z)
F_obs = L_lam .* (1 + z) ./ (4π .* d_L.^2)
lines!(ax4, ustrip.(w_obs), ustrip.(F_obs); label = "z = $z", color = col)
end
axislegend(ax4, position = :rt)
fig4
fig4, ax4 = lines(ustrip.(wave_rest), ustrip.(bb_rest.flux);
label = "z = 0", color = :black,
axis = (xlabel = "Wavelength (Å)",
ylabel = "Flux Density (erg s⁻¹ cm⁻² Å⁻¹)",
yscale = log10, yticks=LogTicks(LinearTicks(5)),
title = "Cosmological Surface-Brightness Dimming"))
for (z, col) in zip([0.1, 0.5, 1.0], [:blue, :green, :red])
d_L = uconvert(u"cm", luminosity_dist(cosmo, z))
w_obs = wave_rest .* (1 + z)
F_obs = L_lam .* (1 + z) ./ (4π .* d_L.^2)
lines!(ax4, ustrip.(w_obs), ustrip.(F_obs); label = "z = $z", color = col)
end
axislegend(ax4, position = :rt)
fig4

Changed to display a little better

@icweaver
Copy link
Copy Markdown
Member

I've been thinking about re-homing our tutorials section under our learn.JuliaAstro site that is currently in the works. My thinking is that this would help reduce duplication of efforts and also help make things more discoverable. I'd be happy to help migrate things over if this sounds like a reasonable organizational step to y'all. I think I am already seeing a good bit of overlap with our Dust extinction notebook, which could probably absorb the changes proposed here

@barrettp
Copy link
Copy Markdown
Member

Replace FITSIO.jl with FITSFile.jl.

icweaver and others added 5 commits May 15, 2026 15:07
Co-authored-by: Chris Garling <chris.t.garling@gmail.com>
Co-authored-by: Chris Garling <chris.t.garling@gmail.com>
Co-authored-by: Chris Garling <chris.t.garling@gmail.com>
Co-authored-by: Chris Garling <chris.t.garling@gmail.com>
@icweaver
Copy link
Copy Markdown
Member

Ok, I think I incorporated the above comments here and tried to clean things up a bit. Can add more if this seems like the right direction to go for this PR

icweaver added a commit to JuliaAstro/learn-JuliaAstro that referenced this pull request May 18, 2026
Follow-up to JuliaAstro/JuliaAstro.github.io#203

Trying it out in notebook format

Doc preview:
https://learn.juliaastro.org/previews/PR28/tutorials/spectroscopy-sdss/

---------

Co-authored-by: Chris Garling <chris.t.garling@gmail.com>
@icweaver
Copy link
Copy Markdown
Member

Thanks @aditya-pandey-dev for your contribution! We have merged things here over on our learn.JuliaAstro site that is currently under construction

@icweaver icweaver closed this May 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants