From 6301f280abe5dd2a82cb77c854cd814f0412d5f4 Mon Sep 17 00:00:00 2001 From: Hannu Parviainen Date: Thu, 5 Jun 2025 15:24:48 +0200 Subject: [PATCH 01/12] Switching to use sphinx astropy conf v2 with the PyData theme. --- docs/_static/specreduce.css | 15 --------- docs/conf.py | 64 ++++++++++++++++++++----------------- 2 files changed, 35 insertions(+), 44 deletions(-) diff --git a/docs/_static/specreduce.css b/docs/_static/specreduce.css index 229d8787..e69de29b 100644 --- a/docs/_static/specreduce.css +++ b/docs/_static/specreduce.css @@ -1,15 +0,0 @@ -@import url("bootstrap-astropy.css"); - -div.topbar a.brand { - background: transparent url("logo_icon.png") no-repeat 8px 3px; - background-image: url("logo_icon.png"), none; - background-size: 32px 32px; -} - -#logotext1 { - color: #519EA8; -} - -#logotext2 { - color: #FF5000; -} diff --git a/docs/conf.py b/docs/conf.py index cf78023f..5079e8be 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -33,7 +33,7 @@ from specreduce import __version__ try: - from sphinx_astropy.conf.v1 import * # noqa + from sphinx_astropy.conf.v2 import * # noqa except ImportError: print('ERROR: the documentation requires the sphinx-astropy package to be installed') sys.exit(1) @@ -52,7 +52,7 @@ highlight_language = 'python3' # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.2' +needs_sphinx = '3.0' # To perform a Sphinx version check that needs to be more specific than # major.minor, call `check_sphinx_version("x.y.z")` here. @@ -87,40 +87,46 @@ # -- Options for HTML output -------------------------------------------------- -# A NOTE ON HTML THEMES -# The global astropy configuration uses a custom theme, 'bootstrap-astropy', -# which is installed along with astropy. A different theme can be used or -# the options for this theme can be modified by overriding some of the -# variables set in the global configuration. The variables set in the -# global configuration are listed below, commented out. - - -# Add any paths that contain custom themes here, relative to this directory. -# To use a different custom theme, add the directory containing the theme. -#html_theme_path = [] - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. To override the custom theme, set this to the -# name of a builtin theme or the name of a custom theme in html_theme_path. -#html_theme = None html_static_path = ['_static'] # html_theme = None html_style = 'specreduce.css' - -html_theme_options = { - 'logotext1': 'spec', # white, semi-bold - 'logotext2': 'reduce', # orange, light - 'logotext3': ':docs' # white, light +html_theme_options.update( + { + "github_url": "https://github.com/astropy/specreduce", + "use_edit_page_button": False, + "navigation_with_keys": False, + "logo": { + "text": f"{project}", + "image_light": "_static/logo_icon.png", + "image_dark": "_static/logo_icon.png", + }, } +) + +html_context = { + "default_mode": "light", + "version_slug": os.environ.get("READTHEDOCS_VERSION") or "", + "to_be_indexed": ["stable", "latest"], + "github_user": "astropy", + "github_repo": "specreduce", + "github_version": "main", + "doc_path": "docs", + "edit_page_url_template": "{{ astropy_custom_edit_url(github_user, github_repo, github_version, doc_path, file_name, default_edit_page_url_template) }}", + "default_edit_page_url_template": "https://github.com/{github_user}/{github_repo}/edit/{github_version}/{doc_path}{file_name}", + # Tell Jinja2 templates the build is running on Read the Docs + "READTHEDOCS": os.environ.get("READTHEDOCS", "") == "True", +} + +#html_theme_options = { +# 'logotext1': 'spec', # white, semi-bold +# 'logotext2': 'reduce', # orange, light +# 'logotext3': ':docs' # white, light +# } # Custom sidebar templates, maps document names to template names. #html_sidebars = {} -html_sidebars['**'] = ['localtoc.html'] -html_sidebars['index'] = ['globaltoc.html', 'localtoc.html'] - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = '' +#html_sidebars['**'] = ['localtoc.html'] +#html_sidebars['index'] = ['globaltoc.html', 'localtoc.html'] # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 From f4040d878d6c44dc14a400a1f09e6d21bd43761d Mon Sep 17 00:00:00 2001 From: Hannu Parviainen Date: Tue, 10 Jun 2025 20:59:01 +0100 Subject: [PATCH 02/12] Restructuring the documentation without adding anything new. --- docs/api.rst | 4 +- docs/background.rst | 29 ++++++ docs/contributing.rst | 8 ++ docs/extraction.rst | 110 +++++++++++++++++++++++ docs/index.rst | 52 ++++------- docs/installation.rst | 24 +++++ docs/quickstart.rst | 10 +++ docs/tilt_correction/tilt_correction.rst | 2 + docs/trace.rst | 25 ++++++ docs/user_guide.rst | 21 +++++ docs/wavelength_calibration.rst | 14 +-- 11 files changed, 256 insertions(+), 43 deletions(-) create mode 100644 docs/background.rst create mode 100644 docs/contributing.rst create mode 100644 docs/extraction.rst create mode 100644 docs/installation.rst create mode 100644 docs/quickstart.rst create mode 100644 docs/tilt_correction/tilt_correction.rst create mode 100644 docs/trace.rst create mode 100644 docs/user_guide.rst diff --git a/docs/api.rst b/docs/api.rst index e4b4de6b..a6fa6948 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -1,7 +1,7 @@ .. _api_index: -API Index -========= +API +=== .. automodapi:: specreduce :no-inheritance-diagram: diff --git a/docs/background.rst b/docs/background.rst new file mode 100644 index 00000000..28dc7c46 --- /dev/null +++ b/docs/background.rst @@ -0,0 +1,29 @@ +Background correction +===================== + +The `specreduce.background` module generates and subtracts a background image from +the input 2D spectral image. The `~specreduce.background.Background` object is +defined by one or more windows, and can be generated with: + +* `~specreduce.background.Background` +* `Background.one_sided ` +* `Background.two_sided ` + +The center of the window can either be passed as a float/integer or as a trace + +.. code-block:: python + + bg = specreduce.background.Background.one_sided(image, trace, separation=5, width=2) + +or, equivalently + +.. code-block:: python + + bg = specreduce.background.Background.one_sided(image, 15, separation=5, width=2) + +The background image can be accessed via `~specreduce.background.Background.bkg_image` +and the background-subtracted image via `~specreduce.background.Background.sub_image` +(or ``image - bg``). + +The background and trace steps can be done iteratively, to refine an automated +trace using the background-subtracted image as input. \ No newline at end of file diff --git a/docs/contributing.rst b/docs/contributing.rst new file mode 100644 index 00000000..989e0e6d --- /dev/null +++ b/docs/contributing.rst @@ -0,0 +1,8 @@ +Contributing +============ + +.. toctree:: + :maxdepth: 1 + + process/index + terms \ No newline at end of file diff --git a/docs/extraction.rst b/docs/extraction.rst new file mode 100644 index 00000000..a35a68ca --- /dev/null +++ b/docs/extraction.rst @@ -0,0 +1,110 @@ +Spectrum Extraction +=================== + +The `specreduce.extract` module extracts a 1D spectrum from an input 2D spectrum +(likely a background-extracted spectrum from the previous step) and a defined +window, using one of the following implemented methods: + +* `~specreduce.extract.BoxcarExtract` +* `~specreduce.extract.HorneExtract` + +Each of these takes the input image and trace as inputs (see the :ref:`api_index` for +other required and optional parameters) + +.. code-block:: python + + extract = specreduce.extract.BoxcarExtract(image-bg, trace, width=3) + +or + +.. code-block:: python + + extract = specreduce.extract.HorneExtract(image-bg, trace) + +For the Horne algorithm, the variance array is required. If the input image is +an ``astropy.NDData`` object with ``image.uncertainty`` provided, +then this will be used. Otherwise, the ``variance`` parameter must be set. + +.. code-block:: python + + extract = specreduce.extract.HorneExtract(image-bg, trace, variance=var_array) + +An optional mask array for the image may be supplied to HorneExtract as well. +This follows the same convention and can either be attached to ``image`` if it +is an ``astropy.NDData`` object, or supplied as a keyword argument. + +The extraction methods automatically detect non-finite pixels in the input +image and combine them with the user-supplied mask to prevent them from biasing the +extraction. In the boxcar extraction, the treatment of these pixels is controlled by +the ``mask_treatment`` option. When set to ``exclude`` (the default), non-finite +pixels within the extraction window are excluded from the extraction, and the extracted +flux is scaled according to the effective number of unmasked pixels. When using other +options (``filter`` or ``omit``), the non-finite values may be propagated or treated +differently as documented in the API. + +The previous examples in this section show how to initialize the BoxcarExtract +or HorneExtract objects with their required parameters. To extract the 1D +spectrum + +.. code-block:: python + + spectrum = extract.spectrum + +The ``extract`` object contains all the set options. The extracted 1D spectrum +can be accessed via the ``spectrum`` property or by calling (e.g ``extract()``) +the ``extract`` object (which also allows temporarily overriding any values) + +.. code-block:: python + + spectrum2 = extract(width=6) + +or, for example to override the original ``trace_object`` + +.. code-block:: python + + spectrum2 = extract(trace_object=new_trace) + +Spatial profile options +----------------------- +The Horne algorithm provides two options for fitting the spatial profile to the +cross dispersion direction of the source: a Gaussian fit (default), +or an empirical ``interpolated_profile`` option. + +If the default Gaussian option is used, an optional background model may be +supplied as well (default is a 2D Polynomial) to account +for residual background in the spatial profile. This option is not supported for +``interpolated_profile``. + +If the ``interpolated_profile`` option is used, the image will be sampled in various +wavelength bins (set by ``n_bins_interpolated_profile``), averaged in those bins, and +samples are then interpolated between (linear by default, interpolation degree can +be set with ``interp_degree_interpolated_profile``, which defaults to linear in +x and y) to generate an empirical interpolated spatial profile. Since this option +has two optional parameters to control the fit, the input can either be a string +to indicate that ``interpolated_profile`` should be used for the spatial profile +and to use the defaults for bins and interpolation degree, or to override these +defaults a dictionary can be passed in. + +For example, to use the ``interpolated_profile`` option with default bins and +interpolation degree + +.. code-block:: python + + interp_profile_extraction = extract(spatial_profile='interpolated_profile') + +Or, to override the default of 10 samples and use 20 samples + +.. code-block:: python + + interp_profile_extraction = extract(spatial_profile={'name': 'interpolated_profile', + 'n_bins_interpolated_profile': 20) + +Or, to do a cubic interpolation instead of the default linear + +.. code-block:: python + + interp_profile_extraction = extract(spatial_profile={'name': 'interpolated_profile', + 'interp_degree_interpolated_profile': 3) + +As usual, parameters can either be set when instantiating the HorneExtraxt object, +or supplied/overridden when calling the extraction method on that object. \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 40727b1a..0075d76e 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -5,16 +5,23 @@ Specreduce Documentation The `specreduce `_ package aims to provide a data reduction toolkit for optical and infrared spectroscopy, on which applications such as pipeline processes for -specific instruments can be built. The scope of its functionality is limited to -basic spectroscopic reduction, currently encompassing the following three tasks: +specific instruments can be built. The scope of its functionality is limited to basic spectroscopic +reduction, currently encompassing the following tasks: -#. Determining the trace of a spectrum dispersed in a 2D image, either by setting a flat +#. **2D tilt model calculation and correction:** A 2D tilt model can be calculated from arc + spectra. Tilt correction removes the wavelength curvature along the cross-dispersion axis, + +#. **1D wavelength calibration:** from arc spectra. +#. **Spectrum trace determination:** Determining the trace of a spectrum dispersed in a 2D + image, either by setting a flat trace, providing a custom trace array, or fitting a spline, polynomial, or other model to the positions of the dispersed spectrum. -#. Generating a background based on a region on one or both sides of this trace, and making +#. **Background subtraction:** Generating a background based on a region on one or both sides of + this trace, and making available the background image, 1D spectrum of the background, and the background-subtracted image. -#. Performing either a Horne (a.k.a. "optimal") or boxcar extraction on either the original +#. **Spectrum extraction:** Performing either a Horne (a.k.a. "optimal") or boxcar extraction on + either the original or background-subtracted 2D spectrum, using the trace generated by the first task to generate a 1D spectrum. @@ -32,33 +39,22 @@ complementary packages. change. Please feel free to contribute code and suggestions through github. -.. _spectral-extraction: +.. toctree:: + :maxdepth: 2 -******************* -Spectral Extraction -******************* + quickstart .. toctree:: :maxdepth: 2 - extraction_quickstart.rst + user_guide.rst -*********** -Calibration -*********** .. toctree:: - :maxdepth: 1 - - wavelength_calibration.rst - extinction.rst - specphot_standards.rst - mask_treatment/mask_treatment.rst + :maxdepth: 2 + contributing.rst -***** -Index -***** .. toctree:: :maxdepth: 1 @@ -68,15 +64,3 @@ Index * :ref:`genindex` * :ref:`modindex` * :ref:`search` - - -**************** -Development Docs -**************** - -.. toctree:: - :maxdepth: 1 - - process/index - terms - diff --git a/docs/installation.rst b/docs/installation.rst new file mode 100644 index 00000000..dd531292 --- /dev/null +++ b/docs/installation.rst @@ -0,0 +1,24 @@ +.. _installation: + +Installation +============ + +Specreduce can be installed from PyPI using ``pip`` + +.. code-block:: console + + pip install specreduce + +from the conda-forge repository using ``conda`` + +.. code-block:: console + + conda install conda-forge::specreduce + +or by cloning the repository from `GitHub `_ + +.. code-block:: console + + git clone https://github.com/astropy/specreduce.git + cd specreduce + pip install . \ No newline at end of file diff --git a/docs/quickstart.rst b/docs/quickstart.rst new file mode 100644 index 00000000..7f06cb2a --- /dev/null +++ b/docs/quickstart.rst @@ -0,0 +1,10 @@ +.. _spectral-extraction: + +Quickstart +========== + +.. toctree:: + :maxdepth: 2 + + installation.rst + extraction_quickstart.rst \ No newline at end of file diff --git a/docs/tilt_correction/tilt_correction.rst b/docs/tilt_correction/tilt_correction.rst new file mode 100644 index 00000000..dcea1ff7 --- /dev/null +++ b/docs/tilt_correction/tilt_correction.rst @@ -0,0 +1,2 @@ +2D Tilt Correction +================== \ No newline at end of file diff --git a/docs/trace.rst b/docs/trace.rst new file mode 100644 index 00000000..4cddbc84 --- /dev/null +++ b/docs/trace.rst @@ -0,0 +1,25 @@ +Tracing +======= + +The `specreduce.tracing` module defines the trace of a spectrum on the 2D image. +These traces can either be determined semi-automatically or manually, and are +provided as the inputs for the remaining steps of the extraction process. +Supported trace types include: + +* `~specreduce.tracing.ArrayTrace` +* `~specreduce.tracing.FlatTrace` +* `~specreduce.tracing.FitTrace` + + +Each of these trace classes takes the 2D spectral image as input, as well as +additional information needed to define or determine the trace (see the API docs +above for required parameters for each of the available trace classes) + +.. code-block:: python + + trace = specreduce.tracing.FlatTrace(image, 15) + +.. note:: + The fit for `~specreduce.tracing.FitTrace` may be adversely affected by noise where the spectrum + is faint. Narrowing the window parameter or lowering the order of the fitting function may + improve the result for noisy data. \ No newline at end of file diff --git a/docs/user_guide.rst b/docs/user_guide.rst new file mode 100644 index 00000000..cea5dcf6 --- /dev/null +++ b/docs/user_guide.rst @@ -0,0 +1,21 @@ +User Guide +========== + +.. toctree:: + :maxdepth: 1 + :caption: Core Functionality + + tilt_correction/tilt_correction + wavelength_calibration + trace + background + extraction + + +.. toctree:: + :maxdepth: 1 + :caption: Additional Topics + + extinction + specphot_standards + mask_treatment/mask_treatment \ No newline at end of file diff --git a/docs/wavelength_calibration.rst b/docs/wavelength_calibration.rst index f34d7dec..f2b77ef6 100644 --- a/docs/wavelength_calibration.rst +++ b/docs/wavelength_calibration.rst @@ -1,7 +1,7 @@ .. _wavelength_calibration: -Wavelength Calibration -====================== +1D Wavelength Calibration +========================= Wavelength calibration is currently supported for 1D spectra. Given a list of spectral lines with known wavelengths and estimated pixel positions on an input calibration @@ -21,11 +21,11 @@ example below, the line positions (``pixel_centers``) have already been extracte ``lamp_spectrum``:: import astropy.units as u - from specreduce import WavelengthCalibration1D - pixel_centers = [10, 22, 31, 43] - wavelengths = [5340, 5410, 5476, 5543]*u.AA - test_cal = WavelengthCalibration1D(lamp_spectrum, line_pixels=pixel_centers, - line_wavelengths=wavelengths) + from specreduce import WavelengthCalibration1D + pixel_centers = [10, 22, 31, 43] + wavelengths = [5340, 5410, 5476, 5543]*u.AA + test_cal = WavelengthCalibration1D(lamp_spectrum, line_pixels=pixel_centers, + line_wavelengths=wavelengths) calibrated_spectrum = test_cal.apply_to_spectrum(science_spectrum) The example above uses the default model (`~astropy.modeling.functional_models.Linear1D`) From a5f744ee52323581803bb28808cedec42d788f40 Mon Sep 17 00:00:00 2001 From: Hannu Parviainen Date: Tue, 10 Jun 2025 21:10:00 +0100 Subject: [PATCH 03/12] Revised tracing documentation. --- docs/trace.rst | 56 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/docs/trace.rst b/docs/trace.rst index 4cddbc84..dcfa9cd0 100644 --- a/docs/trace.rst +++ b/docs/trace.rst @@ -1,25 +1,53 @@ Tracing ======= -The `specreduce.tracing` module defines the trace of a spectrum on the 2D image. -These traces can either be determined semi-automatically or manually, and are -provided as the inputs for the remaining steps of the extraction process. -Supported trace types include: +The `specreduce.tracing` module defines the spatial position (trace) of a spectrum across a 2D +detector image. Tracing is a necessary step that identifies where the spectrum falls on each +column and row of the detector, enabling accurate extraction of the 1D spectrum. The trace can be +determined either semi-automatically or manually depending on the data quality and spectral +characteristics. -* `~specreduce.tracing.ArrayTrace` -* `~specreduce.tracing.FlatTrace` -* `~specreduce.tracing.FitTrace` +The module provides three main trace types for different scenarios: +* `~specreduce.tracing.ArrayTrace` - Uses a pre-defined array of positions for maximum flexibility +* `~specreduce.tracing.FlatTrace` - Assumes spectrum follows a straight horizontal/vertical line +* `~specreduce.tracing.FitTrace` - Fits a polynomial function to automatically detected spectrum positions -Each of these trace classes takes the 2D spectral image as input, as well as -additional information needed to define or determine the trace (see the API docs -above for required parameters for each of the available trace classes) +Each trace class requires the 2D spectral image as input, along with trace-specific parameters. + +Flat trace +---------- + +.. code-block:: python + + # FlatTrace example - specify the fixed row/column position + trace = specreduce.tracing.FlatTrace(image, position=15) + +ArrayTrace +---------- .. code-block:: python - trace = specreduce.tracing.FlatTrace(image, 15) + # ArrayTrace example - manual position array + positions = [14, 15, 15, 16] # pixel positions along dispersion axis + trace = specreduce.tracing.ArrayTrace(image, positions) + +FitTrace +-------- + +.. code-block:: python + + # FitTrace example - automatic detection with polynomial fitting + trace = specreduce.tracing.FitTrace(image, + order=3, # polynomial order + window=10) # pixel window for centroid + .. note:: - The fit for `~specreduce.tracing.FitTrace` may be adversely affected by noise where the spectrum - is faint. Narrowing the window parameter or lowering the order of the fitting function may - improve the result for noisy data. \ No newline at end of file + + When using `~specreduce.tracing.FitTrace` with noisy or faint spectra: + + * Reduce the ``window`` parameter to minimize impact of background noise + * Lower the polynomial ``order`` to prevent overfitting + * Consider using `~specreduce.tracing.FlatTrace` for very faint spectra + * Mask cosmic rays or bad pixels before tracing \ No newline at end of file From 558d655c195d06d30d85d1bff4adf1f7b31c2d9c Mon Sep 17 00:00:00 2001 From: Hannu Parviainen Date: Tue, 10 Jun 2025 21:15:01 +0100 Subject: [PATCH 04/12] Revised tracing documentation. --- docs/trace.rst | 59 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/docs/trace.rst b/docs/trace.rst index dcfa9cd0..980ceb5a 100644 --- a/docs/trace.rst +++ b/docs/trace.rst @@ -2,18 +2,32 @@ Tracing ======= The `specreduce.tracing` module defines the spatial position (trace) of a spectrum across a 2D -detector image. Tracing is a necessary step that identifies where the spectrum falls on each -column and row of the detector, enabling accurate extraction of the 1D spectrum. The trace can be -determined either semi-automatically or manually depending on the data quality and spectral -characteristics. +detector image. In spectroscopic data reduction, tracing is a critical step that identifies and maps +where the spectrum falls on each column and row of the detector. This mapping enables accurate +extraction of the one-dimensional spectrum from the two-dimensional image data. The trace effectively +accounts for any curvature or tilt in how the spectrum is projected onto the detector, which can +occur due to optical effects in the spectrograph or mechanical flexure during observations. -The module provides three main trace types for different scenarios: +The trace position can be determined either semi-automatically or manually depending on factors like: -* `~specreduce.tracing.ArrayTrace` - Uses a pre-defined array of positions for maximum flexibility -* `~specreduce.tracing.FlatTrace` - Assumes spectrum follows a straight horizontal/vertical line -* `~specreduce.tracing.FitTrace` - Fits a polynomial function to automatically detected spectrum positions +* Data quality and signal-to-noise ratio +* Spectral characteristics and features +* Presence of contaminating sources or artifacts +* Wavelength coverage and dispersion direction -Each trace class requires the 2D spectral image as input, along with trace-specific parameters. +The module provides three main trace types to handle different observational scenarios: + +* `~specreduce.tracing.ArrayTrace` - Uses a pre-defined array of positions for maximum flexibility. + Ideal for complex or unusual trace shapes that are difficult to model mathematically. + +* `~specreduce.tracing.FlatTrace` - Assumes the spectrum follows a straight horizontal/vertical line + across the detector. Best for well-aligned spectrographs with minimal optical distortion. + +* `~specreduce.tracing.FitTrace` - Fits a polynomial function to automatically detected spectrum + positions. Suitable for typical spectra with smooth, continuous trace profiles. + +Each trace class requires the 2D spectral image as input, along with trace-specific parameters +that control how the trace is determined and fitted to the data. Flat trace ---------- @@ -43,11 +57,24 @@ FitTrace window=10) # pixel window for centroid -.. note:: +Best Practices +------------- + +When selecting and configuring a trace method, consider these guidelines: + +* For bright, well-defined spectra: + - `FitTrace` with default parameters usually works well + - Larger ``window`` values can improve centroid accuracy + - Higher polynomial orders can better follow any curvature + +* For noisy or faint spectra: + - Reduce the ``window`` parameter to minimize impact of background noise + - Lower the polynomial ``order`` to prevent overfitting + - Consider using `FlatTrace` for very faint spectra + - Mask cosmic rays or bad pixels before tracing + - Pre-process images to improve signal-to-noise if needed - When using `~specreduce.tracing.FitTrace` with noisy or faint spectra: - - * Reduce the ``window`` parameter to minimize impact of background noise - * Lower the polynomial ``order`` to prevent overfitting - * Consider using `~specreduce.tracing.FlatTrace` for very faint spectra - * Mask cosmic rays or bad pixels before tracing \ No newline at end of file +* For unusual or complex traces: + - Use `ArrayTrace` with manually determined positions + - Consider breaking the trace into segments + - Validate trace positions visually before extraction \ No newline at end of file From e5ea1f5a89641c09c3289193c482c2f1df93828e Mon Sep 17 00:00:00 2001 From: Hannu Parviainen Date: Tue, 10 Jun 2025 21:15:17 +0100 Subject: [PATCH 05/12] Revised documentation. --- docs/index.rst | 5 ----- docs/terms.rst | 3 +-- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 0075d76e..e58f702d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -33,11 +33,6 @@ and visualization by `matplotlib `_. A few examples will be provided that feature ``specreduce`` in conjunction with these complementary packages. -.. note:: - - Specreduce is currently an incomplete work-in-progress and is liable to - change. Please feel free to contribute code and suggestions through github. - .. toctree:: :maxdepth: 2 diff --git a/docs/terms.rst b/docs/terms.rst index 815233e0..304bdfac 100644 --- a/docs/terms.rst +++ b/docs/terms.rst @@ -476,10 +476,9 @@ Processing Steps what redshift?) ----- Mentioned but not defined -------------------------- +========================= - WCS & Database archive - Cloud archiving From 68108a56301ebd82a3d444735b2b7d7a967230dd Mon Sep 17 00:00:00 2001 From: Hannu Parviainen Date: Sat, 21 Jun 2025 20:17:44 +0100 Subject: [PATCH 06/12] Added basic plots to the ``specreduce.tracing`` docs and revised the text. --- docs/trace.rst | 130 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 104 insertions(+), 26 deletions(-) diff --git a/docs/trace.rst b/docs/trace.rst index 980ceb5a..362799ec 100644 --- a/docs/trace.rst +++ b/docs/trace.rst @@ -3,59 +3,137 @@ Tracing The `specreduce.tracing` module defines the spatial position (trace) of a spectrum across a 2D detector image. In spectroscopic data reduction, tracing is a critical step that identifies and maps -where the spectrum falls on each column and row of the detector. This mapping enables accurate -extraction of the one-dimensional spectrum from the two-dimensional image data. The trace effectively +where the spectrum falls on each column and row of the detector. The trace effectively accounts for any curvature or tilt in how the spectrum is projected onto the detector, which can occur due to optical effects in the spectrograph or mechanical flexure during observations. -The trace position can be determined either semi-automatically or manually depending on factors like: +The trace position can be determined either semi-automatically or manually depending on: * Data quality and signal-to-noise ratio * Spectral characteristics and features * Presence of contaminating sources or artifacts -* Wavelength coverage and dispersion direction -The module provides three main trace types to handle different observational scenarios: +The `~specreduce.tracing` module provides three main trace types to handle different scenarios: +`~specreduce.tracing.FlatTrace`, `~specreduce.tracing.FitTrace`, and +`~specreduce.tracing.ArrayTrace`. Each trace class requires the 2D spectral image as input, along +with trace-specific parameters that control how the trace is determined and fitted to the data. -* `~specreduce.tracing.ArrayTrace` - Uses a pre-defined array of positions for maximum flexibility. - Ideal for complex or unusual trace shapes that are difficult to model mathematically. +Flat trace +---------- -* `~specreduce.tracing.FlatTrace` - Assumes the spectrum follows a straight horizontal/vertical line - across the detector. Best for well-aligned spectrographs with minimal optical distortion. +`~specreduce.tracing.FlatTrace` assumes that the spectrum follows a straight line across the +detector, and is best for well-aligned spectrographs with minimal optical distortion. To +initialize a `~specreduce.tracing.FlatTrace`, we need to specify the fixed cross-dispersion +pixel position: -* `~specreduce.tracing.FitTrace` - Fits a polynomial function to automatically detected spectrum - positions. Suitable for typical spectra with smooth, continuous trace profiles. +.. code-block:: python -Each trace class requires the 2D spectral image as input, along with trace-specific parameters -that control how the trace is determined and fitted to the data. + trace = specreduce.tracing.FlatTrace(image, position=6) -Flat trace ----------- + +.. plot:: + + import numpy as np + import matplotlib.pyplot as plt + from scipy.stats import norm + + fw = 10 + nd, ncd = 31, 13 + xd, xcd = np.arange(nd), np.arange(ncd) + + spectrum = np.zeros((ncd, nd)) + spectrum[:,:] = norm(6.0, 1.5).pdf(xcd)[:, None] + + plt.rc('font', size=13) + fig, ax = plt.subplots(figsize=(fw, fw*(ncd/nd)), constrained_layout=True) + ax.imshow(spectrum, origin='lower') + ax.plot((0, nd-1), (6, 6), c='k') + ax.set_xticks(xd+0.5, minor=True) + ax.set_yticks(xcd+0.5, minor=True) + ax.grid(alpha=0.25, lw=1, which='minor') + plt.setp(ax, xlabel='Dispersion axis', ylabel='Cross-dispersion axis') + fig.show() + +FitTrace +-------- + +`~specreduce.tracing.FitTrace` fits a polynomial function to automatically detected spectrum +positions, and is suitable for typical spectra with smooth, continuous trace profiles. The trace +model can be chosen from `~astropy.modeling.polynomial.Chebyshev1D`, +`~astropy.modeling.polynomial.Legendre1D`, `~astropy.modeling.polynomial.Polynomial1D`, +or `~astropy.modeling.spline.Spline1D`, and the fitting can be optimized by binning the spectrum +along the dispersion axis. .. code-block:: python - # FlatTrace example - specify the fixed row/column position - trace = specreduce.tracing.FlatTrace(image, position=15) + trace = specreduce.tracing.FitTrace(image, bins=10, trace_model=Polynomial1D(3)) + +.. plot:: + + import numpy as np + import matplotlib.pyplot as plt + from scipy.stats import norm + plt.rc('font', size=13) + + fw = 10 + nd, ncd = 31, 13 + xd, xcd = np.arange(nd), np.arange(ncd) + + tr = np.poly1d([-0.01, 0.2, 7.0]) + spectrum = np.zeros((ncd, nd)) + for i,x in enumerate(xd): + spectrum[:,i] = norm(tr(x), 1.0).pdf(xcd) + + fig, ax = plt.subplots(figsize=(fw, fw*(ncd/nd)), constrained_layout=True) + ax.imshow(spectrum, origin='lower') + ax.plot(xd, tr(xd), 'k') + ax.set_xticks(xd+0.5, minor=True) + ax.set_yticks(xcd+0.5, minor=True) + ax.grid(alpha=0.25, lw=1, which='minor') + plt.setp(ax, xlabel='Dispersion axis', ylabel='Cross-dispersion axis') + fig.show() ArrayTrace ---------- +`~specreduce.tracing.ArrayTrace` uses a pre-defined array of positions for maximum flexibility, +and is ideal for complex or unusual trace shapes that are difficult to model mathematically. +`~specreduce.tracing.ArrayTrace` initialization requires an array of cross-dispersion pixel +positions. The size of the array must match the number of dispersion-axis pixels in the image. + .. code-block:: python - # ArrayTrace example - manual position array - positions = [14, 15, 15, 16] # pixel positions along dispersion axis trace = specreduce.tracing.ArrayTrace(image, positions) -FitTrace --------- +.. plot:: -.. code-block:: python + import numpy as np + import matplotlib.pyplot as plt + from scipy.stats import norm + plt.rc('font', size=13) + + fw = 10 + nd, ncd = 31, 13 + xd, xcd = np.arange(nd), np.arange(ncd) + + tr = np.full_like(xd, 6) + tr[:6] = 4 + tr[15:23] = 8 + + spectrum = np.zeros((ncd, nd)) - # FitTrace example - automatic detection with polynomial fitting - trace = specreduce.tracing.FitTrace(image, - order=3, # polynomial order - window=10) # pixel window for centroid + for i,x in enumerate(xd): + spectrum[:,i] = norm(tr[i], 1.0).pdf(xcd) + plt.rc('font', size=13) + fig, ax = plt.subplots(figsize=(fw, fw*(ncd/nd)), constrained_layout=True) + ax.imshow(spectrum, origin='lower') + ax.plot(xd, tr, 'k') + ax.set_xticks(xd+0.5, minor=True) + ax.set_yticks(xcd+0.5, minor=True) + ax.grid(alpha=0.25, lw=1, which='minor') + plt.setp(ax, xlabel='Dispersion axis', ylabel='Cross-dispersion axis') + fig.show() Best Practices ------------- From 239e2e4b7996e472bb48c8af5259a89c95de5c8c Mon Sep 17 00:00:00 2001 From: Hannu Parviainen Date: Sat, 21 Jun 2025 22:03:49 +0100 Subject: [PATCH 07/12] Revised extraction_quickstart.rst. --- docs/extraction_quickstart.rst | 57 ++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/docs/extraction_quickstart.rst b/docs/extraction_quickstart.rst index febd4198..85f1dd04 100644 --- a/docs/extraction_quickstart.rst +++ b/docs/extraction_quickstart.rst @@ -24,7 +24,9 @@ Supported trace types include: Each of these trace classes takes the 2D spectral image as input, as well as additional information needed to define or determine the trace (see the API docs -above for required parameters for each of the available trace classes):: +above for required parameters for each of the available trace classes) + +.. code-block:: python trace = specreduce.tracing.FlatTrace(image, 15) @@ -45,16 +47,18 @@ defined by one or more windows, and can be generated with: * `Background.one_sided ` * `Background.two_sided ` -The center of the window can either be passed as a float/integer or as a trace:: +The center of the window can either be passed as a float/integer or as a trace + +.. code-block:: python bg = specreduce.background.Background.one_sided(image, trace, separation=5, width=2) +or, equivalently -or, equivalently:: +.. code-block:: python bg = specreduce.background.Background.one_sided(image, 15, separation=5, width=2) - The background image can be accessed via `~specreduce.background.Background.bkg_image` and the background-subtracted image via `~specreduce.background.Background.sub_image` (or ``image - bg``). @@ -73,23 +77,29 @@ window, using one of the following implemented methods: * `~specreduce.extract.HorneExtract` Each of these takes the input image and trace as inputs (see the API above for -other required and optional parameters):: +other required and optional parameters) + +.. code-block:: python extract = specreduce.extract.BoxcarExtract(image-bg, trace, width=3) -or:: +or + +.. code-block:: python extract = specreduce.extract.HorneExtract(image-bg, trace) For the Horne algorithm, the variance array is required. If the input image is -an ``astropy.NDData`` object with ``image.uncertainty`` provided, -then this will be used. Otherwise, the ``variance`` parameter must be set.:: +an ``~astropy.nddata.NDData`` object with ``image.uncertainty`` provided, +then this will be used. Otherwise, the ``variance`` parameter must be set. + +.. code-block:: python extract = specreduce.extract.HorneExtract(image-bg, trace, variance=var_array) An optional mask array for the image may be supplied to HorneExtract as well. This follows the same convention and can either be attached to ``image`` if it -is an ``astropy.NDData`` object, or supplied as a keyword argument. +is an ``~astropy.nddata.NDData`` object, or supplied as a keyword argument. The extraction methods automatically detect non-finite pixels in the input image and combine them with the user-supplied mask to prevent them from biasing the @@ -102,17 +112,24 @@ differently as documented in the API. The previous examples in this section show how to initialize the BoxcarExtract or HorneExtract objects with their required parameters. To extract the 1D -spectrum:: +spectrum + +.. code-block:: python spectrum = extract.spectrum The ``extract`` object contains all the set options. The extracted 1D spectrum can be accessed via the ``spectrum`` property or by calling (e.g ``extract()``) -the ``extract`` object (which also allows temporarily overriding any values):: +the ``extract`` object (which also allows temporarily overriding any values) + +.. code-block:: python spectrum2 = extract(width=6) -or, for example to override the original ``trace_object``:: +or, for example to override the original ``trace_object`` + +.. code-block:: python + spectrum2 = extract(trace_object=new_trace) Spatial profile options @@ -138,16 +155,22 @@ and to use the defaults for bins and interpolation degree, or to override these defaults a dictionary can be passed in. For example, to use the ``interpolated_profile`` option with default bins and -interpolation degree:: +interpolation degree + +.. code-block:: python interp_profile_extraction = extract(spatial_profile='interpolated_profile') -Or, to override the default of 10 samples and use 20 samples:: +Or, to override the default of 10 samples and use 20 samples + +.. code-block:: python interp_profile_extraction = extract(spatial_profile={'name': 'interpolated_profile', 'n_bins_interpolated_profile': 20) -Or, to do a cubic interpolation instead of the default linear:: +Or, to do a cubic interpolation instead of the default linear + +.. code-block:: python interp_profile_extraction = extract(spatial_profile={'name': 'interpolated_profile', 'interp_degree_interpolated_profile': 3) @@ -163,7 +186,9 @@ wavelength units will be pixels. Wavelength and flux calibration steps are not included here. Putting all these steps together, a simple extraction process might look -something like:: +something like + +.. code-block:: python from specreduce.tracing import FlatTrace from specreduce.background import Background From e00957b040a60ab1793bf5ff5b0e505258476801 Mon Sep 17 00:00:00 2001 From: Hannu Parviainen Date: Sat, 21 Jun 2025 22:11:03 +0100 Subject: [PATCH 08/12] Cleaned up and revised the documentation. --- docs/contributing.rst | 3 +++ docs/extraction.rst | 4 ++-- docs/extraction_quickstart.rst | 2 +- docs/index.rst | 3 +-- docs/wavelength_calibration.rst | 12 +++++++++--- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/docs/contributing.rst b/docs/contributing.rst index 989e0e6d..af621423 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -1,6 +1,9 @@ Contributing ============ +Please feel free to contribute code and suggestions through `GitHub. `_ + .. toctree:: :maxdepth: 1 diff --git a/docs/extraction.rst b/docs/extraction.rst index a35a68ca..de1e6d50 100644 --- a/docs/extraction.rst +++ b/docs/extraction.rst @@ -22,7 +22,7 @@ or extract = specreduce.extract.HorneExtract(image-bg, trace) For the Horne algorithm, the variance array is required. If the input image is -an ``astropy.NDData`` object with ``image.uncertainty`` provided, +an `~astropy.nddata.NDData` object with ``image.uncertainty`` provided, then this will be used. Otherwise, the ``variance`` parameter must be set. .. code-block:: python @@ -31,7 +31,7 @@ then this will be used. Otherwise, the ``variance`` parameter must be set. An optional mask array for the image may be supplied to HorneExtract as well. This follows the same convention and can either be attached to ``image`` if it -is an ``astropy.NDData`` object, or supplied as a keyword argument. +is an `~astropy.nddata.NDData` object, or supplied as a keyword argument. The extraction methods automatically detect non-finite pixels in the input image and combine them with the user-supplied mask to prevent them from biasing the diff --git a/docs/extraction_quickstart.rst b/docs/extraction_quickstart.rst index 85f1dd04..48158407 100644 --- a/docs/extraction_quickstart.rst +++ b/docs/extraction_quickstart.rst @@ -90,7 +90,7 @@ or extract = specreduce.extract.HorneExtract(image-bg, trace) For the Horne algorithm, the variance array is required. If the input image is -an ``~astropy.nddata.NDData`` object with ``image.uncertainty`` provided, +an `~astropy.nddata.NDData` object with ``image.uncertainty`` provided, then this will be used. Otherwise, the ``variance`` parameter must be set. .. code-block:: python diff --git a/docs/index.rst b/docs/index.rst index e58f702d..80386f88 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -9,8 +9,7 @@ specific instruments can be built. The scope of its functionality is limited to reduction, currently encompassing the following tasks: #. **2D tilt model calculation and correction:** A 2D tilt model can be calculated from arc - spectra. Tilt correction removes the wavelength curvature along the cross-dispersion axis, - + spectra. Tilt correction removes the wavelength curvature along the cross-dispersion axis. #. **1D wavelength calibration:** from arc spectra. #. **Spectrum trace determination:** Determining the trace of a spectrum dispersed in a 2D image, either by setting a flat diff --git a/docs/wavelength_calibration.rst b/docs/wavelength_calibration.rst index f2b77ef6..45921352 100644 --- a/docs/wavelength_calibration.rst +++ b/docs/wavelength_calibration.rst @@ -18,7 +18,9 @@ The `~specreduce.wavelength_calibration.WavelengthCalibration1D` class can be us to fit a dispersion model to a list of line positions and wavelengths. Future development will implement catalogs of known lamp spectra for use in matching observed lines. In the example below, the line positions (``pixel_centers``) have already been extracted from -``lamp_spectrum``:: +``lamp_spectrum`` + +.. code-block:: python import astropy.units as u from specreduce import WavelengthCalibration1D @@ -34,7 +36,9 @@ spectrum (``science_spectrum``). Any other 1D ``astropy`` model can be provided input ``model`` parameter to the `~specreduce.wavelength_calibration.WavelengthCalibration1D`. In the above example, the model fit and WCS construction is all done as part of the ``apply_to_spectrum()`` call, but you could also access the `~gwcs.wcs.WCS` object itself -by calling:: +by calling + +.. code-block:: python test_cal.wcs @@ -44,7 +48,9 @@ fit. You can also provide the input pixel locations and wavelengths of the lines as an `~astropy.table.QTable` with (at minimum) columns ``pixel_center`` and ``wavelength``, -using the ``matched_line_list`` input argument:: +using the ``matched_line_list`` input argument + +.. code-block:: python from astropy.table import QTable pixels = [10, 20, 30, 40]*u.pix From afb7904d560bed6f38b932f5aeb4b72dde3e9e28 Mon Sep 17 00:00:00 2001 From: Hannu Parviainen Date: Sat, 21 Jun 2025 23:30:06 +0100 Subject: [PATCH 09/12] Revised the tracing documentation. --- docs/index.rst | 5 +-- docs/trace.rst | 86 +++++++++++++++++++++++++++----------------------- 2 files changed, 50 insertions(+), 41 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 80386f88..0caced44 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,9 +1,10 @@ +.. _docroot: + ######################## Specreduce Documentation ######################## -The `specreduce `_ package -aims to provide a data reduction toolkit for optical +The :ref:`specreduce ` package aims to provide a data reduction toolkit for optical and infrared spectroscopy, on which applications such as pipeline processes for specific instruments can be built. The scope of its functionality is limited to basic spectroscopic reduction, currently encompassing the following tasks: diff --git a/docs/trace.rst b/docs/trace.rst index 362799ec..7bb86063 100644 --- a/docs/trace.rst +++ b/docs/trace.rst @@ -1,22 +1,11 @@ Tracing ======= -The `specreduce.tracing` module defines the spatial position (trace) of a spectrum across a 2D -detector image. In spectroscopic data reduction, tracing is a critical step that identifies and maps -where the spectrum falls on each column and row of the detector. The trace effectively -accounts for any curvature or tilt in how the spectrum is projected onto the detector, which can -occur due to optical effects in the spectrograph or mechanical flexure during observations. - -The trace position can be determined either semi-automatically or manually depending on: - -* Data quality and signal-to-noise ratio -* Spectral characteristics and features -* Presence of contaminating sources or artifacts - -The `~specreduce.tracing` module provides three main trace types to handle different scenarios: -`~specreduce.tracing.FlatTrace`, `~specreduce.tracing.FitTrace`, and -`~specreduce.tracing.ArrayTrace`. Each trace class requires the 2D spectral image as input, along -with trace-specific parameters that control how the trace is determined and fitted to the data. +The `specreduce.tracing` module provides three ``Trace`` classes that are used to define the +spatial position (trace) of a spectrum across a 2D detector image: `~specreduce.tracing.FlatTrace`, +`~specreduce.tracing.FitTrace`, and `~specreduce.tracing.ArrayTrace`. Each trace class requires +the 2D spectral image as input, along with trace-specific parameters that control how the trace +is determined. Flat trace ---------- @@ -28,7 +17,7 @@ pixel position: .. code-block:: python - trace = specreduce.tracing.FlatTrace(image, position=6) + trace = specreduce.tracing.FlatTrace(image, trace_pos=6) .. plot:: @@ -93,6 +82,47 @@ along the dispersion axis. plt.setp(ax, xlabel='Dispersion axis', ylabel='Cross-dispersion axis') fig.show() +The method works by (optionally) binning the 2D spectrum along the dispersion axis, finding +the PSF peak position along the cross-dispersion for each bin, and then fitting a 1D polynomial to +the cross-dispersion and dispersion axis positions. Binning is optional, and the native image +resolution is used by default. Binning can significantly increase the reliability of the fitting +with low SNR spectra, and always increases the speed. + +The peak detection method can be chosen from ``max``, ``centroid``, and ``gaussian``. Of these +methods, ``max`` is the fastest but yields an integer pixel precision. Both ``centroid`` and +``gaussian`` can be used when sub-pixel precision is required, and ``gaussian``, while being the +slowest method of the three, is the best option if the data is significantly contaminated by +non-finite values. + +.. plot:: + + import numpy as np + import matplotlib.pyplot as plt + from scipy.stats import norm + from numpy.random import seed, normal + from astropy.modeling.models import Gaussian1D + from astropy.modeling.fitting import DogBoxLSQFitter + plt.rc('font', size=13) + seed(5) + + fw = 10 + nd, ncd = 31, 13 + xd, xcd = np.arange(nd), np.arange(ncd) + + psf = norm(5.4, 1.5).pdf(xcd) + normal(0, 0.01, ncd) + fitter = DogBoxLSQFitter() + m = fitter(Gaussian1D(), xcd, psf) + + fig, ax = plt.subplots(figsize=(fw, fw*(ncd/nd)), constrained_layout=True) + ax.step(xcd, psf, where='mid', c='k') + ax.axvline(xcd[np.argmax(psf)], label='max') + ax.axvline(np.average(xcd, weights=psf), ls='--', label='centroid') + ax.axvline(m.mean.value, ls=':', label='gaussian') + ax.plot(xcd, m(xcd), ls=':') + ax.legend() + plt.setp(ax, yticks=[], ylabel='Flux', xlabel='Cross-dispersion axis [pix]', xlim=(0, ncd-1)) + fig.show() + ArrayTrace ---------- @@ -134,25 +164,3 @@ positions. The size of the array must match the number of dispersion-axis pixels ax.grid(alpha=0.25, lw=1, which='minor') plt.setp(ax, xlabel='Dispersion axis', ylabel='Cross-dispersion axis') fig.show() - -Best Practices -------------- - -When selecting and configuring a trace method, consider these guidelines: - -* For bright, well-defined spectra: - - `FitTrace` with default parameters usually works well - - Larger ``window`` values can improve centroid accuracy - - Higher polynomial orders can better follow any curvature - -* For noisy or faint spectra: - - Reduce the ``window`` parameter to minimize impact of background noise - - Lower the polynomial ``order`` to prevent overfitting - - Consider using `FlatTrace` for very faint spectra - - Mask cosmic rays or bad pixels before tracing - - Pre-process images to improve signal-to-noise if needed - -* For unusual or complex traces: - - Use `ArrayTrace` with manually determined positions - - Consider breaking the trace into segments - - Validate trace positions visually before extraction \ No newline at end of file From fab9754b96706cfd139f8f172d792f16c918d342 Mon Sep 17 00:00:00 2001 From: Hannu Parviainen Date: Tue, 24 Jun 2025 09:21:49 -0700 Subject: [PATCH 10/12] Revised index.rst. --- docs/index.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index 0caced44..5c96bdf1 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -9,13 +9,14 @@ and infrared spectroscopy, on which applications such as pipeline processes for specific instruments can be built. The scope of its functionality is limited to basic spectroscopic reduction, currently encompassing the following tasks: -#. **2D tilt model calculation and correction:** A 2D tilt model can be calculated from arc - spectra. Tilt correction removes the wavelength curvature along the cross-dispersion axis. -#. **1D wavelength calibration:** from arc spectra. #. **Spectrum trace determination:** Determining the trace of a spectrum dispersed in a 2D image, either by setting a flat trace, providing a custom trace array, or fitting a spline, polynomial, or other model to the positions of the dispersed spectrum. +#. **2D tilt correction:** Calculating a 2D tilt model from arc spectra and applying it to + correct the wavelength curvature along the cross-dispersion axis. +#. **1D wavelength calibration:** Calculating a 1D wavelength solution from arc spectra and line + lists. #. **Background subtraction:** Generating a background based on a region on one or both sides of this trace, and making available the background image, 1D spectrum of the background, and the From 2a9208d8e573f470a91c468ffa19e3662a0f4cef Mon Sep 17 00:00:00 2001 From: Hannu Parviainen Date: Wed, 25 Jun 2025 14:52:51 -0700 Subject: [PATCH 11/12] Added `sphinx-copybutton` to documentation dependencies in `pyproject.toml`. --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 52565e49..1fc5c3d0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,6 +24,7 @@ test = [ ] docs = [ "sphinx-astropy", + "sphinx-copybutton", "matplotlib>=3.7", "photutils>=1.0", "synphot", From 7ee2d1650ea97fb642b7b6dcfc69a2e41335191a Mon Sep 17 00:00:00 2001 From: Hannu Parviainen Date: Wed, 25 Jun 2025 14:56:31 -0700 Subject: [PATCH 12/12] Updated `sphinx-astropy` dependency to use `confv2` in `pyproject.toml`. --- pyproject.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1fc5c3d0..20f18f5e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,8 +23,7 @@ test = [ "tox", ] docs = [ - "sphinx-astropy", - "sphinx-copybutton", + "sphinx-astropy[confv2]", "matplotlib>=3.7", "photutils>=1.0", "synphot",