pax_global_header00006660000000000000000000000064151053725030014513gustar00rootroot0000000000000052 comment=05be8282c706f8bef2279858ea5e3d29f20c5bfe astropy-specreduce-05be828/000077500000000000000000000000001510537250300156735ustar00rootroot00000000000000astropy-specreduce-05be828/.flake8000066400000000000000000000000371510537250300170460ustar00rootroot00000000000000[flake8] max-line-length = 100 astropy-specreduce-05be828/.github/000077500000000000000000000000001510537250300172335ustar00rootroot00000000000000astropy-specreduce-05be828/.github/dependabot.yml000066400000000000000000000011171510537250300220630ustar00rootroot00000000000000# To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates version: 2 updates: - package-ecosystem: "github-actions" # See documentation for possible values directory: ".github/workflows" # Location of package manifests schedule: interval: "monthly" groups: actions: patterns: - "*" astropy-specreduce-05be828/.github/workflows/000077500000000000000000000000001510537250300212705ustar00rootroot00000000000000astropy-specreduce-05be828/.github/workflows/cron-tests.yml000066400000000000000000000021211510537250300241100ustar00rootroot00000000000000# GitHub Actions workflow for testing and continuous integration. # # This file performs testing using tox and tox.ini to define and configure the test environments. name: Weekly Tests on: pull_request: # We also want this workflow triggered if the 'Extra CI' label is added # or present when PR is updated types: - synchronize - labeled schedule: # run every Monday at 6am UTC - cron: '0 6 * * 1' concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: tests: if: (github.repository == 'astropy/specreduce' && (github.event_name == 'schedule' || github.event_name == 'push' || contains(github.event.pull_request.labels.*.name, 'Extra CI'))) uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@d9b81a07e789d1b1921ab5fe33de2ddcbbd02c3f # v2.3.0 with: submodules: false coverage: '' envs: | - name: Check URLs in docs linux: linkcheck - name: Python 3.12 on Linux with pre-releases linux: py312-test-alldeps-predeps toxargs: -v astropy-specreduce-05be828/.github/workflows/publish-to-pypi.yml000066400000000000000000000011341510537250300250570ustar00rootroot00000000000000name: Release on: pull_request: push: tags: - '*' jobs: publish: uses: OpenAstronomy/github-actions-workflows/.github/workflows/publish_pure_python.yml@d9b81a07e789d1b1921ab5fe33de2ddcbbd02c3f # v2.3.0 # NOTE: Uncomment "if" if you do not want this to run for every PR. # if: ((github.event_name == 'push' && startsWith(github.ref, 'refs/tags')) || contains(github.event.pull_request.labels.*.name, 'Build wheels')) with: test_extras: test test_command: pytest $GITHUB_WORKSPACE/specreduce/tests secrets: pypi_token: ${{ secrets.PYPI_API_TOKEN }} astropy-specreduce-05be828/.github/workflows/tox-tests.yml000066400000000000000000000027571510537250300240000ustar00rootroot00000000000000# GitHub Actions workflow for testing and continuous integration. # # This file performs testing using tox and tox.ini to define and configure the test environments. name: Python Tests on: push: branches: - main tags: - '*' pull_request: schedule: # run every Monday at 6am UTC - cron: '0 6 * * 1' workflow_dispatch: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: tests: uses: OpenAstronomy/github-actions-workflows/.github/workflows/tox.yml@d9b81a07e789d1b1921ab5fe33de2ddcbbd02c3f # v2.3.0 secrets: CODECOV_TOKEN: ${{ secrets.CODECOV }} with: submodules: false coverage: '' envs: | - name: Codestyle linux: codestyle - name: Python 3.11 on Windows with oldest supported dependencies windows: py311-test-oldestdeps toxargs: -v - name: Python 3.11 on OSX with minimal dependencies macos: py311-test toxargs: -v - name: Python 3.12 on Linux with minimal dependencies linux: py312-test toxargs: -v - name: Python 3.13 on Linux with all dependencies, remote data, and coverage linux: py313-test-alldeps-cov coverage: codecov toxargs: -v posargs: --remote-data=any - name: (Allowed Failure) Python 3.13 on Linux with dev dependencies linux: py313-test-devdeps-cov coverage: codecov toxargs: -v astropy-specreduce-05be828/.gitignore000066400000000000000000000013371510537250300176670ustar00rootroot00000000000000# Compiled files *.py[cod] *.a *.o *.so __pycache__ # Ignore .c files by default to avoid including generated code. If you want to # add a non-generated .c extension, use `git add -f filename.c`. *.c # Other generated files */version.py */cython_version.py htmlcov .coverage MANIFEST .ipynb_checkpoints # Sphinx docs/api docs/_build # Eclipse editor project files .project .pydevproject .settings .vscode/ # Pycharm editor project files .idea # Floobits project files .floo .flooignore # Packages/installer info .eggs/ *.egg *.egg-info dist build eggs parts bin var sdist develop-eggs .installed.cfg distribute-*.tar.gz # Other .cache .tox .*.sw[op] *~ .project .pydevproject .settings pip-wheel-metadata/ # Mac OSX .DS_Store astropy-specreduce-05be828/.readthedocs.yaml000066400000000000000000000004501510537250300211210ustar00rootroot00000000000000version: 2 build: os: ubuntu-22.04 apt_packages: - graphviz tools: python: "3.13" sphinx: builder: html configuration: docs/conf.py fail_on_warning: true python: install: - method: pip path: . extra_requirements: - docs - all formats: [] astropy-specreduce-05be828/CHANGES.rst000066400000000000000000000175131510537250300175040ustar00rootroot000000000000001.7.0 (2025-11-13) ------------------ New Features ^^^^^^^^^^^^ - Added a new ``specreduce.wavecal1d.WavelengthCalibration1D`` class for one-dimensional wavelength calibration. The old ``specreduce.wavelength_calibration.WavelengthCalibration1D`` is deprecated and will be removed in v. 2.0. - Added a ``disp_bounds`` argument to ``tracing.FitTrace``. The argument allows for adjusting the dispersion-axis window from which the trace peaks are estimated. 1.6.0 (2025-06-18) ------------------ Bug Fixes ^^^^^^^^^ - When all-zero bin encountered in fit_trace with peak_method=gaussian, the bin peak will be set to NaN in this case to work better with DogBoxLSQFitter. [#257] - Reverted the changes to ``background.Background.bgk_spectrum`` introduced in 1.5.0 [#266]. Other changes ^^^^^^^^^^^^^ - Compatibility with specutils 2.0. [#260] - Set Python 3.11 as the minimum supported Python version and added test support for Python 3.13. [#271] - Changed the ``statistic`` parameter in ``utils.measure_cross_dispersion_profile`` to accept either ``median`` or ``average`` instead of ``median`` or ``mean``. [#258] 1.5.1 (2025-03-08) ------------------ Bug Fixes ^^^^^^^^^ - Changed Horne extraction to behave as before when using an interpolated spatial profile and not explicitly setting `bkgrd_prof` to `None`. The changed default behavior in 1.5.0 caused problems in codes using specreduce. [#256] 1.5.0 (2025-03-06) ------------------ New Features ^^^^^^^^^^^^ - Added the ``mask_treatment`` parameter to Background, Trace, and Boxcar Extract operations to handle non-finite data and boolean masks. Available options are ``apply``, ``ignore``, ``propagate``, ``zero_fill``, ``nan_fill``, ``apply_mask_only``, or ``apply_nan_only``. [#216, #254] - Modified ``background.Background.bgk_spectrum`` to allow the user to select the statistic used for background estimation between ``median`` or ``average``. [#253] - Modified ``extract.BoxcarExtract`` to ignore non-finite pixels when ``mask_treatment`` is set to ``apply``; otherwise, non-finite values are propagated. Boxcar extraction is now carried out as a weighed sum over the window. When no non-finite values are present, the extracted spectra remain unchanged from the previous behaviour. Bug Fixes ^^^^^^^^^ - Fixed Astropy v7.0 incompatibility bug in ``tracing.FitTrace``: changed to use ``astropy.modeling.fitting.DogBoxLSQFitter`` when fitting a Gaussian peak model instead of ``astropy.modeling.fitting.LevMarLSQFitter`` that may be deprecated in the future. Also changed to use ``fitting.LMLSQFitter`` instead of ``fitting.LevMarLSQFitter`` when fitting a generic nonlinear trace model. [#229] Other changes ^^^^^^^^^^^^^ - Changed ``tracing.FitTrace`` to use ``astropy.modeling.fitting.LinearLSQFitter`` if the trace model is linear. 1.4.1 (2024-06-20) ------------------ Bug Fixes ^^^^^^^^^ - Fix bug where Background one sided / two sided was not correctly assigning units to data. [#221] 1.4.0 (2024-05-29) ------------------ New Features ^^^^^^^^^^^^ - Added 'interpolated_profile' option for HorneExtract. 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 the ``interp_degree_interpolated_profile`` parameter) to generate a continuously varying spatial profile that can be evaluated at any wavelength. [#173] - Added a function to measure a cross-dispersion profile. A profile can be obtained at a single pixel/wavelength, or an average profile can be obtained from a range/set of wavelengths. [#214] API Changes ^^^^^^^^^^^ - Fit residuals exposed for wavelength calibration in ``WavelengthCalibration1D.fit_residuals``. [#446] Bug Fixes ^^^^^^^^^ - Output 1D spectra from Background no longer include NaNs. Output 1D spectra from BoxcarExtract no longer include NaNs when none are present in the extraction window. NaNs in the window will still propagate to BoxcarExtract's extracted 1D spectrum. [#159] - Backgrounds using median statistic properly ignore zero-weighted pixels. [#159] - HorneExtract now accepts 'None' as a vaild option for ``bkgrd_prof``. [#171] - Fix in FitTrace to set fully-masked column bin peaks to NaN. Previously, for peak_method='max' these were set to 0.0, and for peak_method='centroid' they were set to the number of rows in the image, biasing the final fit to all bin peaks. Previously for Gaussian, the entire fit failed. [#205, #206] - Fixed input of `traces` in `Background`. Added a condition to 'FlatTrace' that trace position must be a positive number. [#211] Other changes ^^^^^^^^^^^^^ - The following packages are now optional dependencies because they are not required for core functionality: ``matplotlib``, ``photutils``, ``synphot``. To install them anyway, use the ``[all]`` specifier when you install specreduce; e.g.: ``pip install specreduce[all]`` [#202] 1.3.0 (2022-12-05) ------------------ New Features ^^^^^^^^^^^^ - The new FitTrace class (see "API Changes" below) introduces the ability to take a polynomial trace of an image [#128] API Changes ^^^^^^^^^^^ - Renamed KosmosTrace as FitTrace, a conglomerate class for traces that are fit to images instead of predetermined [#128] - The default number of bins for FitTrace is now its associated image's number of dispersion pixels instead of 20. Its default peak_method is now 'max' [#128] - All operations now accept Spectrum1D and Quantity-type images. All accepted image types are now processed internally as Spectrum1D objects [#144, #154] - All operations' ``image`` attributes are now coerced Spectrum1D objects [#144, #154] - HorneExtract can now handle non-flat traces [#148] Bug Fixes ^^^^^^^^^ - Fixed passing a single ``Trace`` object to ``Background`` [#146] - Moved away from creating image masks with numpy's ``mask_invalid()`` function after change to upstream API. This will make specreduce be compatible with numpy 1.24 or later. [#155] 1.2.0 (2022-10-04) ------------------ New Features ^^^^^^^^^^^^ - ``Background`` has new methods for exposing the 1D spectrum of the background or background-subtracted regions [#143] Bug Fixes ^^^^^^^^^ - Improved errors/warnings when background region extends beyond bounds of image [#127] - Fixed boxcar weighting bug that often resulted in peak pixels having weight above 1 and erroneously triggered overlapping background errors [#125] - Fixed boxcar weighting to handle zero width and edge of image cases [#141] 1.1.0 (2022-08-18) ------------------ New Features ^^^^^^^^^^^^ - ``peak_method`` as an optional argument to ``KosmosTrace`` [#115] API Changes ^^^^^^^^^^^ - ``HorneExtract`` no longer requires ``mask`` and ``unit`` arguments [#105] - ``BoxcarExtract`` and ``HorneExtract`` now accept parameters (and require the image and trace) at initialization, and allow overriding any input parameters when calling [#117] Bug Fixes ^^^^^^^^^ - Corrected the default mask created in ``HorneExtract``/``OptimalExtract`` when a user doesn't specify one and gives their image as a numpy array [#118] 1.0.0 (2022-03-29) ------------------ New Features ^^^^^^^^^^^^ - Added ``Trace`` classes - Added basic synthetic data routines - Added ``BoxcarExtract`` - Added ``HorneExtract``, a.k.a. ``OptimalExtract`` - Added basic ``Background`` subtraction Bug Fixes ^^^^^^^^^ - Update ``codecov-action`` to ``v2`` - Change default branch from ``master`` to ``main`` - Test fixes; bump CI to python 3.8 and 3.9 and deprecate support for 3.7 astropy-specreduce-05be828/CITATION.cff000077500000000000000000000024511510537250300175720ustar00rootroot00000000000000# This CITATION.cff file was generated with cffinit. # Visit https://bit.ly/cffinit to generate yours today! cff-version: 1.2.0 title: Specreduce message: >- If you use Specreduce for work/research presented in a publication (whether directly, or as a dependency to another package), please cite the Zenodo DOI for the appropriate version of Specreduce. type: software authors: - given-names: Timothy family-names: Pickering email: te.pickering@gmail.com affiliation: MMT Observatory orcid: 'https://orcid.org/0000-0002-9427-5448' - given-names: Kyle family-names: Conroy affiliation: STScI orcid: 'https://orcid.org/0000-0002-5442-8550' - given-names: O. Justin family-names: Otor affiliation: Space Telescope Science Institute orcid: 'https://orcid.org/0000-0002-4679-5692' - given-names: Erik family-names: Tollerud email: erik.tollerud@gmail.com affiliation: Space Telescope Science Institute orcid: 'https://orcid.org/0000-0002-9599-310X' - given-names: Clare family-names: Shanahan email: cshanahan@stsci.edu affiliation: Space Telescope Science Institute orcid: 'https://orcid.org/0009-0008-4112-7418X' identifiers: - type: doi value: 10.5281/zenodo.6608788 description: 'Version 1.0.0: First Official Release' astropy-specreduce-05be828/MANIFEST.in000066400000000000000000000002721510537250300174320ustar00rootroot00000000000000include README.rst include CHANGES.rst include pyproject.toml recursive-include docs * recursive-include licenses * prune notebook_sandbox prune build prune docs/_build prune docs/api astropy-specreduce-05be828/README.rst000066400000000000000000000022041510537250300173600ustar00rootroot00000000000000Specreduce ========== .. image:: https://github.com/astropy/specreduce/actions/workflows/tox-tests.yml/badge.svg?branch=main :target: https://github.com/astropy/specreduce/actions/workflows/tox-tests.yml :alt: CI Status .. image:: https://codecov.io/gh/astropy/specreduce/graph/badge.svg?token=3fLGjZ2Pe0 :target: https://codecov.io/gh/astropy/specreduce :alt: Coverage .. image:: https://readthedocs.org/projects/specreduce/badge/?version=latest :target: http://specreduce.readthedocs.io/en/latest/ :alt: Documentation Status .. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.6608787.svg :target: https://zenodo.org/doi/10.5281/zenodo.6608787 :alt: Zenodo DOI 10.5281/zenodo.6608787 .. image:: http://img.shields.io/badge/powered%20by-AstroPy-orange.svg?style=flat :target: http://www.astropy.org/ :alt: Powered by Astropy Specreduce is an Astropy coordinated package with the goal of providing a shared set of Python utilities that can be used to reduce and calibrate spectroscopic data. License ------- Specreduce is licensed under a 3-clause BSD style license. Please see the licenses/LICENSE.rst file. astropy-specreduce-05be828/conftest.py000066400000000000000000000016221510537250300200730ustar00rootroot00000000000000# Root level conftest.py is only for nice pytest header when using tox. try: from pytest_astropy_header.display import PYTEST_HEADER_MODULES, TESTED_VERSIONS ASTROPY_HEADER = True except ImportError: ASTROPY_HEADER = False def pytest_configure(config): if ASTROPY_HEADER: config.option.astropy_header = True # Customize the following lines to add/remove entries from the list of # packages for which version numbers are displayed when running the tests. PYTEST_HEADER_MODULES.pop('Pandas', None) PYTEST_HEADER_MODULES.pop('h5py', None) PYTEST_HEADER_MODULES['astropy'] = 'astropy' PYTEST_HEADER_MODULES['specutils'] = 'specutils' PYTEST_HEADER_MODULES['photutils'] = 'photutils' PYTEST_HEADER_MODULES['synphot'] = 'synphot' from specreduce import __version__ TESTED_VERSIONS["specreduce"] = __version__ astropy-specreduce-05be828/docs/000077500000000000000000000000001510537250300166235ustar00rootroot00000000000000astropy-specreduce-05be828/docs/Makefile000066400000000000000000000107451510537250300202720ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest #This is needed with git because git doesn't create a dir if it's empty $(shell [ -d "_static" ] || mkdir -p _static) help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" clean: -rm -rf $(BUILDDIR) -rm -rf api -rm -rf generated html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Astropy.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Astropy.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/Astropy" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Astropy" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." make -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: @echo "Run 'python setup.py test' in the root directory to run doctests " \ @echo "in the documentation." astropy-specreduce-05be828/docs/_static/000077500000000000000000000000001510537250300202515ustar00rootroot00000000000000astropy-specreduce-05be828/docs/_static/logo_icon.ico000066400000000000000000000104761510537250300227250ustar00rootroot00000000000000  (( @   ߿߾Oضn}ڷsٵpڹx׳iZ۶s*Uյo7Գiٺ|ʍtypɆ͏uڷsٶpݽŒ#̙fUͰg׷mݻm׹xؽұjѮ[ǚհbضrߺn̍ݼֱgֵcU yϴrϴoԺ~бiؾӰb׹{ضs‹ݿ}ڹzܽtUθ~ԢѺѻѺƘеp׾ؾؽǗœڿϒ‹Ȥ@ĬcԺjι~Ī^ī`ĩ\ʱoй5”Լ˫[ͮcԹ}ӷwϯcҳmѯcȇپϟ8 êd3Įcd̺bìeªaȲr͹OǭbϯƩS˯iҺѸ{̯fˬ]ίfջ‚бhع|!Sư][Ƕ{X[Vïkdzsìgϰ5=ū`ζy̳rȬaƝ˯gжwзwԴdήe㴇̿s²r²s̾±ròt±qɹʹ˜Ɲí_Ưgʵw͸z̩Էк}϶xăӼgHĵrmpȼnpmƷĴvҷƶ}cƳtŰoϿȴr͸zѾ˴tͶzĀθz}TtVOSvPTNiUDOбijyFƴx]ƱmDzrXë_¨ZϺҿ(U[UYyVYTl`1dŠ?Ĵy°pʹűq^d_ćưnULPJOrKOJ^nԽ dpֿoõ}bV[Uȶz¬c7.cmfhfhgm™ǤT{sN|Şϱбrorm̾ijthvnfifijcպa{obsѴźmprnʽǸ{m⟟@>NFBGmCGI*8F_U l?BDRSLt[U\:M!IKNqKNNCSaho¡)NWYSxa]ZnCǛACj>D4dĦHUkSHOHqWRObroliqU̱ekvKy5ӻmupüz¹yujKHnGA "YOat=$6YNu]WUTftXcF;QeBAF;AbZ{fbbƩPBE?Tg?DCͳ.Sƨd׻I'_*91J`.?.=K8>8L¤˯ŧЯɮqRHHWqy\c_m|^e_}v`g`{mEOGrYJ2UєSH[iDMHZlGPGicJRJhjSZTwd\UYf}0၎*HX{%5~,G])9*YQ.;.XV1=4eL)^@Iy+ՐN[y+9}1I^~.3ZX5A7kM@O^w(|6y-G\z+9|+YQ/;/XV2=8brUfl`c\ky[b[wq]d^vu`ifh1@v7v1s)H]r%z6u'VNx+~8y*UU099@f3fu#IUs'~6y%YPz)8}*QUsY@@u00x1bnUKr$v1w/g@,astropy-specreduce-05be828/docs/_static/logo_icon.png000066400000000000000000001712661510537250300227440ustar00rootroot00000000000000PNG  IHDR9JgAMA a cHRMz&u0`:pQ<eXIfMM*JR(iZ,,K pHYs.#.#x?vYiTXtXML:com.adobe.xmp 1 ^@IDATx ]E?~{/BJBXPpTEg>? ("8aOD23ttVe\q6q]pA@VYd [^u>]]]}-IN'VuշUݷwZmkgvhgvhgvhgvhg`Bg3d 3l֭:t3\u9Ӧufm*fGͽiud<4Ӟ{_<>.3 @aH8`;vg,m޼KSR.EYfYJx˚MlŽ?~ƢS<^' ;Nѻ}Ϳ׭{$m7#[ߐ303p2mc V :+{`EWa7zb(fݮ1WLdsf1$\IFQTMYPpžPm --Enw{0 ƶ8SVwVsbyp@"[ь܊`(v\74R{O喢ۻ6ouԋ"];Q;E-xusGf> ͹su6/ włmN'g z_;F򞛋^:ser]gsy-Wby30,jg`}_24\hw+7~MZᱝ"e30A3_V m2Boyh9(`9AiΆ!*d+ xt]^N_ݑonONB23?SĶv;wCMל_a6d C>5V3u~|< ߵ7o_mT ]`og`Kp;z9t2ϻ>1|̍mp/ĿK}޽*>ޓ NsX2Q(B&omCđw]S>5ONO hm71qsfXu{zךlm!6 [!M5 fybKg7 D@aLl>]LsG'ÁW0Vxtg O- ^Pghh8q \(~|~$Uy c' uۯy O=}Ʊsg} 68ņٰGxt'&Jd Q4|։'/7>0Ǥ!7]pykG{_kҎ\&[bA'ȉ \XN'B)NK|橪U?8cj7xNZ't;EooBl55)'j_bMEJQ9A]rnf1' urІ3 W~sod ,NnF௶X"뗭Pά']I٘'BQR&V<3͕ɽnfǕ+wʺ|@ahqU2\uhCx\\l55('6f L13E$ˣ"E@;u͛|駆ɺuqPm{ n9*iGuo' 2[slg~cH~=;YūjD'ґeS$< xWeުݻt_pwg `Nw-5X'pH:jpb@k%E$kͣ2{i({2XZ2i/3?;6>g=+׿we{kt&$P>֪ $[rJАʫ'D,wEј" 5G*f:lQ]g_ mn?v?-?6Ãa4|xtgrNVnL2 HM֚GUjIKA*EU](ןj6h_AwO~yrY|dnSd |C-irwWbp9+:9A@O7Z'qr@d+roeG3j:5Prn?_wtۘA w9>7RdO ApDP N @HL~9yZLrlAꞔLO&nnl|Ѻ#7w[por۠n;ݺCCo3/aͼ_dQNH?aS j9@bUe{k ͢^qz'[0x#o{vGu;2l(sC6wMC#.'NYH 'bI.%)̆J /3 sqS:lݖ5=wu7e>tw!^zCÇ6xnV9֜/"Q#u"$o ^i| ODr9™JEctxεm8p6 3zO9/5Q\9", 'i˻ړs}}8"*Qj$Pco'HchQVvRi\CqkZHqpq횋>:)mqn%5<cw?uOO`[l 8IӛL\kW@BA*i9q zPzM G ηӫ$Bnnt^rXTrcpH0eP|f =.ZO`;톱?M_}iWw_z5f}qQZPx<9Zx^m0Y>- EG%kp:MA JkJOLj1pcNTYtXQ0ZمCE祽Or9kkVa\mg_̛5#C#;HCM.,Eْ9D*=bYK6m-?VNUbS"oc( t?geWP VIctE/(V?' c} 38l4i/E~~gN=5o_׾1UqQ g9oY47(G͛99mPpQ'%$O/F͚] u|YHJ*QمQIxyG ǘ•܊YK W.G7=iC=gN2#?):娝/i(lώn*MZrP<&c*4>9gGan)|~Iu$(.ŌQ,&_bS!3sW'rr{z?ICÖ"JR*nfk^5ooo={F?a GRylT84 VQsPQ Å$Poe9MM/~=ڧ#VSv ?ߥS09@fgXw Ũ#5ƠShY6ߝ/^˜RG}1 C#ך<UDL*uay졅z QTEJ!ju%%-nñG;/f͉!H5衒5m3@TC^GŠҨߩcCG-ĔHsG }S盯8OP HGdtՅS%DG&hhuNO[AsھQN*Vd ђx.I(CUN. Y靡NY_oy c*< 55çxZ4nH?P76-S:"?~z/SpW2/1q< 7yR*fٓI4*!(U+(rs"e GƐkD;<͂@?d< =cdd1W^2N?TWk&.h NKOг3 +Jm(*> 'Tߔ&-Wlk0ʹe+puuŏsGͫ Xӕ*;d+qg>|׿&pWaL Oo]bz4 qsL&V jr{8#lobNz@Ϲ˯'XăRBL/3fR>O}hsW^ED0㡯Dp!BqtLG\~ƌ70{} (iots4D}S<JcDr9(_faG¼aւ*f•1p$!*`BPYD1L1b xP8S̃T/۠ڏ}l'<}}ټ=7ȥRkĦElid+螔KʯA6%w9=%Z[ 3EÅIJ Wa:דe:Tx?u%qA*dywRddzs6gMl|-]]p~ˏԮJ+R<|(P'nA Dq)f{S-9=sh }n{4VGC)IW iGM!Dǫeҟc)yL8GuрƁ0Ć2;.qe69ZaLμ?5CϙeKjکD()pkOt\Q0WE܂PR5bӓpGB ʃ]>@1h4"9JDzD;@(GGe p cg},3!%_xw )JShAYyK"4(9U% gyŠ:5l~n /7Y0<܏G5`t j\JJgܒGOh'aQ.5h ԣ B] nt3G|蒗i7ۀYpo眉u0BGpxEWqEE=e HLe&MʜֈҲE%jbp3@PjD;Ix"T0Ntx4ZԽ#jZAigTx4w|R5/ٰa&JaLL7b2UZˑd+D랔煃&)1y^W-T&9@"UEfyY4ud:Tx?R & wSwLUg0qvלwΣ#Ly(d+ND'*"SR=AK0U̺GKd|*CG*fIu *kfq Yp5 Ӹ1i=`.Hje \]E(%)fA)kDi/*!'5VR+ 5CcIJO֠@6kՅp7q𒐓,<7imrpq=V)Џ+bAp׊6+Δtrܟj77tq p3-\na$#sW,xuTE;\ŠJCp'$&KDю+c@K')4|y<z]h@Y@J  4p|'B<PB)+-ΐ /򲃸}mcן^8.FVXMLV=F%OӀW@DRÐP5)*\u(%#$Tcaȡ贗%Pʟo̥WdluARFLT7g]2K{1yŦmej0b}2^gT| 30uO ުjB c^bQaΏ(CSHe8*b+/7A!#h5&hOz+ý9h5&֩3Ǭ-8VUUZ5xy>!%IZU4Cz ƢK W>UxZ:=kA&DqBX2@DP R1M"RyQSզ6أY:;.ZD #cCoASJoU5ΐ` A(G,VJؐDHe8*bW1gB A`BJJ*KgdC1X_뽢0dթ2b̈ţndAq7"|8CԵq8*B@x_6tm0L歳5 D .Tͧ2)B+QFR3J1@:9 ɝ'5E->Po+db[^[+[kF%7O1С;x-2g |љ+;gPxxBQ f{$ cq4R GQ,*0hv È4y-TZSC1TW]xPnu,a-;d+q/V❙A_o0ќ{dMVEZp"PCä]=@}|JvQW|M;^a(S撳nKU&4lGJbxMx3J<0;I);d+T{xU $qIxlT[?! zUgEWxZF<'Ś vvY>j#"6ZPH)ĠJ%W!.Jax3Fq~$%7OޜV*^HaCe^(6x 7ۙYI\_arc*3c6WhXXjÕ']ycEAYg/{WWl^nPnl oJbx>?G1ky-<36fcbKY"(`kH,ü8q!kUM+?6x8+jhEf357TL> &ƋAQSǠ[)+<@?d<:3Us?۬bEd 2Hss 78<$8pk"us'%EF~PYA?xC gekx^-w8+Xfv+ 3a_t[ Ns:jtI!x1]b1Nh>H[1ItDLt\ܺSE[񁞇sC@Qvxl#[Β^ l jϔ[EgV!V^7gϏ7L,uXsYsÿo`iF)`-֊DHu ޚ')OZ 5PŬw 6OR"輱"cekZXEڋ(')6wpI%}qiM. Y?8-v7!F ^E);RI(rE/)1LaDm r'K+ LxE/N;;̞ki\?VrPg=qŲt)-V/C%/>!k^^nsvGu/\yF l7O"*Eޘ5 /9w2NkԘ!+JL=}xXXYӵ-{J,*Zu\ұ+< .|* WY]0c˂A}i)BЛ޸ioȴUnUOoz-7όn64m(*\u(ede^^<ϼ[9w~u፣b #5t]2!?l؞ٴ[~^u/[1",< 3F'9s?:5"sn8^0D?ފ]+3sLx d|f9%!Ie)y=_vzM}C׏SRV3d`JTxX&5/[ uu:#`=c%Éc#'Js]"9DBq(-{(ċ* !gy,6ƥPYFdf,~̲5UpίgU#3fZ#0"Õ3Wt,֭k4)5LI󑗯?o̙5;flEo'pzXp@ A ^#5$FI]<-[1FzQb@$PaWKL|>+L̺™lUg)=enap@mV @h$4e.i N9@M$"*vpt,=fekݪ:sLrBoI&e w9Ѥ! ~4Ap`ٟ+2tQQ:e#t0O/UfَBfqgNq2>$C + Q 3A@ѡ?bl/w{%v϶0sycbGB<\U 2ni^mZb^T-3%5" jc)T~ڨsd. =)6˒`Wby{')no6GAf& ћŢ25PY:7.DT7!QBXZNVԈ3Z &,I䀁`xY}J<>VyZ 6dJzsƓ1o/&e&q$Kġ.쐭X] fN}hs#<.J5Q*k 4wqAUg ~[= Hutn2ֲ.•0D*59~j5R[SR^zqf Ln2=\gt˘kY22s'7!Kk[ҋBD s u F3l˖d+(fuMrL` :a QG1<0 J &ff]&Z5d\?4-r8w2_5s"k0xR[hpK!H,]U!#/[ 0QߜU# :cN09|8貨F(u =%'p| P<_{ }?Orآ^>CtՅ`Ԉe4ނ`P>ER(Y,?zR"SBJ/  q4^|4&ko ~_Ngcke> )g0٪P937燾m11Ӳ8n<"{TVxj+A@>i*5n\Ri#b#ɄmüqGMc8n̜{9Bp8֥1sO/V*s7ixr/Zsl00FN.ԉ_,[̆7|V l:(nyl`6=[tyh6\ggnT1/N?JzM*`00 K{*d|t(i2^PՋȲ?~͋Qљc*8s13Cu|fI^播PQo@IDAT3uQݸ]8lws[{1wtci۠f` wҸ c%}ǝhJvP7qv~qkqmAȎ2"uG^Z*EU-v ͮh(䥹NqVOz39橬gvKYn$'=PzdY- QOs1j͛~%ў\jDZ Nm~˧W62-okɒWLXIΘQ7xf%,jz1*zPDT*V9nE+yN@ܿr % wݵ{gT:6sOO"W_ُYdVRG|dad֖v ISg1Mq̭ _Бc2K2 OvdBCi=h~b3693%噲~/_oޚlqkRxGETYKSr~kq,od Q3LH7e$Z B%dIF zqK- 7K=C5oL"O[(fGnfnԅF n (#@dy 'H'isH[wcNC™٬;$yln 9tO%|PsWb~K5 ?[ef`Hq 7N 7^d!/t[N? P %n T#G;pLΛ}FLO\H3{>1Tj FH%d¼őq.뒭S< DkD|yKRZ̡A6dt>oߚS1'<-uq6_C`%Ɛ*:;/T)Q+qe9u[B3|r%n>H կ]{ U!(%ACO>eO ٛREOMtN&<oH9̓WW)͙GN/㛖Z>n*y*K_G[\e6'$k [1V4/v_S8Uڌi#+x-S){ lEyM>='&G+K .Ñ/&}lԣ˂;FC4F 4^S?yś:v\:☽%0O/9( b6,fo3F-㙧̆ǎ>k~JkR)i*:k*!H&r&_mfIsE1} p#'vjj8&H K,޽v ̛1}G^ǔ0>w.nƋiG'"(Dg9+[͟A[V4Z 궚S<۠1{Un7Ҡi({TY1.&VsgΜ>\s5_'G}?%m6f:^`/Ց7شys#WSy x Flq=/??WHEY0xݣ$̭9,\z(HrQ}YaӸG*$l⁃*jsj`n47y ۏ⦏ GXjـoݜ = E$sz( vS ya>YL/^ɍxf4yc,_p ^[XlM- 쇯أ}+)B Nhʯe2C2>$GtЁYT ^,I#}YM^tw7x Cƨ&wA;dlid+Ҥ saމT(|'?P<;\'畭Gƚs͏~tg&uXs;-n[KWjQΓzXn.\H'숗ϑ$1 n(Jfn{x_/c2K2 x8ԈA85w][?kLTJ#S=\|[Kk2$ 4=O@]uRs3=1D;T N)Ϥ1n콾02~,x#~3Cuկˏ (Ʊ5ɆL9[b]LJJ"*=.> `sV{.K:pU} T-~+C?O4ſV<"<$8"kossUH:G[D:70zf [8 0594zyРO ^d c _Bf#{<~,<jy9*3Q >ZpDkNEWҗɃ˟oLKy/Dm*qo:;<Яk<&^ qԈsF o&,a RRiCɽX WĿ3?:O4;p:oIp餳_&i\[.yjs}w8[6TF/6ccph@tD% a^&鹓a2_82[HB͖NGh F̈́|1*:LlϐJ_6ǠڑAa>osb ru e &x,e [nt5W1k5+հ'8|&b*c cH֐v澦Vu{qͭ.Vu"tz:*=w@?]Mo2`UVY'Me|$O^:FEJD1ސ3}6 `:H){j:e8W >[G3+ʳ-U+k! >M6e !<(T8ؼ+oPM `M/9_̛"V%ɦP;l/\$EWoibMl疀;]v n@ ie+pCn` zZQt  cpdT(tL94Ef De};SSkdېZ3NJ<Ǐ{ BDTY>s:"`y< *yǝy[|>5{sPd0b0OGm4Dh'Wŭ.;Apx8&I;%d8]`i cO苏0W0)\Y`y@6A*iNЫvׯCuL1rUJ)Jc|<5C?aX`x*ACޑ4Eݱo0R܃ !T" ={|4@0.|^xn땭*\p1Xk3F /(ٸ' 05cp릊 S ֯Kedz@\Dw綬 dy~t=7nm~->xl%UQs/V(fjbm'iYryW[ s8Z2أSQ+r}rDl<-"y3M-|]x`z>vr }^5=C>?fxx\=y'L]$Qzd4~6:(̒ ݀%6<$/b m4Q壦pw-ލ4W_n_%q|*[==v=5=7^P %3*҄+3QNntyj ܚ3PŹ}tʫ < xD™V1 8x_?7A{1Vd+)ŬiXk QEЂ{d q(-꘽_~; Bؿ^Xa^p7f-]]{MK[x>(Kvtzuig("WD^p! eCDUauX G"Ee +JKU zmk8ϡ{v)֚5=v|[jk^\تtOjqMꞈxu%}lr$x6 >G<@|<2r"<CAl7GBzVd`-2 uTz~<^Жo?/n<])=tHF0o;/P7jE{# !(+@8$AYWkTMi UWW #nX2%H~TBY@MW9{Uwtx>5|UEHU.+2^ Й\͎({eb`TzcuP*uu^$ZOc^נM>4DCuk1i'=[S^a4mʬͥsÇZhC} PCߥq0Ep%:AomÜ(khƐ_Ȕoٰ <+x-b{W܊ٖ$o=\:x^*"\ftjT~c\b 6 j}͛5wc{i\༡K8+W.ٹ.Ǟ0_uxZ%Fn I{)98jPR2_lehWZN6q0׀1T-8ґ`e -g+3Ue%wX':xC-}Œp$ؑcY;$X7+?t)b!02t8@?t<}\T?{3xODdx^^2 8_ϋ) (itDZcm@4)p -A + 6 塩` 1 .Xx졬c "U c\]襠ڱѪ3*.fEYC-߄r'IxOKAw}10PzQ7XT( ttP V6.+J gm87(lѷ[w6Z 7eY8Vƭ.;,zKC;+ U͉#C?tT :aD,z>͏H Qg"Aq|$5;.xG(]Z^_6y,)U5'p>{rQŇxdU0MC#7GDe:sG4@C0aSA{'/)?B&Wuco{%3vFd ź? З'ql@~#Mw'A b0$Ҟ޴SΚ⬡ bTҸpHyztJ@syF/7|(Є Q&9QS5Xv5 QӟϸR|̒L[Bţ}e3za#OKo6}w{"ҠṳNsI=kgf YjrWFҟ߽S?Q ׯ2wB!._.2/g7+>Mп?{l >Г~'!jnY2uO+6QO~^-T}Sm#O?mR ~1^{vhsxc59l6ţ҉7< li; zIGW/G /p& }TLj0w?(dn䅧=l=c _2Pp;L|eNZ*8u>LX?]>rǠ͜) f?pZAZ #Ĕd\ ^l{ 㑵Ggv/мq-Z &#05*AS鞈T+0? yw!lU!Ơq[ GzSÝCqn=hyT&Tz_?; η ?=͵ݷocluʃCWX^\}=.Hjce}M٬7C (uQHPi_z:Soc Ie+7C?p1PO<y皷VZPh}F3f~Y<2ZR9CTфVVmgX-y[kZ~1,o)=ϷZݘ/%jeC$(FT5fE csG=6+rSsa` TڄԂ:-Eb2]:GRdhx*S P2LZ HWRx~us^:נ7Gsa8i*G"^pȇ^n%|v|kԢÏaW4)vQԎ!ZVFD"M'QJnZ?{T*܂yك>r)g-0x 8(CsYlf'_OD<Z9<9/94Tc0p cc?p>{9o 5jS5Y\eJW5acWnltجd\+ e&Pp:Q 4/UǠ{0H7( 5_L:|Z(+iOmӸqi% Nmcc0[@kVBŐk3$QJV^kOh[,1o/ʃ o}\Xrc*/%\眪BAZoq@:lcKҥmБМ&V$J{2<?4ח/vWhOϦUu4=9Jrh@IWK}_]<|kDiJ_E"7nͣeQz~PMr &wAa2Em8?TOrV`@. >YGb* vQҚGe66xThNcZA5 G@=ZuoN: `]Qѣs F50^DJVLj܋ k}nBHmpnZeI&JOB:=LeF[ 00J[}\sVGYQ+p3qX"8QX$ٗhc>jKӁ H,9 =>Nxk/+C>cZNVZ_ttد0N+ rڧ\PS A:f__Uj6MA [jeM7ẊFt:C0^kh~ waqTj4=JJD~4ꂔ܊ظg=C?1 aӟ+Pg).,rB7Ic8OP ÄN-z+=+JS8a~{cʘJ+ sGB2_ m ee=ȚִfyeI&ŽޓэaWPqv6+|8ԲG1W"^"y\UjxdD8hp,|Pm+v4_AK`?f dcT|.\qͭ.Bp ystܹ2 wAHjy])l >|CժaN'-GslUN(Yxt67J/|B=RamɂG50="\"Md0z]-(GҢtx*o<_&Q+NiNԓg2d=>ޏTzQ,q5֚rEs7㎵?7IRNn 0oHΏ-;sHQu?Q {hWX0{ў'qSpW'#Y{0oq+d%^2[1QVnRi]Ԃ:㌺CY1.}|Ȁ(#3 O0cN6PzG#;JiŢsFֹr'vxJ*Hrc>*C(xf?<*_GYC}UuC*0@ &P?Fn&A|s(rht״j/ W]¤^譪P\kېJ471TxF桙gSG;o2u"-ZP]|>< ^YXrWIgv ti1N A<{YnBۗ>cnuY6!cҗF1qD(}ZPzO7f +D|5T|:ppr|RrnšQԊ(+vaFG5cJu)tcv]<[ؿVd`ea-hEzi}x#k?huh@e :g{_~y]5A'{?ꖣ8E# Ebil6 `:v{鶻Y9=^ac nc: mCX ==ғNFf}==7"#"2+[ֽy2w%T5Y~3.sOVl_$ szN9'O8#n =FqG45ו"F0V_߷e´p9 7=, ć]n!g)+4ԙke|xB)VI|S Ȏ'*f\ ۇnݯ0W:A&V(&rdCnv^!Q%2_FCsMSDK&XY&X?@Z7u%^Z2ɥ#((f="3߸B!My3ݻ @.G}OJ]j*6>X"0s_]MwP1=T,\&T͏$ڱ<'f'ιͅF<,7Mjx7 7jQ;5cͶZ/}T 3!mQ20ťX}/6*.=F +߳~[e[ǹjEĺ:^0AU'9cǤxo6f^Gũajw1:s[.q6C3g빧1ۿbKW^E-U4B^VԚ<㔞[Gj }E씕hn #4'ɚ4Ε*Ѵ9_I& =1S.Ti)dY48tAFJB!TW# ._XcҚ!mZC!\Pe;2l*[wk[|;<*zЌ.>oi; ȴ֫eNx;tU\Ōf.+ytMg@*y_orFK5Hz \n$ePƑJGnQbηv*}锖g.ЏӧxlL򪒃[I Ү|ܹGuͰ/ж' ):_IU4>ռK:=|*d ͼ}zKjuh5˦0W=:+LKTΣ6ìb]2_Yn(ɝ%Иde A_xuJ/86;SQ% }K~rEL6#ܛnr6 DwkBoԫK2;z~_lܔf{PH.u'sAVgּύ"o9U(& 22$IOFa\#г2wЭ~Zqٔ=N$ȥqIAܼJDqWy'% ȢXGB_~Hqy䷤j{Phi"Zw[FFat+X^ <=iՒyYufH] GC;^Z81rp~C>4ow'hg5ᘇj/_#%PJVG#Or]Ɠ?X7Uif2f-BʊR.)a C1h'0U|uQ'by,4ӤĉوFҭb=ey{ZnJH;`% Z0EPjEo"weťe螹RrBF;4!'K$0=Y49Xmk8AY<&Rr`4: +Q)9>2ye4qN&cX||"+ z9ecp[-a㴭~fhpo}ͻў+\w@`L;}*hsѣ*g.U`ӈJ A"=5 2ACaj gQ' wDW(E(1x.4N AATB^=<;߽|~>۔x\:SZs7Jh@IPߞ;8csYOpb"=X+`=qL@!jc2F&t81;.=%7: @ֹ_:#F%̛<ڱθɗdڵ_Whk G>#:d-ʸ+KG5!7}>k@ vDW} L:ar‘K 2"9ͦVս@/<ԯ5/A:2zQ^m_ 7&e"+KzI(BzZ`A 0xB,8riK\%AIm5DO\K:Êrog¦H^9bһ C20V-wZ"zZƔ4ԯ6;@ztt/YHxCnI ˙#OlA,* c 2b C z .8sr೥N[u%ގuY.qN1$?Úl}NǁsOQ&n: 1 u|rRE ѡ*@A&,\p}>ּwaa4JS6ìbQЭ`R'is5/& ֪3OWgݏmQ-j0)` oH\(#s?0}# Ihmzy,KziUHkd<1N(&_~weތ2TcĒ,dӭE%C\d[O ^:Hӕ1 &k@2P^e]`Gyə>Rq",k%a;-[VLb,@U 2`rr鱕i}ʿy0B\rdKzuUVVZ"K^:YYZ.EA;St. j)齽{ ˜%}0&vP'W%N]>T6G¤Ƌ.\j#=z2c{^ R F|5CP we(@@t.n8ld/MzuA!k#WQ z=lOnUu 7D]ufr:p٩Gsoc:X VI oE`PgVL?V~͔,I):-k?DI Q.FqEACD)Tc ;p3,n J"Rs D {y/+#@IDAT ɏx5  = dt#d:VxZ=D";!EﲳgFԊ eQEn".\&h;[c$gcY ӡFiop$~I 4Zmc\JEPϝWzZM=mIӧ҂g(H7}:@dH QfI^yK<}q:хM6僤1ukʢk2*%[gmYkTs;m m2' qtb|Y9B蠅0BV〃`#{ a1W/q{u,//IHқ<]?1аcM޻{@ON~a]rm9w)q;%Am&9sHFFvS?Y].+x#dDV70ttv !;À;2rW|NZͷ^pE\)cYٽckhO/awUf"̆S`S"3涳\VV$3ʘIN50vH'Z|V8ā~קy3G:rDꝰ3_o3MÅ;OIv'I'XDseiY$ Y ;1?:bCu8o]ǒ #R;ǩQJGpJkͱ2<,5.ZGY/X^u,nX!h5z/([E;cH[S%jzYjV2>)tCp$V͆90Ⲙ.Mk<5 MKєư\:K&I,eéyyȔ=nt 䂱pCWU_zVVj^59<ёWЭMh%wE=*+ c{SO~wz3 .HMounU n->>xs,:^BQ$tit G =F|w}SuL?ҳi7 q{N<1;Ajm|?ν?>|{4y^{n3 @}S.>v^h KJ;Qs]+wݦUlYe{$Gߺcr,{mVJm'}{X=t}z¸{Oʙ^T}<_rDw)瞝n}`o vܺU%Fk OH`'Ϻ3؎Nɗ* Mԏ1ObPH0 .>MA%x^Ee~.^5}rk q+Hyμӡm\ ~_oೣUj(84]wV>ί~{'1SH^{+8ɢ0s1K0ݡ[\e*1׭2}@_Tu1Rji D&}z(/.{byD|_ /Po)Bfh7~^'=9PI璳]O`oJ.HRޔo)*15%ZP -I3iw%^\M*eѫ;t+I+MGh0&M,*F 6cYF71rV=q* $71<˝<ŽMOY]'-(Y3La:lQ( F~uA gdO dIRiM5JO' x0TD*]=L&q ɱYM0c*\osV(Mt16`_t^)iH&Sn.c0F(UgqQ=矅E=t2{ }xC˖D qr3 jȶ#"p2yt I:C#;*qM<}K{hF2mľUDeaf*SzS%~L)S^D|sC^K~CjtF316SNN`LX=5$bBLSO2@|y[ Ŧ,j?쳪'ztwN2Ԃ 3`6&׭&/"bFn9"'ƍJvVw2:ezG^`Z[= ۫M?q-;ZUsMf ӡ&ѶG%ϭn4ȳ@WOTFҀW7(N[cPP?cO쯵L-ƂB^g KK-fʘYi|K~:,X @SDKoIpݵUњor j1uuTn޹ZSaW+1 K_/8 VxM?I 9tdg^']XsxBFg(e90B-B01$.!]p90B4 R%q,lScK%.@.m:m-cL3E#{׾3t0\K\$7qj5،r)$L[Kfj.~f 1KrYsx4PI1/w?+hNdD#AT7W<ɘ֙-@L$CrHMBʈ= ôl_pcj2YT7pq, j{Wį%0\@(K/N+8tnY\iZ vcc=ek1d^ZoEl~B:Ȋ}4ijb vn^=1'A2X։i[O?}iF;]ЕtXOhyIHZomJDń$[XB8L8۾?gƙ;}=^5vVj8֘iRZ{Zc* 7t/_Xl}nc3ce_99r##O z!kj7}_ӻ1S*9}X?<Pա(ۣxݪ2 "-ZR7][d ݧR|@_+yelz5uo#ct/! WI?':]q>]ଛ0ުQp6FAveǞN=F ^ p2W.?QR;jhۣqۣ֗YH1!Ր'?yk:8B=8G8Ph"F;EbAz&(т* 2w &zU%e:#Keyҵ+=~p*n+w%ݝ,r78k#=ͥ 0?1z@Bjdþ}L>kk!nW>/J ^!jry0XHTUZ}Oh3bMFm)-"oU]oFfK\à^n53X*G>5Yo;o$-ډ^,6 cgk/};v^(Jc0潢`l,'b`v 1EzqD=])V[s(2E?I,z_APÕ _WcK}qL O3oJjĸ[G0/fԅTor ,N4{*5T^qx'%~#]se]\PS!L[v0:Fo+[XͶj`F^<}~MTBo]6h(ֻ*.SRT/8&"/MSSe 9.W#=wJJ`am##ѩRz3 t-T |fr@kNtUshFDI~귛 dfK|VܷYn|BF"/վ'Ӓi,@-C#N}j_af- V4`z-G_nmj2Y!=V6S} ZlueQ6!s`}w roO~]cT6>-sN91ugΉ74 =q;[ u#]yAmGzm/?BzXWO81If==5 /'{zMf٪{YDLcIJD3TC*ũF/U;{T-q;P&<`:PDI<~x%󿷕^a'/[yr( c}zoDu}A ۣv8.Pzp[!q@UiL=\Sͣ8F_*R7mT2*RIeY%?jbttIƚ0֫ |S)qz-uYjdj:5NMFsža ,gp!$tDWmXXrgSX^&nȗտ29Mײ8*A~'iO%<=y\N:Iz@AF~,_ WZP dRhQxRϳą+wv1rBF@@tAHzZo -5>y'VGBØc̨o].tp zƓ̂#9@X{[Ip}c8ܛRpunY"xT#7;ϊwD2 4 I,PSP{ H m!syDc` 8Ѷ'81u|( _+)ԋ[ݨD'_089pY -.*^ i%e#Ϋ s#՞9'T];ԓM*ܺH${*tV-[Y,-w|l;Pm4R9N3MshŘ1U.Sn"w`dqA2ۣWpoI6?6Z7=[uKe:ʨ֭ P_FS!M#w"FGxiAQ-q.V;j,*{%M4tyOvw~PI)4їЪ )qK|Al&,#%z1vyw%GQQ_al[iô> YQ,4PW 27คO1Bp;~h:D/cV!"-yʾq^h[n;ƲZ--=1E>4৲+풳NJcS;'a!h/`w A}4%[G*_al;X@r &h8-;vĕP;]SۖLPGM |F׮%Ho].tpbUۗm[szu/:_|\wNb|v&5cz1A`σQ\,#u_T85(UY4qTL+ϗiD"iN d| xL?@y)Go/Odz$ K{0_49I s b;Eb8)*f*+M$c" G20%Ȁa=9O8iQŘi앆qZ1gȑEɈz 2iu yUn2'^F2zT%ʤ(+J[!L&cGAM!YQjj @@tt%.|u89 r*^[gK\w0ʑ!"|"Q{{s" Kpi̔%7 U_*rD޻R_7&D=aP6WܭVV9m٘7C|J3ZU^8)L85tχd= P\n!5ӕ;@,[Mgӥ|yހN5HLh^P)d@YF+A*ءݟIc+ =hLFKa:"lf;u߃X҅o?atʦ 5(fI2eI"_o89@Z& {IO-2x{\hǁxA(1R8v {',e6 hRi:.vHĄ9t+ZoAyi:I&=K%NnrfB &Qq6c~~^sޛ/ʜ>W[ctpzhHOI+_PcMse=Es#fqIO![5qȀscH JǷfnؤ1yb-ةӰ%H_lR^va twoQ{Gv hPi4@`FMl;उx.W_Xvlh+9dTjټUw9(*Z fS]dT*Mix ׄQV sp7&𷾎)҈ :- X ~MNes_ߓ)ӆTNRzxq:o]5L6>2BQzn^gw|sC+P9"\@؁2u)BzztNW "arrIcpVXRF9wc ikoB L@A&4,\&y{OOp ^5@u_ R\iU'M妸1A ip}B\_KJsDZlPd@"L y;v&Wx^ܾUzk˝00/(<=Z$B/ƃ;2F GAO X G\z7nW2"py{s,hot&yygBUrqm<'oI181@L`!E1Ae~L\qOHYU)D3ď>HEB&^XH6[\Ͷy'j'5߱`0~\2#TFK&]gK8MxQuL!!}1FgC;jBORsbBam,m]nHn\lr̍(Sɽ&QZoG**P 4emdo,3UC*dɕd~]nS2ݼG~q7|$W27!U2HZʙP$WIYR{*@ǐuە՛l0|2bӑбLOCyOVեsʉ=L*(HK%'<ga aF")Is piGPmeRG2խ9\nVf:Z﶐Rbפ (J {9Vפ{֜}:xxЄkTb>ʹ|CV+.~b$[ԐNJXgL$F۞qH$^U]=^:m e6z P ECRs纟E5~e_?%~)?Er{0xG={tyalfPԊ?u_+X7_awݳp2F}b0:Zz(i)Yz =к`rٛLxddнCzA.qsh-[;̣BzWb8Y?6KuXA G&2|1uol>SNMOnY| 3$ ӴJty,d2cOsslZ0|߸m4IѶG?xnzWt$["H PK>.ӡRhCD*yh%2Z{^y±WY[6r4Fua3 )ECĿ= Lhn%}l]d!Z3ܲgn>q=F \@/3-Kύxֿo˔g|T&=7F K,Ej*ՂOq_Oc^ 1Ez;@#tc;}RJu  [`aУf|f3]Ch;*.:'pˇ-~'1M?M<-l(X/"Su/jݡ%Ș1Tmexzd[Evhc'0OŎd@l&/省FO8wԾ{|@&|{7g?mc=8z)[ &w'Z޵#pʮ]#'l < sܹ>0dno[\v=iĝ$f +z{?u"1KGJY׿U7oo[ 0s⢬taݱ$x|pxBYq)hdz6O' S~9ov{ed:u&]LCnAO ?r$ps'}m[[ٳmr'O*8h};ٽI!kͽ{\zbS Y[ <75Ca#ÿ8I/dbj؞&l8:s*e{vWTƍM4 ݦ}6Ք@zu&sJDKJ x.&wcO?ph^/ިxne4᭪K5fZwqUO4s 7lc0%hۣ]+8>Gos]E)jZDhs/<7Fk67?uUEqq0r)'/h}Ľ ΊMMCQiw7={n ?XLw {í֑/=qt-еѕgͬcju_Vز8ziR$@B1@&2 9t=|Bc<ތ|Izj'aI2$KGuvR@E[ 1AR]FKpxE~zN7Ę\HҺq/m d`CFC*/mړ' =Q _o믜nȘC(d>JL4;>!-+ I \z'70| N'g`=>M2n˾?G.NԾ]< Ku|rdOMzgω>E,o@SmI |eFt1DP:!4mO/F'"_w~L.1瘼'#׏=:,E2Q`8֫=[Qv0E' PNj,MU `Ÿj ‘f{k_LH9syʹw?V #>N^י,΍|\QBӳz{|D,ɣj9+11Ȏo㲓rvLzj6:oK}]7*-Dc8M2ѭ6K[Q1:acm'?iހf3jȶ#"p2ytŊh.xnh HQ Kխyd֓/jx/}xw}Gl*HzlrkF鈡\Ѷg\0cM)Q;2b$R4i\?7dLgϹxp Ü'b`KBz"t3p2yTX0hH563e:~\n~]3=N!˾`2/]E2QsȘ̨r1Kx{ RR'[rB[E<[[[? }D× W>&h.R?6lE.>抍+ %T'eKz)M;(0[h#iQzni"b' $ {, NNsڧ?|>H丣RpAZ.B M@հkUcܹ Ƽ^;;9[lvC( ͭu㴸pEFsvЬF'_.; ȶ+ ?m2*w^?RK92i v\iT3)K 53oRZ{? 9[f>]+}ky~mmy' p}پC.himLǂ)%p+ݾMvP%7B*vc)GFr/.'vɤ87$OpּGfۀk,wMMvjOz,7ߎc痹ZVٛX\/ʔY7sx.oNFfp#T.>/*UPQ0e``0IDAT1M}kW$wK .&jh6?Ӈ^|e \Uu$$g坉5{F*331PGj//!|L^Z8Gˑ5 9J5"3V>`zT@Sjf9cXo ?kgE<6qo;4ǒGhl7nG}QKRr#Yq%ikI6^2޲AO_vֱV)B"roP+dV;Wf AG_˚Mz܍)ٚY @Llk2Fۯ+3Ap'C3`h[MG Bz\&$:_숹䡈J;? έ7Z1!eLnSl1EH8 _-[m)Kj<'䝪ɓô|l@AF\a)`2wn8_{2J*5^<ނ@ ]\ RsNgv7֭,L!'t#Ghp%]փpKѺ|zB:6zWo|{9adlǤ HzvJHQW.`7ANRL9c܁$#uUߒ{w HWu1K Xw5laT\Q=aK2Ѓ]wsjŎ #=qȼeai(0?B:4GvP!c`dsGt.1eUAn 25.қMn`@6\z@64U6x2WlmW+:idݜ]씐>UJ\f;Ic+[Io4{w(A$g93/I*cr. a%e_&tSXwZUet-] d n*ByWC5ÁfB:X bѶ'ۅ2z3O{˯|V;a,׻iƎ F(wKpVYAyedQHrZ%hX/i[ñ[񧟜\jmeZfWŚh9fnjխZ%&s3kFWl֜ëJцG[Xv~^{W0\r{!5N \+e41r}n젝,XFPyTuML|nnuL)GCIϏ߿șe^ۭ6t6Yȼԯ0|TUW΂q!P!# \Fgpr ` Vo?㊟󸵵}z;Ʒݰc@6 G2E3iDN"+!0۞aZk,P|L! 2o} tqx/ ooܲvK¸~8Yeb j٤cLJJ; +AP7@&Cх0@zΕ]_zOD&i 5 +,\&oy{~ ݎv d9G䩵%.|?WK|n NT^ʄG2Ѓu4stp4ԗE vDW|d{7:\b dlo֝ǭ4Gou- _vQowe=e2yTy)._tF #rB 7D>Sэp` >=sIh+4EgLXaLA'1-/\$9 ;YcPx{KTNcD4%gaBSrt;\&4>6׭yd7ſ1{r <}[;~7e>V`G)P v*+X^ɄTl;gjfb@ P/rBx[n?;f2уld'6Vf"CC&,\:/BA0@61N*^̯[~ٲGqwe2brqQTiL(n%xN.eL>Z%c@H36υN \cSU>skI򦕒4Ry{\ YedF&9ZzG\YbWGC7s[y?FqY#v <w`XQ6~@ld423U)#&wPG3Rˠj?PAwQ}t˽t[ft;yBEomõ6ߖҎ (ep62уqQ| ŭOkK|R= ssƎ<(? d+.ڋG vWK趇E9h՚oHW(,G: Bf>C|MxuyL ,=-z5}sG[dCh0h,JK F@*`]=P}itf㘗~Ac0hC\3Vy56<92 /RR\ybL3p_aP-Ɨ;ZXYIkg1j@o Z~/ yi6>]g`L_&BO94:.ɶ|Ku뽕/aEJ=6m9 ̭U 4 -ʘЭ1HQd]3rF|j>ɢ9QQ9aP6Y-|DŽNX?S;2JE\z!sK7 ڔ`Hd<))Rpb[:gb~ᚏAu󿰗]A>H#/` 3grCgS:lf;t+b,)FiNsd1N{q,~r8ʚv¸_1|?w@ʖ+v HMREȀ%VtI$O"JzaюNyn;PE0n!'8V<&^aLkZr̥ Y`2: ',]dp$̻н94\kwOv ZO`9'TYzLOפc4(6q<8PCH^ xxJD;VNK0-s^]^+Ԑ=U 9[-d\A8d¥.txJhfc7Y!հ7O;Q+X ;~zJ=l^Z>ZE#b.phR('eTi)a#vNXJ|z[:Q~;~-m7 3M<빇砦Ä\5"fÙO<9Zw#|;c+ ]o|W+v/ZQqC+צ4tDp PK /[Lht>p+"#@ vDW}Ak K>p4c3rX b%Cv]%:{usݫ<~HvOT]ܫէæ\|#Ҧ1(p\|Lzcsb . Yo+W-.2=)몳ᇰ.?]U6'|a.]\. .ZcǓnW2"qi:)uMNQl.u|̓o?gy}\[j/D *2'0&Yٺ+bT}1eI).G+Ohz!ǝjdn7&"޵@7=\+0ȉj;"+&,K6i=: |d !C8@Idxכ_}ŋ_~7,2 *9㈰ R$I 2#V+E7:\V$#S/e[_[$h~bCt#\}OU s' /V@c$2o}WYKNMZ4.9!+Ako|}nw_ꘟ};l`b0'PwDWj2U;Y2IaCP 8$9ndC黟w6Q' w~ _[%M.zNeyu6Z#syCs}v+ z+]Ȇ [=&}l9AL-A_%FK+[,w~_Ϲ㮣<̧q?q^}[tߩjFĎp%7v="9un-\v))&ܽcˍQ,)8˽S';P]vVmiou(>ťtچ2=iM2,ZtRa?㿎7cTh: 3xً=?8vvSw:aKtԪ(F}'ܑhOv' ImګHv#vީ' /ǟ6Xzp;n6Hel#5t" R{JQ.mvmOȡxG~@~d=vꊕ_g{|{('e2`RPL7W sxchp5*^Z^>飿Ht䶳LdAɣ10/1rslw??Y̙#{̟0h?xݷ?o0ѦC2]·r 9qнGr{[jn;t8]îitwx/&Zo.8N ,H4?Iov^Ÿ,><[p;}]}[H:0l!v\zJ=xI^'75÷51\cy PhUZ]A@?w?̙ϝٝOr<͝{?<;ѕx;ɻCEk..Q: G *c<xkj2z q sRD_Jc:]"Mω|SukHor#LEvMt9,c+N1Զk(6~\>;}QnGnI\zk;A`Uf̓`yj nAbA[a `h~2;տBJ37yfhrʣQXX3掸FMh Opp3kG=3j<=4썍+/I* Ri*%3o;tut[t,j rv?q*$zFzߙN#N1fQp[ H!@2V+# -k4t):i}Fp/͍R]jhSũnB RrAVN#F[Tw\t<Oc`H2w|:?b#Dʏ)B:-4MBZYZ #U:zvtk}uR4ǡ&CW8)èH Jt14ҽh4f!#4uwuƁm/N&  ' .1'T(ڈi).@9N.|4 Fhc):,}x口Dhp#-mbIv:ULNB^٠X9 RQ!i|+!IN ;)j$(LYH I]5-tԏeɇT:C[rBn@I(U Vm~IUm# eqK 'cL/mV/ \=XaUqZWQOۍX4M;.?wOuf!FLYm4 %E|&(FIu+(t&&0 M OQȻ~) nwttdkSK)i( -g^'7@$[Z{)pAG`ǺGa]8^<}yf#'hoҾ4TaA0)-RD4M)CɌiA y-cffhx}ҚPJ,쑲yUTUDtk},\Ѩ{͎@S0v :_L~W2.&B|HREvAWyz3h0Hl(iuyK5ySx|U\Uq {ᬩt|+@(l;mMkFL%S0DnR("IDWJZ&_.%WesFZ! iyjcGOw@7TA!-suWjx4_]Xuq&48LaWإqD%WYKUa1L |C7 Q)(l(9"ڕO[0?ٶ#5G` tw:q:kvښf0(Щ`NKhqȣ@d+ʐ`ȍ rQRh60 oZgW_+m 7Fi ̚bzI.zj 4XKͮKчf%_nfy@yvj&GeU5`pUI~z}0C $e:+dx{NvGݍTS.$To&NwzWu^N t#F )ƏX>]:Gp׀x.u!]>~q!ywT(MެRo[r,ll6?AGNsbA{-yTo휼 ~rCkW9k+ɆPO`vA/:YgSg7ÝS_Ə%}[]Q=9YZI ~.80i F \0*3gʲy+7~w܂{pB[ɞT^yښR ތ$f+W n|, Y Pred|.!B|ã)wuwfrApF` cy&Yyx>InE9FjFd=6<8$a}[|[9THXKo]2 X!\ @Rvw->{ڝ҅aA F.t' b8Nljwz n8TbGew}SS#cvAw1@{XT./rϗ>ui yipK: k|+kzui?n#` X8ߑÛ wa;/6F`SxP}`Z{Gq|.#P3` &W;P8:&B =8 n&)M]Zq4>\0 ! (w/{b~}C1&M |E}(dp>~rmSn[|濱fLJ/2cҎPd!!cHLV܀?nl3n```(1zlƹ0 ?3. 2 ~8'eqcvƌ4؆`F`F`F`F`F`F`F&j'‘U]IENDB`astropy-specreduce-05be828/docs/_static/specreduce.css000066400000000000000000000004221510537250300231030ustar00rootroot00000000000000@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; } astropy-specreduce-05be828/docs/_templates/000077500000000000000000000000001510537250300207605ustar00rootroot00000000000000astropy-specreduce-05be828/docs/_templates/autosummary/000077500000000000000000000000001510537250300233465ustar00rootroot00000000000000astropy-specreduce-05be828/docs/_templates/autosummary/base.rst000066400000000000000000000003721510537250300250140ustar00rootroot00000000000000{% extends "autosummary_core/base.rst" %} {# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #}astropy-specreduce-05be828/docs/_templates/autosummary/class.rst000066400000000000000000000003731510537250300252100ustar00rootroot00000000000000{% extends "autosummary_core/class.rst" %} {# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #}astropy-specreduce-05be828/docs/_templates/autosummary/module.rst000066400000000000000000000003741510537250300253710ustar00rootroot00000000000000{% extends "autosummary_core/module.rst" %} {# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #}astropy-specreduce-05be828/docs/api.rst000066400000000000000000000012251510537250300201260ustar00rootroot00000000000000.. _api_index: API Index ========= .. automodapi:: specreduce :no-inheritance-diagram: .. automodapi:: specreduce.core :no-inheritance-diagram: .. automodapi:: specreduce.utils.synth_data :no-inheritance-diagram: .. automodapi:: specreduce.tracing :no-inheritance-diagram: .. automodapi:: specreduce.background :no-inheritance-diagram: .. automodapi:: specreduce.extract :no-inheritance-diagram: .. automodapi:: specreduce.wavecal1d :no-inheritance-diagram: .. automodapi:: specreduce.wavesol1d :no-inheritance-diagram: .. automodapi:: specreduce.calibration_data :no-inheritance-diagram: :include-all-objects: astropy-specreduce-05be828/docs/atm_transmission_secz1.5_1.6mm.dat000066400000000000000000006367201510537250300251130ustar00rootroot000000000000000.900000 0.948654 0.900500 0.942270 0.901000 0.947468 0.901500 0.946108 0.902000 0.941138 0.902500 0.944661 0.903000 0.956764 0.903500 0.978545 0.904000 0.987198 0.904500 0.985155 0.905000 0.985933 0.905500 0.983675 0.906000 0.980373 0.906500 0.967384 0.907000 0.943643 0.907500 0.936187 0.908000 0.947027 0.908500 0.948955 0.909000 0.954411 0.909500 0.960169 0.910000 0.955615 0.910500 0.950850 0.911000 0.957920 0.911500 0.968951 0.912000 0.960049 0.912500 0.962144 0.913000 0.951225 0.913500 0.932353 0.914000 0.942717 0.914500 0.969754 0.915000 0.965365 0.915500 0.932753 0.916000 0.937585 0.916500 0.969009 0.917000 0.970596 0.917500 0.948742 0.918000 0.949352 0.918500 0.965726 0.919000 0.975516 0.919500 0.976791 0.920000 0.980078 0.920500 0.988850 0.921000 0.987226 0.921500 0.981262 0.922000 0.979548 0.922500 0.985318 0.923000 0.986866 0.923500 0.984321 0.924000 0.980954 0.924500 0.978778 0.925000 0.978388 0.925500 0.982463 0.926000 0.983853 0.926500 0.984372 0.927000 0.987250 0.927500 0.977302 0.928000 0.957896 0.928500 0.950821 0.929000 0.949588 0.929500 0.936239 0.930000 0.912281 0.930500 0.895657 0.931000 0.871601 0.931500 0.836746 0.932000 0.796466 0.932500 0.784504 0.933000 0.791712 0.933500 0.778925 0.934000 0.730238 0.934500 0.689957 0.935000 0.748015 0.935500 0.756215 0.936000 0.724900 0.936500 0.771703 0.937000 0.754404 0.937500 0.751159 0.938000 0.763841 0.938500 0.779592 0.939000 0.846616 0.939500 0.916115 0.940000 0.918993 0.940500 0.902259 0.941000 0.889363 0.941500 0.881720 0.942000 0.883934 0.942500 0.846681 0.943000 0.785517 0.943500 0.814545 0.944000 0.775153 0.944500 0.749129 0.945000 0.842947 0.945500 0.847050 0.946000 0.793236 0.946500 0.813635 0.947000 0.860710 0.947500 0.867957 0.948000 0.836124 0.948500 0.831939 0.949000 0.887025 0.949500 0.837512 0.950000 0.765804 0.950500 0.804802 0.951000 0.899172 0.951500 0.898838 0.952000 0.828835 0.952500 0.814234 0.953000 0.860126 0.953500 0.894153 0.954000 0.882984 0.954500 0.849349 0.955000 0.859827 0.955500 0.865675 0.956000 0.861372 0.956500 0.858717 0.957000 0.855468 0.957500 0.904725 0.958000 0.905174 0.958500 0.880795 0.959000 0.859772 0.959500 0.853298 0.960000 0.893632 0.960500 0.912352 0.961000 0.920746 0.961500 0.934287 0.962000 0.916878 0.962500 0.900972 0.963000 0.926794 0.963500 0.938201 0.964000 0.909834 0.964500 0.906022 0.965000 0.925492 0.965500 0.953079 0.966000 0.945531 0.966500 0.926942 0.967000 0.939247 0.967500 0.963107 0.968000 0.970026 0.968500 0.969073 0.969000 0.982198 0.969500 0.985010 0.970000 0.977449 0.970500 0.973962 0.971000 0.981516 0.971500 0.977721 0.972000 0.974243 0.972500 0.973712 0.973000 0.972839 0.973500 0.963881 0.974000 0.953921 0.974500 0.955559 0.975000 0.956370 0.975500 0.954694 0.976000 0.952368 0.976500 0.960257 0.977000 0.976785 0.977500 0.983021 0.978000 0.975044 0.978500 0.970744 0.979000 0.973373 0.979500 0.970194 0.980000 0.972061 0.980500 0.976089 0.981000 0.987769 0.981500 0.991617 0.982000 0.989496 0.982500 0.985568 0.983000 0.985701 0.983500 0.991358 0.984000 0.994686 0.984500 0.993137 0.985000 0.991633 0.985500 0.994589 0.986000 0.997970 0.986500 0.998532 0.987000 0.997169 0.987500 0.996260 0.988000 0.997617 0.988500 0.999203 0.989000 0.999440 0.989500 0.998697 0.990000 0.997875 0.990500 0.998411 0.991000 0.999130 0.991500 0.999395 0.992000 0.999422 0.992500 0.998854 0.993000 0.998370 0.993500 0.999084 0.994000 0.999641 0.994500 0.999782 0.995000 0.999814 0.995500 0.999674 0.996000 0.999664 0.996500 0.999777 0.997000 0.999731 0.997500 0.999677 0.998000 0.999590 0.998500 0.999655 0.999000 0.999624 0.999500 0.999449 1.00000 0.999452 1.00050 0.999674 1.00100 0.999647 1.00150 0.998836 1.00200 0.997946 1.00250 0.998486 1.00300 0.999449 1.00350 0.999617 1.00400 0.999258 1.00450 0.999361 1.00500 0.999567 1.00550 0.999433 1.00600 0.999526 1.00650 0.999679 1.00700 0.999666 1.00750 0.999518 1.00800 0.999270 1.00850 0.999172 1.00900 0.998637 1.00950 0.998235 1.01000 0.998769 1.01050 0.999405 1.01100 0.999681 1.01150 0.999602 1.01200 0.999323 1.01250 0.999492 1.01300 0.999763 1.01350 0.999849 1.01400 0.999809 1.01450 0.999670 1.01500 0.999663 1.01550 0.999578 1.01600 0.999730 1.01650 0.999822 1.01700 0.999707 1.01750 0.999713 1.01800 0.999864 1.01850 0.999851 1.01900 0.999416 1.01950 0.999160 1.02000 0.999603 1.02050 0.999814 1.02100 0.999849 1.02150 0.999711 1.02200 0.999722 1.02250 0.999716 1.02300 0.999454 1.02350 0.999075 1.02400 0.998936 1.02450 0.999573 1.02500 0.999873 1.02550 0.999826 1.02600 0.999803 1.02650 0.999840 1.02700 0.999711 1.02750 0.999519 1.02800 0.999688 1.02850 0.999762 1.02900 0.999815 1.02950 0.999908 1.03000 0.999946 1.03050 0.999960 1.03100 0.999918 1.03150 0.999883 1.03200 0.999949 1.03250 0.999990 1.03300 0.999977 1.03350 0.999966 1.03400 0.999988 1.03450 0.999999 1.03500 0.999999 1.03550 0.999987 1.03600 0.999960 1.03650 0.999907 1.03700 0.999857 1.03750 0.999883 1.03800 0.999949 1.03850 0.999970 1.03900 0.999952 1.03950 0.999942 1.04000 0.999944 1.04050 0.999959 1.04100 0.999978 1.04150 0.999992 1.04200 0.999999 1.04250 1.000000 1.04300 1.00000 1.04350 1.00000 1.04400 1.00000 1.04450 1.00000 1.04500 1.00000 1.04550 1.00000 1.04600 1.00000 1.04650 1.00000 1.04700 1.00000 1.04750 1.000000 1.04800 0.999996 1.04850 0.999938 1.04900 0.999708 1.04950 0.999489 1.05000 0.999585 1.05050 0.999812 1.05100 0.999888 1.05150 0.999833 1.05200 0.999792 1.05250 0.999806 1.05300 0.999850 1.05350 0.999895 1.05400 0.999930 1.05450 0.999956 1.05500 0.999975 1.05550 0.999986 1.05600 0.999991 1.05650 0.999991 1.05700 0.999987 1.05750 0.999984 1.05800 0.999975 1.05850 0.999968 1.05900 0.999953 1.05950 0.999961 1.06000 0.999953 1.06050 0.999954 1.06100 0.999937 1.06150 0.999924 1.06200 0.999833 1.06250 0.999689 1.06300 0.999630 1.06350 0.999551 1.06400 0.999452 1.06450 0.999223 1.06500 0.999143 1.06550 0.999265 1.06600 0.999358 1.06650 0.999460 1.06700 0.999320 1.06750 0.998738 1.06800 0.998397 1.06850 0.998842 1.06900 0.999116 1.06950 0.999013 1.07000 0.999058 1.07050 0.999346 1.07100 0.999615 1.07150 0.999471 1.07200 0.999014 1.07250 0.998782 1.07300 0.999174 1.07350 0.999633 1.07400 0.999161 1.07450 0.997460 1.07500 0.997703 1.07550 0.999305 1.07600 0.999643 1.07650 0.999299 1.07700 0.997739 1.07750 0.995892 1.07800 0.997439 1.07850 0.998967 1.07900 0.999435 1.07950 0.998522 1.08000 0.996039 1.08050 0.995377 1.08100 0.996175 1.08150 0.996278 1.08200 0.997916 1.08250 0.999084 1.08300 0.997164 1.08350 0.993476 1.08400 0.994690 1.08450 0.996819 1.08500 0.997534 1.08550 0.994862 1.08600 0.986948 1.08650 0.986943 1.08700 0.993688 1.08750 0.996690 1.08800 0.997774 1.08850 0.996961 1.08900 0.994510 1.08950 0.993157 1.09000 0.991080 1.09050 0.989124 1.09100 0.994849 1.09150 0.998258 1.09200 0.993379 1.09250 0.980956 1.09300 0.982794 1.09350 0.992623 1.09400 0.994362 1.09450 0.989816 1.09500 0.987046 1.09550 0.986598 1.09600 0.982533 1.09650 0.989097 1.09700 0.994809 1.09750 0.988697 1.09800 0.983299 1.09850 0.984920 1.09900 0.981452 1.09950 0.972369 1.10000 0.972351 1.10050 0.977640 1.10100 0.977123 1.10150 0.977883 1.10200 0.971043 1.10250 0.968623 1.10300 0.970545 1.10350 0.975563 1.10400 0.970007 1.10450 0.963794 1.10500 0.973415 1.10550 0.971069 1.10600 0.958290 1.10650 0.956328 1.10700 0.973571 1.10750 0.975610 1.10800 0.955917 1.10850 0.945755 1.10900 0.956992 1.10950 0.969107 1.11000 0.966012 1.11050 0.939959 1.11100 0.920135 1.11150 0.925545 1.11200 0.948692 1.11250 0.933251 1.11300 0.876186 1.11350 0.851763 1.11400 0.889769 1.11450 0.910296 1.11500 0.841800 1.11550 0.817737 1.11600 0.789890 1.11650 0.686181 1.11700 0.699684 1.11750 0.783042 1.11800 0.833176 1.11850 0.788880 1.11900 0.720396 1.11950 0.728391 1.12000 0.757344 1.12050 0.779253 1.12100 0.815802 1.12150 0.748593 1.12200 0.625861 1.12250 0.579093 1.12300 0.686282 1.12350 0.703119 1.12400 0.724877 1.12450 0.818729 1.12500 0.739023 1.12550 0.575220 1.12600 0.623246 1.12650 0.750044 1.12700 0.792277 1.12750 0.721815 1.12800 0.708645 1.12850 0.743655 1.12900 0.732202 1.12950 0.691436 1.13000 0.704174 1.13050 0.828487 1.13100 0.910727 1.13150 0.912520 1.13200 0.886162 1.13250 0.842981 1.13300 0.782162 1.13350 0.667562 1.13400 0.569252 1.13450 0.425347 1.13500 0.430525 1.13550 0.638204 1.13600 0.726293 1.13650 0.826607 1.13700 0.907367 1.13750 0.875251 1.13800 0.848953 1.13850 0.836608 1.13900 0.897902 1.13950 0.908410 1.14000 0.857842 1.14050 0.844483 1.14100 0.809568 1.14150 0.820806 1.14200 0.854212 1.14250 0.892016 1.14300 0.918704 1.14350 0.869072 1.14400 0.761278 1.14450 0.729615 1.14500 0.757038 1.14550 0.768671 1.14600 0.772257 1.14650 0.719294 1.14700 0.680704 1.14750 0.730166 1.14800 0.853410 1.14850 0.870374 1.14900 0.825745 1.14950 0.776315 1.15000 0.763452 1.15050 0.841766 1.15100 0.853065 1.15150 0.852384 1.15200 0.817911 1.15250 0.766774 1.15300 0.821260 1.15350 0.864742 1.15400 0.826659 1.15450 0.847765 1.15500 0.885408 1.15550 0.868207 1.15600 0.874482 1.15650 0.913144 1.15700 0.924995 1.15750 0.900897 1.15800 0.897519 1.15850 0.915011 1.15900 0.906591 1.15950 0.918299 1.16000 0.911739 1.16050 0.907733 1.16100 0.936403 1.16150 0.949203 1.16200 0.944764 1.16250 0.948642 1.16300 0.972327 1.16350 0.969878 1.16400 0.969258 1.16450 0.974017 1.16500 0.958576 1.16550 0.945447 1.16600 0.950553 1.16650 0.961556 1.16700 0.966523 1.16750 0.973922 1.16800 0.973221 1.16850 0.972920 1.16900 0.978206 1.16950 0.980222 1.17000 0.981184 1.17050 0.976008 1.17100 0.976547 1.17150 0.982596 1.17200 0.979140 1.17250 0.974704 1.17300 0.974501 1.17350 0.958697 1.17400 0.938513 1.17450 0.958885 1.17500 0.975557 1.17550 0.975021 1.17600 0.988260 1.17650 0.994002 1.17700 0.980372 1.17750 0.949508 1.17800 0.949525 1.17850 0.972612 1.17900 0.981544 1.17950 0.969594 1.18000 0.975340 1.18050 0.987625 1.18100 0.977929 1.18150 0.941932 1.18200 0.916442 1.18250 0.949461 1.18300 0.982671 1.18350 0.986757 1.18400 0.969196 1.18450 0.951621 1.18500 0.956697 1.18550 0.978990 1.18600 0.988531 1.18650 0.985182 1.18700 0.976861 1.18750 0.954704 1.18800 0.939069 1.18850 0.951637 1.18900 0.971985 1.18950 0.982253 1.19000 0.984752 1.19050 0.980359 1.19100 0.981037 1.19150 0.985026 1.19200 0.987986 1.19250 0.991293 1.19300 0.983971 1.19350 0.974746 1.19400 0.984188 1.19450 0.988584 1.19500 0.983569 1.19550 0.980270 1.19600 0.982935 1.19650 0.987270 1.19700 0.986618 1.19750 0.978813 1.19800 0.980855 1.19850 0.971897 1.19900 0.961843 1.19950 0.974741 1.20000 0.983190 1.20050 0.981964 1.20100 0.978773 1.20150 0.973377 1.20200 0.974917 1.20250 0.985326 1.20300 0.977496 1.20350 0.944434 1.20400 0.936448 1.20450 0.961981 1.20500 0.968605 1.20550 0.981381 1.20600 0.989106 1.20650 0.982717 1.20700 0.977013 1.20750 0.976124 1.20800 0.976634 1.20850 0.978362 1.20900 0.976562 1.20950 0.977756 1.21000 0.982973 1.21050 0.989250 1.21100 0.982825 1.21150 0.975368 1.21200 0.980099 1.21250 0.985002 1.21300 0.991563 1.21350 0.991791 1.21400 0.985006 1.21450 0.981860 1.21500 0.983106 1.21550 0.988560 1.21600 0.993286 1.21650 0.990601 1.21700 0.990397 1.21750 0.993539 1.21800 0.990053 1.21850 0.986350 1.21900 0.983398 1.21950 0.984957 1.22000 0.988633 1.22050 0.991860 1.22100 0.992328 1.22150 0.986436 1.22200 0.985590 1.22250 0.987027 1.22300 0.988197 1.22350 0.988667 1.22400 0.990009 1.22450 0.993038 1.22500 0.994105 1.22550 0.994089 1.22600 0.995171 1.22650 0.993444 1.22700 0.990217 1.22750 0.992936 1.22800 0.996877 1.22850 0.997753 1.22900 0.996750 1.22950 0.995914 1.23000 0.996826 1.23050 0.998364 1.23100 0.998967 1.23150 0.998883 1.23200 0.998834 1.23250 0.997977 1.23300 0.996776 1.23350 0.997367 1.23400 0.999008 1.23450 0.999468 1.23500 0.999303 1.23550 0.999318 1.23600 0.999496 1.23650 0.999138 1.23700 0.999013 1.23750 0.999507 1.23800 0.999662 1.23850 0.999657 1.23900 0.999799 1.23950 0.999921 1.24000 0.999819 1.24050 0.999496 1.24100 0.999474 1.24150 0.999785 1.24200 0.999937 1.24250 0.999972 1.24300 0.999982 1.24350 0.999936 1.24400 0.999796 1.24450 0.999773 1.24500 0.999830 1.24550 0.999858 1.24600 0.999864 1.24650 0.999655 1.24700 0.999669 1.24750 0.999586 1.24800 0.998969 1.24850 0.999182 1.24900 0.999223 1.24950 0.998261 1.25000 0.998700 1.25050 0.998587 1.25100 0.996748 1.25150 0.997608 1.25200 0.997834 1.25250 0.994814 1.25300 0.995997 1.25350 0.997178 1.25400 0.992464 1.25450 0.993117 1.25500 0.996493 1.25550 0.991123 1.25600 0.989697 1.25650 0.995638 1.25700 0.991237 1.25750 0.985451 1.25800 0.992316 1.25850 0.990902 1.25900 0.979553 1.25950 0.981838 1.26000 0.983431 1.26050 0.968600 1.26100 0.960381 1.26150 0.963959 1.26200 0.953670 1.26250 0.937863 1.26300 0.940169 1.26350 0.939693 1.26400 0.924447 1.26450 0.920700 1.26500 0.930985 1.26550 0.928900 1.26600 0.919060 1.26650 0.929692 1.26700 0.945111 1.26750 0.945282 1.26800 0.899087 1.26850 0.784339 1.26900 0.758176 1.26950 0.853277 1.27000 0.930262 1.27050 0.957934 1.27100 0.963815 1.27150 0.964836 1.27200 0.961788 1.27250 0.961196 1.27300 0.961872 1.27350 0.967564 1.27400 0.963418 1.27450 0.966112 1.27500 0.969241 1.27550 0.976962 1.27600 0.973136 1.27650 0.973427 1.27700 0.980372 1.27750 0.984600 1.27800 0.985305 1.27850 0.982528 1.27900 0.989911 1.27950 0.992007 1.28000 0.990550 1.28050 0.989450 1.28100 0.993592 1.28150 0.997412 1.28200 0.995688 1.28250 0.993663 1.28300 0.996647 1.28350 0.998384 1.28400 0.997067 1.28450 0.994882 1.28500 0.996985 1.28550 0.999208 1.28600 0.998780 1.28650 0.997108 1.28700 0.997172 1.28750 0.998351 1.28800 0.997678 1.28850 0.995288 1.28900 0.994508 1.28950 0.996863 1.29000 0.998151 1.29050 0.998247 1.29100 0.997249 1.29150 0.994203 1.29200 0.993317 1.29250 0.995928 1.29300 0.997616 1.29350 0.997860 1.29400 0.997272 1.29450 0.997292 1.29500 0.995935 1.29550 0.993070 1.29600 0.993259 1.29650 0.993791 1.29700 0.989695 1.29750 0.988357 1.29800 0.993488 1.29850 0.996987 1.29900 0.995085 1.29950 0.988373 1.30000 0.985354 1.30050 0.982596 1.30100 0.984381 1.30150 0.992523 1.30200 0.994774 1.30250 0.988664 1.30300 0.980634 1.30350 0.971293 1.30400 0.962918 1.30450 0.969263 1.30500 0.987720 1.30550 0.991306 1.30600 0.985716 1.30650 0.968053 1.30700 0.967671 1.30750 0.978376 1.30800 0.971561 1.30850 0.979002 1.30900 0.984302 1.30950 0.962535 1.31000 0.950377 1.31050 0.956719 1.31100 0.976448 1.31150 0.990140 1.31200 0.978798 1.31250 0.966486 1.31300 0.956840 1.31350 0.934889 1.31400 0.939970 1.31450 0.958249 1.31500 0.960607 1.31550 0.962254 1.31600 0.974172 1.31650 0.970949 1.31700 0.954463 1.31750 0.971178 1.31800 0.968766 1.31850 0.946931 1.31900 0.945659 1.31950 0.942867 1.32000 0.918592 1.32050 0.929011 1.32100 0.950730 1.32150 0.945695 1.32200 0.955817 1.32250 0.946827 1.32300 0.926178 1.32350 0.936737 1.32400 0.941362 1.32450 0.956181 1.32500 0.965625 1.32550 0.949400 1.32600 0.957974 1.32650 0.958642 1.32700 0.939564 1.32750 0.937278 1.32800 0.916788 1.32850 0.879224 1.32900 0.878624 1.32950 0.913538 1.33000 0.924358 1.33050 0.907027 1.33100 0.864149 1.33150 0.834164 1.33200 0.830201 1.33250 0.843688 1.33300 0.889382 1.33350 0.871627 1.33400 0.859372 1.33450 0.904001 1.33500 0.918914 1.33550 0.905105 1.33600 0.866219 1.33650 0.897052 1.33700 0.880653 1.33750 0.842492 1.33800 0.866221 1.33850 0.905274 1.33900 0.903538 1.33950 0.903040 1.34000 0.857331 1.34050 0.827196 1.34100 0.874881 1.34150 0.881135 1.34200 0.912678 1.34250 0.918185 1.34300 0.902951 1.34350 0.859701 1.34400 0.738835 1.34450 0.709692 1.34500 0.798344 1.34550 0.816491 1.34600 0.786334 1.34650 0.762971 1.34700 0.768541 1.34750 0.643887 1.34800 0.491810 1.34850 0.508059 1.34900 0.629390 1.34950 0.706715 1.35000 0.576285 1.35050 0.462633 1.35100 0.527266 1.35150 0.509747 1.35200 0.483102 1.35250 0.445504 1.35300 0.356107 1.35350 0.342676 1.35400 0.328445 1.35450 0.197219 1.35500 0.164488 1.35550 0.218198 1.35600 0.276226 1.35650 0.365766 1.35700 0.283954 1.35750 0.194598 1.35800 0.208406 1.35850 0.205095 1.35900 0.199447 1.35950 0.156136 1.36000 0.177611 1.36050 0.153180 1.36100 6.62577E-02 1.36150 2.66995E-02 1.36200 1.51404E-02 1.36250 5.98374E-02 1.36300 0.209144 1.36350 0.297767 1.36400 0.196222 1.36450 6.98286E-02 1.36500 4.96920E-02 1.36550 0.135551 1.36600 0.302574 1.36650 0.337787 1.36700 0.217834 1.36750 1.00855E-01 1.36800 4.70564E-02 1.36850 6.26280E-02 1.36900 0.149675 1.36950 0.198916 1.37000 0.149135 1.37050 0.118841 1.37100 9.56551E-02 1.37150 0.140676 1.37200 0.195606 1.37250 0.283089 1.37300 0.326103 1.37350 0.354299 1.37400 0.386147 1.37450 0.322281 1.37500 0.360891 1.37550 0.453086 1.37600 0.377087 1.37650 0.327164 1.37700 0.320174 1.37750 0.495142 1.37800 0.519425 1.37850 0.294434 1.37900 0.276679 1.37950 0.407687 1.38000 0.299731 1.38050 1.03512E-01 1.38100 0.109494 1.38150 0.214145 1.38200 0.162237 1.38250 6.52233E-02 1.38300 6.09866E-02 1.38350 0.109256 1.38400 0.178010 1.38450 0.220932 1.38500 0.158425 1.38550 0.168395 1.38600 0.233275 1.38650 0.331220 1.38700 0.442871 1.38750 0.345280 1.38800 0.172340 1.38850 0.275885 1.38900 0.499047 1.38950 0.535737 1.39000 0.472701 1.39050 0.478809 1.39100 0.483321 1.39150 0.449178 1.39200 0.237272 1.39250 0.132192 1.39300 0.295937 1.39350 0.433298 1.39400 0.392175 1.39450 0.258722 1.39500 1.01425E-01 1.39550 5.64375E-02 1.39600 7.69295E-02 1.39650 0.126794 1.39700 0.284888 1.39750 0.501226 1.39800 0.592373 1.39850 0.580968 1.39900 0.481826 1.39950 0.249707 1.40000 0.114295 1.40050 6.69293E-02 1.40100 7.63803E-02 1.40150 0.167137 1.40200 0.417217 1.40250 0.602445 1.40300 0.547245 1.40350 0.490765 1.40400 0.338334 1.40450 0.167855 1.40500 0.142995 1.40550 0.336699 1.40600 0.535478 1.40650 0.441941 1.40700 0.209916 1.40750 0.264541 1.40800 0.480982 1.40850 0.469298 1.40900 0.267194 1.40950 0.176476 1.41000 0.328066 1.41050 0.466136 1.41100 0.497142 1.41150 0.517930 1.41200 0.494083 1.41250 0.528470 1.41300 0.670770 1.41350 0.543994 1.41400 0.315460 1.41450 0.215553 1.41500 0.281061 1.41550 0.462164 1.41600 0.679135 1.41650 0.731140 1.41700 0.647579 1.41750 0.573938 1.41800 0.580755 1.41850 0.508240 1.41900 0.292362 1.41950 0.289450 1.42000 0.447425 1.42050 0.533599 1.42100 0.596804 1.42150 0.673366 1.42200 0.744543 1.42250 0.689326 1.42300 0.530980 1.42350 0.431204 1.42400 0.491623 1.42450 0.675004 1.42500 0.674831 1.42550 0.558107 1.42600 0.613803 1.42650 0.753543 1.42700 0.695788 1.42750 0.561568 1.42800 0.504341 1.42850 0.511057 1.42900 0.608029 1.42950 0.705028 1.43000 0.748174 1.43050 0.790472 1.43100 0.613405 1.43150 0.423867 1.43200 0.373470 1.43250 0.385777 1.43300 0.555137 1.43350 0.672079 1.43400 0.582412 1.43450 0.536952 1.43500 0.644952 1.43550 0.689954 1.43600 0.636357 1.43650 0.633261 1.43700 0.588406 1.43750 0.429183 1.43800 0.480450 1.43850 0.686126 1.43900 0.692260 1.43950 0.588509 1.44000 0.660672 1.44050 0.723990 1.44100 0.676157 1.44150 0.617975 1.44200 0.686400 1.44250 0.661564 1.44300 0.628641 1.44350 0.763524 1.44400 0.785264 1.44450 0.759266 1.44500 0.672885 1.44550 0.438539 1.44600 0.472890 1.44650 0.673442 1.44700 0.705155 1.44750 0.771982 1.44800 0.831514 1.44850 0.835559 1.44900 0.856568 1.44950 0.796607 1.45000 0.602390 1.45050 0.417076 1.45100 0.460663 1.45150 0.674837 1.45200 0.740778 1.45250 0.746815 1.45300 0.790204 1.45350 0.875651 1.45400 0.906380 1.45450 0.855457 1.45500 0.740161 1.45550 0.706508 1.45600 0.833406 1.45650 0.890081 1.45700 0.867164 1.45750 0.829506 1.45800 0.862152 1.45850 0.921453 1.45900 0.933240 1.45950 0.903528 1.46000 0.796659 1.46050 0.751729 1.46100 0.795446 1.46150 0.818978 1.46200 0.886126 1.46250 0.854437 1.46300 0.714736 1.46350 0.744172 1.46400 0.885306 1.46450 0.899101 1.46500 0.749455 1.46550 0.696033 1.46600 0.719099 1.46650 0.670840 1.46700 0.677860 1.46750 0.741448 1.46800 0.811650 1.46850 0.882057 1.46900 0.821356 1.46950 0.689987 1.47000 0.681842 1.47050 0.596856 1.47100 0.555473 1.47150 0.693104 1.47200 0.692504 1.47250 0.643489 1.47300 0.730927 1.47350 0.761093 1.47400 0.825224 1.47450 0.926959 1.47500 0.933974 1.47550 0.829277 1.47600 0.768126 1.47650 0.807752 1.47700 0.773674 1.47750 0.737137 1.47800 0.728135 1.47850 0.838802 1.47900 0.856256 1.47950 0.790548 1.48000 0.731276 1.48050 0.698974 1.48100 0.796290 1.48150 0.777120 1.48200 0.738904 1.48250 0.846352 1.48300 0.913145 1.48350 0.922818 1.48400 0.878982 1.48450 0.829555 1.48500 0.866690 1.48550 0.882665 1.48600 0.858853 1.48650 0.794350 1.48700 0.795396 1.48750 0.832984 1.48800 0.842272 1.48850 0.892043 1.48900 0.925376 1.48950 0.895341 1.49000 0.918729 1.49050 0.964423 1.49100 0.923781 1.49150 0.867480 1.49200 0.900942 1.49250 0.930368 1.49300 0.941320 1.49350 0.958792 1.49400 0.955063 1.49450 0.939097 1.49500 0.915747 1.49550 0.911000 1.49600 0.912630 1.49650 0.914039 1.49700 0.951242 1.49750 0.962185 1.49800 0.942913 1.49850 0.953168 1.49900 0.962683 1.49950 0.962687 1.50000 0.976127 1.50050 0.987873 1.50100 0.988915 1.50150 0.978267 1.50200 0.968245 1.50250 0.964149 1.50300 0.952026 1.50350 0.930347 1.50400 0.910647 1.50450 0.921950 1.50500 0.949984 1.50550 0.978659 1.50600 0.990180 1.50650 0.994654 1.50700 0.989170 1.50750 0.984464 1.50800 0.970488 1.50850 0.939241 1.50900 0.940464 1.50950 0.975258 1.51000 0.989160 1.51050 0.988591 1.51100 0.989222 1.51150 0.991763 1.51200 0.989753 1.51250 0.982265 1.51300 0.980492 1.51350 0.978270 1.51400 0.977114 1.51450 0.983816 1.51500 0.989752 1.51550 0.993510 1.51600 0.987815 1.51650 0.981240 1.51700 0.981664 1.51750 0.982419 1.51800 0.986983 1.51850 0.987771 1.51900 0.984376 1.51950 0.988020 1.52000 0.992537 1.52050 0.993898 1.52100 0.996880 1.52150 0.995895 1.52200 0.995165 1.52250 0.998102 1.52300 0.998530 1.52350 0.997494 1.52400 0.996642 1.52450 0.994038 1.52500 0.993946 1.52550 0.993713 1.52600 0.993061 1.52650 0.992550 1.52700 0.992221 1.52750 0.994028 1.52800 0.996662 1.52850 0.996541 1.52900 0.996339 1.52950 0.996204 1.53000 0.995676 1.53050 0.996101 1.53100 0.994965 1.53150 0.994058 1.53200 0.995719 1.53250 0.995789 1.53300 0.994631 1.53350 0.993077 1.53400 0.991478 1.53450 0.990239 1.53500 0.989070 1.53550 0.989680 1.53600 0.991399 1.53650 0.993151 1.53700 0.994556 1.53750 0.996615 1.53800 0.997626 1.53850 0.996225 1.53900 0.994022 1.53950 0.992960 1.54000 0.992898 1.54050 0.992830 1.54100 0.993067 1.54150 0.993408 1.54200 0.993820 1.54250 0.994946 1.54300 0.996148 1.54350 0.997009 1.54400 0.997002 1.54450 0.997351 1.54500 0.998492 1.54550 0.998804 1.54600 0.998827 1.54650 0.999161 1.54700 0.999538 1.54750 0.999680 1.54800 0.999747 1.54850 0.999898 1.54900 0.999957 1.54950 0.999908 1.55000 0.999905 1.55050 0.999869 1.55100 0.999727 1.55150 0.999531 1.55200 0.999232 1.55250 0.999521 1.55300 0.999876 1.55350 0.999927 1.55400 0.999782 1.55450 0.999738 1.55500 0.999903 1.55550 0.999961 1.55600 0.999858 1.55650 0.999794 1.55700 0.999909 1.55750 0.999950 1.55800 0.999853 1.55850 0.999752 1.55900 0.999777 1.55950 0.999810 1.56000 0.999819 1.56050 0.999835 1.56100 0.999836 1.56150 0.999811 1.56200 0.999451 1.56250 0.999325 1.56300 0.999658 1.56350 0.999748 1.56400 0.999556 1.56450 0.999502 1.56500 0.999757 1.56550 0.999748 1.56600 0.999569 1.56650 0.999419 1.56700 0.998895 1.56750 0.997646 1.56800 0.995226 1.56850 0.991109 1.56900 0.984467 1.56950 0.975234 1.57000 0.964163 1.57050 0.952727 1.57100 0.942431 1.57150 0.934682 1.57200 0.930290 1.57250 0.929652 1.57300 0.932669 1.57350 0.939408 1.57400 0.950297 1.57450 0.964999 1.57500 0.979779 1.57550 0.983609 1.57600 0.974103 1.57650 0.962790 1.57700 0.955258 1.57750 0.951500 1.57800 0.950629 1.57850 0.951747 1.57900 0.954432 1.57950 0.958269 1.58000 0.962654 1.58050 0.967323 1.58100 0.972054 1.58150 0.976600 1.58200 0.980834 1.58250 0.984497 1.58300 0.987513 1.58350 0.990428 1.58400 0.992995 1.58450 0.994813 1.58500 0.996168 1.58550 0.997180 1.58600 0.997703 1.58650 0.998076 1.58700 0.998400 1.58750 0.998924 1.58800 0.999493 1.58850 0.999719 1.58900 0.999806 1.58950 0.999795 1.59000 0.999626 1.59050 0.999606 1.59100 0.999684 1.59150 0.999478 1.59200 0.999361 1.59250 0.999411 1.59300 0.999673 1.59350 0.999755 1.59400 0.999421 1.59450 0.999211 1.59500 0.999479 1.59550 0.999537 1.59600 0.999160 1.59650 0.998724 1.59700 0.998103 1.59750 0.997171 1.59800 0.995456 1.59850 0.991753 1.59900 0.985847 1.59950 0.977709 1.60000 0.967902 1.60050 0.957382 1.60100 0.947361 1.60150 0.939081 1.60200 0.933282 1.60250 0.930844 1.60300 0.931917 1.60350 0.936357 1.60400 0.944567 1.60450 0.956796 1.60500 0.972188 1.60550 0.984489 1.60600 0.983245 1.60650 0.972040 1.60700 0.961620 1.60750 0.954897 1.60800 0.951228 1.60850 0.950145 1.60900 0.951139 1.60950 0.953324 1.61000 0.956358 1.61050 0.960237 1.61100 0.964884 1.61150 0.969655 1.61200 0.974316 1.61250 0.978735 1.61300 0.982687 1.61350 0.986299 1.61400 0.989509 1.61450 0.991717 1.61500 0.993204 1.61550 0.994340 1.61600 0.995103 1.61650 0.995492 1.61700 0.996078 1.61750 0.996861 1.61800 0.997288 1.61850 0.997381 1.61900 0.997678 1.61950 0.998421 1.62000 0.998802 1.62050 0.998776 1.62100 0.998729 1.62150 0.998804 1.62200 0.998989 1.62250 0.999105 1.62300 0.999097 1.62350 0.998694 1.62400 0.998469 1.62450 0.999025 1.62500 0.999183 1.62550 0.998587 1.62600 0.998171 1.62650 0.998464 1.62700 0.998196 1.62750 0.997820 1.62800 0.997434 1.62850 0.997274 1.62900 0.997993 1.62950 0.998421 1.63000 0.997172 1.63050 0.994920 1.63100 0.996114 1.63150 0.997760 1.63200 0.997498 1.63250 0.995306 1.63300 0.993580 1.63350 0.995311 1.63400 0.997154 1.63450 0.997027 1.63500 0.993315 1.63550 0.990432 1.63600 0.994459 1.63650 0.996644 1.63700 0.994306 1.63750 0.986407 1.63800 0.986976 1.63850 0.994173 1.63900 0.994776 1.63950 0.991007 1.64000 0.980729 1.64050 0.976942 1.64100 0.986842 1.64150 0.990721 1.64200 0.988497 1.64250 0.976916 1.64300 0.968928 1.64350 0.982052 1.64400 0.991232 1.64450 0.992525 1.64500 0.982766 1.64550 0.967816 1.64600 0.980126 1.64650 0.993557 1.64700 0.994296 1.64750 0.988097 1.64800 0.973328 1.64850 0.972751 1.64900 0.984921 1.64950 0.989340 1.65000 0.989238 1.65050 0.978063 1.65100 0.967990 1.65150 0.981931 1.65200 0.992765 1.65250 0.995613 1.65300 0.991795 1.65350 0.978515 1.65400 0.980623 1.65450 0.993565 1.65500 0.995874 1.65550 0.995054 1.65600 0.991908 1.65650 0.987227 1.65700 0.991630 1.65750 0.997000 1.65800 0.998547 1.65850 0.998189 1.65900 0.995499 1.65950 0.993695 1.66000 0.996784 1.66050 0.999005 1.66100 0.998375 1.66150 0.996868 1.66200 0.994010 1.66250 0.993167 1.66300 0.996674 1.66350 0.997982 1.66400 0.998521 1.66450 0.995489 1.66500 0.971076 1.66550 0.927306 1.66600 0.923475 1.66650 0.952526 1.66700 0.975791 1.66750 0.989480 1.66800 0.994668 1.66850 0.995675 1.66900 0.997153 1.66950 0.998042 1.67000 0.998188 1.67050 0.997299 1.67100 0.995376 1.67150 0.995133 1.67200 0.997900 1.67250 0.999163 1.67300 0.999223 1.67350 0.998118 1.67400 0.992682 1.67450 0.988228 1.67500 0.994055 1.67550 0.997917 1.67600 0.998936 1.67650 0.998614 1.67700 0.993459 1.67750 0.984968 1.67800 0.989630 1.67850 0.997209 1.67900 0.999228 1.67950 0.999313 1.68000 0.997405 1.68050 0.990808 1.68100 0.989273 1.68150 0.995740 1.68200 0.998706 1.68250 0.999319 1.68300 0.998376 1.68350 0.990795 1.68400 0.980805 1.68450 0.988967 1.68500 0.997343 1.68550 0.998664 1.68600 0.998913 1.68650 0.997086 1.68700 0.990052 1.68750 0.988390 1.68800 0.995657 1.68850 0.998457 1.68900 0.998063 1.68950 0.997635 1.69000 0.994119 1.69050 0.985778 1.69100 0.987120 1.69150 0.992654 1.69200 0.994602 1.69250 0.996123 1.69300 0.997699 1.69350 0.995098 1.69400 0.990797 1.69450 0.992972 1.69500 0.996296 1.69550 0.998484 1.69600 0.998157 1.69650 0.992445 1.69700 0.984021 1.69750 0.985571 1.69800 0.994299 1.69850 0.997533 1.69900 0.997159 1.69950 0.994233 1.70000 0.992502 1.70050 0.990767 1.70100 0.988779 1.70150 0.993147 1.70200 0.994740 1.70250 0.991910 1.70300 0.990486 1.70350 0.991295 1.70400 0.993332 1.70450 0.994203 1.70500 0.991526 1.70550 0.988988 1.70600 0.989099 1.70650 0.987328 1.70700 0.986778 1.70750 0.985875 1.70800 0.981381 1.70850 0.972679 1.70900 0.977266 1.70950 0.989928 1.71000 0.992930 1.71050 0.991058 1.71100 0.993445 1.71150 0.996543 1.71200 0.996317 1.71250 0.995869 1.71300 0.995553 1.71350 0.990737 1.71400 0.979007 1.71450 0.976442 1.71500 0.988320 1.71550 0.991714 1.71600 0.986361 1.71650 0.989698 1.71700 0.995886 1.71750 0.997766 1.71800 0.998281 1.71850 0.998016 1.71900 0.998005 1.71950 0.997728 1.72000 0.995841 1.72050 0.988585 1.72100 0.967241 1.72150 0.961070 1.72200 0.981616 1.72250 0.989215 1.72300 0.983622 1.72350 0.971844 1.72400 0.970175 1.72450 0.969362 1.72500 0.978757 1.72550 0.988441 1.72600 0.986625 1.72650 0.987573 1.72700 0.990403 1.72750 0.991697 1.72800 0.989576 1.72850 0.980966 1.72900 0.981130 1.72950 0.991560 1.73000 0.995457 1.73050 0.993014 1.73100 0.990766 1.73150 0.976093 1.73200 0.939757 1.73250 0.941933 1.73300 0.980472 1.73350 0.995811 1.73400 0.996484 1.73450 0.994913 1.73500 0.989011 1.73550 0.973590 1.73600 0.962304 1.73650 0.961789 1.73700 0.973036 1.73750 0.990482 1.73800 0.994329 1.73850 0.994816 1.73900 0.993127 1.73950 0.979801 1.74000 0.973763 1.74050 0.978315 1.74100 0.951173 1.74150 0.940155 1.74200 0.973486 1.74250 0.993695 1.74300 0.997225 1.74350 0.994541 1.74400 0.974627 1.74450 0.957539 1.74500 0.980048 1.74550 0.994150 1.74600 0.978571 1.74650 0.918166 1.74700 0.877017 1.74750 0.922594 1.74800 0.978262 1.74850 0.995971 1.74900 0.996797 1.74950 0.996542 1.75000 0.996631 1.75050 0.992819 1.75100 0.967950 1.75150 0.934713 1.75200 0.961233 1.75250 0.989495 1.75300 0.994754 1.75350 0.997510 1.75400 0.995987 1.75450 0.977098 1.75500 0.936040 1.75550 0.947272 1.75600 0.977622 1.75650 0.954346 1.75700 0.918975 1.75750 0.923623 1.75800 0.968881 1.75850 0.994627 1.75900 0.998502 1.75950 0.998742 1.76000 0.995493 1.76050 0.976922 1.76100 0.952603 1.76150 0.970133 1.76200 0.975319 1.76250 0.948511 1.76300 0.940851 1.76350 0.969066 1.76400 0.991622 1.76450 0.992540 1.76500 0.959453 1.76550 0.834546 1.76600 0.772715 1.76650 0.901742 1.76700 0.980070 1.76750 0.990129 1.76800 0.986865 1.76850 0.985082 1.76900 0.979604 1.76950 0.962794 1.77000 0.950618 1.77050 0.931784 1.77100 0.942754 1.77150 0.981390 1.77200 0.990495 1.77250 0.987907 1.77300 0.984096 1.77350 0.951467 1.77400 0.894844 1.77450 0.907695 1.77500 0.952940 1.77550 0.943479 1.77600 0.884594 1.77650 0.894857 1.77700 0.957899 1.77750 0.974114 1.77800 0.934478 1.77850 0.844515 1.77900 0.832301 1.77950 0.927918 1.78000 0.974862 1.78050 0.948595 1.78100 0.846457 1.78150 0.831929 1.78200 0.931842 1.78250 0.978378 1.78300 0.979546 1.78350 0.958535 1.78400 0.889102 1.78450 0.758125 1.78500 0.738123 1.78550 0.830661 1.78600 0.854463 1.78650 0.886765 1.78700 0.868959 1.78750 0.899529 1.78800 0.959811 1.78850 0.951439 1.78900 0.943822 1.78950 0.969998 1.79000 0.936923 1.79050 0.847680 1.79100 0.819047 1.79150 0.858394 1.79200 0.860120 1.79250 0.835251 1.79300 0.812922 1.79350 0.739816 1.79400 0.755525 1.79450 0.858164 1.79500 0.856749 1.79550 0.841673 1.79600 0.841466 1.79650 0.803639 1.79700 0.784590 1.79750 0.847177 1.79800 0.840571 1.79850 0.885013 1.79900 0.922763 1.79950 0.780291 1.80000 0.584666 1.80050 0.506150 1.80100 0.471652 1.80150 0.512914 1.80200 0.568489 1.80250 0.591665 1.80300 0.677113 1.80350 0.699647 1.80400 0.736619 1.80450 0.830771 1.80500 0.855857 1.80550 0.690749 1.80600 0.438181 1.80650 0.411676 1.80700 0.566936 1.80750 0.610007 1.80800 0.732577 1.80850 0.782688 1.80900 0.726123 1.80950 0.764853 1.81000 0.711491 1.81050 0.489735 1.81100 0.388435 1.81150 0.506124 1.81200 0.510681 1.81250 0.387894 1.81300 0.388558 1.81350 0.579377 1.81400 0.761626 1.81450 0.764149 1.81500 0.537874 1.81550 0.332955 1.81600 0.358867 1.81650 0.495185 1.81700 0.572971 1.81750 0.679194 1.81800 0.647414 1.81850 0.448197 1.81900 0.502743 1.81950 0.529272 1.82000 0.283356 1.82050 0.116465 1.82100 0.180236 1.82150 0.217103 1.82200 0.180477 1.82250 0.254541 1.82300 0.503638 1.82350 0.767083 1.82400 0.841912 1.82450 0.745811 1.82500 0.595845 1.82550 0.484293 1.82600 0.267268 1.82650 0.176834 1.82700 0.368454 1.82750 0.478558 1.82800 0.339694 1.82850 0.171749 1.82900 0.173364 1.82950 0.276971 1.83000 0.240067 1.83050 0.207665 1.83100 0.176644 1.83150 0.227948 1.83200 0.341251 1.83250 0.261043 1.83300 0.258407 1.83350 0.412062 1.83400 0.408319 1.83450 0.219426 1.83500 8.46848E-02 1.83550 6.81353E-02 1.83600 4.97111E-02 1.83650 5.47538E-02 1.83700 8.75217E-02 1.83750 5.25519E-02 1.83800 4.88797E-02 1.83850 0.154729 1.83900 0.245404 1.83950 0.154266 1.84000 5.04592E-02 1.84050 8.40258E-02 1.84100 0.134459 1.84150 7.03485E-02 1.84200 2.09530E-02 1.84250 8.08668E-02 1.84300 0.224701 1.84350 0.273863 1.84400 0.325278 1.84450 0.504203 1.84500 0.597827 1.84550 0.501915 1.84600 0.292331 1.84650 1.03795E-01 1.84700 1.76967E-02 1.84750 5.70865E-03 1.84800 5.19340E-03 1.84850 1.80083E-02 1.84900 8.55736E-02 1.84950 0.206820 1.85000 0.212377 1.85050 0.132717 1.85100 0.228723 1.85150 0.463528 1.85200 0.513124 1.85250 0.312798 1.85300 9.91987E-02 1.85350 2.73874E-02 1.85400 3.10382E-02 1.85450 1.03641E-01 1.85500 0.240103 1.85550 0.348119 1.85600 0.256409 1.85650 9.17837E-02 1.85700 4.44364E-02 1.85750 0.139329 1.85800 0.331460 1.85850 0.386931 1.85900 0.255882 1.85950 8.92806E-02 1.86000 1.56786E-02 1.86050 2.36687E-02 1.86100 0.136774 1.86150 0.388707 1.86200 0.562145 1.86250 0.481994 1.86300 0.365988 1.86350 0.376995 1.86400 0.258770 1.86450 0.144683 1.86500 0.229582 1.86550 0.439161 1.86600 0.595415 1.86650 0.513722 1.86700 0.269665 1.86750 7.28503E-02 1.86800 2.86421E-02 1.86850 8.05517E-02 1.86900 0.106550 1.86950 5.89996E-02 1.87000 2.42958E-02 1.87050 1.71540E-02 1.87100 8.70671E-03 1.87150 2.33764E-02 1.87200 7.93091E-02 1.87250 8.55701E-02 1.87300 2.92135E-02 1.87350 7.85538E-03 1.87400 3.38997E-02 1.87450 8.69694E-02 1.87500 8.87879E-02 1.87550 7.36377E-02 1.87600 1.00062E-01 1.87650 8.17879E-02 1.87700 4.91521E-02 1.87750 0.122091 1.87800 0.243875 1.87850 0.389643 1.87900 0.517754 1.87950 0.519130 1.88000 0.508667 1.88050 0.316157 1.88100 0.173518 1.88150 0.255371 1.88200 0.476100 1.88250 0.588994 1.88300 0.520819 1.88350 0.331499 1.88400 0.131395 1.88450 0.178703 1.88500 0.342564 1.88550 0.387104 1.88600 0.440294 1.88650 0.384287 1.88700 0.327282 1.88750 0.542175 1.88800 0.729578 1.88850 0.729931 1.88900 0.615871 1.88950 0.370293 1.89000 0.125563 1.89050 0.128184 1.89100 0.288727 1.89150 0.297685 1.89200 0.169225 1.89250 0.147100 1.89300 0.200545 1.89350 0.190246 1.89400 0.234055 1.89450 0.413328 1.89500 0.578752 1.89550 0.660335 1.89600 0.579465 1.89650 0.531565 1.89700 0.494070 1.89750 0.293291 1.89800 0.159377 1.89850 0.145070 1.89900 6.59336E-02 1.89950 1.57474E-02 1.90000 1.26247E-02 1.90050 4.09072E-02 1.90100 0.158473 1.90150 0.322464 1.90200 0.362018 1.90250 0.205565 1.90300 8.48610E-02 1.90350 0.183224 1.90400 0.316524 1.90450 0.236446 1.90500 8.30411E-02 1.90550 2.20497E-02 1.90600 2.54519E-02 1.90650 3.64896E-02 1.90700 0.108216 1.90750 0.337190 1.90800 0.525159 1.90850 0.482315 1.90900 0.405334 1.90950 0.483618 1.91000 0.439805 1.91050 0.287100 1.91100 0.198571 1.91150 0.122362 1.91200 0.149485 1.91250 0.219584 1.91300 0.168011 1.91350 6.53308E-02 1.91400 5.08557E-02 1.91450 0.134771 1.91500 0.310537 1.91550 0.422834 1.91600 0.266148 1.91650 0.137026 1.91700 0.274917 1.91750 0.568813 1.91800 0.756328 1.91850 0.740929 1.91900 0.553928 1.91950 0.250883 1.92000 6.11322E-02 1.92050 2.58625E-02 1.92100 8.31992E-02 1.92150 0.277266 1.92200 0.546590 1.92250 0.703957 1.92300 0.704167 1.92350 0.512093 1.92400 0.218637 1.92450 0.234665 1.92500 0.542120 1.92550 0.734648 1.92600 0.669011 1.92650 0.491648 1.92700 0.257205 1.92750 0.264051 1.92800 0.369206 1.92850 0.302842 1.92900 0.418468 1.92950 0.602152 1.93000 0.487219 1.93050 0.306640 1.93100 0.260635 1.93150 0.339334 1.93200 0.500856 1.93250 0.616774 1.93300 0.619693 1.93350 0.580344 1.93400 0.431508 1.93450 0.531992 1.93500 0.757475 1.93550 0.771910 1.93600 0.624667 1.93650 0.478980 1.93700 0.540739 1.93750 0.577286 1.93800 0.488617 1.93850 0.497161 1.93900 0.399613 1.93950 0.306515 1.94000 0.457610 1.94050 0.614259 1.94100 0.521632 1.94150 0.479325 1.94200 0.665395 1.94250 0.836420 1.94300 0.804259 1.94350 0.650314 1.94400 0.558456 1.94450 0.491433 1.94500 0.504787 1.94550 0.649515 1.94600 0.704404 1.94650 0.721354 1.94700 0.671476 1.94750 0.628802 1.94800 0.613201 1.94850 0.603658 1.94900 0.633286 1.94950 0.638534 1.95000 0.663765 1.95050 0.655430 1.95100 0.669548 1.95150 0.720225 1.95200 0.682669 1.95250 0.608920 1.95300 0.526445 1.95350 0.486591 1.95400 0.496520 1.95450 0.484241 1.95500 0.491300 1.95550 0.451325 1.95600 0.437327 1.95650 0.432061 1.95700 0.448548 1.95750 0.454386 1.95800 0.446968 1.95850 0.465756 1.95900 0.446269 1.95950 0.508316 1.96000 0.660921 1.96050 0.700766 1.96100 0.664026 1.96150 0.697099 1.96200 0.687160 1.96250 0.614468 1.96300 0.547593 1.96350 0.536336 1.96400 0.562797 1.96450 0.588990 1.96500 0.627330 1.96550 0.635671 1.96600 0.647841 1.96650 0.683231 1.96700 0.704657 1.96750 0.699117 1.96800 0.691477 1.96850 0.723825 1.96900 0.752994 1.96950 0.771480 1.97000 0.796069 1.97050 0.797955 1.97100 0.757150 1.97150 0.716151 1.97200 0.733529 1.97250 0.802412 1.97300 0.856930 1.97350 0.849135 1.97400 0.795526 1.97450 0.821585 1.97500 0.894606 1.97550 0.895768 1.97600 0.892699 1.97650 0.931530 1.97700 0.948029 1.97750 0.940579 1.97800 0.946013 1.97850 0.952906 1.97900 0.935200 1.97950 0.830717 1.98000 0.741971 1.98050 0.802358 1.98100 0.916834 1.98150 0.974485 1.98200 0.981750 1.98250 0.964425 1.98300 0.944212 1.98350 0.967332 1.98400 0.986558 1.98450 0.977321 1.98500 0.947129 1.98550 0.949520 1.98600 0.968415 1.98650 0.906401 1.98700 0.824194 1.98750 0.891949 1.98800 0.966978 1.98850 0.984228 1.98900 0.981862 1.98950 0.942798 1.99000 0.867579 1.99050 0.864036 1.99100 0.932131 1.99150 0.978125 1.99200 0.985413 1.99250 0.987140 1.99300 0.986963 1.99350 0.969279 1.99400 0.925177 1.99450 0.922377 1.99500 0.940895 1.99550 0.916483 1.99600 0.897388 1.99650 0.867044 1.99700 0.827800 1.99750 0.787334 1.99800 0.706908 1.99850 0.662155 1.99900 0.639285 1.99950 0.596910 2.00000 0.556002 2.00050 0.508995 2.00100 0.454164 2.00150 0.417463 2.00200 0.387244 2.00250 0.345502 2.00300 0.327869 2.00350 0.337062 2.00400 0.337982 2.00450 0.331677 2.00500 0.321837 2.00550 0.315961 2.00600 0.334940 2.00650 0.384449 2.00700 0.431995 2.00750 0.468816 2.00800 0.514937 2.00850 0.593274 2.00900 0.657419 2.00950 0.609583 2.01000 0.521058 2.01050 0.468812 2.01100 0.449696 2.01150 0.444837 2.01200 0.440626 2.01250 0.439943 2.01300 0.445357 2.01350 0.449248 2.01400 0.458862 2.01450 0.476211 2.01500 0.484873 2.01550 0.493869 2.01600 0.504679 2.01650 0.506091 2.01700 0.512109 2.01750 0.535956 2.01800 0.553449 2.01850 0.575841 2.01900 0.600710 2.01950 0.632571 2.02000 0.659412 2.02050 0.675746 2.02100 0.690374 2.02150 0.714045 2.02200 0.744452 2.02250 0.771781 2.02300 0.787411 2.02350 0.803735 2.02400 0.820653 2.02450 0.841601 2.02500 0.856356 2.02550 0.875177 2.02600 0.891883 2.02650 0.904355 2.02700 0.916050 2.02750 0.915351 2.02800 0.908367 2.02850 0.909366 2.02900 0.931483 2.02950 0.949025 2.03000 0.956729 2.03050 0.954635 2.03100 0.958649 2.03150 0.962757 2.03200 0.964469 2.03250 0.960821 2.03300 0.951341 2.03350 0.950733 2.03400 0.960386 2.03450 0.963544 2.03500 0.964312 2.03550 0.964373 2.03600 0.964186 2.03650 0.964009 2.03700 0.963889 2.03750 0.963145 2.03800 0.959963 2.03850 0.957111 2.03900 0.956403 2.03950 0.947628 2.04000 0.930549 2.04050 0.927770 2.04100 0.935863 2.04150 0.938058 2.04200 0.938262 2.04250 0.938662 2.04300 0.938092 2.04350 0.937561 2.04400 0.937251 2.04450 0.942568 2.04500 0.950601 2.04550 0.954354 2.04600 0.951335 2.04650 0.938762 2.04700 0.920234 2.04750 0.898897 2.04800 0.875485 2.04850 0.853501 2.04900 0.832114 2.04950 0.809014 2.05000 0.785837 2.05050 0.768295 2.05100 0.755254 2.05150 0.733945 2.05200 0.714702 2.05250 0.702360 2.05300 0.697071 2.05350 0.683016 2.05400 0.665835 2.05450 0.659634 2.05500 0.662759 2.05550 0.669362 2.05600 0.666639 2.05650 0.662827 2.05700 0.674628 2.05750 0.695444 2.05800 0.719976 2.05850 0.745888 2.05900 0.778991 2.05950 0.827200 2.06000 0.877946 2.06050 0.889037 2.06100 0.842994 2.06150 0.802663 2.06200 0.776576 2.06250 0.753178 2.06300 0.739510 2.06350 0.735301 2.06400 0.732821 2.06450 0.731170 2.06500 0.732417 2.06550 0.734088 2.06600 0.734408 2.06650 0.743096 2.06700 0.754927 2.06750 0.763885 2.06800 0.772236 2.06850 0.781575 2.06900 0.789880 2.06950 0.797068 2.07000 0.806938 2.07050 0.815498 2.07100 0.824557 2.07150 0.836803 2.07200 0.847271 2.07250 0.860418 2.07300 0.865582 2.07350 0.867764 2.07400 0.876762 2.07450 0.883734 2.07500 0.889187 2.07550 0.899364 2.07600 0.908583 2.07650 0.917289 2.07700 0.922241 2.07750 0.920770 2.07800 0.929780 2.07850 0.948897 2.07900 0.963711 2.07950 0.970740 2.08000 0.971610 2.08050 0.972781 2.08100 0.970019 2.08150 0.964121 2.08200 0.958987 2.08250 0.955405 2.08300 0.952902 2.08350 0.952600 2.08400 0.950460 2.08450 0.942934 2.08500 0.941579 2.08550 0.951750 2.08600 0.957638 2.08650 0.961765 2.08700 0.965898 2.08750 0.968015 2.08800 0.968744 2.08850 0.969073 2.08900 0.970050 2.08950 0.969301 2.09000 0.967523 2.09050 0.971590 2.09100 0.975703 2.09150 0.977484 2.09200 0.978377 2.09250 0.978491 2.09300 0.978757 2.09350 0.972654 2.09400 0.969828 2.09450 0.980094 2.09500 0.986052 2.09550 0.987759 2.09600 0.988737 2.09650 0.989196 2.09700 0.988857 2.09750 0.988783 2.09800 0.984599 2.09850 0.971005 2.09900 0.970741 2.09950 0.983968 2.10000 0.985586 2.10050 0.984140 2.10100 0.982791 2.10150 0.969959 2.10200 0.971298 2.10250 0.986679 2.10300 0.991906 2.10350 0.992403 2.10400 0.992585 2.10450 0.991891 2.10500 0.990666 2.10550 0.991320 2.10600 0.991978 2.10650 0.990860 2.10700 0.990089 2.10750 0.989484 2.10800 0.988603 2.10850 0.987929 2.10900 0.986920 2.10950 0.983884 2.11000 0.982689 2.11050 0.986071 2.11100 0.986735 2.11150 0.981447 2.11200 0.979408 2.11250 0.985626 2.11300 0.991021 2.11350 0.993767 2.11400 0.994487 2.11450 0.994103 2.11500 0.993010 2.11550 0.991964 2.11600 0.990991 2.11650 0.991483 2.11700 0.992698 2.11750 0.991889 2.11800 0.983970 2.11850 0.971855 2.11900 0.979086 2.11950 0.986677 2.12000 0.986021 2.12050 0.988951 2.12100 0.992599 2.12150 0.993930 2.12200 0.995124 2.12250 0.995836 2.12300 0.996118 2.12350 0.995328 2.12400 0.989318 2.12450 0.982217 2.12500 0.988202 2.12550 0.995557 2.12600 0.997300 2.12650 0.997113 2.12700 0.992464 2.12750 0.977895 2.12800 0.977083 2.12850 0.992157 2.12900 0.997727 2.12950 0.998401 2.13000 0.998534 2.13050 0.998556 2.13100 0.998703 2.13150 0.998836 2.13200 0.998842 2.13250 0.998855 2.13300 0.998938 2.13350 0.999044 2.13400 0.999137 2.13450 0.999175 2.13500 0.998478 2.13550 0.995184 2.13600 0.993312 2.13650 0.996881 2.13700 0.999013 2.13750 0.999248 2.13800 0.999150 2.13850 0.998895 2.13900 0.998691 2.13950 0.998646 2.14000 0.998875 2.14050 0.999125 2.14100 0.999183 2.14150 0.999165 2.14200 0.998968 2.14250 0.998034 2.14300 0.997102 2.14350 0.997802 2.14400 0.998546 2.14450 0.998475 2.14500 0.998611 2.14550 0.998569 2.14600 0.998272 2.14650 0.998110 2.14700 0.997262 2.14750 0.996111 2.14800 0.995171 2.14850 0.994371 2.14900 0.993065 2.14950 0.991842 2.15000 0.991835 2.15050 0.991803 2.15100 0.983901 2.15150 0.975700 2.15200 0.980254 2.15250 0.984396 2.15300 0.985028 2.15350 0.987872 2.15400 0.989390 2.15450 0.989185 2.15500 0.989151 2.15550 0.990972 2.15600 0.994613 2.15650 0.995879 2.15700 0.996363 2.15750 0.996285 2.15800 0.995721 2.15850 0.993083 2.15900 0.987623 2.15950 0.988481 2.16000 0.990452 2.16050 0.987673 2.16100 0.980903 2.16150 0.985045 2.16200 0.992109 2.16250 0.989632 2.16300 0.973865 2.16350 0.958663 2.16400 0.977795 2.16450 0.993738 2.16500 0.995623 2.16550 0.994897 2.16600 0.992859 2.16650 0.986264 2.16700 0.982185 2.16750 0.988255 2.16800 0.987906 2.16850 0.976416 2.16900 0.980153 2.16950 0.993003 2.17000 0.995129 2.17050 0.995134 2.17100 0.997341 2.17150 0.997671 2.17200 0.991474 2.17250 0.977741 2.17300 0.980152 2.17350 0.990936 2.17400 0.989441 2.17450 0.984273 2.17500 0.988683 2.17550 0.992322 2.17600 0.987212 2.17650 0.987250 2.17700 0.995416 2.17750 0.996183 2.17800 0.984596 2.17850 0.973010 2.17900 0.977554 2.17950 0.983870 2.18000 0.993351 2.18050 0.998100 2.18100 0.998929 2.18150 0.999065 2.18200 0.998138 2.18250 0.991366 2.18300 0.971275 2.18350 0.960062 2.18400 0.969308 2.18450 0.964133 2.18500 0.959404 2.18550 0.981925 2.18600 0.996161 2.18650 0.996612 2.18700 0.991580 2.18750 0.986871 2.18800 0.984696 2.18850 0.989740 2.18900 0.994335 2.18950 0.991143 2.19000 0.988768 2.19050 0.987144 2.19100 0.993016 2.19150 0.998238 2.19200 0.999085 2.19250 0.999107 2.19300 0.999104 2.19350 0.998684 2.19400 0.993953 2.19450 0.979371 2.19500 0.972930 2.19550 0.986936 2.19600 0.995153 2.19650 0.993627 2.19700 0.993788 2.19750 0.989778 2.19800 0.969747 2.19850 0.958481 2.19900 0.959772 2.19950 0.936635 2.20000 0.904162 2.20050 0.908416 2.20100 0.952181 2.20150 0.968994 2.20200 0.961742 2.20250 0.961983 2.20300 0.972796 2.20350 0.982878 2.20400 0.981270 2.20450 0.966098 2.20500 0.958580 2.20550 0.976865 2.20600 0.989844 2.20650 0.991440 2.20700 0.990608 2.20750 0.992038 2.20800 0.995536 2.20850 0.998074 2.20900 0.998375 2.20950 0.998150 2.21000 0.996682 2.21050 0.993781 2.21100 0.989655 2.21150 0.991445 2.21200 0.997280 2.21250 0.998798 2.21300 0.998861 2.21350 0.998463 2.21400 0.996766 2.21450 0.993372 2.21500 0.991418 2.21550 0.987521 2.21600 0.971367 2.21650 0.963606 2.21700 0.980334 2.21750 0.994027 2.21800 0.994988 2.21850 0.994404 2.21900 0.996066 2.21950 0.996900 2.22000 0.995557 2.22050 0.991455 2.22100 0.979036 2.22150 0.963817 2.22200 0.973502 2.22250 0.989688 2.22300 0.994425 2.22350 0.993828 2.22400 0.992148 2.22450 0.990939 2.22500 0.988860 2.22550 0.988802 2.22600 0.985367 2.22650 0.973255 2.22700 0.967869 2.22750 0.977822 2.22800 0.988426 2.22850 0.992117 2.22900 0.993506 2.22950 0.994752 2.23000 0.994718 2.23050 0.991141 2.23100 0.982207 2.23150 0.966953 2.23200 0.960961 2.23250 0.964296 2.23300 0.976815 2.23350 0.978526 2.23400 0.981932 2.23450 0.987778 2.23500 0.987859 2.23550 0.985300 2.23600 0.977612 2.23650 0.972477 2.23700 0.975502 2.23750 0.971001 2.23800 0.971979 2.23850 0.984863 2.23900 0.991374 2.23950 0.987579 2.24000 0.979151 2.24050 0.974810 2.24100 0.974257 2.24150 0.972455 2.24200 0.981710 2.24250 0.984980 2.24300 0.983033 2.24350 0.973910 2.24400 0.961679 2.24450 0.973755 2.24500 0.989035 2.24550 0.984345 2.24600 0.967868 2.24650 0.956469 2.24700 0.944037 2.24750 0.955394 2.24800 0.983178 2.24850 0.990925 2.24900 0.986336 2.24950 0.979128 2.25000 0.972989 2.25050 0.969456 2.25100 0.974776 2.25150 0.982455 2.25200 0.979486 2.25250 0.974909 2.25300 0.971611 2.25350 0.958053 2.25400 0.946224 2.25450 0.959704 2.25500 0.971204 2.25550 0.960936 2.25600 0.952730 2.25650 0.943552 2.25700 0.938235 2.25750 0.957662 2.25800 0.967147 2.25850 0.969626 2.25900 0.979161 2.25950 0.978685 2.26000 0.967217 2.26050 0.953147 2.26100 0.930291 2.26150 0.915995 2.26200 0.914730 2.26250 0.940945 2.26300 0.968367 2.26350 0.958359 2.26400 0.950043 2.26450 0.940373 2.26500 0.943509 2.26550 0.974245 2.26600 0.988689 2.26650 0.988223 2.26700 0.979713 2.26750 0.963261 2.26800 0.932784 2.26850 0.899877 2.26900 0.921958 2.26950 0.963219 2.27000 0.958127 2.27050 0.947918 2.27100 0.969175 2.27150 0.969777 2.27200 0.948723 2.27250 0.935947 2.27300 0.959925 2.27350 0.974447 2.27400 0.979633 2.27450 0.968265 2.27500 0.927595 2.27550 0.872848 2.27600 0.881464 2.27650 0.921859 2.27700 0.935959 2.27750 0.954508 2.27800 0.971933 2.27850 0.978674 2.27900 0.987011 2.27950 0.990485 2.28000 0.975465 2.28050 0.934239 2.28100 0.930259 2.28150 0.963877 2.28200 0.967130 2.28250 0.918723 2.28300 0.880540 2.28350 0.910531 2.28400 0.918914 2.28450 0.946450 2.28500 0.946472 2.28550 0.940926 2.28600 0.970154 2.28650 0.977190 2.28700 0.975369 2.28750 0.974304 2.28800 0.974016 2.28850 0.976595 2.28900 0.953052 2.28950 0.896540 2.29000 0.882249 2.29050 0.932530 2.29100 0.963816 2.29150 0.967471 2.29200 0.951108 2.29250 0.937592 2.29300 0.959022 2.29350 0.956944 2.29400 0.947137 2.29450 0.941898 2.29500 0.919981 2.29550 0.910921 2.29600 0.915713 2.29650 0.946151 2.29700 0.973374 2.29750 0.974277 2.29800 0.931860 2.29850 0.891625 2.29900 0.903607 2.29950 0.918032 2.30000 0.904420 2.30050 0.893896 2.30100 0.923603 2.30150 0.956751 2.30200 0.954860 2.30250 0.945079 2.30300 0.939584 2.30350 0.913138 2.30400 0.895780 2.30450 0.901001 2.30500 0.924654 2.30550 0.938239 2.30600 0.943688 2.30650 0.944019 2.30700 0.934959 2.30750 0.913497 2.30800 0.938670 2.30850 0.965929 2.30900 0.964231 2.30950 0.963499 2.31000 0.973815 2.31050 0.987864 2.31100 0.994375 2.31150 0.988675 2.31200 0.975269 2.31250 0.980292 2.31300 0.993809 2.31350 0.997085 2.31400 0.997118 2.31450 0.996271 2.31500 0.992056 2.31550 0.968407 2.31600 0.905904 2.31650 0.813697 2.31700 0.741154 2.31750 0.762081 2.31800 0.807843 2.31850 0.853012 2.31900 0.898999 2.31950 0.917139 2.32000 0.927846 2.32050 0.936867 2.32100 0.942031 2.32150 0.938965 2.32200 0.925964 2.32250 0.929202 2.32300 0.938148 2.32350 0.950685 2.32400 0.963227 2.32450 0.975641 2.32500 0.960537 2.32550 0.940908 2.32600 0.953554 2.32650 0.962983 2.32700 0.978302 2.32750 0.984367 2.32800 0.957858 2.32850 0.914691 2.32900 0.927635 2.32950 0.958990 2.33000 0.977835 2.33050 0.972343 2.33100 0.953465 2.33150 0.932278 2.33200 0.926684 2.33250 0.946931 2.33300 0.965216 2.33350 0.963410 2.33400 0.946427 2.33450 0.939448 2.33500 0.937441 2.33550 0.946345 2.33600 0.941163 2.33650 0.953312 2.33700 0.969662 2.33750 0.964027 2.33800 0.933469 2.33850 0.908774 2.33900 0.917623 2.33950 0.899535 2.34000 0.849853 2.34050 0.859787 2.34100 0.886399 2.34150 0.902342 2.34200 0.923683 2.34250 0.939823 2.34300 0.939325 2.34350 0.927649 2.34400 0.937298 2.34450 0.929117 2.34500 0.905541 2.34550 0.911958 2.34600 0.922879 2.34650 0.908866 2.34700 0.901061 2.34750 0.886318 2.34800 0.861221 2.34850 0.883943 2.34900 0.913045 2.34950 0.905750 2.35000 0.884418 2.35050 0.846103 2.35100 0.848492 2.35150 0.872819 2.35200 0.858068 2.35250 0.855305 2.35300 0.877964 2.35350 0.882434 2.35400 0.926982 2.35450 0.943698 2.35500 0.931073 2.35550 0.882179 2.35600 0.833487 2.35650 0.895704 2.35700 0.941379 2.35750 0.942649 2.35800 0.898892 2.35850 0.811805 2.35900 0.839390 2.35950 0.948189 2.36000 0.985150 2.36050 0.984192 2.36100 0.962659 2.36150 0.916173 2.36200 0.931674 2.36250 0.974088 2.36300 0.977077 2.36350 0.946484 2.36400 0.908475 2.36450 0.921383 2.36500 0.959631 2.36550 0.973592 2.36600 0.954171 2.36650 0.942535 2.36700 0.907596 2.36750 0.858218 2.36800 0.896493 2.36850 0.921080 2.36900 0.912123 2.36950 0.903999 2.37000 0.782742 2.37050 0.628936 2.37100 0.618359 2.37150 0.672108 2.37200 0.764363 2.37250 0.828775 2.37300 0.876091 2.37350 0.914529 2.37400 0.937871 2.37450 0.944311 2.37500 0.937856 2.37550 0.945167 2.37600 0.916955 2.37650 0.844378 2.37700 0.847027 2.37750 0.888169 2.37800 0.848238 2.37850 0.868077 2.37900 0.941370 2.37950 0.935210 2.38000 0.897067 2.38050 0.899442 2.38100 0.945207 2.38150 0.975747 2.38200 0.975352 2.38250 0.936696 2.38300 0.843852 2.38350 0.777218 2.38400 0.777523 2.38450 0.861230 2.38500 0.938573 2.38550 0.912114 2.38600 0.837304 2.38650 0.854894 2.38700 0.908215 2.38750 0.895066 2.38800 0.848374 2.38850 0.893604 2.38900 0.958882 2.38950 0.944031 2.39000 0.918148 2.39050 0.919918 2.39100 0.847690 2.39150 0.780647 2.39200 0.880173 2.39250 0.953289 2.39300 0.948335 2.39350 0.944433 2.39400 0.938653 2.39450 0.923676 2.39500 0.932864 2.39550 0.939643 2.39600 0.918608 2.39650 0.830222 2.39700 0.808714 2.39750 0.887448 2.39800 0.938626 2.39850 0.952752 2.39900 0.957573 2.39950 0.948458 2.40000 0.911583 2.40050 0.892039 2.40100 0.943568 2.40150 0.969052 2.40200 0.962411 2.40250 0.965630 2.40300 0.961690 2.40350 0.919130 2.40400 0.805536 2.40450 0.800888 2.40500 0.913866 2.40550 0.938582 2.40600 0.923120 2.40650 0.881429 2.40700 0.815630 2.40750 0.824301 2.40800 0.888851 2.40850 0.952288 2.40900 0.946111 2.40950 0.862613 2.41000 0.821815 2.41050 0.912370 2.41100 0.955188 2.41150 0.911764 2.41200 0.898795 2.41250 0.945079 2.41300 0.963990 2.41350 0.921457 2.41400 0.833355 2.41450 0.827269 2.41500 0.890472 2.41550 0.782933 2.41600 0.623885 2.41650 0.744560 2.41700 0.913734 2.41750 0.942810 2.41800 0.857536 2.41850 0.669586 2.41900 0.568041 2.41950 0.669188 2.42000 0.867286 2.42050 0.956546 2.42100 0.970454 2.42150 0.958259 2.42200 0.932975 2.42250 0.944180 2.42300 0.958509 2.42350 0.913936 2.42400 0.828977 2.42450 0.862245 2.42500 0.918503 2.42550 0.923287 2.42600 0.861337 2.42650 0.827370 2.42700 0.914487 2.42750 0.958499 2.42800 0.969334 2.42850 0.977016 2.42900 0.974032 2.42950 0.968545 2.43000 0.967515 2.43050 0.974601 2.43100 0.977684 2.43150 0.977794 2.43200 0.974221 2.43250 0.939977 2.43300 0.847345 2.43350 0.817170 2.43400 0.885587 2.43450 0.819872 2.43500 0.587468 2.43550 0.423735 2.43600 0.450873 2.43650 0.573688 2.43700 0.803187 2.43750 0.933509 2.43800 0.963263 2.43850 0.972448 2.43900 0.977902 2.43950 0.980418 2.44000 0.978676 2.44050 0.977528 2.44100 0.979516 2.44150 0.979711 2.44200 0.970300 2.44250 0.926485 2.44300 0.891714 2.44350 0.932442 2.44400 0.963169 2.44450 0.961123 2.44500 0.925630 2.44550 0.767493 2.44600 0.557422 2.44650 0.622374 2.44700 0.690174 2.44750 0.691813 2.44800 0.763652 2.44850 0.872282 2.44900 0.938356 2.44950 0.877507 2.45000 0.694134 2.45050 0.607990 2.45100 0.548934 2.45150 0.564526 2.45200 0.787022 2.45250 0.923653 2.45300 0.933530 2.45350 0.855869 2.45400 0.768594 2.45450 0.687864 2.45500 0.758187 2.45550 0.915924 2.45600 0.960811 2.45650 0.957282 2.45700 0.962986 2.45750 0.972367 2.45800 0.975347 2.45850 0.973874 2.45900 0.965308 2.45950 0.960711 2.46000 0.970417 2.46050 0.974221 2.46100 0.964829 2.46150 0.940391 2.46200 0.833780 2.46250 0.592366 2.46300 0.578570 2.46350 0.808207 2.46400 0.878948 2.46450 0.870326 2.46500 0.930417 2.46550 0.963790 2.46600 0.960592 2.46650 0.959658 2.46700 0.934625 2.46750 0.832232 2.46800 0.803242 2.46850 0.893985 2.46900 0.940032 2.46950 0.953463 2.47000 0.947762 2.47050 0.931176 2.47100 0.882532 2.47150 0.707245 2.47200 0.386032 2.47250 0.230481 2.47300 0.387630 2.47350 0.702714 2.47400 0.892005 2.47450 0.931527 2.47500 0.911206 2.47550 0.900902 2.47600 0.931180 2.47650 0.951266 2.47700 0.923727 2.47750 0.888870 2.47800 0.891582 2.47850 0.868052 2.47900 0.864266 2.47950 0.822565 2.48000 0.708235 2.48050 0.596334 2.48100 0.577294 2.48150 0.572595 2.48200 0.727780 2.48250 0.858553 2.48300 0.841080 2.48350 0.683533 2.48400 0.415841 2.48450 0.417153 2.48500 0.700256 2.48550 0.861003 2.48600 0.862802 2.48650 0.760302 2.48700 0.625782 2.48750 0.462789 2.48800 0.320126 2.48850 0.454396 2.48900 0.669309 2.48950 0.755920 2.49000 0.798100 2.49050 0.788546 2.49100 0.787778 2.49150 0.697324 2.49200 0.528836 2.49250 0.589910 2.49300 0.698714 2.49350 0.706435 2.49400 0.566537 2.49450 0.289364 2.49500 0.250413 2.49550 0.512559 2.49600 0.739590 2.49650 0.762701 2.49700 0.806569 2.49750 0.839128 2.49800 0.816082 2.49850 0.836141 2.49900 0.825863 2.49950 0.812290 2.50000 0.859637 2.50050 0.880342 2.50100 0.881045 2.50150 0.861771 2.50200 0.800617 2.50250 0.629906 2.50300 0.392314 2.50350 0.484261 2.50400 0.674368 2.50450 0.648110 2.50500 0.632014 2.50550 0.494431 2.50600 0.358292 2.50650 0.528584 2.50700 0.782765 2.50750 0.902050 2.50800 0.890074 2.50850 0.768570 2.50900 0.651085 2.50950 0.666175 2.51000 0.697582 2.51050 0.470949 2.51100 0.277624 2.51150 0.433166 2.51200 0.563810 2.51250 0.544119 2.51300 0.578282 2.51350 0.710885 2.51400 0.776085 2.51450 0.579143 2.51500 0.337549 2.51550 0.248457 2.51600 0.173012 2.51650 0.146515 2.51700 0.140888 2.51750 0.206415 2.51800 0.462253 2.51850 0.621524 2.51900 0.526686 2.51950 0.416277 2.52000 0.530547 2.52050 0.642531 2.52100 0.770596 2.52150 0.785093 2.52200 0.633073 2.52250 0.541423 2.52300 0.597740 2.52350 0.521539 2.52400 0.292984 2.52450 0.330189 2.52500 0.435927 2.52550 0.405049 2.52600 0.382376 2.52650 0.316188 2.52700 0.275948 2.52750 0.336176 2.52800 0.414042 2.52850 0.426600 2.52900 0.371080 2.52950 0.173469 2.53000 0.129927 2.53050 0.217549 2.53100 0.159081 2.53150 5.42837E-02 2.53200 7.36881E-02 2.53250 1.04730E-01 2.53300 8.87523E-02 2.53350 0.214393 2.53400 0.448291 2.53450 0.481634 2.53500 0.281284 2.53550 0.106706 2.53600 4.10849E-02 2.53650 5.17446E-02 2.53700 0.168290 2.53750 0.289895 2.53800 0.361603 2.53850 0.307732 2.53900 0.230749 2.53950 0.377892 2.54000 0.566428 2.54050 0.509028 2.54100 0.277028 2.54150 0.132388 2.54200 1.00939E-01 2.54250 7.86398E-02 2.54300 3.17442E-02 2.54350 2.29503E-02 2.54400 1.71456E-02 2.54450 6.21574E-03 2.54500 1.48122E-02 2.54550 6.53314E-02 2.54600 0.167322 2.54650 0.211016 2.54700 0.119869 2.54750 2.79078E-02 2.54800 3.07616E-03 2.54850 1.27496E-02 2.54900 7.94431E-02 2.54950 0.180338 2.55000 0.164326 2.55050 6.64017E-02 2.55100 2.36729E-02 2.55150 5.29800E-02 2.55200 7.37960E-02 2.55250 3.58386E-02 2.55300 1.27467E-02 2.55350 6.23339E-02 2.55400 0.200682 2.55450 0.286113 2.55500 0.287589 2.55550 0.344045 2.55600 0.433375 2.55650 0.468968 2.55700 0.392275 2.55750 0.310678 2.55800 0.281874 2.55850 0.236204 2.55900 0.155075 2.55950 6.06339E-02 2.56000 1.12537E-02 2.56050 8.22040E-04 2.56100 1.99218E-05 2.56150 5.31712E-08 2.56200 7.04277E-08 2.56250 2.83073E-06 2.56300 3.04938E-05 2.56350 8.86269E-05 2.56400 6.98677E-05 2.56450 4.31127E-05 2.56500 8.69180E-04 2.56550 8.53199E-03 2.56600 3.50122E-02 2.56650 7.84159E-02 2.56700 9.29130E-02 2.56750 5.37144E-02 2.56800 1.51688E-02 2.56850 2.63614E-03 2.56900 4.80369E-04 2.56950 4.89174E-05 2.57000 1.90489E-04 2.57050 2.33284E-03 2.57100 1.08536E-02 2.57150 1.96635E-02 2.57200 1.53896E-02 2.57250 5.76536E-03 2.57300 9.72730E-04 2.57350 7.02864E-05 2.57400 6.76498E-05 2.57450 1.50234E-04 2.57500 4.64435E-04 2.57550 1.48849E-03 2.57600 1.51976E-03 2.57650 4.39861E-04 2.57700 1.25036E-04 2.57750 1.49480E-03 2.57800 9.01993E-03 2.57850 2.27736E-02 2.57900 2.94524E-02 2.57950 2.04180E-02 2.58000 7.44139E-03 2.58050 1.78394E-03 2.58100 2.24446E-04 2.58150 7.36249E-05 2.58200 2.50571E-04 2.58250 2.92329E-04 2.58300 1.00811E-04 2.58350 9.96234E-06 2.58400 5.73564E-07 2.58450 1.01644E-05 2.58500 1.04099E-04 2.58550 3.47114E-04 2.58600 3.83984E-04 2.58650 1.34896E-04 2.58700 1.41135E-05 2.58750 4.15259E-07 2.58800 7.73058E-10 2.58850 6.14685E-08 2.58900 5.82730E-06 2.58950 1.37129E-04 2.59000 1.03550E-03 2.59050 2.55482E-03 2.59100 2.28052E-03 2.59150 1.26387E-03 2.59200 5.39003E-04 2.59250 8.89576E-05 2.59300 4.33847E-06 2.59350 5.14225E-08 2.59400 0. 2.59450 0. 2.59500 0. 2.59550 0. 2.59600 0. 2.59650 1.29516E-08 2.59700 2.36268E-06 2.59750 8.43206E-05 2.59800 1.03404E-03 2.59850 4.75963E-03 2.59900 9.11354E-03 2.59950 7.86873E-03 2.60000 4.64774E-03 2.60050 2.75123E-03 2.60100 7.50119E-04 2.60150 6.49983E-05 2.60200 5.84982E-06 2.60250 9.52441E-06 2.60300 5.50399E-06 2.60350 8.13932E-07 2.60400 3.07099E-08 2.60450 1.22151E-10 2.60500 0. 2.60550 0. 2.60600 0. 2.60650 0. 2.60700 0. 2.60750 0. 2.60800 0. 2.60850 0. 2.60900 2.69301E-09 2.60950 5.82116E-07 2.61000 2.21126E-05 2.61050 2.66238E-04 2.61100 1.08433E-03 2.61150 1.57924E-03 2.61200 7.90820E-04 2.61250 1.22123E-04 2.61300 5.76671E-06 2.61350 9.44120E-06 2.61400 5.49874E-05 2.61450 8.50224E-05 2.61500 3.46907E-05 2.61550 3.73304E-06 2.61600 1.05655E-07 2.61650 1.85436E-11 2.61700 0. 2.61750 0. 2.61800 0. 2.61850 0. 2.61900 0. 2.61950 0. 2.62000 0. 2.62050 4.94590E-08 2.62100 3.39033E-06 2.62150 6.77962E-05 2.62200 5.25843E-04 2.62250 2.23750E-03 2.62300 6.41913E-03 2.62350 1.08452E-02 2.62400 1.01490E-02 2.62450 5.37306E-03 2.62500 1.82351E-03 2.62550 4.08479E-04 2.62600 4.60204E-05 2.62650 1.97978E-06 2.62700 2.37133E-08 2.62750 0. 2.62800 0. 2.62850 0. 2.62900 0. 2.62950 0. 2.63000 0. 2.63050 0. 2.63100 0. 2.63150 0. 2.63200 0. 2.63250 0. 2.63300 8.50751E-10 2.63350 1.08282E-06 2.63400 6.21755E-05 2.63450 1.10571E-03 2.63500 7.21401E-03 2.63550 2.18695E-02 2.63600 4.42830E-02 2.63650 7.04138E-02 2.63700 0.123779 2.63750 0.185466 2.63800 0.198941 2.63850 0.139015 2.63900 9.40803E-02 2.63950 0.135771 2.64000 0.128158 2.64050 5.31014E-02 2.64100 1.37403E-02 2.64150 3.48079E-03 2.64200 1.29076E-03 2.64250 9.07881E-03 2.64300 3.61677E-02 2.64350 5.35005E-02 2.64400 3.25188E-02 2.64450 1.32081E-02 2.64500 5.22988E-03 2.64550 9.54610E-04 2.64600 9.78894E-05 2.64650 1.05753E-03 2.64700 1.02039E-02 2.64750 4.47219E-02 2.64800 0.105665 2.64850 0.158865 2.64900 0.167898 2.64950 0.124930 2.65000 9.27436E-02 2.65050 7.01388E-02 2.65100 2.98892E-02 2.65150 5.70136E-03 2.65200 4.31643E-04 2.65250 1.46558E-05 2.65300 5.84877E-05 2.65350 5.05101E-04 2.65400 1.48995E-03 2.65450 1.45131E-03 2.65500 4.61932E-04 2.65550 7.52919E-05 2.65600 3.15886E-04 2.65650 1.25352E-03 2.65700 2.92523E-03 2.65750 3.58311E-03 2.65800 2.34480E-03 2.65850 1.58906E-03 2.65900 5.66940E-04 2.65950 6.46782E-05 2.66000 2.23259E-06 2.66050 1.33573E-08 2.66100 0. 2.66150 0. 2.66200 0. 2.66250 0. 2.66300 0. 2.66350 0. 2.66400 0. 2.66450 0. 2.66500 0. 2.66550 0. 2.66600 0. 2.66650 0. 2.66700 0. 2.66750 0. 2.66800 0. 2.66850 0. 2.66900 0. 2.66950 0. 2.67000 0. 2.67050 0. 2.67100 0. 2.67150 0. 2.67200 0. 2.67250 0. 2.67300 0. 2.67350 0. 2.67400 0. 2.67450 0. 2.67500 0. 2.67550 0. 2.67600 0. 2.67650 0. 2.67700 0. 2.67750 0. 2.67800 0. 2.67850 0. 2.67900 0. 2.67950 0. 2.68000 0. 2.68050 0. 2.68100 0. 2.68150 0. 2.68200 0. 2.68250 0. 2.68300 0. 2.68350 0. 2.68400 0. 2.68450 0. 2.68500 0. 2.68550 0. 2.68600 0. 2.68650 0. 2.68700 0. 2.68750 0. 2.68800 0. 2.68850 0. 2.68900 0. 2.68950 0. 2.69000 0. 2.69050 0. 2.69100 0. 2.69150 0. 2.69200 0. 2.69250 0. 2.69300 0. 2.69350 0. 2.69400 0. 2.69450 0. 2.69500 0. 2.69550 0. 2.69600 0. 2.69650 0. 2.69700 0. 2.69750 0. 2.69800 0. 2.69850 0. 2.69900 0. 2.69950 0. 2.70000 0. 2.70050 0. 2.70100 0. 2.70150 0. 2.70200 0. 2.70250 0. 2.70300 0. 2.70350 0. 2.70400 0. 2.70450 0. 2.70500 0. 2.70550 0. 2.70600 0. 2.70650 0. 2.70700 0. 2.70750 0. 2.70800 0. 2.70850 0. 2.70900 0. 2.70950 0. 2.71000 0. 2.71050 0. 2.71100 0. 2.71150 7.46271E-09 2.71200 4.08152E-07 2.71250 5.77449E-06 2.71300 2.24869E-05 2.71350 3.24894E-05 2.71400 1.18316E-04 2.71450 4.45578E-04 2.71500 6.04868E-04 2.71550 7.04037E-04 2.71600 9.45985E-04 2.71650 4.97751E-04 2.71700 8.49472E-05 2.71750 4.81223E-06 2.71800 7.95806E-08 2.71850 0. 2.71900 0. 2.71950 0. 2.72000 0. 2.72050 0. 2.72100 0. 2.72150 0. 2.72200 0. 2.72250 0. 2.72300 0. 2.72350 0. 2.72400 0. 2.72450 0. 2.72500 3.43786E-09 2.72550 8.05882E-07 2.72600 2.99542E-05 2.72650 3.76366E-04 2.72700 1.75447E-03 2.72750 3.64936E-03 2.72800 7.77668E-03 2.72850 2.18814E-02 2.72900 3.50740E-02 2.72950 3.32743E-02 2.73000 3.91123E-02 2.73050 4.55297E-02 2.73100 3.12457E-02 2.73150 1.84191E-02 2.73200 7.97910E-03 2.73250 7.04690E-03 2.73300 1.02623E-02 2.73350 6.63580E-03 2.73400 1.88625E-03 2.73450 2.15843E-04 2.73500 9.37679E-06 2.73550 2.99425E-05 2.73600 2.76024E-04 2.73650 8.22255E-04 2.73700 7.91828E-04 2.73750 2.57058E-04 2.73800 3.09913E-05 2.73850 1.38114E-06 2.73900 1.82239E-08 2.73950 0. 2.74000 0. 2.74050 0. 2.74100 0. 2.74150 0. 2.74200 2.85219E-07 2.74250 1.67434E-05 2.74300 2.59645E-04 2.74350 1.12757E-03 2.74400 1.50164E-03 2.74450 7.08162E-04 2.74500 1.34187E-04 2.74550 7.26413E-05 2.74600 8.19766E-04 2.74650 3.45077E-03 2.74700 4.11042E-03 2.74750 1.62636E-03 2.74800 4.64222E-04 2.74850 9.91428E-05 2.74900 3.97107E-05 2.74950 1.12449E-04 2.75000 2.72961E-04 2.75050 2.25304E-04 2.75100 5.04539E-05 2.75150 2.98142E-06 2.75200 4.50252E-08 2.75250 0. 2.75300 0. 2.75350 0. 2.75400 0. 2.75450 0. 2.75500 0. 2.75550 0. 2.75600 0. 2.75650 0. 2.75700 0. 2.75750 0. 2.75800 0. 2.75850 0. 2.75900 0. 2.75950 0. 2.76000 0. 2.76050 0. 2.76100 0. 2.76150 0. 2.76200 0. 2.76250 0. 2.76300 0. 2.76350 0. 2.76400 0. 2.76450 0. 2.76500 0. 2.76550 0. 2.76600 0. 2.76650 0. 2.76700 0. 2.76750 0. 2.76800 0. 2.76850 0. 2.76900 0. 2.76950 0. 2.77000 0. 2.77050 0. 2.77100 0. 2.77150 0. 2.77200 0. 2.77250 0. 2.77300 2.66520E-10 2.77350 2.00496E-08 2.77400 3.77809E-07 2.77450 1.78330E-06 2.77500 2.10791E-06 2.77550 6.24441E-07 2.77600 4.62515E-08 2.77650 8.58907E-10 2.77700 0. 2.77750 0. 2.77800 0. 2.77850 0. 2.77900 0. 2.77950 0. 2.78000 0. 2.78050 0. 2.78100 0. 2.78150 0. 2.78200 0. 2.78250 8.38924E-08 2.78300 3.80616E-06 2.78350 4.40936E-05 2.78400 1.31333E-04 2.78450 1.02332E-04 2.78500 2.46771E-05 2.78550 1.28573E-05 2.78600 1.06914E-05 2.78650 2.52232E-06 2.78700 1.52624E-07 2.78750 2.36056E-09 2.78800 1.07191E-07 2.78850 8.13460E-06 2.78900 1.52285E-04 2.78950 7.39647E-04 2.79000 9.33600E-04 2.79050 4.01153E-04 2.79100 1.25820E-03 2.79150 4.57812E-03 2.79200 6.13691E-03 2.79250 7.91617E-03 2.79300 8.07466E-03 2.79350 4.18372E-03 2.79400 1.12827E-02 2.79450 2.18905E-02 2.79500 1.30209E-02 2.79550 4.06567E-03 2.79600 9.17343E-03 2.79650 1.58233E-02 2.79700 7.69597E-03 2.79750 1.12372E-03 2.79800 8.26521E-04 2.79850 7.00086E-03 2.79900 2.90093E-02 2.79950 5.35208E-02 2.80000 3.99908E-02 2.80050 1.41603E-02 2.80100 8.16306E-03 2.80150 5.25740E-03 2.80200 1.37133E-03 2.80250 1.26905E-04 2.80300 3.67799E-06 2.80350 2.16667E-08 2.80400 4.15539E-07 2.80450 3.28079E-06 2.80500 1.15962E-05 2.80550 3.18687E-05 2.80600 1.51171E-04 2.80650 6.66623E-04 2.80700 3.75033E-03 2.80750 1.17382E-02 2.80800 1.12231E-02 2.80850 5.55076E-03 2.80900 1.34713E-02 2.80950 3.77404E-02 2.81000 5.26864E-02 2.81050 4.92516E-02 2.81100 3.47226E-02 2.81150 4.87988E-02 2.81200 0.125513 2.81250 0.158933 2.81300 1.01133E-01 2.81350 4.69394E-02 2.81400 2.35216E-02 2.81450 1.63181E-02 2.81500 7.15731E-03 2.81550 1.02543E-02 2.81600 2.30568E-02 2.81650 3.81845E-02 2.81700 6.91011E-02 2.81750 7.17183E-02 2.81800 3.48098E-02 2.81850 1.57872E-02 2.81900 1.17363E-02 2.81950 2.27773E-02 2.82000 3.28932E-02 2.82050 1.39404E-02 2.82100 2.00513E-03 2.82150 9.62986E-04 2.82200 6.04452E-03 2.82250 4.37365E-02 2.82300 0.138730 2.82350 0.224456 2.82400 0.249512 2.82450 0.192406 2.82500 0.172525 2.82550 0.190434 2.82600 0.289760 2.82650 0.308545 2.82700 0.165275 2.82750 6.59645E-02 2.82800 0.117027 2.82850 0.277408 2.82900 0.348433 2.82950 0.405702 2.83000 0.453038 2.83050 0.433093 2.83100 0.406940 2.83150 0.220348 2.83200 6.20016E-02 2.83250 4.59858E-02 2.83300 5.01135E-02 2.83350 2.19248E-02 2.83400 4.36578E-03 2.83450 1.49209E-03 2.83500 3.76535E-03 2.83550 2.38627E-02 2.83600 6.65644E-02 2.83650 9.23693E-02 2.83700 7.02928E-02 2.83750 3.86315E-02 2.83800 2.22160E-02 2.83850 1.25131E-02 2.83900 4.10920E-02 2.83950 0.113036 2.84000 0.209938 2.84050 0.289646 2.84100 0.200746 2.84150 1.02646E-01 2.84200 0.128186 2.84250 0.228789 2.84300 0.346488 2.84350 0.448027 2.84400 0.513021 2.84450 0.581912 2.84500 0.472795 2.84550 0.301061 2.84600 0.224535 2.84650 0.178578 2.84700 0.168988 2.84750 0.112529 2.84800 9.13010E-02 2.84850 1.00960E-01 2.84900 6.80385E-02 2.84950 3.76179E-02 2.85000 0.118412 2.85050 0.286894 2.85100 0.387376 2.85150 0.332130 2.85200 0.204127 2.85250 0.122805 2.85300 6.86505E-02 2.85350 2.26740E-02 2.85400 1.05554E-02 2.85450 5.94908E-03 2.85500 1.02322E-02 2.85550 2.43368E-02 2.85600 7.77783E-02 2.85650 0.204824 2.85700 0.272392 2.85750 0.319424 2.85800 0.392779 2.85850 0.412704 2.85900 0.336409 2.85950 0.168226 2.86000 0.105973 2.86050 0.160466 2.86100 0.184883 2.86150 0.323649 2.86200 0.474922 2.86250 0.496971 2.86300 0.544977 2.86350 0.548370 2.86400 0.442921 2.86450 0.366866 2.86500 0.469400 2.86550 0.558558 2.86600 0.450554 2.86650 0.233590 2.86700 0.175106 2.86750 0.305468 2.86800 0.320947 2.86850 0.282038 2.86900 0.299453 2.86950 0.344015 2.87000 0.385138 2.87050 0.387361 2.87100 0.269768 2.87150 9.75122E-02 2.87200 6.28070E-02 2.87250 9.56696E-02 2.87300 0.126041 2.87350 0.286362 2.87400 0.478362 2.87450 0.649139 2.87500 0.729783 2.87550 0.721234 2.87600 0.692020 2.87650 0.634344 2.87700 0.469409 2.87750 0.235782 2.87800 0.262597 2.87850 0.400127 2.87900 0.403897 2.87950 0.540406 2.88000 0.642782 2.88050 0.616171 2.88100 0.542903 2.88150 0.441903 2.88200 0.546196 2.88250 0.599684 2.88300 0.524222 2.88350 0.477117 2.88400 0.346084 2.88450 0.289478 2.88500 0.434816 2.88550 0.616555 2.88600 0.654299 2.88650 0.620983 2.88700 0.575662 2.88750 0.346760 2.88800 0.146877 2.88850 0.135701 2.88900 0.154779 2.88950 0.283967 2.89000 0.492082 2.89050 0.673564 2.89100 0.638540 2.89150 0.547495 2.89200 0.524884 2.89250 0.575575 2.89300 0.549092 2.89350 0.451469 2.89400 0.585078 2.89450 0.782930 2.89500 0.832595 2.89550 0.824502 2.89600 0.823092 2.89650 0.842020 2.89700 0.851538 2.89750 0.848143 2.89800 0.819554 2.89850 0.767634 2.89900 0.681430 2.89950 0.436780 2.90000 0.190966 2.90050 8.04939E-02 2.90100 5.22625E-02 2.90150 0.177364 2.90200 0.366965 2.90250 0.439223 2.90300 0.562444 2.90350 0.635965 2.90400 0.454733 2.90450 0.179353 2.90500 0.133475 2.90550 0.350234 2.90600 0.504669 2.90650 0.449374 2.90700 0.481131 2.90750 0.620807 2.90800 0.614649 2.90850 0.554749 2.90900 0.648051 2.90950 0.759177 2.91000 0.772661 2.91050 0.811187 2.91100 0.891973 2.91150 0.906852 2.91200 0.843808 2.91250 0.708414 2.91300 0.549391 2.91350 0.593320 2.91400 0.532625 2.91450 0.345238 2.91500 0.495452 2.91550 0.769385 2.91600 0.864587 2.91650 0.777137 2.91700 0.555704 2.91750 0.560811 2.91800 0.767043 2.91850 0.875260 2.91900 0.912828 2.91950 0.913540 2.92000 0.850900 2.92050 0.738098 2.92100 0.602366 2.92150 0.410188 2.92200 0.198998 2.92250 0.133223 2.92300 0.149814 2.92350 8.80086E-02 2.92400 0.106390 2.92450 0.278048 2.92500 0.421402 2.92550 0.553195 2.92600 0.759390 2.92650 0.855360 2.92700 0.895248 2.92750 0.894276 2.92800 0.896422 2.92850 0.919440 2.92900 0.878229 2.92950 0.728081 2.93000 0.634454 2.93050 0.775061 2.93100 0.905109 2.93150 0.948339 2.93200 0.952087 2.93250 0.921270 2.93300 0.798097 2.93350 0.660756 2.93400 0.776352 2.93450 0.902821 2.93500 0.868471 2.93550 0.830116 2.93600 0.901471 2.93650 0.929039 2.93700 0.852116 2.93750 0.612270 2.93800 0.412329 2.93850 0.535266 2.93900 0.582152 2.93950 0.526606 2.94000 0.625587 2.94050 0.752818 2.94100 0.842912 2.94150 0.852848 2.94200 0.776636 2.94250 0.701950 2.94300 0.524318 2.94350 0.293954 2.94400 0.386065 2.94450 0.627858 2.94500 0.813171 2.94550 0.886154 2.94600 0.857624 2.94650 0.694996 2.94700 0.365423 2.94750 0.169441 2.94800 0.328133 2.94850 0.600225 2.94900 0.814623 2.94950 0.901854 2.95000 0.906888 2.95050 0.921669 2.95100 0.934276 2.95150 0.912625 2.95200 0.884223 2.95250 0.827627 2.95300 0.608257 2.95350 0.336159 2.95400 0.329959 2.95450 0.354751 2.95500 0.422713 2.95550 0.546026 2.95600 0.614572 2.95650 0.806454 2.95700 0.912714 2.95750 0.872883 2.95800 0.748171 2.95850 0.755293 2.95900 0.782054 2.95950 0.756888 2.96000 0.789198 2.96050 0.781476 2.96100 0.807608 2.96150 0.856365 2.96200 0.852847 2.96250 0.796962 2.96300 0.704986 2.96350 0.728750 2.96400 0.872661 2.96450 0.942164 2.96500 0.950822 2.96550 0.931343 2.96600 0.836771 2.96650 0.755112 2.96700 0.788955 2.96750 0.716179 2.96800 0.546853 2.96850 0.501973 2.96900 0.501303 2.96950 0.410558 2.97000 0.441363 2.97050 0.335326 2.97100 0.189865 2.97150 0.193803 2.97200 0.204897 2.97250 0.289943 2.97300 0.514177 2.97350 0.547055 2.97400 0.401034 2.97450 0.308716 2.97500 0.468761 2.97550 0.610235 2.97600 0.488289 2.97650 0.448675 2.97700 0.646504 2.97750 0.830525 2.97800 0.809276 2.97850 0.587379 2.97900 0.459506 2.97950 0.475649 2.98000 0.419790 2.98050 0.542393 2.98100 0.642221 2.98150 0.565400 2.98200 0.547219 2.98250 0.740329 2.98300 0.874824 2.98350 0.816548 2.98400 0.731269 2.98450 0.814366 2.98500 0.859664 2.98550 0.878881 2.98600 0.882006 2.98650 0.834952 2.98700 0.867769 2.98750 0.923849 2.98800 0.899121 2.98850 0.823156 2.98900 0.869983 2.98950 0.948497 2.99000 0.967438 2.99050 0.960395 2.99100 0.910352 2.99150 0.816810 2.99200 0.760632 2.99250 0.792270 2.99300 0.822826 2.99350 0.788582 2.99400 0.762209 2.99450 0.786309 2.99500 0.807097 2.99550 0.876326 2.99600 0.806686 2.99650 0.528090 2.99700 0.388324 2.99750 0.623353 2.99800 0.771542 2.99850 0.629423 2.99900 0.585653 2.99950 0.804276 3.00000 0.929646 3.00050 0.942570 3.00100 0.947215 3.00150 0.959289 3.00200 0.958495 3.00250 0.923474 3.00300 0.809707 3.00350 0.766460 3.00400 0.856123 3.00450 0.828962 3.00500 0.587872 3.00550 0.398067 3.00600 0.366364 3.00650 0.473768 3.00700 0.693656 3.00750 0.672690 3.00800 0.597106 3.00850 0.650113 3.00900 0.589731 3.00950 0.602968 3.01000 0.810882 3.01050 0.926795 3.01100 0.943991 3.01150 0.919944 3.01200 0.930757 3.01250 0.920965 3.01300 0.801026 3.01350 0.726411 3.01400 0.741368 3.01450 0.727163 3.01500 0.843827 3.01550 0.932749 3.01600 0.928417 3.01650 0.891623 3.01700 0.823873 3.01750 0.614397 3.01800 0.335038 3.01850 0.345331 3.01900 0.478746 3.01950 0.597397 3.02000 0.703785 3.02050 0.630770 3.02100 0.639982 3.02150 0.583434 3.02200 0.286108 3.02250 0.162272 3.02300 0.378514 3.02350 0.697134 3.02400 0.885020 3.02450 0.936965 3.02500 0.951402 3.02550 0.955922 3.02600 0.944999 3.02650 0.886838 3.02700 0.709125 3.02750 0.648019 3.02800 0.834275 3.02850 0.944127 3.02900 0.944823 3.02950 0.853488 3.03000 0.745710 3.03050 0.815749 3.03100 0.893278 3.03150 0.798308 3.03200 0.526720 3.03250 0.325800 3.03300 0.396732 3.03350 0.641157 3.03400 0.828016 3.03450 0.891895 3.03500 0.805095 3.03550 0.605020 3.03600 0.544893 3.03650 0.405090 3.03700 0.219819 3.03750 0.304842 3.03800 0.375178 3.03850 0.490531 3.03900 0.720450 3.03950 0.809840 3.04000 0.681576 3.04050 0.388538 3.04100 0.377474 3.04150 0.686453 3.04200 0.886411 3.04250 0.914064 3.04300 0.884316 3.04350 0.894000 3.04400 0.876974 3.04450 0.763228 3.04500 0.616480 3.04550 0.549638 3.04600 0.528105 3.04650 0.716960 3.04700 0.882602 3.04750 0.863702 3.04800 0.672534 3.04850 0.429857 3.04900 0.442974 3.04950 0.574243 3.05000 0.662228 3.05050 0.775589 3.05100 0.745945 3.05150 0.488669 3.05200 0.228848 3.05250 0.312351 3.05300 0.514118 3.05350 0.550209 3.05400 0.392843 3.05450 0.173134 3.05500 0.242303 3.05550 0.490824 3.05600 0.561583 3.05650 0.558221 3.05700 0.577959 3.05750 0.580034 3.05800 0.722199 3.05850 0.886487 3.05900 0.946118 3.05950 0.957915 3.06000 0.949489 3.06050 0.910814 3.06100 0.806656 3.06150 0.670848 3.06200 0.628784 3.06250 0.510712 3.06300 0.555131 3.06350 0.734077 3.06400 0.717293 3.06450 0.672201 3.06500 0.783790 3.06550 0.879181 3.06600 0.865132 3.06650 0.671782 3.06700 0.448464 3.06750 0.573635 3.06800 0.810794 3.06850 0.878719 3.06900 0.789325 3.06950 0.583334 3.07000 0.393161 3.07050 0.501137 3.07100 0.683033 3.07150 0.764032 3.07200 0.711630 3.07250 0.435874 3.07300 0.255076 3.07350 0.463547 3.07400 0.752790 3.07450 0.884441 3.07500 0.909237 3.07550 0.904012 3.07600 0.932161 3.07650 0.949669 3.07700 0.926702 3.07750 0.905748 3.07800 0.929640 3.07850 0.933432 3.07900 0.873124 3.07950 0.808809 3.08000 0.795530 3.08050 0.672448 3.08100 0.371499 3.08150 0.120289 3.08200 0.170776 3.08250 0.469912 3.08300 0.702139 3.08350 0.750228 3.08400 0.768389 3.08450 0.695536 3.08500 0.694485 3.08550 0.730422 3.08600 0.543921 3.08650 0.499174 3.08700 0.741970 3.08750 0.878165 3.08800 0.852257 3.08850 0.767106 3.08900 0.591507 3.08950 0.359219 3.09000 0.473547 3.09050 0.756501 3.09100 0.863031 3.09150 0.849549 3.09200 0.806784 3.09250 0.624109 3.09300 0.357632 3.09350 0.345891 3.09400 0.550098 3.09450 0.721833 3.09500 0.691413 3.09550 0.495141 3.09600 0.317136 3.09650 0.461954 3.09700 0.698846 3.09750 0.737930 3.09800 0.521011 3.09850 0.398638 3.09900 0.615255 3.09950 0.744053 3.10000 0.761172 3.10050 0.863257 3.10100 0.934657 3.10150 0.941478 3.10200 0.915058 3.10250 0.862052 3.10300 0.712737 3.10350 0.493344 3.10400 0.543438 3.10450 0.607589 3.10500 0.396912 3.10550 0.232055 3.10600 0.177360 3.10650 0.309727 3.10700 0.614369 3.10750 0.807379 3.10800 0.813168 3.10850 0.632031 3.10900 0.494410 3.10950 0.638528 3.11000 0.690316 3.11050 0.487546 3.11100 0.217134 3.11150 0.223265 3.11200 0.510849 3.11250 0.754984 3.11300 0.850735 3.11350 0.862128 3.11400 0.809751 3.11450 0.653167 3.11500 0.391053 3.11550 0.222784 3.11600 0.406256 3.11650 0.700836 3.11700 0.851481 3.11750 0.883193 3.11800 0.893441 3.11850 0.930656 3.11900 0.951940 3.11950 0.952509 3.12000 0.955137 3.12050 0.960361 3.12100 0.947260 3.12150 0.926064 3.12200 0.935413 3.12250 0.945236 3.12300 0.935014 3.12350 0.920014 3.12400 0.849780 3.12450 0.664957 3.12500 0.471656 3.12550 0.506267 3.12600 0.610925 3.12650 0.441280 3.12700 0.217590 3.12750 0.301135 3.12800 0.427994 3.12850 0.346078 3.12900 0.408404 3.12950 0.698124 3.13000 0.878433 3.13050 0.932687 3.13100 0.948588 3.13150 0.950539 3.13200 0.943832 3.13250 0.915022 3.13300 0.909595 3.13350 0.938049 3.13400 0.953228 3.13450 0.960945 3.13500 0.963910 3.13550 0.967775 3.13600 0.966440 3.13650 0.960633 3.13700 0.954688 3.13750 0.943391 3.13800 0.909201 3.13850 0.790486 3.13900 0.495492 3.13950 0.212668 3.14000 0.308207 3.14050 0.641106 3.14100 0.837688 3.14150 0.851917 3.14200 0.786948 3.14250 0.814790 3.14300 0.903018 3.14350 0.925465 3.14400 0.910338 3.14450 0.836187 3.14500 0.719173 3.14550 0.595188 3.14600 0.340259 3.14650 0.165420 3.14700 0.331235 3.14750 0.636826 3.14800 0.820410 3.14850 0.882916 3.14900 0.862171 3.14950 0.775146 3.15000 0.800311 3.15050 0.905639 3.15100 0.915005 3.15150 0.894647 3.15200 0.929168 3.15250 0.955631 3.15300 0.955992 3.15350 0.936237 3.15400 0.877351 3.15450 0.692855 3.15500 0.573704 3.15550 0.730442 3.15600 0.806578 3.15650 0.679334 3.15700 0.702454 3.15750 0.812218 3.15800 0.828099 3.15850 0.846559 3.15900 0.905479 3.15950 0.921914 3.16000 0.883593 3.16050 0.829500 3.16100 0.872977 3.16150 0.951313 3.16200 0.973224 3.16250 0.973852 3.16300 0.979039 3.16350 0.983354 3.16400 0.983704 3.16450 0.982576 3.16500 0.978883 3.16550 0.969419 3.16600 0.931483 3.16650 0.847291 3.16700 0.810435 3.16750 0.896619 3.16800 0.961779 3.16850 0.963643 3.16900 0.948609 3.16950 0.955114 3.17000 0.973468 3.17050 0.976124 3.17100 0.961186 3.17150 0.926863 3.17200 0.861718 3.17250 0.815011 3.17300 0.741281 3.17350 0.766663 3.17400 0.903275 3.17450 0.934732 3.17500 0.830639 3.17550 0.686659 3.17600 0.748619 3.17650 0.910697 3.17700 0.960585 3.17750 0.958318 3.17800 0.952650 3.17850 0.957153 3.17900 0.966223 3.17950 0.970188 3.18000 0.969132 3.18050 0.955376 3.18100 0.891001 3.18150 0.693657 3.18200 0.592397 3.18250 0.785266 3.18300 0.918368 3.18350 0.876219 3.18400 0.667318 3.18450 0.524348 3.18500 0.698083 3.18550 0.895583 3.18600 0.948551 3.18650 0.952048 3.18700 0.945510 3.18750 0.934421 3.18800 0.930528 3.18850 0.926805 3.18900 0.922542 3.18950 0.895012 3.19000 0.832804 3.19050 0.726206 3.19100 0.489850 3.19150 0.208117 3.19200 0.201690 3.19250 0.417885 3.19300 0.460319 3.19350 0.430033 3.19400 0.653189 3.19450 0.858192 3.19500 0.916293 3.19550 0.910515 3.19600 0.844142 3.19650 0.761989 3.19700 0.695324 3.19750 0.526249 3.19800 0.271525 3.19850 0.195851 3.19900 0.286279 3.19950 0.425516 3.20000 0.559350 3.20050 0.736134 3.20100 0.757112 3.20150 0.542421 3.20200 0.216575 3.20250 8.74721E-02 3.20300 0.223656 3.20350 0.470549 3.20400 0.694308 3.20450 0.788522 3.20500 0.738277 3.20550 0.496497 3.20600 0.209099 3.20650 0.161143 3.20700 0.266429 3.20750 0.495759 3.20800 0.621190 3.20850 0.467155 3.20900 0.234696 3.20950 0.175865 3.21000 0.312157 3.21050 0.313021 3.21100 0.263176 3.21150 0.234222 3.21200 0.240528 3.21250 0.343903 3.21300 0.310191 3.21350 0.467391 3.21400 0.712678 3.21450 0.648611 3.21500 0.435642 3.21550 0.374932 3.21600 0.460313 3.21650 0.638390 3.21700 0.646816 3.21750 0.541501 3.21800 0.429542 3.21850 0.515505 3.21900 0.742962 3.21950 0.804359 3.22000 0.778070 3.22050 0.607875 3.22100 0.306640 3.22150 0.283885 3.22200 0.393062 3.22250 0.264640 3.22300 0.212674 3.22350 0.325291 3.22400 0.301725 3.22450 0.176513 3.22500 0.256840 3.22550 0.340643 3.22600 0.242395 3.22650 0.363061 3.22700 0.653523 3.22750 0.803705 3.22800 0.811319 3.22850 0.670424 3.22900 0.430267 3.22950 0.239733 3.23000 8.46591E-02 3.23050 4.17210E-02 3.23100 0.127076 3.23150 0.298467 3.23200 0.397493 3.23250 0.476625 3.23300 0.718094 3.23350 0.874254 3.23400 0.918314 3.23450 0.931914 3.23500 0.935854 3.23550 0.932063 3.23600 0.880212 3.23650 0.837640 3.23700 0.887418 3.23750 0.908567 3.23800 0.881510 3.23850 0.790457 3.23900 0.592514 3.23950 0.485439 3.24000 0.338618 3.24050 0.204305 3.24100 0.411464 3.24150 0.708056 3.24200 0.839487 3.24250 0.846709 3.24300 0.793635 3.24350 0.606999 3.24400 0.404947 3.24450 0.444872 3.24500 0.394503 3.24550 0.370789 3.24600 0.527478 3.24650 0.443854 3.24700 0.224968 3.24750 0.301574 3.24800 0.504563 3.24850 0.435309 3.24900 0.286354 3.24950 0.309534 3.25000 0.248860 3.25050 0.294550 3.25100 0.597309 3.25150 0.822699 3.25200 0.901763 3.25250 0.926175 3.25300 0.921652 3.25350 0.890969 3.25400 0.889685 3.25450 0.921096 3.25500 0.936674 3.25550 0.932779 3.25600 0.923908 3.25650 0.916214 3.25700 0.890954 3.25750 0.874063 3.25800 0.855686 3.25850 0.826873 3.25900 0.735485 3.25950 0.500186 3.26000 0.198810 3.26050 8.39780E-02 3.26100 0.187924 3.26150 0.381855 3.26200 0.511540 3.26250 0.448754 3.26300 0.236173 3.26350 0.232855 3.26400 0.512985 3.26450 0.748374 3.26500 0.847221 3.26550 0.888537 3.26600 0.889874 3.26650 0.848406 3.26700 0.796327 3.26750 0.632249 3.26800 0.438582 3.26850 0.568484 3.26900 0.737648 3.26950 0.656631 3.27000 0.369037 3.27050 0.170099 3.27100 0.194345 3.27150 0.183306 3.27200 0.164073 3.27250 0.305534 3.27300 0.553599 3.27350 0.761732 3.27400 0.841002 3.27450 0.860872 3.27500 0.867676 3.27550 0.877051 3.27600 0.868304 3.27650 0.870210 3.27700 0.880665 3.27750 0.861178 3.27800 0.835147 3.27850 0.803387 3.27900 0.650494 3.27950 0.331259 3.28000 1.03092E-01 3.28050 0.144306 3.28100 0.431149 3.28150 0.746096 3.28200 0.885414 3.28250 0.924374 3.28300 0.935643 3.28350 0.942296 3.28400 0.944544 3.28450 0.938377 3.28500 0.926847 3.28550 0.927994 3.28600 0.938667 3.28650 0.930623 3.28700 0.925407 3.28750 0.940549 3.28800 0.947302 3.28850 0.941044 3.28900 0.934280 3.28950 0.929518 3.29000 0.890570 3.29050 0.731982 3.29100 0.527197 3.29150 0.633871 3.29200 0.827627 3.29250 0.872217 3.29300 0.839976 3.29350 0.682757 3.29400 0.498551 3.29450 0.560467 3.29500 0.529294 3.29550 0.310872 3.29600 0.370828 3.29650 0.632644 3.29700 0.723318 3.29750 0.574746 3.29800 0.275939 3.29850 0.148915 3.29900 0.187524 3.29950 0.200564 3.30000 0.372385 3.30050 0.593196 3.30100 0.649042 3.30150 0.513762 3.30200 0.576965 3.30250 0.794993 3.30300 0.876865 3.30350 0.867296 3.30400 0.773104 3.30450 0.519265 3.30500 0.355621 3.30550 0.554754 3.30600 0.768791 3.30650 0.860551 3.30700 0.889241 3.30750 0.860436 3.30800 0.724231 3.30850 0.531470 3.30900 0.559063 3.30950 0.589115 3.31000 0.536321 3.31050 0.633001 3.31100 0.749855 3.31150 0.726666 3.31200 0.520128 3.31250 0.208805 3.31300 3.50122E-02 3.31350 3.01087E-03 3.31400 1.26671E-03 3.31450 3.80167E-03 3.31500 1.35262E-02 3.31550 2.71408E-02 3.31600 3.34067E-02 3.31650 4.18014E-02 3.31700 7.36682E-02 3.31750 0.122044 3.31800 0.126703 3.31850 0.134040 3.31900 0.111121 3.31950 9.55825E-02 3.32000 0.210154 3.32050 0.346944 3.32100 0.405499 3.32150 0.333834 3.32200 0.251975 3.32250 0.379761 3.32300 0.487623 3.32350 0.498639 3.32400 0.601451 3.32450 0.674567 3.32500 0.690361 3.32550 0.704372 3.32600 0.749284 3.32650 0.770722 3.32700 0.681506 3.32750 0.563265 3.32800 0.468280 3.32850 0.452546 3.32900 0.404902 3.32950 0.503752 3.33000 0.763725 3.33050 0.898567 3.33100 0.926654 3.33150 0.927781 3.33200 0.929823 3.33250 0.937668 3.33300 0.932619 3.33350 0.872614 3.33400 0.662674 3.33450 0.534527 3.33500 0.722461 3.33550 0.878062 3.33600 0.931973 3.33650 0.950493 3.33700 0.946962 3.33750 0.922459 3.33800 0.817444 3.33850 0.728850 3.33900 0.693643 3.33950 0.571146 3.34000 0.578143 3.34050 0.687782 3.34100 0.790606 3.34150 0.732030 3.34200 0.630775 3.34250 0.672466 3.34300 0.851666 3.34350 0.929390 3.34400 0.915487 3.34450 0.820378 3.34500 0.598257 3.34550 0.299419 3.34600 0.270836 3.34650 0.482349 3.34700 0.497619 3.34750 0.571485 3.34800 0.812295 3.34850 0.927370 3.34900 0.952117 3.34950 0.955612 3.35000 0.929426 3.35050 0.810463 3.35100 0.711726 3.35150 0.828405 3.35200 0.921983 3.35250 0.898060 3.35300 0.872892 3.35350 0.888445 3.35400 0.818606 3.35450 0.732328 3.35500 0.638457 3.35550 0.609000 3.35600 0.655601 3.35650 0.431378 3.35700 0.212085 3.35750 0.298015 3.35800 0.457460 3.35850 0.700208 3.35900 0.881195 3.35950 0.921450 3.36000 0.923010 3.36050 0.880014 3.36100 0.731258 3.36150 0.669058 3.36200 0.772374 3.36250 0.798552 3.36300 0.603631 3.36350 0.551893 3.36400 0.779823 3.36450 0.913802 3.36500 0.921848 3.36550 0.883246 3.36600 0.894855 3.36650 0.918896 3.36700 0.877561 3.36750 0.743041 3.36800 0.464940 3.36850 0.222155 3.36900 0.351468 3.36950 0.671682 3.37000 0.860901 3.37050 0.880463 3.37100 0.757050 3.37150 0.602160 3.37200 0.707731 3.37250 0.849178 3.37300 0.900511 3.37350 0.935921 3.37400 0.949898 3.37450 0.956225 3.37500 0.956622 3.37550 0.934129 3.37600 0.832512 3.37650 0.700960 3.37700 0.750747 3.37750 0.877735 3.37800 0.931510 3.37850 0.920751 3.37900 0.827866 3.37950 0.546992 3.38000 0.207306 3.38050 0.187789 3.38100 0.501241 3.38150 0.753812 3.38200 0.818282 3.38250 0.832678 3.38300 0.806243 3.38350 0.809017 3.38400 0.867590 3.38450 0.814805 3.38500 0.736118 3.38550 0.751630 3.38600 0.788096 3.38650 0.883794 3.38700 0.946163 3.38750 0.954523 3.38800 0.963240 3.38850 0.965491 3.38900 0.955193 3.38950 0.945517 3.39000 0.935408 3.39050 0.865575 3.39100 0.684179 3.39150 0.363389 3.39200 0.147977 3.39250 0.295101 3.39300 0.665525 3.39350 0.872481 3.39400 0.852606 3.39450 0.806390 3.39500 0.886410 3.39550 0.946926 3.39600 0.953120 3.39650 0.942419 3.39700 0.910869 3.39750 0.883465 3.39800 0.920427 3.39850 0.959429 3.39900 0.966122 3.39950 0.965888 3.40000 0.964562 3.40050 0.959133 3.40100 0.955429 3.40150 0.952306 3.40200 0.941270 3.40250 0.875214 3.40300 0.641708 3.40350 0.358788 3.40400 0.239321 3.40450 0.298555 3.40500 0.574377 3.40550 0.775403 3.40600 0.792986 3.40650 0.730946 3.40700 0.699110 3.40750 0.826285 3.40800 0.857636 3.40850 0.740297 3.40900 0.699973 3.40950 0.803932 3.41000 0.870337 3.41050 0.845349 3.41100 0.869324 3.41150 0.931802 3.41200 0.931212 3.41250 0.882666 3.41300 0.879496 3.41350 0.932583 3.41400 0.945585 3.41450 0.900443 3.41500 0.717920 3.41550 0.493264 3.41600 0.334241 3.41650 0.274816 3.41700 0.524915 3.41750 0.839073 3.41800 0.947135 3.41850 0.961991 3.41900 0.961002 3.41950 0.959999 3.42000 0.957211 3.42050 0.957721 3.42100 0.956905 3.42150 0.956752 3.42200 0.958729 3.42250 0.953321 3.42300 0.944235 3.42350 0.938257 3.42400 0.931174 3.42450 0.926684 3.42500 0.908780 3.42550 0.835615 3.42600 0.789815 3.42650 0.818993 3.42700 0.753777 3.42750 0.593311 3.42800 0.475669 3.42850 0.387997 3.42900 0.448967 3.42950 0.706849 3.43000 0.909537 3.43050 0.950941 3.43100 0.957356 3.43150 0.956556 3.43200 0.951796 3.43250 0.963593 3.43300 0.968264 3.43350 0.954482 3.43400 0.934225 3.43450 0.937634 3.43500 0.940937 3.43550 0.912258 3.43600 0.907996 3.43650 0.920403 3.43700 0.920670 3.43750 0.931723 3.43800 0.935852 3.43850 0.921656 3.43900 0.885740 3.43950 0.770118 3.44000 0.653705 3.44050 0.593934 3.44100 0.636492 3.44150 0.682416 3.44200 0.837907 3.44250 0.927737 3.44300 0.926145 3.44350 0.940609 3.44400 0.959339 3.44450 0.968757 3.44500 0.961495 3.44550 0.917923 3.44600 0.844306 3.44650 0.857763 3.44700 0.931068 3.44750 0.930468 3.44800 0.862567 3.44850 0.866287 3.44900 0.902996 3.44950 0.923655 3.45000 0.943901 3.45050 0.953359 3.45100 0.917704 3.45150 0.838238 3.45200 0.800668 3.45250 0.795415 3.45300 0.763456 3.45350 0.740103 3.45400 0.685250 3.45450 0.779611 3.45500 0.874728 3.45550 0.829543 3.45600 0.865265 3.45650 0.942162 3.45700 0.965817 3.45750 0.971008 3.45800 0.974527 3.45850 0.973906 3.45900 0.969949 3.45950 0.965975 3.46000 0.957669 3.46050 0.958242 3.46100 0.958821 3.46150 0.936755 3.46200 0.919475 3.46250 0.943985 3.46300 0.943677 3.46350 0.926200 3.46400 0.900749 3.46450 0.855791 3.46500 0.804392 3.46550 0.773715 3.46600 0.742394 3.46650 0.768408 3.46700 0.841000 3.46750 0.901808 3.46800 0.905265 3.46850 0.934322 3.46900 0.962645 3.46950 0.970549 3.47000 0.972980 3.47050 0.969704 3.47100 0.966060 3.47150 0.958420 3.47200 0.940794 3.47250 0.920784 3.47300 0.925739 3.47350 0.915190 3.47400 0.873087 3.47450 0.888806 3.47500 0.923229 3.47550 0.906547 3.47600 0.916203 3.47650 0.913899 3.47700 0.883410 3.47750 0.866386 3.47800 0.862903 3.47850 0.859224 3.47900 0.890929 3.47950 0.907703 3.48000 0.909419 3.48050 0.922517 3.48100 0.932526 3.48150 0.947587 3.48200 0.948336 3.48250 0.936223 3.48300 0.932291 3.48350 0.942180 3.48400 0.959903 3.48450 0.972356 3.48500 0.960773 3.48550 0.915780 3.48600 0.896888 3.48650 0.922925 3.48700 0.929716 3.48750 0.902589 3.48800 0.884601 3.48850 0.888542 3.48900 0.853630 3.48950 0.868533 3.49000 0.893525 3.49050 0.892129 3.49100 0.905550 3.49150 0.932652 3.49200 0.948645 3.49250 0.931404 3.49300 0.916768 3.49350 0.913462 3.49400 0.908071 3.49450 0.918627 3.49500 0.947276 3.49550 0.966971 3.49600 0.971297 3.49650 0.963422 3.49700 0.955938 3.49750 0.960099 3.49800 0.949178 3.49850 0.913843 3.49900 0.903277 3.49950 0.928701 3.50000 0.916092 3.50050 0.926237 3.50100 0.957892 3.50150 0.956503 3.50200 0.948687 3.50250 0.945300 3.50300 0.917185 3.50350 0.869709 3.50400 0.867302 3.50450 0.928201 3.50500 0.963235 3.50550 0.966528 3.50600 0.964750 3.50650 0.969629 3.50700 0.968409 3.50750 0.957432 3.50800 0.953337 3.50850 0.964700 3.50900 0.963699 3.50950 0.945694 3.51000 0.946416 3.51050 0.953799 3.51100 0.929929 3.51150 0.883554 3.51200 0.913951 3.51250 0.958877 3.51300 0.968084 3.51350 0.960897 3.51400 0.945299 3.51450 0.934072 3.51500 0.945875 3.51550 0.961818 3.51600 0.959915 3.51650 0.959839 3.51700 0.963237 3.51750 0.963498 3.51800 0.963229 3.51850 0.963537 3.51900 0.952780 3.51950 0.947303 3.52000 0.952410 3.52050 0.948184 3.52100 0.944332 3.52150 0.956223 3.52200 0.967925 3.52250 0.960877 3.52300 0.945014 3.52350 0.945427 3.52400 0.958456 3.52450 0.969761 3.52500 0.969107 3.52550 0.957964 3.52600 0.947315 3.52650 0.938212 3.52700 0.903172 3.52750 0.888101 3.52800 0.919719 3.52850 0.932343 3.52900 0.930589 3.52950 0.955547 3.53000 0.966193 3.53050 0.949302 3.53100 0.906320 3.53150 0.907267 3.53200 0.936225 3.53250 0.940923 3.53300 0.906834 3.53350 0.879392 3.53400 0.923352 3.53450 0.944981 3.53500 0.878656 3.53550 0.759260 3.53600 0.754393 3.53650 0.858428 3.53700 0.918962 3.53750 0.951193 3.53800 0.951346 3.53850 0.885979 3.53900 0.812809 3.53950 0.817626 3.54000 0.854790 3.54050 0.854844 3.54100 0.829168 3.54150 0.854172 3.54200 0.884243 3.54250 0.866413 3.54300 0.854518 3.54350 0.873003 3.54400 0.895926 3.54450 0.913682 3.54500 0.890408 3.54550 0.881525 3.54600 0.895960 3.54650 0.907632 3.54700 0.908812 3.54750 0.871626 3.54800 0.859899 3.54850 0.924517 3.54900 0.952282 3.54950 0.928271 3.55000 0.899211 3.55050 0.923922 3.55100 0.945666 3.55150 0.942808 3.55200 0.928646 3.55250 0.911709 3.55300 0.923847 3.55350 0.901387 3.55400 0.855161 3.55450 0.864056 3.55500 0.873092 3.55550 0.898631 3.55600 0.936643 3.55650 0.943086 3.55700 0.934157 3.55750 0.932456 3.55800 0.931784 3.55850 0.938929 3.55900 0.935141 3.55950 0.899877 3.56000 0.871921 3.56050 0.901541 3.56100 0.948855 3.56150 0.958914 3.56200 0.958503 3.56250 0.963258 3.56300 0.965085 3.56350 0.953583 3.56400 0.926084 3.56450 0.884535 3.56500 0.881881 3.56550 0.906704 3.56600 0.898395 3.56650 0.886223 3.56700 0.857887 3.56750 0.836020 3.56800 0.893727 3.56850 0.927875 3.56900 0.879367 3.56950 0.826559 3.57000 0.882100 3.57050 0.932522 3.57100 0.923562 3.57150 0.881867 3.57200 0.866240 3.57250 0.883643 3.57300 0.891969 3.57350 0.847236 3.57400 0.804469 3.57450 0.821359 3.57500 0.853838 3.57550 0.864893 3.57600 0.865111 3.57650 0.891033 3.57700 0.920547 3.57750 0.922517 3.57800 0.917367 3.57850 0.931453 3.57900 0.934496 3.57950 0.912785 3.58000 0.919756 3.58050 0.927386 3.58100 0.866778 3.58150 0.815407 3.58200 0.840710 3.58250 0.898035 3.58300 0.937369 3.58350 0.934427 3.58400 0.909646 3.58450 0.879553 3.58500 0.874711 3.58550 0.867903 3.58600 0.855161 3.58650 0.896903 3.58700 0.886616 3.58750 0.838346 3.58800 0.881971 3.58850 0.933394 3.58900 0.938334 3.58950 0.914374 3.59000 0.903644 3.59050 0.915227 3.59100 0.915507 3.59150 0.910163 3.59200 0.898077 3.59250 0.887020 3.59300 0.883055 3.59350 0.887080 3.59400 0.916847 3.59450 0.947209 3.59500 0.946351 3.59550 0.940150 3.59600 0.944876 3.59650 0.926088 3.59700 0.882549 3.59750 0.895561 3.59800 0.938200 3.59850 0.947834 3.59900 0.942448 3.59950 0.938339 3.60000 0.917257 3.60050 0.877647 3.60100 0.898906 3.60150 0.941817 3.60200 0.952048 3.60250 0.956553 3.60300 0.957527 3.60350 0.955091 3.60400 0.952915 3.60450 0.933248 3.60500 0.897581 3.60550 0.901115 3.60600 0.912280 3.60650 0.870167 3.60700 0.807533 3.60750 0.791990 3.60800 0.826427 3.60850 0.896437 3.60900 0.938177 3.60950 0.944205 3.61000 0.924852 3.61050 0.922689 3.61100 0.935907 3.61150 0.916428 3.61200 0.891749 3.61250 0.905671 3.61300 0.912726 3.61350 0.876031 3.61400 0.893147 3.61450 0.938227 3.61500 0.953030 3.61550 0.959277 3.61600 0.956464 3.61650 0.936288 3.61700 0.895973 3.61750 0.898596 3.61800 0.939962 3.61850 0.956623 3.61900 0.956900 3.61950 0.949708 3.62000 0.945213 3.62050 0.952477 3.62100 0.948600 3.62150 0.944735 3.62200 0.957778 3.62250 0.962461 3.62300 0.957246 3.62350 0.951719 3.62400 0.952041 3.62450 0.950964 3.62500 0.935901 3.62550 0.898845 3.62600 0.884380 3.62650 0.895868 3.62700 0.871990 3.62750 0.820088 3.62800 0.855970 3.62850 0.933959 3.62900 0.960988 3.62950 0.963313 3.63000 0.963128 3.63050 0.960023 3.63100 0.935763 3.63150 0.888257 3.63200 0.894698 3.63250 0.937017 3.63300 0.952515 3.63350 0.950886 3.63400 0.931678 3.63450 0.899731 3.63500 0.915601 3.63550 0.938327 3.63600 0.941885 3.63650 0.941924 3.63700 0.940434 3.63750 0.952949 3.63800 0.962514 3.63850 0.962234 3.63900 0.955985 3.63950 0.945941 3.64000 0.945788 3.64050 0.950981 3.64100 0.955630 3.64150 0.956803 3.64200 0.956321 3.64250 0.958949 3.64300 0.959973 3.64350 0.960664 3.64400 0.955318 3.64450 0.949449 3.64500 0.950450 3.64550 0.925271 3.64600 0.876637 3.64650 0.859151 3.64700 0.836995 3.64750 0.802784 3.64800 0.859275 3.64850 0.937563 3.64900 0.958321 3.64950 0.960407 3.65000 0.955881 3.65050 0.935646 3.65100 0.906374 3.65150 0.916214 3.65200 0.934818 3.65250 0.943031 3.65300 0.944690 3.65350 0.939893 3.65400 0.949044 3.65450 0.950604 3.65500 0.947874 3.65550 0.954284 3.65600 0.959541 3.65650 0.960866 3.65700 0.960550 3.65750 0.959723 3.65800 0.958480 3.65850 0.958542 3.65900 0.955612 3.65950 0.953420 3.66000 0.957716 3.66050 0.960768 3.66100 0.954450 3.66150 0.938030 3.66200 0.937093 3.66250 0.949150 3.66300 0.942064 3.66350 0.932389 3.66400 0.944345 3.66450 0.956497 3.66500 0.957733 3.66550 0.956908 3.66600 0.956025 3.66650 0.937581 3.66700 0.858404 3.66750 0.773729 3.66800 0.809182 3.66850 0.876456 3.66900 0.920003 3.66950 0.945280 3.67000 0.949404 3.67050 0.940199 3.67100 0.910055 3.67150 0.864136 3.67200 0.849856 3.67250 0.859767 3.67300 0.859187 3.67350 0.846003 3.67400 0.831769 3.67450 0.878836 3.67500 0.856210 3.67550 0.799027 3.67600 0.799760 3.67650 0.849226 3.67700 0.915802 3.67750 0.936782 3.67800 0.912042 3.67850 0.903118 3.67900 0.922868 3.67950 0.921008 3.68000 0.923520 3.68050 0.926579 3.68100 0.926862 3.68150 0.919216 3.68200 0.920999 3.68250 0.928991 3.68300 0.914855 3.68350 0.909011 3.68400 0.932141 3.68450 0.946163 3.68500 0.950466 3.68550 0.954178 3.68600 0.951547 3.68650 0.929166 3.68700 0.875682 3.68750 0.859601 3.68800 0.873028 3.68850 0.894840 3.68900 0.931189 3.68950 0.946528 3.69000 0.951074 3.69050 0.947556 3.69100 0.937292 3.69150 0.935822 3.69200 0.929292 3.69250 0.914140 3.69300 0.930947 3.69350 0.947394 3.69400 0.947416 3.69450 0.947163 3.69500 0.942285 3.69550 0.945636 3.69600 0.954704 3.69650 0.954193 3.69700 0.941326 3.69750 0.935661 3.69800 0.948744 3.69850 0.956100 3.69900 0.955470 3.69950 0.952220 3.70000 0.949464 3.70050 0.947561 3.70100 0.948760 3.70150 0.954742 3.70200 0.957702 3.70250 0.957937 3.70300 0.957704 3.70350 0.957270 3.70400 0.954643 3.70450 0.951360 3.70500 0.952056 3.70550 0.951006 3.70600 0.945770 3.70650 0.930439 3.70700 0.922548 3.70750 0.926628 3.70800 0.934038 3.70850 0.936375 3.70900 0.903445 3.70950 0.882846 3.71000 0.891409 3.71050 0.901868 3.71100 0.928437 3.71150 0.938689 3.71200 0.937999 3.71250 0.936016 3.71300 0.921042 3.71350 0.881337 3.71400 0.889461 3.71450 0.930326 3.71500 0.932213 3.71550 0.924302 3.71600 0.933242 3.71650 0.947356 3.71700 0.941503 3.71750 0.911876 3.71800 0.907920 3.71850 0.936590 3.71900 0.948796 3.71950 0.949710 3.72000 0.951365 3.72050 0.952735 3.72100 0.952050 3.72150 0.951961 3.72200 0.951560 3.72250 0.950264 3.72300 0.950007 3.72350 0.950332 3.72400 0.946849 3.72450 0.942955 3.72500 0.944462 3.72550 0.946432 3.72600 0.937751 3.72650 0.931045 3.72700 0.934623 3.72750 0.934603 3.72800 0.928638 3.72850 0.936472 3.72900 0.945149 3.72950 0.930388 3.73000 0.878069 3.73050 0.860205 3.73100 0.909951 3.73150 0.942886 3.73200 0.950124 3.73250 0.948110 3.73300 0.932670 3.73350 0.908456 3.73400 0.886842 3.73450 0.863841 3.73500 0.899069 3.73550 0.924609 3.73600 0.906507 3.73650 0.907417 3.73700 0.925700 3.73750 0.920371 3.73800 0.906907 3.73850 0.924384 3.73900 0.938865 3.73950 0.938658 3.74000 0.942298 3.74050 0.940206 3.74100 0.922391 3.74150 0.885018 3.74200 0.891771 3.74250 0.929324 3.74300 0.940905 3.74350 0.940096 3.74400 0.943700 3.74450 0.944691 3.74500 0.942212 3.74550 0.941783 3.74600 0.942349 3.74650 0.941717 3.74700 0.941991 3.74750 0.945678 3.74800 0.944581 3.74850 0.940878 3.74900 0.938062 3.74950 0.932117 3.75000 0.899876 3.75050 0.865114 3.75100 0.900388 3.75150 0.932785 3.75200 0.926605 3.75250 0.923447 3.75300 0.932378 3.75350 0.938416 3.75400 0.921922 3.75450 0.871800 3.75500 0.872188 3.75550 0.922640 3.75600 0.941501 3.75650 0.942789 3.75700 0.944763 3.75750 0.944055 3.75800 0.930029 3.75850 0.901654 3.75900 0.905667 3.75950 0.923418 3.76000 0.913207 3.76050 0.911874 3.76100 0.932129 3.76150 0.939606 3.76200 0.935262 3.76250 0.920768 3.76300 0.898019 3.76350 0.906853 3.76400 0.926015 3.76450 0.921383 3.76500 0.910073 3.76550 0.878260 3.76600 0.872561 3.76650 0.914432 3.76700 0.931654 3.76750 0.937308 3.76800 0.941692 3.76850 0.943201 3.76900 0.942452 3.76950 0.938827 3.77000 0.928828 3.77050 0.896673 3.77100 0.867158 3.77150 0.899643 3.77200 0.927268 3.77250 0.934884 3.77300 0.938675 3.77350 0.930306 3.77400 0.894836 3.77450 0.862631 3.77500 0.896464 3.77550 0.931780 3.77600 0.938854 3.77650 0.937980 3.77700 0.932634 3.77750 0.933122 3.77800 0.938793 3.77850 0.939429 3.77900 0.935184 3.77950 0.927727 3.78000 0.930182 3.78050 0.931709 3.78100 0.911485 3.78150 0.893550 3.78200 0.915248 3.78250 0.932790 3.78300 0.934150 3.78350 0.928157 3.78400 0.909863 3.78450 0.893317 3.78500 0.892837 3.78550 0.911687 3.78600 0.929699 3.78650 0.936321 3.78700 0.937182 3.78750 0.935612 3.78800 0.931519 3.78850 0.924863 3.78900 0.902808 3.78950 0.853690 3.79000 0.841900 3.79050 0.888697 3.79100 0.899090 3.79150 0.874720 3.79200 0.886100 3.79250 0.920494 3.79300 0.930601 3.79350 0.915685 3.79400 0.876802 3.79450 0.878718 3.79500 0.916834 3.79550 0.930172 3.79600 0.931193 3.79650 0.931476 3.79700 0.926743 3.79750 0.912376 3.79800 0.899385 3.79850 0.915912 3.79900 0.930605 3.79950 0.930251 3.80000 0.922275 3.80050 0.922143 3.80100 0.927319 3.80150 0.927451 3.80200 0.927806 3.80250 0.929537 3.80300 0.928757 3.80350 0.921441 3.80400 0.899801 3.80450 0.888154 3.80500 0.906717 3.80550 0.924416 3.80600 0.929197 3.80650 0.930794 3.80700 0.929987 3.80750 0.925672 3.80800 0.914990 3.80850 0.905939 3.80900 0.899362 3.80950 0.901918 3.81000 0.911155 3.81050 0.912217 3.81100 0.907999 3.81150 0.914501 3.81200 0.907648 3.81250 0.878559 3.81300 0.871396 3.81350 0.866071 3.81400 0.857239 3.81450 0.881508 3.81500 0.915050 3.81550 0.925625 3.81600 0.925674 3.81650 0.914607 3.81700 0.892660 3.81750 0.897223 3.81800 0.918311 3.81850 0.920119 3.81900 0.902556 3.81950 0.898328 3.82000 0.917762 3.82050 0.926920 3.82100 0.928334 3.82150 0.929017 3.82200 0.928856 3.82250 0.928963 3.82300 0.928726 3.82350 0.927230 3.82400 0.920239 3.82450 0.915502 3.82500 0.919529 3.82550 0.919656 3.82600 0.923261 3.82650 0.925718 3.82700 0.919091 3.82750 0.904191 3.82800 0.906639 3.82850 0.920056 3.82900 0.925007 3.82950 0.925211 3.83000 0.924883 3.83050 0.923470 3.83100 0.921535 3.83150 0.920292 3.83200 0.916980 3.83250 0.911526 3.83300 0.912049 3.83350 0.898557 3.83400 0.877582 3.83450 0.876125 3.83500 0.873951 3.83550 0.887489 3.83600 0.901969 3.83650 0.896289 3.83700 0.891827 3.83750 0.904988 3.83800 0.905702 3.83850 0.902151 3.83900 0.908147 3.83950 0.907419 3.84000 0.903458 3.84050 0.901534 3.84100 0.907768 3.84150 0.909086 3.84200 0.907170 3.84250 0.907203 3.84300 0.901438 3.84350 0.895419 3.84400 0.898175 3.84450 0.894736 3.84500 0.888385 3.84550 0.890968 3.84600 0.887148 3.84650 0.882521 3.84700 0.877438 3.84750 0.881467 3.84800 0.888676 3.84850 0.893875 3.84900 0.901605 3.84950 0.905661 3.85000 0.901693 3.85050 0.893832 3.85100 0.888552 3.85150 0.896461 3.85200 0.902764 3.85250 0.902770 3.85300 0.903896 3.85350 0.903785 3.85400 0.901893 3.85450 0.900865 3.85500 0.892898 3.85550 0.878873 3.85600 0.870518 3.85650 0.880831 3.85700 0.891815 3.85750 0.893516 3.85800 0.891539 3.85850 0.884247 3.85900 0.871688 3.85950 0.866859 3.86000 0.874359 3.86050 0.878809 3.86100 0.877739 3.86150 0.870645 3.86200 0.867207 3.86250 0.860285 3.86300 0.857616 3.86350 0.857616 3.86400 0.861373 3.86450 0.861431 3.86500 0.858028 3.86550 0.855213 3.86600 0.847457 3.86650 0.849141 3.86700 0.842916 3.86750 0.837250 3.86800 0.827011 3.86850 0.825227 3.86900 0.817496 3.86950 0.824437 3.87000 0.823015 3.87050 0.821470 3.87100 0.814600 3.87150 0.816815 3.87200 0.803373 3.87250 0.794406 3.87300 0.790290 3.87350 0.803279 3.87400 0.794914 3.87450 0.795960 3.87500 0.793137 3.87550 0.800080 3.87600 0.790848 3.87650 0.795720 3.87700 0.777758 3.87750 0.778835 3.87800 0.763146 3.87850 0.783537 3.87900 0.773600 3.87950 0.787414 3.88000 0.771176 3.88050 0.778252 3.88100 0.764849 3.88150 0.775734 3.88200 0.771553 3.88250 0.770202 3.88300 0.777867 3.88350 0.769159 3.88400 0.783888 3.88450 0.765064 3.88500 0.783867 3.88550 0.758678 3.88600 0.775110 3.88650 0.768182 3.88700 0.776628 3.88750 0.784267 3.88800 0.770434 3.88850 0.790383 3.88900 0.766714 3.88950 0.787321 3.89000 0.774275 3.89050 0.776642 3.89100 0.778058 3.89150 0.778179 3.89200 0.801082 3.89250 0.780286 3.89300 0.800587 3.89350 0.792846 3.89400 0.800228 3.89450 0.813858 3.89500 0.802728 3.89550 0.829085 3.89600 0.818642 3.89650 0.830523 3.89700 0.842055 3.89750 0.830284 3.89800 0.846659 3.89850 0.844890 3.89900 0.852682 3.89950 0.862854 3.90000 0.858421 3.90050 0.865934 3.90100 0.875806 3.90150 0.875606 3.90200 0.867403 3.90250 0.861125 3.90300 0.856016 3.90350 0.837602 3.90400 0.842767 3.90450 0.844057 3.90500 0.828002 3.90550 0.839817 3.90600 0.818910 3.90650 0.809439 3.90700 0.833037 3.90750 0.808596 3.90800 0.819508 3.90850 0.823713 3.90900 0.793778 3.90950 0.811833 3.91000 0.774555 3.91050 0.751832 3.91100 0.797041 3.91150 0.779991 3.91200 0.791990 3.91250 0.810021 3.91300 0.774358 3.91350 0.801923 3.91400 0.798882 3.91450 0.770916 3.91500 0.806702 3.91550 0.783009 3.91600 0.769207 3.91650 0.804367 3.91700 0.770844 3.91750 0.779912 3.91800 0.807344 3.91850 0.763763 3.91900 0.787400 3.91950 0.803665 3.92000 0.761555 3.92050 0.795571 3.92100 0.796438 3.92150 0.758724 3.92200 0.800827 3.92250 0.793502 3.92300 0.762855 3.92350 0.806084 3.92400 0.790088 3.92450 0.763916 3.92500 0.801453 3.92550 0.777236 3.92600 0.763287 3.92650 0.807545 3.92700 0.779617 3.92750 0.768704 3.92800 0.811629 3.92850 0.780229 3.92900 0.771407 3.92950 0.818360 3.93000 0.793956 3.93050 0.782159 3.93100 0.821785 3.93150 0.798395 3.93200 0.783563 3.93250 0.822445 3.93300 0.804857 3.93350 0.789000 3.93400 0.826638 3.93450 0.811891 3.93500 0.791612 3.93550 0.826833 3.93600 0.818617 3.93650 0.794508 3.93700 0.825884 3.93750 0.824173 3.93800 0.796177 3.93850 0.822917 3.93900 0.830454 3.93950 0.802728 3.94000 0.821858 3.94050 0.835511 3.94100 0.804791 3.94150 0.807606 3.94200 0.824007 3.94250 0.802379 3.94300 0.809184 3.94350 0.838984 3.94400 0.826825 3.94450 0.817147 3.94500 0.838744 3.94550 0.832704 3.94600 0.817153 3.94650 0.835370 3.94700 0.838579 3.94750 0.819660 3.94800 0.829818 3.94850 0.842990 3.94900 0.828789 3.94950 0.828609 3.95000 0.843315 3.95050 0.834852 3.95100 0.826725 3.95150 0.839850 3.95200 0.837967 3.95250 0.821698 3.95300 0.829299 3.95350 0.839619 3.95400 0.825000 3.95450 0.820725 3.95500 0.837216 3.95550 0.837163 3.95600 0.831801 3.95650 0.839691 3.95700 0.840750 3.95750 0.832875 3.95800 0.832496 3.95850 0.826060 3.95900 0.819936 3.95950 0.828257 3.96000 0.838252 3.96050 0.838305 3.96100 0.832826 3.96150 0.836390 3.96200 0.839439 3.96250 0.834936 3.96300 0.834106 3.96350 0.838123 3.96400 0.836587 3.96450 0.832532 3.96500 0.835211 3.96550 0.836506 3.96600 0.833419 3.96650 0.832621 3.96700 0.834792 3.96750 0.834187 3.96800 0.830477 3.96850 0.831338 3.96900 0.832950 3.96950 0.830737 3.97000 0.829514 3.97050 0.831007 3.97100 0.830440 3.97150 0.827375 3.97200 0.828173 3.97250 0.829135 3.97300 0.827664 3.97350 0.826265 3.97400 0.825511 3.97450 0.822606 3.97500 0.810896 3.97550 0.805542 3.97600 0.812903 3.97650 0.815329 3.97700 0.816207 3.97750 0.820252 3.97800 0.822824 3.97850 0.821232 3.97900 0.817784 3.97950 0.813052 3.98000 0.808779 3.98050 0.808101 3.98100 0.807428 3.98150 0.799935 3.98200 0.805205 3.98250 0.814153 3.98300 0.816043 3.98350 0.815537 3.98400 0.815483 3.98450 0.814255 3.98500 0.813752 3.98550 0.812937 3.98600 0.812273 3.98650 0.812170 3.98700 0.811505 3.98750 0.811284 3.98800 0.810109 3.98850 0.809644 3.98900 0.809318 3.98950 0.808340 3.99000 0.808011 3.99050 0.807054 3.99100 0.806770 3.99150 0.805809 3.99200 0.804086 3.99250 0.801399 3.99300 0.800418 3.99350 0.801883 3.99400 0.801775 3.99450 0.800565 3.99500 0.799542 3.99550 0.798779 3.99600 0.798086 3.99650 0.798631 3.99700 0.798746 3.99750 0.798100 3.99800 0.797432 3.99850 0.796848 3.99900 0.795769 3.99950 0.794321 4.00000 0.793263 4.00050 0.792460 4.00100 0.791906 4.00150 0.790770 4.00200 0.789996 4.00250 0.789282 4.00300 0.788595 4.00350 0.787513 4.00400 0.786554 4.00450 0.785536 4.00500 0.784638 4.00550 0.784021 4.00600 0.782618 4.00650 0.780995 4.00700 0.775564 4.00750 0.770433 4.00800 0.765232 4.00850 0.757148 4.00900 0.757792 4.00950 0.756861 4.01000 0.759298 4.01050 0.768317 4.01100 0.770548 4.01150 0.770972 4.01200 0.769822 4.01250 0.769100 4.01300 0.767485 4.01350 0.765223 4.01400 0.765563 4.01450 0.763732 4.01500 0.762289 4.01550 0.760590 4.01600 0.759253 4.01650 0.759907 4.01700 0.757148 4.01750 0.756945 4.01800 0.755749 4.01850 0.753165 4.01900 0.753944 4.01950 0.750041 4.02000 0.750373 4.02050 0.748762 4.02100 0.745739 4.02150 0.747494 4.02200 0.742465 4.02250 0.743530 4.02300 0.741628 4.02350 0.738010 4.02400 0.740852 4.02450 0.734761 4.02500 0.736114 4.02550 0.733957 4.02600 0.728735 4.02650 0.732631 4.02700 0.725807 4.02750 0.726901 4.02800 0.727063 4.02850 0.721243 4.02900 0.725600 4.02950 0.719416 4.03000 0.719085 4.03050 0.721076 4.03100 0.713298 4.03150 0.717759 4.03200 0.712527 4.03250 0.708457 4.03300 0.713619 4.03350 0.704902 4.03400 0.708598 4.03450 0.706877 4.03500 0.697022 4.03550 0.697391 4.03600 0.685643 4.03650 0.688292 4.03700 0.697357 4.03750 0.690877 4.03800 0.699090 4.03850 0.693976 4.03900 0.689388 4.03950 0.697016 4.04000 0.686202 4.04050 0.689952 4.04100 0.690084 4.04150 0.676406 4.04200 0.680439 4.04250 0.673635 4.04300 0.672087 4.04350 0.682467 4.04400 0.672222 4.04450 0.674923 4.04500 0.678092 4.04550 0.671753 4.04600 0.680591 4.04650 0.673689 4.04700 0.671418 4.04750 0.678680 4.04800 0.669166 4.04850 0.673266 4.04900 0.674266 4.04950 0.666165 4.05000 0.673390 4.05050 0.668879 4.05100 0.665713 4.05150 0.671790 4.05200 0.664507 4.05250 0.666431 4.05300 0.668763 4.05350 0.661806 4.05400 0.666112 4.05450 0.664741 4.05500 0.660522 4.05550 0.664381 4.05600 0.661264 4.05650 0.660885 4.05700 0.663735 4.05750 0.660073 4.05800 0.661080 4.05850 0.662057 4.05900 0.659388 4.05950 0.660228 4.06000 0.660142 4.06050 0.658821 4.06100 0.658988 4.06150 0.659079 4.06200 0.657548 4.06250 0.654597 4.06300 0.651550 4.06350 0.650216 4.06400 0.647559 4.06450 0.642944 4.06500 0.640364 4.06550 0.633352 4.06600 0.631183 4.06650 0.636216 4.06700 0.631714 4.06750 0.628857 4.06800 0.630853 4.06850 0.623109 4.06900 0.621957 4.06950 0.622982 4.07000 0.614772 4.07050 0.617389 4.07100 0.616443 4.07150 0.607690 4.07200 0.612120 4.07250 0.608249 4.07300 0.601014 4.07350 0.606759 4.07400 0.599692 4.07450 0.594709 4.07500 0.600943 4.07550 0.591631 4.07600 0.589207 4.07650 0.592944 4.07700 0.580809 4.07750 0.581454 4.07800 0.585150 4.07850 0.575752 4.07900 0.579831 4.07950 0.578633 4.08000 0.565349 4.08050 0.572882 4.08100 0.573585 4.08150 0.564527 4.08200 0.571876 4.08250 0.567617 4.08300 0.559065 4.08350 0.566456 4.08400 0.560799 4.08450 0.555039 4.08500 0.561607 4.08550 0.553861 4.08600 0.550834 4.08650 0.556923 4.08700 0.547084 4.08750 0.545627 4.08800 0.551482 4.08850 0.541618 4.08900 0.540525 4.08950 0.544633 4.09000 0.535922 4.09050 0.536957 4.09100 0.538536 4.09150 0.528791 4.09200 0.531837 4.09250 0.533723 4.09300 0.523976 4.09350 0.525478 4.09400 0.526841 4.09450 0.519121 4.09500 0.520014 4.09550 0.514918 4.09600 0.507542 4.09650 0.514729 4.09700 0.514821 4.09750 0.506707 4.09800 0.508551 4.09850 0.507943 4.09900 0.502017 4.09950 0.503890 4.10000 0.500565 4.10050 0.494693 4.10100 0.497707 4.10150 0.495578 4.10200 0.489234 4.10250 0.489486 4.10300 0.487684 4.10350 0.483577 4.10400 0.484567 4.10450 0.481145 4.10500 0.475654 4.10550 0.476932 4.10600 0.474882 4.10650 0.470113 4.10700 0.469343 4.10750 0.466443 4.10800 0.462777 4.10850 0.462775 4.10900 0.460147 4.10950 0.455150 4.11000 0.454054 4.11050 0.452066 4.11100 0.447959 4.11150 0.446527 4.11200 0.442661 4.11250 0.437438 4.11300 0.436298 4.11350 0.434320 4.11400 0.431779 4.11450 0.430495 4.11500 0.427799 4.11550 0.423068 4.11600 0.419921 4.11650 0.416893 4.11700 0.412462 4.11750 0.411159 4.11800 0.410682 4.11850 0.407446 4.11900 0.404547 4.11950 0.402311 4.12000 0.398946 4.12050 0.395920 4.12100 0.393190 4.12150 0.389319 4.12200 0.386284 4.12250 0.384075 4.12300 0.380870 4.12350 0.377507 4.12400 0.374187 4.12450 0.370612 4.12500 0.367789 4.12550 0.365124 4.12600 0.361552 4.12650 0.356997 4.12700 0.353454 4.12750 0.351058 4.12800 0.348513 4.12850 0.345645 4.12900 0.342480 4.12950 0.338538 4.13000 0.334527 4.13050 0.331755 4.13100 0.328949 4.13150 0.325707 4.13200 0.322348 4.13250 0.318336 4.13300 0.314242 4.13350 0.311537 4.13400 0.308689 4.13450 0.305240 4.13500 0.301753 4.13550 0.297682 4.13600 0.293539 4.13650 0.290778 4.13700 0.287876 4.13750 0.284380 4.13800 0.280770 4.13850 0.276724 4.13900 0.272669 4.13950 0.269695 4.14000 0.266630 4.14050 0.263127 4.14100 0.259452 4.14150 0.255420 4.14200 0.251279 4.14250 0.248076 4.14300 0.244996 4.14350 0.241532 4.14400 0.237879 4.14450 0.233991 4.14500 0.229863 4.14550 0.226430 4.14600 0.223260 4.14650 0.219746 4.14700 0.216084 4.14750 0.212160 4.14800 0.207682 4.14850 0.203708 4.14900 0.200850 4.14950 0.197747 4.15000 0.194214 4.15050 0.190534 4.15100 0.186569 4.15150 0.182330 4.15200 0.178744 4.15250 0.175597 4.15300 0.171951 4.15350 0.168292 4.15400 0.164681 4.15450 0.160857 4.15500 0.157487 4.15550 0.154384 4.15600 0.150954 4.15650 0.147419 4.15700 0.143876 4.15750 0.140206 4.15800 0.136330 4.15850 0.132830 4.15900 0.129759 4.15950 0.126502 4.16000 0.123112 4.16050 0.119692 4.16100 0.116244 4.16150 0.112833 4.16200 0.109603 4.16250 0.106390 4.16300 1.03140E-01 4.16350 9.99059E-02 4.16400 9.66974E-02 4.16450 9.34549E-02 4.16500 9.02848E-02 4.16550 8.72630E-02 4.16600 8.42312E-02 4.16650 8.12137E-02 4.16700 7.82405E-02 4.16750 7.52792E-02 4.16800 7.23399E-02 4.16850 6.94750E-02 4.16900 6.66983E-02 4.16950 6.39533E-02 4.17000 6.12338E-02 4.17050 5.85592E-02 4.17100 5.59368E-02 4.17150 5.33413E-02 4.17200 5.08086E-02 4.17250 4.83752E-02 4.17300 4.59705E-02 4.17350 4.36091E-02 4.17400 4.13232E-02 4.17450 3.90819E-02 4.17500 3.68913E-02 4.17550 3.47646E-02 4.17600 3.27242E-02 4.17650 3.07441E-02 4.17700 2.88065E-02 4.17750 2.69104E-02 4.17800 2.50773E-02 4.17850 2.33034E-02 4.17900 2.15705E-02 4.17950 1.98873E-02 4.18000 1.82441E-02 4.18050 1.66531E-02 4.18100 1.50602E-02 4.18150 1.35810E-02 4.18200 1.20403E-02 4.18250 1.07259E-02 4.18300 9.29839E-03 4.18350 8.17188E-03 4.18400 6.93094E-03 4.18450 5.92354E-03 4.18500 5.01647E-03 4.18550 4.05469E-03 4.18600 3.52783E-03 4.18650 2.60022E-03 4.18700 2.28597E-03 4.18750 1.62705E-03 4.18800 1.26226E-03 4.18850 1.01039E-03 4.18900 5.98714E-04 4.18950 5.19988E-04 4.19000 3.05751E-04 4.19050 1.81818E-04 4.19100 1.46604E-04 4.19150 5.89732E-05 4.19200 3.41927E-05 4.19250 2.08923E-05 4.19300 4.06534E-06 4.19350 2.17920E-07 4.19400 2.87676E-09 4.19450 0. 4.19500 0. 4.19550 0. 4.19600 0. 4.19650 0. 4.19700 0. 4.19750 0. 4.19800 0. 4.19850 0. 4.19900 0. 4.19950 0. 4.20000 0. 4.20050 0. 4.20100 0. 4.20150 0. 4.20200 0. 4.20250 0. 4.20300 0. 4.20350 0. 4.20400 0. 4.20450 0. 4.20500 0. 4.20550 0. 4.20600 0. 4.20650 0. 4.20700 0. 4.20750 0. 4.20800 0. 4.20850 0. 4.20900 0. 4.20950 0. 4.21000 0. 4.21050 0. 4.21100 0. 4.21150 0. 4.21200 0. 4.21250 0. 4.21300 0. 4.21350 0. 4.21400 0. 4.21450 0. 4.21500 0. 4.21550 0. 4.21600 0. 4.21650 0. 4.21700 0. 4.21750 0. 4.21800 0. 4.21850 0. 4.21900 0. 4.21950 0. 4.22000 0. 4.22050 0. 4.22100 0. 4.22150 0. 4.22200 0. 4.22250 0. 4.22300 0. 4.22350 0. 4.22400 0. 4.22450 0. 4.22500 0. 4.22550 0. 4.22600 0. 4.22650 0. 4.22700 0. 4.22750 0. 4.22800 0. 4.22850 0. 4.22900 0. 4.22950 0. 4.23000 0. 4.23050 0. 4.23100 0. 4.23150 0. 4.23200 0. 4.23250 0. 4.23300 0. 4.23350 0. 4.23400 0. 4.23450 0. 4.23500 0. 4.23550 0. 4.23600 0. 4.23650 0. 4.23700 0. 4.23750 0. 4.23800 0. 4.23850 0. 4.23900 0. 4.23950 0. 4.24000 0. 4.24050 0. 4.24100 0. 4.24150 0. 4.24200 0. 4.24250 0. 4.24300 0. 4.24350 0. 4.24400 0. 4.24450 0. 4.24500 0. 4.24550 0. 4.24600 0. 4.24650 0. 4.24700 0. 4.24750 0. 4.24800 0. 4.24850 0. 4.24900 0. 4.24950 0. 4.25000 0. 4.25050 0. 4.25100 0. 4.25150 0. 4.25200 0. 4.25250 0. 4.25300 0. 4.25350 0. 4.25400 0. 4.25450 0. 4.25500 0. 4.25550 0. 4.25600 0. 4.25650 0. 4.25700 0. 4.25750 0. 4.25800 0. 4.25850 0. 4.25900 0. 4.25950 0. 4.26000 0. 4.26050 0. 4.26100 0. 4.26150 0. 4.26200 0. 4.26250 0. 4.26300 0. 4.26350 0. 4.26400 0. 4.26450 0. 4.26500 0. 4.26550 0. 4.26600 0. 4.26650 0. 4.26700 0. 4.26750 0. 4.26800 0. 4.26850 0. 4.26900 0. 4.26950 0. 4.27000 0. 4.27050 0. 4.27100 0. 4.27150 0. 4.27200 0. 4.27250 0. 4.27300 0. 4.27350 0. 4.27400 0. 4.27450 0. 4.27500 0. 4.27550 0. 4.27600 0. 4.27650 0. 4.27700 0. 4.27750 0. 4.27800 0. 4.27850 0. 4.27900 0. 4.27950 0. 4.28000 0. 4.28050 0. 4.28100 0. 4.28150 0. 4.28200 0. 4.28250 0. 4.28300 0. 4.28350 0. 4.28400 0. 4.28450 0. 4.28500 0. 4.28550 0. 4.28600 0. 4.28650 0. 4.28700 0. 4.28750 0. 4.28800 0. 4.28850 0. 4.28900 0. 4.28950 0. 4.29000 0. 4.29050 0. 4.29100 0. 4.29150 0. 4.29200 0. 4.29250 0. 4.29300 0. 4.29350 0. 4.29400 0. 4.29450 0. 4.29500 0. 4.29550 0. 4.29600 0. 4.29650 0. 4.29700 0. 4.29750 0. 4.29800 0. 4.29850 0. 4.29900 0. 4.29950 0. 4.30000 0. 4.30050 0. 4.30100 0. 4.30150 0. 4.30200 0. 4.30250 0. 4.30300 0. 4.30350 0. 4.30400 0. 4.30450 0. 4.30500 0. 4.30550 0. 4.30600 0. 4.30650 0. 4.30700 0. 4.30750 0. 4.30800 0. 4.30850 0. 4.30900 0. 4.30950 0. 4.31000 0. 4.31050 0. 4.31100 0. 4.31150 0. 4.31200 0. 4.31250 0. 4.31300 0. 4.31350 0. 4.31400 0. 4.31450 0. 4.31500 0. 4.31550 0. 4.31600 0. 4.31650 0. 4.31700 0. 4.31750 0. 4.31800 0. 4.31850 0. 4.31900 0. 4.31950 0. 4.32000 0. 4.32050 0. 4.32100 0. 4.32150 0. 4.32200 0. 4.32250 0. 4.32300 0. 4.32350 0. 4.32400 0. 4.32450 0. 4.32500 0. 4.32550 0. 4.32600 0. 4.32650 0. 4.32700 0. 4.32750 0. 4.32800 0. 4.32850 0. 4.32900 0. 4.32950 0. 4.33000 0. 4.33050 0. 4.33100 0. 4.33150 0. 4.33200 0. 4.33250 0. 4.33300 0. 4.33350 0. 4.33400 0. 4.33450 0. 4.33500 0. 4.33550 0. 4.33600 0. 4.33650 0. 4.33700 0. 4.33750 0. 4.33800 0. 4.33850 0. 4.33900 0. 4.33950 0. 4.34000 0. 4.34050 0. 4.34100 0. 4.34150 0. 4.34200 0. 4.34250 0. 4.34300 0. 4.34350 0. 4.34400 0. 4.34450 0. 4.34500 0. 4.34550 0. 4.34600 0. 4.34650 0. 4.34700 0. 4.34750 0. 4.34800 0. 4.34850 0. 4.34900 0. 4.34950 0. 4.35000 0. 4.35050 0. 4.35100 0. 4.35150 0. 4.35200 0. 4.35250 0. 4.35300 0. 4.35350 0. 4.35400 0. 4.35450 0. 4.35500 0. 4.35550 0. 4.35600 0. 4.35650 0. 4.35700 0. 4.35750 0. 4.35800 0. 4.35850 0. 4.35900 0. 4.35950 0. 4.36000 0. 4.36050 0. 4.36100 0. 4.36150 0. 4.36200 0. 4.36250 0. 4.36300 0. 4.36350 0. 4.36400 0. 4.36450 0. 4.36500 0. 4.36550 0. 4.36600 0. 4.36650 0. 4.36700 0. 4.36750 0. 4.36800 0. 4.36850 0. 4.36900 0. 4.36950 0. 4.37000 0. 4.37050 0. 4.37100 0. 4.37150 1.45745E-09 4.37200 1.89976E-07 4.37250 4.72338E-06 4.37300 3.39044E-05 4.37350 6.98734E-05 4.37400 4.10755E-05 4.37450 7.34538E-06 4.37500 1.28891E-05 4.37550 9.75554E-05 4.37600 2.52611E-04 4.37650 2.15945E-04 4.37700 5.83381E-05 4.37750 2.88221E-05 4.37800 2.57909E-04 4.37850 8.91630E-04 4.37900 1.24768E-03 4.37950 1.53929E-03 4.38000 1.96160E-03 4.38050 1.23701E-03 4.38100 4.66956E-04 4.38150 1.91997E-04 4.38200 4.84889E-05 4.38250 1.52762E-05 4.38300 7.38050E-05 4.38350 3.29145E-04 4.38400 4.96661E-04 4.38450 2.15111E-04 4.38500 2.70901E-05 4.38550 4.54316E-06 4.38600 3.78773E-05 4.38650 1.16438E-04 4.38700 1.14703E-04 4.38750 3.99505E-05 4.38800 4.75128E-06 4.38850 1.50953E-06 4.38900 1.55983E-05 4.38950 4.84433E-05 4.39000 4.02808E-05 4.39050 8.91040E-06 4.39100 5.22384E-07 4.39150 8.81681E-09 4.39200 1.41008E-07 4.39250 3.35473E-06 4.39300 2.13106E-05 4.39350 3.65936E-05 4.39400 1.70251E-05 4.39450 2.15445E-06 4.39500 4.58233E-07 4.39550 7.33621E-06 4.39600 3.87604E-05 4.39650 5.75940E-05 4.39700 2.43400E-05 4.39750 2.92557E-06 4.39800 1.24957E-07 4.39850 1.40379E-06 4.39900 2.08596E-05 4.39950 8.92652E-05 4.40000 1.12751E-04 4.40050 4.28264E-05 4.40100 4.88213E-06 4.40150 7.90382E-07 4.40200 1.14748E-05 4.40250 6.14110E-05 4.40300 9.88700E-05 4.40350 4.93643E-05 4.40400 8.08794E-06 4.40450 5.09460E-07 4.40500 9.36044E-07 4.40550 9.44320E-06 4.40600 3.92555E-05 4.40650 8.75527E-05 4.40700 8.32043E-05 4.40750 2.51813E-05 4.40800 2.29733E-06 4.40850 2.45936E-06 4.40900 2.59770E-05 4.40950 1.37453E-04 4.41000 2.69817E-04 4.41050 1.77976E-04 4.41100 3.93874E-05 4.41150 3.10249E-06 4.41200 1.26939E-05 4.41250 1.81001E-04 4.41300 8.06423E-04 4.41350 1.19935E-03 4.41400 6.33457E-04 4.41450 1.19440E-04 4.41500 9.35754E-06 4.41550 5.50369E-05 4.41600 5.35522E-04 4.41650 1.82873E-03 4.41700 2.22286E-03 4.41750 9.24570E-04 4.41800 1.23985E-04 4.41850 1.03996E-05 4.41900 1.23113E-04 4.41950 8.98436E-04 4.42000 2.14764E-03 4.42050 1.75847E-03 4.42100 6.27424E-04 4.42150 2.04135E-04 4.42200 4.96044E-05 4.42250 9.21165E-05 4.42300 8.01634E-04 4.42350 2.46058E-03 4.42400 2.63355E-03 4.42450 1.71595E-03 4.42500 9.48818E-04 4.42550 2.35021E-04 4.42600 1.45257E-04 4.42650 9.98260E-04 4.42700 2.47239E-03 4.42750 3.05703E-03 4.42800 5.99212E-03 4.42850 7.43127E-03 4.42900 3.17459E-03 4.42950 4.97004E-04 4.43000 5.45414E-04 4.43050 2.09134E-03 4.43100 7.48731E-03 4.43150 2.07705E-02 4.43200 2.41198E-02 4.43250 1.09202E-02 4.43300 1.85035E-03 4.43350 1.53272E-04 4.43400 7.68504E-04 4.43450 7.40557E-03 4.43500 2.81424E-02 4.43550 3.74237E-02 4.43600 1.68647E-02 4.43650 2.83228E-03 4.43700 3.98465E-04 4.43750 9.84583E-04 4.43800 8.99221E-03 4.43850 2.94991E-02 4.43900 3.68256E-02 4.43950 2.60548E-02 4.44000 1.14614E-02 4.44050 3.78331E-03 4.44100 1.24692E-03 4.44150 3.34536E-03 4.44200 1.65728E-02 4.44250 4.74705E-02 4.44300 6.21879E-02 4.44350 3.59381E-02 4.44400 2.09443E-02 4.44450 1.27589E-02 4.44500 4.14917E-03 4.44550 1.26294E-02 4.44600 5.40787E-02 4.44650 7.95956E-02 4.44700 4.98576E-02 4.44750 4.66747E-02 4.44800 4.48139E-02 4.44850 1.79792E-02 4.44900 9.38092E-03 4.44950 3.54121E-02 4.45000 6.63210E-02 4.45050 5.00071E-02 4.45100 5.48736E-02 4.45150 6.82396E-02 4.45200 4.91982E-02 4.45250 2.71416E-02 4.45300 1.39817E-02 4.45350 2.82739E-02 4.45400 3.27536E-02 4.45450 3.67099E-02 4.45500 6.26726E-02 4.45550 5.59118E-02 4.45600 5.08018E-02 4.45650 3.73346E-02 4.45700 1.23777E-02 4.45750 8.11773E-03 4.45800 1.38328E-02 4.45850 3.98425E-02 4.45900 6.04592E-02 4.45950 6.74567E-02 4.46000 9.12996E-02 4.46050 5.46578E-02 4.46100 1.28652E-02 4.46150 8.48518E-03 4.46200 2.03308E-02 4.46250 5.61681E-02 4.46300 6.61649E-02 4.46350 6.20434E-02 4.46400 8.55826E-02 4.46450 5.19454E-02 4.46500 1.48358E-02 4.46550 8.78687E-03 4.46600 1.58777E-02 4.46650 4.46134E-02 4.46700 6.23438E-02 4.46750 5.19429E-02 4.46800 6.29921E-02 4.46850 4.42479E-02 4.46900 1.86556E-02 4.46950 1.63210E-02 4.47000 1.66989E-02 4.47050 4.96097E-02 4.47100 1.03858E-01 4.47150 7.99682E-02 4.47200 3.88077E-02 4.47250 4.50153E-02 4.47300 3.94336E-02 4.47350 2.52310E-02 4.47400 1.78227E-02 4.47450 1.76451E-02 4.47500 6.17339E-02 4.47550 0.105105 4.47600 7.09658E-02 4.47650 7.10820E-02 4.47700 0.109933 4.47750 6.84886E-02 4.47800 2.87308E-02 4.47850 3.33235E-02 4.47900 3.71116E-02 4.47950 6.19893E-02 4.48000 9.37548E-02 4.48050 7.08317E-02 4.48100 7.26721E-02 4.48150 0.116146 4.48200 8.06277E-02 4.48250 4.89525E-02 4.48300 9.69953E-02 4.48350 1.00434E-01 4.48400 9.13643E-02 4.48450 0.138209 4.48500 0.106413 4.48550 7.97803E-02 4.48600 0.136360 4.48650 0.122351 4.48700 7.01300E-02 4.48750 0.106394 4.48800 0.146659 4.48850 0.106203 4.48900 0.125071 4.48950 0.198020 4.49000 0.156973 4.49050 0.157898 4.49100 0.246504 4.49150 0.211197 4.49200 0.188060 4.49250 0.295959 4.49300 0.266987 4.49350 0.190025 4.49400 0.278656 4.49450 0.302146 4.49500 0.244458 4.49550 0.269450 4.49600 0.316912 4.49650 0.409150 4.49700 0.463783 4.49750 0.397145 4.49800 0.363814 4.49850 0.271170 4.49900 0.283891 4.49950 0.364703 4.50000 0.271629 4.50050 0.225996 4.50100 0.312102 4.50150 0.277067 4.50200 0.191142 4.50250 0.274353 4.50300 0.290309 4.50350 0.159419 4.50400 0.168762 4.50450 0.241677 4.50500 0.170121 4.50550 0.112904 4.50600 0.167374 4.50650 0.188593 4.50700 0.128868 4.50750 1.04182E-01 4.50800 0.180653 4.50850 0.195243 4.50900 0.110563 4.50950 0.150260 4.51000 0.240227 4.51050 0.168189 4.51100 0.119610 4.51150 0.221681 4.51200 0.239078 4.51250 0.131175 4.51300 0.141440 4.51350 0.242094 4.51400 0.193683 4.51450 0.106401 4.51500 0.178212 4.51550 0.222937 4.51600 0.124254 4.51650 1.01912E-01 4.51700 0.192672 4.51750 0.188176 4.51800 0.105007 4.51850 0.112480 4.51900 0.188709 4.51950 0.173521 4.52000 9.91521E-02 4.52050 0.139927 4.52100 0.237857 4.52150 0.193776 4.52200 0.107695 4.52250 0.187350 4.52300 0.273411 4.52350 0.186735 4.52400 0.120641 4.52450 0.222486 4.52500 0.281026 4.52550 0.173592 4.52600 0.122600 4.52650 0.238656 4.52700 0.277770 4.52750 0.162242 4.52800 0.149742 4.52850 0.284882 4.52900 0.288227 4.52950 0.153361 4.53000 0.160247 4.53050 0.283991 4.53100 0.260731 4.53150 0.137482 4.53200 0.133571 4.53250 0.232300 4.53300 0.244068 4.53350 0.152218 4.53400 0.151617 4.53450 0.237545 4.53500 0.252812 4.53550 0.161757 4.53600 0.151443 4.53650 0.277269 4.53700 0.318662 4.53750 0.187061 4.53800 0.147202 4.53850 0.269558 4.53900 0.302643 4.53950 0.195393 4.54000 0.183365 4.54050 0.354189 4.54100 0.412130 4.54150 0.261908 4.54200 0.207409 4.54250 0.375345 4.54300 0.442430 4.54350 0.285561 4.54400 0.199164 4.54450 0.329507 4.54500 0.385887 4.54550 0.246365 4.54600 0.175285 4.54650 0.342953 4.54700 0.427319 4.54750 0.284989 4.54800 0.187204 4.54850 0.304000 4.54900 0.401631 4.54950 0.326879 4.55000 0.230387 4.55050 0.279106 4.55100 0.381733 4.55150 0.370345 4.55200 0.286873 4.55250 0.246785 4.55300 0.340693 4.55350 0.418745 4.55400 0.372055 4.55450 0.251893 4.55500 0.300811 4.55550 0.427885 4.55600 0.447137 4.55650 0.289835 4.55700 0.259513 4.55750 0.439397 4.55800 0.528404 4.55850 0.364406 4.55900 0.226761 4.55950 0.378819 4.56000 0.546608 4.56050 0.483872 4.56100 0.324367 4.56150 0.427118 4.56200 0.608897 4.56250 0.574518 4.56300 0.388083 4.56350 0.401004 4.56400 0.579279 4.56450 0.597097 4.56500 0.413596 4.56550 0.269749 4.56600 0.346288 4.56650 0.478049 4.56700 0.447182 4.56750 0.330920 4.56800 0.440403 4.56850 0.589162 4.56900 0.537835 4.56950 0.426682 4.57000 0.404479 4.57050 0.522213 4.57100 0.569687 4.57150 0.507571 4.57200 0.414391 4.57250 0.354471 4.57300 0.356833 4.57350 0.396518 4.57400 0.494691 4.57450 0.479048 4.57500 0.522011 4.57550 0.555980 4.57600 0.574138 4.57650 0.529350 4.57700 0.497079 4.57750 0.560605 4.57800 0.616636 4.57850 0.626750 4.57900 0.536330 4.57950 0.479669 4.58000 0.434754 4.58050 0.463036 4.58100 0.560919 4.58150 0.513867 4.58200 0.534364 4.58250 0.664911 4.58300 0.721010 4.58350 0.618050 4.58400 0.480163 4.58450 0.551011 4.58500 0.695948 4.58550 0.722765 4.58600 0.619436 4.58650 0.563518 4.58700 0.591772 4.58750 0.510627 4.58800 0.520366 4.58850 0.556750 4.58900 0.641179 4.58950 0.747972 4.59000 0.762814 4.59050 0.683239 4.59100 0.618977 4.59150 0.702012 4.59200 0.775512 4.59250 0.752038 4.59300 0.677955 4.59350 0.656053 4.59400 0.696238 4.59450 0.607677 4.59500 0.467573 4.59550 0.546125 4.59600 0.670062 4.59650 0.748281 4.59700 0.757018 4.59750 0.727802 4.59800 0.720025 4.59850 0.727623 4.59900 0.755261 4.59950 0.763617 4.60000 0.758367 4.60050 0.747376 4.60100 0.725691 4.60150 0.717794 4.60200 0.587047 4.60250 0.478013 4.60300 0.594776 4.60350 0.714554 4.60400 0.766488 4.60450 0.756868 4.60500 0.730058 4.60550 0.682126 4.60600 0.701010 4.60650 0.750245 4.60700 0.774148 4.60750 0.796512 4.60800 0.787342 4.60850 0.757996 4.60900 0.734921 4.60950 0.615622 4.61000 0.488409 4.61050 0.602528 4.61100 0.741940 4.61150 0.784682 4.61200 0.789679 4.61250 0.795773 4.61300 0.807854 4.61350 0.795450 4.61400 0.776823 4.61450 0.791077 4.61500 0.818900 4.61550 0.817382 4.61600 0.782341 4.61650 0.757909 4.61700 0.686499 4.61750 0.521999 4.61800 0.555692 4.61850 0.712795 4.61900 0.793219 4.61950 0.818556 4.62000 0.809968 4.62050 0.807923 4.62100 0.813304 4.62150 0.801805 4.62200 0.758106 4.62250 0.753093 4.62300 0.789792 4.62350 0.788880 4.62400 0.779832 4.62450 0.744626 4.62500 0.582666 4.62550 0.390198 4.62600 0.452906 4.62650 0.673806 4.62700 0.801396 4.62750 0.824734 4.62800 0.810855 4.62850 0.809199 4.62900 0.826816 4.62950 0.831380 4.63000 0.824072 4.63050 0.819503 4.63100 0.831220 4.63150 0.835848 4.63200 0.816133 4.63250 0.736666 4.63300 0.574816 4.63350 0.563968 4.63400 0.730104 4.63450 0.804920 4.63500 0.828817 4.63550 0.843008 4.63600 0.834292 4.63650 0.789443 4.63700 0.757682 4.63750 0.800739 4.63800 0.837821 4.63850 0.835727 4.63900 0.832705 4.63950 0.841019 4.64000 0.829555 4.64050 0.745867 4.64100 0.578996 4.64150 0.597468 4.64200 0.767462 4.64250 0.832102 4.64300 0.834120 4.64350 0.840825 4.64400 0.849192 4.64450 0.837295 4.64500 0.760230 4.64550 0.642034 4.64600 0.696561 4.64650 0.812627 4.64700 0.842540 4.64750 0.840044 4.64800 0.831914 4.64850 0.777556 4.64900 0.645457 4.64950 0.620872 4.65000 0.763553 4.65050 0.840963 4.65100 0.856535 4.65150 0.855341 4.65200 0.851941 4.65250 0.855203 4.65300 0.857114 4.65350 0.857082 4.65400 0.848935 4.65450 0.835950 4.65500 0.832774 4.65550 0.840946 4.65600 0.815956 4.65650 0.723193 4.65700 0.641081 4.65750 0.648287 4.65800 0.762565 4.65850 0.839436 4.65900 0.854972 4.65950 0.853870 4.66000 0.822492 4.66050 0.708598 4.66100 0.617091 4.66150 0.725282 4.66200 0.818992 4.66250 0.835667 4.66300 0.849907 4.66350 0.858283 4.66400 0.861696 4.66450 0.866448 4.66500 0.869763 4.66550 0.867957 4.66600 0.869060 4.66650 0.872489 4.66700 0.871943 4.66750 0.864440 4.66800 0.858034 4.66850 0.866041 4.66900 0.871219 4.66950 0.868547 4.67000 0.867641 4.67050 0.867601 4.67100 0.865296 4.67150 0.866575 4.67200 0.868571 4.67250 0.860030 4.67300 0.829256 4.67350 0.723717 4.67400 0.525465 4.67450 0.538248 4.67500 0.746182 4.67550 0.844205 4.67600 0.845041 4.67650 0.784261 4.67700 0.757775 4.67750 0.812389 4.67800 0.803883 4.67850 0.684300 4.67900 0.601512 4.67950 0.704575 4.68000 0.768835 4.68050 0.728408 4.68100 0.564779 4.68150 0.505015 4.68200 0.620747 4.68250 0.603898 4.68300 0.681057 4.68350 0.820861 4.68400 0.865183 4.68450 0.867401 4.68500 0.859359 4.68550 0.860573 4.68600 0.867831 4.68650 0.868084 4.68700 0.865430 4.68750 0.861845 4.68800 0.854960 4.68850 0.850938 4.68900 0.846527 4.68950 0.834266 4.69000 0.821477 4.69050 0.747092 4.69100 0.579122 4.69150 0.578919 4.69200 0.728203 4.69250 0.766684 4.69300 0.771687 4.69350 0.795203 4.69400 0.786570 4.69450 0.746081 4.69500 0.685483 4.69550 0.569517 4.69600 0.543056 4.69650 0.607816 4.69700 0.676755 4.69750 0.712564 4.69800 0.702857 4.69850 0.704621 4.69900 0.691231 4.69950 0.557957 4.70000 0.453651 4.70050 0.577039 4.70100 0.676542 4.70150 0.680948 4.70200 0.726007 4.70250 0.736078 4.70300 0.704099 4.70350 0.655689 4.70400 0.703656 4.70450 0.714904 4.70500 0.660826 4.70550 0.573229 4.70600 0.511776 4.70650 0.574674 4.70700 0.603852 4.70750 0.539736 4.70800 0.528388 4.70850 0.470414 4.70900 0.466541 4.70950 0.593707 4.71000 0.614142 4.71050 0.620341 4.71100 0.630155 4.71150 0.632926 4.71200 0.663445 4.71250 0.635801 4.71300 0.600647 4.71350 0.610276 4.71400 0.577977 4.71450 0.606113 4.71500 0.648169 4.71550 0.614552 4.71600 0.606094 4.71650 0.611882 4.71700 0.570529 4.71750 0.451189 4.71800 0.436903 4.71850 0.563594 4.71900 0.634656 4.71950 0.656946 4.72000 0.703936 4.72050 0.708192 4.72100 0.642753 4.72150 0.615425 4.72200 0.646924 4.72250 0.670394 4.72300 0.714933 4.72350 0.731532 4.72400 0.692305 4.72450 0.653345 4.72500 0.620488 4.72550 0.624109 4.72600 0.624477 4.72650 0.494709 4.72700 0.450227 4.72750 0.440544 4.72800 0.310740 4.72850 0.367687 4.72900 0.513731 4.72950 0.595787 4.73000 0.716981 4.73050 0.762418 4.73100 0.787642 4.73150 0.793170 4.73200 0.772535 4.73250 0.815162 4.73300 0.861253 4.73350 0.864253 4.73400 0.845788 4.73450 0.843678 4.73500 0.781021 4.73550 0.607287 4.73600 0.564569 4.73650 0.742332 4.73700 0.835784 4.73750 0.813108 4.73800 0.749092 4.73850 0.682665 4.73900 0.663193 4.73950 0.684330 4.74000 0.701637 4.74050 0.684549 4.74100 0.663699 4.74150 0.660747 4.74200 0.657239 4.74250 0.680859 4.74300 0.687300 4.74350 0.662139 4.74400 0.657887 4.74450 0.570056 4.74500 0.408081 4.74550 0.437466 4.74600 0.584780 4.74650 0.663945 4.74700 0.623196 4.74750 0.545606 4.74800 0.600220 4.74850 0.657027 4.74900 0.649640 4.74950 0.655328 4.75000 0.696800 4.75050 0.744425 4.75100 0.748129 4.75150 0.740780 4.75200 0.738124 4.75250 0.745827 4.75300 0.743708 4.75350 0.706983 4.75400 0.588811 4.75450 0.503417 4.75500 0.604921 4.75550 0.704963 4.75600 0.739933 4.75650 0.755776 4.75700 0.771805 4.75750 0.755600 4.75800 0.745322 4.75850 0.730420 4.75900 0.731125 4.75950 0.726148 4.76000 0.708789 4.76050 0.589426 4.76100 0.515739 4.76150 0.643361 4.76200 0.724355 4.76250 0.726648 4.76300 0.670923 4.76350 0.578997 4.76400 0.515972 4.76450 0.641497 4.76500 0.735701 4.76550 0.763278 4.76600 0.758415 4.76650 0.731340 4.76700 0.712242 4.76750 0.596043 4.76800 0.525150 4.76850 0.651507 4.76900 0.759814 4.76950 0.773897 4.77000 0.763842 4.77050 0.762660 4.77100 0.749436 4.77150 0.756904 4.77200 0.752909 4.77250 0.695896 4.77300 0.593814 4.77350 0.537548 4.77400 0.633548 4.77450 0.707854 4.77500 0.709968 4.77550 0.648468 4.77600 0.556209 4.77650 0.447339 4.77700 0.456899 4.77750 0.600157 4.77800 0.685273 4.77850 0.749400 4.77900 0.779240 4.77950 0.764904 4.78000 0.749410 4.78050 0.697490 4.78100 0.715675 4.78150 0.774001 4.78200 0.768034 4.78250 0.675549 4.78300 0.510518 4.78350 0.406147 4.78400 0.288206 4.78450 0.172570 4.78500 0.262867 4.78550 0.457925 4.78600 0.648541 4.78650 0.751558 4.78700 0.760176 4.78750 0.674504 4.78800 0.601737 4.78850 0.668170 4.78900 0.750152 4.78950 0.734852 4.79000 0.612113 4.79050 0.431060 4.79100 0.427030 4.79150 0.548432 4.79200 0.694302 4.79250 0.715701 4.79300 0.622457 4.79350 0.650249 4.79400 0.727964 4.79450 0.703077 4.79500 0.612668 4.79550 0.688245 4.79600 0.769360 4.79650 0.774147 4.79700 0.802170 4.79750 0.811441 4.79800 0.741624 4.79850 0.614809 4.79900 0.615796 4.79950 0.707922 4.80000 0.763260 4.80050 0.790090 4.80100 0.809754 4.80150 0.753070 4.80200 0.592246 4.80250 0.497785 4.80300 0.469637 4.80350 0.526414 4.80400 0.711431 4.80450 0.779202 4.80500 0.722147 4.80550 0.614664 4.80600 0.569105 4.80650 0.688085 4.80700 0.761042 4.80750 0.765058 4.80800 0.760533 4.80850 0.736691 4.80900 0.620507 4.80950 0.490889 4.81000 0.480425 4.81050 0.401817 4.81100 0.279015 4.81150 0.238285 4.81200 0.180438 4.81250 9.74173E-02 4.81300 3.55621E-02 4.81350 8.14577E-03 4.81400 2.17195E-03 4.81450 2.01062E-02 4.81500 0.141790 4.81550 0.403876 4.81600 0.617347 4.81650 0.703843 4.81700 0.725496 4.81750 0.749887 4.81800 0.767941 4.81850 0.744553 4.81900 0.755550 4.81950 0.761361 4.82000 0.718029 4.82050 0.565820 4.82100 0.393617 4.82150 0.474360 4.82200 0.552953 4.82250 0.612290 4.82300 0.679701 4.82350 0.706343 4.82400 0.755354 4.82450 0.716698 4.82500 0.602095 4.82550 0.514619 4.82600 0.538330 4.82650 0.708099 4.82700 0.789166 4.82750 0.806050 4.82800 0.795635 4.82850 0.742044 4.82900 0.596950 4.82950 0.479017 4.83000 0.620498 4.83050 0.757390 4.83100 0.793663 4.83150 0.810594 4.83200 0.780772 4.83250 0.640200 4.83300 0.445442 4.83350 0.505438 4.83400 0.685670 4.83450 0.782357 4.83500 0.830806 4.83550 0.809275 4.83600 0.668628 4.83650 0.452788 4.83700 0.468499 4.83750 0.665062 4.83800 0.771693 4.83850 0.799321 4.83900 0.764617 4.83950 0.631356 4.84000 0.357103 4.84050 0.152292 4.84100 0.252014 4.84150 0.432618 4.84200 0.374438 4.84250 0.155458 4.84300 6.28569E-02 4.84350 0.113365 4.84400 0.228425 4.84450 0.479885 4.84500 0.703947 4.84550 0.797364 4.84600 0.818047 4.84650 0.783710 4.84700 0.612458 4.84750 0.397901 4.84800 0.494551 4.84850 0.720490 4.84900 0.814522 4.84950 0.828840 4.85000 0.798362 4.85050 0.670889 4.85100 0.433767 4.85150 0.413567 4.85200 0.576594 4.85250 0.510377 4.85300 0.277666 4.85350 0.282468 4.85400 0.458609 4.85450 0.410868 4.85500 0.383864 4.85550 0.620799 4.85600 0.798979 4.85650 0.848012 4.85700 0.849923 4.85750 0.789367 4.85800 0.592586 4.85850 0.417267 4.85900 0.574977 4.85950 0.788882 4.86000 0.863859 4.86050 0.870658 4.86100 0.834939 4.86150 0.685507 4.86200 0.460641 4.86250 0.530584 4.86300 0.766927 4.86350 0.865598 4.86400 0.880814 4.86450 0.857834 4.86500 0.741992 4.86550 0.512099 4.86600 0.493559 4.86650 0.725128 4.86700 0.847706 4.86750 0.867656 4.86800 0.861693 4.86850 0.790927 4.86900 0.589554 4.86950 0.482378 4.87000 0.677542 4.87050 0.822839 4.87100 0.847713 4.87150 0.870820 4.87200 0.849180 4.87250 0.694764 4.87300 0.515188 4.87350 0.631365 4.87400 0.816353 4.87450 0.877400 4.87500 0.889860 4.87550 0.865605 4.87600 0.752504 4.87650 0.562716 4.87700 0.598689 4.87750 0.790160 4.87800 0.859733 4.87850 0.857209 4.87900 0.846833 4.87950 0.801162 4.88000 0.645042 4.88050 0.597874 4.88100 0.769811 4.88150 0.867954 4.88200 0.892274 4.88250 0.898362 4.88300 0.866682 4.88350 0.730721 4.88400 0.612808 4.88450 0.735133 4.88500 0.842637 4.88550 0.795206 4.88600 0.607698 4.88650 0.526618 4.88700 0.622861 4.88750 0.616336 4.88800 0.709130 4.88850 0.844434 4.88900 0.885447 4.88950 0.889212 4.89000 0.874620 4.89050 0.811526 4.89100 0.655979 4.89150 0.525091 4.89200 0.362396 4.89250 0.230886 4.89300 0.422321 4.89350 0.688889 4.89400 0.787085 4.89450 0.733354 4.89500 0.697624 4.89550 0.784001 4.89600 0.824738 4.89650 0.802696 4.89700 0.725022 4.89750 0.542285 4.89800 0.259147 4.89850 6.65506E-02 4.89900 8.91169E-02 4.89950 0.309456 4.90000 0.576836 4.90050 0.736871 4.90100 0.804667 4.90150 0.804424 4.90200 0.758348 4.90250 0.795964 4.90300 0.868243 4.90350 0.890752 4.90400 0.895579 4.90450 0.899456 4.90500 0.887327 4.90550 0.837805 4.90600 0.820955 4.90650 0.842177 4.90700 0.791803 4.90750 0.605336 4.90800 0.450908 4.90850 0.550268 4.90900 0.701900 4.90950 0.805599 4.91000 0.880535 4.91050 0.910697 4.91100 0.916575 4.91150 0.919761 4.91200 0.917234 4.91250 0.896292 4.91300 0.873025 4.91350 0.886539 4.91400 0.906928 4.91450 0.912202 4.91500 0.905793 4.91550 0.860829 4.91600 0.753690 4.91650 0.729827 4.91700 0.836869 4.91750 0.901277 4.91800 0.914776 4.91850 0.921646 4.91900 0.923248 4.91950 0.914975 4.92000 0.899019 4.92050 0.897896 4.92100 0.914163 4.92150 0.922408 4.92200 0.923671 4.92250 0.923432 4.92300 0.921693 4.92350 0.912444 4.92400 0.903260 4.92450 0.910452 4.92500 0.914714 4.92550 0.905103 4.92600 0.894219 4.92650 0.901629 4.92700 0.911601 4.92750 0.905200 4.92800 0.902927 4.92850 0.914693 4.92900 0.920531 4.92950 0.919312 4.93000 0.914948 4.93050 0.910009 4.93100 0.897104 4.93150 0.872795 4.93200 0.844848 4.93250 0.748796 4.93300 0.508844 4.93350 0.328327 4.93400 0.268369 4.93450 0.304112 4.93500 0.558504 4.93550 0.761213 4.93600 0.850283 4.93650 0.888722 4.93700 0.901087 4.93750 0.904215 4.93800 0.905882 4.93850 0.903727 4.93900 0.890534 4.93950 0.884923 4.94000 0.896452 4.94050 0.897952 4.94100 0.885697 4.94150 0.853419 4.94200 0.753947 4.94250 0.511115 4.94300 0.286938 4.94350 0.415277 4.94400 0.691181 4.94450 0.831428 4.94500 0.872874 4.94550 0.885475 4.94600 0.892754 4.94650 0.885846 4.94700 0.871963 4.94750 0.881103 4.94800 0.887810 4.94850 0.873222 4.94900 0.846001 4.94950 0.841226 4.95000 0.840484 4.95050 0.804977 4.95100 0.749460 4.95150 0.652499 4.95200 0.433656 4.95250 0.178885 4.95300 0.122308 4.95350 0.206840 4.95400 0.167651 4.95450 8.32333E-02 4.95500 0.177114 4.95550 0.390483 4.95600 0.517064 4.95650 0.494249 4.95700 0.349747 4.95750 0.155425 4.95800 3.60030E-02 4.95850 2.91983E-02 4.95900 0.137671 4.95950 0.348444 4.96000 0.550491 4.96050 0.681161 4.96100 0.758091 4.96150 0.801530 4.96200 0.819314 4.96250 0.830355 4.96300 0.852599 4.96350 0.868109 4.96400 0.871210 4.96450 0.882879 4.96500 0.898115 4.96550 0.902808 4.96600 0.897266 4.96650 0.894569 4.96700 0.906400 4.96750 0.909608 4.96800 0.904752 4.96850 0.908448 4.96900 0.914552 4.96950 0.910934 4.97000 0.901875 4.97050 0.904815 4.97100 0.915721 4.97150 0.916645 4.97200 0.911112 4.97250 0.900285 4.97300 0.897409 4.97350 0.905036 4.97400 0.899399 4.97450 0.893851 4.97500 0.883525 4.97550 0.830868 4.97600 0.659202 4.97650 0.380964 4.97700 0.358490 4.97750 0.622520 4.97800 0.797679 4.97850 0.850080 4.97900 0.847964 4.97950 0.781486 4.98000 0.598841 4.98050 0.326375 4.98100 0.277042 4.98150 0.538119 4.98200 0.762314 4.98250 0.854728 4.98300 0.890579 4.98350 0.906904 4.98400 0.915272 4.98450 0.918136 4.98500 0.909510 4.98550 0.865938 4.98600 0.832236 4.98650 0.880441 4.98700 0.918884 4.98750 0.924630 4.98800 0.925437 4.98850 0.927141 4.98900 0.926206 4.98950 0.922568 4.99000 0.921826 4.99050 0.923215 4.99100 0.919328 4.99150 0.914689 4.99200 0.915728 4.99250 0.916695 4.99300 0.918148 4.99350 0.918296 4.99400 0.921394 4.99450 0.924775 4.99500 0.924046 4.99550 0.922574 4.99600 0.922327 4.99650 0.920933 4.99700 0.913692 4.99750 0.900774 4.99800 0.898561 4.99850 0.902930 4.99900 0.895375 4.99950 0.863371 5.00000 0.810439 5.00050 0.792185 5.00100 0.759818 5.00150 0.622549 5.00200 0.361530 5.00250 0.134370 5.00300 0.169277 5.00350 0.428795 5.00400 0.668715 5.00450 0.790279 5.00500 0.842940 5.00550 0.867617 5.00600 0.880745 5.00650 0.888906 5.00700 0.893607 5.00750 0.894915 5.00800 0.893267 5.00850 0.890179 5.00900 0.889614 5.00950 0.889363 5.01000 0.886010 5.01050 0.881820 5.01100 0.875621 5.01150 0.868860 5.01200 0.862267 5.01250 0.854039 5.01300 0.842320 5.01350 0.826701 5.01400 0.805162 5.01450 0.774552 5.01500 0.727762 5.01550 0.645511 5.01600 0.482977 5.01650 0.242374 5.01700 9.17023E-02 5.01750 7.43204E-02 5.01800 4.27656E-02 5.01850 8.54365E-03 5.01900 6.56119E-04 5.01950 2.49578E-04 5.02000 2.52280E-04 5.02050 2.95188E-03 5.02100 2.79753E-02 5.02150 0.117886 5.02200 0.271942 5.02250 0.428257 5.02300 0.547726 5.02350 0.629427 5.02400 0.682495 5.02450 0.713343 5.02500 0.725219 5.02550 0.729537 5.02600 0.727122 5.02650 0.700811 5.02700 0.638108 5.02750 0.517540 5.02800 0.325704 5.02850 0.126351 5.02900 2.71894E-02 5.02950 4.31819E-02 5.03000 0.178813 5.03050 0.391822 5.03100 0.549878 5.03150 0.587374 5.03200 0.619323 5.03250 0.730223 5.03300 0.809465 5.03350 0.841637 5.03400 0.859447 5.03450 0.865773 5.03500 0.853044 5.03550 0.860358 5.03600 0.889567 5.03650 0.902932 5.03700 0.906848 5.03750 0.908614 5.03800 0.903818 5.03850 0.874708 5.03900 0.841169 5.03950 0.865926 5.04000 0.904428 5.04050 0.919123 5.04100 0.922079 5.04150 0.921388 5.04200 0.913046 5.04250 0.888076 5.04300 0.881021 5.04350 0.901204 5.04400 0.916111 5.04450 0.920106 5.04500 0.911696 5.04550 0.907305 5.04600 0.916366 5.04650 0.916023 5.04700 0.904224 5.04750 0.897815 5.04800 0.843133 5.04850 0.760297 5.04900 0.822202 5.04950 0.906813 5.05000 0.927036 5.05050 0.930295 5.05100 0.931945 5.05150 0.932626 5.05200 0.932100 5.05250 0.929855 5.05300 0.929166 5.05350 0.930793 5.05400 0.930583 5.05450 0.929289 5.05500 0.928592 5.05550 0.923506 5.05600 0.901121 5.05650 0.873174 5.05700 0.889699 5.05750 0.912139 5.05800 0.910428 5.05850 0.891843 5.05900 0.836764 5.05950 0.661715 5.06000 0.399055 5.06050 0.422180 5.06100 0.689779 5.06150 0.846123 5.06200 0.890673 5.06250 0.903984 5.06300 0.913172 5.06350 0.920136 5.06400 0.922859 5.06450 0.923789 5.06500 0.924867 5.06550 0.925355 5.06600 0.925271 5.06650 0.923685 5.06700 0.920150 5.06750 0.919730 5.06800 0.920786 5.06850 0.920327 5.06900 0.919307 5.06950 0.917704 5.07000 0.917066 5.07050 0.915409 5.07100 0.910191 5.07150 0.905888 5.07200 0.906961 5.07250 0.906373 5.07300 0.903445 5.07350 0.899589 5.07400 0.894700 5.07450 0.887531 5.07500 0.872825 5.07550 0.854889 5.07600 0.850293 5.07650 0.842098 5.07700 0.826790 5.07750 0.807216 5.07800 0.781552 5.07850 0.757399 5.07900 0.721259 5.07950 0.659412 5.08000 0.571396 5.08050 0.448757 5.08100 0.291219 5.08150 0.136710 5.08200 3.68731E-02 5.08250 4.71039E-03 5.08300 3.91930E-03 5.08350 2.69501E-02 5.08400 8.30485E-02 5.08450 0.119724 5.08500 8.06327E-02 5.08550 2.52612E-02 5.08600 3.05160E-02 5.08650 0.139254 5.08700 0.337136 5.08750 0.518571 5.08800 0.632302 5.08850 0.706217 5.08900 0.762331 5.08950 0.798324 5.09000 0.821899 5.09050 0.838093 5.09100 0.848732 5.09150 0.857370 5.09200 0.859084 5.09250 0.855978 5.09300 0.867364 5.09350 0.878281 5.09400 0.880940 5.09450 0.880451 5.09500 0.877144 5.09550 0.869747 5.09600 0.851047 5.09650 0.805936 5.09700 0.748649 5.09750 0.671230 5.09800 0.481400 5.09850 0.214377 5.09900 9.60914E-02 5.09950 0.240977 5.10000 0.500371 5.10050 0.684104 5.10100 0.776498 5.10150 0.832239 5.10200 0.857213 5.10250 0.839682 5.10300 0.817595 5.10350 0.854007 5.10400 0.889682 5.10450 0.894187 5.10500 0.881832 5.10550 0.882951 5.10600 0.895977 5.10650 0.895459 5.10700 0.873492 5.10750 0.780051 5.10800 0.631925 5.10850 0.668742 5.10900 0.769185 5.10950 0.732340 5.11000 0.724572 5.11050 0.757531 5.11100 0.659584 5.11150 0.414822 5.11200 0.320324 5.11250 0.505235 5.11300 0.614701 5.11350 0.568199 5.11400 0.409382 5.11450 0.182705 5.11500 5.41840E-02 5.11550 0.115497 5.11600 0.335816 5.11650 0.564735 5.11700 0.708607 5.11750 0.779458 5.11800 0.815410 5.11850 0.848578 5.11900 0.869560 5.11950 0.880131 5.12000 0.887105 5.12050 0.891743 5.12100 0.893909 5.12150 0.890819 5.12200 0.882312 5.12250 0.884941 5.12300 0.893333 5.12350 0.893618 5.12400 0.881341 5.12450 0.820364 5.12500 0.694098 5.12550 0.696540 5.12600 0.813965 5.12650 0.861952 5.12700 0.861497 5.12750 0.828332 5.12800 0.807869 5.12850 0.833132 5.12900 0.826795 5.12950 0.721543 5.13000 0.558831 5.13050 0.597463 5.13100 0.757413 5.13150 0.821759 5.13200 0.827909 5.13250 0.820017 5.13300 0.806262 5.13350 0.786976 5.13400 0.760254 5.13450 0.722022 5.13500 0.667854 5.13550 0.588341 5.13600 0.464204 5.13650 0.288559 5.13700 0.114223 5.13750 2.32351E-02 5.13800 1.20032E-02 5.13850 4.90075E-02 5.13900 9.38655E-02 5.13950 7.71044E-02 5.14000 2.68936E-02 5.14050 9.03515E-03 5.14100 4.39264E-02 5.14150 0.152071 5.14200 0.290068 5.14250 0.384634 5.14300 0.418595 5.14350 0.406507 5.14400 0.366361 5.14450 0.301549 5.14500 0.213296 5.14550 0.118738 5.14600 4.52747E-02 5.14650 9.84843E-03 5.14700 1.01084E-03 5.14750 4.19953E-05 5.14800 1.96166E-05 5.14850 3.83762E-04 5.14900 2.54328E-03 5.14950 5.69234E-03 5.15000 8.87359E-03 5.15050 4.41223E-02 5.15100 0.154988 5.15150 0.302670 5.15200 0.427612 5.15250 0.519266 5.15300 0.577431 5.15350 0.588458 5.15400 0.600293 5.15450 0.674730 5.15500 0.729347 5.15550 0.746004 5.15600 0.747026 5.15650 0.715593 5.15700 0.685806 5.15750 0.734386 5.15800 0.769297 5.15850 0.799457 5.15900 0.825902 5.15950 0.806353 5.16000 0.760983 5.16050 0.792554 5.16100 0.831361 5.16150 0.786951 5.16200 0.705295 5.16250 0.720726 5.16300 0.806409 5.16350 0.852306 5.16400 0.850559 5.16450 0.853556 5.16500 0.869450 5.16550 0.873811 5.16600 0.870794 5.16650 0.858359 5.16700 0.837914 5.16750 0.838405 5.16800 0.832950 5.16850 0.814648 5.16900 0.808555 5.16950 0.793523 5.17000 0.761679 5.17050 0.713669 5.17100 0.640197 5.17150 0.518682 5.17200 0.327264 5.17250 0.127788 5.17300 5.70592E-02 5.17350 0.115877 5.17400 0.192733 5.17450 0.289853 5.17500 0.442921 5.17550 0.529036 5.17600 0.648778 5.17650 0.797829 5.17700 0.854241 5.17750 0.868641 5.17800 0.873097 5.17850 0.868955 5.17900 0.862379 5.17950 0.866251 5.18000 0.875896 5.18050 0.881051 5.18100 0.881590 5.18150 0.880150 5.18200 0.875689 5.18250 0.859303 5.18300 0.836699 5.18350 0.848280 5.18400 0.866882 5.18450 0.869520 5.18500 0.867005 5.18550 0.862763 5.18600 0.851654 5.18650 0.803548 5.18700 0.717678 5.18750 0.733727 5.18800 0.806562 5.18850 0.827511 5.18900 0.819998 5.18950 0.783954 5.19000 0.725039 5.19050 0.719037 5.19100 0.707834 5.19150 0.681905 5.19200 0.720184 5.19250 0.738519 5.19300 0.723167 5.19350 0.692405 5.19400 0.630119 5.19450 0.541790 5.19500 0.487970 5.19550 0.437082 5.19600 0.414073 5.19650 0.377037 5.19700 0.289568 5.19750 0.182818 5.19800 8.60844E-02 5.19850 2.57030E-02 5.19900 4.01882E-03 5.19950 2.75968E-04 5.20000 1.30486E-05 5.20050 4.30023E-05 5.20100 8.63149E-05 5.20150 6.32951E-05 5.20200 5.35923E-04 5.20250 6.79118E-03 5.20300 3.49327E-02 5.20350 9.02334E-02 5.20400 0.175752 5.20450 0.285733 5.20500 0.362380 5.20550 0.389308 5.20600 0.405660 5.20650 0.436620 5.20700 0.438379 5.20750 0.385614 5.20800 0.310848 5.20850 0.284028 5.20900 0.228665 5.20950 0.174114 5.21000 0.154803 5.21050 0.116951 5.21100 6.36240E-02 5.21150 2.37161E-02 5.21200 5.42342E-03 5.21250 6.39848E-04 5.21300 3.18588E-05 5.21350 5.39736E-07 5.21400 2.50503E-06 5.21450 8.78982E-05 5.21500 1.16953E-03 5.21550 6.82322E-03 5.21600 2.40752E-02 5.21650 6.77174E-02 5.21700 0.138812 5.21750 0.220242 5.21800 0.302018 5.21850 0.374292 5.21900 0.433874 5.21950 0.469450 5.22000 0.445407 5.22050 0.421820 5.22100 0.481066 5.22150 0.547905 5.22200 0.610377 5.22250 0.582492 5.22300 0.505570 5.22350 0.560000 5.22400 0.574775 5.22450 0.456961 5.22500 0.490434 5.22550 0.646032 5.22600 0.718339 5.22650 0.733201 5.22700 0.732826 5.22750 0.715325 5.22800 0.632760 5.22850 0.497242 5.22900 0.530176 5.22950 0.634497 5.23000 0.628541 5.23050 0.584769 5.23100 0.579590 5.23150 0.559925 5.23200 0.490666 5.23250 0.368046 5.23300 0.261685 5.23350 0.193110 5.23400 1.03328E-01 5.23450 3.23885E-02 5.23500 5.15729E-03 5.23550 3.64237E-04 5.23600 4.14137E-04 5.23650 5.64691E-03 5.23700 3.39909E-02 5.23750 1.01348E-01 5.23800 0.183745 5.23850 0.240334 5.23900 0.244682 5.23950 0.188810 5.24000 9.72294E-02 5.24050 2.74259E-02 5.24100 3.66085E-03 5.24150 4.95273E-03 5.24200 3.96735E-02 5.24250 0.144874 5.24300 0.297385 5.24350 0.434553 5.24400 0.529351 5.24450 0.565579 5.24500 0.554369 5.24550 0.605048 5.24600 0.671332 5.24650 0.697228 5.24700 0.720877 5.24750 0.729514 5.24800 0.715889 5.24850 0.665501 5.24900 0.550117 5.24950 0.402360 5.25000 0.238537 5.25050 9.64640E-02 5.25100 2.98057E-02 5.25150 7.42896E-02 5.25200 0.246921 5.25250 0.450395 5.25300 0.560536 5.25350 0.631215 5.25400 0.720876 5.25450 0.769450 5.25500 0.772097 5.25550 0.713149 5.25600 0.668164 5.25650 0.722128 5.25700 0.720141 5.25750 0.600486 5.25800 0.417051 5.25850 0.421536 5.25900 0.655543 5.25950 0.795730 5.26000 0.832484 5.26050 0.836954 5.26100 0.813990 5.26150 0.787221 5.26200 0.812185 5.26250 0.840031 5.26300 0.847299 5.26350 0.847621 5.26400 0.844812 5.26450 0.835543 5.26500 0.812124 5.26550 0.784372 5.26600 0.791169 5.26650 0.800164 5.26700 0.797749 5.26750 0.801877 5.26800 0.794326 5.26850 0.757307 5.26900 0.687718 5.26950 0.602093 5.27000 0.510715 5.27050 0.548764 5.27100 0.646577 5.27150 0.663878 5.27200 0.630361 5.27250 0.578754 5.27300 0.508348 5.27350 0.412193 5.27400 0.299225 5.27450 0.178532 5.27500 7.21419E-02 5.27550 1.65859E-02 5.27600 1.89778E-03 5.27650 1.41956E-04 5.27700 8.95184E-04 5.27750 8.95282E-03 5.27800 5.15688E-02 5.27850 0.151602 5.27900 0.271827 5.27950 0.359408 5.28000 0.350505 5.28050 0.281107 5.28100 0.368060 5.28150 0.512502 5.28200 0.571348 5.28250 0.588420 5.28300 0.547481 5.28350 0.434788 5.28400 0.427643 5.28450 0.521540 5.28500 0.546084 5.28550 0.521431 5.28600 0.481271 5.28650 0.435904 5.28700 0.389857 5.28750 0.336538 5.28800 0.269811 5.28850 0.195754 5.28900 0.123185 5.28950 6.22444E-02 5.29000 2.25138E-02 5.29050 5.05633E-03 5.29100 6.02626E-04 5.29150 3.27799E-05 5.29200 6.77782E-07 5.29250 1.11436E-06 5.29300 3.80502E-05 5.29350 5.40606E-04 5.29400 4.49051E-03 5.29450 2.26492E-02 5.29500 6.65216E-02 5.29550 0.131820 5.29600 0.206955 5.29650 0.282080 5.29700 0.350745 5.29750 0.410799 5.29800 0.462355 5.29850 0.506744 5.29900 0.544430 5.29950 0.574371 5.30000 0.597596 5.30050 0.614588 5.30100 0.623953 5.30150 0.623177 5.30200 0.595165 5.30250 0.514671 5.30300 0.436550 5.30350 0.357991 5.30400 0.202466 5.30450 0.134934 5.30500 0.117748 5.30550 5.26849E-02 5.30600 1.03618E-02 5.30650 1.08774E-02 5.30700 6.68695E-02 5.30750 0.205550 5.30800 0.376458 5.30850 0.512955 5.30900 0.604199 5.30950 0.664720 5.31000 0.705791 5.31050 0.733412 5.31100 0.752264 5.31150 0.767509 5.31200 0.781033 5.31250 0.792011 5.31300 0.798645 5.31350 0.803287 5.31400 0.809857 5.31450 0.814803 5.31500 0.816750 5.31550 0.813565 5.31600 0.805610 5.31650 0.804818 5.31700 0.812509 5.31750 0.812451 5.31800 0.788680 5.31850 0.731763 5.31900 0.633332 5.31950 0.449155 5.32000 0.336063 5.32050 0.377198 5.32100 0.388218 5.32150 0.485758 5.32200 0.650292 5.32250 0.762931 5.32300 0.804616 5.32350 0.810988 5.32400 0.809552 5.32450 0.801709 5.32500 0.777613 5.32550 0.758283 5.32600 0.774160 5.32650 0.784196 5.32700 0.770434 5.32750 0.717428 5.32800 0.554756 5.32850 0.328373 5.32900 0.363668 5.32950 0.592174 5.33000 0.714935 5.33050 0.747010 5.33100 0.753955 5.33150 0.752597 5.33200 0.747233 5.33250 0.740214 5.33300 0.733915 5.33350 0.727762 5.33400 0.719693 5.33450 0.709782 5.33500 0.698029 5.33550 0.686103 5.33600 0.673174 5.33650 0.657913 5.33700 0.641196 5.33750 0.623665 5.33800 0.605031 5.33850 0.584078 5.33900 0.560221 5.33950 0.533246 5.34000 0.503052 5.34050 0.470341 5.34100 0.434475 5.34150 0.394457 5.34200 0.348988 5.34250 0.297257 5.34300 0.239931 5.34350 0.176061 5.34400 0.105977 5.34450 4.34366E-02 5.34500 9.53290E-03 5.34550 1.61476E-03 5.34600 2.34086E-03 5.34650 2.67856E-03 5.34700 1.29685E-03 5.34750 2.82016E-04 5.34800 2.68318E-05 5.34850 9.78214E-07 5.34900 9.67941E-09 5.34950 0. 5.35000 0. 5.35050 0. 5.35100 0. 5.35150 0. 5.35200 0. 5.35250 0. 5.35300 0. 5.35350 5.31888E-09 5.35400 6.76332E-07 5.35450 1.98471E-05 5.35500 2.07038E-04 5.35550 8.71145E-04 5.35600 1.59270E-03 5.35650 1.28280E-03 5.35700 4.33812E-04 5.35750 5.68169E-05 5.35800 2.72815E-05 5.35850 5.92407E-04 5.35900 5.78010E-03 5.35950 2.71195E-02 5.36000 7.37757E-02 5.36050 0.139559 5.36100 0.210247 5.36150 0.276243 5.36200 0.333970 5.36250 0.380503 5.36300 0.403590 5.36350 0.370415 5.36400 0.311511 5.36450 0.317030 5.36500 0.434225 5.36550 0.548620 5.36600 0.594000 5.36650 0.613379 5.36700 0.618761 5.36750 0.598626 5.36800 0.572816 5.36850 0.597325 5.36900 0.644184 5.36950 0.653085 5.37000 0.633495 5.37050 0.596025 5.37100 0.498532 5.37150 0.305357 5.37200 0.211598 5.37250 0.369970 5.37300 0.455031 5.37350 0.348942 5.37400 0.400163 5.37450 0.587523 5.37500 0.660934 5.37550 0.635057 5.37600 0.504596 5.37650 0.263859 5.37700 0.136754 5.37750 0.273915 5.37800 0.470142 5.37850 0.523232 5.37900 0.449242 5.37950 0.287111 5.38000 0.111127 5.38050 2.30591E-02 5.38100 3.38744E-02 5.38150 0.154613 5.38200 0.355937 5.38250 0.513644 5.38300 0.592182 5.38350 0.643199 5.38400 0.688041 5.38450 0.710676 5.38500 0.715305 5.38550 0.709487 5.38600 0.668920 5.38650 0.518145 5.38700 0.312264 5.38750 0.361780 5.38800 0.584335 5.38850 0.702335 5.38900 0.735180 5.38950 0.745742 5.39000 0.750866 5.39050 0.753501 5.39100 0.752142 5.39150 0.745741 5.39200 0.732120 5.39250 0.678858 5.39300 0.539583 5.39350 0.469545 5.39400 0.584904 5.39450 0.680037 5.39500 0.704656 5.39550 0.699818 5.39600 0.685307 5.39650 0.660266 5.39700 0.596827 5.39750 0.443420 5.39800 0.218199 5.39850 0.140282 5.39900 0.307492 5.39950 0.501188 5.40000 0.591786 5.40050 0.623304 5.40100 0.631564 5.40150 0.628824 5.40200 0.622599 5.40250 0.613445 5.40300 0.601816 5.40350 0.588640 5.40400 0.572516 5.40450 0.553674 5.40500 0.531586 5.40550 0.505317 5.40600 0.470968 5.40650 0.431782 5.40700 0.392937 5.40750 0.349234 5.40800 0.287778 5.40850 0.184708 5.40900 0.105626 5.40950 8.74172E-02 5.41000 5.53687E-02 5.41050 1.94159E-02 5.41100 3.50767E-03 5.41150 2.85380E-04 5.41200 3.30660E-05 5.41250 5.04517E-04 5.41300 4.17533E-03 5.41350 1.59843E-02 5.41400 3.43283E-02 5.41450 4.96089E-02 5.41500 5.45485E-02 5.41550 4.84713E-02 5.41600 3.57202E-02 5.41650 2.00637E-02 5.41700 6.68404E-03 5.41750 1.01431E-03 5.41800 6.39959E-05 5.41850 2.26461E-06 5.41900 4.90469E-08 5.41950 2.11769E-11 5.42000 0. 5.42050 0. 5.42100 0. 5.42150 0. 5.42200 0. 5.42250 0. 5.42300 0. 5.42350 0. 5.42400 1.54473E-08 5.42450 1.08025E-06 5.42500 2.32928E-05 5.42550 2.08633E-04 5.42600 1.00074E-03 5.42650 3.01453E-03 5.42700 5.61037E-03 5.42750 5.71928E-03 5.42800 2.83265E-03 5.42850 3.27122E-03 5.42900 1.82158E-02 5.42950 5.54411E-02 5.43000 1.02955E-01 5.43050 0.147112 5.43100 0.186721 5.43150 0.222270 5.43200 0.252659 5.43250 0.279555 5.43300 0.300973 5.43350 0.304245 5.43400 0.312035 5.43450 0.347732 5.43500 0.374681 5.43550 0.380081 5.43600 0.350363 5.43650 0.270256 5.43700 0.198636 5.43750 0.230506 5.43800 0.321131 5.43850 0.340056 5.43900 0.290104 5.43950 0.250537 5.44000 0.236616 5.44050 0.190614 5.44100 0.118617 5.44150 5.12054E-02 5.44200 1.28428E-02 5.44250 1.54251E-03 5.44300 9.99536E-05 5.44350 6.84990E-04 5.44400 7.20201E-03 5.44450 3.46486E-02 5.44500 9.10499E-02 5.44550 0.154074 5.44600 0.177344 5.44650 0.127918 5.44700 1.02419E-01 5.44750 0.204017 5.44800 0.317710 5.44850 0.358619 5.44900 0.322736 5.44950 0.202020 5.45000 8.94850E-02 5.45050 8.54677E-02 5.45100 0.193745 5.45150 0.294163 5.45200 0.323718 5.45250 0.337427 5.45300 0.339716 5.45350 0.305743 5.45400 0.216641 5.45450 0.106806 5.45500 1.02932E-01 5.45550 0.174774 5.45600 0.204172 5.45650 0.191135 5.45700 0.162969 5.45750 0.130052 5.45800 9.90518E-02 5.45850 7.15272E-02 5.45900 4.75445E-02 5.45950 2.79514E-02 5.46000 1.37297E-02 5.46050 5.32218E-03 5.46100 1.49865E-03 5.46150 2.72313E-04 5.46200 2.67848E-05 5.46250 1.12693E-06 5.46300 1.45533E-08 5.46350 0. 5.46400 0. 5.46450 0. 5.46500 0. 5.46550 0. 5.46600 0. 5.46650 0. 5.46700 0. 5.46750 3.03549E-08 5.46800 2.13489E-06 5.46850 4.57886E-05 5.46900 3.95639E-04 5.46950 1.84622E-03 5.47000 5.58748E-03 5.47050 1.19854E-02 5.47100 2.22257E-02 5.47150 3.51332E-02 5.47200 4.62472E-02 5.47250 5.36877E-02 5.47300 5.60791E-02 5.47350 5.30440E-02 5.47400 4.50682E-02 5.47450 3.35459E-02 5.47500 2.09950E-02 5.47550 1.04162E-02 5.47600 3.76425E-03 5.47650 8.81722E-04 5.47700 1.14532E-04 5.47750 6.80370E-06 5.47800 1.46597E-07 5.47850 3.88584E-10 5.47900 0. 5.47950 6.44391E-08 5.48000 3.98057E-06 5.48050 8.43082E-05 5.48100 8.00408E-04 5.48150 4.12506E-03 5.48200 1.34735E-02 5.48250 3.14761E-02 5.48300 5.76296E-02 5.48350 8.80779E-02 5.48400 0.116000 5.48450 0.129750 5.48500 0.111790 5.48550 5.99735E-02 5.48600 1.92124E-02 5.48650 3.39319E-02 5.48700 0.107147 5.48750 0.169993 5.48800 0.154242 5.48850 0.110705 5.48900 0.113003 5.48950 0.182524 5.49000 0.184652 5.49050 0.198950 5.49100 0.348086 5.49150 0.473069 5.49200 0.523173 5.49250 0.532916 5.49300 0.502346 5.49350 0.491116 5.49400 0.550281 5.49450 0.597412 5.49500 0.615233 5.49550 0.623942 5.49600 0.630923 5.49650 0.636958 5.49700 0.638342 5.49750 0.634499 5.49800 0.633647 5.49850 0.634415 5.49900 0.629426 5.49950 0.614256 5.50000 0.583224 5.50050 0.514827 5.50100 0.358177 5.50150 0.149966 5.50200 3.93236E-02 5.50250 6.04801E-02 5.50300 0.182845 5.50350 0.366480 5.50400 0.511792 5.50450 0.574686 5.50500 0.587514 5.50550 0.537074 5.50600 0.385606 5.50650 0.300847 5.50700 0.431592 5.50750 0.538398 5.50800 0.551068 5.50850 0.579611 5.50900 0.611067 5.50950 0.603653 5.51000 0.550708 5.51050 0.499873 5.51100 0.528999 5.51150 0.560841 5.51200 0.557640 5.51250 0.544033 5.51300 0.522033 5.51350 0.489253 5.51400 0.448917 5.51450 0.406163 5.51500 0.344978 5.51550 0.262421 5.51600 0.183616 5.51650 1.01786E-01 5.51700 3.41895E-02 5.51750 5.70567E-03 5.51800 8.79390E-04 5.51850 4.19959E-03 5.51900 1.44159E-02 5.51950 2.31335E-02 5.52000 2.00896E-02 5.52050 1.01954E-02 5.52100 2.96492E-03 5.52150 4.52524E-04 5.52200 3.15935E-05 5.52250 8.44875E-07 5.52300 2.65635E-08 5.52350 2.44013E-06 5.52400 7.59352E-05 5.52450 9.61195E-04 5.52500 5.94500E-03 5.52550 2.10886E-02 5.52600 4.75673E-02 5.52650 7.14471E-02 5.52700 9.69348E-02 5.52750 0.153943 5.52800 0.195797 5.52850 0.174543 5.52900 0.137876 5.52950 0.151738 5.53000 0.144315 5.53050 9.59912E-02 5.53100 3.67680E-02 5.53150 6.64104E-03 5.53200 2.44910E-03 5.53250 1.90113E-02 5.53300 7.91757E-02 5.53350 0.178494 5.53400 0.274202 5.53450 0.338950 5.53500 0.366048 5.53550 0.386210 5.53600 0.415615 5.53650 0.416930 5.53700 0.375013 5.53750 0.323370 5.53800 0.280787 5.53850 0.190303 5.53900 7.70454E-02 5.53950 1.64788E-02 5.54000 2.01648E-02 5.54050 8.46797E-02 5.54100 0.186551 5.54150 0.272068 5.54200 0.325513 5.54250 0.344228 5.54300 0.338002 5.54350 0.316207 5.54400 0.279811 5.54450 0.234387 5.54500 0.181547 5.54550 0.120555 5.54600 6.17196E-02 5.54650 2.08133E-02 5.54700 3.85526E-03 5.54750 3.29736E-04 5.54800 2.20920E-05 5.54850 1.54864E-04 5.54900 7.87325E-04 5.54950 2.22683E-03 5.55000 3.53652E-03 5.55050 2.30437E-03 5.55100 6.17192E-04 5.55150 2.98423E-04 5.55200 1.83642E-03 5.55250 5.67850E-03 5.55300 8.04342E-03 5.55350 6.04253E-03 5.55400 2.62397E-03 5.55450 6.55999E-04 5.55500 8.58096E-05 5.55550 4.95827E-06 5.55600 1.00570E-07 5.55650 1.42085E-10 5.55700 2.29469E-10 5.55750 1.13957E-07 5.55800 4.96854E-06 5.55850 6.98112E-05 5.55900 3.80852E-04 5.55950 1.44136E-03 5.56000 6.34001E-03 5.56050 1.76034E-02 5.56100 2.89334E-02 5.56150 4.56527E-02 5.56200 7.00865E-02 5.56250 8.54037E-02 5.56300 8.68363E-02 5.56350 7.69647E-02 5.56400 5.46624E-02 5.56450 2.37520E-02 5.56500 5.58176E-03 5.56550 3.80790E-03 5.56600 4.92004E-03 5.56650 2.47108E-03 5.56700 4.45268E-04 5.56750 2.74335E-05 5.56800 1.23263E-06 5.56850 2.22203E-05 5.56900 2.09185E-04 5.56950 6.39915E-04 5.57000 7.02770E-04 5.57050 4.22882E-04 5.57100 1.24942E-03 5.57150 3.97686E-03 5.57200 6.09825E-03 5.57250 5.46108E-03 5.57300 3.38366E-03 5.57350 1.52947E-03 5.57400 4.71708E-04 5.57450 9.52347E-05 5.57500 1.21855E-05 5.57550 6.98121E-07 5.57600 1.25897E-08 5.57650 0. 5.57700 0. 5.57750 0. 5.57800 0. 5.57850 0. 5.57900 0. 5.57950 0. 5.58000 0. 5.58050 0. 5.58100 0. 5.58150 0. 5.58200 0. 5.58250 0. 5.58300 0. 5.58350 1.76648E-10 5.58400 1.05957E-07 5.58450 4.98160E-06 5.58500 7.68187E-05 5.58550 4.42321E-04 5.58600 9.72458E-04 5.58650 1.25999E-03 5.58700 5.45207E-03 5.58750 2.09932E-02 5.58800 4.50466E-02 5.58850 6.94624E-02 5.58900 9.17806E-02 5.58950 0.109747 5.59000 0.112703 5.59050 8.17191E-02 5.59100 3.71259E-02 5.59150 1.94040E-02 5.59200 3.41528E-02 5.59250 7.01345E-02 5.59300 0.129605 5.59350 0.205564 5.59400 0.251872 5.59450 0.272518 5.59500 0.283161 5.59550 0.286849 5.59600 0.271564 5.59650 0.252346 5.59700 0.261812 5.59750 0.270169 5.59800 0.258529 5.59850 0.230035 5.59900 0.184633 5.59950 0.131931 5.60000 8.66785E-02 astropy-specreduce-05be828/docs/conf.py000066400000000000000000000165611510537250300201330ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Licensed under a 3-clause BSD style license - see LICENSE.rst # # Astropy documentation build configuration file. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this file. # # All configuration values have a default. Some values are defined in # the global Astropy configuration which is loaded here before anything else. # See astropy.sphinx.conf for which values are set there. # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('..')) # IMPORTANT: the above commented section was generated by sphinx-quickstart, but # is *NOT* appropriate for astropy or Astropy affiliated packages. It is left # commented out with this explanation to make it clear why this should not be # done. If the sys.path entry above is added, when the astropy.sphinx.conf # import occurs, it will import the *source* version of astropy instead of the # version installed (if invoked as "make html" or directly with sphinx), or the # version in the build directory (if "python setup.py build_sphinx" is used). # Thus, any C-extensions that are needed to build the documentation will *not* # be accessible, and the documentation will not build correctly. import sys import datetime import sphinx from specreduce import __version__ try: from sphinx_astropy.conf.v1 import * # noqa except ImportError: print('ERROR: the documentation requires the sphinx-astropy package to be installed') sys.exit(1) # xref: https://github.com/sphinx-doc/sphinx/issues/13232#issuecomment-2608708175 if sys.version_info[:2] >= (3, 13) and sphinx.version_info[:2] < (8, 2): import pathlib from sphinx.util.typing import _INVALID_BUILTIN_CLASSES _INVALID_BUILTIN_CLASSES[pathlib.Path] = "pathlib.Path" # -- General configuration ---------------------------------------------------- # By default, highlight as Python 3. highlight_language = 'python3' # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.2' # To perform a Sphinx version check that needs to be more specific than # major.minor, call `check_sphinx_version("x.y.z")` here. # check_sphinx_version("1.2.1") # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns.append('_templates') # This is added to the end of RST files - a good place to put substitutions to # be used globally. rst_epilog += """ """ # -- Project information ------------------------------------------------------ # This does not *have* to match the package name, but typically does project = "specreduce" author = "Astropy Specreduce contributors" copyright = '{0}, {1}'.format( datetime.datetime.now().year, author) # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # The short X.Y version. version = __version__.split('-', 1)[0] # The full version, including alpha/beta/rc tags. release = __version__ # -- 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 } # 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 = '' # 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 # pixels large. html_favicon = '_static/logo_icon.ico' # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '' # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". html_title = '{0} v{1}'.format(project, release) # Output file base name for HTML help builder. htmlhelp_basename = project + 'doc' # Prefixes that are ignored for sorting the Python module index modindex_common_prefix = ["specreduce."] # -- Options for LaTeX output ------------------------------------------------- # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [('index', project + '.tex', project + u' Documentation', author, 'manual')] # -- Options for manual page output ------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [('index', project.lower(), project + u' Documentation', [author], 1)] extensions.append('nbsphinx') # -- Options for the edit_on_github extension --------------------------------- # -- Turn on nitpicky mode for sphinx (to warn about references not found) ---- # nitpicky = True intersphinx_mapping.update( { 'astropy': ('https://docs.astropy.org/en/stable/', None), 'ccdproc': ('https://ccdproc.readthedocs.io/en/stable/', None), 'specutils': ('https://specutils.readthedocs.io/en/stable/', None), 'gwcs': ('https://gwcs.readthedocs.io/en/stable/', None) } ) # # Some warnings are impossible to suppress, and you can list specific references # that should be ignored in a nitpick-exceptions file which should be inside # the docs/ directory. The format of the file should be: # # # # for example: # # py:class astropy.io.votable.tree.Element # py:class astropy.io.votable.tree.SimpleElement # py:class astropy.io.votable.tree.SimpleElementWithContent # # Uncomment the following lines to enable the exceptions: # # for line in open('nitpick-exceptions'): # if line.strip() == "" or line.startswith("#"): # continue # dtype, target = line.split(None, 1) # target = target.strip() # nitpick_ignore.append((dtype, six.u(target))) # -- Options for linkcheck output ------------------------------------------- linkcheck_retry = 5 linkcheck_ignore = [ "https://www.aanda.org/", ] linkcheck_timeout = 180 linkcheck_anchors = False astropy-specreduce-05be828/docs/extinction.rst000066400000000000000000000115771510537250300215540ustar00rootroot00000000000000Atmospheric Extinction ====================== Introduction ------------ The Earth's atmosphere is highly chromatic in its transmission of light. The wavelength-dependence is dominated by scattering in the optical (320-700 nm) and molecular features in the near-infrared and infrared. Supported Optical Extinction Models ----------------------------------- ``specreduce`` offers support for average optical extinction models for a set of observatories: .. csv-table:: :header: "Model Name", "Observatory", "Lat", "Lon", "Elevation (m)", "Ref" "ctio", "Cerro Tololo Int'l Observatory", "-30.165", "70.815", "2215", "1" "kpno", "Kitt Peak Nat'l Observatory", "31.963", "111.6", "2120", "2" "lapalma", "Roque de Los Muchachos Observatory", "28.764", "17.895", "2396", "3" "mko", "Mauna Kea Int'l Observatory", "19.828", "155.48", "4160", "4" "mtham", "Lick Observatory, Mt. Hamilton Station", "37.341", "121.643", "1290", "5" "paranal", "European Southern Obs., Paranal Station", "-24.627", "70.405", "2635", "6" "apo", "Apache Point Observatory", "32.780", "105.82", "2788", "7" 1. The CTIO extinction curve was originally distributed with IRAF and comes from the work of Stone & Baldwin (1983 MN 204, 347) plus Baldwin & Stone (1984 MN 206, 241). The first of these papers lists the points from 3200-8370A while the second extended the flux calibration from 6056 to 10870A but the derived extinction curve was not given in the paper. The IRAF table follows SB83 out to 6436, the redder points presumably come from BS84 with averages used in the overlap region. More recent CTIO extinction curves are shown as Figures in Hamuy et al (92, PASP 104, 533 ; 94 PASP 106, 566). 2. The KPNO extinction table was originally distributed with IRAF. The ultimate provenance of this data is unclear, but it has been used as-is in this form for over 30 years. 3. Extinction table for Roque de Los Muchachos Observatory, La Palma. Described in https://www.ing.iac.es/Astronomy/observing/manuals/ps/tech_notes/tn031.pdf. 4. Median atmospheric extinction data for Mauna Kea Observatory measured by the Nearby SuperNova Factory: https://www.aanda.org/articles/aa/pdf/2013/01/aa19834-12.pdf. 5. Extinction table for Lick Observatory on Mt. Hamilton constructed from https://mthamilton.ucolick.org/techdocs/standards/lick_mean_extinct.html. 6. Updated extinction table for ESO-Paranal taken from https://www.aanda.org/articles/aa/pdf/2011/03/aa15537-10.pdf. 7. Extinction table for Apache Point Observatory. Based on the extinction table used for SDSS and available at https://www.apo.nmsu.edu/arc35m/Instruments/DIS/ (https://www.apo.nmsu.edu/arc35m/Instruments/DIS/images/apoextinct.dat). In each case, the extinction is given in magnitudes per airmass and the wavelengths are in Angstroms. Here is an example that uses the `~specreduce.calibration_data.AtmosphericExtinction` class to load each model and plots the extinction in magnitudes as well as fractional transmission as a function of wavelength: .. plot:: :include-source: import matplotlib.pyplot as plt from specreduce.calibration_data import AtmosphericExtinction, SUPPORTED_EXTINCTION_MODELS fig, ax = plt.subplots(2, 1, sharex=True) for model in SUPPORTED_EXTINCTION_MODELS: ext = AtmosphericExtinction(model=model) ax[0].plot(ext.spectral_axis, ext.extinction_mag, label=model) ax[1].plot(ext.spectral_axis, ext.transmission) ax[0].legend(fancybox=True, shadow=True) ax[1].set_xlabel("Wavelength (Angstroms)") ax[0].set_ylabel("Extinction (mag)") ax[1].set_ylabel("Transmission") plt.tight_layout() fig.show() A convenience class, `~specreduce.calibration_data.AtmosphericTransmission`, is provided for loading data files containing atmospheric transmission versus wavelength. The common use case for this would be loading the output of telluric models. By default it loads a telluric model for an airmass of 1 and 1 mm of precipitable water. Some resources for generating more realistic model atmospheric transmission spectra include https://mwvgroup.github.io/pwv_kpno/1.0.0/documentation/html/index.html and http://www.eso.org/sci/software/pipelines/skytools/molecfit. .. plot:: :include-source: import matplotlib.pyplot as plt from specreduce.calibration_data import AtmosphericTransmission, SUPPORTED_EXTINCTION_MODELS fig, ax = plt.subplots() ext_default = AtmosphericTransmission() ext_custom = AtmosphericTransmission(data_file="atm_transmission_secz1.5_1.6mm.dat") ax.plot(ext_default.spectral_axis, ext_default.transmission, label=r"sec $z$ = 1; 1 mm H$_{2}$O", linewidth=1) ax.plot(ext_custom.spectral_axis, ext_custom.transmission, label=r"sec $z$ = 1.5; 1.6 mm H$_{2}$O", linewidth=1) ax.legend(loc="upper center", bbox_to_anchor=(0.5, 1.12), ncol=2, fancybox=True, shadow=True) ax.set_xlabel("Wavelength (microns)") ax.set_ylabel("Transmission") fig.show() astropy-specreduce-05be828/docs/extraction_quickstart.rst000066400000000000000000000160131510537250300240100ustar00rootroot00000000000000.. _extraction_quickstart: =============================== Spectral Extraction Quick Start =============================== Specreduce provides flexible functionality for extracting a 1D spectrum from a 2D spectral image, including steps for determining the trace of a spectrum, background subtraction, and extraction. 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):: 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. Background ========== 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:: bg = specreduce.background.Background.one_sided(image, trace, separation=5, width=2) or, equivalently:: 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. 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 API above for other required and optional parameters):: extract = specreduce.extract.BoxcarExtract(image-bg, trace, width=3) 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, then this will be used. Otherwise, the ``variance`` parameter must be set.:: 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:: 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):: spectrum2 = extract(width=6) or, for example to override the original ``trace_object``:: 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:: interp_profile_extraction = extract(spatial_profile='interpolated_profile') Or, to override the default of 10 samples and use 20 samples:: 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:: 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. Example Workflow ================ This will produce a 1D spectrum, with flux in units of the 2D spectrum. The 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:: from specreduce.tracing import FlatTrace from specreduce.background import Background from specreduce.extract import BoxcarExtract trace = FlatTrace(image, 15) bg = Background.two_sided(image, trace, separation=5, width=2) extract = BoxcarExtract(image-bg, trace, width=3) spectrum = extract.spectrum astropy-specreduce-05be828/docs/index.rst000066400000000000000000000047351510537250300204750ustar00rootroot00000000000000######################## 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 tasks: #. 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 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 or background-subtracted 2D spectrum, using the trace generated by the first task to generate a 1D spectrum. #. Calculating a 1D wavelength solution from arc spectra that can be used to resample the science spectra to produce wavelength-calibrated spectra, or stored to be used by other tools. Further details about these capabilities are detailed in the sections linked below. Beyond these tasks, basic *image* processing steps (such as bias subtraction) are covered by `ccdproc `_ and other packages, data analysis by `specutils `_, 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. .. _spectral-extraction: ******************* Spectral Extraction ******************* .. toctree:: :maxdepth: 2 extraction_quickstart.rst *********** Calibration *********** .. toctree:: :maxdepth: 1 wavelength_calibration/wavelength_calibration.rst extinction.rst specphot_standards.rst mask_treatment/mask_treatment.rst ***** Index ***** .. toctree:: :maxdepth: 1 api.rst * :ref:`genindex` * :ref:`modindex` * :ref:`search` **************** Development Docs **************** .. toctree:: :maxdepth: 1 process/index terms astropy-specreduce-05be828/docs/make.bat000066400000000000000000000106411510537250300202320ustar00rootroot00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Astropy.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Astropy.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) :end astropy-specreduce-05be828/docs/mask_treatment/000077500000000000000000000000001510537250300216415ustar00rootroot00000000000000astropy-specreduce-05be828/docs/mask_treatment/fig_masking_apply.svg000066400000000000000000000776201510537250300260610ustar00rootroot00000000000000 2025-02-27T11:02:27.464870 image/svg+xml Matplotlib v3.9.2, https://matplotlib.org/ astropy-specreduce-05be828/docs/mask_treatment/fig_masking_apply_mask_only.svg000066400000000000000000001010451510537250300301220ustar00rootroot00000000000000 2025-02-27T11:02:30.168638 image/svg+xml Matplotlib v3.9.2, https://matplotlib.org/ astropy-specreduce-05be828/docs/mask_treatment/fig_masking_apply_nan_only.svg000066400000000000000000001007551510537250300277520ustar00rootroot00000000000000 2025-02-27T11:02:29.756590 image/svg+xml Matplotlib v3.9.2, https://matplotlib.org/ astropy-specreduce-05be828/docs/mask_treatment/fig_masking_ignore.svg000066400000000000000000000766771510537250300262320ustar00rootroot00000000000000 2025-02-27T11:02:27.971940 image/svg+xml Matplotlib v3.9.2, https://matplotlib.org/ astropy-specreduce-05be828/docs/mask_treatment/fig_masking_nan_fill.svg000066400000000000000000001000531510537250300265010ustar00rootroot00000000000000 2025-02-27T11:02:29.355840 image/svg+xml Matplotlib v3.9.2, https://matplotlib.org/ astropy-specreduce-05be828/docs/mask_treatment/fig_masking_propagate.svg000066400000000000000000000777321510537250300267220ustar00rootroot00000000000000 2025-02-27T11:02:28.520732 image/svg+xml Matplotlib v3.9.2, https://matplotlib.org/ astropy-specreduce-05be828/docs/mask_treatment/fig_masking_zero_fill.svg000066400000000000000000001004321510537250300267050ustar00rootroot00000000000000 2025-02-27T11:02:28.955119 image/svg+xml Matplotlib v3.9.2, https://matplotlib.org/ astropy-specreduce-05be828/docs/mask_treatment/mask_treatment.rst000066400000000000000000000037361510537250300254220ustar00rootroot00000000000000.. _mask_treatment: Treatment of masked and non-finite pixel values =============================================== Specreduce provides several options for handling images that contain masked or non-finite pixels. These options allow users to decide whether to preserve, modify, or remove invalid data. The mask treatment option is selected using the ``mask_treatment`` argument in class initializers, methods, and functions where applicable. Note that different classes and procedures within Specreduce may support only a subset of these options. Available Options ----------------- - ``apply`` The input image is left unmodified. Any pixel that is non-finite (e.g., NaN or infinity) is marked as masked, and if an existing mask is present, it is combined with the mask derived from non-finite values. .. image:: fig_masking_apply.svg - ``ignore`` The input image remains unchanged, and any existing mask is discarded. Non-finite values are neither masked nor replaced. .. image:: fig_masking_ignore.svg - ``propagate`` The image data remains unchanged. However, if any pixel is masked or non-finite, the entire cross-dispersion axis containing that pixel is marked as masked. .. image:: fig_masking_propagate.svg - ``zero_fill`` All pixels that are masked or non-finite are replaced with ``0.0`` and the the mask is cleared from the image. .. image:: fig_masking_zero_fill.svg - ``nan_fill`` Similar to zero_fill, but instead of replacing invalid pixels with ``0.0``, they are replaced with ``nan``. The mask is then removed from the image. .. image:: fig_masking_nan_fill.svg - ``apply_mask_only`` The image and its mask are returned as provided. Only the existing mask is applied without incorporating non-finite value checks. .. image:: fig_masking_apply_mask_only.svg - ``apply_nan_only`` The input image is returned unaltered, but any existing mask is ignored. A new mask is generated solely based on non-finite pixels. .. image:: fig_masking_apply_nan_only.svgastropy-specreduce-05be828/docs/process/000077500000000000000000000000001510537250300203015ustar00rootroot00000000000000astropy-specreduce-05be828/docs/process/NIR_MOS_arc.odg000066400000000000000000000313271510537250300227750ustar00rootroot00000000000000PKxL.++mimetypeapplication/vnd.oasis.opendocument.graphicsPKxL_Thumbnails/thumbnail.pngPNG  IHDRKPLTE555>>>AAAKKK\\\dddh#:IDATx܋r(v[Gs ɉݸIgGaD5ge|jjjjjjz4uv?_]/p)ݩUۖ,dR=;#j`u@Bd,̑"aaڵCƉyqڎ#2:$M5IBd5REs̋OQ{5J-Τ̹Cc,C]H#S d"uH⬔XdZ#H [9s1d1XjeDKHoԅ(@>x:Ӗ-]73J~ռh!jEMUͤI5aԚ0~峂m¬"s^Cl?j\QՋh Ѥ]\-E,QD±9u}$jj87ڹ$o#L&o=I9Ϩkk,IJ){/25eRɦs:L1M'&9u۬/_gBy'[yؐ߬A4 >yc˓[Ȯg>؋ףĺi0n%KNu_;jTjzUi Ӟfmuqm[d#mN,ij?9} 9|;b^cEşSIX$ȾCU (퀇PR￴Ԃ(ul:'hօ?:]vbSׂeD2'n.o{UcZU[*IDI(UK{4S$-YN5M蹮v>ϧwVeF{vr Cp\6үuelan.N^H9\ROڤZ 5+XREVzp ۖnJ]?bVpQHlyCn5n]\bO %k;W'sŐ(;s)(]my:N wp5Zy5!{= N9[[8U\s.o9Sk]ӾlۯmL{.cHJ9M7oPsOe}n% r߀mF^ҋqD:%ZI6؆%=IwϛnEk-=t1>%of6uEýy\p`ËkPKҰ$PKxL settings.xmlZr8}HQ0SSC$]f10b7a)Dܒ 4m⩮ŖιtϽK@ѫ\!3*:v"K}T̏De^ )UqSQ^ܾEX)(KBDWo[ŕUn&eX.8>Oi!GBA>oi}Ft_EcF% 㴰j-Lm> Be󄼛+@q/n1Unھ\7.R]aחY|DemUNQ1_'>z,ꦜ&2w}zV:,lv=mbtrr0C9j|Og[/^|< ΅QX\3SH\!wn&ÖX1]?"!6gt}?%,ub*vHHۘ0#YzLl#h uaU:[zꌔW'lJP]fI&Y,`Ua&새 È_7*j7CDԉTH\`S5I?9E!I3@hB>9$"C|pUӢW`(UL|u37LnDQE4\d4LJ2i}H`AҮ; OXVȻ>Z 軮9gQC%k;)+0l4u[)F@X ny[.- 캽6lo ܿ$rL C2w5 + jwQH璠 AXI:V%d8PjWYv(O~N=2?i YjN=HE;DtVmY9Co^k+m' hZNJ4F%u\Vj:?q+gn@7,m(AZBy/Z")T{"( [ Hr|X>Dlʜ G`!)2)'U;ap0A) دPu>M2@Fz\QuG.(n-%ZrBH\lM>SVzJEL9g(:[OG`>퇔X[*p*$|&ьDzQn+#gyܒidU?)_ yBž\}ܱ~Woaou|חn3-uj,c|]PB6 LZq50U/Qϫ|bؘݘLT;e8Yq$K֞cݸv/>4W?û˜^0ܔOy*a"1Aٔ|+V)*X $zcgY®x] PKoJy%&PKxL content.xml]ْ}WHޞncWndz8~CDE@JO1/7")B#yi /#eMY&iDa$YӋ WK窟9@8(k/'+_$$ ,ivIJE[xWYtB:lc.+%wo.ۭF6,n>Kdg:KeJpG(\Ny^LFZSy޴mtŢB*4eihZ.iNdm2ihHN:2|.'\G6siv0 ¤yVT1yA䋁u7PY-ee|ҟYJ'IҨ^uݜ-^ sZ^qD~x $To 4Ӳ΂tIḰYN-22GdHKP \c:aqkh|E]E,zEAc 曉!fǚBXҧ\q'@mb&ΒUPHSB^EمC{+q!H4=WI$̀`Izj-<iv{qX~y>:|j՛Z\yMDziS0FCb|z_NCv-K@E4.'ߒ4ɾۑ+ '5W4 ձdIbA" s`T^5r&|ltBMes[eAP'Jˏ#'CQÙ,\ILfx8wE+;T~W*JȟL鐧*Ox8բ?/ RԼjdt:M猤ЯS|xPF#ZK¾PmiD(rO_k>Z 1\uy5xdGR!rϷ_bu<̂rh!ah<{%_'Q.'ş‘vm b~` GgJ{"R?+75pY3Bwf`| \o#t뜹bͱсp) Ɂ`H|iŴ:SFoށ>:S/d@" $MI>Za":XaYȪJRq%ޝܩw'CO;6{1YQC%Bi.bd!*VyDjy;O_e,,aeѲ/[E4K:Hz'CZ!!da|'Cx8idO{'Dui~DY/Qtz:xK桺gpX %2Ϩک+ۺPf9e52#@ j )vT\_h6 ͏‹0A-&>E_RU^^FleZ6B>ֽˆVikLH6q3"0_iͪQ-K+xhFuN%C 4]֫5!c km6[zGUG+I+yiUPuI{.gb1Q!pfQ)UgU oBw ЯυtV/c ϯ֧D!?nPf!L@Yvüt/uo3o7UG`I) - /_ۺ; )5bW%i vfl`xl D֮"MݶH1[cl:AWBAdmKÖY--e43`k#O~z֦(ի_^^+ZZc ǬlcF<=0Аybmp5w ׵-=uQ]xӵ")9j/UZ.40܄'atmsĮŨ[E:k+V,7G8drns84`lCH!Ҽ–`X0Iĝq@}'4525Ǡ@ЗwAGv>qH {zSc0%RS.%0`L@HEeIeZIS%ZMF]xNNXA޳>aYf~܄<'Bɢ0WrF-Bdl[c+0elݐHg8=qq+Pw={ "T &6n4#HFFSN?3 ޹t ҉C8A25 C-dR;S^ŧ<7` NΓ.YEXputӾ!#k6wN=&a%92TMM%WND4Q Yӈ|ΦɰI[M^sY^Cٰ x4s<4%I&fwH#u=k<9>I'QxHN~9Vcnķ 䂜k!)[1R a6'I~i) }kJ~QBrHfs{LqmBR,yމw > >Y|4{,4^74C6 <QXDS኱fmOV/b7܏q~\ϫ` +f_膉) Yz5Yt CG"Pmm} XJ4v4r`"Xބ?#Ȝ\ݮzwoşs;|Heăd㾳]nݶwn&2[BB3־ߏo?۸}¸e`Bdp%b s00x}ahCj J*#dXX[ C9-!6 ?giհuz'8xGa1:qvN!tl- q$1̠a5lG°(  a*/*wM_ӁPK^ OtPKxLϣ[[5Pictures/100000000000002000000020B2FF2A327EABC87D.pngPNG  IHDR DPLTE3f333f3333f3ffffff3f̙3f3f333f333333333f33333333f33f3ff3f3f3f3333f33̙33333f3333333f3333f3ffffff3f33ff3f3f3f3fff3ffffffffffff3ffff̙fff3fffffff3ffffff3f333f3333f3ffffff3f̙̙3̙f̙̙̙̙3f3f̙333f3̙333f3fff̙fff3f̙̙3f̙3f̙3f333f3333f3ffffff3f̙3f3fOIDATxc'F*U0RU<4IENDB`PKxL styles.xml[_s۸覝ɱƹI.M^k;"! Ip@в%wA9N!v+Y0Yr_q0X?~yC.F߿s\W)]J&/G炖4c\sQNsы يݪ5.﬙ى0u/ɷeJ"+;Rܦp^rQ+6َ![S4{Ny& jRRTybn &9h[+{,Y?gVR,Qs!HVbnE>fD>E Y) /iH|Df3(C{i!ղ]@ Qy OV,h(!4PɵmE%dC/-rsdgyWXʻzaS"]XY)\y _,[Es?,~d{7WEzܔ/cDDAOFu\ %e;,:~̨l=p{.?5 RjCXy@IpwBo@k5`ruPSAM¶v%}N`Es,߂qY=,{DK.-+_E|-\\~汪5_EoD/'_^Wv uWhB_ X$#C 8E~%hhQIWRͼxQM3i]c) qpK%GZZ5<.⯣5>FHv'/jd*C&,_a:E$EmΨs %Һ~\Gpb孟IW&gFFdN덵QYy4[XK1RDa+QA%;$Z)Q Ś8TT X[S2t d!`E>E2`D-Z 76I*(n,iZ)(1հ^{V%#Ql޼QɊ̚^O@c) )1\h~jo]ͻ׷|fz#Kt{kI|_%]v g CE؞V-1>b@GJLF{X`d! Oϣwd+%HLbǓ&V1 Ěw_tP;&c@h Y7WS}_4N'nsJkM+JiQ0:CB(M.Zʖ ){WkbwMI L6m]'x?0< M!f벥솥,4e3DYF?qg}!'1e vl鋕H#T3Y:>ÃҔ$ x37KMNP8$B"t$:;Bx$zv2&OD>8=;!BO3N :C@;ؼ*Z¦Pz QSǚ-53MF5r\7) k/ znsI RT5[ZnQdZ|ǧLp2JxQwM̘Lf4bm+=+8iD.&vM}rvڛ@RggH_V߇%vv_ҷ4 .QZrp90GTf~/ G? K NCmq,+ԘoIrlﴺ~%X6\A7MNmRټ@F G5:[W?:?2xu4MxH8tKh>%:uC~n_|Do.7a t+hCkxpStȷ!B$w){j}xQh>T%Xiw5ĥ|˻4wԯW#.;dUa!OG2>N,&_Cq{m =8iӮ,q<}]g0.8BW}rT2Y3i9[y>FJw0";/wӶak[u.%:oc`w PK* D:PKxLConfigurations2/toolpanel/PKxLConfigurations2/menubar/PKxLConfigurations2/floater/PKxLConfigurations2/statusbar/PKxLConfigurations2/popupmenu/PKxLConfigurations2/images/Bitmaps/PKxLConfigurations2/progressbar/PKxLConfigurations2/toolbar/PKxL'Configurations2/accelerator/current.xmlPKPKxLMETA-INF/manifest.xmlTn0 UM;*Zlw`n8U H@ih%vld'YN$GA;,،OY\)~.ت,D]Cj$][1w2萣rRk+{~~ay+'ɝҮޟu4&m% &܏-TZtn`mV4qĊ_Nx L Raw arc exposures Standardize meta-data Linearity correction Initialize variance Add mask Attach slit traces Cut out slits Resample to linear co-ords Map spectral distortions Map pixels -> wavelength Calibrated arc Rectified arc Subtract dark Part-processed flats Processed dark astropy-specreduce-05be828/docs/process/NIR_MOS_flat.odg000066400000000000000000000363151510537250300231600ustar00rootroot00000000000000PK!L.++mimetypeapplication/vnd.oasis.opendocument.graphicsPK!Lۗ Thumbnails/thumbnail.pngPNG  IHDRZPLTE''',,,555===EEESSSZZZcccnnnsss}}}5 IDATx훉v8 ,wmI9dJE-8 P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P P {Qta֑ҭ8By7V9JYVRy߸Ŵ୳u.ֵ R1Ot85r2(7ppl G t_Щ ;J8꾏_Cϗ#ժjgC9: ap.V\<'ѕXvl3XFec2*K;U7&P&Q=b0yUP}cN,@*Yk;Ͽ|8uPک?J6DOPjzqp6v/7? /5Qgb}NSzo!4 uX8Lj-Sn0xc#^)˿ɿʥnPT4FG&WPe*D]j{c[cZmmU-V#Zf[MK%ZѦ'˳J8ydku xvDG`7{0+Ki-$%gɅBםB֌c:{zձi {.: Uk;S[3\@܊F!nyhW>R#5odй8nQS~S*T{1ԶW#M t+YeչJ!OJV'vk hWˢS*M\puPlm{ q4!a*lE9aEH!ZCn m7`ds8獃)WI{Ԇ{w엸Bf m5МګMvRle 5\j^97 [\r5`Bl۲n9?tѱY; u& mQä; s}׍GXSӪ nr)Ml,ݟ<`H![ajN& ޽IOɉq]lw~ԄtE>z7ߣS(mn#ne[k} 'LQFqxN+F+/!%"(}"(m,+OU7[esI5PÅ vh8^rn*E8hs5)/_bD})(y@ekV?X*!kÍu566IxA8.z+R84;nуsbR7֧cJdBj׵O9ww:(䠧h]sBQ)t 9vye[GG`y -Wv@wËhx/L iR:S0^SO%4,'ke}?ʼb5ȸ^PQ_<#D_deb/(u_g]S/a7`=]N}!q^C,Op>{NNؿf5V3hΐ-NPrTx~?D$/5Nݩ:i|辽n.:>SgP+ya?4{{)6]M,!|iszQ+}ls#%mտkȍ)NilBP P P P P P P P P P P P P P P P P P P/g 9(IENDB`PK!Lmeta.xmlM W:fzڪJE)- :58N6Z3/3CtdʍZ5 M ulǸO]_^i:t\㮍&x5`0 Uqźj5C$Հq1O9t]PF/\?(F!W0MRὦ<nhBS˱֬si/ln@!TжފA^U7gs}4[C@Ƌ>(}¶~?B&bh\XX (\?}3/F .g׹P}>|Qڂkfr+.cfBX)=0J=[|H@<%G`Ӑ],%vHNwȍ0y1w(p¯q `*ߕ_ Lrˣ F!(g֖L;MH0b?8ꬾx=T([Gs ' ][`5'Ã{폝I opFڮ[SKEs>iz)lNC:q 0Tk4Zqd+Ⱥvѯ>$W?ߍ!v+l2e]Ng݀䙞 ԗ}Gq9e-o]ḷs1#ce_ϳ;ov?j7k WiI@"eIfF4fCw|ajAݎa4MioGy;~/,i]y' ?X  m~_w*ovJCi%QM`55 j}5A1sviZ@KM%d/'Jh@@ |= Ҏx\T鴳o޽,z$.p(mh( Nۚ: CqVq4n)"[*Vd:U;d #:fD-cNSp%ڶu4-ơ {X$U~7zG+? =HF*`aWRv2 ÄW7Bk%ˇaIOg k$SǼN&Z$W_St\gS6 W_.֊].Ώ@KHaj>ގ~W pI]sz}"$^D 9Y.gxㄟ9:mU_㴻N$O׵vZnkiƖG g2 ?6 $EZ,hN&;OKӔ:9y? Jo6]a+ }ΓVy*^ __wT~2UMhidK5(,uG`$?__I]4 fM o#[`yo 3?Lv,.5 ϛ,m046͋X', ugmm6\bZUߎ~[㦁t¢|5H>N$`fotqhr6a04ѫ tuBPb}0UID0iy/}zj 2&Hdܹw>PSS.lx(3Og:D5M/dAUs9`溜X_,gA"60L"@PIiZyYtϹBn@%09^jA\z{˲Un> 9jVIPˋϴx:r} ᗱΰ"Ԅ /(YI-We,\Ё~>rĥxȠAz떖ײKDigb(LJ6RiRJ |ԅw3` ǟg5,އq+*2 JVo΋u? 졬.P?5qaʶ:dPZxQ m+pUtӯ.mwT%?@">ֽ*6Om^n#Epۓwm$6H.V%tNi}ޒc>h,\=,b”=ɺFit'd:ƌR{=dc)4{^Q#C?Edp义47I4`LvxOybEOLϹfڮ 7|d2-OB2P"*vWܬ)'`u*vuK R yQ<;YD5ȇP*j DN y kh) /fQn|  tzT;( WW&6$xͅP{Z&Hs)Ty7^20b%:4l肅#tj84 -&(B{uT && فCȐPvl8vt ǖaafy:M5?\R]Wof̰wqLgƆ]lH('wwfO z 7 ) 1ivUKSb:3y r]uvċ<`"#b=wwd 䏾K@3t5&4d{^EksmkB7T8A .'d=b;TnObg _'8ߊ5ҴЊ3)yJ>42{k?|ܿ|~`ۑ~2]RDT06\SΠSny %6 z}ӕ\i &&Ť 9x62:XO{Ӟ"ctRùF>^xT6qڠ61̦'W5ߔ-ŌL9NJW̸nnM7?GI=O˹q-Vl]sH{{Ø\)0GTֳ@GvfԒ*dqn#U0"CačV{}L*lA=,Y;TzBhԢ߭xHTJg+♝%rUx_lk hP?(YE c:,;PK{GPK!Lϣ[[5Pictures/100000000000002000000020B2FF2A327EABC87D.pngPNG  IHDR DPLTE3f333f3333f3ffffff3f̙3f3f333f333333333f33333333f33f3ff3f3f3f3333f33̙33333f3333333f3333f3ffffff3f33ff3f3f3f3fff3ffffffffffff3ffff̙fff3fffffff3ffffff3f333f3333f3ffffff3f̙̙3̙f̙̙̙̙3f3f̙333f3̙333f3fff̙fff3f̙̙3f̙3f̙3f333f3333f3ffffff3f̙3f3fOIDATxc'F*U0RU<4IENDB`PK!L styles.xml[_s۸覝ɱƹI.Cr6w/$$$AΗ}~JB9r7 `~MzL\䗣p<"rۯgx*Ky"*c"MY伜娒\Вfx. Is{2#z5;[5t25;;t3t2:LRXdU|G.Gko6f2r凳F+*j$Ypǡoy3P)j!Y ,.尅9-^ Uvۦ2I$qfT{ D7[нU,y1XMB4Z(yv77+& {LӸA\d]_ahOk =FBs>z3UjxKV@Ã.5!c?d ղdt88/lݨu6َ!)ɍ'qeN XlA! [P"#hhQIWRf^ (&kmc) qpK%ZZ%<.⯢>FHv/jd*C&,_a:E$EmΨs >ot ;UjJrY]xUZ2l|b孟IR[D;kgh!`,|KQ‡DTG0M#R,(j& +M5rm8.bB2(  VL$%QVy°^M%MK I: *zZ ;굧mU2ņkXK`z4-K!V Hz D]I8/%PSѼ+R\odion,Rr﫤˔ ؼܾvдj=&G V xq #R M9:D{=z|K: -z̰b[N:&c@h Y79<8O' 'G٤'(h^NjB)ltRTH#HZ;skO@g@W2EnڐD E&o 0[-e,5dQ)S!⸾g!]wٚlpmhHkǶNCjt'U}3[ 'xPtsyB!G]J ɣt<8}q24NNap2ξ@:+6/`oV)*EB{"u b|VQM ڋ>(*6C҂jMꮖ[3eglَuČYdF-ֶӸCObb'g׫) ѹ,u{ejkλ^`XƐ%jWk@.8j;B臣aiHAâ-eŚ-RvZ]hq{ WˁNmR|G G5:[WN@p84A>ᬣ5/yuF4{qi2gaCe߹q- [o1[Aoz2Lw'ݣ3F )"}HIuZJpZiחϚ7q)_݌jU򈤽sJf \tz!JCf)0Ցwctn#ߍýdC#:894-ؾjrdzuC[Þ!tqz'G]&kFN9A_9 URa &CwOa嫅n <\D3FJ~ u/chXbs^HZBDER\ՕЃT~oLbb #PAI:_s [&eޯ.^c˵|(B_H]|--mREO.`YقV>*Yj=Ri~ J6GFS=V! Part-processedflat spectra Processed flat Attach wavelength calibration Derive “slit function” Project to raw co-ords Normalize continuum Cut out slits Resample to linear co-ords Sum over spatial axis Fit continuum Project to raw co-ords Divide by continuum Spatial flatness correction Divide by slit function Cut out slits Resample tolinear co-ords Calibrated arc Processed twilight flat Inputs Resample tolinear co-ords Inputs astropy-specreduce-05be828/docs/process/NIR_MOS_science.odg000066400000000000000000000373031510537250300236410ustar00rootroot00000000000000PKlL.++mimetypeapplication/vnd.oasis.opendocument.graphicsPKlLXz z Thumbnails/thumbnail.pngPNG  IHDRHPLTESSS[[[gggiiippp}}} IDATx흋ڸ;gVۺrU\({{M !͇p~%?ˏNݩ;uԝSwNݩ;uԝSwNݩ;uԝSw|Oqa_q$)ge'ˋURWr ap#|/Rz6ZY&m; njR9dTГwq a~/KTjqRpzFX چnyJSǺ}+ʼnԿEC+Z.Uۇ!F LکcT!sx7F·ENGz <GjൎD'i: K Cf}2E/7?6!^&mADZ98Cq 5f&g qK^GZK5ݹa(!DJD}鲃"դͯ!jJ VO|Y75_rNs}i܊t>:5vrR41!5NɤC}xtTz[ƹ~;`Շ[ Ռ^?Nz H$ZmW "Uj7W!!א%k)no¾Vl-n1Rryc" Hb%Ɣ up~;q$Uve/z+Xu赧?vڼl>oaٲKzEW\VSW۽NlQdW(ڞx,y~\Clq1SL>cr39ZĎڠT=T Fs1zNhmPJL~'y~=^.0'42B-QrVqԙ3rT 6g2<#f-J׊nYIpFS(Z>YO8`= L#ɺ!d݃P_?-}=^p_N~e7?'`"9z_^JQ%2.& !>֩ 0Wm}%Mεh@~i~ puZz?u3D#ԋ4Sv០׉οۢ.o-ANWE $mҋèQcUI%$۠ j^:,s )ddB 2r fjR KeԈ@!FQj#"oD <027zw^Hϓ!v=1VHwçg^_?Y5-w%%t,lL2>43sK瞧b[6s~ƗCyr'S[>]O[j3 al )אD$Ios(>A▯-sgR,f|> p|}5VA=KimSgWOC.5'zFmVd X''.}b5ru΋j8!ߍ}j,QԂ,<*7ߏTwW@t>w^x|܏zlu au2Iz6e'/Iꅍ:΢̚^nIǗnu|dȱr[VhVQ2 9ցlel%(BΩv[_ u~T@eLiO+~^j/-RQX->!;3ZEZo)R\ 8mH2A*~T!d'q7rokKM5N$ziA79݌%_ԶʵͰCF0#Vj(s؈=P l'ʚO^)s5d?U/펶|m{:yꛊ&sNjҏS+KfisckG ZaR ;R3Vf4^a^xErW)nmg;uR'zlg*ǶD[n1EW9NQ S;hFRN "" >0cD@X5owJАLWѥSwNݩ;uԝSwNݩ;uԝSwNݩ?Sr6M/IENDB`PKlLmeta.xml͎0} lETT."-6C0{qpjZFRK}1COO-(`*F1][i[q;Pi6%oNTKӹa< C4l"myui&Jp ӈo5ٵ΀_k75k:lLcBx>/meskFφ\ݘ\V5g_>!kC=o᳄=XվjbT-[Q1 T1YHlwMHm,O}xi W7j3V ؊/3|ZQ |\$"QwR,ݧ`;wlD$oe֯uӽ>x8^%9U/z/PKp/PKlL settings.xmlZ[s6~aNŐKcfb7a)D\IC}%,,+Ng[#H;|%"BUh ˂ŋW?}a8DU$BTR5Tw*ۗ**UVY[mjFB0},̥RӓόJe۶KuӘ# >m!xv(ʲWu2+uZZ^&rŐEyJ+@qt(n5UnھZ7.R)\aW_V(b"#VEY}(}®~ p<7"V71EKi;AB/Oc |yw_9*#1M.^88bᆙBr +ehq b5Sp@ໜ9Q{L3|"yr$~`R|@n(.Wsg3L$PHpH 9]lٿ<$8HgdM[G]ylYhXztBžM| iMK3[ꌔbMO~ߔz̑*LX3¶M<ه A_7*o9j"DCP(p[de0hK$ <"d934d\! #>dE0ԲzZ )oNvV\YS Cp7ls\g e8tW~,~֊53$9r4erDq/>qE&y5MjŖGNsPƢ[Cbokn $/--/$< ?Rcr,|xHҢ}vT?~%Q"(U,ԌU)uyC_G6sBCN"H3SMtG%x.S !q|Ir#X-h= df1Bw{~?5ĩ#Ԛ$-L')%) -ǻITͧΙXa:;D5E.Cpg &P̐UibJ"%q#FE@$th'DMMW?;OBH_|DQ^gkI,7Sx[N\XlDXZT"D(zr=UDxqnǭFH&ZGIz[ɲID'zyFqvkPqMJn ?;ެm|t8]GQda˵GK`|fMڶWD`# NP[LiI둭 T}NA9X ^ie[=\V]L*$ܿ]Ϛjvt^LZA [38 {br7!SN45Y97[k*/850f ^dp\Ӗg)z Ǻ}r˰u-N^"| vg ]YC֚AP״oVZxF%N#jB@P>% ݊!C%<Ѵ_o-S/PK+x'&PKlL content.xml]r㸕ORvSIHθ:{I;;;l&%J4EjIJ3'$[vk-B987߽\6(M'0'Zy,'7yKh^f&>Kj;ɯ&K $XU1Jab[_ϪJ)V^6f{cڙwO.YڙPTcP_"1/דX_M1l9EOvzel!}X>E6mWaelVwa MPY]gaMu)a݈vL]ۥ})Y٘'2W'2g^2T|UR}mA5ˢkViC*f/MӚVL뇽3loYZӕ4hB[&@xZU?}݇`8nGI^|ʳm%D$2)ж=(1HYN"O-F*0Z4]f) LA0ѷQ :'LCR6bׂ9mZq[e.M20|\YDv݁8[1sn¸\+ o*BMWLo~VjL;v,I!?NiN|X'1kJӶ`f>gqj}jꚎzrbW« H XDOד_4m]U8Ѹ[2LuY :*fl,*o>4Bils@G.!Zmqڍt`\6|:TLBn$XBtv>& ?G_D0nAG[K)iNe.6EJ^ާAܛר}X %L2u]f>5 ^yW2oE_" s +u&HT>͢TA-Aɋhm횭"XQe>aU`9.ҫUZ <[ќ*@؃b: @'Dkd_ fƄ+ x?KZ4e!> RV|F(pmҧ(l8GQ)꫉g ڧ&4PY%)N/x\H<f 9 P0;o,2 ׇ =R@߂./ZlFu"]\51МH МH>Whg6\p!͜5jLv0:=icھDVbEsDj2H?QqOßEem2~JW%߆]PXSf ɑV8~>+L!d44. ]ޢ^u1u([N˷P%,AGႎLUգKwի8JPRUwO`]%)LeޱzfYʵ}h·0nVVߠub=ȣ U48|ձ4"E4s,-}頲Ujnʕ_usu= 4ѿ[/B`1ޗ'Bh VvⳂ\."TF ='# HuM!BP8t۽ݫsw>/3ym&y}׸g=s{/9zꛝg>ǜ]XH6=99q3!w&l8܆q=aw8 0IuYU`?-Mvx[vE>M3zٲ"ۄ9)_}ˌxUUZt ]HzibEUC]qp}g@:[BUƛC:"BޛD>Bذ$B"oxQ9 !iM9M=G~]P.? +=n Vՙ scּ9clbjݔ fơ:ߨ<ԡMGR`~N\דh4 5>˫zlwʉeBjOe/Dס5j  _ |,Ԃd_q,[P==Vk/tS9,z>RFYL@eid:luW.M()r G 3G^к[M ;4gaR%.?i @-KALX0 ITDA zV^tD? 8[(~A@A>Q,~1H,MNٸPP}< $ 0BI1;Ij$\.dsټ mV+fYŌ1~-pLֶ,k  T-D*X*9gTbCPm*!8TeT1 ,pŊ-skG{O Dhe[z6x TzX>d asD ` a6S M[?wڬ@JHǪVd!2V;u9X >2 }~yD#!=J#- sw@sXҖ̞sbDccms)d#ƞ3a2øuPշ"шQyRx-$f GH1̾ [0K|솗6Ƞ襰`E26,iC{ZO9/3=Mn0", BGvP!_7=\B%Hy6_ܴ=>B⺣`\$jõp\i`4drze .f1&5QMbB9A&0/&Sċɠe.A1<$ [`yX1r ktQeމr4dz-DT9gW!}'}lܶB0!} @muJ#/? vd)-Zpc^[#l}ܣӹ»ؤA RL`FU9H -dqT\/)烝h8ک).6-!T~[{/#> ',xbWކذ/K/ru91<ia^GpN[zYG FqN̨ubkM [k9caC0mm"ޒCmqU Gp G.NPՅq1q7iyiqIm-[ڟhQ\b'is2& @,.$ޤ\wCQݧQ%~x1v;!"K!l`mɲ`,FqZrr˓'84|" 7*E~.b~L˽Zaq 3]Ǵڒz!0Thם tDm89`:ݿ=V*BE &}m`>g7 ɈߑX!#6~mZL|i)(l/B&{&A;E}ŔPǛ,i]f Z.mʆv\:򼧖‡ԃ:,ڢruCs[]XuEHJ]Aq0D+TLǒc;6&Kz,.%& w}iEi689No7^bxvoaE&ܗEl%AK&6mbhwA$0~^F,]D+Bs- ohiŞxy V"ai؇m Cs`ƃ6@ XyA0m hgHʱN|2VIBݵ@;\̾\6 nG;iiE̙cs\e0d[IC!ǟyw%4PqBX aj%x}$7%1LX K,֖%٩%  BeǹxXZKҬsAhkK.{Ɇ-bËKdy:kp=XG{æGBS^>G_,[Is?,~d7SwEjܔW/0CJ1 'j:]_ %E;,:~̨=p{n*Ԛ?9+,~LjlBxc_8  j4+8S(a6(wQ-ђ' Kˊb*9b@t52_KyJ 뿯7o—//_0x=̳]BZ4W=V6ɠ-N45IĤK)?f^[y8%$u8|`עFT[1<^A0`L_/z<$|B SOG"JOXhXkxf1yN)5>"kv'/ld*0x$,[a)04$MΰsR %-+aCM Zk ,oLr518+4:EƓ3:6vo)l/|K7D9TGEhDSTLVkjCe^fxaqko1ndj#E=IEMh_ +UPYҤ`5RpDE^`VfG- F6y%kuC5Nr%"LDpVu G4k/lp}gv`6ϷTmi)Uubn{l^sn_S[iZi5#txp8 n9bX<:|K6^;q8cE1,y70AwO9e21EQ}={e!ݷͧs>HK2/8ANclpZ'P#Ja_BAڡ]Xnx:lS ixJNG Okٺl aa&2I uяDMw9mYdk~Wz0wB$>&gRU{jDl)ζxP$tsj9w3dY"49!Bg g?K|.N3ӓ!4yqzvBgF' r`h BA[$4GM!kjX 7Rqݤ03艢Ta]9$-ZKQ֤jiE>B-}c(Ꚙ1LiVt{p\Lrz71U3":ӝ~OL|ys",}_Gc  {DJ5=wQstQt4 `|Md OvZ],R ^{k˶^q#{͆a-apvlx@p8=4A!ᬢ / ԍ{hyqi2gaCeĿ߸ӭy2eL} #߆ =Z}, piu5%|˻4wԯW#.;dzU򤁡!O&G2q]FOg\FluA'7à: -{\ Raw science and sky exposures Standardizemeta-data? Dark subtraction Divide by flat Linearity correction Initialize variance ADU -> electrons Add BPM Reduced data Object - sky Sky subtraction Select sky exposures Associate sky exposures Sky sub. along slit Subtract sky Interpolate sky Register WCS shifts Attach slit traces Attach wavelength calibration Cut out slits Trace object spectra Extract 1D spectra DAR flux correction Correct telluric absorption Resample to linear co-ords Scale exposures tocommon level Stack exposures Apply flux calibration astropy-specreduce-05be828/docs/process/NIR_MOS_trace.odg000066400000000000000000000315131510537250300233230ustar00rootroot00000000000000PK{L.++mimetypeapplication/vnd.oasis.opendocument.graphicsPK{LaThumbnails/thumbnail.pngPNG  IHDRKPLTE"""***555@@@ppp~~~Tw$IDATx : =cVM'- =p γݒ*{l_PC 5PC 5PC 5PC 5PC 5PC 5PC R.{o#^=uR=8ǍL|zw.zwԾacZYF|=HOQ$.I<4>cE7[%ё'k݉:o\ͥOXڡmޅ {QŔ5MQ݌"6F(1@ij޸ڷAc )bb_Ve~Ԗ6=N>ז='ډu45. H}ՆGH  \މzjv^|[BGg|nl[S)3O+ukߪM2,%PWTo˥Z}Mj;ѦZm.Mb{T4*j1Zx}l_sKʵڭX87R^׭}P?׭kV8eu/-O4̺:Nb!zGv|ϝuA>xˬsZxJY_[Ҏ^ןe$X.P#BmvlZNФ!).]-Bs.9:bZk '/>NW浭Crh\N9ܭȗ|i|n;1uw-4 I}}NrMutS-n*6݌[Y_ !k#{ 65b`^ͪsKyeGl#׃k-79M9.~J-Stĺ3PC 5PC 5PC 5PC 5PC 5PC 5PC 5PC 5PC 5PC 5PC 5PC 5PC 5PC 5PC 5PC 5PC 5PC 5PC 5PC 5PC 5PC 5PC 5PC 5PCo1IENDB`PK{Lmeta.xmlMo0++# \i{jWڬ[Dl7u 6M5dU93gñwi28A  x`_ ǍU)Tjj*U#VYB4 M7ZxROUb<Q\zCqo55KK.D+?6K21lzM R8g54m/zZiܚf`?>X!kC W0tUd.מ`xyˆqBpHFht %)]I&$[pƊqR(V7~nq=UKk >H-XV=u,!Jw&eiv5{N"&"M xo> Ӿ$c/ePKRIPK{L settings.xmlZ[s6~aNŐ&s16 oR@,y%9 Y.Y*NiuYxYPgW)} =Gcqa}S.buSY:b|-m#zg/G1]'hkg퓋CB&Jw/VG_b1JpL!•L8m )cZzDc]z[(=Yr>Tc<9Dw0E{)>` GJE Oq ($H8$W`6R{_sha $3Ȧ.HG<,t4\y,j=:`"&>Uť-}uFJ_'lJP=Hy,`a&Ä Èc7Cqu u!?-2W2TE%jOzMFch2eOHt"jZ )oNvV\Y[-9Å3$Zl߱(tWI׽ 5~z532$9r4erDq/>qE&x5MjGFsƢ[Cbo+n $/+-/$< 1YE K5PO?}K uEPY1(,ҵO]L],4#m17愆$D*ڑ-'ʕ3SMtGKx.S !q|Ar#X-h= Tf1Bw{85ĩ#Ԛ$-L')%)-ǻITͧʙXa:;D5E.uCog &P̐UibJ"%q#FE@$thŊ̑%1 ؙ|JE8$:[3O$`9T2X*pG*$vb&Ңь$zGQk#>gŋsҟP"[u?r^괶3kr׶$Q`ubN{NZl&Hvj!.ĪGEHO[/sI䊰LbR!ɤ~w=kqVi8[Oe{1i)l&݄LU;e$[sd+־n9ʾ4 n»˜t{qO[3n)-օ\: z17pZXvo5 ;vg FZkA; ^ӾZAshF:a"1 A|2w+V~ PRR,PwD~RNi?PKA}#&PK{L content.xml][s~(m'Iz47ƛv%fy+IYvδ%=/DR"ɷ83kK9\輺#E&33$^|?^AzOULRҤh'YU{>[Yaq1)J,HhgYUIQEՙ0]r2tOf¼T@ՃtmA Ǚ[[VFa|,l>_ZS|1GYmke*˛kO-Ψf9)@K9!^Gb2n0{K73&,RESEy-kB%rë<,*+@a64ik*U&;3>s<,IΉ{;=7ZӸ4Cs |;(ŀWխp6啷$Dž0)J7 Sa4y@vnNLaqc,vA[e 0Zۈ.rs93p&MH֟̄贛1SaB|,ة9i PuE8Tی!r#v&V&x̵ DjLqD fgvZst~B+9iȇV?KuuT~7rzD_U-e+] x "(Lͻo,-~%W$i*//H@M,,=7n2ͧMlm\۾ U']&H݇YoVM-)%tr&tsK^;IrB{H&t9Z6hly]) Ǟi])P bCLWuwT-C)ܜRiV3$/CRHpD$M Hꊡ=W^ycJF mڞCMs"ykyI@FY&mH|4[5. ъ#A-3fB!O/rj鍪`1=z{ "xdkfGXӠE]YQGˁ('& 6e~=ATRB[,g|LK "|_4nτ6pw>8gacQS,HSAhO {a=2 ibf*ڞyx#RVv.X'\ x?e&uȆ(dp x$։c}'kʹ4?u'.o?nyNfWyRjvG0񡤒nw'vWVaX=C{1VY?B%BY)l+b-B7c݉9viƸQ[FuQyFuښC}G1N~xl=}#w={j)ʻN:xnPhNzG==(,j{,h DD5׫("TUrhV}dz|ݢ5dW.\.N\֑Kd&YC[+nu}Wg*Y]t^q&AFcE{ :Ie-BBCH?"BD8BXџ%BҞ%>y~>B3z~^18Dr\uN/-ש~o'~6jJw8kh5@(I.7͵]EtUvH!v=SH: Y7bȽ6¯tUVwꑲb\e#QԚBMk-)њzYMުvAI"7Τ rKȈWn=RT$K//H2cJj>4Ns`9+ъY&e `Ǥ@6C7%1hOk,.(]72evX]"+Ju#Z8j說DЭa`$0iG?ў?TlzD>^tπ/0dޱS? BQ%].B;w>o*t~j@U:7 Cȥ|V*}^ɧ|4 V?lw#xV\C6[YVΏ[O+lqEs[:-״z{@V:8 9:ܩ~T;38"3Xӷlu9'"q*/1PVmigA?k~ܬ3e 4;%a%]Qub؇-ju]WJ׮q +9$Ld(ɀ>*#-̶Ldb{f0nw4H+xIO"uD6O"[ =Jv}cm !琦`8CKčBRhx^!Ph`G,4mm~8B_{* 8k;6pճobxN$#v)?rgxG7*3CCG>ifW޽ RR*Z4"/ E^/8 H6ばX!Tq/;1o+jV_RQMaA][/LƆiEl]ILܤ@ ֑,4ƳR4p|L|vbFpv&tc$4烡G=S~gdd9<.Q2*KCR-J&I'+3!|k6ߍZ!v AOMLn=8! |iLc(IeKQ9 )H6oV*dZIFFe YIx"3r﷿H#!8hf1# Sa|F!/Go8~`R-+8菴_vk-dr_-B5\ۆ?\4Xr9H6d +7,?G_xJWח%{OYyo^xvv[*}q5WKvMs9ǹEV˽d}7Ƴ!%фC'z* GH-isx\Wp?fT6cpoܞ ~蟚)!,Ok {gR7+ݮ23Z5\T0TP]qzS/XD˷`DqVKaA#ђ)Kˊb*f@t52_K_y*aDѫWIt?^.n ]V++xdPz$vT4dT~`⹔bco3/ h^xCZ~XJB\GfRI#{ Y\EW`W) {N ܏$e pvNǰ5dmY6gùkMKؒViݞ1d65GL >18+)X_LivK9fR7Zh^( JbMm,\[1,Np:0~,'$j J ɣt<8}q24NNap2ξ@:+6/`oV)*EB{"u b|*QM ڋ>(*6C҂jMꖖ[3vdgDl؎uČYdF-ֶӸCObb'g׫) ѹ,u{ejkλ=رJXƐ%jWk@.8j;B臣aiHAâ-eŚ-RvZ]hq{ WMÿe[T6/fQͰ8<;<8:?2xu4MиO8tKhht!`?U7MZ>l7¿vc,^.QdhWAhN>8p8F9ABÁj6BSXjv4'?ьѲ__$ylP wkQ+!N_B$UU]i=_~u$&`\1m09`_=`gd3Q_ \43 ;l{Ɩk$P/7^$.>6)"a5< 4{VotGe^PU2Z*mۗA)†Ѻyswc1ب1zj.WJ,b~7m^R~VPK7# :PK{LConfigurations2/toolpanel/PK{LConfigurations2/menubar/PK{LConfigurations2/floater/PK{LConfigurations2/statusbar/PK{LConfigurations2/popupmenu/PK{LConfigurations2/images/Bitmaps/PK{LConfigurations2/progressbar/PK{LConfigurations2/toolbar/PK{L'Configurations2/accelerator/current.xmlPKPK{LMETA-INF/manifest.xmlTn0 UM;*Zlw`n8U H@ih%vld'YN$GA;,،OY\)~.ت,D]Cj$][1w2萣rRk+{~~ay+'ɝҮޟu4&m% &܏-TZtn`mV4qĊ_Nx L Raw lamp flat spectra Standardizemeta-data Group lamp on/off exposures Subtract background Linearity correction Initialize variance Add mask Trace slits Part-processed flatswith slit traces ADU → electrons Stack Lamp on – lamp off astropy-specreduce-05be828/docs/process/NIR_arcs.rst000066400000000000000000000005251510537250300224750ustar00rootroot00000000000000************************ Near-IR, multi-slit arcs ************************ .. figure:: NIR_MOS_arc.svg :alt: DR flowchart for MOS wavelength calibration. :height: 1200 :width: 600 :scale: 50 % Reduction of arc exposures using previously-determined flat traces. Steps in grey are optional or alternative processing steps. astropy-specreduce-05be828/docs/process/NIR_flats.rst000066400000000000000000000010631510537250300226540ustar00rootroot00000000000000************************* Near-IR, multi-slit flats ************************* .. figure:: NIR_MOS_trace.svg :alt: DR flowchart for MOS slit traces. :height: 1200 :width: 600 :scale: 50 % Tracing of lamp flat spectra. Steps in grey are optional or alternative processing steps. .. figure:: NIR_MOS_flat.svg :alt: DR flowchart for multi-slit lamp flat processing. :height: 1200 :width: 600 :scale: 50 % Reduction of lamp flat spectra to produce a normalized flat. Steps in grey are optional or alternative processing steps. astropy-specreduce-05be828/docs/process/NIR_science_data.rst000066400000000000000000000007231510537250300241470ustar00rootroot00000000000000******************************** Near-IR, multi-slit science data ******************************** This example is based on plans for reduction of near-infrared, multi-slit spectra with a single detector array. .. figure:: NIR_MOS_science.svg :alt: DR flowchart for MOS science data. :height: 1200 :width: 600 :scale: 50 % Reduction of science exposures using previously-processed calibrations. Steps in grey are alternative processing options. astropy-specreduce-05be828/docs/process/index.rst000066400000000000000000000014701510537250300221440ustar00rootroot00000000000000.. _specreduce-process: ************************************ Spectroscopic data reduction outline ************************************ Here are some examples of complete DR processes, to help guide development (including basic image reduction steps, provided by other packages). These are not a summary of functionality actually implemented in `specreduce `_ today. .. _specreduce-nir-mos: Near-IR, multi-slit spectroscopy ================================ This example, from Gemini, is based on plans for the reduction of near-infrared, multi-slit spectra (considering future use with optical data to a lesser extent). Some adjustments might be needed as the functionality takes form. .. toctree:: :maxdepth: 1 NIR_science_data NIR_flats NIR_arcs astropy-specreduce-05be828/docs/specphot_standards.rst000066400000000000000000000243171510537250300232540ustar00rootroot00000000000000.. _specphot_standards: Spectrophotometric Standards ============================ Introduction ------------ Instrument sensitivity as a function of wavelength is calibrated using observations of spectrophotometric standard stars. `specreduce `_ offers some convenience functions for accessing some databases of commonly used standard stars and loading the data into `~specutils.Spectrum1D` instances. Supported Databases ------------------- Probably the most well-curated database of spectrophotometric calibration data is the `CALSPEC `_ database at `MAST `_ (Ref.: `Bohlin, Gordon, & Tremblay 2014 `_). It also has the advantage of including data that extends well into both the UV and the IR. The `~specreduce.calibration_data.load_MAST_calspec` function provides a way to easily load CALSPEC data either directly from `MAST `_ (specifically, https://archive.stsci.edu/hlsps/reference-atlases/cdbs/calspec/) or from a previously downloaded local file. Here is an example of how to use it and of a CALSPEC standard that has both UV and IR coverage: .. plot:: :include-source: import matplotlib.pyplot as plt from specreduce.calibration_data import load_MAST_calspec spec = load_MAST_calspec("agk_81d266_stisnic_007.fits") fig, ax = plt.subplots() ax.step(spec.spectral_axis, spec.flux, where="mid") ax.set_yscale('log') ax.set_xlabel(f"Wavelength ({spec.spectral_axis.unit})") ax.set_ylabel(f"Flux ({spec.flux.unit})") ax.set_title("AGK+81 266") fig.show() The `specreduce_data `_ package provides several datasets of spectrophotometric standard spectra. The bulk of them are inherited from IRAF's `onedstds `_ datasets, but some more recently curated datasets from `ESO `_, the `Nearby Supernova Factory `_, and `Gemini `_ are included as well. The `~specreduce.calibration_data.load_onedstds` function is provided to load these data into `~specutils.Spectrum1D` instances. If `specreduce_data `_ is not installed, the data will be downloaded from the GitHub `repository `_. The available database names and their descriptions are listed here. Please refer to the `specreduce-data repository `_ for details on the specific data files that are available: - `bstdscal `_: Directory of the brighter KPNO IRS standards (i.e., those with HR numbers) at 29 bandpasses, data from various sources transformed to the Hayes and Latham system, unpublished. - `ctiocal `_: Directory containing fluxes for the southern tertiary standards as published by `Baldwin & Stone, 1984, MNRAS, 206, 241 `_ and `Stone and Baldwin, 1983, MNRAS, 204, 347 `_. - `ctionewcal `_: Directory containing fluxes at 50 Å steps in the blue range 3300-7550 Å for the tertiary standards of Baldwin and Stone derived from the revised calibration of `Hamuy et al., 1992, PASP, 104, 533 `_. This directory also contains the fluxes of the tertiaries in the red (6050-10000 Å) at 50 Å steps as will be published in PASP (Hamuy et al 1994). The combined fluxes are obtained by gray shifting the blue fluxes to match the red fluxes in the overlap region of 6500-7500 Å and averaging the red and blue fluxes in the overlap. The separate red and blue fluxes may be selected by following the star name with "red" or "blue"; i.e. CD 32 blue. - `iidscal `_: Directory of the KPNO IIDS standards at 29 bandpasses, data from various sources transformed to the Hayes and Latham system, unpublished. - `irscal `_: Directory of the KPNO IRS standards at 78 bandpasses, data from various sources transformed to the Hayes and Latham system, unpublished (note that in this directory the brighter standards have no values - the `bstdscal `_ directory must be used for these standards). - `oke1990 `_: Directory of spectrophotometric standards observed for use with the HST, Table VII, `Oke 1990, AJ, 99, 1621 `_ (no correction was applied). An arbitrary 1 Å bandpass is specified for these smoothed and interpolated flux "points". - `redcal `_: Directory of standard stars with flux data beyond 8370 Å. These stars are from the IRS or the IIDS directory but have data extending as far out into the red as the literature permits. Data from various sources. - `spechayescal `_: The KPNO spectrophotometric standards at the Hayes flux points, Table IV, Spectrophotometric Standards, `Massey et al., 1988, ApJ 328, p. 315 `_. - `spec16cal `_: Directory containing fluxes at 16 Å steps in the blue range 3300-7550 Å for the secondary standards, published in `Hamuy et al., 1992, PASP, 104, 533 `_. This directory also contains the fluxes of the secondaries in the red (6020-10300 Å) at 16 Å steps as will be published in PASP (`Hamuy et al 1994 `_). The combined fluxes are obtained by gray shifting the blue fluxes to match the red fluxes in the overlap region of 6500-7500 Å and averaging the blue and red fluxes in the overlap. The separate red and blue fluxes may be selected by following the star name with "red" or "blue"; i.e. HR 1544 blue. - `spec50cal `_: The KPNO spectrophotometric standards at 50 Å intervals. The data are from (1) Table V, Spectrophotometric Standards, `Massey et al., 1988, ApJ 328, p. 315 `_ and (2) Table 3, The Kitt Peak Spectrophotometric Standards: Extension to 1 micron, `Massey and Gronwall, 1990, ApJ 358, p. 344 `_. - `snfactory `_: Preferred standard stars from the LBL Nearby Supernova Factory project: https://ui.adsabs.harvard.edu/abs/2002SPIE.4836...61A/abstract Data compiled from https://snfactory.lbl.gov/snf/snf-specstars.html. See notes there for details and references. - `eso`_: Directories of spectrophotometric standards copied from ftp://ftp.eso.org/pub/stecf/standards/. See https://www.eso.org/sci/observing/tools/standards/spectra/stanlis.html for links, notes, and details. - `gemini `_: Directory of spectrophotometric standards used by Gemini. Originally copied from https://github.com/GeminiDRSoftware/DRAGONS/tree/master/geminidr/gemini/lookups/spectrophotometric_standards. Selecting Spectrophotometric Standard Stars ------------------------------------------- Many commonly used standard stars have spectra in multiple datasets, but the quality and systematics can differ. The `~specreduce.calibration_data.load_MAST_calspec` and `~specreduce.calibration_data.load_onedstds` functions can be useful tools for exploring and comparing spectra from the various databases. An example is shown here for `LTT 9491 `_ which has spectra available from MAST, ESO, and the Nearby Supernova factory: .. plot:: :include-source: import matplotlib.pyplot as plt from specreduce.calibration_data import load_MAST_calspec, load_onedstds s1 = load_MAST_calspec("ltt9491_002.fits") s2 = load_onedstds("snfactory", "LTT9491.dat") s3 = load_onedstds("eso", "ctiostan/ltt9491.dat") fig, ax = plt.subplots() ax.step(s1.spectral_axis, s1.flux, label="MAST", where="mid") ax.step(s2.spectral_axis, s2.flux, label="SNFactory", where="mid") ax.step(s3.spectral_axis, s3.flux, label="ESO", where="mid") ax.set_yscale('log') ax.set_xlabel(f"Wavelength ({s1.spectral_axis.unit})") ax.set_ylabel(f"Flux ({s1.flux.unit})") ax.set_title("LTT 9491") ax.legend() fig.show() The `MAST`_ data have the best UV coverage, but that's not useful from the ground and they only extend to 0.9 microns in the red in this case. The other data extend to 1.0 microns, but both spectra show systematics due to telluric absorption. The `SNFactory`_ data extend well past the atmospheric cutoff with no correction applied for atmospheric transmission. The `ESO`_ data, on the other hand, are not corrected for the telluric features in the near-IR while the `SNFactory`_ data are. Regions affected by such telluric systematics should be masked out before these spectra are used for calibration purposes. astropy-specreduce-05be828/docs/terms.rst000066400000000000000000000370511510537250300205150ustar00rootroot00000000000000 Terminology ----------- As part of a workshop at NOIRLab, 13-16 Nov 2024, the attendees extensively discussed terminology in an effort to generate a common understanding of, and the nuances in, many of the terms bandied about when discussing spectroscopy data and its reduction and analysis. The following is a living document that stemmed from that original discussion. .. note:: Below, relative terms that can have multiple meanings are highlighted in italics. 2D Spectrum/Image ================= - Image = 2D Image - Optical/IR, different for other wavelengths - Something that is not necessarily pure “raw” data, but data that exists prior to extraction - Refers to e.g. the 2D CCD images (optionally pre-processed) from which 1D spectra (flux vs. wavelength) are extracted .. KBW: I missed this discussion, so I don't know how we want to capture "Alt" definitions here... Seems a bit awkward. Alt Spectrum 2D =============== - Spectrum as a function of slit position? - Fiber dispersed - Lots of alt Spectra 2D - Multiple spectral orders? - Can get up to something like 5D for solar data: wavelength x space x space x time x polarization - Is there an IVOA definition that differs from both of the above? 1D Spectrum =========== - Flux versus spectral axis (wavelength/frequency). Could be calibrated but not necessarily. *Preprocessing* =============== - (As related to spectral reduction): Things like flat-fielding and bias subtraction that are done on a full CCD image before extractions are performed. - Alt term: instrument signature removal - Meaning of this depends on context (“What do others do before I start?”) - Typically done on raw/2d image - Work done before mine. *Post-processing* ================= - Typically done on the extracted spectra? Extraction ========== - The process of converting raw spectrum data on 2D image into flux versus spectral axis or pixel (i.e. Spectrum1D), not necessarily flux or spectral calibration. Rectified ND spectrum ===================== - Non-dispersion axes means something like ra/dec, or polarization? - Nearly always (maybe always?) Implies some amount of resampling - There is one dimension that is ENTIRELY a spectral axis, all others are not specified by calling it a “Rectified ND Spectrum”, although they often do have some kind of meaning Calibrated 2D image =================== - Not-resampled. - Calibrated from raw pixel to wavelength. .. KBW: Not really sure this is terminology, but I've left it as written in the workshop notes. Facilitating Data sharing, cross-matching, etc., standards via IVOA standards ============================================================================= - Data models (but see below) - COM - ObsCore - SSA - Not widely adopted, but could be! *Workflow* ========== - More holistic than a pipeline. Often a superset of pipeline with additional steps to facilitate data ingest, job orchestration, data collection/coordination, data archiving, etc. - Also analysis. *Pipeline* ========== - Organized code for **automatically** processing raw data into calibrated spectra and - Optionally derived quantities like redshifts, line fits, ... - More generically, the linking of several steps/jobs/codes/methods where outputs of one feed as inputs to another. - “Spectral reduction pipeline”? vs. “analysis pipeline” vs. “XYZ pipeline” - SDSS and JWST pipelines are different, Dragons has three pipelines. DESI has different pipelines depending on who you talk to. Classification ============== - Identifying the type of object a spectrum represents: star, galaxy, QSO, ... - Result of Model fitting (auto or by-eye). *Redshifting* ============= - Determining the redshift of a spectrum, which may or may not be independent of classification. - Sometimes also means “changing the redshift of the object to its redshift”, e.g. converting the “wavelength/frequency” axis to rest-frame - Related issues on GitHub: - `#258 `__ - `#455 `__ - `#820 `__ Heliocentric / barycentric correct ================================== - Converting a spectrum to some rest frame in order to measure a radial velocity for a nearby stellar source. - Heliocentric is “the frame where the sun is at rest” - Barycentric is “the frame where the barycenter of the solar system is at rest” - (Some of this is very very precisely defined at the GR level) *Archive* ========= - A physical or virtual location from which processed data can be accessed. This could include both PI/collaboration access and public access - Or unprocessed. - And metadata needed to reduce raw data. - Raw data bundle (science+all cals needed to reduce it) - Ideally would Supporting FAIR principles (Findable, Accessible, Interoperable, Reusable) - Noun or verb. Data Assembly ============= - A bundle of data prepared for collaboration access (to write papers, etc.) that will eventually become a data release. - Used internally by DESI, but deprecated. - It becomes the data release at the DR date - Sloan synonym: “Internal Product Launch” Data release ============ - A bundle of data specifically intended to be public - Can be raw or not raw - Somehow “pinned” data raw/reduced/analyzed with a particular version of pipelines. - Aspires to be frozen. - Can be either a noun or a verb Open Development ================ - Developing software in a way that the community can see both how it has been developed and why it was developed that way. - Usually, but not absolutely necessarily, implies the community is also free to contribute. - Not necessarily open source. - Repos are publicly visible, including issue tracker. Flux calibration ================ - Converting a 1D/2D spectrum from “counts” to astrophysical units of flux density *Telluric Correction* ===================== - Removing the telluric (atmospheric) absorption bands from spectra - Removing the *multiplicative* component of the sky - absorption - But there was some disagreement over whether this includes sky *Sky subtraction* ================= - Removing the *additive* component of the sky/emission so all “photons” come from the source - But there was some disagreement over whether this is overlapping with a Telluric correction IFU (Integral-Field Unit) ========================= - Covers a “contiguous” 2d field on the sky with spatial information along both axes - Fibers or similar are tightly bundled and contiguously cover a region on the sky. Or an image slicer. Or a microlens array. - May or may not be multi-object. - IFS (Integral field Spectrograph) and IFU are sometimes distinguished where IFS is the whole instrument but IFU is the head-unit that does the IF part MOS (Multi-Object Spectroscopy) =============================== - Could be a fiber or a slit - Multiple objects observed in the same exposure *Flux* ====== - Energy per time per area - Also used as a shorthand for “the not spectral unit part of a 1D spectrum” (would that be the “dependent variable”?) - Oftentimes used to mean “flux density” - `Spectrum1D `__ uses the attribute 'flux'. Should this be renamed to 'flux_density'? - The intent in specutils was to not agonize over this but just accept that it's a shorthand astronomers use, and there wasn't a better name (“y”, “data”, etc) Flux Density ============ - Flux per unit wavelength/energy/wavenumber, usually(?) in astrophysical units, e.g., W/m^2/nm *Row-stacked spectra* ===================== - Collection of 1D spectra in a 2D array (image?), one spectrum per row. - Shared spectral axis. - This is the format of specutils.Spectrum1D when it's a “vector” spectrum1D *Data cube* =========== - Spectral 3D matrix with 2 spatial dimensions and one spectral one. Product of IFU data with contiguous sky coverage - Doesn't even have to be spectral, although in the spectral context it usually is - Not always 3D (data hypercuboid??). - “Multi dimensional data blob” *Spectral data cube* ==================== - At least one axis is a spectral axis but who knows about the rest! - Hypercube. *[Spectral] Data format* ======================== - “Format” can mean data structure (i.e., in-memory, possibly bound to a particular language, though it doesn't have to be - see Apache Arrow) - “Format” can also mean a file format - “Format” can also be something even more technical like “how the bytes in a struct are packed“ Data Structures =============== - Python Data structures, which are Python classes. - NDData/NDCube/SpectrumCollection, Spectrum1D etc. - CCDData. Subclass of NDData - AstroData - from DRAGONS (collection of NDData-like objects, mapped to a file, plus metadata abstraction etc.) - Lots of classes to represent spectra - Link to issue about renaming Spectrum1D class in specutils. - arrays *Data Model* ============ - In the SDSS/DESI sphere, this has a meaning that is known to differ from other uses of the term. In SDSS/DESI this means a documentation product that describes all of the files in a data release, both file formats and how they are organized into a hierarchy of directories on disk. For example, see the `desidatamodel `__. - IVOA data model is a formalized thing that follows a specific XML schema - Data model is abstract, implementation could potentially be different. - In the IVOA it is not yet allowed to be anything other than XML although there's a lot of interest in changing that - Which is different from SQL data models - The word 'schema' is sometimes used here, but that is also ambiguous even within SQL flavors itself. *Spectroscopic search - Data discovery* ======================================= - Search for spectra from any/particular instrument based on position or other known properties of the sources. If available, all the spectra will be listed. - Example tool to do this: SPARCL (How-To Jupyter notebook available here) SSA = Simple Spectral Access [VO protocol] ========================================== - "Uniform interface to remotely discover and access one-dimensional spectra." See `here `__. - Not commonly (used in the US?). (Example of use Data Central) Reduction (of spectroscopic data) ================================= - Getting data from raw-off-the-instrument (or nearly so) to the point where analysis can be done. - The process of turning 2D spectral images to 1D spectra. Can be wavelength calibrated, sky subtracted, flux calibrated, but intermediate products are "reduced" compared to earlier steps of the process. - MAYBE: Can potentially be done automatically without a human-in-the-loop? - Required products vs optional products - Removing instrument signature. - "Reduction" is in the sense of reducing complexity, but it is often an inflation of bytes (in radio it is a literal reduction, in optical usually not) - Astronomy specific word. - Spectroscopic reduction: the process of going from raw data to science-ready spectra Analysis (of spectroscopic data) ================================ - Taking scientific measurements or achieving scientific results from already-reduced spectroscopic data - Analysis does not depend on the instrument.Rem - MAYBE: cannot be done automatically, requires a human to make some sort of judgment - Optional. - Spectroscopic analysis: the process of going from science-ready spectra to science Sky === - Model or observed sky background (really a foreground!) which was usually subtracted from the observed spectrum *Stacking* ========== - Combination of multiple spectra in a prescribed way to increase quality (e.g., S/N) - in some contexts like numpy arrays and astropy.table.vstack, it can refer to combining multiple objects / tables into a single object without coadding data. *Coadding* ========== - combining multiple spectra of the same object into a single spectrum, e.g. to improve signal-to-noise or combine spectra across multiple wavelength ranges. - Alternative term for “stacking” to disambiguate meanings Spectral fitting ================ - Modeling an observed spectrum with templates (possibly physically motivated) and/or mathematical functions Digital Twins ============= - Realistic fake data that potentially adapts to new states of the system over time. Trace fitting ============= - on a 2D CCD image from a multi-object spectrometer, typically wavelengths span in 1 direction and fibers/objects in the other direction. “trace fitting” is mapping the y vs. x of where the spectra actually go on the CCD image. - Different for slit-based and fiber-based spectrographs - slit-based: trace the *edges* of the slit spectrum along the spectral direction - fiber-based: trace the *center* of the fiber spectrum spatial point-spread function - Spectral tracing Wavelength calibration ====================== - calibrating what true wavelength is represented by the observed photons on a detector, e.g. what wavelength is row y of a detector? - Possibly a 2d process - The process of adding (the spectral part of) a WCS Visual Inspection (of spectra) ============================== - Humans looking at spectra and making decisions about what the “truth” is. - Can include identifying the presence/absence of features (qualitative) or assessing a quantitative fit (e.g., best-fit redshift value) *Spectral resolution* ===================== - Changes in spectral dispersion power as a function of wavelength due to instrument - Resolving power vs Resolution/Dispersion - Resolving power is the ability to distinguish close features - Dispersion is the change in wavelength/energy per pixel API === - Application Programming Interface - What makes a good API for spectroscopic software? - What is needed for different aspects of spectroscopic software (e.g., reduction vs. archive access)? *Spectral class* ================ - E.g., Spectrum1D - In SDSS, 'class' is short for 'classification'. - DESI uses SPECTYPE for spectral type (QSO, GALAXY, STAR) Package ======= - A software tool or collection of tools developed in the same “space” - Has a specific meaning in a Python context that’s more specific, but can be used more generally for multiple languages Spectral data visualization =========================== - Tools and procedures to display reduced spectral data Spectral decomposition ====================== - a form of spectral fitting that identifies separate components that appear in a spectrum; e.g, quasar + galaxy. - Goes with spectral fitting. Processing Steps ================ - For DESI (largely inherited from SDSS usage): - pre-processing (of CCD images, bias, dark, pixel-flat fielding) - extraction (getting counts vs. wavelength from 2D images) - sky subtraction (subtracting the additive non-signal sky component) - flux calibration (includes both instrument throughput and telluric absorption multiplicative corrections) - classification and redshift fitting (is it a galaxy, star, or quasar; at what redshift?) ---- Mentioned but not defined ------------------------- - WCS & Database archive - Cloud archiving - Modular functions which can be used by other pipelines. - Interactive Dashboard astropy-specreduce-05be828/docs/wavelength_calibration/000077500000000000000000000000001510537250300233365ustar00rootroot00000000000000astropy-specreduce-05be828/docs/wavelength_calibration/wavelength_calibration.rst000066400000000000000000000272471510537250300306170ustar00rootroot00000000000000.. _wavelength_calibration: Wavelength Calibration ====================== In spectroscopy, the raw data from a detector typically records the intensity of light at different pixel positions. For scientific analysis, we need to know the physical wavelength (or frequency, or energy) corresponding to each pixel. **Wavelength calibration** is the process of determining this mapping, creating a model that converts pixel coordinates to wavelength values. This is often achieved by observing a calibration source with well-known emission lines (e.g., an arc lamp). By identifying the pixel positions of these lines, we can fit a mathematical model describing the spectrograph’s dispersion. The ``specreduce`` library provides two complementary classes for 1D calibration: - :class:`~specreduce.wavecal1d.WavelengthCalibration1D`: a high-level calibration workflow to detect and match arc lines and fit a dispersion model. - `~specreduce.wavesol1d.WavelengthSolution1D`: a lightweight wavelength-solution container that holds the pixel→wavelength transform with its inverse, a WCS solution, and a method for flux-conserving resampling. Tools for calibrating 2D spectra will be added in later versions. 1D Wavelength Calibration ------------------------- The :class:`~specreduce.wavecal1d.WavelengthCalibration1D` class encapsulates the data and methods needed to compute a 1D wavelength solution, and the :class:`~specreduce.wavesol1d.WavelengthSolution1D` class provides the tools to use the computed solution. A typical workflow involves: 1. **Initialization**: Create an instance of the class with either arc spectra or pre-identified observed line positions, and provide one or more line lists of known wavelengths. Multiple arcs and multiple catalogs are supported. 2. **Line Detection (if using arc spectra)**: Identify line positions in the arc spectra. 3. **Fitting the Wavelength Solution**: Use either direct fitting with known pixel– wavelength pairs (:meth:`~specreduce.wavecal1d.WavelengthCalibration1D.fit_lines`) or automated global optimization (:meth:`~specreduce.wavecal1d.WavelengthCalibration1D.fit_dispersion`). 4. **Refinement and Inspection**: Optionally refine the solution and check fit quality using RMS statistics and plots. 5. **Applying the Solution**: Access the fitted solution as a :class:`~specreduce.wavesol1d.WavelengthSolution1D` to resample spectra, or attach the solution to a `specutils.Spectrum` as a `~gwcs.wcs.WCS` object. Quickstart ---------- 1. Initialization ***************** You instantiate the :class:`~specreduce.wavecal1d.WavelengthCalibration1D` by providing basic information about your setup and data. You must provide *either* a list of arc spectra (or a single arc spectrum) *or* a list of known observed line positions: * **Using an Arc Spectrum**: Provide the arc spectrum as a `specutils.Spectrum` object via the ``arc_spectra`` argument. You also need to provide a ``line_lists`` argument, which can be a list of known catalog wavelengths or the name(s) of standard line lists recognized by `specreduce` (e.g., ``"HeI"``). You can query the available line lists by using the `~specreduce.calibration_data.get_available_line_catalogs` function. .. code-block:: python wc = WavelengthCalibration1D(arc_spectra=arc_he, line_lists=["HeI"]) * **Using multiple Arc Spectra**: .. code-block:: python wc = WavelengthCalibration1D(arc_spectra=[arc_he, arc_hg_ar], line_lists=[["HeI"], ["HgI", "ArI"]]) * **Using Observed Line Positions**: If you have already identified the pixel centroids of lines in your calibration spectrum, you can provide them directly via the ``obs_lines`` argument (as a list of NumPy arrays). In this case, you *must* also provide the detector's pixel boundaries using ``pix_bounds`` (a tuple like ``(min_pixel, max_pixel)``) and a reference pixel, ``ref_pixel``, which serves as the anchor point for the polynomial fit. You also need to provide the ``line_lists`` containing the potential matching catalog wavelengths. .. code-block:: python obs_he = np.array([105.3, 210.8, 455.1, 512.5, 680.2]) pixel_bounds = (0, 1024) wc = WavelengthCalibration1D(ref_pixel=512, obs_lines=obs_he, line_lists=["HeI"], pix_bounds=pixel_bounds) * **Using Observed Line Positions From Multiple Arcs**: .. code-block:: python obs_he = np.array([105.3, 210.8, 455.1, 512.5, 680.2]) obs_hg_ar = np.array([234.2, 534.1, 768.2, 879.6]) pixel_bounds = (0, 1024) wc = WavelengthCalibration1D(ref_pixel=512, obs_lines=[obs_he, obs_hg_ar], line_lists=[["HeI"], ["HgI", "ArI"]], pix_bounds=pixel_bounds) 2. Finding Observed Lines ************************* If you initialized the class with ``arc_spectra``, you need to detect the lines in it. Use the :meth:`~specreduce.wavecal1d.WavelengthCalibration1D.find_lines` method: .. code-block:: python wc.find_lines(fwhm=3.5, noise_factor=5) This populates the `~specreduce.wavecal1d.WavelengthCalibration1D.observed_line_locations` attribute. .. code-block:: python print(wc.observed_line_locations) 3. Matching and Fitting the Solution ************************************ The core of the calibration process is fitting a model that maps pixels to wavelengths. * **Global Fitting for Automated Pipelines**: If you have `~specreduce.wavecal1d.WavelengthCalibration1D.observed_lines` (either found automatically or provided initially) and `~specreduce.wavecal1d.WavelengthCalibration1D.catalog_lines` (from ``line_lists``), but don't know the exact pixel-wavelength pairs, you can use :meth:`~specreduce.wavecal1d.WavelengthCalibration1D.fit_dispersion`. This method applies the `differential evolution optimization algorithm `_ to find the polynomial coefficients that minimize the distance between observed line positions (transformed to wavelength space) and the nearest catalog lines. The fit is anchored around the reference pixel (``ref_pixel``), which defines the centre of the polynomial model. If not explicitly set at initialization, it defaults to the middle of the detector when arc spectra are supplied. You must provide estimated bounds for both the wavelength and the dispersion (dλ/dx) at ``ref_pixel``. The polynomial degree is set with the ``degree`` argument. A higher degree can capture more complex dispersion behaviour but risks overfitting if too few calibration lines are available. The ``higher_order_limits`` argument optionally constrains the absolute values of the higher-order polynomial coefficients, reducing the risk of unrealistic solutions. The ``popsize`` argument controls the population size in the differential evolution search. Larger values generally improve robustness at the expense of longer computation times. .. code-block:: python ws = wc.fit_dispersion(wavelength_bounds=(7450, 7550), dispersion_bounds=(1.8, 2.2), higher_order_limits=[0.001, 1e-5], degree=4, popsize=30, refine_fit=True) The fitted `~specreduce.wavesol1d.WavelengthSolution1D` is returned by the method and also stored in ``WavelengthCalibration1D.solution``. Setting ``refine_fit=True`` automatically performs a least-squares refinement after the global fit finds an initial solution and matches lines. * **Fitting Known Pairs for an Interactive Workflow**: If you have already established explicit pairs of observed pixel centers and their corresponding known wavelengths, you can use :meth:`~specreduce.wavecal1d.WavelengthCalibration1D.fit_lines` to perform a direct least-squares fit. .. code-block:: python ws = wc.fit_lines(pixels=[105.3, 512.5, 780.1], wavelengths=[6965.43, 7503.87, 7723.76], degree=2, refine_fit=True) When ``refine_fit=True`` is set, the method automatically identifies matching pairs between observed and catalog lines, then performs a least-squares refinement using **all matching lines**. This goes beyond the subset of lines provided to :meth:`~specreduce.wavecal1d.WavelengthCalibration1D.fit_lines`, resulting in an improved wavelength solution. 4. Inspecting the Fit ********************* Several tools help assess the quality of the wavelength solution: * **RMS Error**: Calculate the root-mean-square error of the fit in wavelength or pixel units using :meth:`~specreduce.wavecal1d.WavelengthCalibration1D.rms`. .. code-block:: python rms_wave = wc.rms(space='wavelength') rms_pix = wc.rms(space='pixel') print(f"Fit RMS (wavelength): {rms_wave}") print(f"Fit RMS (pixel): {rms_pix}") * **Plotting**: Visualize the fit and residuals: * :meth:`~specreduce.wavecal1d.WavelengthCalibration1D.plot_fit`: Shows the observed line positions mapped to the wavelength axis, overlaid with the catalog lines and the fitted solution. Also shows the fit residuals (observed - fitted wavelength) vs. pixel. * :meth:`~specreduce.wavecal1d.WavelengthCalibration1D.plot_residuals`: Plots residuals vs. pixel or vs. wavelength. * :meth:`~specreduce.wavecal1d.WavelengthCalibration1D.plot_observed_lines`: Plots the identified observed line positions (in pixels or mapped to wavelengths). Can optionally overlay the arc spectrum. * :meth:`~specreduce.wavecal1d.WavelengthCalibration1D.plot_catalog_lines`: Plots the catalog line positions (in wavelengths or mapped to pixels). 5. Using the Wavelength Solution ******************************** The fitted wavelength solution is stored as a :class:`~specreduce.wavesol1d.WavelengthSolution1D` instance that you can use to transform and resample spectra. The fitting methods return the solution, but it is also stored in ``WavelengthCalibration1D.solution``. * **Convert Coordinates**: Use :meth:`~specreduce.wavesol1d.WavelengthSolution1D.pix_to_wav` and :meth:`~specreduce.wavesol1d.WavelengthSolution1D.wav_to_pix` to convert between pixel and wavelength coordinates. .. code-block:: python pixels = np.array([100, 500, 900]) wavelengths = ws.pix_to_wav(pixels) print(wavelengths) * **Get WCS Object**: Access the `~gwcs.wcs.WCS` object representing the solution via the :attr:`~specreduce.wavesol1d.WavelengthSolution1D.gwcs` attribute. This is particularly useful for attaching the calibration to a :class:`~specutils.Spectrum` object. * **Rebin Spectrum**: Resample a spectrum onto a new wavelength grid using :meth:`~specreduce.wavesol1d.WavelengthSolution1D.resample`. The rebinning is flux-conserving, meaning the integrated flux in the output spectrum matches the integrated flux in the input spectrum. .. code-block:: python resampled_arc = ws.resample(arc_spectrum, nbins=1000) print(resampled_arc.spectral_axis) By default, :meth:`~specreduce.wavesol1d.WavelengthSolution1D.resample` produces a spectrum on a linear wavelength grid. Alternatively, you can pass an arbitrary 1D array of wavelength bin edges via ``bin_edges`` to define a custom grid. .. code-block:: python resampled_arc = ws.resample(arc_spectrum, bin_edges=np.geomspace(4500, 7500, 1000)) print(resampled_arc.spectral_axis)astropy-specreduce-05be828/environment-dev.yml000066400000000000000000000003131510537250300215330ustar00rootroot00000000000000name: specreduce-dev channels: - conda-forge dependencies: - astropy - gwcs - numpy - scipy - specutils - matplotlib - pytest-astropy - photutils - tox - sphinx-astropy - synphot astropy-specreduce-05be828/licenses/000077500000000000000000000000001510537250300175005ustar00rootroot00000000000000astropy-specreduce-05be828/licenses/KOSMOS_LICENSE000066400000000000000000000021771510537250300216070ustar00rootroot00000000000000# NOTE: This license applies only to code used in part of the FitTrace class. MIT License Copyright (c) 2019 James Davenport Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. astropy-specreduce-05be828/licenses/LICENSE.rst000066400000000000000000000027351510537250300213230ustar00rootroot00000000000000Copyright (c) 2017, Astropy-specreduce Developers All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Astropy Team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. astropy-specreduce-05be828/notebook_sandbox/000077500000000000000000000000001510537250300212315ustar00rootroot00000000000000astropy-specreduce-05be828/notebook_sandbox/README.md000066400000000000000000000002651510537250300225130ustar00rootroot00000000000000# specreduce Notebook Sandbox This directory is for specreduce-related notebooks that are not integrated into the documentation, but are still useful as examples of functionality. astropy-specreduce-05be828/notebook_sandbox/apo05.ipynb000066400000000000000000313141341510537250300232320ustar00rootroot00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Full Reduction Workflow\n", "This is a demonstration of a full (basic) reduction with the `specreduce` tools I have developed. This essentially puts all the other demo notebooks together, and is the outline for a reduction pipeline.\n", "\n", "As with the PyDIS example, the data is the \"apo05\" M dwarf example from DIS." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "%matplotlib notebook\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "from astropy.table import Table\n", "from astropy import units as u\n", "\n", "from astropy.nddata import CCDData, StdDevUncertainty\n", "from specreduce.compat import Spectrum as Spectrum1D\n", "from ccdproc import trim_image, Combiner\n", "\n", "# need to get import to work in notebook w/o global package install\n", "import sys \n", "sys.path.append('..')\n", "import identify as iden\n", "import apextract as ap\n", "import fluxcal as fc\n", "import flatfield as ft" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. Bias and Flat" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "dir = '../../pydis_example/'\n", "\n", "# a very IRAF-y way to store the list of files, but it works...\n", "biasfiles = Table.read(dir+'biaslist.txt', format='ascii.no_header', names=['impath'])\n", "flatfiles = Table.read(dir+'flatlist.txt', format='ascii.no_header', names=['impath'])" ] }, { "cell_type": "code", "execution_count": 198, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING: FITSFixedWarning: RADECSYS= 'Mount' / Coordinate system, per TCC ObjSys \n", "the RADECSYS keyword is deprecated, use RADESYSa. [astropy.wcs.wcs]\n", "WARNING:astropy:FITSFixedWarning: RADECSYS= 'Mount' / Coordinate system, per TCC ObjSys \n", "the RADECSYS keyword is deprecated, use RADESYSa.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "(1078, 2098)\n" ] } ], "source": [ "Blist = []\n", "\n", "for k in range(len(flatfiles)):\n", " img = CCDData.read(dir + biasfiles['impath'][k], unit=u.adu)\n", "\n", " Blist.append(img)\n", "\n", "BIAS = Combiner(Blist).median_combine()\n", "print(BIAS.shape)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**ISSUE:** This could probably be done with `ccdproc` directly?" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support. ' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " if (mpl.ratio != 1) {\n", " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " fig.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\n", " titlebar.append(titletext)\n", " this.root.append(titlebar);\n", " this.header = titletext[0];\n", "}\n", "\n", "\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "\n", "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "mpl.figure.prototype._init_canvas = function() {\n", " var fig = this;\n", "\n", " var canvas_div = $('
');\n", "\n", " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", "\n", " function canvas_keyboard_event(event) {\n", " return fig.key_event(event, event['data']);\n", " }\n", "\n", " canvas_div.keydown('key_press', canvas_keyboard_event);\n", " canvas_div.keyup('key_release', canvas_keyboard_event);\n", " this.canvas_div = canvas_div\n", " this._canvas_extra_style(canvas_div)\n", " this.root.append(canvas_div);\n", "\n", " var canvas = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var backingStore = this.context.backingStorePixelRatio ||\n", "\tthis.context.webkitBackingStorePixelRatio ||\n", "\tthis.context.mozBackingStorePixelRatio ||\n", "\tthis.context.msBackingStorePixelRatio ||\n", "\tthis.context.oBackingStorePixelRatio ||\n", "\tthis.context.backingStorePixelRatio || 1;\n", "\n", " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width * mpl.ratio);\n", " canvas.attr('height', height * mpl.ratio);\n", " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
');\n", " nav_element.attr('style', 'width: 100%');\n", " this.root.append(nav_element);\n", "\n", " // Define a callback function for later on.\n", " function toolbar_event(event) {\n", " return fig.toolbar_button_onclick(event['data']);\n", " }\n", " function toolbar_mouse_event(event) {\n", " return fig.toolbar_button_onmouseover(event['data']);\n", " }\n", "\n", " for(var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " // put a spacer in here.\n", " continue;\n", " }\n", " var button = $('');\n", " button.click(method_name, toolbar_event);\n", " button.mouseover(tooltip, toolbar_mouse_event);\n", " nav_element.append(button);\n", " }\n", "\n", " // Add the status bar.\n", " var status_bar = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('
');\n", " var button = $('');\n", " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", " buttongrp.append(button);\n", " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", " titlebar.prepend(buttongrp);\n", "}\n", "\n", "mpl.figure.prototype._root_extra_style = function(el){\n", " var fig = this\n", " el.on(\"remove\", function(){\n", "\tfig.close_ws(fig, {});\n", " });\n", "}\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(el){\n", " // this is important to make the div 'focusable\n", " el.attr('tabindex', 0)\n", " // reach out to IPython and tell the keyboard manager to turn it's self\n", " // off when our div gets focus\n", "\n", " // location in version 3\n", " if (IPython.notebook.keyboard_manager) {\n", " IPython.notebook.keyboard_manager.register_events(el);\n", " }\n", " else {\n", " // location in version 2\n", " IPython.keyboard_manager.register_events(el);\n", " }\n", "\n", "}\n", "\n", "mpl.figure.prototype._key_event_extra = function(event, name) {\n", " var manager = IPython.notebook.keyboard_manager;\n", " if (!manager)\n", " manager = IPython.keyboard_manager;\n", "\n", " // Check for shift+enter\n", " if (event.shiftKey && event.which == 13) {\n", " this.canvas_div.blur();\n", " // select the cell after this one\n", " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", " IPython.notebook.select(index + 1);\n", " }\n", "}\n", "\n", "mpl.figure.prototype.handle_save = function(fig, msg) {\n", " fig.ondownload(fig, null);\n", "}\n", "\n", "\n", "mpl.find_output_cell = function(html_output) {\n", " // Return the cell and output element which can be found *uniquely* in the notebook.\n", " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", " // IPython event is triggered only after the cells have been serialised, which for\n", " // our purposes (turning an active figure into a static one), is too late.\n", " var cells = IPython.notebook.get_cells();\n", " var ncells = cells.length;\n", " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", " data = data.data;\n", " }\n", " if (data['text/html'] == html_output) {\n", " return [cell, data, j];\n", " }\n", " }\n", " }\n", " }\n", "}\n", "\n", "// Register the function which deals with the matplotlib target/channel.\n", "// The kernel may be null if the page has been refreshed.\n", "if (IPython.notebook.kernel != null) {\n", " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", "}\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.figure(figsize=(6,3))\n", "plt.imshow(medflat, origin='lower', aspect='auto', cmap=plt.cm.inferno)\n", "plt.clim(np.percentile(medflat, (5, 98)))\n", "cb = plt.colorbar()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we get to the `specreduce` part: normalize out the spectral response, found by averaging the spatial dimension together, and dividing out" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [], "source": [ "ilum = ft.find_illum(medflat)\n", "\n", "FLAT = ft.flat_response(medflat[ilum, :], smooth=False)" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support. ' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " if (mpl.ratio != 1) {\n", " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " fig.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\n", " titlebar.append(titletext)\n", " this.root.append(titlebar);\n", " this.header = titletext[0];\n", "}\n", "\n", "\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "\n", "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "mpl.figure.prototype._init_canvas = function() {\n", " var fig = this;\n", "\n", " var canvas_div = $('
');\n", "\n", " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", "\n", " function canvas_keyboard_event(event) {\n", " return fig.key_event(event, event['data']);\n", " }\n", "\n", " canvas_div.keydown('key_press', canvas_keyboard_event);\n", " canvas_div.keyup('key_release', canvas_keyboard_event);\n", " this.canvas_div = canvas_div\n", " this._canvas_extra_style(canvas_div)\n", " this.root.append(canvas_div);\n", "\n", " var canvas = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var backingStore = this.context.backingStorePixelRatio ||\n", "\tthis.context.webkitBackingStorePixelRatio ||\n", "\tthis.context.mozBackingStorePixelRatio ||\n", "\tthis.context.msBackingStorePixelRatio ||\n", "\tthis.context.oBackingStorePixelRatio ||\n", "\tthis.context.backingStorePixelRatio || 1;\n", "\n", " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width * mpl.ratio);\n", " canvas.attr('height', height * mpl.ratio);\n", " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
');\n", " nav_element.attr('style', 'width: 100%');\n", " this.root.append(nav_element);\n", "\n", " // Define a callback function for later on.\n", " function toolbar_event(event) {\n", " return fig.toolbar_button_onclick(event['data']);\n", " }\n", " function toolbar_mouse_event(event) {\n", " return fig.toolbar_button_onmouseover(event['data']);\n", " }\n", "\n", " for(var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " // put a spacer in here.\n", " continue;\n", " }\n", " var button = $('');\n", " button.click(method_name, toolbar_event);\n", " button.mouseover(tooltip, toolbar_mouse_event);\n", " nav_element.append(button);\n", " }\n", "\n", " // Add the status bar.\n", " var status_bar = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('
');\n", " var button = $('');\n", " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", " buttongrp.append(button);\n", " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", " titlebar.prepend(buttongrp);\n", "}\n", "\n", "mpl.figure.prototype._root_extra_style = function(el){\n", " var fig = this\n", " el.on(\"remove\", function(){\n", "\tfig.close_ws(fig, {});\n", " });\n", "}\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(el){\n", " // this is important to make the div 'focusable\n", " el.attr('tabindex', 0)\n", " // reach out to IPython and tell the keyboard manager to turn it's self\n", " // off when our div gets focus\n", "\n", " // location in version 3\n", " if (IPython.notebook.keyboard_manager) {\n", " IPython.notebook.keyboard_manager.register_events(el);\n", " }\n", " else {\n", " // location in version 2\n", " IPython.keyboard_manager.register_events(el);\n", " }\n", "\n", "}\n", "\n", "mpl.figure.prototype._key_event_extra = function(event, name) {\n", " var manager = IPython.notebook.keyboard_manager;\n", " if (!manager)\n", " manager = IPython.keyboard_manager;\n", "\n", " // Check for shift+enter\n", " if (event.shiftKey && event.which == 13) {\n", " this.canvas_div.blur();\n", " // select the cell after this one\n", " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", " IPython.notebook.select(index + 1);\n", " }\n", "}\n", "\n", "mpl.figure.prototype.handle_save = function(fig, msg) {\n", " fig.ondownload(fig, null);\n", "}\n", "\n", "\n", "mpl.find_output_cell = function(html_output) {\n", " // Return the cell and output element which can be found *uniquely* in the notebook.\n", " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", " // IPython event is triggered only after the cells have been serialised, which for\n", " // our purposes (turning an active figure into a static one), is too late.\n", " var cells = IPython.notebook.get_cells();\n", " var ncells = cells.length;\n", " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", " data = data.data;\n", " }\n", " if (data['text/html'] == html_output) {\n", " return [cell, data, j];\n", " }\n", " }\n", " }\n", " }\n", "}\n", "\n", "// Register the function which deals with the matplotlib target/channel.\n", "// The kernel may be null if the page has been refreshed.\n", "if (IPython.notebook.kernel != null) {\n", " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", "}\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.figure(figsize=(6,3))\n", "plt.imshow(sciimg, origin='lower', aspect='auto')\n", "plt.clim(np.percentile(sciimg, (5, 98)))" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/james/opt/anaconda3/lib/python3.7/site-packages/numpy/core/fromnumeric.py:746: UserWarning: Warning: 'partition' will ignore the 'mask' of the MaskedArray.\n", " a.partition(kth, axis=axis, kind=kind, order=order)\n" ] }, { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support. ' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " if (mpl.ratio != 1) {\n", " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " fig.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\n", " titlebar.append(titletext)\n", " this.root.append(titlebar);\n", " this.header = titletext[0];\n", "}\n", "\n", "\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "\n", "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "mpl.figure.prototype._init_canvas = function() {\n", " var fig = this;\n", "\n", " var canvas_div = $('
');\n", "\n", " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", "\n", " function canvas_keyboard_event(event) {\n", " return fig.key_event(event, event['data']);\n", " }\n", "\n", " canvas_div.keydown('key_press', canvas_keyboard_event);\n", " canvas_div.keyup('key_release', canvas_keyboard_event);\n", " this.canvas_div = canvas_div\n", " this._canvas_extra_style(canvas_div)\n", " this.root.append(canvas_div);\n", "\n", " var canvas = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var backingStore = this.context.backingStorePixelRatio ||\n", "\tthis.context.webkitBackingStorePixelRatio ||\n", "\tthis.context.mozBackingStorePixelRatio ||\n", "\tthis.context.msBackingStorePixelRatio ||\n", "\tthis.context.oBackingStorePixelRatio ||\n", "\tthis.context.backingStorePixelRatio || 1;\n", "\n", " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width * mpl.ratio);\n", " canvas.attr('height', height * mpl.ratio);\n", " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
');\n", " nav_element.attr('style', 'width: 100%');\n", " this.root.append(nav_element);\n", "\n", " // Define a callback function for later on.\n", " function toolbar_event(event) {\n", " return fig.toolbar_button_onclick(event['data']);\n", " }\n", " function toolbar_mouse_event(event) {\n", " return fig.toolbar_button_onmouseover(event['data']);\n", " }\n", "\n", " for(var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " // put a spacer in here.\n", " continue;\n", " }\n", " var button = $('');\n", " button.click(method_name, toolbar_event);\n", " button.mouseover(tooltip, toolbar_mouse_event);\n", " nav_element.append(button);\n", " }\n", "\n", " // Add the status bar.\n", " var status_bar = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('
');\n", " var button = $('');\n", " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", " buttongrp.append(button);\n", " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", " titlebar.prepend(buttongrp);\n", "}\n", "\n", "mpl.figure.prototype._root_extra_style = function(el){\n", " var fig = this\n", " el.on(\"remove\", function(){\n", "\tfig.close_ws(fig, {});\n", " });\n", "}\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(el){\n", " // this is important to make the div 'focusable\n", " el.attr('tabindex', 0)\n", " // reach out to IPython and tell the keyboard manager to turn it's self\n", " // off when our div gets focus\n", "\n", " // location in version 3\n", " if (IPython.notebook.keyboard_manager) {\n", " IPython.notebook.keyboard_manager.register_events(el);\n", " }\n", " else {\n", " // location in version 2\n", " IPython.keyboard_manager.register_events(el);\n", " }\n", "\n", "}\n", "\n", "mpl.figure.prototype._key_event_extra = function(event, name) {\n", " var manager = IPython.notebook.keyboard_manager;\n", " if (!manager)\n", " manager = IPython.keyboard_manager;\n", "\n", " // Check for shift+enter\n", " if (event.shiftKey && event.which == 13) {\n", " this.canvas_div.blur();\n", " // select the cell after this one\n", " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", " IPython.notebook.select(index + 1);\n", " }\n", "}\n", "\n", "mpl.figure.prototype.handle_save = function(fig, msg) {\n", " fig.ondownload(fig, null);\n", "}\n", "\n", "\n", "mpl.find_output_cell = function(html_output) {\n", " // Return the cell and output element which can be found *uniquely* in the notebook.\n", " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", " // IPython event is triggered only after the cells have been serialised, which for\n", " // our purposes (turning an active figure into a static one), is too late.\n", " var cells = IPython.notebook.get_cells();\n", " var ncells = cells.length;\n", " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", " data = data.data;\n", " }\n", " if (data['text/html'] == html_output) {\n", " return [cell, data, j];\n", " }\n", " }\n", " }\n", " }\n", "}\n", "\n", "// Register the function which deals with the matplotlib target/channel.\n", "// The kernel may be null if the page has been refreshed.\n", "if (IPython.notebook.kernel != null) {\n", " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", "}\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Extraction of the spectrum along the trace for both the Science and Flux Cal images\n", "sci_ex = ap.extract(sciimg, sci_tr, display=True, apwidth=10, skysep=5, skywidth=5)\n", "cal_ex = ap.extract(calimg, cal_tr, display=False, apwidth=10, skysep=5, skywidth=5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. Wavelength Calibration" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [], "source": [ "lamp = '../../pydis_example/apo05/05may31.0035r.fits' # HeNeAr lamp\n", "\n", "arcimg = CCDData.read(lamp, unit=u.adu)\n", "# put in units of ADU/s\n", "arcimg.data = arcimg.data / (arcimg.header['EXPTIME'])\n", "arcimg.unit = arcimg.unit / u.s\n", "\n", "# trim off bias section\n", "arcimg = trim_image(arcimg, fits_section=arcimg.header['DATASEC'])" ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [], "source": [ "# this data comes from the APO DIS red channel, which has wavelength axis backwards\n", "# (despite not mentioning in the header)\n", "wapprox = (np.arange(sciimg.shape[1]) - sciimg.shape[1]/2)[::-1] * sciimg.header['DISPDW'] + sciimg.header['DISPWC']\n", "\n", "wapprox = wapprox * u.angstrom" ] }, { "cell_type": "code", "execution_count": 81, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "../apextract.py:287: RuntimeWarning: invalid value encountered in sqrt\n", " (N_A + N_A**2. / N_B) * (sigB**2.))\n" ] } ], "source": [ "# now we need to extract the trace from the Arc lamp image to get proper wavelength calibration\n", "arc_sci_ex = ap.extract(arcimg, sci_tr, display=False, apwidth=10, skysep=5, skywidth=5)\n", "arc_cal_ex = ap.extract(arcimg, cal_tr, display=False, apwidth=10, skysep=5, skywidth=5)" ] }, { "cell_type": "code", "execution_count": 84, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support. ' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " if (mpl.ratio != 1) {\n", " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " fig.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\n", " titlebar.append(titletext)\n", " this.root.append(titlebar);\n", " this.header = titletext[0];\n", "}\n", "\n", "\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "\n", "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "mpl.figure.prototype._init_canvas = function() {\n", " var fig = this;\n", "\n", " var canvas_div = $('
');\n", "\n", " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", "\n", " function canvas_keyboard_event(event) {\n", " return fig.key_event(event, event['data']);\n", " }\n", "\n", " canvas_div.keydown('key_press', canvas_keyboard_event);\n", " canvas_div.keyup('key_release', canvas_keyboard_event);\n", " this.canvas_div = canvas_div\n", " this._canvas_extra_style(canvas_div)\n", " this.root.append(canvas_div);\n", "\n", " var canvas = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var backingStore = this.context.backingStorePixelRatio ||\n", "\tthis.context.webkitBackingStorePixelRatio ||\n", "\tthis.context.mozBackingStorePixelRatio ||\n", "\tthis.context.msBackingStorePixelRatio ||\n", "\tthis.context.oBackingStorePixelRatio ||\n", "\tthis.context.backingStorePixelRatio || 1;\n", "\n", " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width * mpl.ratio);\n", " canvas.attr('height', height * mpl.ratio);\n", " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
');\n", " nav_element.attr('style', 'width: 100%');\n", " this.root.append(nav_element);\n", "\n", " // Define a callback function for later on.\n", " function toolbar_event(event) {\n", " return fig.toolbar_button_onclick(event['data']);\n", " }\n", " function toolbar_mouse_event(event) {\n", " return fig.toolbar_button_onmouseover(event['data']);\n", " }\n", "\n", " for(var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " // put a spacer in here.\n", " continue;\n", " }\n", " var button = $('');\n", " button.click(method_name, toolbar_event);\n", " button.mouseover(tooltip, toolbar_mouse_event);\n", " nav_element.append(button);\n", " }\n", "\n", " // Add the status bar.\n", " var status_bar = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('
');\n", " var button = $('');\n", " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", " buttongrp.append(button);\n", " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", " titlebar.prepend(buttongrp);\n", "}\n", "\n", "mpl.figure.prototype._root_extra_style = function(el){\n", " var fig = this\n", " el.on(\"remove\", function(){\n", "\tfig.close_ws(fig, {});\n", " });\n", "}\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(el){\n", " // this is important to make the div 'focusable\n", " el.attr('tabindex', 0)\n", " // reach out to IPython and tell the keyboard manager to turn it's self\n", " // off when our div gets focus\n", "\n", " // location in version 3\n", " if (IPython.notebook.keyboard_manager) {\n", " IPython.notebook.keyboard_manager.register_events(el);\n", " }\n", " else {\n", " // location in version 2\n", " IPython.keyboard_manager.register_events(el);\n", " }\n", "\n", "}\n", "\n", "mpl.figure.prototype._key_event_extra = function(event, name) {\n", " var manager = IPython.notebook.keyboard_manager;\n", " if (!manager)\n", " manager = IPython.keyboard_manager;\n", "\n", " // Check for shift+enter\n", " if (event.shiftKey && event.which == 13) {\n", " this.canvas_div.blur();\n", " // select the cell after this one\n", " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", " IPython.notebook.select(index + 1);\n", " }\n", "}\n", "\n", "mpl.figure.prototype.handle_save = function(fig, msg) {\n", " fig.ondownload(fig, null);\n", "}\n", "\n", "\n", "mpl.find_output_cell = function(html_output) {\n", " // Return the cell and output element which can be found *uniquely* in the notebook.\n", " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", " // IPython event is triggered only after the cells have been serialised, which for\n", " // our purposes (turning an active figure into a static one), is too late.\n", " var cells = IPython.notebook.get_cells();\n", " var ncells = cells.length;\n", " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", " data = data.data;\n", " }\n", " if (data['text/html'] == html_output) {\n", " return [cell, data, j];\n", " }\n", " }\n", " }\n", " }\n", "}\n", "\n", "// Register the function which deals with the matplotlib target/channel.\n", "// The kernel may be null if the page has been refreshed.\n", "if (IPython.notebook.kernel != null) {\n", " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", "}\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.plot(final_spectrum.wavelength, final_spectrum.flux, c='K')\n", "\n", "# having to convert the Spectrum1D parameters like this is annoying\n", "# and also inconsistent behavior with the uncertainty\n", "plt.errorbar(final_spectrum.wavelength.value, final_spectrum.flux.value, \n", " yerr=final_spectrum.uncertainty.array, alpha=0.2, c='C5')\n", "\n", "plt.xlabel('Wavelength ['+str(final_spectrum.wavelength.unit)+']')\n", "plt.ylabel('Flux ['+str(final_spectrum.flux.unit)+']')\n", "plt.title('Gl 669A – workflow example reduction');" ] }, { "cell_type": "code", "execution_count": 152, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support. ' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " if (mpl.ratio != 1) {\n", " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " fig.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\n", " titlebar.append(titletext)\n", " this.root.append(titlebar);\n", " this.header = titletext[0];\n", "}\n", "\n", "\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "\n", "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "mpl.figure.prototype._init_canvas = function() {\n", " var fig = this;\n", "\n", " var canvas_div = $('
');\n", "\n", " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", "\n", " function canvas_keyboard_event(event) {\n", " return fig.key_event(event, event['data']);\n", " }\n", "\n", " canvas_div.keydown('key_press', canvas_keyboard_event);\n", " canvas_div.keyup('key_release', canvas_keyboard_event);\n", " this.canvas_div = canvas_div\n", " this._canvas_extra_style(canvas_div)\n", " this.root.append(canvas_div);\n", "\n", " var canvas = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var backingStore = this.context.backingStorePixelRatio ||\n", "\tthis.context.webkitBackingStorePixelRatio ||\n", "\tthis.context.mozBackingStorePixelRatio ||\n", "\tthis.context.msBackingStorePixelRatio ||\n", "\tthis.context.oBackingStorePixelRatio ||\n", "\tthis.context.backingStorePixelRatio || 1;\n", "\n", " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width * mpl.ratio);\n", " canvas.attr('height', height * mpl.ratio);\n", " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
');\n", " nav_element.attr('style', 'width: 100%');\n", " this.root.append(nav_element);\n", "\n", " // Define a callback function for later on.\n", " function toolbar_event(event) {\n", " return fig.toolbar_button_onclick(event['data']);\n", " }\n", " function toolbar_mouse_event(event) {\n", " return fig.toolbar_button_onmouseover(event['data']);\n", " }\n", "\n", " for(var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " // put a spacer in here.\n", " continue;\n", " }\n", " var button = $('');\n", " button.click(method_name, toolbar_event);\n", " button.mouseover(tooltip, toolbar_mouse_event);\n", " nav_element.append(button);\n", " }\n", "\n", " // Add the status bar.\n", " var status_bar = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('
');\n", " var button = $('');\n", " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", " buttongrp.append(button);\n", " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", " titlebar.prepend(buttongrp);\n", "}\n", "\n", "mpl.figure.prototype._root_extra_style = function(el){\n", " var fig = this\n", " el.on(\"remove\", function(){\n", "\tfig.close_ws(fig, {});\n", " });\n", "}\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(el){\n", " // this is important to make the div 'focusable\n", " el.attr('tabindex', 0)\n", " // reach out to IPython and tell the keyboard manager to turn it's self\n", " // off when our div gets focus\n", "\n", " // location in version 3\n", " if (IPython.notebook.keyboard_manager) {\n", " IPython.notebook.keyboard_manager.register_events(el);\n", " }\n", " else {\n", " // location in version 2\n", " IPython.keyboard_manager.register_events(el);\n", " }\n", "\n", "}\n", "\n", "mpl.figure.prototype._key_event_extra = function(event, name) {\n", " var manager = IPython.notebook.keyboard_manager;\n", " if (!manager)\n", " manager = IPython.keyboard_manager;\n", "\n", " // Check for shift+enter\n", " if (event.shiftKey && event.which == 13) {\n", " this.canvas_div.blur();\n", " // select the cell after this one\n", " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", " IPython.notebook.select(index + 1);\n", " }\n", "}\n", "\n", "mpl.figure.prototype.handle_save = function(fig, msg) {\n", " fig.ondownload(fig, null);\n", "}\n", "\n", "\n", "mpl.find_output_cell = function(html_output) {\n", " // Return the cell and output element which can be found *uniquely* in the notebook.\n", " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", " // IPython event is triggered only after the cells have been serialised, which for\n", " // our purposes (turning an active figure into a static one), is too late.\n", " var cells = IPython.notebook.get_cells();\n", " var ncells = cells.length;\n", " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", " data = data.data;\n", " }\n", " if (data['text/html'] == html_output) {\n", " return [cell, data, j];\n", " }\n", " }\n", " }\n", " }\n", "}\n", "\n", "// Register the function which deals with the matplotlib target/channel.\n", "// The kernel may be null if the page has been refreshed.\n", "if (IPython.notebook.kernel != null) {\n", " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", "}\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.plot(final_spectrum.wavelength, final_spectrum.flux, c='K')\n", "\n", "plt.plot(new_wave, final_spectrum.flux, c='C0')\n", "\n", "# plt.errorbar(new_wave.value, final_spectrum.flux.value, \n", "# yerr=final_spectrum.uncertainty.array, alpha=0.2, c='C5')\n", "\n", "plt.xlabel('Wavelength ['+str(final_spectrum.wavelength.unit)+']')\n", "plt.ylabel('Flux ['+str(final_spectrum.flux.unit)+']')\n", "plt.title('Gl 669A – workflow example reduction');" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 161, "metadata": {}, "outputs": [], "source": [ "from ccdproc import cosmicray_lacosmic" ] }, { "cell_type": "code", "execution_count": 201, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING: FITSFixedWarning: RADECSYS= 'FK5' / Coordinate system, per TCC ObjSys \n", "the RADECSYS keyword is deprecated, use RADESYSa. [astropy.wcs.wcs]\n", "WARNING:astropy:FITSFixedWarning: RADECSYS= 'FK5' / Coordinate system, per TCC ObjSys \n", "the RADECSYS keyword is deprecated, use RADESYSa.\n" ] }, { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support. ' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " if (mpl.ratio != 1) {\n", " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " fig.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\n", " titlebar.append(titletext)\n", " this.root.append(titlebar);\n", " this.header = titletext[0];\n", "}\n", "\n", "\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "\n", "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "mpl.figure.prototype._init_canvas = function() {\n", " var fig = this;\n", "\n", " var canvas_div = $('
');\n", "\n", " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", "\n", " function canvas_keyboard_event(event) {\n", " return fig.key_event(event, event['data']);\n", " }\n", "\n", " canvas_div.keydown('key_press', canvas_keyboard_event);\n", " canvas_div.keyup('key_release', canvas_keyboard_event);\n", " this.canvas_div = canvas_div\n", " this._canvas_extra_style(canvas_div)\n", " this.root.append(canvas_div);\n", "\n", " var canvas = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var backingStore = this.context.backingStorePixelRatio ||\n", "\tthis.context.webkitBackingStorePixelRatio ||\n", "\tthis.context.mozBackingStorePixelRatio ||\n", "\tthis.context.msBackingStorePixelRatio ||\n", "\tthis.context.oBackingStorePixelRatio ||\n", "\tthis.context.backingStorePixelRatio || 1;\n", "\n", " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width * mpl.ratio);\n", " canvas.attr('height', height * mpl.ratio);\n", " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
');\n", " nav_element.attr('style', 'width: 100%');\n", " this.root.append(nav_element);\n", "\n", " // Define a callback function for later on.\n", " function toolbar_event(event) {\n", " return fig.toolbar_button_onclick(event['data']);\n", " }\n", " function toolbar_mouse_event(event) {\n", " return fig.toolbar_button_onmouseover(event['data']);\n", " }\n", "\n", " for(var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " // put a spacer in here.\n", " continue;\n", " }\n", " var button = $('');\n", " button.click(method_name, toolbar_event);\n", " button.mouseover(tooltip, toolbar_mouse_event);\n", " nav_element.append(button);\n", " }\n", "\n", " // Add the status bar.\n", " var status_bar = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('
');\n", " var button = $('');\n", " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", " buttongrp.append(button);\n", " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", " titlebar.prepend(buttongrp);\n", "}\n", "\n", "mpl.figure.prototype._root_extra_style = function(el){\n", " var fig = this\n", " el.on(\"remove\", function(){\n", "\tfig.close_ws(fig, {});\n", " });\n", "}\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(el){\n", " // this is important to make the div 'focusable\n", " el.attr('tabindex', 0)\n", " // reach out to IPython and tell the keyboard manager to turn it's self\n", " // off when our div gets focus\n", "\n", " // location in version 3\n", " if (IPython.notebook.keyboard_manager) {\n", " IPython.notebook.keyboard_manager.register_events(el);\n", " }\n", " else {\n", " // location in version 2\n", " IPython.keyboard_manager.register_events(el);\n", " }\n", "\n", "}\n", "\n", "mpl.figure.prototype._key_event_extra = function(event, name) {\n", " var manager = IPython.notebook.keyboard_manager;\n", " if (!manager)\n", " manager = IPython.keyboard_manager;\n", "\n", " // Check for shift+enter\n", " if (event.shiftKey && event.which == 13) {\n", " this.canvas_div.blur();\n", " // select the cell after this one\n", " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", " IPython.notebook.select(index + 1);\n", " }\n", "}\n", "\n", "mpl.figure.prototype.handle_save = function(fig, msg) {\n", " fig.ondownload(fig, null);\n", "}\n", "\n", "\n", "mpl.find_output_cell = function(html_output) {\n", " // Return the cell and output element which can be found *uniquely* in the notebook.\n", " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", " // IPython event is triggered only after the cells have been serialised, which for\n", " // our purposes (turning an active figure into a static one), is too late.\n", " var cells = IPython.notebook.get_cells();\n", " var ncells = cells.length;\n", " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", " data = data.data;\n", " }\n", " if (data['text/html'] == html_output) {\n", " return [cell, data, j];\n", " }\n", " }\n", " }\n", " }\n", "}\n", "\n", "// Register the function which deals with the matplotlib target/channel.\n", "// The kernel may be null if the page has been refreshed.\n", "if (IPython.notebook.kernel != null) {\n", " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", "}\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "d5585f2db2a840f9886a0d2df32055f6", "version_major": 2, "version_minor": 0 }, "text/plain": [ "HBox(children=(BoundedFloatText(value=2047.0, description='Pixel Value (from click):', max=2047.0, step=0.1, s…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "## This makes a nice GUI, but it doesn't return the variables like this... hmm...\n", "xpl, wav = identify_widget(np.arange(len(flux)), flux)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(xpl, wav)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.4" } }, "nbformat": 4, "nbformat_minor": 4 } astropy-specreduce-05be828/notebook_sandbox/jwst_boxcar/000077500000000000000000000000001510537250300235565ustar00rootroot00000000000000astropy-specreduce-05be828/notebook_sandbox/jwst_boxcar/boxcar_extraction.ipynb000066400000000000000000004561171510537250300303550ustar00rootroot00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Boxcar extraction with specreduce" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This notebook demonstrates a simplified boxcar extraction scenario, using a rectified spectrum in a 2D spectral image where the dispersion axis is the second (X) axis. \n", "\n", "The extraction algorithm in `specreduce` is a plain adaptation of the algorithm presented in the MIRI LRS extraction notebook at https://github.com/spacetelescope/jdat_notebooks/tree/main/notebooks/MIRI_LRS_spectral_extraction This algorithm is demonstrated separately from the `specreduce` package, in the acompanying notebook http://localhost:8888/notebooks/notebook_sandbox/jwst_boxcar/jwst_boxcar_algorithm.ipynb\n", "\n", "Note that the extraction algorithm in the MIRI LRS extraction notebook performs simultaneous background subtraction when extracting from the source. Although it can only subtract the average of the two background extraction boxes. The original extraction code in `specreduce`'s `BoxcarExtract` class was capable of modeling the background with a polynomial along the cross-dispersion direction. This feature was lost in the conversion. \n", "\n", "Note also that we cannot yet perform offline, after-the-fact background subtractions from spectra extracted with `BoxcarExtract`. The reason is that `BoxcarExtract` delivers its `Spectrum1D` product with `spectral_axis` in units of `pixel`. Subsequent operations with such spectra, such as subtraction, are severely limited due to the `pixel` units." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "from matplotlib.colors import LogNorm\n", "%matplotlib inline\n", "\n", "from pathlib import Path\n", "from zipfile import ZipFile\n", "\n", "from astropy.io import fits\n", "from astropy.table import Table\n", "from astropy.visualization import simple_norm\n", "from astropy.utils.data import download_file\n", "\n", "from jwst import datamodels\n", "\n", "from specreduce.extract import BoxcarExtract\n", "from specreduce.tracing import FitTrace, FlatTrace\n", "from specreduce.background import Background\n", "\n", "import os\n", "import tempfile\n", "\n", "import numpy as np\n", "import ccdproc\n", "\n", "import matplotlib.pyplot as plt\n", "import matplotlib as mpl" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ingest s2d data" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# data is taken from s2d file. x1d is used for comparison with pipeline extraction.\n", "zipped_datapath = Path(download_file('https://stsci.box.com/shared/static/qdj79y7rv99wuui2hot0l3kg5ohq0ah9.zip', cache=True))\n", "\n", "data_dir = Path(tempfile.gettempdir())\n", "\n", "with ZipFile(zipped_datapath, 'r') as sample_data_zip:\n", " sample_data_zip.extractall(data_dir)\n", "\n", "s2dfile = str(data_dir / \"nirspec_fssim_d1_s2d.fits\")\n", "x1dfile = str(data_dir / \"nirspec_fssim_d1_x1d.fits\")" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# use a jwst datamodel to provide a good interface to the data and wcs info\n", "s2d = datamodels.open(s2dfile)\n", "image = np.array(s2d.slits[0].data)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0.5, 1.0, 'slit[0]')" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# display s2d image\n", "norm_data = simple_norm(image, \"sqrt\")\n", "plt.figure(figsize=(15, 15))\n", "plt.imshow(image, norm=norm_data, origin=\"lower\")\n", "plt.title(\"slit[0]\")" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "data": { "image/png": "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iIhcl5lFewCZNnGKiIiIBBgVNBEREZEAo4ImIiIiEmBU0EREREQCjAqaiIiISIBRQRMREREJMCpoIiIiIgFGBU1EREQkwKigiYiIiAQYFTQRERGRAKOCJiIiIhJggupanBK3jh07xtatW8mfPz+nTp1i+/btnDlzhtDQUEJDQ8mUKRPFixf3OqaIiEjQUUGTaLVt25aZM2fGOE/NmjV57bXXKFWqVAKlEhERCX4qaHJN69evZ+bMmXTu3JkiRYqQMmVKChUqROrUqbl48SIXLlxg3bp1vPbaa9xzzz3MnDmTWrVqeR1bREQkKJhzzusMcaZ06dJu3bp1XsdIlM6cOUPy5MkJCfHtlti4cWMWL17Mzp07SZcuXbSvO3LkCNWrV2f79u3MnDmTatWqJVRkERGRRM3M1jvnSl/rOR0kkMRNnjyZXLlykSpVKkqWLMnx48dZvnw5M2bM4Omnn46xnAHceuutzJ07l5w5c1K9enXuvPNO+vXrx759+xLoHYiIiASfoChoZtbAzEYfO3bM6yiJymuvvUaLFi3Ili0bvXr1YvPmzTRr1oyGDRuSL18+nnzyyVgt57bbbmPlypWMGDGCrFmz0rdvX3Lnzs2rr74az+9AREQkOGkTZxI1atQoHnnkEVq1asW4ceNIlSoVgwcPpmfPnmTNmpXly5dz++2339Cyf/75Z5555hm++uortm3bdsPLERERCWYxbeJUQUuCZs+eTYMGDahTpw4zZswgWTLfsSLOOd5//32qVKlCoUKFbmod+/bt44477qBZs2ZMmDAhLmKLiIgEFe2DJpdt2LCBFi1aUKJECT7//PPL5QzAzOjSpctNlzOAbNmy0a1bNz7++GO2bNly08sTERFJSjSCFuQuXLjACy+8QJYsWahcuTINGjQgVapUrFq1imzZssXrug8fPsztt99O6tSpadOmDalSpWLp0qVERETw2muvkTp16nhdv4iISCCLaQRN50ELYs45nnzySUaOHHl5Wp48eZg7d268lzOAjBkzMnv2bAYPHszw4cO5ePEixYoV4+2332bRokVMnjyZggULxnsOERGRxEYjaEEsMjKShg0b0qNHDyIiIoiMjGTo0KEJUs6uduzYMUJCQggPD2fOnDm0bduWtGnTsmHDBm699dYEzyMiIuI1HSSQRDVs2JB169bx+++/X7GvWSBYu3YtFStW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efJ4HUXiSefOnSlatCg9e/bkzJkzXscREZEgExQFLdBOs7Fy5UrKly+PmXkdReJJsmTJGDp0KL/88guDBg3yOo6IiASZoChogeTgwYP88ssvVKhQwesoEs9q165N69at6du3L+PGjfM6joiIBBHtwR7HLu1/poKWNIwbN47Dhw/TuXNnzIwOHTpo5FRERG6aRtDi2KpVq0iWLBmlSpXyOookgJQpUzJ16lSqVq1Kx44dadmyJUeOHPE6loiIJHIqaHHs+++/p1ChQqRJk8brKJJA0qRJw7x583j11VeZOnUqVapU4c8///Q6loiIJGIqaHFs+/btFCxY0OsYksBCQ0N54YUXmDNnDtu2baNRo0acOnXK61giIpJIqaDFoQsXLrBjxw4KFCjgdRTxSI0aNfjoo49YunSpTmQrIiI3LCgOEjCzBkCD/Pnze7L+EydOsGnTJnLkyMHZs2c1gpbEPfjgg/z+++/06tWLYsWK8b///c/rSCIiksgExQia1+dBa9euHZUqVWL58uUAGkETevTowUMPPUSfPn0YNmwYR48e9TqSiIgkIkFR0Ly2detWABU0uczMGD16NFWqVOGZZ54hS5YsdOzYkUOHDnkdTUREEgEVtDhwaeRu3bp1hIWFkTVrVo8TSSBIlSoVCxcuZM2aNTzyyCN8/PHHFCpUiGnTpnkdTUREApwKWhxIly4d4CtoxYsX14lK5TIzo0yZMrz99tt8++235M+fn+bNmzN16lSvo4mISABTQYsDUfd9K126tIdJJJDdeeedzJ8/n7Jly9KyZUtmzpzpdSQREQlQKmhxIGpBu/feez1MIoEubdq0fPXVV5QoUYLGjRvz0UcfeR1JREQCkApaHLi0iROgYcOGHiaRxCB9+vR88803VKlShXbt2tGrVy+OHz/udSwREQkgKmhxIOoIWqpUqTxMIolFunTpmD17Np06deKNN96gQIECzJgxw+tYIiISIFTQ4kBYWBgAvXv39jiJJCYpU6ZkzJgxrF27lly5ctGkSRPGjh3rdSwREQkAKmhx4NJRm7169fI4iSRGpUuXZvHixdSuXZuHH36Y119/3etIIiLisaAoaGbWwMxGHzt2zOsoIjckLCyMGTNm0LJlS5577jl69uyp63iKiCRhQXEtTudcJBBZunTpzl5nEblRKVKkYOLEiWTMmJHBgwdz+PBhRo8e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h7fffpvbbruNxo0bU62azo0tIklHTPug5U3AHCIihIaGMmLECCpUqEDFihVJnz49586dY8SIEUydOpVGjRp5HVFEJEFoT1wRCSjly5enT58+tGvXju3bt3PgwAFKly5Ny5Yt+fLLL72OJyKSIGJ1qScRkYT08ssvX/F45syZ1KxZk0aNGtGwYUMeeOABWrRoQZo0aTxKKCISvzSCJiIBL3PmzKxdu5Z+/fqxcuVK/vOf/1CjRg2OHDnidTQRkXhx3YJmZlPNrL6ZqcyJiGdSpEjB//73P/bv38+kSZPYuHEj99xzD2vXrvU6mohInItN6XoHaA1sN7PXzKxQPGcSEYlWSEgIzZs3Z968efz1119UqFCBMWPGeB1LRCROXbegOee+cc61AUoCvwHfmNkKM/uPmSWP74CxYWYNzGz0sWO6NKhIUlG5cmU2b95MzZo1eeSRR5g3b57XkURE4kysNluaWUagA/Awvss7vYWvsH0db8n+BedcpHOuy6ULMotI0pAhQwYmT57MnXfeSfPmzdmyZYvXkURE4kRs9kGbBiwF0gANnHMNnXOfO+e6AWnjO6CISEzCw8OZOXMmqVOn5v7772fNmjWcPn3a61giIjclNiNo7zvn7nTODXTO7YPLF0rHOVc6XtOJiMRC7ty5iYyM5I8//qBcuXLcdtttDBkyhLNnz3odTUTkhsSmoA24xrSVcR1ERORmlClThu3btzN58mTuvfdeevToQZ06dThx4oTX0URE/rVoC5qZZTWzUkBqM4sws5L+W1V8mztFRAJKjhw5aNasGbNmzWL8+PEsWbKEKlWq8O2333odTUTkX4lpBO0+YDCQExgKDPHfngFejP9oIiI3rn379syYMYPdu3dTqlQpunfvztGjR72OJSISK9EWNOfch865akAH51y1KLeGzrmpCZhRROSG1K9fn23btvHoo48ycuRIcuXKRZMmTdi0aZPX0UREYhTTJs62/rt5zeyZq28JlE9E5KbccsstjBgxgnXr1tGmTRuWLVtGxYoViYyM9DqaiEi0YtrEGeb/My0Qfo2biEiiERERwXvvvcemTZsoUqQITZs2ZdGiRV7HEhG5pmTRPeGcG+X/8+WEiyMiEr+yZcvG119/TYUKFWjSpAmLFi2iePHiXscSEblCbE5U+7qZpTOz5GY238wORtn8KSKS6GTIkIFZs2aR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EZHgV6NGDbZv3860adN49NFHmTJlClmzZqVx48ZkzpyZOXPmeB1RJM4ERUETEZGkISQkhMaNGzNy5EiaNGnCmjVreP/998mUKRNdu3bl5MmTXkcUiRMqaCIikmilSJGChx9+mPfff5/ff/+de+65hy1btngdS+SmqaCJiEiiV6lSJT7//HN+//13evfu7XUckZumi6WLiEhQaNGiBatXr2b48OEcPnyYPXv2cODAAcqVK0d4eLjX8UT+FY2giYhI0Gjbti3nzp2jVq1alChRglq1alGsWDE2b97sdTSRf0UFTUREgkaJEiV46KGHOHPmDE8++SRffvklZ8+epUmTJpw7dw7nHBs3buT777/3OqpIjLSJU0REgoaZMWHChH9Ma9CgAW+++SbLly9nxowZpEqVivnz53PPPfd4lFQkZhpBExGRoFa/fn1q1KhBr169mDFjBn379iVXrlzUqVOHefPmeR1P5Jo0giYiIkHNzIiMjGTUqFGkTZuWhx9+mIcffpj69etTr149XnjhBSpUqEDt2rVJlky/FiUw6CdRRESCXurUqXnqqacuP86ZMydLly6ldevWDBgwAIC77rqLZcuWoavSSCAIik2cuhaniIj8W+nSpSMyMpJDhw4xceJEtm7dSqNGjZgzZw5nz571Op4kcUFR0HQtThERuRFmRsaMGWndujXvvvsuGzdupG7duhQrVoy//vrL63iShAVFQRMREblZDz/8MAcOHOCjjz7ip59+urzpU8QL2gdNRETEL2XKlLRt25YFCxYwaNAgNm3axIULF6hYsSL//e9/dRCBJBj9pImIiFzlnXfeISwsjNmzZ5MhQwZeeukltm3bxsSJEzEzr+NJEqCCJiIicpVUqVIxfPhwhg8fDsArr7xC7969yZo1K9myZQOgbt263HXXXV7GlCCmgiYiInIdL774IqtXr2bYsGGXp/Xq1Yt27drx6quvkiNHDg/TSTDSQQIiIiLXYWZMnz6drVu3cvToUfbv30+vXr347LPPiIiIYNOmTV5HlCCjgiYiIhILISEhFCpUiPTp03PbbbcxaNAgvv32W5IlS0aJEiVIly4dBQsW5IMPPvA6qgQBFTQREZEbVKRIEdauXcvAgQPp2LEjt956Kx07dqRdu3Zs2bLF63iSiKmgiYiI3IQcOXLw/PPP8+abb7J8+XKee+45Jk+ezF133cWzzz7rdTxJpFTQRERE4khoaCivvfYau3btonPnzgwdOpRnn32WvXv3eh1NEhkVNBERkTiWKVMm3n33XR566CGGDRtGnjx5qFixImvXrvU6miQSKmgiIiLxIDQ0lAkTJrB9+3Z69OjBjh076NixIxcuXPA6miQCKmgiIiLx6I477mDgwIG89dZbbN68mffee8/rSJIIqKCJiIgkgObNm1O7dm2effZZVq9e7XUcCXBBUdDMrIGZjT527JjXUURERK7JzPj444/JkSMHtWvXZuDAgcydO5eLFy+yd+9eJk+erM2fcllQFDTnXKRzrkv69Om9jiIiIhKtzJkzs3DhQkqUKMGLL75InTp1aNmyJREREbRo0YIaNWpw4sQJr2NKAAiKgiYiIpJY5M6dm8WLF7Nv3z4effRRJk+eTI4cOXjjjTdYtmwZlSpVYtiwYezfv9/rqOIhFTQREREPZM2alREjRvDjjz+yfv16evToweeff8758+d55plnqFixIqdPn/Y6pnhEBU1ERMQjISEhFC5cGDMDoGnTpmzevJlZs2axY8cO6tatS7t27Xj33XdV1pIYFTQREZEAU69ePXr06MHu3btZsGABjz32GA0bNmTcuHEcPXrU63iSAFTQREREAtAbb7zB9u3b2bVrF++99x5ff/01nTp1olq1ahw5csTreBLPVNBEREQCmJnRtWtX1q1bx6RJk9iyZQvNmzfnt99+4+LFi17Hk3iSzOsAIiIicn2lSpWiVKlSnDx5ko4dO5IvXz5y5szJlClTKFu2rNfxJI5pBE1ERCQRad++Pdu3b+ftt98mWbJkVKpUicGDB2s0LciooImIiCQyt99+O926dWPdunXUr1+fnj170rx5c86fP+91NIkjKmgiIiKJVMaMGZkyZQpvvPEGU6dOpWnTpgwYMIDdu3d7HU1ukvZBExERScTMjB49epA8eXJ69uzJl19+yZQpU2jdujXh4eF07dr18nnWJPHQCJqIiEgQePLJJ9m3bx+TJk3ihx9+oFevXjz66KPMmzfP62hyA1TQREREgkTGjBlp3rw5hw4d4siRI2TPnp033njD61hyA1TQREREgkx4eDi33HIL3bp1Y/78+WzduvXyc845/vzzTw/TSWyooImIiASpDh06EBoayptvvkmLFi1o3749efPm5dZbb2XcuHFs3bqVY8eOeR1T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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# pipeline 1d extraction (for comparison)\n", "jpipe_x1d = Table.read(x1dfile, hdu=1)\n", "print(jpipe_x1d.columns)\n", "# plot\n", "fig, ax = plt.subplots(figsize=(10, 6))\n", "ax.plot(jpipe_x1d['WAVELENGTH'], jpipe_x1d['FLUX'], 'k-', label=\"jpipe_x1d\")\n", "ax.set_title(\"JWST Pipeline x1d extracted spectrum\")\n", "ax.set_xlabel(\"wavelength\")\n", "ax.set_ylabel(\"Flux Density [Jy]\")\n", "ax.set_yscale(\"log\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Define region to be extracted" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since this is rectified data, one option is to use the `FlatTrace` class and find the spectrum position and width by eye." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0.5, 1.0, 'slit[0] slice')" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAA2cAAAFLCAYAAABSuvQBAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8/fFQqAAAACXBIWXMAAAsTAAALEwEAmpwYAAAc4UlEQVR4nO3dfaxteVkf8O9zz70zA8OFGV6cDgMKCNGMNgzNFLHaFqFaoLZgtVZq7dhgRhNpobEviGnFpCTaqGijsRmFOqkoUoRAjLFSSqs2KfUiiMBAeRFkxoGB8nYZmZd77tM/ziZe6Z3zW3P3Puf87jmfT3Jzz95r7fV71tprrX2+Z+29n+ruAAAAcLCOHXQBAAAACGcAAABTEM4AAAAmIJwBAABMQDgDAACYgHAGAAAwAeEMAABgAsIZAFOoqpdU1S+tfv7SqvpcVW3dx7yPqapezXPjwuX/YlV9vqpuvYDa/ntVfc/q5++sqt+6v8sAgBHhDIDpdPcfd/eDuns7+fPh6Itc0d03feFGVT29qt5TVX9aVW+uqi87Z5nfneSZG6jtld39TesuBwC+mHAGwKFQVQ9P8tok/zrJQ5OcSvKrB1oUANwPwhkA+6qq/lVV3VZVp6vqvVX19PPM84W3LR6vqpcm+atJfmb1NsafuY9F/90k7+ru/9zddyV5SZInVtVXLqzrsqr6par6v1X16ar6vaq66jzzfXdV/e45t7+qqt5YVZ+sqo9V1YtX9x+rqhdV1QdWy3x1VT10SS0AHE3CGQD7pqq+Isnzk/zl7j6Z5G8m+dBuj+nuH0ryO0mev3qr4/PvY9avSvIH5zzuziQfWN2/xA1JHpLk0UkeluT7knx+twdU1ckk/zXJbyZ5ZJLHJ3nTavI/SfKcJH99Ne1TSX52YS0AHEHCGQD7aTvJpUmuraoT3f2h7v7Ahpb9oCSf+aL7PpPk5MLH35udUPb47t7u7rd292cHj/nmJB/t7p/o7ru6+3R3v2U17fuS/FB339rdd2fnSt63VdXxhfUAcMQIZwDsm+5+f5IXZieo3FFVr6qqR25o8Z9L8uAvuu/BSU4vfPx/SvJfkryqqv6kqv5dVZ0YPObR2bk6dz5fluR1q7dIfjrJLdkJp//fWyUBIBHOANhn3f3L3f312QkvneTHljxswTzvSvLEL9yoqsuTfPnq/iV13dvdP9Ld1yb5K9m5KvaPBg/7SJLH7TLtmd19xTn/Luvu25bUA8DRI5wBsG+q6iuq6mlVdWmSu7Lzma6zCx76sdx3CPqC1yX56qr61qq6LMm/SfKO7n7Pwtq+oar+4qq32mez8zbHUW2/nuTqqnphVV1aVSer6mtW0/5Dkpd+4ev8q+oRVfXsJbUAcDQJZwDsp0uT/GiSTyT5aJIvSfKDCx7309n5vNanqurfn2+G7v54km9N8tLsfPnG1yT5jvtR219I8prsBLNbkvyP7LzV8T519+kk35jkb2dnfd6X5BvOqfkNSX6rqk4n+V+rmgDgvKp7yTtFAGAeq6tR783O1bd/0d0/v+AxL0/y95Lc0d2P3+MSAeB+E84AAAAm4G2NAAAAExDOAAAAJrCvjTC3Tl7exx9xxX4OCQAAMI17/uhPPtHdjzjftH0NZ8cfcUWueen37+eQAAAA0/ijf/BDH76vad7WCAAAMAHhDAAAYALCGQAAwASEMwAAgAkIZwAAABMQzgAAACYgnAEAAExAOAMAAJiAcAYAADAB4QwAAGACwhkAAMAEhDMAAIAJCGcAAAATEM4AAAAmIJwBAABMQDgDAACYgHAGAAAwAeEMAABgAsIZAADABIQzAACACQhnAAAAExDOAAAAJiCcAQAATOD4QRcA7LPqg64AAJhJ10FXwMrwyllVXVZV/7uq/qCq3lVVP7K6/7FV9Zaqen9V/WpVXbL35QIAABxOS97WeHeSp3X3E5Ncl+QZVfWUJD+W5GXd/fgkn0ryvD2rEgAA4JAbhrPe8bnVzROrf53kaUles7r/5iTP2YsCAQAAjoJFXwhSVVtV9fYkdyR5Y5IPJPl0d59ZzXJrkmv2pEIAAIAjYFE46+7t7r4uyaOSPDnJVy4doKpurKpTVXVq+/SdF1YlAADAIXe/vkq/uz+d5M1JvjbJFVX1hW97fFSS2+7jMTd19/Xdff3WycvXqRUAAODQWvJtjY+oqitWPz8gyTcmuSU7Ie3bVrPdkOT1e1QjAADAobekz9nVSW6uqq3shLlXd/evV9W7k7yqqv5tkrclefke1gkAAHCoDcNZd78jyZPOc/8Hs/P5M46w0tD4ouM5O4dtwfloxgrrGZ1bHWPT8Wo4j/v1mTMAAAD2hnAGAAAwAeEMAABgAsIZAADABIQzAACACQhnAAAAExDOAAAAJrCkCTXcpyse/Kd7PsaSvlzH1uxXtR9jJMmos8vxY2fXH2NQ52iME8e2h2OMtsXx2n2MY4PpSyzZVpcM1mUTdZwYruv6+82ozlENS5Yxcqa3hvNsr9m76MzZ8Rgjm9jeZ/ehB9Mm6hyPsf7+vQlbg3U9NuiwdHZ45hwv4/jgXLCVJcfQoM4F+829g+PoRO1e55Lz3mhdNrEeI9uDv/0vGePus7v/inq2x9cX7h3MM1rGsud0vTHOLFiPkTNnx8sYrctHPnvlrtOPb41/N3jYA3b/nXBUZy/Y3qPzwZLnbN19fFGdg3k+uMs0V84AAAAmIJwBAABMQDgDAACYgHAGAAAwAeEMAABgAsIZAADABIQzAACACehzxlouv+Se4TyjvlujnitL+gGNetxsDXrDLBljE727hv3BBnUu6c0xGuMBW/euNT1Jjg968Vx67Myu00e9fJJxv7UHHhvve5ce231dRnUs6X30wGN3776MDfSzOlG7b8+twf6/X4Z1Do6R7QX9fkbLGLm3xy97ozpG65mM6xw9Z8cW7HuXDPbf0TlpSZ+o0TIuyfhYPjk4Vkd9+pb0z7ts2Atw9PjxGCdq9+21taAf2129+/YajfGQYw8YjjGD7d79+bi7x8fQJnyud38N2O7dj8MTC/aLewfLuGtwer5rwXF496A/3p19YriMuwbz3PXIwfSzlwzHGBn1+btnQT/Nu3r3Ou4+u2Rb7P46MFrGkteqkf+5yzRXzgAAACYgnAEAAExAOAMAAJiAcAYAADAB4QwAAGACwhkAAMAEhDMAAIAJCGcAAAAT0ISaPffJOx+46/RR+9xxC8ixUWPmUaPsJfMc20ChozF6QTPW0TJGDbk30TR51Ex7yfYeNuxe0Ix4Xxqgb2B7DcfYhybTZzdwpI2akw9r2EBjz+EYC9Zz1Ox9E8/5Jp7TJY3vd7OJ7b2khtH5YLQ9R8/HkmWMtveyY3297Z2sv80vPTZu3nzvPhxHI6P1XPKcbsI9Z3dvaryJY/3MaIzBOWfJtjhzdvftueR3gzNr7hfbgxqS8bqMpi85Kw6XsWBbrLuMsxt5SX7DfU45+CMYAAAA4QwAAGAGwhkAAMAEhDMAAIAJCGcAAAATEM4AAAAmIJwBAABMQJ8z1nLrx68czrOkp9VhcFTWM0lykaxr7U8rHQA4r744Xi6Tfeo9dzFY0ittLw2vnFXVo6vqzVX17qp6V1W9YHX/S6rqtqp6++rfs/a+XAAAgMNpyZWzM0l+oLt/v6pOJnlrVb1xNe1l3f3je1ceAADA0TAMZ919e5LbVz+frqpbklyz14UBAAAcJffrC0Gq6jFJnpTkLau7nl9V76iqV1TVeT98VFU3VtWpqjq1ffrO9aoFAAA4pBaHs6p6UJJfS/LC7v5skp9L8uVJrsvOlbWfON/juvum7r6+u6/fOnn5+hUDAAAcQovCWVWdyE4we2V3vzZJuvtj3b3d3WeT/HySJ+9dmQAAAIfbkm9rrCQvT3JLd//kOfdffc5s35LknZsvDwAA4GhY8m2NX5fku5L8YVW9fXXfi5M8t6quS9JJPpTke/egPg6Bg+4XsV8umvXcRI+yi2VdAQD22xq/Jy35tsbfTXK+EX7jgkcFAADgz7lf39YIAADA3hDOAAAAJiCcAQAATEA4AwAAmIBwBgAAMAHhDAAAYALCGQAAwASWNKEGDhMNpAEApuTKGQAAwASEMwAAgAkIZwAAABMQzgAAACYgnAEAAExAOAMAAJiAcAYAADAB4QwAAGACwhkAAMAEhDMAAIAJCGcAAAATEM4AAAAmIJwBAABMQDgDAACYgHAGAAAwAeEMAABgAsIZAADABIQzAACACQhnAAAAExDOAAAAJiCcAQAATEA4AwAAmIBwBgAAMAHhDAAAYALHD7oAgItZ90FXAMDFquqgK2A2wytnVfXoqnpzVb27qt5VVS9Y3f/QqnpjVb1v9f+Ve18uAADA4bTkbY1nkvxAd1+b5ClJvr+qrk3yoiRv6u4nJHnT6jYAAAAXYBjOuvv27v791c+nk9yS5Jokz05y82q2m5M8Z49qBAAAOPTu1xeCVNVjkjwpyVuSXNXdt68mfTTJVffxmBur6lRVndo+fec6tQIAABxai8NZVT0oya8leWF3f/bcad3dSc77sfjuvqm7r+/u67dOXr5WsQAAAIfVonBWVSeyE8xe2d2vXd39saq6ejX96iR37E2JAAAAh9+Sb2usJC9Pckt3/+Q5k96Q5IbVzzckef3mywMAADgalvQ5+7ok35XkD6vq7av7XpzkR5O8uqqel+TDSb59TyrkoqcPFHvCfsXFTG8jIH5HOteSnm9HYXsNw1l3/27u+2Xk6ZstBwAA4Gi6X9/WCAAAwN4QzgAAACYgnAEAAExAOAMAAJiAcAYAADAB4QwAAGACwhkAAMAEljShhrX0mfn/BjBNU8Peh860M6zrJmrYxLbaj22xH+taMzyp3C/7cayPLNlvZqhzE0aruk+HUA22Zw+ek9HjdxZyfyo63yBrPn6B0XpuzGhdRtOXlLkfh8gM5/gl63mxbIt169zj9Zz/t2YAAIAjQDgDAACYgHAGAAAwAeEMAABgAsIZAADABIQzAACACQhnAAAAE9DnjLX0xy8dz3PJ2bXGqLN7389qUduMQX+ZWrKam6hjNMRgc23dM5hhQQ3DdR1MX/Kc1vbu04+dGS5iWOcmxhg+p4MxRtOTpM6OBlmyjPWmj57TjdjAemykLdfgz5ZLxhjuO6OndMH2Pra9+0KO3TsoYWs8xtY9g0IXnC+Ondl9puN37n4Q9NZ4g29ftvuTduL07mNs3TU+2I/dveSEMFjGZ/501+nbDz+56/Stz941HGP73f9n92VceeVwGSN1+QN3n2FrcBDdM9g5k/S9u8+z/bhHDpex/cATu0+/bPeD4Ng94wNxtO9tX7r79LMLfhP//MN2r/P4eLcYnlO2LxktYDzG9qW7z3R2dM5ZcMmoB/Oc3f0p31nGfvTyWyNhuXIGAAAwAeEMAABgAsIZAADABIQzAACACQhnAAAAExDOAAAAJiCcAQAATEA4AwAAmIAm1Kzl7MkFTTnXbCLdvYnOzOsvYtS1cBNDDBeyiX7cgyaRG1mRDTQsHjaqXtQ4fDDGaBkbaIA+HGMj++YGljGwDz0792M1NrMiS5axHyszOCeN9r0ljVhrE91ah8fh7p1pF5Uw+lPzoPtt9agD76Y8eNepo3Wtvnw8RH/tYCHjRaxrP5r8LmpYPJphE7v3qI7Rgbight5avxn8aJzhczZ8Mcv6l3yWbIsNbM+17fEYrpwBAABMQDgDAACYgHAGAAAwAeEMAABgAsIZAADABIQzAACACQhnAAAAE9DnjLUcu2T7oEuYRu9LY5eLxCSt6WYYY8h+c/FZ0u/H88oe2ETbz5Fa0mtq1GrK7r/ckvPJxWIfnvcZdq3a4+dseOWsql5RVXdU1TvPue8lVXVbVb199e9Ze1olAADAIbfkbY2/mOQZ57n/Zd193erfb2y2LAAAgKNlGM66+7eTfHIfagEAADiy1vlCkOdX1TtWb3u88r5mqqobq+pUVZ3aPn3nGsMBAAAcXhcazn4uyZcnuS7J7Ul+4r5m7O6buvv67r5+6+TlFzgcAADA4XZB4ay7P9bd2919NsnPJ3nyZssCAAA4Wi4onFXV1efc/JYk77yveQEAABgb9jmrql9J8tQkD6+qW5P8cJKnVtV12WkT9KEk37t3JTK1GRpOTGKv+15wWNlvDifPK5s3y0vuLHXAYTQMZ9393PPc/fI9qAUAAODIWufbGgEAANgQ4QwAAGACwhkAAMAEhDMAAIAJCGcAAAATEM4AAAAmIJwBAABMYNjnDHZTOlFyxLVewwCwL47C752unAEAAExAOAMAAJiAcAYAADAB4QwAAGACwhkAAMAEhDMAAIAJCGcAAAAT0OcMYA370XNFLzUA1nEU+oMdFq6cAQAATEA4AwAAmIBwBgAAMAHhDAAAYALCGQAAwASEMwAAgAkIZwAAABPQ54w9p0cTAMDB8bvY5ux1zzhXzgAAACYgnAEAAExAOAMAAJiAcAYAADAB4QwAAGACwhkAAMAEhDMAAIAJCGcAAAAT0ISatZzdHnfiqzoanQ+797gr4UKj7T1FnUdjlwBmMcN5b4lNvF5eLOvKjiPyO9JU1jxE9voZG145q6pXVNUdVfXOc+57aFW9saret/r/yr0tEwAA4HBb8rbGX0zyjC+670VJ3tTdT0jyptVtAAAALtAwnHX3byf55Bfd/ewkN69+vjnJczZbFgAAwNFyoV8IclV33776+aNJrrqvGavqxqo6VVWntk/feYHDAQAAHG5rf1tjd3d2+Wxcd9/U3dd39/VbJy9fdzgAAIBD6ULD2ceq6uokWf1/x+ZKAgAAOHouNJy9IckNq59vSPL6zZQDAABwNA37nFXVryR5apKHV9WtSX44yY8meXVVPS/Jh5N8+14Wybz6c+NWeT36E8AGGkbU2X1oWjGaZ9Eydq+zzg4ev4H2NcfODIZYsC2HdQ6m1/ZwiGEdS1rDDMcZLGO4ngvn2fXxC7bFRupc9zjbxDEyOhesuS2TBeu5ZD0Gh8DwnLZgnNFztuT5GrWz6sHp+dg94zGOnVn/BL119+7TR8fAse1xDaPn5Phdg/6PC86txz+/+zK27lpyMO/unoec2HX6kufj2L27z1OD7dnHlrwGDMbYwOv69qW7P6lLjsPe2n1dzly2+/Szx9d/0T27tfv00XGajNf17GA9kwzPv2cHdZzdfddMkvRoXQc1jB6fjOtcsvOtW+cS6yxjuEt093PvY9LTL3xYAAAAzrWBbAgAAMC6hDMAAIAJCGcAAAATEM4AAAAmIJwBAABMQDgDAACYgHAGAAAwgQWt72AXx5d0Sh3NsH6Txz62gY6XA8PmzItKGDX/XFzOGnZfjx40F00WND0eNdte0GgyvYEmp6NGwBtoWDxsJjzab/aj8fIkljT63XNLathEnRtoHD6FBU3pR9ZvuD2uYbRvbaLp9+hYrWF33Ky9b9WZ9R6/bJA5xhg2LF5S57B58+DxG9gWm2i8PKpjybYY/p40qnPJ7yfr/pq0pLH4JvbPwbbYzBgH8lAAAAA2RTgDAACYgHAGAAAwAeEMAABgAsIZAADABIQzAACACQhnAAAAE9DnjLXUZdvjmS6SHkxDUzRpWt+wjdl+rOcs+8R+1HGx7Deb2BYXyaoObaJx3MXyvO+H/TjORpt7lnPOyMVS57r26/DYl55taz5ptsW+q8lPz66cAQAATEA4AwAAmIBwBgAAMAHhDAAAYALCGQAAwASEMwAAgAkIZwAAABPQ54y11LGLo6fFZhyOdZ28vcfF53DsFgDsBS+63E+unAEAAExAOAMAAJiAcAYAADAB4QwAAGACwhkAAMAEhDMAAIAJCGcAAAATEM4AAAAmoAk1aynNFTkgPUvzZ8cAABwZe/2771rhrKo+lOR0ku0kZ7r7+k0UBQAAcNRs4srZN3T3JzawHAAAgCPLZ84AAAAmsG446yS/VVVvraobzzdDVd1YVaeq6tT26TvXHA4AAOBwWvdtjV/f3bdV1ZckeWNVvae7f/vcGbr7piQ3Jcmlj7tmlo/wAwAATGWtK2fdfdvq/zuSvC7JkzdRFAAAwFFzweGsqi6vqpNf+DnJNyV556YKAwAAOErWeVvjVUleVztf9n88yS93929upCqAAT32AIDD5oLDWXd/MMkTN1gLAADAkeWr9AEAACYgnAEAAExAOAMAAJiAcAYAADAB4QwAAGACwhkAAMAEhDMAAIAJCGcAAAATEM4AAAAmIJwBAABMQDgDAACYgHAGAAAwAeEMAABgAsIZAADABIQzAACACQhnAAAAExDOAAAAJiCcAQAATEA4AwAAmIBwBgAAMAHhDAAAYALCGQAAwASEMwAAgAkIZwAAABMQzgAAACYgnAEAAExAOAMAAJiAcAYAADAB4QwAAGACwhkAAMAEhDMAAIAJCGcAAAATEM4AAAAmsFY4q6pnVNV7q+r9VfWiTRUFAABw1FxwOKuqrSQ/m+SZSa5N8tyqunZThQEAABwl61w5e3KS93f3B7v7niSvSvLszZQFAABwtKwTzq5J8pFzbt+6uu/Pqaobq+pUVZ3aPn3nGsMBAAAcXnv+hSDdfVN3X9/d12+dvHyvhwMAALgorRPObkvy6HNuP2p1HwAAAPfTOuHs95I8oaoeW1WXJPmOJG/YTFkAAABHS3X3hT+46llJfirJVpJXdPdLB/N/PMmHz7nr4Uk+ccEFwN6yfzIr+yazsm8yM/sns/iy7n7E+SasFc7WVVWnuvv6AysAdmH/ZFb2TWZl32Rm9k8uBnv+hSAAAACMCWcAAAATOOhwdtMBjw+7sX8yK/sms7JvMjP7J9M70M+cAQAAsOOgr5wBAAAQ4QwAAGAKBxbOquoZVfXeqnp/Vb3ooOqAqnp0Vb25qt5dVe+qqhes7n9oVb2xqt63+v/Kg66Vo6mqtqrqbVX166vbj62qt6zOn79aVZccdI0cTVV1RVW9pqreU1W3VNXXOncyg6r6Z6vX9HdW1a9U1WXOnVwMDiScVdVWkp9N8swk1yZ5blVdexC1QJIzSX6gu69N8pQk37/aH1+U5E3d/YQkb1rdhoPwgiS3nHP7x5K8rLsfn+RTSZ53IFVB8tNJfrO7vzLJE7Oznzp3cqCq6pok/zTJ9d391Um2knxHnDu5CBzUlbMnJ3l/d3+wu+9J8qokzz6gWjjiuvv27v791c+ns/PLxTXZ2SdvXs12c5LnHEiBHGlV9agkfyvJL6xuV5KnJXnNahb7Jgeiqh6S5K8leXmSdPc93f3pOHcyh+NJHlBVx5M8MMntce7kInBQ4eyaJB855/atq/vgQFXVY5I8KclbklzV3bevJn00yVUHVRdH2k8l+ZdJzq5uPyzJp7v7zOq28ycH5bFJPp7kP67edvsLVXV5nDs5YN19W5IfT/LH2Qlln0ny1jh3chHwhSCwUlUPSvJrSV7Y3Z89d1rv9JzQd4J9VVXfnOSO7n7rQdcC53E8yV9K8nPd/aQkd+aL3sLo3MlBWH3O8dnZ+QPCI5NcnuQZB1oULHRQ4ey2JI8+5/ajVvfBgaiqE9kJZq/s7teu7v5YVV29mn51kjsOqj6OrK9L8neq6kPZefv307LzGZ8rVm/VSZw/OTi3Jrm1u9+yuv2a7IQ1504O2t9I8kfd/fHuvjfJa7NzPnXuZHoHFc5+L8kTVt+ac0l2PqT5hgOqhSNu9Rmelye5pbt/8pxJb0hyw+rnG5K8fr9r42jr7h/s7kd192Oyc578b939nUnenOTbVrPZNzkQ3f3RJB+pqq9Y3fX0JO+OcycH74+TPKWqHrh6jf/CvuncyfRq5x0HBzBw1bOy81mKrSSv6O6XHkghHHlV9fVJfifJH+bPPtfz4ux87uzVSb40yYeTfHt3f/JAiuTIq6qnJvnn3f3NVfW47FxJe2iStyX5h9199wGWxxFVVddl58tqLknywST/ODt/+HXu5EBV1Y8k+fvZ+UbmtyX5nux8xsy5k6kdWDgDAADgz/hCEAAAgAkIZwAAABMQzgAAACYgnAEAAExAOAMAAJiAcAYAADAB4QwAAGAC/w+lHM9r7O00uwAAAABJRU5ErkJggg==\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# blow up of the region to be extracted\n", "plt.figure(figsize=(15, 15))\n", "plt.imshow(image[::,0:100], norm=norm_data, origin=\"lower\")\n", "plt.title(\"slit[0] slice\")" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "# extraction parameters based on image above\n", "ext_center = 27\n", "ext_width = 4\n", "\n", "bkg_sep = 4\n", "bkg_width = 2" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0.5, 1.0, 'Cross-dispersion Cut at Pixel=70')" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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vXp1pk+fzksvvcT06dO56KKL2LJli9NpVVhSUhLt27fXDlmA2rZty4033sjbb7997Nl7p4Jx48bxySef8Pzzz586HTKlVLlop0x5iojw+OOP89VXX5Genk5sbCwLFy50Oq0KSUxMJDa2xH80qZMYM2YMWVlZ3r4rsZh58+bx+OOPM3jwYMaMGeN0OsFz/fW+OaSccPvtlmNfP+N6/vKVQ3k76PY5t1s/bo+2tVtop0x50lVXXUVCQgKNGzcmLi6OcePGebLObMeOHWRmZmo9mUWdO3fm2muv5bXXXiPL4qN03GLdunUMGTKELl26MGnSpFNrbr7u3X21Rk7o2tVy7O5NuxPT0Nq2FdU7LofeceV7oHewdW3c1fpxe7St3UJrypSnZWVlceuttzJz5kyGDBnC+++/76mHn8+dO5drr72Wb7/9lksr8BDd09ny5cu56KKL+L//+z8efPBBp9OxZN++fZx//vkcOnSIhIQEmjVrdvKNvMajdUY6JYYFHm3rUNGaMnXKql69OjNmzODFF19k2rRpXHTRRWzdutXptMotMTEREaFLly5Op+JZ3bt3p0ePHowbN47cXOdmQbcqPz+fwYMHk56ezqxZs07NDplSqly0U6Y8T0QYPXo08+bNIyUlxVO1OImJiZx11llU1wc1V8gTTzzBtm3b+Oijj5xOJWCPPvooCxcu5J133qF79+5Op2OP/v3hzjudiT1ihOXY/af25865zuQ9qG+9Y3dghtqIf4+wftwebWu3cNWzL5WqiLi4OIYOHcqnn37KkSNHPHEZMykpid69ezudhuf17t2b2NhYXn75ZW699VYqVfLG/9omTZrEa6+9xoMPPsitt97qdDr26dULdu50JvYll4DFEdRerXqx87BDeTvokuaXkJtvcdTZo23tFlpTpk4p33zzDT179mTatGkMHjzY6XTKtG3bNpo0acL48eO57777nE7H82bNmsXAgQOZOnUq8fHxTqdzUt9//z09e/akZ8+ezJ071zMdScs8Wmek85RZ4NG2DhWtKVOnjUsvvZTGjRszdepUp1M5qaJ/TOidl8ExYMAAzj77bF544QXX34mbnp7OwIEDadmyJdOmTTv1O2RKqXLRTpk6pYSHhxMfH8+8efNcP6FoYmIiYWFhxHj8Fm63CAsLY8yYMfzyyy/MdfGz744cOcKf/vQncnJymDNn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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Plot along cross-disperion cut showing the extraction parameters\n", "fig, ax = plt.subplots(figsize=(10, 6))\n", "y = np.arange(image.shape[0])\n", "ax.plot(y, image[:,70], 'k-')\n", "mm = np.array([ext_center, ext_center])\n", "mm_y = ax.get_ylim()\n", "\n", "# extraction region\n", "ax.axvspan(ext_center - ext_width/2., ext_center + ext_width/2., color='green', alpha=0.1)\n", "ax.plot(mm, mm_y, 'b--')\n", "ax.plot(mm - ext_width/2., mm_y, 'g:')\n", "ax.plot(mm + ext_width/2., mm_y, 'g:')\n", "\n", "# background region, symmetric on both sides of extraction region\n", "ax.axvspan(ext_center - bkg_sep - bkg_width/2., ext_center - bkg_sep + bkg_width/2., color='red', alpha=0.1)\n", "ax.plot(mm - bkg_sep - bkg_width/2., mm_y, 'r:')\n", "ax.plot(mm - bkg_sep + bkg_width/2., mm_y, 'r:')\n", "\n", "ax.axvspan(ext_center + bkg_sep - bkg_width/2., ext_center + bkg_sep + bkg_width/2., color='red', alpha=0.1)\n", "ax.plot(mm + bkg_sep - bkg_width/2., mm_y, 'r:')\n", "ax.plot(mm + bkg_sep + bkg_width/2., mm_y, 'r:')\n", "\n", "ax.set_title(\"Cross-dispersion Cut at Pixel=70\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Background Subtraction" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "# extract the background using custom individual traces\n", "trace = FlatTrace(image, ext_center)\n", "bg = Background(image, [trace-bkg_sep, trace+bkg_sep], width=bkg_width)\n", "\n", "bg = Background.two_sided(image, trace, bkg_sep, width=bkg_width)\n", "# or in the place of any trace, an int/float can be passed which resolves to a FlatTrace\n", "bg = Background.two_sided(image, ext_center, bkg_sep, width=bkg_width)\n", "\n", "# or for single sided:\n", "# bg = Background.one_sided(image, trace, bkg_sep, width=bkg_width)\n", "# bg = Background.one_sided(image, trace, -bkg_sep, width=bkg_width)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(34, 435)" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# access the underlying weight image\n", "bg.bkg_wimage.shape" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0.5, 1.0, 'slit[0] slice')" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.figure(figsize=(15, 15))\n", "plt.imshow(bg.bkg_wimage[::,0:100].data, origin=\"lower\")\n", "plt.title(\"slit[0] slice\")" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0.5, 1.0, 'slit[0] slice')" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.figure(figsize=(15, 15))\n", "plt.imshow(bg.bkg_image(image)[::,0:100].data, norm=norm_data, origin=\"lower\")\n", "plt.title(\"slit[0] slice\")" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0.5, 1.0, 'slit[0] slice')" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.figure(figsize=(15, 15))\n", "plt.imshow(bg.sub_image(image)[::,0:100].data, norm=norm_data, origin=\"lower\")\n", "plt.title(\"slit[0] slice\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that when using median, partial pixel weights are not supported:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0.5, 1.0, 'slit[0] slice')" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAA2cAAAFLCAYAAABSuvQBAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8/fFQqAAAACXBIWXMAAAsTAAALEwEAmpwYAAAUk0lEQVR4nO3df7DldX3f8dc7u8sSfhhACV2BiBGiQ9KAnS2aaluFmKC1hTQ2lUlT0jGzyUxopWN/EDNtdabMaCdqkoljZw1UpjGiRRwZJyMipTXOtNRFiQKrBS0qW2AxgqwxIuC7f5wvkxu6y73cH3s+3PN4zNy55/vrnDczZ77Lc8/3fLe6OwAAAMzXD8x7AAAAAMQZAADAEMQZAADAAMQZAADAAMQZAADAAMQZAADAAMQZAADAAMQZAEOoqrdU1R9Mj3+kqr5dVVsOse9pVdXTPrtW+Pzvq6o/r6p7VjHbf6uqX5ke/2JVfeLpPgcALEecATCc7v5adx/T3Y8nfzmOnuS47t79xEJVnVdVX6yq71TVTVX1vCXP+ctJXr0Os72/u39mrc8DAE8mzgDYFKrqOUmuTfJvkpyQZE+SD851KAB4GsQZAIdVVf3rqtpXVQeq6ktVdd5B9nnissWtVXV5kr+Z5Pemyxh/7xBP/feT3N7d/6W7v5vkLUnOqqoXrXCuI6vqD6rqT6vqoar6TFWddJD9frmqPr1k+cer6oaq+mZV3V9Vb57W/0BVXVZVX56e80NVdcJKZgFgMYkzAA6bqnphkkuS/PXuPjbJzya5+6mO6e7fTPLHSS6ZLnW85BC7/niSP1ly3J8l+fK0fiUuTvJDSU5N8uwkv5bkz5/qgKo6Nsknk3w8yXOTnJ7kxmnzP01yYZK/PW17MMm7VzgLAAtInAFwOD2eZHuSM6tqW3ff3d1fXqfnPibJt5607ltJjl3h8Y9mFmWnd/fj3X1Ldz+8zDGvTXJfd7+ju7/b3Qe6++Zp268l+c3uvqe7H8nsk7zXVdXWFc4DwIIRZwAcNt19V5JLMwuV/VV1dVU9d52e/ttJnvWkdc9KcmCFx//nJNcnubqq/m9V/Yeq2rbMMadm9uncwTwvyUemSyQfSrI3szj9/y6VBIBEnAFwmHX3H3b3yzOLl07y9pUctoJ9bk9y1hMLVXV0khdM61cy16Pd/dbuPjPJ38jsU7F/vMxhX0/yo0+x7dXdfdySnyO7e99K5gFg8YgzAA6bqnphVZ1bVduTfDez73R9fwWH3p9DR9ATPpLkJ6rq56vqyCT/Nsnnu/uLK5ztlVX1V6d/W+3hzC5zXG62jyXZUVWXVtX2qjq2ql4ybfuPSS5/4nb+VXViVV2wklkAWEziDIDDaXuStyX5RpL7kvxwkt9YwXG/k9n3tR6sqt892A7d/UCSn09yeWY333hJktc/jdn+SpJrMguzvUn+e2aXOh5Sdx9I8qokfzez/547k7xyyczXJflEVR1I8j+nmQDgoKp7JVeKAMA4pk+jvpTZp2//srvfu4JjrkjyD5Ls7+7TN3hEAHjaxBkAAMAAXNYIAAAwAHEGAAAwgMP6D2EeUdv7yBx9OF8SAABgGAfy4De6+8SDbTuscXZkjs5L6rzD+ZIAAADD+GRf89VDbXNZIwAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwAAO6630f+wnv5Prr7/1cL4kAADAMLbsOPQ2n5wBAAAMQJwBAAAMQJwBAAAMQJwBAAAMQJwBAAAMQJwBAAAMQJwBAAAMQJwBAAAMQJwBAAAMQJwBAAAMQJwBAAAMQJwBAAAMQJwBAAAMQJwBAAAMQJwBAAAMQJwBAAAMQJwBAAAMYNk4q6ojq+p/VdWfVNXtVfXWaf3zq+rmqrqrqj5YVUds/LgAAACb00o+OXskybndfVaSs5OcX1UvTfL2JO/q7tOTPJjkDRs2JQAAwCa3bJz1zLenxW3TTyc5N8k10/qrkly4EQMCAAAsghV956yqtlTVrUn2J7khyZeTPNTdj0273JPk5A2ZEAAAYAGsKM66+/HuPjvJKUnOSfKilb5AVe2qqj1VteeBP318dVMCAABsck/rbo3d/VCSm5L8VJLjqmrrtOmUJPsOcczu7t7Z3TtPfPaWtcwKAACwaa3kbo0nVtVx0+MfTPKqJHszi7TXTbtdnOSjGzQjAADAprd1+V2yI8lVVbUls5j7UHd/rKruSHJ1Vf37JJ9LcsUGzgkAALCpVXcfthd7Vp3QL6nzDtvrAQAAjOSTfc0t3b3zYNue1nfOAAAA2BjiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADiDAAAYADLxllVnVpVN1XVHVV1e1W9cVr/lqraV1W3Tj+v2fhxAQAANqetK9jnsSRv6u7PVtWxSW6pqhumbe/q7t/auPEAAAAWw7Jx1t33Jrl3enygqvYmOXmjBwMAAFgkT+s7Z1V1WpIXJ7l5WnVJVX2+qq6squMPccyuqtpTVXsezSNrmxYAAGCTWnGcVdUxST6c5NLufjjJe5K8IMnZmX2y9o6DHdfdu7t7Z3fv3Jbta58YAABgE1pRnFXVtszC7P3dfW2SdPf93f14d38/yXuTnLNxYwIAAGxuK7lbYyW5Isne7n7nkvU7luz2c0luW//xAAAAFsNK7tb4siS/lOQLVXXrtO7NSS6qqrOTdJK7k/zqck/0Yz/5nVx//a3L7QYAALApbdlx6G0ruVvjp5PUQTb90epHAgAAYKmndbdGAAAANoY4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGIA4AwAAGMDWw/li//vzR+Vnn3v24XxJAACAgdx1yC0+OQMAABiAOAMAABiAOAMAABiAOAMAABiAOAMAABiAOAMAABiAOAMAABiAOAMAABjAsnFWVadW1U1VdUdV3V5Vb5zWn1BVN1TVndPv4zd+XAAAgM1pJZ+cPZbkTd19ZpKXJvn1qjozyWVJbuzuM5LcOC0DAACwCsvGWXff292fnR4fSLI3yclJLkhy1bTbVUku3KAZAQAANr2tT2fnqjotyYuT3JzkpO6+d9p0X5KTDnHMriS7kuTIHLXqQQEAADazFd8QpKqOSfLhJJd298NLt3V3J+mDHdfdu7t7Z3fv3JbtaxoWAABgs1pRnFXVtszC7P3dfe20+v6q2jFt35Fk/8aMCAAAsPmt5G6NleSKJHu7+51LNl2X5OLp8cVJPrr+4wEAACyGlXzn7GVJfinJF6rq1mndm5O8LcmHquoNSb6a5Bc2ZEIAAIAFsGycdfenk9QhNp+3vuMAAAAsphXfEAQAAICNI84AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGIM4AAAAGsGycVdWVVbW/qm5bsu4tVbWvqm6dfl6zsWMCAABsbiv55Ox9Sc4/yPp3dffZ088fre9YAAAAi2XZOOvuTyX55mGYBQAAYGGt5Ttnl1TV56fLHo8/1E5Vtauq9lTVnkfzyBpeDgAAYPNabZy9J8kLkpyd5N4k7zjUjt29u7t3dvfObdm+ypcDAADY3FYVZ919f3c/3t3fT/LeJOes71gAAACLZVVxVlU7liz+XJLbDrUvAAAAy9u63A5V9YEkr0jynKq6J8m/S/KKqjo7SSe5O8mvbtyIAAAAm9+ycdbdFx1k9RUbMAsAAMDCWsvdGgEAAFgn4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAA4gwAAGAAy8ZZVV1ZVfur6rYl606oqhuq6s7p9/EbOyYAAMDmtpJPzt6X5PwnrbssyY3dfUaSG6dlAAAAVmnZOOvuTyX55pNWX5DkqunxVUkuXN+xAAAAFsvWVR53UnffOz2+L8lJh9qxqnYl2ZUkR+aoVb4cAADA5rbmG4J0dyfpp9i+u7t3dvfObdm+1pcDAADYlFYbZ/dX1Y4kmX7vX7+RAAAAFs9q4+y6JBdPjy9O8tH1GQcAAGAxreRW+h9I8j+SvLCq7qmqNyR5W5JXVdWdSX56WgYAAGCVlr0hSHdfdIhN563zLAAAAAtrzTcEAQAAYO3EGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwADEGQAAwAC2ruXgqro7yYEkjyd5rLt3rsdQAAAAi2ZNcTZ5ZXd/Yx2eBwAAYGG5rBEAAGAAa42zTvKJqrqlqnYdbIeq2lVVe6pqz6N5ZI0vBwAAsDmt9bLGl3f3vqr64SQ3VNUXu/tTS3fo7t1JdifJs+qEXuPrAQAAbEpr+uSsu/dNv/cn+UiSc9ZjKAAAgEWz6jirqqOr6tgnHif5mSS3rddgAAAAi2QtlzWelOQjVfXE8/xhd398XaYCAABYMKuOs+7+SpKz1nEWAACAheVW+gAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAAMQZwAAAANYU5xV1flV9aWququqLluvoQAAABbNquOsqrYkeXeSVyc5M8lFVXXmeg0GAACwSNbyydk5Se7q7q909/eSXJ3kgvUZCwAAYLGsJc5OTvL1Jcv3TOv+kqraVVV7qmrPo3lkDS8HAACweW34DUG6e3d37+zunduyfaNfDgAA4BlpLXG2L8mpS5ZPmdYBAADwNK0lzj6T5Iyqen5VHZHk9UmuW5+xAAAAFkt19+oPrnpNkt9OsiXJld19+TL7P5Dkq0tWPSfJN1Y9AGws709G5b3JqLw3GZn3J6N4XnefeLANa4qztaqqPd29c24DwFPw/mRU3puMynuTkXl/8kyw4TcEAQAAYHniDAAAYADzjrPdc359eCren4zKe5NReW8yMu9PhjfX75wBAAAwM+9PzgAAAIg4AwAAGMLc4qyqzq+qL1XVXVV12bzmgKo6tapuqqo7qur2qnrjtP6Eqrqhqu6cfh8/71lZTFW1pao+V1Ufm5afX1U3T+fPD1bVEfOekcVUVcdV1TVV9cWq2ltVP+XcyQiq6p9Pf6bfVlUfqKojnTt5JphLnFXVliTvTvLqJGcmuaiqzpzHLJDksSRv6u4zk7w0ya9P78fLktzY3WckuXFahnl4Y5K9S5bfnuRd3X16kgeTvGEuU0HyO0k+3t0vSnJWZu9T507mqqpOTvLPkuzs7p9IsiXJ6+PcyTPAvD45OyfJXd39le7+XpKrk1wwp1lYcN19b3d/dnp8ILP/uTg5s/fkVdNuVyW5cC4DstCq6pQkfyfJ70/LleTcJNdMu3hvMhdV9UNJ/laSK5Kku7/X3Q/FuZMxbE3yg1W1NclRSe6NcyfPAPOKs5OTfH3J8j3TOpirqjotyYuT3JzkpO6+d9p0X5KT5jUXC+23k/yrJN+flp+d5KHufmxadv5kXp6f5IEk/2m67Pb3q+roOHcyZ929L8lvJflaZlH2rSS3xLmTZwA3BIFJVR2T5MNJLu3uh5du69m/OeHfneCwqqrXJtnf3bfMexY4iK1J/lqS93T3i5P8WZ50CaNzJ/Mwfc/xgsz+AuG5SY5Ocv5ch4IVmlec7Uty6pLlU6Z1MBdVtS2zMHt/d187rb6/qnZM23ck2T+v+VhYL0vy96rq7swu/z43s+/4HDddqpM4fzI/9yS5p7tvnpavySzWnDuZt59O8n+6+4HufjTJtZmdT507Gd684uwzSc6Y7ppzRGZf0rxuTrOw4Kbv8FyRZG93v3PJpuuSXDw9vjjJRw/3bCy27v6N7j6lu0/L7Dz5X7v7F5PclOR1027em8xFd9+X5OtV9cJp1XlJ7ohzJ/P3tSQvraqjpj/jn3hvOncyvJpdcTCHF656TWbfpdiS5Mruvnwug7DwqurlSf44yRfyF9/reXNm3zv7UJIfSfLVJL/Q3d+cy5AsvKp6RZJ/0d2vraofzeyTtBOSfC7JP+ruR+Y4Hguqqs7O7GY1RyT5SpJ/ktlf/Dp3MldV9dYk/zCzOzJ/LsmvZPYdM+dOhja3OAMAAOAvuCEIAADAAMQZAADAAMQZAADAAMQZAADAAMQZAADAAMQZAADAAMQZAADAAP4fayc9iLtgdBgAAAAASUVORK5CYII=\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "bg_med = Background.two_sided(image, ext_center, bkg_sep, width=bkg_width, statistic='median')\n", "plt.figure(figsize=(15, 15))\n", "plt.imshow(bg_med.bkg_wimage[::,0:100].data, origin=\"lower\")\n", "plt.title(\"slit[0] slice\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Trace\n", "\n", "We can now refine the initial, flat trace by finding an automated trace on the subtracted image with by fitting another wuth the `FitTrace` class. This process could then be iterated as necessary (recreating the subtracted image with the refined trace, etc)." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "auto_trace = FitTrace(image-bg, guess=ext_center, window=ext_width)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Extract" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "boxcar = BoxcarExtract(image-bg, auto_trace)\n", "spectrum = boxcar(width=ext_width)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "image/png": "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/33NSyYiIiEhoIXMzMab2VEz23bV8tpmttPMdplZ72iregEzA5kpIdi/fz/ff/89DRo08DpK0OrQoQNHjx5lzpw5XkcRERG5oUCPkE0EakdfYGbhwEigDlAYeMrMCptZTeAH4GiAM4W8xYsXA1C7du0bPDPxqlmzJvny5WPUqFFeRxEREbmhgBYy59xXwO9XLS4H7HLO/eyciwKmAw2AKsD9wNPAc2Z2zWxm1sa/W3P9sWPHAhc+iC1evJicOXNSuHBhr6MErbCwMNq1a8fKlSvZunWr13FERERi5MUxZNmB/dEeHwCyO+decs51BaYCY51zl6/1YufcGOdcGedcmSxZsgQ+bZA5deoUn3/+ObVr18bMvI4T1Fq0aEHy5Ml59913vY4iIiISo6A6qB/AOTfRObfQ6xzBasyYMZw5c4a2bdt6HSXoZcqUiSeffJLJkydz+vRpr+OIiIhclxeF7CCQM9rjHP5lcgNRUVH85z//oVq1atx3331exwkJ7du358yZM/z3v//1OoqIiMh1eVHI1gH5zeweM0sGPAnM9yBHyJk/fz4HDx6kW7duXkcJGeXKleOxxx6jb9++jBw50us4IiIi1xToaS+mAWuAgmZ2wMxaOecuAZ2Az4DtwEzn3PeBzJFQjB07lly5cunsyptgZkybNo169erRqVMnnXUpIiJBKSSvZWlm9YB6ERERz/30009ex4kXe/bsIW/evPTv359+/fp5HSfkREVF8fjjj7N48WI2btxIsWLFvI4kIiKJTIK7lqVzboFzrk369Om9jhJvpkyZAqBLJd2iZMmSMXHiRDJkyECbNm24fPmaJ/GKiIh4IiQLWWLjnGPKlCk8+OCD5MqVy+s4IStTpkwMGzaMb775ho8++sjrOCIiIn9TIQsBmzdvZseOHTRt2tTrKCHvmWeeoUiRIrz88stcvHjR6zgiIiKACllImDBhAsmSJePxxx/3OkrICw8PZ9CgQfz44480a9aMS5cueR1JREREhSzYnTlzhg8++IAmTZqQKVMmr+MkCPXr1+f1119n2rRpjB492us4IiIioVnIzKyemY05efKk11ECbsqUKZw6dYoOHTp4HSVB6dWrF/fffz8jRozQAf4iIuK5kCxkieksy4ULF1KgQAHuv/9+r6MkOJ06deLHH39kyZIlXkcREZFELiQLWWKyYcMGypcvrwuJB0Djxo25++676d+/P6E4H5+IiCQcKmRB7NChQxw6dEjXrQyQ5MmT89prr7FmzRqmTZvmdRwREUnEVMiC2IYNGwBUyAKoWbNmlClThg4dOrB161av44iISCKlQhbENmzYgJlRsmRJr6MkWOHh4cyePZvUqVNTv359zp0753UkERFJhFTIgtiGDRsoVKgQadKk8TpKgpYrVy6mTZvG3r17GTx4sNdxREQkEQrJQpZYpr3YsGGDdlfGkwcffJCmTZsydOhQjh8/7nUcERFJZEKykCWGaS8OHTrEr7/+qkIWj7p3705UVBRz5871OoqIiCQyIVnIEgMd0B//SpYsSUREBDNnzvQ6ioiIJDIqZEHqygH9pUqV8jpKomFmNGnShGXLlnH06FGv44iISCKiQhakNmzYQMGCBXVAfzyLjIzEOcegQYO8jiIiIomIClkQioqKYu3atdpd6YFChQrRunVrRo4cyfbt272OIyIiiYQKWRDZvn07lStXpnnz5hw5coSnn37a60iJ0oABA0iXLh2PP/44p06d8jqOiIgkAipkQWTYsGGsXr2aadOm0ahRIx555BGvIyVKd911Fx999BE//fQT3bt39zqOiIgkAipkQeLEiRNMmzaNyMhIRo0axXvvved1pEStatWqdOjQgQkTJvDTTz95HUdERBK4kCxkCXFi2PHjx/Pnn3/SrVs32rdvT+bMmb2OlOj16dOHZMmS8eqrr3odRUREEriQLGQJbWLY8+fPM2zYMKpWrarrVgaRrFmz0rlzZ6ZOncr333/vdRwREUnAQrKQJTTjx4/n8OHDvPzyy15Hkav07NmTNGnS0K1bN06fPu11HBERSaBUyDwWFRXFkCFDqFixIlWqVPE6jlwlU6ZMvPbaa3z++ecULVpUx5OJiEhAqJB57MMPP2Tfvn307dsXM/M6jlxDly5dWL16NefOnaNatWocPnzY60giIpLAqJB56NKlSwwePJjSpUtTu3Ztr+NIDCpWrMgXX3zB0aNH6dmzp9dxREQkgVEh89DMmTPZtWuXRsdCRMmSJenRoweTJ0/myy+/9DqOiIgkIOac8zrDLStTpoxbv3691zFuiXOO4sWL45xjy5YthIWpG4eCs2fPUqpUKU6ePMm6devIlSuX15FERCREmNkG51yZa61TC/DI999/z7Zt2+jcubPKWAhJnTo18+bN4/z58zz44IO63qWIiMSJkGwCCWFi2Llz5wJQv359b4PITbv33ntZunQp58+fp2HDhly6dMnrSCIiEuJCspAlhIlh582bx/3338/dd9/tdRS5BWXKlGH06NH8+OOPTJo0yes4IiIS4kKykIWSCxcucPny5X8sO3DgAOvXr6dBgwYepZK40KBBA8qWLcsrr7xCKI/WioiI91TIAixFihS0bNnyH8vmz58PoEIW4syMESNGcOjQIbp16+Z1HBERCWEqZPHggw8++MfjefPmUaBAAQoVKuRRIokr5cuXp2fPnowfP55PPvnE6zgiIhKiVMji2cmTJ1m+fDkNGjTQ3GMJRP/+/SlatCgtW7bk2WefZdSoUdqFKSIiN0WFLJ599NFHXLx4kYYNG3odReJI8uTJ+fDDD7nzzjtZunQpHTt25IEHHuC3337zOpqIiIQITQwbYFdGwU6dOkXq1KkpXLgwKVOmZOPGjRohS6AWL15Mw4YNKV26NCtWrCBp0qReRxIRkSCgiWGDwJ49e/joo4/YuXMnPXv2VBlLwGrXrs0HH3zAmjVr6Nu3r9dxREQkBKiQxZNFixbRpk0bSpQowb/+9S+v40iAPfHEE7Ru3Zrhw4ezZ88er+OIiEiQUyGLJ7179yZp0qTMmzePJEmSeB1H4kH//v0JCwtj+PDhXkcREZEgp0IWYNHL1zvvvEPu3Lk9TCPxKXv27ERGRjJ27Fh69erFn3/+6XUkEREJUiE5VGNm9YB6ERERXkeJtVKlStGkSROvY0g8Gzx4MGfOnGHo0KGcPXuWd955x+tIIiIShEJyhCzUrmXZu3dv1q1bpwP5E6E777yTGTNm8PzzzzNy5Eg+/fRTryOJiEgQCslCFmrCwsIIDw/3OoZ4aNCgQRQrVoyWLVvy8ccfs23bNq8jiYhIEFEhE4kHKVKkYMqUKZw4cYJGjRpRsmRJhg4dSijPAygiInEnJI8hEwlFxYoV4+uvv+bUqVOMHj2aXr168ddff9GnTx+vo4mIiMdUyETi0X333QfAQw89RJIkSXjxxRdJly4dHTt29DiZiIh4SYVMxANhYWFMnDiRM2fO0KlTJ9KnT88zzzzjdSwREfGIjiET8UjSpEmZMWMGVatWpXnz5vTr148//vjD61giIuIBFTIRD6VIkYJ58+bRoEEDBgwYQK1atYiKivI6loiIxDMVMhGPpU2bltmzZzNr1izWrl1Lt27ddPaliEgio0ImEiQaN25M9+7dGTlyJAMGDPA6joiIxCMd1C8SRIYOHcpvv/1G//79SZMmDd27d/c6koiIxAMVMpEgEhYWxtixYzlz5gw9evRgy5YtvP3222TIkMHraCIiEkDaZSkSZJIkScLUqVN5+eWXmTJlCsWKFWPz5s1exxIRkQBSIRMJQkmTJmXAgAGsWbOGv/76ixYtWvDXX395HUtERAJEhUwkiJUtW5a3336bzZs3M3r0aK/jiIhIgIRkITOzemY25uTJk15HEQm4xo0bU716dfr27cvRo0e9jiMiIgEQkoXMObfAOdcmffr0XkcRCTgz45133uHs2bM89dRTrFu3zutIIiISx0KykIkkNoUKFeLNN99k7dq1lC9fnpdeekmTx4qIJCAqZCIholOnTvz66680b96cQYMG8emnn3odSURE4ogKmUgISZs2Le+99x45c+bkjTfe8DqOiIjEkesWMjPLGItbhnjMKiL4psTo1q0bK1asoH///vz5559eRxIRkdsU00z9v/pvFsNzwoFccZpIRG6oTZs2rFq1ildffZUlS5awcOFCzeYvIhLCYtplud05l9c5d8/1bsBv8RVURP4nVapUfPTRR8ycOZO1a9eSL18+zVMmIhLCYipkFWLx+tg8R0QC5F//+herVq2iSJEidO7cmZ9//tnrSCIicguuW8icc+cBzGy4mRWJ6Tki4p1y5coxffp0kiRJQpMmTahbty4DBw7k999/9zqaiIjEUmzOstwOjDGzb82snZlpNlaRIJMtWza6d+/O5s2b+emnn3j55Ze59957mTVrluYrExEJATcsZM65951zlYBngTzAFjObamZVAx1ORGLv//7v/zh9+jQ7d+5k06ZN5MyZkyZNmtCuXTuVMhGRIBerecjMLBwo5L8dB74DupnZ9ABmE5GbYGakTJkSgBIlSvDNN9/Qo0cPxowZw8CBAz1OJyIiMYlp2gsAzOwtoB6wFBjknFvrXzXEzHYGMpyI3LokSZIwdOhQjhw5wssvv8w999xD06ZNvY4lIiLXcMNCBmwB+jrnzl5jXbk4ziMiccjMeP/999m/fz8tW7akcOHClCpVyutYIiJylesWMjMr7b/7HVDQ7B/zw14A9jnnTgYwm4jEgWTJkjFr1ixKlizJE088webNm0mVKpXXsURE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4+jRo5QsWZJ7772Xrl278umnn3odTyROqZCJiEhQK1++PLt27WL06NHkyJGDMWPG8Oijj7JkyRKvo4nEmZAsZGZWz8zGnDx50usoIiISD+68807atm3LkiVL+O233yhYsCCtWrXSQf+SYIRkIXPOLXDOtUmfPr3XUUREJJ6lTJmSSZMmcezYMapXr87Ro0e9jiRy20KykImISOJWrlw55s+fz65duyhXrhxz587l999//8dB/3v27NFVACRkqJCJiEhIqlGjBl999RWXL1/mscceI1OmTJQqVYo1a9bQrFkz8ubNS+nSpVm3bp3XUUVuSIVMRERCVpkyZdi9ezeLFy9myJAh7Nmzh4oVKzJlyhTatWvH77//zkMPPcQbb7zB5s2bNWImQUuXThIRkZCWNGlSatWqRa1atXjkkUf49NNPefLJJ8mVKxdHjx7l8ccfp2fPngDkzZuXr7/+mrvuusvj1CL/pEImIiIJRtGiRSlatOjfj++8805WrlzJvn37WLp0KR06dKBp06a0aNGCsLAwihUrRpEiRTAzD1OLqJCJiEgikCtXLlq0aEFUVBTt2rVj6dKlf6+rWbMm48eP5/Lly+TKlcvDlJKY6RgyERFJNNq2bcuBAwfYuXMn27ZtY+jQoSxbtoycOXOSJ08eevbsycWLF72OKYmQRshERCRRyZ49+9/3ixQpQrly5Vi1ahW//PILb7zxBlu3bmXixIk6zkzilQqZiIgkag899BAPPfQQ4JvfrF27duTMmZNChQrx8MMP079/f9KkSeNxSknotMtSRETEr3Xr1mzfvp3nn3+e7Nmz8+abb5I/f37efPNNoqKivI4nCZgKmYiISDT58+dnyJAhLFq0iNWrV1O4cGG6d+9O8eLF2bJli9fxJIFSIRMREbmOChUqsHTpUhYtWsSZM2eoUKECo0aNYsWKFRw6dMjreJKA6BgyERGRG6hduzbr1q0jMjKSjh07ApAxY0bGjx9P6tSpSZMmDeXLl9d8ZnLLNEImIiISC3fffTdffPEFS5YsYc6cOaRLl46GDRtSs2ZNKlSowMSJE72OKCFMhUxERCSWzIzq1avz2GOPsXHjRhYvXszKlSupWLEivXr14sSJE15HlBClQiYiInIL7rjjDmrVqkXlypUZOXIkx48f5/XXX/c6loQoFTIREZHbVLJkSZo2bcqIESM4cOAAb7/9Nu3atePtt9+mePHiZM6cmVGjRnH58mX+/PNPLl++7HVkCTIqZCIiInGgX79+REVFkTNnTrp27cr48ePp2rUrKVKkoFChQnTs2JEsWbKQKlUqcufOzcKFC72OLEFEZ1mKiIjEgYiICJYtW8YXX3xBsWLFqFGjBrt27aJs2bJcuHCBdu3aAVCoUCGmTp1KvXr16NKlC4888ghFixb9xyWdJPEx55zXGW5ZmTJl3Pr1672OEaOkSZPSs2dPBg4c6HUUEREJElFRUXTv3p133nnn72U5cuSgbNmyVK5cmZYtW5IhQwbvAkpAmNkG51yZa60LyV2WZlbPzMacPHnS6ygiIiI3LVmyZIwYMYI9e/awYsUK/vOf/1C5cmW2bdtG9+7dyZ07N8OGDaNfv37MnTuXS5cueR1ZAkwjZAGmETIREbkZmzdv5vnnn+fLL7/8e1nZsmWZOXMmefLk8SyX3L4EN0ImIiKSUJUsWZKlS5eyYcMGTpw4wZQpU9i5cyflypVj0qRJTJw4kVOnTnkdU+KYCpmIiEiQCQsLo3Tp0mTIkIGnn36atWvXkiZNGpo1a0aLFi3IkSMHjRo1YuHChYTyni75HxUyERGRIFewYEE2btzIypUrWb16NU2aNGHt2rXUq1ePp59+mkOHDrFt2zavY8pt0LQXIiIiISBDhgxUrlwZgIoVK3Lx4kUGDhzIq6++ysyZMwkLC2PlypXcf//9HieVW6FCJiIiEoKSJk1Kv379CAsLY+/evSxfvpx//etfvPnmm5w7d47ixYtTsmRJzMzrqBILKmQiIiIhysx45ZVXANi0aRONGjWiSZMmf68vUqQINWvWpFSpUkRGRqqcBTEVMhERkQSgVKlS7Ny5kxUrVnD33XezevVqJk+ezJgxYzh37hyff/45kZGRHDt2jGrVqpEtWzavI0s0KmQiIiIJRLJkyahZsyYARYsWpW3btjjnGDBgAK+++ipTpkwBIFOmTEyZMoVatWp5GVei0VmWIiIiCZiZ0a9fP44dO8ayZctYtWoV2bNn59FHH+XZZ5+latWq5M+fn6FDh3Lo0CGv4yZaKmQiIiKJQKZMmahatSqVKlVi1apVNGjQgEWLFnH27FmyZ89Or169yJYtG/fddx+vvPIK8+fPZ/v27V7HTjS0y1JERCSRSZs2LbNnz/7Hsq1bt7Jw4UI++eQTBg4cyOXLlwkLC2PUqFG0bdvWo6SJh0bIREREhGLFitGnTx9WrVrFsWPHWLt2LbVr16Zdu3asWrXK63gJngqZiIiI/EPGjBkpW7Yss2bNImvWrPTt21eXaAowFTIRERG5plSpUvHiiy+yYsUKqlSpQs2aNenXrx9RUVFeR0twVMhERETkutq2bctLL73En3/+yfHjxxkwYAA1atRQKYtjKmQiIiJyXcmSJeO1115j7dq1bNq0iUmTJrFy5Uqee+45fv75Z6/jJRgqZCIiIhJrkZGR9O7dm0mTJpEvXz6eeeYZfvnlF69jhTwVMhEREbkpgwcPZufOnfTp04fZs2dTsGBBJk2a5HWskKZCJiIiIjetQIECDBo0iJ07d1KhQgVatWrF/PnzdTbmLVIhExERkVuWK1cuPv74YwoUKECDBg2oUqUKe/bs8TpWyFEhExERkduSIUMG1q9fz8iRI9m8eTNlypRh//79XscKKSpkIiIicttSpkxJhw4dWLt2LRcuXKBVq1bafXkTVMhEREQkzhQsWJA33niDL774gmnTpnkdJ2SokImIiEicatu2LaVLl6Z3796cO3fO6zghQYVMRERE4lRYWBhvvvkm+/fvp2HDhhw8eNDrSEFPhUxERETi3EMPPcT48eNZvnw5OXLkIGvWrOTIkYNcuXLRqVMndu3a5XXEoJLE6wAiIiKSMLVo0YIKFSqwcOFCfvrpJ6Kiojh16hTjxo1j9OjRzJgxg8cff9zrmEFBhUxEREQCplChQhQqVOgfyw4fPky9evVo06YNOXPmJCwsjIwZM5I3b16PUnpPuyxFREQkXmXNmpXJkydz7tw5ypcvT9myZcmfPz89evTg0qVLXsfzhEbIREREJN4VKlSIH374gfXr15MkSRIWL17M8OHD+fHHHxk1ahQ5cuTwOmK8UiETERERT9xzzz3cc889ADz22GOUKFGCLl26cM899zB58mSefPJJjxPGn6DaZWlmDc1srJnNMLOHvc4jIiIi8adDhw7s2rWL8uXL06pVKzZt2uR1pHgT8EJmZuPN7KiZbbtqeW0z22lmu8ysN4Bzbq5z7jmgHfBEoLOJiIhIcMmTJw+zZs0iQ4YMVKpUiSlTpngdKV7ExwjZRKB29AVmFg6MBOoAhYGnzKxwtKf09a8XERGRRObuu+9m/fr1lC1blubNm7NmzRqvIwVcwAuZc+4r4PerFpcDdjnnfnbORQHTgQbmMwRY5JzbGOhsIiIiEpzuvvtu5s6dS65cuXj44Yfp2bNngr4Mk1fHkGUH9kd7fMC/rDNQA2hsZu2u9UIza2Nm681s/bFjxwKfVERERDxxxx138MUXX9CgQQOGDRtG+fLlOXz4sNexAiKoDup3zv3XOXefc66dc270dZ4zxjlXxjlXJkuWLPEdUUREROJR3rx5+fDDD1m0aBG7d+/m6aef5q+//vI6VpzzqpAdBHJGe5zDv0xERETk/1OrVi3effddli9fTpcuXXDOXfe5O3bsYOfOnfGY7vZ5NQ/ZOiC/md2Dr4g9CTztURYREREJAc2aNWPbtm0MGzaMEydOMHTo0GtOIHvvvfcCxFjagk3AC5mZTQOqAJnN7ADQzzk3zsw6AZ8B4cB459z3gc4iIiIioW3o0KGkTJmSoUOH8t133/Hdd9+RJMn/6kwolbDo4uMsy6ecc3c755I653I458b5l3/qnCvgnMvnnBt4M+9pZvXMbMzJkycDE1pERESCkpkxYMAApk2bxg8//MD48eP/sf7QoUMeJbs9QXVQf2w55xY459qkT5/e6ygiIiLigYYNG1KpUiVeeukl9u//38QNoXbs2BUhWchEREQkcTMzxo0bx4ULF3jggQeoVq0ae/fu/buQRUREeJzw5qiQiYiISEgqWLAgM2fOJFu2bHz77be0b9+eHTt2AJA9e3aP090cFTIREREJWbVr1+brr79m8ODBLF68mLfffhuAsLDQqjihlVZERETkGjp27EjdunW9jnHLVMhEREQk5IWHh/PRRx/RtWtXr6PckpAsZJr2QkRERK6WPHly3nrrLR544AGvo9y0kCxkmvZCREREEpKQLGQiIiIiCYkKmYiIiIjHVMhEREREPKZCJiIiIuIxFTIRERERj4VkIdO0FyIiIpKQhGQh07QXIiIikpCEZCETERERSUhUyEREREQ8pkImIiIi4jEVMhERERGPqZCJiIiIeMycc15nuGVmdgz4JcAfkxk4HuDPkPilbZrwaJsmPNqmCY+2KeR2zmW51oqQLmTxwczWO+fKeJ1D4o62acKjbZrwaJsmPNqmMdMuSxERERGPqZCJiIiIeEyF7MbGeB1A4py2acKjbZrwaJsmPNqmMdAxZCIiIiIe0wiZiIiIiMdUyGJgZrXNbKeZ7TKz3l7nkdgxs/FmdtTMtkVbltHMvjCzn/z/3uFfbmb2X/823mJmpb1LLtdiZjnNbLmZ/WBm35vZv/3LtU1DlJmlMLO1Zvadf5u+6l9+j5l96992M8wsmX95cv/jXf71eTz9AnJdZhZuZpvMbKH/sbZpLKmQXYeZhQMjgTpAYeApMyvsbSqJpYlA7auW9QaWOufyA0v9j8G3ffP7b22Ad+Mpo8TeJaC7c64wcD/Q0f+/RW3T0HUBqOacKwGUBGqb2f3AEOAt51wEcAJo5X9+K+CEf/lb/udJcPo3sD3aY23TWFIhu75ywC7n3M/OuShgOtDA40wSC865r4Dfr1rcAPjAf/8DoGG05ZOczzdABjO7O16CSqw45w455zb675/G98s+O9qmIcu/bc74Hyb13xxQDfjIv/zqbXplW38EVDczi5+0EltmlgN4FHjf/9jQNo01FbLryw7sj/b4gH+ZhKa7nHOH/PcPA3f572s7hxD/bo1SwLdom4Y0/66tzcBR4AtgN/CHc+6S/ynRt9vf29S//iSQKV4DS2z8B+gJXPY/zoS2aaypkEmi43ynFuv04hBjZmmA2UBX59yp6Ou0TUOPc+4v51xJIAe+PRKFvE0kt8PM6gJHnXMbvM4SqlTIru8gkDPa4xz+ZRKajlzZbeX/96h/ubZzCDCzpPjK2BTn3Bz/Ym3TBMA59wewHKiAb/dyEv+q6Nvt723qX58e+C1+k8oNVALqm9lefIf4VAPeRts01lTIrm8dkN9/hkgy4ElgvseZ5NbNB5r57zcD5kVb/qz/zLz7gZPRdoNJEPAfVzIO2O6cezPaKm3TEGVmWcwsg/9+SqAmvmMDlwON/U+7epte2daNgWVOk2gGFedcH+dcDudcHnx/L5c555qibRprmhg2Bmb2CL594uHAeOfcQG8TSWyY2TSgCpAZOAL0A+YCM4FcwC9AE+fc7/4/9u/gOyvzHNDCObfeg9hyHWZWGVgJbOV/x6a8iO84Mm3TEGRmxfEd0B2Ob2BgpnNugJnlxTe6khHYBDzjnLtgZimAyfiOH/wdeNI597M36eVGzKwK0MM5V1fbNPZUyEREREQ8pl2WIiIiIh5TIRMRERHxmAqZiIiIiMdUyEREREQ8pkImIiIi4jEVMhFJ1Mzsff/Fym/2dXnMbFsgMolI4pPkxk8REUm4nHOtvc4gIqIRMhFJFPwjWjvMbIqZbTezj8wslZl9aWZlzCy3mf1kZpnNLMzMVprZw/6LYL9hZuvMbIuZtfX6u4hIwqMRMhFJTAoCrZxzq81sPNDhygrn3C9mNgR4F1gL/OCc+9zM2uC7/FJZM0sOrDazz9HFzEUkDmmETEQSk/3OudX++x8ClaOvdM69D6QD2gE9/IsfxndtzM34LteUCcgfL2lFJNHQCJmIJCZXj2r947GZpQJy+B+mAU4DBnR2zn121XPzBCijiCRCGiETkcQkl5lV8N9/Glh11fohwBTgFWCsf9lnQHszSwpgZgXMLHV8hBWRxEOFTEQSk51ARzPbDtyB73gxAMzsIaAsMMQ5NwWIMrMWwPvAD8BG/zQX76G9CyISx8w5HZcqIgmffxfjQudcUa+ziIhcTSNkIiIiIh7TCJmIiIiIxzRCJiIiIuIxFTIRERERj6mQiYiIiHhMhUxERETEYypkIiIiIh5TIRMRERHx2P8DjJaF1YczzNEAAAAASUVORK5CYII=\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "f, ax = plt.subplots(figsize=(10, 6))\n", "ax.plot(spectrum.flux.value, 'k-')\n", "ax.set_title(\"Boxcar 1D extracted spectrum\")\n", "ax.set_xlabel(r\"pixel\")\n", "ax.set_ylabel(\"Flux Density [Jy]\")\n", "ax.set_yscale(\"log\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## About this notebook\n", "\n", "**Author:** Ivo Busko, JWST\n", "**Updated On:** 2022-12-05" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "***" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Top of Page](#top)\n", "\"Space " ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.12" } }, "nbformat": 4, "nbformat_minor": 2 } astropy-specreduce-05be828/notebook_sandbox/jwst_boxcar/jwst_boxcar_algorithm.ipynb000066400000000000000000011775501510537250300312340ustar00rootroot00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Spectral extraction tests (JDAT-1855)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

Note: This is an experimental notebook created for an older version of specreduce. To learn the package's current best practices, please visit our other notebooks.

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notebook contains the following sections:\n", "\n", "- Use specreduce's BoxcarExtract. Originally, doesn't work due to the absence of a Trace object and bugs in the code. Fixing bugs and using the trace function from kosmos (slightly modified), we can produce a 1d extraction from s2d data set at https://stsci.app.box.com/s/ywnauuvan1job9jcsqnzjihv6hm1uono (files also live in /eng/ssb/). \n", "\n", "- Adapt boxcar extraction code from https://github.com/spacetelescope/jdat_notebooks/tree/main/notebooks/MIRI_LRS_spectral_extraction\n", "\n", "- Use the adapted code to extract from same s2d data set as above. \n", "\n", "- Use the adapted code to extract from s3d data set at https://data.science.stsci.edu/redirect/JWST/jwst-data_analysis_tools/IFU_optimal_extraction/\n", "\n", "- Presents a simplified boxcar extraction computation that has the minimal code to extracxt from both 2-D and 3-D rectified data using numpy slices." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "import os\n", "\n", "import numpy as np\n", "\n", "import matplotlib.pyplot as plt\n", "import matplotlib as mpl\n", "from matplotlib.colors import LogNorm\n", "%matplotlib inline\n", "\n", "from astropy.io import fits\n", "from astropy.table import Table\n", "from astropy.visualization import simple_norm\n", "from astropy.utils.data import download_file\n", "\n", "from jwst import datamodels\n", "\n", "from specreduce.extract import BoxcarExtract\n", "\n", "import ccdproc\n", "\n", "from pathlib import Path\n", "import tempfile\n", "from zipfile import ZipFile" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ingest s2d data" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# data is taken from s2d file. x1d is used for comparison with pipeline extraction.\n", "\n", "zipped_datapath = Path(download_file('https://stsci.box.com/shared/static/qdj79y7rv99wuui2hot0l3kg5ohq0ah9.zip', cache=True))\n", "\n", "data_dir = Path(tempfile.gettempdir())\n", "\n", "with ZipFile(zipped_datapath, 'r') as sample_data_zip:\n", " sample_data_zip.extractall(data_dir)\n", "\n", "s2dfile = str(data_dir / \"nirspec_fssim_d1_s2d.fits\")\n", "x1dfile = str(data_dir / \"nirspec_fssim_d1_x1d.fits\")" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "DEBUG:jwst.datamodels.util:Opening C:\\Users\\Duy\\AppData\\Local\\Temp\\nirspec_fssim_d1_s2d.fits as \n" ] } ], "source": [ "# use a jwst datamodel to provide a good interface to the data and wcs info\n", "s2d = datamodels.open(s2dfile)\n", "image = s2d.slits[0].data" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0.5, 1.0, 'slit[0]')" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# display s2d image\n", "norm_data = simple_norm(image, \"sqrt\")\n", "plt.figure(figsize=(15, 15))\n", "plt.imshow(image, norm=norm_data, origin=\"lower\")\n", "plt.title(\"slit[0]\")" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "data": { "image/png": "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3bs3V1xxBdu3b6d3794sWrTI70gJTSUhIlHllFNOYebMmWzdupXSpUvTr18/hg0bxvr16/2OlpBUEiISlfLnz88///lPPvvsMwYNGsR5553Hv//9b79jJRyVhIhErXvuuYf169ezadMmUlJSSEtLY9OmTX7HSigqCRGJWrly5aJy5cqkpKTw/vvvA3DmmWfSoEEDtm7d6nO6xKCSEJGYUK5cOebNm8ctt9zCF198Qbt27di5c6ffseKeSkJEYka9evUYN24cL730EitXruS8885j9+7dfseKayoJEYk57dq1Y+7cuWzdupX777+fI0eO+B0pbqkkRCQmNWrUiB49evDMM89Qt25dNm7c6HekuKSSEJGY9dxzz/Hyyy+zevVqRo0a5XecuKSSEJGYZWZ07tyZq666ijfffJPDhw/7HSnuqCREJOZ169aNn376iddff93vKHEnLkpC55MQSWytWrXi3HPP5e677+b9999ny5Yt2js7h8RFSeh8EiKJLSkpiYkTJ/L7779z+eWXU6FCBS6++GLeeecdv6PFvLgoCRGRevXqsXXrVmrUqPHXsNtuu40PPvjAx1SxTyUhInGjQIECLFq0iF27drF06VJy585Ny5YtWblypd/RYpZKQkTiSpEiRShRogT16tVj5cqV5M6dmx49evDEE09o66cToJIQkbhVrFgx7rjjDn7++Wfuvvtuqlevzo8//uh3rJiikhCRuDZ8+HC2bNnClVdeyfr167nuuutwzvkdK2aoJEQkIUyePJk+ffqwcOFCXn/9dRVFFqkkRCQhFC5cmBEjRlCtWjWuu+46OnTowNGjR/2OFfVUEiKSMHLnzs2iRYvo3bs3b7zxBkOHDvU7UtTL5XcAEZFIKlasGGPGjGH//v08+OCDNG3alIsuusjvWFFLcxIiknDMjGeffZby5ctzxRVX8PLLL/sdKWqpJEQkIeXLl4/x48fz+++/07VrV4YMGcJ3333nd6yoo5IQkYTVokUL1qxZQ6FChRg6dKjWUWRAJSEiCa1mzZps27aN1q1bM2/ePG0aewyVhIgkvAIFCnDJJZfwww8//HUa1P379/ucKjqoJERE4K8tnCpVqoSZUahQIV5++WV+//13f4P5TCUhIgKcc845lC5d+m/Dunbtyrnnnsu+fft8SuU/lYSICIHNYhcvXsyUKVNYt24dM2bMoFOn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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# pipeline 1d extraction (for comparison)\n", "jpipe_x1d = Table.read(x1dfile, hdu=1)\n", "print(jpipe_x1d.columns)\n", "# plot\n", "fig, ax = plt.subplots(figsize=(6, 6))\n", "ax.plot(jpipe_x1d['WAVELENGTH'], jpipe_x1d['FLUX'], 'k-', label=\"jpipe_x1d\")\n", "ax.set_title(\"JWST Pipeline x1d extracted spectrum\")\n", "ax.set_xlabel(\"wavelength\")\n", "ax.set_ylabel(\"Flux Density [Jy]\")\n", "ax.set_yscale(\"log\")" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0.5, 1.0, 'slit[0] slice')" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# blow up of the region to be extracted\n", "plt.figure(figsize=(15, 15))\n", "plt.imshow(image[::,0:100], norm=norm_data, origin=\"lower\")\n", "plt.title(\"slit[0] slice\")" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "# extraction parameters based on image above\n", "ext_center = 27\n", "ext_width = 4\n", "bkg_offset = 6\n", "bkg_width = 2" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0.5, 1.0, 'Cross-dispersion Cut at Pixel=70')" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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JWjSpAmGDRuG4cOHY+jQob4Ye1VcXIyPPvoIb731FubNm4eSkhKkpqZi/PjxGD9+PLp27ep2imG3b98+9O/fH0VFRcjJyUHnzp3dTomIwixqbl/WBosy75k9ezb+9Kc/oWnTppgzZw569+7tdkq2evnll3HNNdcgNTX1yG3J0047zdfzK+3YsQOzZ8/GW2+9haVLl0JV0bdvX4wfPx6XXXZZjaY8iBaqiosvvhjvvPMOPv74Y2RkZLidEhE5gAuSU1QZNWoUvvzyS8TExGDAgAHIzMx0OyVb5eTkICkpCatXr8bkyZNx5pln+rogA4CmTZvimmuuwaeffor169dj8uTJKCkpwcSJEzFs2LCQ50iKJlOmTMGsWbPwr3/9y56CbNw4Y3OSGzEtGvfuOIx71/mczz3X2JzmVnst8XFfZlFGEalnz57Izs5G7969MXbsWNxzzz0oKytzOy1b5OXl+XLsVKjatWuHSZMmIS8vD8888wy+/fZbfPrpp26nZatFixbh9ttvx+jRo3HbbbfZc9CePY3NSW7EtKhnq57o2aqn43H37zc2p7nVXkt83Jd5+5Ii2sGDB/GXv/wF06ZNw4UXXojXX38dDRo0cDutWispKUHDhg1x00034dFHH3U7nYh34MABdOzYET169MD8+fPdTscWhYWFSEtLQ+vWrfHNN99EdX+m0HFKDArg7UuKWnXq1MHLL7+Mf//735gzZw5OP/10hHOy4HBbtWoVDh486LlxcuGSmJiIm2++GQsWLMDy5cvdTsey4uJijBw5EqWlpfjggw9YkBHRUViUUcQTEUycOBHz5s3DunXrkJ6eji+++MLttGolLy8PAFiU1cD111+PBg0aYPLkyW6nYomqYsKECfjuu+8wY8YM+58uHTXq9wUWneJGTItGZY7CqMzoytmKqGyvj/syizKKGueccw6+/fZbJCUl4ayzzsIrr7zidko1lpeXhwYNGvhiuge7JCUl4dprr8WsWbOwdu1at9OptaeeegozZszAAw88gPPOO8/+AP37G5uT3IhpUf92/dG/nfM5n3++sTnNrfZa4uO+zDFlFHV27tyJsWPHYuHChZg4cSImT54cNU8vnn766YiNjcVnn33mdipRpaioCJ07d8Z1112Hp556yu10amzJkiUYPHgwhg8fjtmzZ3PpIyIf45gy8pQmTZpg3rx5uPnm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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Plot along cross-disperion cut showing the extraction parameters\n", "fig, ax = plt.subplots(figsize=(10, 6))\n", "y = np.arange(image.shape[0])\n", "ax.plot(y, image[:,70], 'k-')\n", "mm = np.array([ext_center, ext_center])\n", "mm_y = ax.get_ylim()\n", "\n", "ax.plot(mm, mm_y, 'b--')\n", "ax.plot(mm - ext_width/2., mm_y, 'g:')\n", "ax.plot(mm + ext_width/2., mm_y, 'g:')\n", "\n", "ax.plot(mm - bkg_offset - bkg_width/2., mm_y, 'r:')\n", "ax.plot(mm - bkg_offset + bkg_width/2., mm_y, 'r:')\n", "ax.plot(mm + bkg_offset - bkg_width/2., mm_y, 'r:')\n", "ax.plot(mm + bkg_offset + bkg_width/2., mm_y, 'r:')\n", "\n", "ax.set_title(\"Cross-dispersion Cut at Pixel=70\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## specreduce's BoxcarExtract test with s2d data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The Spectral Trace is a new feature that was added to Specreduce. For the development of this notebook, this trace was unavailable at the time of writing. We borrow the trace object from jradavenport's kosmos package as a substitute while we develop Specreduce's own Trace object" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "if not (Path.cwd() / 'kosmos').is_dir():\n", " kosmos_zippath = Path(download_file('https://github.com/jradavenport/kosmos/archive/refs/heads/main.zip', cache=True))\n", " with ZipFile(kosmos_zippath, 'r') as kosmos_zip:\n", " kosmos_zip.extractall(Path.cwd())\n", " (Path.cwd() / 'kosmos-main').rename('kosmos')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We also have to patch kosmos' apextract due to a bug with 2D numpy array support. Kosmos seems to assume the image has a `.data` attribute, which is true of CCDData, but not of 2D numpy arrays." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "14651" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "apextract_path = Path.cwd() / 'kosmos' / 'kosmos' / 'apextract.py'\n", "\n", "apextract_module = apextract_path.read_text()\n", "apextract_path.write_text(apextract_module.replace('.data', ''))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can import kosmos to create our Trace" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "from kosmos import kosmos" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "scrolled": false }, "outputs": [], "source": [ "# build a trace object\n", "class Trace:\n", " def __init__(self, image):\n", " self.trace = kosmos.trace(image, Saxis=0)\n", "\n", "# Define the Trace\n", "trace = Trace(image)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "# extract (need to fix BoxcarExtract before this can run)\n", "boxcar = BoxcarExtract()\n", "boxcar.apwidth = ext_width\n", "boxcar.skysep = int(bkg_offset - bkg_width/2 - ext_width/2)\n", "boxcar.skywidth = bkg_width\n", "\n", "spectrum, bkg_spectrum = boxcar(image, trace)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "# print(spectrum.wavelength)\n", "\n", "# this one crashes with \"UnitConversionError: 'pix' and 'Angstrom' (length) are not convertible\"" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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tWu57rrrco52ZIuMjHTJPnyyIPNl26ZPZ86KFYRa9zf37g04/kO/mjqVlv36sf611+g2dap9IVWpNG3alLfffpthw4bRokUL3njjDTp37syNN95IZmYmHTp0YNSoUcycOZOAgABuvfVWsrKy6Nq1Kz/88APDhw9n+/bttGnThoCAAEaMGMHYsWMZMWIErVq1IiIigg4dOtj9MtU/HQSic92PspblMMZMBaYCxMbGOj1a+/777y9w3Zw5c8jKyipWUFW0ZcuW0b1795z7gYGBvP7664SGhtKlSxe6dOnyj+dUr169wO3Vr1/fHTGLJXex161bN7p168aJEyfYtm0bkydPZs+ePSxdupSLLrqIGjVqEBYWxsCBA+ncuTPR0dEEBgYSHx9Pw4YNcwrO8mLTpk0APPHEE+5rf40xPnu76KKLjK95/vbbzft+fub31183X1933Xnr0lNSzD1+fublESNsSufbtmzZYncE5WL5/Z8Cq40XtD95bzi+4O4CGgAVgfVAy4Ie76r2KyYmxgwZMsQl21LGnDp1ylx77bUGyLm99dZbdsfymB07dpj//e9/5qabbjJXXHHFeb+H7JuImLZt25oRI0aYCRMmmDVr1pjMzEy7o7vVo48+agCTlJRUqu0U1n5pD5kHnT59mtcWLaJrv37cOW4cjBt33vqAoCCWtmhBgzVruPn774nq2dOmpEqp4jLGZIrIWGAh4A9MM8Zsdvd+/fz8tIfMRVJTU7nooovYtWsXAK+++iq33347YWFhNifznMaNG9O4cWMGDx4MOM4Y3b17N/v27SM+Pp569erxxx9/8Msvv/Dpp5+SmJjIc889B0Dr1q2pX78+kZGRHDt2jCNHjtCmTRtuuukmIiMjqVq1KgkJCaSmplKhQgX8/PyoXLkyQUFBOTd3nmBgrGvkbt++nZiYGPbt20dmZiaVK1dm586dREVFsXLlSr755hvi4uI4d+4cYWFh7N69m8TERHr27OnW8bpakHnI78uWsbx7dwYBl9xxR4GP6969O5dNnkxQr14kJyQQHBpa4GOVUt7FGLMAWFDkA13I399fCzIX+N///seQIUMAeOGFF2jWrBl9+vQp92cg1qpVi1q1ap03hrFXr145P8fFxXHppZdy6NAhNm7cSHx8PL///jsVK1akdu3azJw5k8mTJzu1r4CAANq2bUvz5s0JCAigQoUKVKxYkbZt27Jr1y727NlDUFAQbdq0IT09ne7du7Nr1y4yMjIAxxjb9PR0ABYuXMihQ4c4e/YsqamppKWlsXr1as6dO1dkjqZNmxIZGUndunVJSkqiQ4cO1KtXL2c8oLtoQeYhb7zxBiOBjhUq0NUaN5afl198kXkLFtBl3z4mfPFFTgOhlFL50YKs9M6dO5fT1oaFhfHAAw+U+0LMWY0bN+bVV1/lpptu4uDBg9StW/e89WfOnOHrr7/m9OnTAFStWhURISsrC39/f86ePZtzO378OMuXL+enn34iKyuLzMxMzpw5Q0pKCiJC/fr12bt3r1NFVVBQEDVr1iQwMJAaNWoQGBjIf/7zH+rUqUPFihXx8/OjQYMGBAQEkJiYSIMGDdi/fz+tWrX6xwkTnqIFmYcE/PADs3r14pWZMws9c6VKaCi37dnDg3XrsmjRIi3IlFKF0oKs9D7++GMALr74YqZPn67FWDENHDiQG2+8Md/pMkJCQhg0aFCJt52RkcGePXsIDQ2ldu3aHDx4kEOHDhEWFsa6deto3LgxQUFBpKamkpKSQoUKFYiPj6dbt27FPrzYvn37Eud0BS3IPCBh504+PHGCH0SoWrNmkY8XER5s0oQ2n3+OycpC9NRjpVQB/Pz8nOoxUPn74osvcsaJLVq0iMDAQLsj+SR3zV0WEBBAkyZNcu5HRkbmTDPRsGFDt+zTLvo1wM2yTp1ifVwcXQFz441OP69ds2ZUTk9nez6zMyulVDbtISuZZcuW0bVrVwYMGEBkZCRLly7VYkzZSgsyN0rcuZOT4eGs6tmTLVWr0r5fP6efW3/CBLoCC/Wi4z5jz549tGrVyu4Y//Dll1/y9NNPAzBkyBDmzp37j8fMmDGDsWPHui1DQfvduHGjHpYvJS3InLdq1SruvfdennjiCS677DK2bdvGAw88wKZNm7jwwgvtjqfKOT1kWVrWoYIjx44REBCQc3p0SkoK/e+8k9uyspgJTJ06tdBJA/OqX78+zZo1Y/5XXzEuz/QYShUkMzMz5xqY2V566SW+/vprmxIVrnXr1hw4cIB9+/YVa+Z69TctyIp28uRJdu7cSa9evXIuY9avXz9mzJhBtWrV7A2nlEV7yEph02+/sb9SJbb5+1OvTh3GN23K5jp1OPDzzzz+3//y0y+/EDhrFuuNYeDAgcXe/qNNmzLrhx9IOnTIDemVO2RmZjJo0CCaN2/ODTfcQEpKCgBLly6lXbt2tG7dmmHDhpGWlsaqVato06YNqampJCcn07JlSzZt2kRWVhb3338/rVq1ok2bNrz55psAPP3003To0IFWrVoxcuTI7MlIueyyyxg/fjyxsbG8/vrr5+XZvn07lSpVomausYtLliwhNjaWCy64IOfae7l9++23dOnShRMnTrBz5046d+5M69ateeyxx6hSpQoAhw8f5pJLLqFt27a0atWKX3/9FSBnPcDcuXPP6/0qaL99+vRh9uzZpfm1l2v+/v46hqwQZ8+epVOnTnTs2JH4+Hi+/PJL4uLi+PLLL7UYU15FC7ISMsYw9D//4V8VK/LfkBCCKlRgVFISrx09yks33MDYV17hmcsv59Zbby3xPhpfcgkLgHXWHzvl/bZt28bo0aPZunUroaGhvPPOO6SmpjJkyBA+/fRTNm7cSGZmJu+++y4dOnSgb9++PPbYYzz44IPcdttttGrViqlTp7Jnzx7WrVvHhg0bcs5QGjt2LKtWrWLTpk2cPXv2vKImPT2d1atXc999952XZ9myZf84c2jPnj2sXLmSb7/9llGjRp13kfJ58+bxwgsvsGDBAmrWrMk999zDPffcw8aNG4mKisp53Mcff8w111zDunXrWL9+PW3bti3yd1PQfmNjY3MKOlV8OjFswY4cOcKVV15JXFwcoaGh9OrViz59+tg2rYFShdGCrIR+nTuX1atXM3zSJKYfPsyRM2folpqK/8iRLD5xgp9DQ7nznXdKtY9mw4YxTIQft293Uepy5rLLYMYMx88ZGY77H33kuJ+S4rj/6aeO+wkJjvtffOG4f+KE4/78+Y77R444tcvo6Gi6desGwG233cZvv/3Gtm3baNCgQc4Fae+44w5++eUXAB5//HEWL17M6tWrefDBBwFHT9Jdd92Vc+ixRo0aAPz444906tSJ1q1b88MPP7B589+TwN9000355jl8+DDh4eHnLRs4cCB+fn40adKEhg0b8tdffwHwww8/8OKLL/Ltt9/mHF5fvnw5N1ono+T+ctGhQwemT5/Ok08+ycaNGwkJCSnyd1PQfmvVqsUh7QUuMT1k+U8nT55k+PDhtGzZkuXLl3PLLbeQkJDAggULdEoL5bX0nVkCO2bNInbgQD6qVImbb7qJ4ODgnLNzJk2aRO/776fjihVE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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# plot \n", "\n", "f, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 5))\n", "# ax.plot(spectrum.wavelength.values, spectrum.flux.values, 'k-', label=\"boxcar\")\n", "ax1.plot(spectrum.flux.value, 'k-', label=\"boxcar\")\n", "ax1.plot(spectrum.flux.value-bkg_spectrum.flux.value, ':', color='r', label=\"boxcar (bkgsub)\")\n", "ax2.plot(bkg_spectrum.flux.value, 'k-')\n", "# ax.plot(waves_boxcar_bkgsub[gpts], ext1d_boxcar_bkgsub[gpts], 'k:', label=\"boxcar (bkgsub)\")\n", "# ax.plot(jpipe_x1d['FLUX'], 'k-', label=\"jpipe_x1d\")\n", "ax1.set_title(\"Fixed boxcar 1D extracted spectrum\")\n", "ax1.set_xlabel(r\"pixel\")\n", "ax1.set_ylabel(\"Flux Density [Jy]\")\n", "ax1.set_yscale(\"log\")\n", "ax2.set_title(\"Background spectrum\")\n", "ax2.set_xlabel(r\"pixel\")\n", "ax2.set_ylabel(\"Flux Density [Jy]\")\n", "ax2.set_yscale(\"linear\")\n", "ax1.legend()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Extraction code from MIRI LRS extraction notebook" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Functions below are adapted from https://github.com/spacetelescope/jdat_notebooks/tree/main/notebooks/MIRI_LRS_spectral_extraction \n", "\n", "They were rid of the extra code necessary to support wavelength-dependent extraction, and PSF-weighted extraction. These require that a gWCS be present in the input data, which doesn't seem to be the case with s2d files.\n", "\n", "These functions were modified to support both 2d and 3d extractions. Serious refactoring is still required to make this into production-level code." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "def get_boxcar_weights(center, hwidth, npix):\n", " \"\"\"\n", " Compute the weights given an aperture center, half widths, and number of pixels\n", " \"\"\"\n", " \n", " # TODO: this code may fail when regions fall partially or entirelly outside the image.\n", " \n", " weights = np.zeros((npix))\n", "\n", " # 2d\n", " if type(npix) is not tuple:\n", " # pixels with full weight\n", " fullpixels = [max(0, int(center - hwidth + 1)), min(int(center + hwidth), npix)]\n", " weights[fullpixels[0] : fullpixels[1]] = 1.0\n", "\n", " # pixels at the edges of the boxcar with partial weight\n", " if fullpixels[0] > 0:\n", " weights[fullpixels[0] - 1] = hwidth - (center - fullpixels[0])\n", " if fullpixels[1] < npix:\n", " weights[fullpixels[1]] = hwidth - (fullpixels[1] - center)\n", " # 3d\n", " else:\n", " # pixels with full weight\n", " fullpixels_x = [max(0, int(center[1] - hwidth + 1)), min(int(center[1] + hwidth), npix[1])]\n", " fullpixels_y = [max(0, int(center[0] - hwidth + 1)), min(int(center[0] + hwidth), npix[0])]\n", " weights[fullpixels_x[0]:fullpixels_x[1], fullpixels_y[0]:fullpixels_y[1]] = 1.0\n", "\n", " # not yet handling pixels at the edges of the boxcar\n", "\n", " return weights\n", "\n", "\n", "# def ap_weight_images(center, width, bkg_offset, bkg_width, image_shape, waves, wavescale=None):\n", "def ap_weight_images(center, width, disp_axis, crossdisp_axis, bkg_offset, bkg_width, image_shape):\n", "\n", " \"\"\"\n", " Create a weight image that defines the desired extraction aperture\n", " and the weight image for the requested background regions.\n", " \n", " The disp_axis and crossdisp_axis parameters could perhaps be derived from the\n", " jdatamodel wcs and/or meta instances. Since we have test data that lacks the \n", " these, for now we pass then explictly via calling sequence.\n", "\n", "\n", " Parameters\n", " ----------\n", " center : float\n", " center of aperture in pixels\n", " width : float\n", " width of apeture in pixels\n", " disp_axis : int\n", " dispersion axis\n", " crossdisp_axis : int or tuple\n", " cross-dispersion axis\n", " bkg_offset : float\n", " offset from the extaction edge for the background\n", " never scaled for wavelength\n", " bkg_width : float\n", " width of background region\n", " never scaled with wavelength\n", " image_shape : tuple with 2 or 3 elements\n", " size (shape) of image\n", " waves : array\n", " wavelegth values NOT USED\n", " wavescale : float\n", " scale the width with wavelength (default=None)\n", " wavescale gives the reference wavelenth for the width value NOT USED\n", "\n", " Returns\n", " -------\n", " wimage, bkg_wimage : (2D image, 2D image)\n", " wimage is the weight image defining the aperature\n", " bkg_image is the weight image defining the background regions\n", " \"\"\"\n", " wimage = np.zeros(image_shape)\n", " bkg_wimage = np.zeros(image_shape)\n", " hwidth = 0.5 * width\n", " \n", " if len(crossdisp_axis) == 1:\n", " # 2d\n", " image_sizes = image_shape[crossdisp_axis[0]]\n", " else:\n", " # 3d\n", " image_shape_array = np.array(image_shape)\n", " crossdisp_axis_array = np.array(crossdisp_axis)\n", " image_sizes = image_shape_array[crossdisp_axis_array]\n", " image_sizes = tuple(image_sizes.tolist())\n", " \n", " # loop in dispersion direction and compute weights\n", " # \n", " # This loop may be removed or highly cleaned up, replaced by \n", " # vectorized operations, when the extraction parameters are the \n", " # same in every image column. We leave it in place for now, so \n", " # the code may be upgraded later to support height-variable and \n", " # PSF-weighted extraction modes.\n", "\n", " for i in range(image_shape[disp_axis]):\n", "# if wavescale is not None:\n", "# hwidth = 0.5 * width * (waves[i] / wavescale)\n", "\n", " if len(crossdisp_axis) == 1:\n", " wimage[:, i] = get_boxcar_weights(center, hwidth, image_sizes)\n", " else:\n", " wimage[i, ::] = get_boxcar_weights(center, hwidth, image_sizes)\n", " \n", " # bkg regions (only for s2d for now)\n", " if (len(crossdisp_axis) == 1) & (bkg_width is not None) & (bkg_offset is not None):\n", " bkg_wimage[:, i] = get_boxcar_weights(\n", " center - hwidth - bkg_offset, bkg_width, image_shape[0]\n", " )\n", " bkg_wimage[:, i] += get_boxcar_weights(\n", " center + hwidth + bkg_offset, bkg_width, image_shape[0]\n", " )\n", " else:\n", " bkg_wimage = None\n", "\n", " return (wimage, bkg_wimage)\n", "\n", "\n", "# def extract_1dspec(jdatamodel, center, width, bkg_offset, bkg_width, wavescale=None):\n", "def extract_1dspec(image, jdatamodel, center, width, disp_axis, crossdisp_axis, bkg_offset, bkg_width):\n", "\n", " \"\"\"\n", " Extract the 1D spectrum using the boxcar method.\n", " Does a background subtraction as part of the extraction.\n", " \n", " We need to pass both the data model and the image array separately because\n", " different types of data format hold the image in different attributes. This\n", " api should evolve as we deal with other types of data model.\n", " \n", " The disp_axis and crossdisp_axis parameters could perhaps be derived from the\n", " jdatamodel wcs and/or meta instances. Since we have test data that lacks the \n", " these, for now we pass then explictly via calling sequence.\n", "\n", "\n", " Parameters\n", " ----------\n", " image : ndarray\n", " array with 2-D spectral image data\n", " jdatamodel : jwst.DataModel\n", " jwst datamodel with the 2d spectral image\n", " center : float\n", " center of aperture in pixels\n", " width : float\n", " width of apeture in pixels\n", " disp_axis : int\n", " dispersion axis\n", " crossdisp_axis : int or tuple\n", " cross-dispersion axis\n", " bkg_offset : float\n", " offset from the extaction edge for the background\n", " never scaled for wavelength\n", " bkg_width : float\n", " width of background region\n", " never scaled with wavelength\n", " wavescale : float\n", " scale the width with wavelength (default=None)\n", " wavescale gives the reference wavelenth for the width value NOT USED\n", "\n", " Returns\n", " -------\n", " waves, ext1d : (ndarray, ndarray)\n", " 2D `float` array with wavelengths\n", " 1D `float` array with extracted 1d spectrum in Jy\n", " \"\"\"\n", "# # should be determined from the gWCS in cal.fits\n", "# image = np.transpose(jdatamodel.data)\n", "# grid = grid_from_bounding_box(jdatamodel.meta.wcs.bounding_box)\n", "# ra, dec, lam = jdatamodel.meta.wcs(*grid)\n", "# lam_image = np.transpose(lam)\n", "\n", "# # compute a \"rough\" wavelength scale to allow for aperture to scale with wavelength\n", "# rough_waves = np.average(lam_image, axis=0)\n", "\n", " # images to use for extraction\n", " wimage, bkg_wimage = ap_weight_images(\n", " center,\n", " width,\n", " disp_axis, \n", " crossdisp_axis,\n", " bkg_width,\n", " bkg_offset,\n", " image.shape\n", " )\n", "# rough_waves,\n", "# wavescale=wavescale,\n", "# )\n", "\n", " # select weight images\n", " if bkg_wimage is not None:\n", " ext1d_boxcar_bkg = np.average(image, weights=bkg_wimage, axis=0)\n", " data_bkgsub = image - np.tile(ext1d_boxcar_bkg, (image.shape[0], 1))\n", " else:\n", " data_bkgsub = image\n", " \n", " # extract. Note that, for a cube, this is arbitrarily picking one of the\n", " # spatial axis to collapse. This should be handled by the API somehow.\n", " ext1d = np.sum(data_bkgsub * wimage, axis=crossdisp_axis)\n", "\n", " # convert from MJy/sr to Jy\n", " ext1d *= 1e6 * jdatamodel.meta.photometry.pixelarea_steradians\n", "\n", " # compute the average wavelength for each column using the weight image\n", " # this should correspond directly with the extracted spectrum\n", " # wavelengths account for any tiled spectra this way\n", "# waves = np.average(lam_image, weights=wimage, axis=0)\n", "\n", "# return (waves, ext1d, data_bkgsub)\n", " return (ext1d, data_bkgsub)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Extraction code test with s2d data" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0.5, 1.0, 'Fixed boxcar backgound weight image')" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlAAAABbCAYAAAC8uruvAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAAPR0lEQVR4nO3de5RV5XnH8e/P4aZCxVsJihdIUEtTayiiSazxlnhpDNrYlGjRNHa5lkajbYwRkxqTFdOaVJM2VVMrCF7RgKmX6moEXV7aRrwERSQIEYgiSFBRNAZFn/7xviPb0zkzs5kz58yc8/ustdfs/b77nP0+795n5pn9vuccRQRmZmZm1n1bNboBZmZmZv2NEygzMzOzkpxAmZmZmZXkBMrMzMysJCdQZmZmZiU5gTIzMzMryQmUWR8m6XVJY2r8nIdIer6T+pD0oVoes6+TdIGkq7u570WSru/Bsf5U0pItfbyZ9Q0DGt0AMwNJK4ARwDuF4r0iYmhjWtRaIuK7tXqufC7/JiLmVjnWg8DetTqemTWG70CZ9R3HRsTQwvJCoxvU10hqa3QbzMzACZRZn9Y+nCZpkKQFks7K5W2S/lvShXl7F0lzJP1G0nJJXy48x9aSZkh6RdLTwP7dOPQxkp6VtE7S9yVtlZ9rK0nfkLRS0lpJ10raLtfdJenSwnFnSZpeaMOl+XGvSnpI0ta57ieS1uTyByT9YeE5Zki6Mj/3G8ChFf1zqKSFhe17JD1S2H5Q0nHd6KP3DctJOjm39SVJfy9phaQjCocelGPfIGmRpAn5cdcBuwN35OHX8yo7tnIINT/3VyU9KekNSdMkjZB0d37+uZK2L+zfWX/tKOkOSa9JekTSdyQ9VKjfJ/fRy5KWSPpch2ffzLrkBMqsH4iIt4C/Ar4t6Q+A84E24OKc3NwBPAHsChwOnCPpyPzwbwIfzMuRwCndOOTxwARgPDAJ+GIu/0JeDgXGAEOBf811XwSmSDpM0knARODsXPdPwJ8AHwN2AM4D3s11dwNjgd8HHgduqGjLicDFwDDgoYq6nwNjJe0kaSCwL7CLpGE5QZsAPNiNPnqPpHHAFcBJwEhgu/yYos8As4DhwO3tfRARU4Bfs/lu4vcqn7+KzwKfBPYCjs19cgGwM+n39JcL+3bWX5cDbwAfIJ3n9861pG2Be4Ab82MnA1fkeM2srIjw4sVLgxdgBfA6sD4v/5HLA/hQYb+vAEuAV4CxuewA4NcVzzcVuCavPwscVag7DXi+k7ZExf5nAPPy+jzgjELd3sDbwIC8/VngOWAdcFAu2wp4E/jjbvTD8Hz87fL2DODaLh7zIPDnwIHAz4BbgKNISd6T3eyji4Dr8/qFwE2F/bYB3gKOKOw7t1A/Dniz4lwe0Ul7Dyn2f97/pML2HODKwvZZ7ddDZ/1FSqjfBvYu1H8HeCiv/yXwYMXj/w34ZqOvfy9e+uPiSeRmfcdxUWXiccFM0t2YORGxNJftQbrrsr6wXxspsQDYhZTUtFvZjbZU7r9L4blWVtQNIE2AX0W6y/MjYElEtN8t2gkYAvyq8iB5TtPFwF+Q7ra8W3jMqx20pSP3k5OSvP4K8AlgY96Grvuo6H39FRG/lfRSxT5rCuu/BYZIGhARm7poazUvFtbf7GB7KHTZX1uTzkWxv4rrewAHVPTBAOC6LWyzWUvzEJ5Z/3IFcCdwpKSDctlzwPKIGF5YhkXEMbl+NbBb4Tl278ZxKvdvn9D+AukPcbFuE5v/4F8MLAZGSvp8LlsH/I40hFjpRNIQ4RGkuyh75nIV9oku2tqeQB2c1+8nJVCfYHMC1VUfFa0GRrVv5KHAHbtoQ1FX7e2JzvrrN6RzMaqwf/E8PgfcX9EHQyPi9F5sr1nTcgJl1k9ImkKaR/QF0pyYmZKGAvOBDZK+lidrt0n6sKT2yeK3AFMlbS9pFGlIqCtfzfvvRprHdHMuvwn4W0mj87G/C9wcEZskHQz8NXAyae7NjyTtGhHvAtOBy/JE7jZJH5U0mDSvaSPwEmmobEs+TuB/SEOJE4H5EbGIfLcFeCDv01UfFc0GjpX0MUmDSEN26mC/al4kzQ/rDVX7KyLeAW4FLpK0jaR9SOei3Z3AXpKmSBqYl/3znDozK8kJlFk/IGl34IfAyRHxekTcCDwK/CD/4fw0sB+wnHTH52rSHQqAb5GG2paT5gh1Z8jmNuAxYAHwn8C0XD49P/6B/Hy/A86S9HvAtcCZEbEq0mcdTQOukSTgXGAh8AjwMnAJ6ffPtbltq4CnSZPCS4mIN0iTqRdFmmwP8L/AyohYm/fpqo+Kz7eIlGTOIt2Neh1YS0pcuuMfgG9IWi/p3LLxdKGr/jqTFNMa0nm6idzuiNgAfIo0efyFvM8lwOAat9GsJSiiN+82m5n1b/lO23rSpP3lDW5OKZIuAT4QEd1556WZleA7UGZmFSQdm4fBtiV9BMNC0rvl+rT8OU/7KpkInAr8tNHtMmtGTqDMzP6/SaRhrhdIn7k0OfrH7fphpHlQb5DmrV1KGo41sxrzEJ6ZmZlZSb4DZWZmZlaSEygzMzOzkur6SeSDNDiGsG09D2lmZma2RTbwyrqI2LmjuromUEPYlgN0eD0PaWZmZrZF5sbsql995SE8MzMzs5KcQJmZmZmV5ATKzMzMrCQnUGZmZmYl1XUS+cbdt+GZqRPreUgzMzOzLXP67KpVdU2g/mj4OuYfd1U9D2lmZma2RdpOr17nITwzMzOzkpxAmZmZmZXkBMrMzMyspLrOgfrlm8M5eOHx9TykmZmZ2Rb6ftWauiZQWy19i62PXF7PQ5qZmZnVnIfwzMzMzErqMoGStJuk+yQ9LWmRpLNz+Q6S7pG0NP/cvveba2ZmZtZ43bkDtQn4SkSMAw4EviRpHHA+MC8ixgLz8raZmZlZ0+sygYqI1RHxeF7fACwGdgUmATPzbjOB43qpjWZmZmZ9Sqk5UJL2BD4CPAyMiIjVuWoNMKK2TTMzMzPrm7qdQEkaCswBzomI14p1ERFAVHncaZIelfTo22zsUWPNzMzM+oJuJVCSBpKSpxsi4tZc/KKkkbl+JLC2o8dGxFURMSEiJgxkcC3abGZmZtZQ3XkXnoBpwOKIuKxQdTtwSl4/Bbit9s0zMzMz63u680GaHwemAAslLchlFwD/CNwi6VRgJfC5XmmhmZmZWR/TZQIVEQ8BqlJ9eG2bY2ZmZtb3+ZPIzczMzEpyAmVmZmZWkhMoMzMzs5KcQJmZmZmV5ATKzMzMrCQnUGZmZmYlOYEyMzMzK8kJlJmZmVlJTqDMzMzMSnICZWZmZlaSEygzMzOzkpxAmZmZmZXkBMrMzMysJCdQZmZmZiU5gTIzMzMryQmUmZmZWUk9SqAkHSVpiaRlks6vVaPMzMzM+rItTqAktQGXA0cD44DPSxpXq4aZmZmZ9VU9uQM1EVgWEc9GxFvALGBSbZplZmZm1nf1JIHaFXiusP18LjMzMzNragN6+wCSTgNOAxjCNr19ODMzM7Ne15MEahWwW2F7VC57n4i4CrgKQNKGuTF7SQ+O2Qx2AtY1uhEN5Pgdv+NvXY6/teOH/tcHe1Sr6EkC9QgwVtJoUuI0GTixi8csiYgJPThmvyfp0VbuA8fv+B2/4290Oxql1eOH5uqDLU6gImKTpDOB/wLagOkRsahmLTMzMzPro3o0Byoi7gLuqlFbzMzMzPqFen8S+VV1Pl5f1Op94Phbm+NvbY7fmqYPFBGNboOZmZlZv+LvwjMzMzMrqW4JVCt+b56kFZIWSlog6dFctoOkeyQtzT+3b3Q7a0XSdElrJT1VKOswXiX/kq+HJyWNb1zLa6dKH1wkaVW+DhZIOqZQNzX3wRJJRzam1bUhaTdJ90l6WtIiSWfn8pa4BjqJvyXOP4CkIZLmS3oi98G3cvloSQ/nWG+WNCiXD87by3L9ng0NoIc6iX+GpOWFa2C/XN5Ur4F2ktok/ULSnXm7Oc9/RPT6QnqX3q+AMcAg4AlgXD2O3cgFWAHsVFH2PeD8vH4+cEmj21nDeA8GxgNPdRUvcAxwNyDgQODhRre/F/vgIuDcDvYdl18Lg4HR+TXS1ugYehD7SGB8Xh8GPJNjbIlroJP4W+L855gEDM3rA4GH87m9BZicy38MnJ7XzwB+nNcnAzc3OoZein8GcEIH+zfVa6AQ198BNwJ35u2mPP/1ugPl783bbBIwM6/PBI5rXFNqKyIeAF6uKK4W7yTg2kh+DgyXNLIuDe1FVfqgmknArIjYGBHLgWWk10q/FBGrI+LxvL4BWEz6eqeWuAY6ib+apjr/APlcvp43B+YlgMOA2bm88hpovzZmA4dLUn1aW3udxF9NU70GACSNAv4MuDpviyY9//VKoFr1e/MC+Jmkx5S+0gZgRESszutrgBGNaVrdVIu31a6JM/Mt+umFYdum7YN8K/4jpP/AW+4aqIgfWuj85+GbBcBa4B7SnbX1EbEp71KM870+yPWvAjvWtcE1Vhl/RLRfAxfna+AHkgbnsma8Bn4InAe8m7d3pEnPvyeR966DImI8cDTwJUkHFysj3bdsmbdBtlq8BVcCHwT2A1YDlza0Nb1M0lBgDnBORLxWrGuFa6CD+Fvq/EfEOxGxH+nrvSYC+zS2RfVVGb+kDwNTSf2wP7AD8LXGtbD3SPo0sDYiHmt0W+qhXglUt743r9lExKr8cy3wU9Ivkxfbb9Hmn2sb18K6qBZvy1wTEfFi/qX6LvDvbB6mabo+kDSQlDzcEBG35uKWuQY6ir+Vzn9RRKwH7gM+Shqaav/g5mKc7/VBrt8OeKm+Le0dhfiPysO7EREbgWto3mvg48BnJK0gTdU5DPhnmvT81yuBeu978/Ls+8nA7XU6dkNI2lbSsPZ14FPAU6S4T8m7nQLc1pgW1k21eG8HTs7vQjkQeLUwzNNUKuY0HE+6DiD1weT8TpTRwFhgfr3bVyt57sI0YHFEXFaoaolroFr8rXL+ASTtLGl4Xt8a+CRpLth9wAl5t8proP3aOAG4N9+l7JeqxP/Lwj8QIs3/KV4DTfMaiIipETEqIvYk/Z2/NyJOolnPf71mq5PebfAMaTz86/U6bqMW0jsOn8jLovaYSeO784ClwFxgh0a3tYYx30QaonibNM59arV4Se86uTxfDwuBCY1ufy/2wXU5xidJvzBGFvb/eu6DJcDRjW5/D2M/iDQ89ySwIC/HtMo10En8LXH+czz7Ar/IsT4FXJjLx5CSw2XAT4DBuXxI3l6W68c0OoZeiv/efA08BVzP5nfqNdVroKIvDmHzu/Ca8vz7k8jNzMzMSvIkcjMzM7OSnECZmZmZleQEyszMzKwkJ1BmZmZmJTmBMjMzMyvJCZSZmZlZSU6gzMzMzEpyAmVmZmZW0v8BkKZeGJnV7wcAAAAASUVORK5CYII=\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "disp_axis = 1\n", "crossdisp_axis = (0,)\n", "\n", "# visualize the weight images used in the fixed boxcar extraction \n", "wimage_fixedboxcar, wimage_fb_bkg = ap_weight_images(ext_center, ext_width, disp_axis,\n", " crossdisp_axis, bkg_offset, bkg_width, \n", " image.shape)\n", "\n", "norm_data = simple_norm(wimage_fixedboxcar)\n", "plt.figure(figsize=(10, 3))\n", "plt.imshow(wimage_fixedboxcar, norm=norm_data, origin=\"lower\")\n", "plt.title(\"Fixed boxcar weight image\")\n", "\n", "norm_data = simple_norm(wimage_fb_bkg)\n", "plt.figure(figsize=(10, 3))\n", "plt.imshow(wimage_fb_bkg, norm=norm_data, origin=\"lower\")\n", "plt.title(\"Fixed boxcar backgound weight image\")" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYoAAAGDCAYAAAA1cVfYAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAABc/0lEQVR4nO3dd3hURffA8e9JIQmEECD0EFroJBRDkSYoiAgIqChFUUFAEUGKYEHkh+UVbGBDeQVB+mulSxUFROm9NyEU6TUJEDK/P3YTE0hC2OzdTTbn8zz7sHvbnL1s9uydmTsjxhiUUkqptHi5OwCllFJZmyYKpZRS6dJEoZRSKl2aKJRSSqVLE4VSSql0aaJQSimVLk0UHkpELotIWScfs4mIRKez3ohIuDPLVFmDiEwUkbfdHYdyD00U2ZyIHBKRWHtiSHwUN8YEGmMOuDu+rExEHhORP0QkRkSW37SutD3xJZ7Tf0Rkrog0tyiW5SLyrBXHth/fY5K4iAwXkSnujiMn0UThGdrYE0Pi45i7A8pqRMQ7lcVngdHAe+nsGmyMCQSqA4uBn0TkaacHeBsi4uPqMrMrsdHvNifSk+mhEn9BikguEdkkIi/al3uLyCoRGWZ/XVxEfhCRUyJyUET6JjtGgL3K4ZyI7ABqZ6DoB0XkgIicFpH3E/9gRcRLRIaKyN8iclJEvhWRfPZ180Xkw2TlzhCRCcli+NC+3wURWSkiAfZ134nICfvy30WkarJjTBSRsfZjXwGa3hyoMWaJMeZ/wG0TqzHmhDFmDDAcGJnWF5GIVBKRxSJyVkR2i8hj9uXl7Mtq2V8Xt5/zJiLyDtAI+Mx+9fKZfRsjIi+IyF5gr33ZGBE5IiIXRWS9iDRKVra3iLwmIvtF5JJ9fUkR+d2+yWb78R+3b9/a/tk4b7+yikx2rJoissF+nJmAf1rnxv45+83+/3Davn3iOiMifVP7TNjXdxORnfbP2EIRKZVsXdVk5/If+3t7AHgNeNz+Xjbbt10uIu+IyCogBigrtqvtZsmOl3QlIv9eMT5jP5/nROQ5EaktIlvs5+SztN5zjmOM0Uc2fgCHgGapLDdAuP15NeAcUBl4HfgT8Mb2Q2E9MAzIBZQFDgAt7Pu9B6wACgAlgW1AdDqxGOBX+/ZhwB7gWfu6bsA+exmBwI/AZPu6osBJ4F6giz2GvPZ1nwPLgRL2mOsDfsmOmRfww3ZlsClZLBOBC0AD+/v0TyfuZ4HlNy0rbX8/PjctL2tfXjmV4+QBjgDPAD5ATeA0UMW+vgewA8gNLAQ+SLbv8sRzddP5XGw/nwH2ZU8ABe3HHwicSHxvwMvAVqAiINiuggre/Hmwv65pP+d17ef1Kftnyc/+Wfgb6A/4Ao8C14G30zh/07F9rrywJZSGGfxMtLV/Jirb389Q4A/7urzAcft79Le/rmtfNxyYclMMy4HDQFX7sXy56W8j+X7J/n+/tB//fiAO+BkojO3zdhK4x91/41nh4fYA9JHJ/0DbH8Nl4Lz98bN9+c1fDAOB3dgSRnn7srrA4ZuO9yrwjf35AeCBZOt6cvtEkXz73sBS+/OlQO9k6yrav3x87K8fwfYlezrxi8b+xRMLVM/AeQi2l5/P/noi8G0Gz+GdJAp/+/IGqRzncWDFTcu+At5M9no2ti/zLdgTnn35clJPFPfeJvZziefH/v/bNp3/m+Sfh7HAWzdtsxu4B2iM7SpLkq37g7QTxbfAOCD0Dj8TC4DuydZ5YbsaKAV0AjamUd5wUk8UI1L527hdoiiRbP0Z4PFkr38AXsrIZ8jTH1r15BnaGWOC7Y92aWwzCdsf4HxjzF77slJAcftl9nkROY/tsr6IfX1xbF/eif7OQCw3b1882bH+vmmdT7Ky5mD7ZbvbGLPSviwE2xfz/psLsVezvGevZrmI7UshcZ/UYnGWEvZ/z6ayrhRQ96bz2QXbFVOi/2K7wvvUGHM1A+WleA8iMsheVXPBfvx8/PueS5LKuUpDKWDgTbGWxPb/VBw4auzflnbp/d8PxnYFs0ZEtotIt3TeQ/LPRClgTLLyz9qPU+IO30tq5WTUP8mex6byOtCBY3ocTRQ5xxfAXKCFiDS0LzsCHEyWZIKNMXmNMQ/a1x/H9gebKCwD5dy8fWL9/zFsXwzJ18Xz7x/mO8BOoJiIdLIvO42tOqBcKuV0xlZ10Qzbl2Vp+3JJto0VQyO3x1YlsTuVdUeA3246n4HGmOcBRCQQWxXZeGC4iBTIQKxJy+3tEYOBx4D8xphgbNVrie/5CKmfq9QcAd65Kdbcxpjp2P7fS4hI8nOZ5v+9sbXf9DDGFAd6AV9Iyh5WaX0mjgC9boohwBjzh31dWt27b3uu7K5gq+ZLVBTlEE0UOYCIPAncBTwN9AUm2b+01gCXRGSI2BqNvUWkmogkNlr/D3hVRPKLSCjwYgaKe9m+fUmgH5DYsDkd6C8iZexlvwvMNMbEi0hjbPX6XbHVlX8qIiWMMQnABOAjsTX+eovI3SLih63O+iq26oLc9uPd6XnxFhF/bFc2XiLiLyK+aWxbRET6AG8Cr9pju9lcoIKIPCkivvZHbRGpbF8/BlhnjHkWmIetfjzRP6T9xZgoL7bkegrwEVuHhKBk678G3hKR8mITKSIF0zj+f4HnRKSufds8ItJKRPICq+3l9LW/h4eBOmkFJSId7J8PsFWFGSD5+UnrM/Elts9XVftx8olIB/u6udh+NLwkIn4ikldE6iZ7L6Xl9j2bNgEd7e8hCltbi3KEu+u+9JG5B7dpzMb2C+4MyerUsf2h/tf+vDi2L/ET2P7I/0w8HrYv4G+xtX3swNZYers2ir7Y2jbOAB8C3vZ1XtgazY9g+6KbAuTH9kV3COiY7DgjgUXYfikHYPsVfhTbr+ff7csCgVnAJWzVGV1J2YA/kTTq1JOV87R9n+SPifZ1pe2vL2P7ZXoSmE+y+vY0jlkRWxI4ZT8Hy4Aa2K5+jgIF7NsFYmvI7WJ/fTe2ht5zwCfJ/w+THdsbW+K8iO1X/+Dk///29UOBg/bzshZ7uwHwnH2f88Bj9mUP2Lc5b1/3Hf92IogCNtqPM9P+SKuNYpT9vV3GVl3UMyOfCfv6J7G12Vy0fzYmJFtXDVvb1jlsn89X7MsLAivtyzfYly3n1jaessBf9rjmAZ9waxuFT7Lto4EmyV5PAYa6+288KzzEfkKUUsrpRMRg6zyxz92xKMdp1ZNSSql0aaJQSimVLq16UkoplS69olBKKZUuTRRKKaXS5ZEjUoaEhJjSpUu7OwyllMpW1q9ff9oYU+jm5R6ZKEqXLs26devcHYZSSmUrIpLqUC1a9aSUUipdmiiUUkqlSxOFUkqpdHlkG4VSyrmuX79OdHQ0cXFx7g5FOYG/vz+hoaH4+qY6BuYtNFEopW4rOjqavHnzUrp0aVKOPq6yG2MMZ86cITo6mjJlymRoH616UkrdVlxcHAULFtQk4QFEhIIFC97R1aEmCqVUhmiS8Bx3+n+piUIplS0cOnSIatWquTuMHEkThVJKZUB8fLy7Q3AbTRRKqWwjPj6eLl26ULlyZR599FFiYmJYunQpNWvWJCIigm7dunH16lXWrl1LZGQkcXFxXLlyhapVq7Jt2zZu3LjBoEGDqFatGpGRkXz66acAjBgxgtq1a1OtWjV69uyZOMMdTZo04aWXXiIqKooxY8a48627lfZ6UkrdkZdeeolNmzY59Zg1atRg9OjRt91u9+7djB8/ngYNGtCtWzc++ugjvvrqK5YuXUqFChXo2rUrY8eO5aWXXuKhhx5i6NChxMbG8sQTT1CtWjXGjh3LoUOH2LRpEz4+Ppw9exaAPn36MGzYMACefPJJ5s6dS5s2bQC4du1ajh8SSK8oPFB0dDTbtm1j+fLl/PXXXyQkJNx+J6WygZIlS9KgQQMAnnjiCZYuXUqZMmWoUKECAE899RS///47AMOGDWPx4sWsW7eOwYMHA7BkyRJ69eqFj4/tN3KBAgUA+PXXX6lbty4REREsW7aM7du3J5X5+OOPu+z9ZVV6ReGBWrRowY4dO5Jed+nShcmTJ2uvFeUUGfnlb5WbP8PBwcGcOXMm1W3PnDnD5cuXuX79OnFxceTJkyfV7eLi4ujduzfr1q2jZMmSDB8+PEXX0bT2y0myxRWFiLQTkf+KyEwRud/d8WRlp0+fZseOHZQqVYr58+czYMAApk6dysqVK90dmlKZdvjwYVavXg3AtGnTiIqK4tChQ+zbtw+AyZMnc8899wDQq1cv3nrrLbp06cKQIUMAaN68OV999VVSw/TZs2eTkkJISAiXL1/m+++/d/XbyvIsTxQiMkFETorItpuWPyAiu0Vkn4i8kt4xjDE/G2N6AM8Beh2Yivj4eP7880+WLFkCwMSJE2nZsiUjRowgMDCQCRMmuDlCpTKvYsWKfP7551SuXJlz587Rv39/vvnmGzp06EBERAReXl4899xzfPvtt/j6+tK5c2deeeUV1q5dy7Jly3j22WcJCwsjMjKS6tWrM23aNIKDg+nRowfVqlWjRYsW1K5d291vM+sxxlj6ABoDtYBtyZZ5A/uBskAuYDNQBYgA5t70KJxsvw+BWrcr86677jI5TceOHQ1gAOPl5WUuXbqUtO755583gBk2bJhJSEhwY5Qqu9qxY4e7Q1BOltr/KbDOpPKdankbhTHmdxEpfdPiOsA+Y8wBABGZAbQ1xvwHaH3zMcRWMfkesMAYs8HikLOdVatWMWPGjKTXjRo1IjAwMOn16NGjiYuLY8SIETRt2pQmTZq4IUqlVHblrjaKEsCRZK+j7cvS8iLQDHhURJ5LbQMR6Ski60Rk3alTp5wXaTbw4YcfUrBgQebOnQtA3759U6zPlSsXH3/8MWBLKkopdSeyRa8nY8wnwCe32WYcMA4gKirKuCKurODQoUPMmjWLIUOG0KpVK44fP07RokVv2S5fvnyUL1+e9evXuyFKpVR25q4riqNAyWSvQ+3L1B3YuXMnn3zyCSJC7969AVJNEonuuusuli9fzpdffsn58+ddFKVSKrtzV6JYC5QXkTIikgvoCMx2UyzZ0vLly6lSpQoff/wxjz32GKGhobfd57HHHuPcuXM8//zzvPbaay6IUinlCVzRPXY6sBqoKCLRItLdGBMP9AEWAjuB/xljtqd3HJXSf/7zHwB8fHx46623MrRP+/btWbRoEVWqVGH8+PFJwxcopVR6LE8UxphOxphixhhfY0yoMWa8ffl8Y0wFY0w5Y8w7zihLRNqIyLgLFy4443BZ1rVr1/jtt98YMGAA58+fp1y5chnet3nz5owfP55r164l3XOhVFaXVYcY//nnnxkxYgQATz/9dKo3602cOJE+ffpYFkNa5W7dupWnn37aKWVkizuzM8oYM8cY0zNfvnzuDsVS27Zt4+rVq9SpU8eh4QVq165N/vz5WbBggQXRKeWZUhtmfNSoUUntg1lNREQE0dHRHD58ONPH8qhEkVMkjmQZFRXl0P7e3t488MADzJ07l+vXrzszNKUsk9oQ44Dbhhnfs2cPfn5+hISEJC1bsmQJUVFRVKhQIam7enLz5s3j7rvv5vTp0+zfv5969eoRERHB0KFDk+59On78OI0bN6ZGjRpUq1aNFStWAKS4N+r7779PcbWQVrlt2rRJcY+VozRRZCNz587lzTff5NNPPyU0NJSyZcs6fKxOnTpx+vRpFi9e7MQIVU7RpEkTJk6cCMD169dp0qQJU6ZMASAmJoYmTZowc+ZMAC5cuECTJk348ccfAdt4ZE2aNGHOnDkAnDhxIkNl7t69m969e7Nz506CgoL44osviIuL4+mnn2bmzJls3bqV+Ph4xo4dS+3atZOGGR88eHDSMOPjxo1LGmZ8y5YtdOnSBbANM7527Vq2bdtGbGxsii/bxGHGBw4cmCKeVatWUatWrRTLDh06xJo1a5g3bx7PPfdcisEFf/rpJ9577z3mz59PSEgI/fr1o1+/fmzdujVFZ5Rp06bRokULNm3axObNm6lRo8Ztz01a5UZFRSUlmszQRJFNLF68mDZt2jBixAi2bduW1C3WUS1atCB//vxMmzbNiVEqZZ2bhxhfuXIlu3fvdtsw48ePH6dQoUIplj322GN4eXlRvnx5ypYty65duwBYtmwZI0eOZN68eeTPnx+A1atX06FDBwA6d+6cdIzatWvzzTffMHz4cLZu3UrevHlve27SKrdw4cIcO3bstvvfTra44c6TGWOSPuzLli1j/fr1DBw4kICAgKRtpk+fTteuXYmIiKBfv35ERkZmeuCyXLly0aFDB6ZOncqVK1d0KGV1R5YvX5703NfXN8Xr3Llzp3idL1++FK9DQkJSvE7v3p/kbv5hdLsfSlYPMx4QEMDNHWfSirFcuXIcOHCAPXv23LbKuHHjxvz+++/MmzePp59+mgEDBtC1a9cUx04eX3rlxsXFpfgucZRHXVFkt15P165d4/7776dy5cr4+/vz4IMP8sYbb1CyZEkKFy7Mli1bOHXqFL169aJevXqsWLGC7t27O210y8cff5wrV66wbNkypxxPKSvdPMR4w4YNqVixotuGGa9cuXJSuYm+++47EhIS2L9/PwcOHKBixYoAlCpVih9++IGuXbsmXa3Uq1ePH374ASBFO8Lff/9NkSJF6NGjB88++ywbNtiGtytSpAg7d+4kISGBn376KUPl7tmzxym9xTwqUWS3Xk//+c9/WLJkCYMHD6ZWrVq0aNGCb7/9lpYtW3Lt2jWeeuop6tSpQ2xsLP/9739x9vtq0KABAQEB2k6hsoWbhxh//vnn8ff3d9sw440bN2bjxo1JDd8AYWFh1KlTh5YtW/Lll1/i7++ftK5SpUpMnTqVDh06sH//fkaPHs1HH31EZGQk+/btS/r7Xr58OdWrV6dmzZrMnDmTfv36AfDee+/RunVr6tevT7FixVLEkla5v/76K61atcrUeQesH2bcHY/sMMz40aNHTb58+Uzbtm2TliUfAvy9995LGjb8t99+syyOFi1amMqVK1t2fOUZdJjx1PXt29csXrzYoX2vXLmS9Dc/ffp089BDDzkzNBMXF2fq1q1rrl+/nur6Oxlm3KOuKLKLLVu2EBkZyaVLl3jllX/nbEpezzh48GDGjh3L0qVLady48R0df+bMmfz5559Jr9MbTbd58+bs3LmT6OjoOypDKQWvvfZaUjfdO7V+/Xpq1KhBZGQkX3zxBR9++KFTYzt8+DDvvfdeUsN9pqSWPbL7I6tfUdx///2mSJEiZtOmTU4/dkJCgilQoIAZNGiQMcaYN99805QoUcKcO3cu1e03bdpkADNx4kSnx6I8h15ReJ4sNXGRSunq1ausWLGCHj16UL16dUvKWLVqFV5etovF1q1bExAQkPT6ZhEREeTPn58//viDp556ypJ4lFLZmyYKF/vrr7+IjY2ladOmlhxfRKhUqVLS66ioqKTueAkJCbckDC8vL0JDQ/nnn38siUd5DmNMpu7dUVmHMXc2ZY9HtVFk9e6xxhjeeecdgoKCnJooLl26RPv27dm6dStDhgxh48aNt2yzfPlyIiIiUm2vKFy4cLrtGEr5+/tz5syZO/6CUVmPMYYzZ86k6JF1Ox51RWGMmQPMiYqK6uHuWFLzxx9/sGjRIj766COndnXdunUra9asYdu2bYwaNYqQkBBq1qyZYpu8efNSpkwZjh49esvdpIULF2bt2rVOi0d5ntDQUKKjo/UHhYfw9/fP0Bw2iTwqUWR1n332GcHBwfTs2dOpx61fvz6HDx9OqkZKHOYgubvuuivVQcoAChUqxMmTJ50ak/Isvr6+lClTxt1hKDfxqKqnrOzGjRv88ssvPPLII04dLuPy5csYY/D29kZEaNSoUZoN14lx3Kxw4cJcvHiRLl26JI2Jo5RSiTRRuMjWrVs5f/48TZo0cdoxjTF06tSJpk2bZqjuePz48ZQpU4a///47xfLChQsDtmERxo4dS2xsrNNiVEplf5ooXCRxRMvEcWgya+bMmSxevJgnnniCxx57LEO9UTp27EilSpVumQI1MVGA7QpFJzRSSiWnicJF1q9fT7FixShZsqRTjvf222/zwQcf8Pjjj2d4hq08efKwaNEiACIjI5MmQLp59M7EeQSUUgq0MdtlNm7ceEtPpMzYsGHDLUMcZ1RoaCghISFcu3YNsDV0J+rQoQNz587VoceVUkk86ooiq95HERcXx86dOzM0U1VG+fr6ppiC8U4UKlSIZcuWUb9+fQB8fHxYv34977zzDr179yYmJob58+c7LValVPbmUYnCZNFhxjdt2kR8fPwt0yY66sMPP+Tdd9/N9HHi4uK4ePEiALVq1eK1116jUaNGFClShO+++y7Tx1dKeQaPShRZ1aJFixCRTPV4io+PZ8+ePcTHx7N48eJMT2946dIlihUrxieffJJiube3N23atGHx4sWpdqVVSuU8mihc4JdffiEqKoqCBQs6fIy3336b6tWrc+jQIRYsWMBHH32UqZjy5s3LkCFDUk1e9913H+fPn091KBClVM6jjdkWO3fuHH/99Revv/56hvc5evQo586dSzGFYe/evSlcuDDh4eGAbc7rzEo+F0ZyieNQLVu27Lbz+yqlPJ9eUVhs6dKlJCQk0KJFi3S3a9myJaNGjQLg9ddfp2HDhuzbt481a9Zw7do1ChcunOFusHfi0KFD7N69O8WyIkWKULVqVZ1LWykFaKKw3C+//EK+fPmoW7fuLeveeecdVq1aRUJCAkWLFuXs2bMYYxg0aBB//PEHCQkJNGjQgPfee8+S2BISEqhbty7Dhg27Zd29997LihUrkrrQKqVyLq16spAxhoULF9KsWbNbpiNMSEhg+vTp7N27lwYNGvDNN98krUte5fTtt9/y4IMPWhKfl5cX3377bVJ1VnL33nsvn376KX/99ReNGjWypHylVPagicJCiXNRp/aL3cvLi02bNiV1T01Lp06drAoPIM0qsSZNmuDl5cWyZcs0USiVw3lU1VNWu+Hul19+AW79Mp47dy4HDx7Ex8eHAgUKuCO0FH766SeWLFmSYllwcDC1atW6ZblSKufxqESR1W64W7hwIZUrVyYsLCxp2bVr13j88cf54IMP3BhZSm+++SafffbZLcvbtWvHypUrWb58ueuDUkplGeKJUxtGRUWZxAHv3OXGjRsEBgbSs2dPxowZk7TcGMO+ffvw9vambNmybozwX0eOHCEoKOiWWfdiY2OpVq0aPj4+bNmyBT8/PzdFqJRyBRFZb4y5pU+8R11RZCXR0dHExcWlaJgGEBHKly+fZZIEQMmSJVOdmjUgIIAvvviCPXv2MGnSJDdEppTKCjRRWOTgwYMAKaaP3Lx5M8888wxHjx51V1ip2rBhAx999FGqkx/df//9REREMG7cODdEppTKCjRRWOTAgQMAKa4cduzYwfz588mdO7e7wkrVsmXLGDhwIJ999hk///xzinUiQrdu3Vi/fj179uxxT4BKKbfSRGGRgwcP4uXllWKiok6dOhEdHU3+/PndGNmtnnvuOS5cuMDChQtp3749CQkJKdY/8sgjAPzwww/uCE8p5WaaKCxy4MABwsLC8PX1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ent78/DDD7N161befvttEhISqF+/Ps2bN6dv375Jc4fnBJoolFJZVuHChVmxYgU1atTg2rVr9OrVy+VzZleoUIHXX3+defPmERAQwMaNG/n0008pUaIEzzzzDKNHj3ZZw7u7aKJwwP79+9m8ebO7w1AqRxARvLy8uHTpEsuWLXN5okjUuHFjoqOjOX36NBs3bqRTp05MmzaN/v3707t3b7fE5CqaKByQO3du8ubN6+4wlMpRChYsyMaNGxkwYABnzpyhdevWLrtB72Y1atTg66+/5vLly7z00ktMmjSJEydOuCUWV/CoRCEibURk3IULFywtp1ixYpQtW9bSMpRStwoMDATg8uXLrF271u09D319fenRowcJCQk0bNiQRx55hDNnzrg1Jit4VKIwxswxxvTMly+fu0NRSlmoVKlSzJgxg7CwMBISEjh37pzbYqlSpQrPP/88586d48cff+Txxx/H03qTelSicJV9+/axceNGd4ehVI7WtGlTAgMDufvuu93eRvDFF19w5swZPv30U5YuXcq9997Ljh073BqTM+lUqA4IDAwkODjY3WEoleOJCE899RQFCxZk4cKFALRo0QKwzdktIi6Np1evXhw7doyvvvqKmjVrMnPmTNq1a+fSGKygN9w5oFatWoSGhjJ7drYaokopj2WMoVWrVqxfv57du3fz6KOP4u/vz9y5t50Q0xInT56kZcuWHD58mLlz51K3bl23xHGn9IY7pZTHEhF++OEHVq1aRVBQEJGRkUljRZ05c4YpU6Zw9epVl8VTuHBhxo8fj4jQsGFDtyUsZ9ErCgfkzZuXfPnyER0dbVkZSqnMM8bQrl07fv31V06fPu3yKYwvXLhAo0aNiI2NZdeuXXh7e7u0/DuVI64oXNU9NigoiAIFClhahlIq80SEn376iY0bN5IrVy4uXrzII488ws6dO11Sfr58+Rg2bBj79u1j3rx5LinTCh6VKFzVPbZIkSIeP4qkUp7Cy8sraWy2s2fPsm7dOpf2Wmzbti0hISFMnTrVZWU6m/Z6UkrlGKVLl+bAgQOICLGxsXTp0oXw8HBGjRplWZm+vr507NiRcePG8f7777N//36uXr1K9+7dadiwoWXlOpO2UTggMDCQfPnycfRotprBVSmVTGLvqJ9++onw8HBWrFhB3bp1LWnHOHXqFPXq1ePAgQPkzp0bb29vLl26xK+//kpERAQFChRweVfe1OSINgpXCQ4OplChQu4OQymVCRUrVmTr1q2Eh4dz+fJlHn30Ub7++mtLyipUqBA7duzg6NGjXLx4kSNHjlC8eHGaNm1KSEgIXbp0IT4+3pKynUGrnhxQuHBhQkND3R2GUspJ8uTJQ58+fbj//vsxxnD16lX8/f2dWoafnx/FixcHbI3cX331FRMnTuTq1atMnz4dEeGLL74gKw5BpIlCKZXjiQhvvPEGsbGxNG7cmIIFC/Lzzz8DWDYVa+vWrWndujUAw4YN46233sLX15eJEyemu9+lS5dcPnq1Vj05YPfu3axdu9bdYSilnCwgIIChQ4cSGRkJwOHDh2nQoAEXL160tNwRI0bwyiuvMGnSJD788MM0t5s7dy5BQUH8+eeflsZzM49KFK66j6JAgQIULVrU0jKUUu7RokULRowYAZA0SZErbpQbPnw47du3Z8iQIWzZsiXVbWbNmgWQ5nqreFSicNV9FIUKFaJkyZKWlqGUcr9atWpx8OBB8uTJw4ULF3jmmWe4fPmyJWX5+fnx5ZdfEhQURO3atZk2bdot25w9exaA/PnzWxJDWjwqUSillLMVK1YMgG3btjFnzhy+++47AN544w169+7NjRs3nFZW4cKF2bx5M/Xq1ePpp5++ZajyxHk3XJ0otDHbAbt27eLYsWPuDkMp5UINGjTg9OnTSa8TEhKIjY11erVUyZIl+f7776lUqRLPPfccy5cvT2pMT0wUAQEBTi3zdvSKwgEhISGUKFHC3WEopdzonXfeYcKECRhjWL16tVNn2StUqBCjRo1ixYoVdOvWLWnGPHfN5KeJwgGaKJRSYOtWu337durXr8/mzZudeuxu3boxcOBAJk2axO+//w7820bhapooHGCMISEhwd1hKKWygGrVqjFo0CDuuecejDFO67oqIowYMYL8+fMzevRowHYPhTtoonDA7t27sXIsKaVU9vL+++8jInz66ac0adLEaV/ouXPnpm/fvvz8889UqVLFKcd0hDZmO6BQoUI61pNS6hZdu3blxIkTSXdOO2Pe7oEDBzJr1iw2bdrkhAgd41FXFK664a5gwYJJY7YopVSi4OBg3n33XQC+//576tatS2a/j/LmzcvGjRtp166dEyJ0jEclClfdcHfjxo0sPdKjUsr9QkJCMMY4rSvrpEmTkiZgcjWPShSusnfvXjZs2ODuMJRSWViTJk1YvXq10+a3CAoKYuzYsU451p3SROGAwoUL6xAeSqnb8vHx4fTp07Rr146FCxe6OxyHaaJwQIECBZJu61dKqfQEBQWxf/9+Tpw44e5QHKa9nhwQHx/P9evX3R2GUiobyJUrF1u2bEFEuH79OosWLaJVq1buDuuO6BWFA/bt28fGjRvdHYZSKptI7CL7ww8/0Lp162z3/aGJwgFFihShVKlS7g5DKZXNVKpUiVWrVlGjRg3++OMPp96cZyVNFA7Inz8/RYoUcXcYSqlspkaNGtSvXx8R4cqVK1y/fp29e/cCtlGpnTlkuTNponDA9evXuXbtmrvDUEplY82bN2fVqlXUqlWLM2fO0KBBA4YNG+busFKljdkO2L9/P6dOnXJ3GEopD1GwYEGGDh3q1ruv06OJwgFFixalcOHC7g5DKeVB+vfvn/Q8Pj4eH59bv573798PwMWLF10WF3hY1ZOrxnoKDg7WRKGUcjpjDN26daNs2bKpTlI0f/58wDaCtSt5VKJw1VhP169f5+rVq5aWoZTKeUSEbt260a9fv1TnxW7WrBkAVn/H3UyrnhygbRRKKas0bNiQhg0bAraJihKHLAeoXLkyABUqVHBpTB51ReEqxYoVo0yZMu4OQynlwVatWkVYWFiKMaKWL1/ullg0UTggX758OnGRUspSkZGRPPjgg9x1111Jy6ZMmQLAgQMHXBqLJgoHXLt2jdjYWHeHoZTyYHnz5mXq1KmEhIQkLRs0aBAACQkJLo1FE4UDDhw4wNatW90dhlIqBzh8+DB333038+bNo1KlSgCEh4e7NAZtzHZAsWLFdAgPpZRLBAcHkytXLuLj45k2bZpbYtBE4YB8+fKluBxUSimrBAUF8dtvvwEk3bm9f/9+GjRo4LIYtOrJAXFxccTExLg7DKVUDvPpp5+6pVy9onDAoUOHOHv2rLvDUErlMBUrVgSgXLlyLi1XE4UDSpQooW0USqkcQ6ueHJA3b14KFCjg7jCUUjnMrl27ANssm66kicIBsbGxXLlyxd1hKKVyGC8vrxT/uopHVT2JSBugjdV9jP/+++9UR3ZUSikrJY7xVLZsWZeW61FXFK4aPTY0NJTy5ctbWoZSSmUVHpUoXCUwMDDVIYCVUspKO3fuBEiaZ9tVNFE4ICYmhkuXLrk7DKVUDuPr6wuQ6ux3VvKoNgpXOXz4MOfPn3d3GEqpHCax/dXV0xxoonBAyZIlKVq0qLvDUEopl9CqJwfkyZPH5VMRKqXUjh07ANizZ49Ly9VE4YCYmBguXrzo7jCUUjmMn59fin9dRaueHKBtFEopd0gc46lUqVIuLVcThQPCwsK0jUIplWOIMcbdMTidiJwC/nZw9xDgtBPD8RR6XlKn5yVtem5Sl5XPSyljTKGbF3pkosgMEVlnjIlydxxZjZ6X1Ol5SZuem9Rlx/OijdlKKaXSpYlCKaVUujRR3GqcuwPIovS8pE7PS9r03KQu250XbaNQSimVLr2iUEoplS5NFMmIyAMisltE9onIK+6Ox5VEZIKInBSRbcmWFRCRxSKy1/5vfvtyEZFP7Odpi4jUcl/k1hKRkiLyq4jsEJHtItLPvjxHnxsR8ReRNSKy2X5e/s++vIyI/GV//zNFJJd9uZ/99T77+tJufQMWExFvEdkoInPtr7P1edFEYSci3sDnQEugCtBJRKq4NyqXmgg8cNOyV4ClxpjywFL7a7Cdo/L2R09grItidId4YKAxpgpQD3jB/rnI6efmKnCvMaY6UAN4QETqASOBj40x4cA5oLt9++7AOfvyj+3bebJ+wM5kr7P3eTHG6MPWTnM3sDDZ61eBV90dl4vPQWlgW7LXu4Fi9ufFgN32518BnVLbztMfwCyguZ6bFOckN7ABqIvtRjIf+/KkvylgIXC3/bmPfTtxd+wWnY9QbD8e7gXmApLdz4teUfyrBHAk2eto+7KcrIgx5rj9+QmgiP15jjxX9mqBmsBf6LlJrF7ZBJwEFgP7gfPGmHj7Jsnfe9J5sa+/ABR0acCuMxoYDCTYXxckm58XTRQqQ4ztJ0+O7SInIoHAD8BLxpgUQwfn1HNjjLlhjKmB7Rd0HaCSeyNyPxFpDZw0xqx3dyzOpIniX0eBksleh9qX5WT/iEgxAPu/J+3Lc9S5EhFfbEliqjHmR/tiPTd2xpjzwK/YqlSCRSRxsNHk7z3pvNjX5wPOuDZSl2gAPCQih4AZ2KqfxpDNz4smin+tBcrbeyfkAjoCs90ck7vNBp6yP38KW/184vKu9h4+9YALyaphPIqICDAe2GmM+SjZqhx9bkSkkIgE258HYGu32YktYTxq3+zm85J4vh4FltmvxDyKMeZVY0yoMaY0tu+QZcaYLmT38+LuRpKs9AAeBPZgq2t93d3xuPi9TweOA9ex1aF2x1ZXuhTYCywBCti3FWw9xPYDW4Eod8dv4XlpiK1aaQuwyf54MKefGyAS2Gg/L9uAYfblZYE1wD7gO8DPvtzf/nqffX1Zd78HF5yjJsBcTzgveme2UkqpdGnVk1JKqXRpolBKKZUuTRRKKaXSpYlCKaVUujRRKKWUSpcmCqUsIiJfOzKwpIiUTj6Kr1Lu5nP7TZRSjjDGPOvuGJRyBr2iUCqT7FcAu0RkqojsFJHvRSS3iCwXkSgRKWWftyJERLxEZIWI3G8fVO99EVlrn7uil7vfi1Kp0SsKpZyjItDdGLNKRCYAvRNXGGP+FpGR2OamWAPsMMYsEpGe2Ib4qC0ifsAqEVlEDhxgUGVtekWhlHMcMcassj+fgm3ojyTGmK+BIOA5YJB98f3YxoXahG3o8oLYJjxSKkvRKwqlnOPmq4AUr0UkN7ZRQwECgUvYxoV60Riz8KZtS1sUo1IO0SsKpZwjTETutj/vDKy8af1IYCowDPivfdlC4Hn7MOaISAURyeOKYJW6E5oolHKO3djm094J5CfZXNkicg9QGxhpjJkKXBORZ4CvgR3ABnt32K/Qq3yVBenosUplkr2qaK4xppq7Y1HKCnpFoZRSKl16RaGUUipdekWhlFIqXZoolFJKpUsThVJKqXRpolBKKZUuTRRKKaXSpYlCKaVUuv4fcoEkkhYjI54AAAAASUVORK5CYII=\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# extract the spectrum using the weight images\n", "\n", "jdatamodel = s2d.slits[0]\n", "image = jdatamodel.data\n", "\n", "# without background subtraction\n", "ext1d_boxcar, tmpval = extract_1dspec(image, jdatamodel, ext_center, ext_width, disp_axis, \n", " crossdisp_axis, None, None)\n", "\n", "# with background subtraction\n", "ext1d_boxcar_bkgsub, tmpval = extract_1dspec(image, jdatamodel, ext_center, ext_width, disp_axis,\n", " crossdisp_axis, bkg_offset, bkg_width)\n", "\n", "# plot\n", "fig, ax = plt.subplots(figsize=(6, 6))\n", "ax.plot(ext1d_boxcar, 'k-', label=\"boxcar\")\n", "ax.plot(ext1d_boxcar_bkgsub, 'k:', label=\"boxcar (bkgsub)\")\n", "ax.set_title(\"Fixed boxcar 1D extracted spectrum\")\n", "ax.set_xlabel(r\"pixel\")\n", "ax.set_ylabel(\"Flux Density [Jy]\")\n", "ax.set_yscale(\"log\")\n", "ax.legend()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The flux density scale above does not match the pipeline extraction. We should verify the correctness of units conversions in the extraction process. The mismatch is likely caused by the lack of a wavelength scale in the extracted product." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ingest s3d data" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "DEBUG:jwst.datamodels.util:Opening C:\\Users\\Duy\\AppData\\Local\\Temp\\astropy-download-18584-3swaon47_s3d.fits as \n" ] } ], "source": [ "# NIRSpec IFU science data cube\n", "s3dfilename = \"NRS00001-faintQSO-F100LP-G140H-01_1_491_SE_2020-08-25T12h15m00_s3d.fits\"\n", "mainurl = \"https://data.science.stsci.edu/redirect/JWST/jwst-data_analysis_tools/IFU_optimal_extraction/\"\n", "s3dfile_dld = download_file(mainurl + s3dfilename)\n", "\n", "# rename files so that they have the right extensions required for the jwst datamodels to work\n", "s3dfile = s3dfile_dld + '_s3d.fits'\n", "os.rename(s3dfile_dld, s3dfile)\n", "\n", "s3d = datamodels.open(s3dfile)\n", "image2 = s3d.data" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "image/png": "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oYj8CcAxADY4s35BVWcV3aJNCmY7ircYzkjD2SqGaWoaFd308DiKZt22Tettee276Vi2G46lKUbTcTYxHWfT9gxxGpnWaZxmuT3T/tnuAxGFhnWIypefStUtAI5X1c0iUg/gJRF53Jn236p6f3ThERERlR8mRuWnaELkNF3d7Py33nnxpygREVGebB7ER2blx9ezKBGpFZFZAFYDeEpVpzmTfiois0XkVyLS6LHsFBFpFpHm1rYt4URNRESUQuypunz5SohUtV1VJwIYDWCSiOwL4LsA9kJm3KBBAL7jsexUVW1S1aaGut7hRE1EREQUokC1lVV1PYBnAZyqqis0owXAbQAmRRAfERFR2WD5UPkqmhCJyFARGeD83RPASQAWiMgI5z0B8AkAc6MLk4iIqHzwyVn58dPKbASA20WkFpkE6j5VfURE/iUiQ5FJiGcB+ErRNalC2myGi/deRutrvRezbWbd0uq9SkMXANK6w3NaR59entO00XsfOhq8P6Labd7bQ4fhOBv2ob13g/dire3u75viaHNfBgC0l2u1MwBARw/v/a5pbfOett17GnZ4xymGz7x9UD/PaR296r23Z6A13udm3YZtntNku+Ec69vDe4O8OhPFipWqy4+fVmazARzo8v7xkUREREREobhnymQsXL25+IzEwV2JiIgq1eRdBmPyLoOTDqMscOgOIiKikPDpdPliQkRERERVjwkRERERVT0mRERERFT14q1UrQrs8GgWbRwx3dDsvqan93JqWM4wmrppe57xA9CPNnivs8G7eXZHH++m7h09vJvk125q8d7edu9pHX29uwBo72k4JTwejtds2Oq9iKnZ/UC7OIzng+Fzrdli6B7A0BWBuVsEQxcGhmmmwe7r13ofM9lm+MwN51h7X+8uDoiIiCVEREREoamvzdxWz5w4MuFIKCg2uyciIgpJfW0N3vjByehtKFmmdGJCREREFKL+lj3YU7L4yIyIiIiqHhMiIiIiqnpMiIiIiKjqxVuHqKbGc4Rz2bLdeznDKPI1hn7S2wf39ZwmLd7r1DrvynC6cp33tG3eo5TXbtriOa1t9ABDLIZm5Ju9m7vDMHo7+ns3d68zNU33IIZ9Q73ds/T2Ht65eu1272lt/bxHfK/p4R1Ly1Dv5RrWex+TuvXezeDrDF0AbB3t/Rlgjfc51rHN+3vSPnaI57Ta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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Inspect sums over wavelengths and spaxels\n", "data = np.nan_to_num(np.array(image2))\n", "sum_over_waves = np.sum(data, axis=(0))\n", "sum_over_spaxels = np.sum(data, axis=(1, 2))\n", "\n", "f, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 5)) \n", "ax1.imshow(sum_over_waves)\n", "ax1.set_title(\"Sum over wavelength\")\n", "ax2.plot(sum_over_spaxels) \n", "ax2.set_title(\"Sum over spaxels\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Extraction code test with s3d data" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "# extraction parameters based on sum-over-wavelength image \n", "ext_center = (16, 20)\n", "ext_width = 6\n", "bkg_offset = 4\n", "bkg_width = 2" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "## build weight image (no background yet)\n", "disp_axis = 0\n", "crossdisp_axis = (1,2)\n", " \n", "wimage_fixedboxcar, wimage_fb_bkg = ap_weight_images(ext_center, ext_width, disp_axis,\n", " crossdisp_axis, bkg_offset, \n", " bkg_width, image2.shape)\n", "\n", "d1 = np.average(wimage_fixedboxcar, axis=0)\n", "f, ax = plt.subplots(1, figsize=(5, 5))\n", "ax.imshow(d1)\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAA3gAAAEWCAYAAAA0DzVNAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAACPNElEQVR4nO2dd5QURRfF79u8ZJCgJEFBQYKIICoGzBgwoiBJRUTBnAUDmMUsiqIoioFgFgxgAPUzAiooigiuREFy3LzU98dM9Vb3dPf0zO6w6f7O4bDTsbq70q336pUopUAIIYQQQgghpOKTVNYJIIQQQgghhBBSOlDgEUIIIYQQQkglgQKPEEIIIYQQQioJFHiEEEIIIYQQUkmgwCOEEEIIIYSQSgIFHiGEEEIIIYRUEijwCCGknCIiO0Vkv1K+Zg8RWe2zX4lIq9K8JykfiMgrInJfWaeDEEJIYqHAI4SQMkZElotITljQ6X+NlVI1lFJZZZ2+8oyIXCAi34lItoh86djXIixY9Tv9T0Q+FJGTEpSWL0VkSCKuHb5+pRHfIjJaRF4v63QQQkhlhAKPEELKB73Cgk7/+7esE1TeEJFkl82bATwJ4CGfU+sopWoAOBjAZwDeE5GLSz2BURCRlD19z4qKhGAfhRBC4oCVJyGElFO0xUZE0kRkgYhcHd6eLCLfishd4d+NReQdEdkgIv+IyDXGNTLDrnlbROQPAF0D3Po0EckSkY0i8ojuaItIkojcISIrRGS9iLwqIrXD+z4WkceM+04VkYlGGh4Ln7dNRL4RkczwvrdEZF14+9ci0s64xisi8lz42rsAHOdMqFLqc6XUmwCiCmKl1Dql1FMARgMY4yUgRKSNiHwmIptFZImIXBDevn94W+fw78bhd95DRO4HcDSAZ8LWwmfCxygRuVJElgJYGt72lIisEpHtIvKTiBxt3DtZREaKyN8isiO8v5mIfB0+ZGH4+n3Cx58Rzhtbw5bMjsa1DhGRn8PXmQYgw+vdhPPZV+HvsDF8vN6nROQatzwR3j9YRBaH89gsEdnX2NfOeJf/hZ+tJ4CRAPqEn2Vh+NgvReR+EfkWQDaA/SRk3T7RuJ5l+ZNiC+0l4fe5RUSuEJGuIvJr+J084/XMhBBSaVFK8R//8R//8V8Z/gOwHMCJLtsVgFbhv9sD2AKgLYDbAfwAIBmhgbqfANwFIA3AfgCyAJwSPu8hAP8DUA9AMwCLAKz2SYsCMCd8fHMAfwEYEt43GMCy8D1qAHgXwGvhfXsDWA/geAD9w2moGd43DsCXAJqE03wkgHTjmjUBpCNkiVtgpOUVANsAdA8/Z4ZPuocA+NKxrUX4eVIc2/cLb2/rcp3qAFYBuARACoBDAGwEcFB4/2UA/gBQDcAsAI8a536p35XjfX4Wfp+Z4W0DAOwVvv6NANbpZwNwM4DfABwIQBCyOu7lzA/h34eE33m38Hu9KJyX0sN5YQWA6wGkAugNoADAfR7vbwpC+SoJISF4VMA8cVY4T7QNP88dAL4L76sJYG34GTPCv7uF940G8LojDV8CWAmgXfhaqXCUDfM84/uOD1//ZAC5AN4H0BCh/LYewLFlXcb5j//4j//25L8KacETkYnh0eNFpXCt48Kjn/pfroicXQrJJISQWHg/bHHYKiLvO3cqpRYBuA+hzutNAAYqpYoQssg1UErdo5TKV6E5exMA9A2fegGA+5VSm5VSqwCMDZCWMeHjVyIkui4Mb+8P4HGlVJZSaieAEQD6ikiKUmodgGEAJgF4CsAgpdSOsKVnMIBrlVJrlFJFSqnvlFJ54eeaqJTaEf49GsDB2ioY5gOl1LdKqd1KqdwAaQ+CtvbVc9l3BoDlSqmXlVKFSqlfALwD4PxweicgJGh+BLAPQqIoGg+G32dO+BqvK6U2ha//GEKC7MDwsUMA3KGUWqJCLFRKbfK47lAAzyulfgy/10kA8gAcHv6XCuBJpVSBUuptAPN80lgAYF8AjZVSuUqpbxz7vfLEFeHnW6yUKgTwAIBOYSveGQDWKaUeC19zh1Lqxyjv6hWl1O/hd1MQ5VjNveHrfwpgF4ApSqn1Sqk1CA1uHBLwOoQQUimokAIPoVHdnqVxIaXUHKVUJ6VUJ4RGnrMBfFoa1yaEkBg4WylVJ/zvbI9jJiHUCf9YKbU0vG1fAI0NcbgVIfe3RuH9jRGySGlWBEiL8/jGxrVWOPalGPeagZAlaYkhEOojZF3523mTsDviQ2F3xO0IWWv0OW5pKS2ahP/f7LJvXwDdHO+zP0IWSs0EhCyqT2uhGgXbM4jITWGXxm3h69dG8TM3g8u78mBfADc60toMoe/UGMAapZQyjvf79rcgZDGcKyK/i8hgn2cw88S+AJ4y7r85fJ0mMT6L232C8p/xd47L7xpxXJMQQiosFVLgKaW+hqNhDs+NmBmer/A/EWkTx6V7A/hEKZVdKgklhJDS5VkAHwI4RUSOCm9bBeAfQxzWUUrVVEqdFt6/FqGOtqZ5gPs4j9cWr38R6tCb+wpR3KG+H8BiAPuIiLbwbETIbW5/l/v0Q8jF70SERE6L8HYxjlEofc5ByHVvicu+VQC+crzPGkqpYQAgIjUQsmC9BGC0iJhWQK+0WtvD8+1uQciyWlcpVQchN1T9zKvg/q7cWIWQddZMazWl1BSEvnsTETHfpee3V6H5iZcppRoDuBzAs2KP2OmVJ1YBuNyRhkyl1HfhfV7LfER9V2F2IeQOq9kbhBBCfKmQAs+DFwBcrZQ6FCH3pWfjuEZfhOYhEEJIuUJEBgI4FMDFAK4BMCksNuYC2CEit0oomEmyiLQXER1M5U0AI0Skrog0BXB1gNvdHD6+GYBrAeiAG1MAXC8iLcP3fgDANKVUoYgcg9C8tUEIzQV7WkSaKKV2A5gI4HEJBSVJFpEjRCQdoTlZeQA2IdSJfyCO95IsIhkIWRKTRCRDRFI9jm0kIlcBGAVgRDhtTj4EcICIDBSR1PC/riLSNrz/KQDzlVJDAHyE0PwvzX/wFjSamgiJ4g0AUiQUKKeWsf9FAPeKSGsJ0VFE9vK4/gQAV4hIt/Cx1UXkdBGpCeD78H2uCT/DuQAO80qUiJwfzh9AaK6nAmC+H688MR6h/NUufJ3aInJ+eN+HCIn960QkXURqikg341laSPRImQsQcgNOFZEuCA3EEkII8aFSCLxwR+NIAG+JyAIAzyM0NwIicq6ILHL5N8txjX0AdEBo0jwhhJQbRKQ5QlajQUqpnUqpyQDmA3giPA/vDACdAPyDkMXsRYQsYgBwN0Iudf8g5H7+WoBbfoBQ4JYFCImYl8LbJ4bP/zp8vVwAV4tILQCvArgqPM/uf+FzXg5bkG5CKHDIPIS8L8Yg1P68Gk7bGoQCl/wQ25sBAAxEyA3vOYSiWOYgJHxMtkooCudvAE4DcL5SaqLbxZRSOxAK1tEXISvVunB600XkLISmBwwLH34DgM4i0j/8+ykAvSUUzdFrruMsADMRClSyAqF3aLolPo6QKP8UwHaE3mNmeN9ohIT9VhG5QCk1H6GgL88gJMqWITQAAKVUPoBzw783A+iDUFAcL7oC+FFEdgKYjtCcSXMNRtc8oZR6L/x+pobdbBcBODW8bweAkwD0Qug9LkVxJNS3wv9vEpGffdJ1J0IWzS0I5eXJPscSQggBIHb3/IqDiLQA8KFSqn24c7FEKbVPCa53LYB2SqmhpZVGQgghpKIjIgpAa6XUsrJOCyGEkOhUCgueUmo7gH+0W0jYVeXgGC9zIeieSQghhBBCCKnAVEiBJyJTEJpfcKCIrBaRSxGKcnaphBZM/R2hiftBr9cCoQnkXyUguYQQQgghhBCyR6iwLpqEEEIIIYQQQuxUSAseIYQQQgghhJBIUso6AbFSv3591aJFi7JOBiGEEEIIIYSUCT/99NNGpVQDt30VTuC1aNEC8+fPL+tkEEIIIYQQQkiZICIrvPbRRZMQQgghhBBCKgkUeIQQQgghhBBSSaDAI4QQQgghhJBKQoWbg0cIIYQQQgipnBQUFGD16tXIzc0t66SUCzIyMtC0aVOkpqYGPocCjxBCCCGEEFIuWL16NWrWrIkWLVpARMo6OWWKUgqbNm3C6tWr0bJly8Dn0UWTEEIIIYQQUi7Izc3FXnvtVeXFHQCICPbaa6+YrZkUeIQQQgghhJByA8VdMfG8Cwo8QgghhJAKyIwZM/Dvv/+WdTIIIeUMCjxCCCGEkArImWeeiWOOOaask0FIpWP58uVo3759WScjbijwCCGEEEIqGEopAMDff/9dxikhhJQ2hYWFJTqfAo8QQgghpIKxe/duAJyrREiiKCwsRP/+/dG2bVv07t0b2dnZ+OKLL3DIIYegQ4cOGDx4MPLy8jBv3jx07NgRubm52LVrF9q1a4dFixahqKgIN910E9q3b4+OHTvi6aefBgDcc8896Nq1K9q3b4+hQ4dagzU9evTAddddhy5duuCpp54qUdoTtkyCiEwEcAaA9UopTxuniHQF8D2AvkqptxOVHkIIIYSQyoLuFFLgkcrMddddhwULFpTqNTt16oQnn3wy6nFLlizBSy+9hO7du2Pw4MF4/PHH8fzzz+OLL77AAQccgEGDBuG5557DddddhzPPPBN33HEHcnJyMGDAALRv3x7PPfccli9fjgULFiAlJQWbN28GAFx11VW46667AAADBw7Ehx9+iF69egEA8vPzMX/+/BI/YyIteK8A6Ol3gIgkAxgD4NMEpoMQQgghpFKhBR4hJDE0a9YM3bt3BwAMGDAAX3zxBVq2bIkDDjgAAHDRRRfh66+/BgDcdddd+OyzzzB//nzccsstAIDPP/8cl19+OVJSQva0evXqAQDmzJmDbt26oUOHDpg9ezZ+//136559+vQplbQnzIKnlPpaRFpEOexqAO8A6JqodBBCCCGEVDYo8EhVIIilLVE4reN16tTBpk2bXI/dtGkTdu7ciYKCAuTm5qJ69equx+Xm5mL48OGYP38+mjVrhtGjR9vWuPM6L1bKbA6eiDQBcA6A58oqDYQQQgghFRG6aBKSWFauXInvv/8eADB58mR06dIFy5cvx7JlywAAr732Go499lgAwOWXX457770X/fv3x6233goAOOmkk/D8889bAVM2b95sibn69etj586dePvtxMxOS5gFLwBPArhVKbU7WuUkIkMBDAWA5s2bJz5lhBBCCCHlGAZZISSxHHjggRg3bhwGDx6Mgw46CGPHjsXhhx+O888/H4WFhejatSuuuOIKvPrqq0hNTUW/fv1QVFSEI488ErNnz8aQIUPw119/oWPHjkhNTcVll12Gq666Cpdddhnat2+PvffeG127JsaJURJp4g+7aH7oFmRFRP4BoGul+gCyAQxVSr3vd80uXbqo0ph8SAghhBBSUcnOzkb16tWRkpKCgoKCsk4OIaXG4sWL0bZt27JORrnC7Z2IyE9KqS5ux5eZBU8p1VL/LSKvICQE3y+r9BBCCCGEVBTookkI8SKRyyRMAdADQH0RWQ1gFIBUAFBKjU/UfQkhhBBCKjsMskII8SKRUTQvjOHYixOVDkIIIYSQygYteKQyo5Ri3g4Tz2BOmUXRJIQQQggh8cEgK6SykpGRgU2bNtFKjZC427RpEzIyMmI6ryyjaBJCCCGEkDhg55dUVpo2bYrVq1djw4YNZZ2UckFGRgaaNm0a0zkUeIQQQgghFQwKPFJZSU1NRcuWLaMfSDyhiyYhhBBCSAWDc/AIIV5Q4BFCCCGEVDBowSOEeEGBRwghhBBSwWCQFUKIFxR4hBBCCCEVDLpoEkK8oMAjhBBCCKlg0EWTEOIFBR4hhBBCSAWDAo8Q4gUFHiGEEEJIBYMumoQQLyjwCCGEEEIqGDrICiGEOKHAI4QQQgipYNCCRwjxggKPEEIIIaSCQYFHCPGCAo8QQgghpILBICuEEC8o8AghhBBCKhgUeIQQLyjwCCGEEEIqGDrICl00CSFOKPAIIYQQQioYnINHCPGCAo8QQgghpIJBF01CiBcUeIQQQgghFQxa8AghXiRM4InIRBFZLyKLPPb3F5FfReQ3EflORA5OVFoIIYQQQioTtOARQrxIpAXvFQA9ffb/A+BYpVQHAPcCeCGBaSGEEEIIqTQwyAohxIuURF1YKfW1iLTw2f+d8fMHAE0TlRZCCCGEkMoEXTQJIV6Ulzl4lwL4xGuniAwVkfkiMn/Dhg17MFmEEEIIIeUPumgSQrwoc4EnIschJPBu9TpGKfWCUqqLUqpLgwYN9lziCCGEEELKIRR4hBAvEuaiGQQR6QjgRQCnKqU2lWVaCCGEEEIqCnTRJIR4UWYWPBFpDuBdAAOVUn+VVToIIYQQQioaOsgKIYQ4SZgFT0SmAOgBoL6IrAYwCkAqACilxgO4C8BeAJ4Njz4VKqW6JCo9hBBCCCGVBVrwCCFeJDKK5oVR9g8BMCRR9yeEEEIIqaxwDh4hxIsyD7JCCCGEEEJigxY8QogXFHiEEEIIIRUMWvAIIV5Q4BFCCCGEVDB0kBVa8AghTijwCCGEEEIqGHTRJIR4QYFHCCGEEFLBoIsmIcQLCjxCCCGEkAoGBR4hxAsKPEIIIYSQCgZdNAkhXlDgEUIIIYRUMHSQFUIIcUKBRwghhBBSwaAFjxDiBQUeIYQQQkgFgwKPEOIFBR4hhBBCSAWDQVYIIV5Q4BFCCCGEVDAo8AghXlDgEUIIIYRUMHSQFbpoEkKcUOARQgghhFQwaMEjhHhBgUcIIYQQUsFgkBVCiBcUeIQQQgghFQwKPEKIFxR4hBBCCCEVDC50TgjxggKPEEIIIaSCwTl4hBAvEibwRGSiiKwXkUUe+0VExorIMhH5VUQ6JyothBBCCCGVCbpoEkK8SKQF7xUAPX32nwqgdfjfUADPJTAthBBCCCGVBgo8QogXKV47RKRegPN3K6W2uu1QSn0tIi18zj0LwKsqVEP9ICJ1RGQfpdTaAPclhBBCCKmy0EWTEOKFp8AD8G/4n9/QUDKA5nHeuwmAVcbv1eFtEQJPRIYiZOVD8+bx3o4QQgghpHLAhc4JIV74CbzFSqlD/E4WkV9KOT2uKKVeAPACAHTp0oVDVoQQQgip0tCCRwjxwm8O3hEBzg9yjBdrADQzfjcNbyOEEEIIIT5wDh4hxAtPgaeUygUAEXlMRNr5HRMn0wEMCkfTPBzANs6/I4QQQgiJDgUeIcQLPxdNzWIAL4hICoCXAUxRSm2LdpKITAHQA0B9EVkNYBSAVABQSo0H8DGA0wAsA5AN4JJ4HoAQQgghpKpBF01CiBdRBZ5S6kUAL4rIgQiJsF9F5FsAE5RSc3zOuzDKdRWAK2NMLyGEEEJIlUcHWSGEECeB1sETkWQAbcL/NgJYCOAGEZmawLQRQgghhBAX6KJJCPEiqgVPRJ4A0AvAFwAeUErNDe8aIyJLEpk4QgghhBASCV00CSFeBJmD9yuAO5RSu1z2HVbK6SGEEEIIIVGgBY8Q4oWnwBORzuE/FwI40FGB5AFYGSTYCiGEEEIIKV0o8AghXvhZ8B6Lcl5zERmnlHq4lNNECCGEEEJ8YJAVQogXngJPKXWc34kikg7gFwAUeIQQQgghexDOwSOEeOEZRdNw0XRFKZUHYGCpp4gQQgghhPhCF01CiBd+Lpovi0gPAH41x4sADinNBBFCCCGEEH8o8AghXvgJvNoAfoK/wNtQuskhhBBCCCHRoIsmIcQLvzl4LfZgOgghhBBCSEB0kBVa8AghTjzn4BFCCCGEkPIJLXiEEC8o8AghhBBCKhicg0cI8YICjxBCCCGkgkGBRwjxIqrAE5F3ReR0EaEYJIQQQggpB9BFkxDiRRDR9iyAfgCWishDInJggtNECCGEEEJ80EFWCCHESVSBp5T6XCnVH0BnAMsBfC4i34nIJSKSmugEEkIIIYQQO3TRJIR4EcjtUkT2AnAxgCEAfgHwFEKC77OEpYwQQgghhLhCF01CiBd+C50DAETkPQAHAngNQC+l1NrwrmkiMj+RiSOEEEIIIZHQgkcI8SKIBW+CUuogpdSDWtyJSDoAKKW6+J0oIj1FZImILBOR21z2NxeROSLyi4j8KiKnxfUUhBBCCCFVCAo8QogXQQTefS7bvo92kogkAxgH4FQABwG4UEQOchx2B4A3lVKHAOiLUEAXQgghhFQQfv/9d9SsWRMrV64s66RUKRhkhRDihafAE5G9ReRQAJkicoiIdA7/6wGgWoBrHwZgmVIqSymVD2AqgLMcxygAtcJ/1wbwb6wPQAghhJCyY9y4cdi5cydmzJhR1kmpUnAOHiEhCgsLcdttt2HDhg1lnZRyg98cvFMQCqzSFMDjxvYdAEYGuHYTAKuM36sBdHMcMxrApyJyNYDqAE4McF1CCCGElBPy8vIAABkZGWWckqoFXTQJCTFz5kyMGTMGy5cvx9SpU8s6OeUCT4GnlJoEYJKInKeUeidB978QwCtKqcdE5AgAr4lIe6WUze9ARIYCGAoAzZs3T1BSCCGEEBIrubm5AID09PQyTknVghY8QkLs2rULAN2WTTwFnogMUEq9DqCFiNzg3K+UetzlNJM1AJoZv5uGt5lcCqBn+Hrfi0gGgPoA1jvu9QKAFwCgS5curNEIIYSQcgIFXtlACx4hIfLz8wEAaWlpZZyS8oNfkJXq4f9rAKjp8i8a8wC0FpGWIpKGUBCV6Y5jVgI4AQBEpC2ADAB0oCWEEEIqCNpFk+xZtLWCAo9UdXQdxEGmYvxcNJ8P/393PBdWShWKyFUAZgFIBjBRKfW7iNwDYL5SajqAGwFMEJHrEQq4crGizwEhhBBSYdAWPAq9PQu7S4SEoMCLJMhC5w8jtFRCDoCZADoCuD7svumLUupjAB87tt1l/P0HgO4xppkQQggh5QTdudJuUmTPQIFHSAi6aEYSZB28k5VS2wGcAWA5gFYAbk5kogghhBBSMdCugrTg7Vk4B4+QEFrg0YJXTBCBp618pwN4Sym1LYHpIYQQQkgFoaioCAUFBQBowdvTUOAREkIPLtGCV0xUF00AH4rInwi5aA4TkQYAchObLEIIIYSUd44//njMmzcPAAXenoYh4QkJQYEXSVQLnlLqNgBHAuiilCoAsAvAWYlOGCGEEELKN19//bX1N1009yy04BESgoNLkQRx0QSANgD6iMggAL0BnJy4JBFCCCEVn/nz56N27dpYv3599IMrAexk7VkYZIWQEDqSb2FhYRmnpPwQVeCJyGsAHgVwFICu4X9dEpwuQgghpELz2GOPYfv27fjiiy/KOil7BAq8PQsteISEyM7OBkCBZxJkDl4XAAdxfTpCCCEkOElJoTHUoqKiMk7JnoEumnsWCjxCQlDgRRLERXMRgL0TnRBCCCGkMpGcnAyg6gTDoMDbs1SVfEVINHbt2gWg6gymBSGIBa8+gD9EZC4Aq/ZWSp2ZsFQRQgghFRxtwasqHfEdO3aUdRKqFHSsIiQELXiRBBF4oxOdCEIIIaSyUdkteM7n2rx5cxmlpGpCF01CQlDgRRJV4CmlvhKRfQG0Vkp9LiLVACQnPmmEEEJIxUV3vCur25COXKfZsmVLGaWkakILHiGhgabvv/8eAAWeSZAompcBeBvA8+FNTQC8n8A0EUIIIRWeyu6imZOTY/tNC96ehRY8QoCPPvrI+psCr5ggQVauBNAdwHYAUEotBdAwkYkihBBCKjraRbOyWvCcAo8WvD2LHjigwCNVGTP/V9a6Nh6CCLw8pZS1uI2IpACgXwAhhBDiQ2VfJsEZNXPr1q1lk5Aqirbg0VWTVGVMqx0teMUEEXhfichIAJkichKAtwDMSGyyCCGEkIqNtuBV1uUD9MLmAwcOxNVXX438/HwUFBSUcaqqDhR2hBTXQwAFnkkQgXcbgA0AfgNwOYCPAdyRyEQRQgghFR1twXMGI6ks6I7VOeecg5YtWwIoXo+KJB5a8AgprofS0tIo8AyiCjyl1G6EgqoMV0r1VkpNUKxNSCkzYsQIziMghFRKKrsFLy0tDTVq1ABAgbcnocAjVRmlFAoLC616KDMzkwLPwFPgSYjRIrIRwBIAS0Rkg4jcteeSR6oKDz30UFkngRBCShXtrljZLXipqamoXr06AGDnzp1lmaQqhQ6yQoFHqiIjR45EamqqNahUrVq1SjvfOR78LHjXIxQ9s6tSqp5Sqh6AbgC6i8j1eyR1pMrBhooQUlnQAq+yjirTgle2sL0kVZmxY8cCKA7uVK1aNc4BNvATeAMBXKiU+kdvUEplARgAYFCQi4tITxFZIiLLROQ2j2MuEJE/ROR3EZkcS+JJ5aOydoQIIVUP3dnw6nS88sorWLhw4Z5MUqminystLY0WvDKALpqEANu2bQMQctGkBa+YFJ99qUqpjc6NSqkNIpIa7cIikgxgHICTAKwGME9Epiul/jCOaQ1gBIDuSqktIsL19ao4BQUFSE2Nmr0IIaTcE82Cd8kllwCouB1004KnI4bSgrfnoMAjpNiCl5mZabktE38LXn6c+zSHAVimlMoKr6M3FcBZjmMuAzBOKbUFAJRS6wNcl1RiaF4nhFQWolnwKjqmwKtZsyYALna+J6GwI6RY4KWnp9OCZ+An8A4Wke0u/3YA6BDg2k0ArDJ+rw5vMzkAwAEi8q2I/CAiPd0uJCJDRWS+iMzfsGFDgFuTikpl7QgRQqoe5XkOXp8+ffDkk0+W6BqmwGvRogUA4O+//y5hykhQGGSFkJDAS01NRUpKCgWegafAU0olK6VqufyrqZQqLR+6FACtAfQAcCGACSJSxyUtLyiluiilujRo0KCUbk3KIxR4hJDKQnm24L355pu4/vqSxUszBV61atXQrFkz/PXXX6WRPBIAumhWHrZs2YKXX365XA4GlTW7d+9Gp06d8O6777ru37p1q+UmToFXTJCFzuNlDYBmxu+m4W0mqwFMV0oVhIO5/IWQ4CNVFFZuhJDKQk5ODgD3eq0ydERMgQcADRs2xObNm8sySVUKCrvyx59//hnXd5k2bRoGDx6Mhx9+OAGpqtjk5uZi4cKF6Nevn+t+Cjx3Einw5gFoLSItRSQNQF8A0x3HvI+Q9Q4iUh8hl82sBKaJlFP0IuflcaSbEEKiMWfOHAwdOtT6vXDhQnzxxRcA3Ou1yjCYZUbRBELr4bEO33PQgle+mD9/Ptq2bYsnnngi5nO1u+2qVauiHFmxWblyJfr27Yvs7OzA5+h3k5eX57pfC7ykpCQGWTFImMBTShUCuArALACLAbyplPpdRO4RkTPDh80CsElE/gAwB8DNSqlNiUoTKb8kJYWyIjsHFYOePXti4sSJZZ0MQsoNxx9/PCZMmIDs7GyMHTsWnTp1svZVVoFnLnSu/2cdvuegwCtfrF69GgDw9ddfx3yutjzpwe5oFBQUYPv27THfp6y56aabMG3aNMyYMSPwOV5WOf2uaMFzJ6rAE5GDXLb1CHJxpdTHSqkDlFL7K6XuD2+7Syk1Pfy3UkrdoJQ6SCnVQSk1Nbbkk8oCBV7FYtasWbj00kvLOhmElDs2bdqEa6+91rbNTcxVhrrO6aKZkpJSKYRrRaGiWCveeeedKhF8Jz09HYC3pckPXR8EFXiDBg1C7dq1K5y4T0kJrc4WS/3nFG3Z2dmYMGGCVf8UFRUhJSWFAs9BEAvemyJyq4TIFJGnATyY6ISRysW5556Lfffd13M/BR4hpDKwceNGa8kATUFBAc4//3ycd955AIB77rkHV199dVkkD0Dpzf9zCjxa8PYsFcWC17t3b3Ts2LGsk5FwEi3wfv75Z9xzzz0AgKlTQ/aQbdu24Y033qgwwY20tb8kAu/WW2/F0KFDbdegwIskiMDrhlCwlO8Qmlf3L4DuiUwUqXy89957WLlyped+CryKQ3nvTBBSlmzcuBGNGjWybSssLMTbb7+Nd999Fxs2bMCoUaPw+uuvl1EKi4VZSdm1axeSk5OtUXkKvMSTl5eHyZMnQylVbgTem2++iUmTJrnu02mLZc5VRUUPdOTm5sZ8rrZ8+wm8Qw89FKNGjUJRUZElJlesWIEBAwagffv2caQ4Or/++itq1aqFf//9F0Doe3700UdxW49LQ+AtWrQo4pjk5GQkJydXGKv2niCIwCsAkAMgE0AGgH+UUnyDpFShwKs4rFixoqyTQEi55e6770b16tVt28x6rTwEUSgtgffff/+hUaNGVqeULpqJ54477kD//v0xc+bMMhd2mj59+uDiiy923VeVLCr6e8Qj8GJx0czNzUXdunUBwBo4j6XvlJ+fj19++SXQsWPHjsWOHTvw4YcfAgAmT56MM844A82bN8f69esD31OjB4N27twZ+BxnHtq1a5frdZOSkqpUfotGEIE3DyGB1xXA0QAuFJG3EpoqUqlo27Zt1GMo8CoGW7duRcuWLWM6Z8mSJVi3bl2CUkRI2WN2tEUEycnJtv2m6HnuuecCXbOgoADbtm2LO00FBQWeHU1T4H311Vdx32Pt2rXYZ599rN9VzYLXuHFj3HDDDXv0nnqAYOvWreXGgudHaQ0mVAS0uCiJBS+IQMnJybG++datW2O+12233YbOnTsHcuvU6dF1ms5/a9aswbBhw2K+txkYxcnYsWNdPb2cg0a1atWKOEZb8Cjwigki8C4NB0YpUEqtVUqdhcjlDgjx5M8//4x6TEUXeH/++Sfuu+++hN9nzZo1+OGHHxJ+Hy82bNgQ8zlt2rSxdQIJqWyY9VZubq41Su22/8UXXwx0zQsuuAB16tSJO01HHHEEMjMzXfeZne4ePXrEfY9169Zh7733tn5XNYG3du3auELilwYiYrmjlVTg7dy5E2PHjo2YO5adne1radm8eTOOOOII32tXRYFXkjl4QQRKdna2tcammzUrGgsWLAAA32kzGp3HnINWQHzfVqfb6bK7fv16XHvttTjllFMiznG+E91fNNPEOXiRBBF460WkufkPQPxDfoS4oAtqRe0c9OjRA3feeWeJRtyDsO+++0ZtUEvC7t278fTTT9sq3/z8fKvBKsk8ij3tG79u3TrMmTNnj94zFrZv314u3PVIyTE7dLm5ubaOxyGHHBJXBMH333+/RGn66aefPPeVVqfbKfDoopl4TDFXWpa7iy66CNdee21EeP8mTZpEBAwyefvtt6MOOFZFgVcSF80g5ScnJ6dEAk+7kAc512nBM/Oc0xU9CPqezr6evu6mTZErpTlFW1FREY46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8/+qV6/uOqjRrl07azkPsyw72yUziqamf//+Ecv56DwUzZrvdBn2E1Y6r0Yr/6WRb+MZ3EhOTsZ9993nGuAnGtr9s1atWrb0Oy14nTt3Rq1atfDRRx9hwoQJaNiwoWs9e+SRR0IpFbHcSHJysvWdAft78xIlToHnDCwSTeDt3r3b9v1POeUU21QDzbBhwzBq1ChrWaSg6yyWFvGsHepED3Sa79JZx7pZut3KR7t27XDWWWfZIg07oYtmMRR4xJX8/PyIRuHll1/GHXfc4Xq8OVnZqxOrt7///vuB0uCsXE866SQopWyVMWCvTM1OXRDXHLdKoFq1aqhZs6bnnIGgAs9cC8rLgufEyy3BSxSmpaWhfv36lrugFgrmdXRleuGFF+KHH36w7ut0k/FbkDQegWder7QFnumiedFFF0Xs150w8/ump6dHNCSmm1hp4zaC7vVs2gVMLzXhFCcNGzbE33//jbffftvaZkYhjbborFcHb/Xq1diyZYvVYcrMzLT+HjduHCZPnmzluZo1a1r5Suc3M4iCFnheHVcz7yYlJQVeo2/atGk47LDDACDC8gEUd6BycnKszlleXl7EKP+yZctcLak6jwQReHvagmemRd97wIABmDdvHs466yzbsW3bto2rI9+1a1drcMuJU+BFW3JF4+ZurfOo3uZWFrQFLy0tLWK/GbQICLVHZ555ZsQ1ioqKMGXKFDz55JMAQhEPX3/9dc+0pqWloV27dti8eTO+++47ZGdno6CgAIsWLcLChQttAuu8886LGGA037mu590WnXa673m9Sy/PFaA4P/z222/4+eefre1uZc4UQbHOoXQjkcsMuHHVVVehe/fuuOyyy2zlrk6dOjjppJOs37oeady4sTUQFOvzatfjgw8+2LY0jX6vzmfX23WdkZmZiUcffdRaJsa8v5v3S7SgVpratWtj9OjRgQarS8K4ceNc164Msph5NHRbFmQ5jWhUr14d77//vm+kaLpoFkOBR1xxWvCAUKXmjKipKwBzZMmrIOsGO2gnJOgCnV4WvBEjRriOipm4CbyUlBRs377dFo0wngaybt26rgEc/Br4hg0bWpZKzYEHHmibt2fi/K0teKY40+/xuOOOQ7du3azK1BlBzNmImS478TQwZqXttFCVpgWvUaNG+O6772z7db503tf5HfXIqBv63f7www9R0+Okfv36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BIcipCy58sor8dtvv+2RAWxixxSD5pI5VREKvATyzz//BD62Xz9b/BnMnj0br7zyijVHDwD23XdfXHXVVejYsaPlHqkneJvoCJ1paWnWUgo6iIleS2jq1KlYtmwZNm3a5Jqe008/vcRuosTOsmXLbAvRk9gZOXIkjjjiiLJOBkkQ8UYf1IMnu3fvpsCrJOj5TkEXJCekvCAitN6VA9z6x1UJCrxSws2d0c2CFwuNGze2rdViRgVKSkrCunXr8OGHH0acpwWe6eKnO0DXXHONtU0HfRk0aJDNRS0jIwMffvghTjrppBKln9hp3LgxDj300LJORoXm/vvvx3fffVfWySAJIl6Bd/755wMIWQAr2xy8qkqvXr3w+eef49prry3rpBBCKiBVbV1cJ2wBS4lvv/02Ytvvv/9eomvu3LkThxxyiPXbGfa1UaNGtsndDz30EADgmGOOiThe+yW3b9/eWlPojTfeAAA8/PDDuPzyywGE3Dv93DYJISRRxDvX9f7778fatWvRqFEjzsGrRJxwwgkU6oRUUb7++ms8//zzMZ/36aefAuBSCaw5S4k///zT9rtZs2ZxCSUzDO/27duxbt06K4z+kUceGXG87sQcfPDBuPXWW/H333/jjjvuAFBsyQOAM88sXn3Cufhn/fr1LRfOAw44oEwWuCWEkHhJSkqywmPrOpECjxBCKi5HH310XOtKnnTSSRg6dGigNQsrMxR4pYQzSMpBBx0U+FxTuJniavny5Vi7di1OOukkLF68GA888EDEuQceeCBuvfVWvPPOOwCA/fbbzxoFLywsBABMnDjRNpfPGTY2OTnZcgWNN8gBIYTEy5FHHllq62HqoBwUeIQQUjWpXr16lRd4CV0Hryqh1w9r164d+vfvb4tAOXToUDRr1gx33nknevXqhaysLJv75uTJk9GiRQsA9nkjkydPBhDq/DitbhoRsVwznWiB5xRtRx11FKZOnYrXX38dBx98MABYwVgo8Aghe5pvv/221KIland0r2VcCCGEVG5q1KiBXbt2QSlVZQf7aMErJbKzs5GamopFixZhxIgRlqvlEUccgeeff95ylzzkkENw2GGH2c6tVq2atV6HW+SleKOIaYHnXIRVRNCnTx/MmDED9913H4DQfD8g/iAHhBBSEkqrEW7QoAHWr1+Pe++9t1SuRwghpGJRs2ZNKKVwyy23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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# extract the spectrum (no bkg subtraction for now)\n", "\n", "jdatamodel = s3d\n", "image2 = jdatamodel.data\n", "\n", "ext1d_boxcar, tmpval = extract_1dspec(image2, jdatamodel, ext_center, ext_width, disp_axis, \n", " crossdisp_axis, None, None)\n", "\n", "# plot\n", "fig, ax = plt.subplots(figsize=(15, 4))\n", "ax.plot(ext1d_boxcar, 'k-', label=\"boxcar\")\n", "ax.set_title(\"Fixed boxcar 1D extracted spectrum\")\n", "ax.set_xlabel(r\"pixel\")\n", "ax.set_ylabel(\"Flux Density [Jy]\")\n", "ax.legend()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Simplified boxcar extraction code (for rectified data)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(2059, 39, 33)\n", "(2059,)\n", "(34, 435)\n", "(435,)\n" ] }, { "data": { "text/plain": [ "[]" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def array_slice(data, axis, start, end, step=1):\n", " # the usual way to do this is via np.take(). That entails an array copy though,\n", " # which can be inefficient, and not necessary in this application.\n", "\n", " sl = (slice(None),) * (axis % data.ndim) + (slice(start, end, step),)\n", "\n", " return data[sl]\n", "\n", "def sum_over_spaxels(data, axis, position, size):\n", " \"\"\"\n", " Extract the 1D flux using the boxcar method.\n", " \n", " Assumes data is a s2d or s3d rectified pipeline product,\n", " so no trace is required. Does not use fractional pixels.\n", " \n", "\n", " Parameters\n", " ----------\n", " data : ndarray\n", " array with 2-D or 3-D spectral image data\n", " axis : int\n", " axis along the (first) spatial direction\n", " position : tuple\n", " (x, y) position of the center of the extraction region (pixels)\n", " size : int\n", " size in pixels of the extraction region. In the 3-D case, it is\n", " used in both spatial dimensions.\n", "\n", " Returns\n", " -------\n", " flux : ndarray\n", " 1D `float` array with extracted fluxes\n", " \"\"\"\n", " sz = int(size / 2)\n", "\n", " start = position[axis] - sz\n", " end = position[axis] + sz\n", "\n", " # first slice\n", " result = array_slice(data, axis, start, end)\n", "\n", " # if s3d data, second slice\n", " if len(data.shape) > 2:\n", " result = array_slice(result, axis+1, start, end)\n", " return np.sum(np.sum(result, axis=axis), axis=axis)\n", " else: \n", " return np.sum(result, axis=axis)\n", "\n", " \n", "# Test with data used in previous sections of this notebook.\n", "\n", "# 3d\n", "print(image2.shape)\n", "sp = sum_over_spaxels(image2, 1, (16,20), 8)\n", "print(sp.shape)\n", "fig, ax = plt.subplots(figsize=(15, 4))\n", "ax.set_yscale(\"linear\")\n", "ax.plot(sp)\n", "\n", "# 2d\n", "print(image.shape)\n", "sp = sum_over_spaxels(image, 0, (27,), 4)\n", "print(sp.shape)\n", "fig, ax = plt.subplots(figsize=(6, 6))\n", "ax.set_yscale(\"log\")\n", "ax.plot(sp)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## About this notebook\n", "\n", "**Author:** Ivo Busko, JWST\n", "**Updated On:** 2021-12-13" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "***" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Top of Page](#top)\n", "\"Space " ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.7" } }, "nbformat": 4, "nbformat_minor": 2 } astropy-specreduce-05be828/notebook_sandbox/jwst_boxcar/pre-requirements.txt000066400000000000000000000000311510537250300276200ustar00rootroot00000000000000astropy-helpers==2.0.11 astropy-specreduce-05be828/notebook_sandbox/jwst_boxcar/requirements.txt000066400000000000000000000007211510537250300270420ustar00rootroot00000000000000notebook==6.4.12 jupyter_client==5.3.5 numpy==1.22.0 scipy #==1.5.2 specutils==1.1.1 glue-astronomy==0.1 glue-core==1.0.0 glue-jupyter==0.2.1 glue-vispy-viewers==1.0.1 jdaviz==1.0.3 git+https://github.com/astropy/regions.git photutils==1.0.1 astropy>=4.2 matplotlib==3.3.2 ipyvuetify==1.6.2 ipyvue==1.5.0 git+https://github.com/radio-astro-tools/radio-beam.git git+https://github.com/spacetelescope/jwst@0.16.1 git+https://github.com/astropy/specreduce.git ccdproc astropy-specreduce-05be828/notebook_sandbox/tracing_options.ipynb000066400000000000000000002760501510537250300255100ustar00rootroot00000000000000{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Automatic Tracing Options" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "%matplotlib inline\n", "\n", "from pathlib import Path\n", "from zipfile import ZipFile\n", "\n", "from astropy.modeling import models\n", "from astropy.visualization import simple_norm\n", "from astropy.utils.data import download_file\n", "\n", "from jwst import datamodels\n", "\n", "from specreduce.tracing import FitTrace\n", "from specreduce.background import Background\n", "\n", "import tempfile\n", "\n", "import numpy as np\n", "\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ingest s2d data" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# data is taken from s2d file. x1d is used for comparison with pipeline extraction.\n", "zipped_datapath = Path(download_file('https://stsci.box.com/shared/static/qdj79y7rv99wuui2hot0l3kg5ohq0ah9.zip', cache=True))\n", "\n", "data_dir = Path(tempfile.gettempdir())\n", "\n", "with ZipFile(zipped_datapath, 'r') as sample_data_zip:\n", " sample_data_zip.extractall(data_dir)\n", "\n", "s2dfile = str(data_dir / \"nirspec_fssim_d1_s2d.fits\")\n", "x1dfile = str(data_dir / \"nirspec_fssim_d1_x1d.fits\")" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# use a jwst datamodel to provide a good interface to the data and wcs info\n", "s2d = datamodels.open(s2dfile)\n", "image = np.array(s2d.slits[0].data)\n", "norm_data = simple_norm(image, \"sqrt\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Background Extraction" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "# extraction parameters based on image above\n", "ext_center = 27\n", "ext_width = 4\n", "\n", "bkg_sep = 4\n", "bkg_width = 2" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "bg = Background.two_sided(image, ext_center, bkg_sep, width=bkg_width)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Automatic Traces\n", "\n", "Now we'll compare the trace when passing various options to `peak_method` and `window`." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "auto_trace_gauss = FitTrace(image-bg, guess=ext_center, bins=20,\n", " peak_method='gaussian', trace_model=models.Polynomial1D(2))" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0.5, 1.0, 'slit[0] slice')" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.figure(figsize=(15, 15))\n", "plt.imshow(bg.sub_image(image).data, norm=norm_data, aspect=5, origin=\"lower\")\n", "plt.plot(auto_trace_gauss.trace, color='r')\n", "plt.title(\"slit[0] slice\")" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "auto_trace_window = FitTrace(image-bg, guess=ext_center, bins=20, window=4,\n", " peak_method='gaussian', trace_model=models.Polynomial1D(2))" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.plot(auto_trace_gauss.trace-auto_trace_window.trace)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "auto_trace_centroid = FitTrace(image-bg, guess=ext_center, bins=20, window=4,\n", " peak_method='centroid', trace_model=models.Polynomial1D(2))" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.plot(auto_trace_gauss.trace-auto_trace_centroid.trace)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "auto_trace_max = FitTrace(image-bg, guess=ext_center, bins=20,\n", " peak_method='max', trace_model=models.Polynomial1D(2))" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXoAAAD4CAYAAADiry33AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8/fFQqAAAACXBIWXMAAAsTAAALEwEAmpwYAAAhoklEQVR4nO3deXhU5d3/8feXhIR9Tdj3fZE9rCquVBSRtlLFFRTEilptqz74s62CT23VulasUnFBEeouYJFNVFyqhC1AIBACJGFJICwhhIQkc//+yOgTaYABkpzJzOd1XbkyZ5mZ79xX8snJfe5zH3POISIioauK1wWIiEj5UtCLiIQ4Bb2ISIhT0IuIhDgFvYhIiIv0uoDjxcTEuDZt2nhdhohIpbJy5cp9zrnY0rYFXdC3adOG+Ph4r8sQEalUzGzHibap60ZEJMQp6EVEQlxAQW9mw80sycySzWxyKduHmtkqMys0s9HHbWtlZovMbKOZJZpZmzKqXUREAnDKoDezCGAacDnQDbjOzLodt1sqMA54u5SXmAk86ZzrCgwAMs+mYBEROT2BnIwdACQ751IAzGwOMApI/GEH59x2/zZfySf6/yBEOucW+/fLKZuyRUQkUIF03TQH0kosp/vXBaITcNDMPjCz1Wb2pP8/hJ8ws4lmFm9m8Xv37g3wpUVEJBDlfTI2EjgfuA/oD7SjuIvnJ5xz051zcc65uNjYUoeBiojIGQok6HcCLUsst/CvC0Q6sMY5l+KcKwQ+AvqeVoUiImFgSWIG761ML5fXDiToVwAdzaytmUUBY4C5Ab7+CqCemf1wmH4xJfr2RUQEXv96GxPfjGf296kU+cr+HiGnDHr/kfhdwEJgI/COc26DmU01s6sAzKy/maUDvwJeNrMN/ucWUdxts9TM1gEG/LPMP4WISCVU5HNMmbeBR+YlcmnXxrw1fiARVazM38eC7Q5TcXFxTlMgiEioyz1WyD1z1rA4MYNbz23LQyO6nlXIm9lK51xcaduCbq4bEZFQl3k4jwlvxLN+5yGmXNWdsUPalOv7KehFRCrQ5ozD3PLaCvYfOcb0m+K4tFvjcn9PBb2ISAVZvmUvk2atolrVCN65fTA9WtStkPdV0IuIVIBZ3+3gTx9voENsLWaMi6NF/RoV9t4KehGRclTkc/zl3xt55attXNg5lr9f14fa1apWaA0KehGRcnIkv3hkzZKNGYwb0oY/jOhKZETFzw6voBcRKQe7Dx1l/OvxbNqTXSEja05GQS8iUsbW7zzE+DdWkJNXyIyx/bmoSyNP61HQi4iUoUUb9nDPnDXUr1GV9+4YQtemdbwuSUEvIlIWnHO8snwbjy3YSM8W9fjnzf1oVLua12UBCnoRkbNWUOTjTx+vZ/b3aYzo0ZSnrulFtar/desNzyjoRUTOwqGjBUyatZKvk7O486L2/H5YZ6qUw8RkZ0NBLyJyhlKzcrnl9e9J3Z/Lk6N78qu4lqd+kgcU9CIiZyB++34mvrmSIp/jzfEDGdSuodclnZCCXkTkNH2wKp3J76+jef3qzBgbR7vYWl6XdFIKehGRABX5HE8uTOKlL7YyuF1DXryhL/VrRnld1ikp6EVEApCTX8i9c1azZGMmNwxsxSNXdaeqB9MZnAkFvYjIKaTtz2XCG/Ek781h6qju3Dy4jdclnRYFvYjISXy/bT+/fmslhUU+3rhlAOd1jPG6pNOmoBcROYF3VqTx0EfraFm/Bq9UgpOuJ6KgFxE5Tsk55M/vGMML1/Wlbo2KnUO+LCnoRURKyM4r4O63V/PF5r2eziFflhT0IiJ+2/cdYcLMeLbvO8Jjv+jB9QNbeV1SmVDQi4gA32zdx6RZqwCYOX4AQ9pXvpOuJ6KgF5GwN+u7HTz88QbaxNRkxtg4Wjes6XVJZUpBLyJhq6DIx58/2cjr32znws6xPH9dH+pU8I27K4KCXkTC0v4jx7hz1iq+TcliwnltefCKrkQE2fTCZUVBLyJhJ3FXNhPfjCfzcD5P/aoXV/dr4XVJ5UpBLyJh5ZOE3dz37lrqVI/kndsH07tlPa9LKncKehEJCz6f46nFSUxbtpW+rerx0o39aFQnOO7pWt4U9CIS8rLzCvjtnDUs3ZTJmP4tmTKqO9GRwXNP1/KmoBeRkLZ1bw63zYwnNSuXR0d158ZBrTELzZOuJ6KgF5GQtWxTJr+ZvZqoyCq8NSG4b/dXnhT0IhJynHO8+PlW/rYoiW5N6zD95jia16vudVmeUdCLSEjJPVbIA+8lMD9hNyN7NeOJq3tSPSp8+uNLE9CUbGY23MySzCzZzCaXsn2oma0ys0IzG13K9jpmlm5mL5RF0SIipUnbn8vV//iWT9btZvLlXXh+TO+wD3kI4IjezCKAacAwIB1YYWZznXOJJXZLBcYB953gZR4Fvjy7UkVETuzbrVnc+fYqCop8vDauPxd2buR1SUEjkCP6AUCycy7FOXcMmAOMKrmDc267cy4B8B3/ZDPrBzQGFpVBvSIiP+Gc49WvtnHjjO9oUDOKuXedp5A/TiB99M2BtBLL6cDAQF7czKoATwE3ApeeZL+JwESAVq1CY/5nESl/uccKefCDdXy8Zhc/69aYp67pRe0QnJTsbJX3ydhJwL+dc+knG7fqnJsOTAeIi4tz5VyTiISAHVlHuP3NlSRlHOb+yzpzxwXtqRKik5KdrUCCfifQssRyC/+6QAwGzjezSUAtIMrMcpxz/3VCV0QkUMuSMrln9mrMjNdvGcAFnWK9LimoBRL0K4COZtaW4oAfA1wfyIs752744bGZjQPiFPIicqZ8PscLy5J5Zslmujapw8s39aNlgxpelxX0Thn0zrlCM7sLWAhEAK865zaY2VQg3jk318z6Ax8C9YGRZjbFOde9XCsXkbCSnVfA7/61hiUbM/lln+b8+Rc9NHQyQOZccHWJx8XFufj4eK/LEJEgsjnjMLe/uZK0/bn88cpu3Dw4/OarORUzW+mciyttm66MFZGgNj9hFw+8l0DN6EhmTxxE/zYNvC6p0lHQi0hQKizy8cTCJKZ/mUK/1vV58Ya+NA6T+ePLmoJeRIJOVk4+d89ezTdbs7hpUGv+eGU3oiIDmrFFSqGgF5GgsjbtIHe8tZKsI8f42696MTrE7+daERT0IhIUnHPM/j6NR+ZtILZWNO/fMYRzmtf1uqyQoKAXEc8dPVbEQx+t44NVOzm/YwzPjelDg5pRXpcVMhT0IuKplL05TJq1iqSMw9xzSUd+c0lHIjSVQZlS0IuIZxas28397yVQNUJTGZQnBb2IVLiCIh9/XbCJGV9to3fLeky7oW9Y3+qvvCnoRaRC7TmUx11vryJ+xwHGDm7NQyM0dLK8KehFpMJ8k7yP38xZTe6xIp6/rg9X9WrmdUlhQUEvIuXO53P844utPLUoiXaxtZgzsS8dGtX2uqywoaAXkXJ1MPcYv3tnLZ9tyuSqXs34yy97UDNa0VOR1NoiUm4S0g8yadYqMrLzmDqqOzcN0qyTXlDQi0iZc87x9vepTJmbSEytKN65fTB9WtX3uqywpaAXkTKVk1/IQx8W37B7aKdYnr22t65y9ZiCXkTKzMbd2dw5axXbs47w+2GdmHRRB13lGgQU9CJy1n6YkGzKvA3UrV6Vt28bxKB2Db0uS/wU9CJyVnLyC/l/H6xj7tpdnN8xhmeu7U1MrWivy5ISFPQicsYSd2Vz59ur2JF1hPsv68wdF7Snirpqgo6CXkRO24+jauYlUr9GVWbfNoiB6qoJWgp6ETkth/MKePCDdcxP2M3QTrE8c00vGqqrJqgp6EUkYOt3HuKut1eRuj9XXTWViIJeRE7JOcdb36Xy6PxEGtSIYs7EwQxo28DrsiRACnoROanDeQVM/mAdnyTs5oJOsTytrppKR0EvIie0Lv0Qd89eRdqBozwwvDO/HqqumspIQS8i/8Xnc8z4ahtPLNxETK1oZt82SF01lZiCXkR+Yu/hfO57dy1fbN7Lz7o15vGre1Jfc9VUagp6EfnR8i17+e2/1pKdV8Cjo7pzo6YVDgkKehGhoMjH3xYl8fIXKXRoVIu3JgygS5M6XpclZURBLxLmUrNyuXvOatamHeS6Aa3405XdqB4V4XVZUoYU9CJh7OM1O3now/WYwbTr+zKiZ1OvS5JyoKAXCUNH8gt5ZO4G3l2ZTr/W9XluTG9a1K/hdVlSThT0ImFm/c5D/GbOarbtO8LdF3fgnks6EhlRxeuypBwp6EXChHOO177ezl8XbKJ+zarMmjCQIe1jvC5LKkBAf8bNbLiZJZlZsplNLmX7UDNbZWaFZja6xPreZvatmW0wswQzu7YsixeRwGTl5DPhjXimzk9kaKcYFtwzVCEfRk55RG9mEcA0YBiQDqwws7nOucQSu6UC44D7jnt6LnCzc26LmTUDVprZQufcwbIoXkRObVlSJve/m0D20QIeGdmNsUPaaGx8mAmk62YAkOycSwEwsznAKODHoHfObfdv85V8onNuc4nHu8wsE4gFDp5t4SJycnkFRfzl3xt549sddG5cW2Pjw1ggQd8cSCuxnA4MPN03MrMBQBSw9XSfKyKnJ3FXNvfMWc2WzBxuObcN/zO8C9Wqamx8uKqQk7Fm1hR4ExjrnPOVsn0iMBGgVatWFVGSSEj6YTKyJxcmUbdGVWbeOoChnWK9Lks8FkjQ7wRallhu4V8XEDOrA3wCPOSc+09p+zjnpgPTAeLi4lygry0i/2fPoTx+/+4avk7OYph/MrIGmoxMCCzoVwAdzawtxQE/Brg+kBc3syjgQ2Cmc+69M65SRE5qwbrdPPjhOvILfPzllz0Y07+lTrjKj04Z9M65QjO7C1gIRACvOuc2mNlUIN45N9fM+lMc6PWBkWY2xTnXHbgGGAo0NLNx/pcc55xbUw6fRSTsHMkvZMq8DbwTn07PFnV59tretIut5XVZEmTMueDqKYmLi3Px8fFelyES9FanHuDef60hdX8uky5sz72XdqKqrnANW2a20jkXV9o2XRkrUskUFvl48fOtPLd0C03qVONfulG3nIKCXqQSSc3K5XfvrCF+xwFG9W7G1FHnULd6Va/LkiCnoBepBJxzzFmRxqPzE4kw49lre/PzPs29LksqCQW9SJDLzM7jf95PYFnSXoa0b8iTv+pF83rVvS5LKhEFvUgQ+yRhNw99tI6jx4p4eGQ3xg5uQ5UqGjYpp0dBLxKEDuUW8PDc9Xy0Zhc9W9Tl6Wt606GRhk3KmVHQiwSZ5Vv2cv+7CezNyee3l3Zi0kXtNWxSzoqCXiRIHD1WxF8XFM822T62JtNvHkLPFvW8LktCgIJeJAisTj3A799ZS8q+I9x6blseGN5Zs01KmVHQi3joWKGPv3+2hWnLkmlSpxpvTxjIkA6685OULQW9iEc2Zxzmd++sYf3ObK7u24KHr+pGnWq6+EnKnoJepIIVFvl4+csUnluyhVrVInnpxn4MP6eJ12VJCFPQi1SgLRmHue/dtaxNP8Tl5zTh0Z+fQ0ytaK/LkhCnoBepAIVFPv65fBvPLNlMzagI/n5dH67s2VRzxkuFUNCLlLPkzBzue3cta9IOcln3xvzvz3sQW1tH8VJxFPQi5aTI53hleQpPLd5MjagInhvTm6t6NdNRvFQ4Bb1IOdi6N4f7313LqtSDDOvWmD//4hwa1a7mdVkSphT0ImWoyOd49att/G1REtWqRvDstb0Z1VtH8eItBb1IGUnZm8P97yWwcscBLu3aiMd+0YNGdXQUL95T0IucpSKf47Wvt/HkwiSiI6vw9DW9+EWf5jqKl6ChoBc5C5szDvPAewmsSTvIJV0a8dgve9BYR/ESZBT0ImfgWKGPl77Yyt8/20Kt6Ej1xUtQU9CLnKaE9IM88F4Cm/YcZmSvZjw8spuubpWgpqAXCVBeQRHPLN7MP5enEFs7mn/eHMewbo29LkvklBT0IgH4T0oWk99PYHtWLmP6t+TBK7pSt7pmmpTKQUEvchKH8wr464JNzPoulZYNqjNrwkDO1XzxUsko6EVOYNmmTP7fh+vYk53H+PPa8vufdaJGlH5lpPLRT63IcfYfOcbUeRv4aM0uOjaqxft3DKFvq/pelyVyxhT0In7OOeau3cXUeYkcOlrAby7pyJ0XtSc6UvdulcpNQS8CpO3P5aGP1vPl5r30alGXtyYMpGvTOl6XJVImFPQS1gqKfLz6VfENQSLMeGRkN24a3IaIKrrwSUKHgl7C1tq0g0z+YB0bd2czrFtjplzVnWb1qntdlkiZU9BL2MnJL+RvC5N449vtNKodrZtzS8hT0EtYWZyYwZ8+Xs+e7DxuGtSa+y7rTJ1quvBJQpuCXsLCnkN5PDJ3A59u2EPnxrWZdkNfDZmUsKGgl5Dm8zlmfbeDxz9NoqDIxwPDO3Pb+e2oGlHF69JEKkxAP+1mNtzMksws2cwml7J9qJmtMrNCMxt93LaxZrbF/zW2rAoXOZVNe7IZ/dI3/PHjDfRuWY9Fvx3KpAs7KOQl7JzyiN7MIoBpwDAgHVhhZnOdc4kldksFxgH3HffcBsDDQBzggJX+5x4om/JF/ltOfiHPLdnMq19vp271qrrjk4S9QLpuBgDJzrkUADObA4wCfgx659x2/zbfcc+9DFjsnNvv374YGA7MPuvKRY7jnOPT9XuYMi+RPdl5XDegJQ9c1oX6NaO8Lk3EU4EEfXMgrcRyOjAwwNcv7bnNj9/JzCYCEwFatWoV4EuL/J8dWUd4eO4GPk/aS9emdZh2Q1/6tdbJVhEIkpOxzrnpwHSAuLg453E5UonkFxbx8hcpTFuWTGQV449XdmPs4NZEqh9e5EeBBP1OoGWJ5Rb+dYHYCVx43HM/D/C5Iif11ZZ9/PHj9Wzbd4QRPZvyxxHdaFJXN+YWOV4gQb8C6GhmbSkO7jHA9QG+/kLgMTP74X/onwEPnnaVIiVkZOfx6PxE5ifspk3DGsy8dQBDO8V6XZZI0Dpl0DvnCs3sLopDOwJ41Tm3wcymAvHOublm1h/4EKgPjDSzKc657s65/Wb2KMV/LACm/nBiVuR0FRb5mPntDp5evJljRT7uvbQjv76gPdWqahphkZMx54KrSzwuLs7Fx8d7XYYEmdWpB3jow/Uk7s5maKdYpl7VnTYxNb0uSyRomNlK51xcaduC4mSsyInsy8nn8QWbeHdlOk3qVOPFG/py+TlNNCZe5DQo6CUoFRb5ePM/xd00eQVF3H5BO+6+uCO1ovUjK3K69FsjQefbrVk8MncDSRmHOb9jDA+P7E6HRrW8Lkuk0lLQS9DYfegof/5kI/MTdtO8XnVevqkfP+vWWN00ImdJQS+eyy8sYsZX2/j70mR8znHPJR2540KNphEpKwp68dSypEymzktk274jXNa9MX8Y0Y2WDWp4XZZISFHQiyd2ZB3h0fmJLNmYSbuYmrxx6wAu0EVPIuVCQS8VKvdYIS99vpWXvkwhsoox+fIu3HpuW6IiNTeNSHlR0EuF8PkcH6/dyeMLktiTnceo3s148PKumptGpAIo6KXcrU49wJR5iaxJO0iP5nV54fo+xLVp4HVZImFDQS/lZvehozzxaRIfrt5JbO1onhzdk6v7tqBKFQ2XFKlICnopc0ePFTH9yxRe+mIrRc5x50XtuePCDrqqVcQj+s2TMuOcY+7aXTy+YBO7DuUxokdTJl/eRcMlRTymoJcysTbtIFPmbWBV6kG6N6vDM9f2ZmC7hl6XJSIo6OUs7TmUxxMLN/HBqp3E1Iri8at7MLpfSyLUDy8SNBT0ckZyjxXyyvJt/OPzrRT5HL++oD13XtSe2tWqel2aiBxHQS+npcjneH9lOk8tTiIjO5/h3Zvw4BVdaN1QNwERCVYKegnYl5v38ti/N7Jpz2F6t6zHtOv7ajy8SCWgoJdT2rg7m8f+vZHlW/bRskF1Xri+DyN6NNX0wSKVhIJeTmjPoTyeXpzEuyvTqVOtKn8Y0ZWbBrcmOlLTB4tUJgp6+S85+YVM/2Ir05enUORzjD+3LXdd3IF6NaK8Lk1EzoCCXn5UWOTjX/FpPLN4C/ty8rmyZ1MeuKwLrRrqgieRykxBLzjn+GxTJn9ZsInkzBziWtdn+s396NuqvteliUgZUNCHuZU79vPXBZtYsf0AbRrW4KUb+3JZ9yY60SoSQhT0YWpzxmGe+DSJJRsziKkVzaM/P4dr41rqBiAiIUhBH2Z2HjzKM4s38/6qdGpFRXLfzzpx63ltqRGlHwWRUKXf7jCx/8gxXlyWzMz/7ABgwnltmXRhB+rX1EgakVCnoA9xuccKmbF8G9O/TOHIsUKu7tuCe4d1onm96l6XJiIVREEfogqKfMz5PpXnliazLyefYd0ac/9lnenUuLbXpYlIBVPQhxifzzF/3W6eWpTEjqxcBrRpwMs39aVfa81JIxKuFPQhwjnH4sQMnl68mU17DtOlSW1eG9efCzvHaqikSJhT0Fdyzjm+3LKPpxYlkZB+iLYxNXluTG9G9mymm3CLCKCgr9T+k5LFU4uSWLH9AM3rVeeJ0T35ZZ/mREZoLLyI/B8FfSW0KvUATy1K4uvkLBrX0cVOInJyCvpKZP3OQzy9eDOfbcqkYc0o/jCiKzcOak21qpo2WEROLKCgN7PhwHNABPCKc+6vx22PBmYC/YAs4Frn3HYzqwq8AvT1v9dM59xfyrD+sLA54zDPLN7MgvV7qFu9Kvdf1plxQ9pQM1p/p0Xk1E6ZFGYWAUwDhgHpwAozm+ucSyyx23jggHOug5mNAR4HrgV+BUQ753qYWQ0g0cxmO+e2l/UHCUUpe3N4fukWPl67i5pRkdxzSUfGn9+WOroBt4ichkAOCQcAyc65FAAzmwOMAkoG/SjgEf/j94AXrHhMnwNqmlkkUB04BmSXTemhKzkzhxc+28LctbuIiqzC7UPbc/vQdpquQETOSCBB3xxIK7GcDgw80T7OuUIzOwQ0pDj0RwG7gRrAb51z+49/AzObCEwEaNWq1Wl+hNCRnHmY55cmMy9hF9UiI5hwfjtuO78dsbWjvS5NRCqx8u7kHQAUAc2A+sByM1vyw38HP3DOTQemA8TFxblyrinobM44zPNLt/DJut1UrxrBxKHFAR9TSwEvImcvkKDfCbQssdzCv660fdL93TR1KT4pez3wqXOuAMg0s6+BOCAFYdOebJ5fuoV/r9tDzagIfn1Be247vx0N1EUjImUokKBfAXQ0s7YUB/oYigO8pLnAWOBbYDTwmXPOmVkqcDHwppnVBAYBz5ZR7ZVW4q7igP90wx5qRUdy50XtmXCe+uBFpHycMuj9fe53AQspHl75qnNug5lNBeKdc3OBGRSHeTKwn+I/BlA8Wuc1M9sAGPCacy6hPD5IZbB+5yGeX7qFRYkZ1I6O5O6LOzD+vLbUq6GAF5HyY84FV5d4XFyci4+P97qMMrU69QDTlm1lycYMaleL5NZz23LruW2pW0PDJEWkbJjZSudcXGnbdMVNOXHO8c3WLKYtS+abrVnUrV6Vey/tyC3ntqVudQW8iFQcBX0Z8/kcSzZmMO3zraxNO0ij2tE8dEVXrhvYilq6klVEPKDkKSOFRT7mJ+zmxc+T2ZyRQ8sG1fnzL87h6r4tNBeNiHhKQX+W8guLeG9lOi9/kULq/lw6Na7Fs9f25sqeTTVdsIgEBQX9GTqSX8js71OZ/mUKmYfz6dWiLn8Y0Y9LuzbWDT9EJKgo6E/TgSPHmPntDl77ZhsHcwsY0r4hz1zbmyHtG+qWfSISlBT0AUrbn8sry1N4Jz6dowVFXNq1MZMuak/fVvW9Lk1E5KQU9KeQkH6Ql79MYcG63URUMUb1bs7Eoe3o1Li216WJiAREQV8K5xyfJ+3l5S+38p+U/dSOjuS2oe24ZUhbmtSt5nV5IiKnRUFfwrFCHx+v2ck/l6ewOSOHpnWr8dAVXRkzoCW1dbMPEamkFPRAdl4Bb3+XymtfbyMjO58uTWrz9DW9GNmrGVU1RFJEKrmwDvpdB4/y+jfbefu7VHLyCzm3Q0OeGN2LoR1jNIJGREJGWAb9qtQDvPrVNhas3wPAiB5NmTi0Hec0r+txZSIiZS9sgr6gyMen6/cw46ttrEk7SO1qkYw/ry03D25Ni/o1vC5PRKTchHzQH8w9xuzv05j57XZ2H8qjbUxNpo7qztV9W1BTk4yJSBgI2aRLzszh9W+28f7KnRwtKGJI+4b878/P4aLOjTRFgYiElZAKeuccXyXvY8ZX2/g8aS9RkVX4ee9m3HJuW7o2reN1eSIingiZoE/bn8v4N1awOSOHmFrR/PbSTtwwqBUxtaK9Lk1ExFMhE/RN61ajRf0aTBzanpG9mhIdqTngRUQghII+MqIKr47r73UZIiJBR5d9ioiEOAW9iEiIU9CLiIQ4Bb2ISIhT0IuIhDgFvYhIiFPQi4iEOAW9iEiIM+ec1zX8hJntBXacxUvEAPvKqJxQonYpndqldGqX0gVzu7R2zsWWtiHogv5smVm8cy7O6zqCjdqldGqX0qldSldZ20VdNyIiIU5BLyIS4kIx6Kd7XUCQUruUTu1SOrVL6Splu4RcH72IiPxUKB7Ri4hICQp6EZEQFzJBb2bDzSzJzJLNbLLX9VQkM3vVzDLNbH2JdQ3MbLGZbfF/r+9fb2b2vL+dEsysr3eVly8za2lmy8ws0cw2mNk9/vVh3TZmVs3Mvjeztf52meJf39bMvvN//n+ZWZR/fbR/Odm/vY2nH6CcmVmEma02s/n+5UrfLiER9GYWAUwDLge6AdeZWTdvq6pQrwPDj1s3GVjqnOsILPUvQ3EbdfR/TQT+UUE1eqEQ+L1zrhswCLjT/3MR7m2TD1zsnOsF9AaGm9kg4HHgGedcB+AAMN6//3jggH/9M/79Qtk9wMYSy5W/XZxzlf4LGAwsLLH8IPCg13VVcBu0AdaXWE4CmvofNwWS/I9fBq4rbb9Q/wI+BoapbX7SJjWAVcBAiq/4jPSv//F3ClgIDPY/jvTvZ17XXk7t0YLiP/4XA/MBC4V2CYkjeqA5kFZiOd2/Lpw1ds7t9j/eAzT2Pw7LtvL/W90H+A61zQ/dE2uATGAxsBU46Jwr9O9S8rP/2C7+7YeAhhVacMV5FngA8PmXGxIC7RIqQS8n4YoPOcJ2HK2Z1QLeB+51zmWX3BaubeOcK3LO9ab4CHYA0MXbirxnZlcCmc65lV7XUtZCJeh3Ai1LLLfwrwtnGWbWFMD/PdO/PqzaysyqUhzys5xzH/hXq238nHMHgWUUd0nUM7NI/6aSn/3HdvFvrwtkVWylFeJc4Coz2w7Mobj75jlCoF1CJehXAB39Z8ejgDHAXI9r8tpcYKz/8ViK+6d/WH+zf4TJIOBQiW6MkGJmBswANjrnni6xKazbxsxizaye/3F1is9bbKQ48Ef7dzu+XX5or9HAZ/7/hEKKc+5B51wL51wbijPkM+fcDYRCu3h9kqAMT6JcAWymuK/xIa/rqeDPPhvYDRRQ3Ic4nuK+wqXAFmAJ0MC/r1E8QmkrsA6I87r+cmyX8yjulkkA1vi/rgj3tgF6Aqv97bIe+JN/fTvgeyAZeBeI9q+v5l9O9m9v5/VnqIA2uhCYHyrtoikQRERCXKh03YiIyAko6EVEQpyCXkQkxCnoRURCnIJeRCTEKehFREKcgl5EJMT9f99yaVJdOpgkAAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.plot(auto_trace_gauss.trace-auto_trace_max.trace)" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "auto_trace_spline = FitTrace(image-bg, guess=ext_center, bins=20,\n", " peak_method='max', trace_model=models.Spline1D(degree=2))" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.plot(auto_trace_gauss.trace-auto_trace_spline.trace)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## About this notebook\n", "\n", "**Author:** Kyle Conroy, JWST\n", "**Updated On:** 2022-12-05" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Top of Page](#top)\n", "\"Space " ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.12" } }, "nbformat": 4, "nbformat_minor": 2 } astropy-specreduce-05be828/notebook_sandbox/wavecal_demo.ipynb000066400000000000000000011172741510537250300247370ustar00rootroot00000000000000{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "import matplotlib.pyplot as plt\n", "\n", "from photutils.datasets import apply_poisson_noise\n", "from astropy.modeling import models\n", "from astropy.wcs import WCS\n", "from astropy.stats import gaussian_fwhm_to_sigma\n", "from astropy.nddata import StdDevUncertainty\n", "import astropy.units as u\n", "\n", "from specreduce.compat import Spectrum as Spectrum1D\n", "from specutils.fitting import fit_generic_continuum\n", "\n", "from specreduce.calibration_data import load_pypeit_calibration_lines\n", "from specreduce.utils.synth_data import make_2d_arc_image, make_2d_spec_image\n", "from specreduce.tracing import FlatTrace\n", "from specreduce.extract import BoxcarExtract\n", "from specreduce.line_matching import match_lines_wcs, find_arc_lines" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "%load_ext autoreload\n", "%autoreload 2" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The FITS WCS standard implements ideal world coordinate functions based on the physics\n", "of simple dispersers. This is described in detail by Paper III,\n", "https://www.aanda.org/articles/aa/pdf/2006/05/aa3818-05.pdf. This can be used to model a\n", "non-linear dispersion relation based on the properties of a spectrograph. This example\n", "models the MMTO Blue Channel Spectrograph with the 500 lines/mm grating:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "blue_channel_header = {\n", " 'CTYPE1': 'AWAV-GRA', # Grating dispersion function with air wavelengths\n", " 'CUNIT1': 'Angstrom', # Dispersion units\n", " 'CRPIX1': 1344, # Reference pixel [pix]\n", " 'CRVAL1': 5410, # Reference value [Angstrom]\n", " 'CDELT1': 1.19, # Linear dispersion [Angstrom/pix]\n", " 'PV1_0': 5.0e5, # Grating density [1/m]\n", " 'PV1_1': 1, # Diffraction order\n", " 'PV1_2': 8.05, # Incident angle [deg]\n", " 'CTYPE2': 'PIXEL', # Spatial detector coordinates\n", " 'CUNIT2': 'pix', # Spatial units\n", " 'CRPIX2': 1, # Reference pixel\n", " 'CRVAL2': 0, # Reference value\n", " 'CDELT2': 1 # Spatial units per pixel\n", "}\n", "\n", "bc_linear_header = {\n", " 'CTYPE1': 'AWAV', # Grating dispersion function with air wavelengths\n", " 'CUNIT1': 'Angstrom', # Dispersion units\n", " 'CRPIX1': 1344, # Reference pixel [pix]\n", " 'CRVAL1': 5410, # Reference value [Angstrom]\n", " 'CDELT1': 1.19, # Linear dispersion [Angstrom/pix]\n", " 'CTYPE2': 'PIXEL', # Spatial detector coordinates\n", " 'CUNIT2': 'pix', # Spatial units\n", " 'CRPIX2': 1, # Reference pixel\n", " 'CRVAL2': 0, # Reference value\n", " 'CDELT2': 1 # Spatial units per pixel\n", "}\n", "\n", "blue_channel_wcs = WCS(header=blue_channel_header)\n", "bc_linear_wcs = WCS(header=bc_linear_header)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "This figure shows the difference between a constant dispersion per pixel vs the spectrograph model." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAj4AAAGwCAYAAACpYG+ZAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABUzUlEQVR4nO3dd3hT9eIG8DfpSHe69y7QUqClrFKWLBmignoRAREEQZDhwAFXBfGquC8qytXfvYK4wI3svUFGF5QO6KAt3YMmLW3TNjm/PwrRympK0pMm7+d58miTk/D2CPT1nO+QCIIggIiIiMgMSMUOQERERNReWHyIiIjIbLD4EBERkdlg8SEiIiKzweJDREREZoPFh4iIiMwGiw8RERGZDUuxAxgbjUaDwsJCODo6QiKRiB2HiIiIWkEQBFRXV8PX1xdS6c2v67D4/E1hYSECAgLEjkFERERtkJ+fD39//5u+zuLzN46OjgCaT5yTk5PIaYiIiKg1lEolAgICtD/Hb4bF52+u3d5ycnJi8SEiIupgbjdMhYObiYiIyGyw+BAREZHZYPEhIiIis8HiQ0RERGaDxYeIiIjMBosPERERmQ0WHyIiIjIbLD5ERERkNlh8iIiIyGyw+BAREZHZMMni8+mnnyI4OBg2NjaIjY3FyZMnxY5ERERERsDkis/GjRvx3HPPYfny5UhISEB0dDRGjx6N0tJSsaMRERGRyCSCIAhih9Cn2NhY9O3bF6tXrwYAaDQaBAQEYOHChViyZMlt369UKiGXy6FQKLhJKVEH1qTWoFEtoFGjQWNT87+rBQGWUgmsLKSwsrj2TykspLfe1JCIjF9rf36b1O7sDQ0NiI+Px9KlS7XPSaVSjBw5EsePH7/he1QqFVQqlfZrpVJp8JxEpLsmtQbFynqUKOtRrFCh5Oq/lyjrcbm2Ecr6RijrGqGsb4KyrhGqJk2rP9vO2gJONlaQ2zY/nGyt4Okkg4+TDXycbeEjt4G33Ab+LraQWVoY8LskIkMzqeJTXl4OtVoNLy+vFs97eXkhPT39hu9ZuXIlVqxY0R7xiKgVSqvrkVFcjZzyK8gpv4KL5VeQW1GL/Mu1aFS3/QK1hVQCC4kETRoNNH/7mNoGNWob1ChW1t/yM6QSINDVDmEeDgjzdECYhz26+crRxcsR1pYmN3KAyCSZVPFpi6VLl+K5557Tfq1UKhEQECBiIiLzoNYIyCytwblCBdKLq5FWpERakRLlNQ03fY+1hRRechm8HG3gJbeBt5MNvJxkcLWXwcnGEk62VnCysYKTrSXsrS1hbSmFpYUEVlIppH+5naXRXL0FphbQ2KRBdX0TFHWN2kdVXQNKlSoUKepQpKhHsaIehVV1uNKgxsWKWlysqMXe9NIWuSJ8HNHDT44ofzn6hbgh2M0OEglvoREZG5MqPu7u7rCwsEBJSUmL50tKSuDt7X3D98hkMshksvaIR2TWLl9pQGL+ZSTmVSEh7zKS8xWoUTVdd5xEAoS42SPUwwEh7nYIdrdHiJs9gt3t4e1k06LAtJVUKoFMagGZJQAZ4GJvfdv3CIKAsmoVMstqkFV2BVmlNbhQWo2UAiUUdY04c0mBM5cU+PZE8/FeTjL0D3VD/1A3DAhzQ5Cb/R3nJqI7Z1LFx9raGr1798bevXsxYcIEAM2Dm/fu3YsFCxaIG47IzFTUqPBHdiWOZZXjeHYFssuuXHeMnbUFuvk6oavPn49wL0fYWhvfOBqJRAJPJxt4OtlgQJi79nlBEJBfWYczBVU4e0mBhLzLSMqvQolShU1JhdiUVAgACPOwx4iuXhge4Yk+QS6wtOCtMSIxmNysro0bN2L69On4/PPP0a9fP6xatQo//PAD0tPTrxv7cyOc1UXUNjWqJvyRVYFjWRU4llWO9OLq644J9bBHTIALegU5o1egC7p4OZrkjKq6BjUS8y7jj+wKHM+uQGJeFZr+MrDIycYSI7t64b6evhjUyR1WLEFEd6y1P79NrvgAwOrVq/Hee++huLgYPXv2xMcff4zY2NhWvZfFh6j1LpZfwd70UuxPL8WJnIrrBh9HeDsiLswNcaFu6Bvs2qpbSqZIUdeIwxfKsC+tFPszSnG5tlH7mqu9Ne7p4Y37o/3QJ8hFL7fyiMyRWRefO8HiQ3RzTWoNTuZUastOdnnL21eBrnYY1NkdA8Kax7a4O3D83N+pNQLicy9jy5lCbD1ThIorfw7mDnazwyP9AvGP3v48d0Q6YvFpIxYfopYa1Rocy6rAtjNF2JVa3OJqhaVUgn4hrhge4YlhEZ4IdbfnTCYdNF09t78nF2JHSrF2sLeVhQSjIr0xJTYQA8LceE6JWoHFp41YfIiAhiYNjmaWY+vZIuxOLYGiruWtmeERnhge4YlBnd3hZGMlYlLTUdvQhC3JRfjuZB6S8qu0z0d4O+KJwaG4P9qXawUR3QKLTxux+JC50mgEnLxYiV8TCrAtpQjV9X9ONXd3kGFMdy/c090H/UJcOSPJwFILlfj+ZB5+TriE2gY1AMDTUYbpA4LxaGwQ5HYsm0R/x+LTRiw+ZG4yS6vxS0IBNiUVoqCqTvu8p6MMY7t7Y2wPH/QNdjXJ2VfGTlHbiO9O5mHt0RyUVjdvreMgs8TjA4PxxKBQFiCiv2DxaSMWHzIH5TXNa8z8lliAswUK7fOOMkvc08MHE2L8EBviyhlGRqKhSYPNyYX44lA2MkqalwlwlFli5qAQzBwUArktCxARi08bsfiQqdJoBBzOLMeGk3nYnVqiXVfGUirB0HAPTIjxw8iuXrCxMr7FA6mZRiNg57lirNpz4c8CZGOJp4Z2wuMDg/nfjswai08bsfiQqSlS1OHH05ew8VR+i1tZ0f5yPNjLH/dG+cCNU6c7FI1GwPaUYny09zzOl9QAAPycbfHimHDcH+3LWWBkllh82ojFh0xBk1qDfeml2HAqHwcySrW7kTvZWOLBXv6Y1DcAXX34+7uj02gE/JpYgPd2Zmh3lo8OcMar47qiT7CryOmI2heLTxux+FBHVlatwoaTefj2RJ72ByEA9AtxxeR+ARjb3Ye3Q0xQXYMa/zuSjTUHsnDl6iywf/T2x9KxEbyaR2aDxaeNWHyoI0rMu4z1x3Ox9UwRGtQaAICbvTX+0bv56k6oh4PICak9lFbX48Nd57HhVD4AQG5rhZfGROCRvgEcqE4mj8WnjVh8qKNQNamxJbkI649fRPKlP2dm9QxwxowBwRjbwxsyS17dMUcJeZfx8q8pSCtSAmj+PfH2Qz0Q4c2/08h0sfi0EYsPGbtiRT2+/uMiNpzM1+7zZG0hxb3RPpgeF4zoAGdxA5JRaFJrsP54Lj7cfR41qiZYWUiwaHhnzB0axt3gySSx+LQRiw8Zq7QiJf7vcDY2Jxdqd0H3kdvg0f5BeKRvAMdy0A0VK+rx6qYU7E4tAQB093PC+xOjefWHTA6LTxux+JAxEQQBhy6U47+Hs3H4Qrn2+X7Brnh8YDDujvTi9hF0W4Ig4LekArz2eyoUdY2wspDgmZFdMPeuMK7ITSaDxaeNWHzIGKia1Pg9qRD/PZyjXahOKgHu6eGD2YNDeTuL2qRUWY9//noWe9JKAQCxIa5Y9UhP+MhtRU5GdOdYfNqIxYfEVFXbgG9P5OGrYxe1ezPZW1tgUt9APD4wGAGudiInpI5OEAT8nFCA5ZtScKVBDWc7K7zzUBRGd/MWOxrRHWHxaSMWHxJDsaIe/3c4G9+fzNPuxu3lJMPjA0MwuV8g92Iivcspv4JF3ydq92p7tH8gXhkXyXWeqMNi8WkjFh9qTxfLr+A/B7Pwc8Il7YDlCG9HzBkSinujfGFtyfE7ZDgNTRp8sCsDnx/KBgBE+jjh82m9eWWROiQWnzZi8aH2kFakxGcHsrD1TKF2O4l+Ia6YP6wThnR2515L1K4OnS/DsxuTUHGlAXJbK3z0SE8MDfcUOxaRTlh82ojFhwwpPrcSn+7Pwr70Uu1zwyM88dTQMO6tRKIqrKrDvG8TkJxfBYkEeHZkFywY1okrPlOHweLTRiw+pG/XpqR/uj8TJ3MqAfw5Q2ve0DB085WLnJComapJjRWbU/HdiTwAwMiunvj3pJ5wtOEYMzJ+LD5txOJD+qLRCNh5rhifHshESkHz1gFWFhI81MsfT94VhhB3e5ETEt3YD6fz8cpvKWho0qCLlwP+N70vx/2Q0WPxaSMWH7pTGo2A7SnF+HjvBe0aPLZWFpgSG4gnBodwzRTqEM5cqsITX51GabUK7g7W+OKxPugV6CJ2LKKbYvFpIxYfaiuNRsC2lCJ8vPcCzpfUAAAcZZaYMTAYjw8Mgau9tcgJiXRTpKjDrHWnkVqkhLWlFO9PjMb90b5ixyK6IRafNmLxIV2pNQK2nS3CJ/v+UnhsLDFzYAhmDgyB3I7jI6jjuqJqwtMbkrAnrXmvr+fu7oKFwztx5iEZHRafNmLxodZSawRsPVuET/ZewIXSPwvPrEEheHxgCBcdJJOh1ghYuS0N/z2SAwCYGhuI18d35z5fZFRa+/Pbsh0zEZkEtUbAljOF+GRfJjKvFh4nG0vMGhSKGQODWXjI5FhIJXjl3kgEudlh2e/n8O2JPFyubcC/J/WEzJIrPVPHwuJD1ErXCs/Hey8gq+wKgObC88Tg5sLjxCm/ZOKmxQXD1V6GZzcmYdvZYlTVnsLn03pzujt1KCw+RLeh1gjYnFyIj/ddQPbVwiO3tcITg0IwnYWHzMy4KB8421lhzvrTOJZVgcn/9wfWzugHD0eZ2NGIWoVjfP6GY3zomia1Bpuv3tK6Vnic7a4WngHB/L9cMmtnLykwY+1JVFxpQKi7Pb6b3R/echuxY5EZ4+DmNmLxoSa1Br8nF2L1vkxkl/9ZeGYPDsVjcUEsPERX5ZRfwaP/PYGCqjoEudnhu9n94efMdapIHCw+bcTiY76a1BpsSirE6v2ZyLlaeFzsrPDE4FBMHxAMBxnvDBP9XX5lLab89w/kV9bB38UW38/uz1WeSRQsPm3E4mN+mtQa/JZUiNX7LuBiRS2A5sIze0goHotj4SG6ncKqOkz5vz9wsaIWvnIbfD+nP4LcuCULtS8WnzZi8TEfTWoNfk0swOr9mci9Wnhc7a21t7TsWXiIWq1EWY/J//cHssuuwMtJhg1z4rgfHbUrFp82YvExfY1XC8+nfys8c4aEYlp/Fh6itiqrVmHqf//A+ZIa+Mpt8MPcOPi78LYXtQ8WnzZi8TFdjWoNfk1ovsKTV9lceNzsrfHkXaF4tH8Q7KxZeIjuVHmNCpM+P46ssisIdLXDj3Pj4OXE2V5keCw+bcTiY3oa1Rr8knAJq/dnIr+yDgDg7tB8hYeFh0j/ihX1ePjz48irrEUnTwdsnNMfbg5c54cMi8WnjVh8TEdD05+F59LlPwvP3LvCMDU2CLbWXGqfyFDyK2vx8OfHUaSoR1cfJ2yY3Z8b9pJBsfi0EYtPx9fQpMHPCZewel8mCqquFR4Z5t4VysJD1I6yy2rw8Od/oLxGhZ4Bzvj2iViOoSODae3Pb2k7ZjKoixcvYtasWQgJCYGtrS3CwsKwfPlyNDQ0iB2N2klDkwbfnsjFsPcPYOkvZ1FQVQcPRxlevTcSh18chicGh7L0ELWjUA8HfPtELJztrJCUX4Wnvk1Ao1ojdiwycyZTvdPT06HRaPD555+jU6dOSElJwezZs3HlyhW8//77YscjA1I1qfHj6UtYcyBLe4XHw1GGeXeFYUpsIGysWHaIxBLu7Yi1M/piyv+dwMHzZXjp5zP4YGI0JBKJ2NHITJn0ra733nsPa9asQXZ29k2PUalUUKlU2q+VSiUCAgJ4q6sDUDWp8cPpS1izPxOFinoAgKejDPOGhmFyPxYeImOyL70Es9fHQ60RMPeuMCwZGyF2JDIxrb3VZTJXfG5EoVDA1dX1lsesXLkSK1asaKdEpA/1jWr8eDofnx3IQtFfCs9TQ8PwCAsPkVEaHuGFtx/sgRd+OoP/HMyCp6MMMweFiB2LzJDJXvHJzMxE79698f7772P27Nk3PY5XfDqOK6omfHciD/93OBul1c3/zbycZHhqaCdM6hvAwkPUAXy6PxPv7cyARAJ8/EgM7ov2FTsSmQiTueKzZMkSvPPOO7c8Ji0tDRERf142LSgowJgxYzBx4sRblh4AkMlkkMm4voQxU9Q14qtjF7H2aA4u1zYCAHzlNnjyrjAWHqIO5qmhYSirVmHdsYtY/GMyfJ1t0Dvo1lfmifTJ6K/4lJWVoaKi4pbHhIaGwtraGgBQWFiIoUOHon///li3bh2kUt0mrnE6u/GoqFHhf0dy8PXxXFSrmgAAwW52mDc0DA/E+MPa0mQmJRKZFY1GwNxv4rErtQRu9tb4bf5A7uhOd8ws1/EpKCjAsGHD0Lt3b3zzzTewsND9SgCLj/iKFfX44lA2vjuZi/rG5qmv4V6OeGpYGMb18IGlBQsPUUdX29CEif85jnOFSnT2dMDPTw2Akw0XOKS2M7viU1BQgKFDhyIoKAhfffVVi9Lj7e3d6s9h8RFPXkUt1hzMws/xl9Bwda2PaH855g/rhJFdvSCVcvorkSkpVtRj/KdHUKJUYUgXD3w5vQ//x4bazGTG+LTW7t27kZmZiczMTPj7+7d4zUS6nclKLVTii0NZ2HymCGpN83+rfiGuWDCsEwZ3dud6H0Qmyltug/9N74uJ/zmOQ+fL8PqWVLw+vrvYscjEmcwVH33hFZ/2IQgCjmZW4PNDWTh8oVz7/F1dPLBgeCf0DeZgRyJzsSOlGPO+jYcgAP8a3w3T4oLFjkQdkNld8aGOoUmtwdazRfjiUDbOFSoBAFIJMC7KF08OCUV3P7nICYmovY3p7o0XR0fgnR3pWLE5FRE+TvyfHzIYFh9qF7UNTdh4Kh//O5Kj3SndxkqKR/oGYtagEM7oIDJzc+8KxblCBbacKcK8bxKwZeEgeMttxI5FJojFhwyqrFqF9ccv4us/clF1dQ0eV3trTI8LxrS4ILjaW4uckIiMgUQiwbv/iEJmaQ3Si6sx95t4bHyyP2SWXKeL9IvFhwwipUCBL4/mYEtykXaGVqCrHWYPCcU/evlzl3Qiuo6dtSW+mNYH960+gqT8Krz2+zmsfDBK7FhkYlh8SG+a1BrsTi3Bl0dzcOriZe3z0QHOeHJIKEZ384YFp6QT0S0Eutnhk8kxmLH2JL4/mY8efs6YEhsodiwyISw+dMcUtY3YcCoP64/noqCqefyOpVSCe3r44PGBwYgJdBE5IRF1JEO6eOCFq4Odl/+egggfR/Ti3yOkJyw+1GbpxUp8fTwXvyQUoK5RDaB5/M6UfoF4tH8QByYSUZvNvSsUZwuqsO1sMRZ+l4itiwbB2Y5jAunOsfiQTuob1dh2tgjfnshDfO6ft7MivB0xc2AI7u/py01DieiOSSQSvPNQFNKKqpFTfgWLf0jG/z3Whyu40x1j8aFWyS6rwXcn8vBTwiXt7CxLqQSjunlhWv9g9A915QrLRKRXjjZWWD0lBg98dgx700vx3yPZmDMkTOxY1MGx+NBNNTQ1D1b+9kQujmVVaJ/3c7bF5H4BeLhPADydeDuLiAynm68cy++LxMu/puCdHRnoHeSC3kFc3JDajsWHWhAEAecKlfgp/hI2JRXg8tWrOxIJMDzcE1P7B+KuLp6cnUVE7WZKv0CcyK7E78mFWPBdIrYuGsw1wKjNWHwIAFBeo8JviQX4Kf4S0ourtc97OsowqW8AJvUNgL8LV1cmovYnkUjw1oM9cLZAgZzyK3juhyR8Ob0vx/tQm7D4mLH6RjUOZJTi54QC7E8vRdPVndGtLaUYFemFf/T2x6BO7rC0kIqclIjMnYPMEp9O6YUHPjuKAxll+PJoDp4YHCp2LOqAWHzMTKNagyOZ5dicXIhd50pQo2rSvhYd4Ix/9PbH/VG+kNtZiZiSiOh6kb5OePXeSLzyWwre3ZGBAWHuiPS9+S7cRDfC4mMG1BoBJ3IqsDm5CDtSirTjdgDAR26D+6N98VBvf3TxchQxJRHR7U2NDcSBjFLsSSvF0xsSsXnhIC6hQTph8TFR9Y1qHMsqx+7UEuxOLUV5jUr7mruDNcb18MF90b7oFejC++RE1GFcW99n9KrDuFBag5Xb0rBifHexY1EHwuJjQhS1jdiXUYLdqSU4kFGG2ga19jW5rRXGdvfGfdG+iA1x5bgdIuqw3BxkeH9iFGasPYWvjudiaLgnhkV4ih2LOggWnw5Mo2meen7oQhkOnS9DfO5l7QBlAPB2ssHdkV4Y1c0LsSFusLZk2SEi0zA03BOPDwzG2qMX8cJPydj+9BB4OMrEjkUdAItPB1OirMfhC+U4fKEMRy6Uo+JKQ4vXw70ctWWnh5+cqykTkcl6aUwEjmdVIL24Gi/+lIwvZ/Tl33l0Wyw+RkwQBORX1uFETgVOXazEyZxKXKyobXGMg8wScWFuGNLZHUO6eCDIzV6ktERE7cvGygIfPRKD+1Yfwf6MMmw4lY/J/QLFjkVGjsXHiNSomnCuQIGzBQok5Vfh1MVKlChVLY6RSIAefnIM6eyBwZ3d0SvIBVYcr0NEZirc2xEvjg7HG1vT8MaWVAzu7M7FVumWWHxEIAgCSqtVuFBSg4ySapwrUOBMgQJZZTUQhJbHWllIEO3vjL4hrugX4oreQS5wsuEaO0RE1zw+MAQ7UopxOvcyXvzpDL6ZFcvZqnRTLD7toL5RjW9P5OFCSTUulNbgQkk1lPVNNzzWz9kWPfzk6OEvR+8gF/QMcOYaFUREt2AhleD9idEY89EhHMuqwLcncjEtLljsWGSkWHzagaVUgre3p6FR/eflHAupBEFudujs6YBIHzmi/OXo7ifnrAQiojYIdrfHkjEReG1zKt7als4xj3RTLD7twNJCikf7B8FRZolOXo7o4uWAEHd7yCx5JYeISF8eiwvGjnPF+CO7Ei/8eAYb5vTnLS+6jkQQ/j6qxLwplUrI5XIoFAo4OXEPGCKijiS/shajVx1CbYMar94biVmDQsSORO2ktT+/OR2IiIhMRoCrHf55T1cAwLs70pFbcUXkRGRsWHyIiMikTI0NxIAwN6iaNPjnr2fBGxv0Vyw+RERkUiQSCd56oAdkllIczazAzwkFYkciI8LiQ0REJifY3R7PjOwCAHhjayrKa1S3eQeZCxYfIiIySU8MDkGkjxOqahvx+uZUseOQkWDxISIik2RlIcU7D0VBKgF+Ty7E/vRSsSOREWDxISIik9XDX66d0v7yr2dRo7rxqvlkPlh8iIjIpD17dxf4u9iiUFGP93dmiB2HRMbiQ0REJs3O2hJvPdADAPDV8Ys4e0khciISE4sPERGZvCFdPDC+py8EAXhlUwo0Gq7tY67aVHzy8vJw+PBh7Ny5EwkJCVCpOE2QiIiM28v3dIWjzBLJ+VXYcCpf7DgkklYXn4sXL+Kll15CUFAQQkJCcNddd2Hs2LHo06cP5HI57r77bvz444/QaDSGzEtERNQmnk42ePbu5rV93tmRjgqu7WOWWlV8Fi1ahOjoaOTk5OCNN95AamoqFAoFGhoaUFxcjG3btmHQoEFYtmwZoqKicOrUKUPnviWVSoWePXtCIpEgKSlJ1CxERGQ8HosLQlcfJyjqGvHOjnSx45AIWlV87O3tkZ2djR9++AHTpk1DeHg4HB0dYWlpCU9PTwwfPhzLly9HWloa3n//feTni3sJ8cUXX4Svr6+oGYiIyPhYWkjxxoRuAIAfTl9CfG6lyImovbWq+KxcuRJubm6t+sAxY8bgwQcfvKNQd2L79u3YtWsX3n//fdEyEBGR8eod5IqH+/gDAF757Rya1ByiYU5MalZXSUkJZs+eja+//hp2dnateo9KpYJSqWzxICIi0/bSmAjIba2QVqTE13/kih2H2pHOxaeiogLz589HZGQk3N3d4erq2uIhFkEQMGPGDMydOxd9+vRp9ftWrlwJuVyufQQEBBgwJRERGQM3BxleHBMOAPhw13mUVXOgs7mw1PUN06ZNQ2ZmJmbNmgUvLy9IJBJD5NJasmQJ3nnnnVsek5aWhl27dqG6uhpLly7V6fOXLl2K5557Tvu1Uqlk+SEiMgOT+wZi46l8nLmkwAe7MvD2Q1FiR6J2IBEEQadVnBwdHXHkyBFER0cbKlMLZWVlqKiouOUxoaGhePjhh7F58+YWRUytVsPCwgJTp07FV1991apfT6lUQi6XQ6FQwMnJ6Y6yExGRcYvPrcRDa45DIgE2LxiE7n5ysSNRG7X257fOV3wiIiJQV1d3R+F04eHhAQ8Pj9se9/HHH+ONN97Qfl1YWIjRo0dj48aNiI2NNWREIiLqoHoHueL+aF/8nlyI1zenYuOT/Q1+J4PEpXPx+eyzz7BkyRIsW7YM3bt3h5WVVYvXxbpKEhgY2OJrBwcHAEBYWBj8/f3FiERERB3AkrER2JVajJMXK7H1bBHujeJyKKZM58HNzs7OUCqVGD58ODw9PeHi4gIXFxc4OzvDxcXFEBmJiIgMxtfZFnPvCgMArNyWjvpGtciJyJB0vuIzdepUWFlZ4bvvvmuXwc1tFRwcDB2HLxERkZl6ckgYfjiVj4KqOnxxKBuLRnQWOxIZiM7FJyUlBYmJiQgPDzdEHiIionZna22BJfd0xaLvE7HmQBYm9vGHj9xW7FhkADrf6urTp4/oW1IQERHp231RPugT5IK6RjXe2c59vEyVzsVn4cKFePrpp7Fu3TrEx8fjzJkzLR5EREQdkUQiwfL7ukEiAX5LKkRSfpXYkcgAdF7HRyq9vitJJBIIggCJRAK1umMPCuM6PkRE5u25H5LwS0IBYkNcsWEOp7d3FAZbxycnJ+eOghERERmz50eFY8uZIpzIqcTetFKMjPQSOxLpkc7FJygoyBA5iIiIjIKvsy1mDgzBfw5m4e0d6Rga7gFLC5Pa09ustem/ZFZWFhYuXIiRI0di5MiRWLRoEbKysvSdjYiISBRPDQuDi50VMktr8GP8JbHjkB7pXHx27tyJyMhInDx5ElFRUYiKisKJEyfQrVs37N692xAZiYiI2pWTjRUWDm9ey+fD3edxRdUkciLSF50HN8fExGD06NF4++23Wzy/ZMkS7Nq1CwkJCXoN2N44uJmIiACgoUmDkR8eRF5lLZ4d2QVPj+SihsastT+/db7ik5aWhlmzZl33/MyZM5GamqrrxxERERkla0spXhzTvFjv54eyUFatEjkR6YPOxcfDwwNJSUnXPZ+UlARPT099ZCIiIjIK43r4IDrAGbUNaqzac17sOKQHOs/qmj17NubMmYPs7GwMGDAAAHD06FG88847eO655/QekIiISCwSiQT/HBuBSV/8gQ2n8jFrUAhCPRzEjkV3QOcxPoIgYNWqVfjggw9QWFgIAPD19cULL7yARYsWdfiFnjjGh4iI/m7WulPYm16K+6J98cnkGLHj0A0YZIxPU1MTvv76a0yZMgWXLl2CQqGAQqHApUuX8PTTT3f40kNERHQji0c1j/XZnFyI1EKlyGnoTuhUfCwtLTF37lzU19cDABwdHeHo6GiQYERERMYi0tcJ90X7AgA+2JUhchq6EzoPbu7Xrx8SExMNkYWIiMhoPTuyMyykEuxNL0V87mWx41Ab6Ty4+amnnsLixYtx6dIl9O7dG/b29i1ej4qK0ls4IiIiYxHq4YB/9PLHxtP5eG9nOr6fzQ1MOyLuzv43HNxMREQ3U1BVh2HvHUCDWoNvZsViUGd3sSPRVdydnYiISM/8nG0xtX8g1h69iPd2pmNgp4G86tPB6DzGJzc3F35+fggKCmrx8PPzQ25uriEyEhERGY2nhnaCrZUFki8psCu1ROw4pCOdi8+wYcNQWVl53fMKhQLDhg3TSygiIiJj5eEow8xBwQCAD3edh1qj04gREpnOxefaWJ6/q6iouG6gMxERkSmaMzgMTjaWyCipxpYzhWLHIR20eozPgw8+CKB5IPOMGTMgk8m0r6nVapw5c0a7hQUREZEpk9tZYc6QULy/6zw+3nsB90b5wkLKsT4dQauv+MjlcsjlcgiCAEdHR+3Xcrkc3t7emDNnDr755htDZiUiIjIa0wcEQ25rhayyK7zq04G0+orP2rVrAQDBwcF4/vnneVuLiIjMmqONFZ4YFIIPdp/HJ/syedWng9B5jM+LL77YYoxPbm4uVq1ahV27duk1GBERkbGbPjAYTjaWyCytwdazRWLHoVbQufiMHz8e69evBwBUVVWhX79++OCDDzB+/HisWbNG7wGJiIiMlZONFZ4YHAoA+GTvBWg4w8vo6Vx8EhISMHjwYADATz/9BG9vb+Tm5mL9+vX4+OOP9R6QiIjImM24etXnQmkNtqXwqo+x07n41NbWandk37VrFx588EFIpVL079+fCxgSEZHZcbKxwqxBzVd9PuZVH6Onc/Hp1KkTfvvtN+Tn52Pnzp0YNWoUAKC0tJR7WxERkVm6dtXnfEkNtqcUix2HbkHn4rNs2TI8//zzCA4ORmxsLOLi4gA0X/2JiYnRe0AiIiJjJ7e1wsxBIQCAj/ae51UfI6bz7uwAUFxcjKKiIkRHR2t3az958iScnJwQERGh95DtibuzExFRWyjqGjHonX2orm/CZ1N74Z4ePmJHMiut/fmt8xUfAPD29kZMTIy29ABAv379OnzpISIiaiu5rRVmDmy+6rN6XybacF2B2kGrFzC85oEHHrjhXl0SiQQ2Njbo1KkTpkyZgvDwcL0EJCIi6igeHxiM/zucjdQiJQ6cL8OwcE+xI9Hf6HzFRy6XY9++fUhISIBEIoFEIkFiYiL27duHpqYmbNy4EdHR0Th69Kgh8hIRERktZztrPNo/CADw2f5MkdPQjehcfLy9vTFlyhRkZ2fj559/xs8//4ysrCw8+uijCAsLQ1paGqZPn46XXnrJEHmJiIiM2qxBIbC2kOLUxcs4mVMpdhz6G52Lz//+9z8888wzLcb3SKVSLFy4EF988QUkEgkWLFiAlJQUvQYlIiLqCLycbPCPPv4AgM8O8KqPsdG5+DQ1NSE9Pf2659PT06FWqwEANjY2NxwHREREZA7mDgmDVAIcyChDSoFC7Dj0FzoXn2nTpmHWrFn497//jSNHjuDIkSP497//jVmzZuGxxx4DABw8eBDdunXTe9jW2Lp1K2JjY2FrawsXFxdMmDBBlBxERGS+At3scF+0LwBgzcEskdPQX+k8q+vf//43vLy88O6776KkpAQA4OXlhWeffVY7rmfUqFEYM2aMfpO2ws8//4zZs2fjrbfewvDhw9HU1MRbbkREJIp5Q8OwKakQ284WIbusBqEeDmJHIrRxAcNrlEolABjFQn9NTU0IDg7GihUrMGvWrDZ/DhcwJCIifXniq9PYk1aCh/v4491/RIsdx6QZdAHDa5ycnIymHCQkJKCgoABSqRQxMTHw8fHB2LFjb3vFR6VSQalUtngQERHpw1PDwgAAvyYWoLCqTuQ0BLSh+JSUlGDatGnw9fWFpaUlLCwsWjzEkp2dDQB47bXX8Morr2DLli1wcXHB0KFDUVl58+mEK1euhFwu1z4CAgLaKzIREZm4XoEuiAt1Q6NawP8dzhY7DqENt7rGjh2LvLw8LFiwAD4+PtfN3ho/frxeAy5ZsgTvvPPOLY9JS0tDQkICpk6dis8//xxz5swB0Hw1x9/fH2+88QaefPLJG75XpVJBpVJpv1YqlQgICOCtLiIi0ovDF8ow7X8nYWdtgWNLhsPZzlrsSCaptbe6dB7cfOTIERw+fBg9e/a8k3yttnjxYsyYMeOWx4SGhqKoqAgAEBkZqX1eJpMhNDQUeXl5N32vTCaDTCbTS1YiIqK/G9TJHZE+TkgtUuLbE3mYP6yT2JHMms7FJyAgoF03XvPw8ICHh8dtj+vduzdkMhkyMjIwaNAgAEBjYyMuXryIoKAgQ8ckIiK6IYlEgjlDQvHMxiSsPXoRTwwOgcxSvKEh5k7nMT6rVq3CkiVLcPHiRQPEaTsnJyfMnTsXy5cvx65du5CRkYF58+YBACZOnChyOiIiMmfjonzgI7dBeY0KmxILxY5j1nS+4jNp0iTU1tYiLCwMdnZ2sLKyavH6rQYSG9p7770HS0tLTJs2DXV1dYiNjcW+ffvg4uIiWiYiIiIrCylmDgzBm9vS8MXhbPyjtz+kUu5wIAadBzd/9dVXt3x9+vTpdxRIbFzHh4iIDKG6vhEDVu5DtaoJX87og+ERXmJHMikGG9x8q2Ij5tUeIiIiY+ZoY4XJsYH44lA2vjiUzeIjkjtawPCaXbt24eGHH4afn58+Po6IiMgkzRgQDEupBH9kV+LMpSqx45ilNhef3NxcLF++HMHBwZg4cSKkUinWr1+vz2xEREQmxdfZFvdf3bz0i0Nc0FAMOt3qamhowC+//IL//ve/OHr0KEaOHIlLly4hMTERPXr0MFRGIiIik/HE4FD8kliAbWeLkF9ZiwBXO7EjmZVWX/FZuHAhfH198dFHH+GBBx7ApUuXsHnzZkgkElG3qiAiIupIIn2dMLizOzQC8OXRHLHjmJ1WF581a9bgySefxK5duzB//ny4ubkZMhcREZHJmj04FACw8VQ+FLWNIqcxL60uPl9//TVOnjwJHx8fTJo0CVu2bIFarTZkNiIiIpM0uLM7wr0cUdugxsbTN99WifSv1cVn8uTJ2L17N86ePYuIiAjMnz8f3t7e0Gg0SE1NNWRGIiIikyKRSPD4wGAAwFfHctGk1ogbyIzoPKsrJCQEK1aswMWLF/HNN9/goYcewqOPPgp/f38sWrTIEBmJiIhMzoQYP7jYWaGgqg570krEjmM22jydXSKRYPTo0fjhhx9QWFiI559/HgcPHtRnNiIiIpNlY2WByf0CAQBfHr0obhgzopcFDF1dXfHMM88gOTlZHx9HRERkFqbFBcFCKsHJnEqcK1SIHccstKr4vP3226irq2vVB544cQJbt269o1BERETmwEdui7HdvQEAa3nVp120qvikpqYiMDAQTz31FLZv346ysjLta01NTThz5gw+++wzDBgwAJMmTYKjo6PBAhMREZmSmYNCAAC/JxWivEYlchrT16ris379euzZsweNjY2YMmUKvL29YW1tDUdHR8hkMsTExODLL7/EY489hvT0dAwZMsTQuYmIiExCr0AXRAc4o0GtwXcnOLXd0CSCIAi6vEGj0eDMmTPIzc1FXV0d3N3d0bNnT7i7uxsqY7tq7bb2RERE+rIpqQBPb0iCh6MMR18aDmtLvQzBNSut/fmt015dACCVStGzZ0/07NnzTvIRERHRVWO7++BNxzSUVquw7WwRJsT4iR3JZLFSEhERiczaUopp/YMAAGuP5kDHmzGkAxYfIiIiIzAlNhDWllIkX1IgIa9K7Dgmi8WHiIjICLg5yDA+2hcAsP74RXHDmDAWHyIiIiMxfUAwAGDb2SJObTcQFh8iIiIj0d1Pjp4BzmhUC9h4Kl/sOCZJ51ldV65cwdtvv429e/eitLQUGk3LHWWzs7P1Fo6IiMjcTOsfhKT8Knz7Ry7m3hUGC6lE7EgmRefi88QTT+DgwYOYNm0afHx8IJHwPwgREZG+jIvywRtbU1GoqMe+9FLcHekldiSTonPx2b59O7Zu3YqBAwcaIg8REZFZs7GywMN9A/D5wWysP36RxUfPdB7j4+LiAldXV0NkISIiIgBT+wVBIgEOXyhHTvkVseOYFJ2Lz7/+9S8sW7YMtbW1hshDRERk9gLd7DC0iwcA4Ns/ckVOY1p0vtX1wQcfICsrC15eXggODoaVlVWL1xMSEvQWjoiIyFxNiwvC/owy/HA6H4tHhcPW2kLsSCZB5+IzYcIEA8QgIiKiv7qriycCXG2RX1mHzcmFeLhvgNiRTILOu7ObOu7OTkRExuI/B7Pw9vZ0dPdzwuYFgziT+hZa+/O7zQsYxsfH45tvvsE333yDxMTEtn4MERER3cTDfQJgbSlFSoESSflVYscxCTrf6iotLcUjjzyCAwcOwNnZGQBQVVWFYcOGYcOGDfDw8NB3RiIiIrPkam+Ne3v44JfEAnx9PBcxgS5iR+rwdL7is3DhQlRXV+PcuXOorKxEZWUlUlJSoFQqsWjRIkNkJCIiMluPxgUBALacLUJVbYPIaTo+nYvPjh078Nlnn6Fr167a5yIjI/Hpp59i+/bteg1HRERk7mICnBHh7YiGJg1+TSwQO06Hp3Px0Wg0101hBwArK6vr9u0iIiKiOyORSDAlNhAA8P3JPHBO0p3RufgMHz4cTz/9NAoLC7XPFRQU4Nlnn8WIESP0Go6IiIiA8T39YGMlxfmSGiTkXRY7Toemc/FZvXo1lEolgoODERYWhrCwMISEhECpVOKTTz4xREYiIiKzJre1wrgevgCA70/mi5ymY2vTOj6CIGDPnj1IT08HAHTt2hUjR47UezgxcB0fIiIyRvG5lXhozXHYWElx4p8jIbe9ftiJOWvtz2+dp7MDzfcb7777btx9991tDkhERESt1yvQBV28HHC+pAabkgrwWFyw2JE6pFYVn48//hhz5syBjY0NPv7441seyyntRERE+ieRSDC5XyBWbE7FdyfyMK1/EFdyboNW3eoKCQnB6dOn4ebmhpCQkJt/mESC7OxsvQbUxfnz5/HCCy/g6NGjaGhoQFRUFP71r39h2LBhrf4M3uoiIiJjVVXbgNi39kLVpMFv8weiZ4Cz2JGMhl5vdeXk5Nzw343Nvffei86dO2Pfvn2wtbXFqlWrcO+99yIrKwve3t5ixyMiIrojznbWuKeHD35NLMD3J/JYfNpA51ldr7/+Ompra697vq6uDq+//rpeQrVFeXk5Lly4gCVLliAqKgqdO3fG22+/jdraWqSkpNz0fSqVCkqlssWDiIjIWE3u17ymz+/JhaiubxQ5Tcejc/FZsWIFampqrnu+trYWK1as0EuotnBzc0N4eDjWr1+PK1euoKmpCZ9//jk8PT3Ru3fvm75v5cqVkMvl2kdAQEA7piYiItJN32AXhHnYo65Rjd+TC2//BmpB5+IjCMINB1MlJyfD1dVVL6HaQiKRYM+ePUhMTISjoyNsbGzw4YcfYseOHXBxufmmbkuXLoVCodA+8vO5PgIRERmva4OcgeaVnEk3rS4+Li4ucHV1hUQiQZcuXeDq6qp9yOVy3H333Xj44Yf1HnDJkiWQSCS3fKSnp0MQBMyfPx+enp44fPgwTp48iQkTJuC+++5DUVHRTT9fJpPBycmpxYOIiMiYPdjLH9YWUqQUKHH2kkLsOB1Kqxcw/OqrryAIAmbOnIlVq1ZBLpdrX7O2tkZwcDDi4uL0HrCsrAwVFRW3PCY0NBSHDx/GqFGjcPny5RblpXPnzpg1axaWLFnSql+Ps7qIiKgjWPh9IjYnF+LR/oF4Y0IPseOITu8LGE6fPh1A89T2gQMHwtKyTWsf6szDwwMeHh63Pe7agGuptOVFLKlUys1TiYjI5EzqE4DNyYX4PakQr4yLhI2VhdiROgSdx/hcuXIFe/fuve75nTt3Yvv27XoJ1RZxcXFwcXHB9OnTkZycrF3TJycnB+PGjRMtFxERkSEMCHODn7MtlPVN2HmuWOw4HYbOxWfJkiVQq9XXPS8IQqtvJxmCu7s7duzYgZqaGgwfPhx9+vTBkSNHsGnTJkRHR4uWi4iIyBCkUgke6uUHAPgp/pLIaToOne9XXbhwAZGRkdc9HxERgczMTL2Eaqs+ffpg586domYgIiJqL//oHYCP92XiSGY5Cqrq4OdsK3Yko6fzFR+5XH7DbSkyMzNhb2+vl1BERER0e4Fudugf6gpBAH7mVZ9W0bn4jB8/Hs888wyysrK0z2VmZmLx4sW4//779RqOiIiIbu3hPs0L7/4UfwkaTasmaps1nYvPu+++C3t7e0RERCAkJAQhISHo2rUr3Nzc8P777xsiIxEREd3E2O4+cJBZIq+yFidyKsWOY/R0HuMjl8tx7Ngx7N69G8nJybC1tUVUVBSGDBliiHxERER0C7bWFrg3ygcbTuXjx/h8xIW5iR3JqLV6AcMbqa+vh0wmu+EWFh0VFzAkIqKOJj73Mh5acwy2VhY4+fIIONpYiR2p3bX257fOt7o0Gg3+9a9/wc/PDw4ODsjJyQEAvPrqq/jf//7X9sRERETUJr0CnRF6dePSrWduvk0TtaH4vPHGG1i3bh3effddWFtba5/v3r07/vvf/+o1HBEREd2eRCLRDnL+kbO7bknn4rN+/Xp88cUXmDp1Kiws/lweOzo6Gunp6XoNR0RERK3zYIwfLKQSxOdeRmZpjdhxjJbOxaegoACdOnW67nmNRoPGxka9hCIiIiLdeDrZ4K4uzXtbciXnm9O5+ERGRuLw4cPXPf/TTz8hJiZGL6GIiIhIdw/38QcA/JJwCWqu6XNDOk9nX7ZsGaZPn46CggJoNBr88ssvyMjIwPr167FlyxZDZCQiIqJWGB7hBWc7K5RWq3A0sxxDrl4Boj+1aeXmzZs3Y8+ePbC3t8eyZcuQlpaGzZs34+677zZERiIiImoFa0sp7ovyBdB81Yeup9MVn6amJrz11luYOXMmdu/ebahMRERE1EYP9PLD13/kYue5EtSomuAg0/nmjknT6YqPpaUl3n33XTQ1NRkqDxEREd2BmABnhLg3r+mzI6VY7DhGR+dbXSNGjMDBgwcNkYWIiIjukEQiwQMxfgCAXxN5u+vvdL7+NXbsWCxZsgRnz55F7969YW9v3+J17tBOREQkrgdi/PDh7vM4llWBIkUdfOS2YkcyGjrv1SWV3vwikUQigVqtvuNQYuJeXUREZAoe/s9xnLxYiZfGRGDe0DCx4xicQffqutmjo5ceIiIiU/FAr+bbXb8kXMId7EducnQqPo2NjbC0tERKSoqh8hAREZEe3NPDB9aWUlworcG5QqXYcYyGTsXHysoKgYGBvLJDRERk5OS2Vri7qxcA4JeEApHTGA+db3W9/PLL+Oc//4nKykpD5CEiIiI9uTa76/fkAjSpNSKnMQ46z+pavXo1MjMz4evri6CgoOtmdSUkJOgtHBEREbXdXeEecLW3RnlNAw5fKMewCE+xI4lO5+IzYcIEA8QgIiIifbOykOL+aF+sO3YRvyQWsPigDcVn+fLlhshBREREBvBAjB/WHbuIXeeKoaxvhJONldiRRNXmDTzi4+ORlpYGAOjWrRtiYmL0FoqIiIj0I8pfjjAPe2SVXcGOs8V4uG+A2JFEpfPg5tLSUgwfPhx9+/bFokWLsGjRIvTu3RsjRoxAWVmZITISERFRG/11C4tNyZzdpXPxWbhwIaqrq3Hu3DlUVlaisrISKSkpUCqVWLRokSEyEhER0R24P7q5+BzPqkCpsl7kNOLSufjs2LEDn332Gbp27ap9LjIyEp9++im2b9+u13BERER05wLd7BAT6AyNAGw5UyR2HFG1acsKK6vrB0ZZWVlBo+EaAURERMbo/mhfAMDvyYUiJxGXzsVn+PDhePrpp1FY+OeJKygowLPPPosRI0boNRwRERHpx7goH0glQFJ+FXIrrogdRzQ6F5/Vq1dDqVQiODgYYWFhCAsLQ0hICJRKJT755BNDZCQiIqI75Olog4Gd3AEAvyeZ71UfnaezBwQEICEhAXv27EF6ejoAoGvXrhg5cqTewxEREZH+3Bfti8MXyrEpuRALhneCRCIRO1K7kwjcq74FpVIJuVwOhUIBJycnseMQERHpjbK+EX3e2IOGJg22LRqMSF/T+TnX2p/frb7VtW/fPkRGRkKpvH5re4VCgW7duuHw4cNtS0tEREQG52RjheHhzdtWmOsg51YXn1WrVmH27Nk3bFFyuRxPPvkkPvzwQ72GIyIiIv26v2fz7K7NyYXQaMzvpk+ri09ycjLGjBlz09dHjRqF+Ph4vYQiIiIiwxge4QkHmSUKquqQkHdZ7DjtrtXFp6Sk5Ibr91xjaWnJLSuIiIiMnI2VBUZ38wYAbDLD2V2tLj5+fn5ISUm56etnzpyBj4+PXkIRERGR4Vy73bX1bBEa1ea1+HCri88999yDV199FfX11+/xUVdXh+XLl+Pee+/Va7i/evPNNzFgwADY2dnB2dn5hsfk5eVh3LhxsLOzg6enJ1544QU0NTUZLBMREVFHNDDMDW721qi80oCjmeVix2lXrS4+r7zyCiorK9GlSxe8++672LRpEzZt2oR33nkH4eHhqKysxMsvv2ywoA0NDZg4cSLmzZt3w9fVajXGjRuHhoYGHDt2DF999RXWrVuHZcuWGSwTERFRR2RpIcW9Uc13acxtMUOd1vHJzc3FvHnzsHPnTlx7m0QiwejRo/Hpp58iJCTEYEGvWbduHZ555hlUVVW1eH779u249957UVhYCC8vLwDAf/7zH7z00ksoKyuDtbV1qz6f6/gQEZE5iM+txENrjsPe2gLxr94NGysLsSPdEb2v4wMAQUFB2LZtG8rLy3HixAn88ccfKC8vx7Zt29ql9NzK8ePH0aNHD23pAYDRo0dDqVTi3LlzN32fSqWCUqls8SAiIjJ1vQJd4OdsiysNahzIMJ/JSTrv1QUALi4u6Nu3L/r16wcXFxd9Z2qT4uLiFqUHgPbr4uLim75v5cqVkMvl2kdAQIBBcxIRERkDiUSCcVdvd209WyRymvbTpuKjL0uWLIFEIrnl49p+YIaydOlSKBQK7SM/P9+gvx4REZGxGNejufjsTStBXYNa5DTtQ+dNSvVp8eLFmDFjxi2PCQ0NbdVneXt74+TJky2eKykp0b52MzKZDDKZrFW/BhERkSmJ8pfD38UWly7X4UBGKcb2MP1laUQtPh4eHvDw8NDLZ8XFxeHNN99EaWkpPD2b9yHZvXs3nJycEBkZqZdfg4iIyJRcu931+cFsbDlbZBbFR9RbXbrIy8tDUlIS8vLyoFarkZSUhKSkJNTU1ABo3jIjMjIS06ZNQ3JyMnbu3IlXXnkF8+fP5xUdIiKim7i3R/NihvvSSlHbYPpr33WY4rNs2TLExMRg+fLlqKmpQUxMDGJiYnD69GkAgIWFBbZs2QILCwvExcXh0UcfxWOPPYbXX39d5ORERETGq7ufEwJd7VDXqMb+dNOf3aXTOj7mgOv4EBGRuXlnRzrWHMjCPT288dnU3mLHaRODrONDREREpufa7K596aW4ojLt210sPkRERGaum68Tgt3sUN+owb70UrHjGBSLDxERkZlrsZjhGdNezJDFh4iIiDDu6uyu/RmlqDHh210sPkRERISuPo4IdbeHqkmDvWklYscxGBYfIiIianG7a4sJ3+5i8SEiIiIAwL1Rzbe7DmaUobq+UeQ0hsHiQ0RERACALl4O6OTpgAa1BntM9HYXiw8REREBuHq7q4dpz+5i8SEiIiKte64Wn0MXyk1ydheLDxEREWl18XJAiLs9Gpo02G+Cixmy+BAREZGWRCLBmO7eAIAdKcUip9E/Fh8iIiJqYezV4rM/oxT1jWqR0+gXiw8RERG10MNPDj9nW9Q2qHHofJnYcfSKxYeIiIhakEgkGN3NNG93sfgQERHRda6N89mTVoKGJo3IafSHxYeIiIiu0zvIBe4OMijrm3A8u0LsOHrD4kNERETXsZBKMLqbFwBgR4rpLGbI4kNEREQ3dO12165zJVBrBJHT6AeLDxEREd1Q/1A3yG2tUHGlAacuVoodRy9YfIiIiOiGrCykGNn12u0u05jdxeJDRERENzX2L6s4a0zgdheLDxEREd3UoM7usLe2QLGyHsmXqsSOc8dYfIiIiOimbKwsMCzCE4Bp3O5i8SEiIqJbGtvdBwCw41wxBKFj3+5i8SEiIqJbGhruAZmlFLkVtUgrqhY7zh1h8SEiIqJbspdZYkgXDwDNV306MhYfIiIiuq1Rkc3T2nenloic5M6w+BAREdFtjejqBakESCtSIr+yVuw4bcbiQ0RERLflam+NPsGuAJp3bO+oWHyIiIioVa7d7tp1jsWHiIiITNzdV4vPyYuVqKptEDlN27D4EBERUasEudkj3MsRao2A/RmlYsdpExYfIiIiarVR3Tr27S4WHyIiImq1a7e7Dp4vQ32jWuQ0umPxISIiolbr4SeHt5MNahvUOJZVLnYcnbH4EBERUatJJBLtVZ+OuJghiw8RERHp5M/iUwqNpmNtWtphis+bb76JAQMGwM7ODs7Ozte9npycjMmTJyMgIAC2trbo2rUrPvroo/YPSkREZOL6h7rBUWaJ8hoVEvOrxI6jkw5TfBoaGjBx4kTMmzfvhq/Hx8fD09MT33zzDc6dO4eXX34ZS5cuxerVq9s5KRERkWmztpRiaIQngI53u0siCEKHuka1bt06PPPMM6iqqrrtsfPnz0daWhr27dvX6s9XKpWQy+VQKBRwcnK6g6RERESma3NyIRZ+n4hQD3vsWzxU7Dit/vlt2Y6Z2p1CoYCrq+stj1GpVFCpVNqvlUqloWMRERF1eEPDPWBlIUF22RVkldUgzMNB7Eit0mFudenq2LFj2LhxI+bMmXPL41auXAm5XK59BAQEtFNCIiKijsvRxgpxYe4AOtbtLlGLz5IlSyCRSG75SE9P1/lzU1JSMH78eCxfvhyjRo265bFLly6FQqHQPvLz89v67RAREZmVu7WblhaLnKT1RL3VtXjxYsyYMeOWx4SGhur0mampqRgxYgTmzJmDV1555bbHy2QyyGQynX4NIiIiAu7u6oVXf0tBYn4VSqvr4eloI3ak2xK1+Hh4eMDDw0Nvn3fu3DkMHz4c06dPx5tvvqm3zyUiIqLrecttEO0vR/IlBfanl2JS30CxI91Whxnjk5eXh6SkJOTl5UGtViMpKQlJSUmoqakB0Hx7a9iwYRg1ahSee+45FBcXo7i4GGVlZSInJyIiMl0jujbf7tqb1jF2a+8wxWfZsmWIiYnB8uXLUVNTg5iYGMTExOD06dMAgJ9++gllZWX45ptv4OPjo3307dtX5ORERESma/jV9XwOXyjvEJuWdrh1fAyN6/gQERG1niAIiFu5D8XKeqx7vC+GhnuKkqO1P787zBUfIiIiMj4SiQTDuzaXnX3pxn+7i8WHiIiI7siIq7e79qaVwthvJLH4EBER0R0ZEOYOmaUUBVV1yCipFjvOLbH4EBER0R2xtbbAwE7Nqzgb++wuFh8iIiK6YyO6XrvdZdzbV7D4EBER0R27Nq09Mb8KFTWq2xwtHhYfIiIiumM+cltE+jhBEIADGca7eDCLDxEREenFyGu3u9KN93YXiw8RERHpxfCr21ccOl+OhiaNyGlujMWHiIiI9CLKTw53BxlqVE04dbFS7Dg3xOJDREREeiGVSjA8wgMAsMdIZ3ex+BAREZHeDI/4c7d2Y1zFmcWHiIiI9GZwZ3dYW0iRV1mLrLIrYse5DosPERER6Y29zBL9w9wAGOdihiw+REREpFfaTUuNcLd2Fh8iIiLSq2urOMfnXkZVbYPIaVpi8SEiIiK9CnC1QxcvB6g1Ag5fKBc7TgssPkRERKR3w8Kbr/rszzCu210sPkRERKR3d4U3r+dzMKMMGo3xTGtn8SEiIiK96xPkCgeZJSquNCClUCF2HC0WHyIiItI7a0spBnVyBwDsTzee3dpZfIiIiMgghl693XXgvPGM82HxISIiIoMYenWAc1J+FSqvGMe0dhYfIiIiMghvuQ26+jhBEIBD543jdheLDxERERmM9naXkUxrZ/EhIiIig7m2ns/B82VQG8G0dhYfIiIiMphegc5wtLHE5dpGnLlUJXYcFh8iIiIyHEsLKYZ0br7dtT9D/HE+LD5ERERkUMY0zofFh4iIiAzq2vYVZy4pUFatEjULiw8REREZlKejDbr7OQEQf1o7iw8REREZ3LXZXQdYfIiIiMjUXRvnc+h8GZrUGtFysPgQERGRwfUMcIGznRWc7axQpKgXLYelaL8yERERmQ0LqQR7nrsL7g4yUXPwig8RERG1C7FLD8DiQ0RERGaExYeIiIjMBosPERERmY0OU3zefPNNDBgwAHZ2dnB2dr7lsRUVFfD394dEIkFVVVW75CMiIiLj12GKT0NDAyZOnIh58+bd9thZs2YhKiqqHVIRERFRR9JhprOvWLECALBu3bpbHrdmzRpUVVVh2bJl2L59+20/V6VSQaX6c98QpVJ5RzmJiIjIeHWYKz6tkZqaitdffx3r16+HVNq6b23lypWQy+XaR0BAgIFTEhERkVhMpvioVCpMnjwZ7733HgIDA1v9vqVLl0KhUGgf+fn5BkxJREREYhK1+CxZsgQSieSWj/T09FZ91tKlS9G1a1c8+uijOmWQyWRwcnJq8SAiIiLTJOoYn8WLF2PGjBm3PCY0NLRVn7Vv3z6cPXsWP/30EwBAEAQAgLu7O15++WXtGCEiIiIyX6IWHw8PD3h4eOjls37++WfU1dVpvz516hRmzpyJw4cPIywsTC+/BhEREXVsHWZWV15eHiorK5GXlwe1Wo2kpCQAQKdOneDg4HBduSkvLwcAdO3a9bbr/hAREZF56DDFZ9myZfjqq6+0X8fExAAA9u/fj6FDh4qUioiIiDoSiXBtMAwBABQKBZydnZGfn8+BzkRERB2EUqlEQEAAqqqqIJfLb3pch7ni016qq6sBgOv5EBERdUDV1dW3LD684vM3Go0GhYWFcHR0hEQi0dvnXmuivJKkHzyf+sXzqV88n/rF86lfpno+BUFAdXU1fH19b7mIMa/4/I1UKoW/v7/BPp9rBekXz6d+8XzqF8+nfvF86pcpns9bXem5xmRWbiYiIiK6HRYfIiIiMhssPu1EJpNh+fLlkMlkYkcxCTyf+sXzqV88n/rF86lf5n4+ObiZiIiIzAav+BAREZHZYPEhIiIis8HiQ0RERGaDxYeIiIjMBotPO/n0008RHBwMGxsbxMbG4uTJk2JHMjqvvfYaJBJJi0dERIT29fr6esyfPx9ubm5wcHDAQw89hJKSkhafkZeXh3HjxsHOzg6enp544YUX0NTU1N7fiigOHTqE++67D76+vpBIJPjtt99avC4IApYtWwYfHx/Y2tpi5MiRuHDhQotjKisrMXXqVDg5OcHZ2RmzZs1CTU1Ni2POnDmDwYMHw8bGBgEBAXj33XcN/a2J4nbnc8aMGdf9fh0zZkyLY3g+m61cuRJ9+/aFo6MjPD09MWHCBGRkZLQ4Rl9/vg8cOIBevXpBJpOhU6dOWLdunaG/vXbXmvM5dOjQ635/zp07t8UxZns+BTK4DRs2CNbW1sKXX34pnDt3Tpg9e7bg7OwslJSUiB3NqCxfvlzo1q2bUFRUpH2UlZVpX587d64QEBAg7N27Vzh9+rTQv39/YcCAAdrXm5qahO7duwsjR44UEhMThW3btgnu7u7C0qVLxfh22t22bduEl19+Wfjll18EAMKvv/7a4vW3335bkMvlwm+//SYkJycL999/vxASEiLU1dVpjxkzZowQHR0t/PHHH8Lhw4eFTp06CZMnT9a+rlAoBC8vL2Hq1KlCSkqK8P333wu2trbC559/3l7fZru53fmcPn26MGbMmBa/XysrK1scw/PZbPTo0cLatWuFlJQUISkpSbjnnnuEwMBAoaamRnuMPv58Z2dnC3Z2dsJzzz0npKamCp988olgYWEh7Nixo12/X0Nrzfm86667hNmzZ7f4/alQKLSvm/P5ZPFpB/369RPmz5+v/VqtVgu+vr7CypUrRUxlfJYvXy5ER0ff8LWqqirByspK+PHHH7XPpaWlCQCE48ePC4LQ/INKKpUKxcXF2mPWrFkjODk5CSqVyqDZjc3ff1BrNBrB29tbeO+997TPVVVVCTKZTPj+++8FQRCE1NRUAYBw6tQp7THbt28XJBKJUFBQIAiCIHz22WeCi4tLi/P50ksvCeHh4Qb+jsR1s+Izfvz4m76H5/PmSktLBQDCwYMHBUHQ35/vF198UejWrVuLX2vSpEnC6NGjDf0tierv51MQmovP008/fdP3mPP55K0uA2toaEB8fDxGjhypfU4qlWLkyJE4fvy4iMmM04ULF+Dr64vQ0FBMnToVeXl5AID4+Hg0Nja2OI8REREIDAzUnsfjx4+jR48e8PLy0h4zevRoKJVKnDt3rn2/ESOTk5OD4uLiFudPLpcjNja2xflzdnZGnz59tMeMHDkSUqkUJ06c0B4zZMgQWFtba48ZPXo0MjIycPny5Xb6bozHgQMH4OnpifDwcMybNw8VFRXa13g+b06hUAAAXF1dAejvz/fx48dbfMa1Y0z979q/n89rvv32W7i7u6N79+5YunQpamtrta+Z8/nkJqUGVl5eDrVa3eI3FwB4eXkhPT1dpFTGKTY2FuvWrUN4eDiKioqwYsUKDB48GCkpKSguLoa1tTWcnZ1bvMfLywvFxcUAgOLi4hue52uvmbNr3/+Nzs9fz5+np2eL1y0tLeHq6trimJCQkOs+49prLi4uBslvjMaMGYMHH3wQISEhyMrKwj//+U+MHTsWx48fh4WFBc/nTWg0GjzzzDMYOHAgunfvDgB6+/N9s2OUSiXq6upga2triG9JVDc6nwAwZcoUBAUFwdfXF2fOnMFLL72EjIwM/PLLLwDM+3yy+JDRGDt2rPbfo6KiEBsbi6CgIPzwww8d9g8Yma5HHnlE++89evRAVFQUwsLCcODAAYwYMULEZMZt/vz5SElJwZEjR8SOYhJudj7nzJmj/fcePXrAx8cHI0aMQFZWFsLCwto7plHhrS4Dc3d3h4WFxXWzE0pKSuDt7S1Sqo7B2dkZXbp0QWZmJry9vdHQ0ICqqqoWx/z1PHp7e9/wPF97zZxd+/5v9fvQ29sbpaWlLV5vampCZWUlz3ErhIaGwt3dHZmZmQB4Pm9kwYIF2LJlC/bv3w9/f3/t8/r6832zY5ycnEzyf55udj5vJDY2FgBa/P401/PJ4mNg1tbW6N27N/bu3at9TqPRYO/evYiLixMxmfGrqalBVlYWfHx80Lt3b1hZWbU4jxkZGcjLy9Oex7i4OJw9e7bFD5vdu3fDyckJkZGR7Z7fmISEhMDb27vF+VMqlThx4kSL81dVVYX4+HjtMfv27YNGo9H+pRkXF4dDhw6hsbFRe8zu3bsRHh5ukrdldHHp0iVUVFTAx8cHAM/nXwmCgAULFuDXX3/Fvn37rru9p68/33FxcS0+49oxpvZ37e3O540kJSUBQIvfn2Z7PsUeXW0ONmzYIMhkMmHdunVCamqqMGfOHMHZ2bnFaHoShMWLFwsHDhwQcnJyhKNHjwojR44U3N3dhdLSUkEQmqe7BgYGCvv27RNOnz4txMXFCXFxcdr3X5ueOWrUKCEpKUnYsWOH4OHhYTbT2aurq4XExEQhMTFRACB8+OGHQmJiopCbmysIQvN0dmdnZ2HTpk3CmTNnhPHjx99wOntMTIxw4sQJ4ciRI0Lnzp1bTL+uqqoSvLy8hGnTpgkpKSnChg0bBDs7O5Obfi0Itz6f1dXVwvPPPy8cP35cyMnJEfbs2SP06tVL6Ny5s1BfX6/9DJ7PZvPmzRPkcrlw4MCBFtOra2trtcfo48/3tenXL7zwgpCWliZ8+umnJjH9+u9udz4zMzOF119/XTh9+rSQk5MjbNq0SQgNDRWGDBmi/QxzPp8sPu3kk08+EQIDAwVra2uhX79+wh9//CF2JKMzadIkwcfHR7C2thb8/PyESZMmCZmZmdrX6+rqhKeeekpwcXER7OzshAceeEAoKipq8RkXL14Uxo4dK9ja2gru7u7C4sWLhcbGxvb+VkSxf/9+AcB1j+nTpwuC0Dyl/dVXXxW8vLwEmUwmjBgxQsjIyGjxGRUVFcLkyZMFBwcHwcnJSXj88ceF6urqFsckJycLgwYNEmQymeDn5ye8/fbb7fUttqtbnc/a2lph1KhRgoeHh2BlZSUEBQUJs2fPvu5/Zng+m93oPAIQ1q5dqz1GX3++9+/fL/Ts2VOwtrYWQkNDW/wapuJ25zMvL08YMmSI4OrqKshkMqFTp07CCy+80GIdH0Ew3/MpEQRBaL/rS0RERETi4RgfIiIiMhssPkRERGQ2WHyIiIjIbLD4EBERkdlg8SEiIiKzweJDREREZoPFh4iIiMwGiw8RERGZDRYfIjIpM2bMwIQJE/T2eevWrYOzs7PePo+IxMXiQ0QdzowZMyCRSCCRSGBtbY1OnTrh9ddfR1NTEz766COsW7dO7IhEZKQsxQ5ARNQWY8aMwdq1a6FSqbBt2zbMnz8fVlZWWLp0qdjRiMiI8YoPEXVIMpkM3t7eCAoKwrx58zBy5Ej8/vvvLW51lZWVwdvbG2+99Zb2fceOHYO1tTX27t0LAFCpVHj++efh5+cHe3t7xMbG4sCBAyJ8R0TUHlh8iMgk2NraoqGhocVzHh4e+PLLL/Haa6/h9OnTqK6uxrRp07BgwQKMGDECALBgwQIcP34cGzZswJkzZzBx4kSMGTMGFy5cEOPbICIDY/Ehog5NEATs2bMHO3fuxPDhw697/Z577sHs2bMxdepUzJ07F/b29li5ciUAIC8vD2vXrsWPP/6IwYMHIywsDM8//zwGDRqEtWvXtve3QkTtgGN8iKhD2rJlCxwcHNDY2AiNRoMpU6bgtddew/z586879v3330f37t3x448/Ij4+HjKZDABw9uxZqNVqdOnSpcXxKpUKbm5u7fJ9EFH7YvEhog5p2LBhWLNmDaytreHr6wtLy5v/dZaVlYXCwkJoNBpcvHgRPXr0AADU1NTAwsIC8fHxsLCwaPEeBwcHg+YnInGw+BBRh2Rvb49OnTrd9riGhgY8+uijmDRpEsLDw/HEE0/g7Nmz8PT0RExMDNRqNUpLSzF48OB2SE1EYuMYHyIyaS+//DIUCgU+/vhjvPTSS+jSpQtmzpwJAOjSpQumTp2Kxx57DL/88gtycnJw8uRJrFy5Elu3bhU5OREZAosPEZmsAwcOYNWqVfj666/h5OQEqVSKr7/+GocPH8aaNWsAAGvXrsVjjz2GxYsXIzw8HBMmTMCpU6cQGBgocnoiMgSJIAiC2CGIiIiI2gOv+BAREZHZYPEhIiIis8HiQ0RERGaDxYeIiIjMBosPERERmQ0WHyIiIjIbLD5ERERkNlh8iIiIyGyw+BAREZHZYPEhIiIis8HiQ0RERGbj/wHEzckiW92dvwAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "pix_array = np.arange(2688)\n", "nlin = blue_channel_wcs.spectral.pixel_to_world(pix_array)\n", "lin = bc_linear_wcs.spectral.pixel_to_world(pix_array)\n", "resid = (nlin - lin).to(u.Angstrom)\n", "plt.plot(pix_array, resid)\n", "plt.xlabel(\"Pixel\")\n", "plt.ylabel(\"Correction (Angstrom)\")\n", "plt.show()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Create a synthetic 2D image using the non-linear WCS and with curvature in the cross-dispersion direction. The `HeNe` and `Ar` lamps are the optimal ones to use for this spectrograph configuration. For the purposes of this example, the curvature along the cross-dispersion axis is exaggerated compared to the actual spectrograph." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING: No observer defined on WCS, SpectralCoord will be converted without any velocity frame change [astropy.wcs.wcsapi.fitswcs]\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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ne98J373d38X3/Ed3xGfX7x4Ea95zWvwghe8AA888AB+6qd+Cj/2Yz+Gf//v//0T3r8FFngqYWp/AcBrX/vawZn2S7/0S4Pny/5aYAEd3ve+9+Gee+7BBz7wAbz73e/GbrfDa17zGly5ciWWuR584Sc+8Qncfffd+Nt/+2/jQx/6EL7/+78f//Sf/lP8l//yX57U/i6wwJMJJfsLAL792799cIbxi5hlfz1J4J5h8NVf/dXunnvuid/btnXPec5z3Fvf+tanEKsFFnh6w1ve8hb35V/+5eqzxx57zDVN497xjnfE3/7kT/7EAXD333+/c865d73rXc5a6x5++OFY5md/9mfduXPn3GazeUJxX2CBpzsAcL/2a78Wv3dd586fP+9+6qd+Kv722GOPufV67X7pl37JOefcRz/6UQfA/Y//8T9imf/8n/+zM8a4P//zP3fOOfdv/s2/cTfffPNgj/3Ij/yIe/GLX/wE92iBBZ4+IPeXc85967d+q/uGb/iG5DvL/lpggXJ49NFHHQD3vve9zzl3/fjCf/bP/pn70i/90kFbr3/9692dd975RHdpgQWeNiD3l3PO/a2/9bfc933f9yXfWfbXkwPPKIuw7XaLBx54AHfccUf8zVqLO+64A/fff/9TiNkCCzz94U//9E/xnOc8By960Yvwhje8AQ899BAA4IEHHsButxvsq5e85CV4/vOfH/fV/fffj5e//OW47bbbYpk777wTFy9exEc+8pEntyMLLPA0h0984hN4+OGHB3vqxhtvxCtf+crBnrrpppvwVV/1VbHMHXfcAWstPvjBD8Yyr3rVq7BarWKZO++8Ew8++CA+97nPPUm9WWCBpye8973vxbOf/Wy8+MUvxnd913fhM5/5THy27K8FFiiHxx9/HABwyy23ALh+fOH9998/qIPKLDLbAp9PIPcXwS/+4i/i1ltvxcte9jK86U1vwtWrV+OzZX89OVA/1QjMgb/4i79A27aDRQEAt912G/7X//pfTxFWCyzw9IdXvvKVuO+++/DiF78Yn/70p/Ev/+W/xNd+7dfij//4j/Hwww9jtVrhpptuGrxz22234eGHHwYAPPzww+q+o2cLLLBAD7QntD3D99Szn/3swfO6rnHLLbcMyrzwhS8c1UHPbr755icE/wUWeLrDa1/7Wrzuda/DC1/4Qnz84x/HP//n/xx33XUX7r//flRVteyvBRYohK7r8P3f//34G3/jb+BlL3sZAFw3vjBV5uLFizg+Psbh4eET0aUFFnjagLa/AOAf/IN/gBe84AV4znOegz/6oz/Cj/zIj+DBBx/Er/7qrwJY9teTBc8oRdgCCyxwOrjrrrvi5y/7si/DK1/5SrzgBS/Ar/zKryyEcoEFFlhggWcU/P2///fj55e//OX4si/7MnzhF34h3vve9+LVr371U4jZAgs8s+Cee+7BH//xHw/ixi6wwALXB1L7i8erfPnLX47bb78dr371q/Hxj38cX/iFX/hko/l5C88o18hbb70VVVWNspY88sgjOH/+/FOE1QILPPPgpptuwpd8yZfgYx/7GM6fP4/tdovHHntsUIbvq/Pnz6v7jp4tsMACPdCeyJ1V58+fHyV52e/3+OxnP7vsuwUWmAkvetGLcOutt+JjH/sYgGV/LbBACXzP93wP3vnOd+J3fud38Ff+yl+Jv18vvjBV5ty5c8sl7AJ/6SG1vzR45StfCQCDM2zZX088PKMUYavVCq94xSvwnve8J/7WdR3e85734MKFC08hZgss8MyCy5cv4+Mf/zhuv/12vOIVr0DTNIN99eCDD+Khhx6K++rChQv48Ic/PBAs3v3ud+PcuXN46Utf+qTjv8ACT2d44QtfiPPnzw/21MWLF/HBD35wsKcee+wxPPDAA7HMb//2b6PrusgQXbhwAb/7u7+L3W4Xy7z73e/Gi1/84sVta4EFGPzf//t/8ZnPfAa33347gGV/LbBADpxz+J7v+R782q/9Gn77t3975CJ8vfjCCxcuDOqgMovMtsBfZpjaXxp86EMfAoDBGbbsrycBnupo/XPhl3/5l916vXb33Xef++hHP+q+4zu+w910002DrAoLLLDAEH7oh37Ivfe973Wf+MQn3H/7b//N3XHHHe7WW291jz76qHPOue/8zu90z3/+891v//Zvu9///d93Fy5ccBcuXIjv7/d797KXvcy95jWvcR/60Ifcb/7mb7ov+IIvcG9605ueqi4tsMBTCpcuXXJ/+Id/6P7wD//QAXA//dM/7f7wD//Q/Z//83+cc8795E/+pLvpppvcr//6r7s/+qM/ct/wDd/gXvjCF7rj4+NYx2tf+1r31/7aX3Mf/OAH3e/93u+5L/7iL3bf/M3fHJ8/9thj7rbbbnPf8i3f4v74j//Y/fIv/7I7Ojpy/+7f/bsnvb8LLPBkQm5/Xbp0yf3wD/+wu//++90nPvEJ91//6391X/mVX+m++Iu/2J2cnMQ6lv21wAI6fNd3fZe78cYb3Xvf+1736U9/Ov5dvXo1lrkefOH//t//2x0dHbk3vvGN7k/+5E/cvffe66qqcr/5m7/5pPZ3gQWeTJjaXx/72Mfcj//4j7vf//3fd5/4xCfcr//6r7sXvehF7lWvelWsY9lfTw484xRhzjn3r//1v3bPf/7z3Wq1cl/91V/tPvCBDzzVKC2wwNMaXv/617vbb7/drVYr99znPte9/vWvdx/72Mfi8+PjY/fd3/3d7uabb3ZHR0fuG7/xG92nP/3pQR1/9md/5u666y53eHjobr31VvdDP/RDbrfbPdldWWCBpwX8zu/8jgMw+vvWb/1W55xzXde5f/Ev/oW77bbb3Hq9dq9+9avdgw8+OKjjM5/5jPvmb/5md8MNN7hz5865f/JP/om7dOnSoMz//J//0/3Nv/k33Xq9ds997nPdT/7kTz5ZXVxggacMcvvr6tWr7jWveY37gi/4Atc0jXvBC17gvv3bv310IbrsrwUW0EHbWwDc29/+9ljmevGFv/M7v+O+4iu+wq1WK/eiF71o0MYCC/xlhKn99dBDD7lXvepV7pZbbnHr9dp90Rd9kXvjG9/oHn/88UE9y/564sE459yTZ3+2wAILLLDAAgsssMACCyywwAILLLDAAk8NPKNihC2wwAILLLDAAgsssMACCyywwAILLLDAaWFRhC2wwAILLLDAAgsssMACCyywwAILLPB5AYsibIEFFlhggQUWWGCBBRZYYIEFFlhggc8LWBRhCyywwAILLLDAAgsssMACCyywwAILfF7AoghbYIEFFlhggQUWWGCBBRZYYIEFFljg8wIWRdgCCyywwAILLLDAAgsssMACCyywwAKfF7AowhZYYIEFFlhggQUWWGCBBRZYYIEFFvi8gEURtsACCyywwAILLLDAAgsssMACCyywwOcFLIqwBRZYYIEFFlhggQUWWGCBBRZYYIEFPi9gUYQtsMACCyywwAILLLDAAgsssMACCyzweQGLImyBBRZYYIEFFlhggQUWWGCBBRZYYIHPC1gUYQsssMACCyywwAILLLDAAgsssMACC3xewP8Pord+jlR7JZ8AAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "tilt_mod = models.Legendre1D(degree=2, c0=25, c1=0, c2=50)\n", "match_im = make_2d_arc_image(\n", " nx=2688, \n", " ny=512, \n", " linelists=['HeI', 'NeI', 'ArI'], \n", " wcs=blue_channel_wcs, \n", " line_fwhm=3, \n", " tilt_func=tilt_mod, \n", " amplitude_scale=1e-2\n", ")\n", "fig = plt.figure(figsize=(15, 5))\n", "plt.imshow(match_im)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Load the linelist used to create the image, set up the trace and boxcar extraction of the center of the image, and subtract the background in the extracted spectrum. The `specutils` line-finding routines expect background-subtracted spectra." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING: Model is linear in parameters; consider using linear fitting methods. [astropy.modeling.fitting]\n" ] }, { "data": { "image/png": "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RERJhwEMERGlNNYgpSYGMERERJR0GMAQERFR0mEAQ0REKY01SKmJAQwRERElHQYwRERElHQYwBARUUrjQHapiQEMERERJR0GMERERJR0GMAQEVFKYwVSamIAQ0REREmHAQwRERElHQYwRESU0tgJKTUxgCEiIqKkwwCGiIiIkg4DGCIiIko6DGCIiIgo6TCAISKiFMdWvKmIAQwRERElHQYwRERElHQYwBARUUrjODCpiQEMERERJR0GMERERJR0GMAQEVFKYw1SamIAQ0REREmHAQwRERElHQYwRESU0tgLKTUxgCEiIqKkwwCGiIiIkg4DGCIiSmk29kNKSQxgiIgopQmIRGeB4oABDBERESUdBjBERJTSWIWUmhjAEBFRSmMVUmpiAENERERJhwEMERGlNFYhpaaoAphFixbhggsuQHZ2NvLz8/Hd734XlZWVsjSXXnopbDab7O+OO+6QpTl8+DBmzpyJrKws5OfnY/78+fD7/bI0a9aswXnnnQeXy4Xhw4djyZIlsa0hERGd0ViFlJqiCmDWrl2LOXPmYOPGjVi5ciXa2towbdo0NDY2ytLddtttOHbsWPjv0UcfDU8LBAKYOXMmfD4fNmzYgBdffBFLlizBwoULw2kOHjyImTNn4rLLLkNFRQXuuusu3HrrrVixYkU3V5eIiIhSQVo0iZcvXy57v2TJEuTn56O8vBxTpkwJf56VlYXCwkLVeXz44YfYuXMnPvroIxQUFOCcc87Br3/9a9x333148MEH4XQ68fzzz2Po0KH4wx/+AAAYNWoU1q9fjyeeeAKlpaXRriMREZ3BWIWUmrrVBqaurg4AkJeXJ/v85ZdfRr9+/TB27FgsWLAATU1N4WllZWUYN24cCgoKwp+VlpbC6/Vix44d4TRTp06VzbO0tBRlZWWaeWltbYXX65X9ERERUWqKqgRGKhgM4q677sJFF12EsWPHhj//wQ9+gCFDhqCoqAhbt27Ffffdh8rKSrz11lsAAI/HIwteAITfezwe3TRerxfNzc3IzMzskp9FixbhoYceinV1iIiIKInEHMDMmTMH27dvx/r162Wf33777eHX48aNw4ABA3D55Zdj//79OPvss2PPaQQLFizAvHnzwu+9Xi+Ki4vjtjwiIiJKnJiqkObOnYulS5fi448/xqBBg3TTTpo0CQCwb98+AEBhYSGqq6tlaULvQ+1mtNK43W7V0hcAcLlccLvdsj8iIiJKTVEFMEIIzJ07F2+//TZWr16NoUOHRvxORUUFAGDAgAEAgJKSEmzbtg01NTXhNCtXroTb7cbo0aPDaVatWiWbz8qVK1FSUhJNdomIiChFRRXAzJkzBy+99BJeeeUVZGdnw+PxwOPxoLm5GQCwf/9+/PrXv0Z5eTkOHTqEf//737j55psxZcoUjB8/HgAwbdo0jB49GjfddBO2bNmCFStW4P7778ecOXPgcrkAAHfccQcOHDiAe++9F7t378azzz6LN954A3fffbfJq09ERETJKKoA5rnnnkNdXR0uvfRSDBgwIPz3+uuvAwCcTic++ugjTJs2DSNHjsQ999yDWbNm4b333gvPw+FwYOnSpXA4HCgpKcEPf/hD3HzzzXj44YfDaYYOHYply5Zh5cqVmDBhAv7whz/gL3/5C7tQExEREQDAJoRIySEKvV4vcnJyUFdXx/YwRERnsMn/uwoebwsA4NAjMxOcG4rE6PWbz0IiIiKipMMAhoiIiJIOAxgiIiJKOgxgiIiIKOkwgCEiIqKkwwCGiIiIkg4DGCIiIko6DGCIiIgo6TCAISIioqTDAIaIiIiSDgMYIiIiSjoMYIiIiCjpMIAhIiKipMMAhoiIiJIOAxgiIiJKOgxgiIiIKOkwgCEiIqKkwwCGiIiIkg4DGCIiIko6DGCIiIgo6TCAISIioqTDAIaIiIiSDgMYIiIiSjoMYIiIiCjpMIAhIqKUZrMlOgcUDwxgiIgopQmR6BxQPDCAISIioqTDAIaIiFIaq5BSEwMYIiJKaaxCSk0MYIiIiCjpMIAhIqKUxiqk1MQAhoiIUhqrkFITAxgiIiJKOgxgiIgopbEKKTUxgCEiopTGKqTUxACGiIiIkg4DGCIiSmmsQkpNDGCIiCilsQopNTGAISIioqTDAIaIiFIaq5BSEwMYIiIiSjpRBTCLFi3CBRdcgOzsbOTn5+O73/0uKisrZWlaWlowZ84c9O3bF71798asWbNQXV0tS3P48GHMnDkTWVlZyM/Px/z58+H3+2Vp1qxZg/POOw8ulwvDhw/HkiVLYltDIiIiSjlRBTBr167FnDlzsHHjRqxcuRJtbW2YNm0aGhsbw2nuvvtuvPfee3jzzTexdu1aVFVV4dprrw1PDwQCmDlzJnw+HzZs2IAXX3wRS5YswcKFC8NpDh48iJkzZ+Kyyy5DRUUF7rrrLtx6661YsWKFCatMREREyc4mROzts48fP478/HysXbsWU6ZMQV1dHfr3749XXnkF3//+9wEAu3fvxqhRo1BWVobJkyfjgw8+wJVXXomqqioUFBQAAJ5//nncd999OH78OJxOJ+677z4sW7YM27dvDy/r+uuvR21tLZYvX24ob16vFzk5Oairq4Pb7Y51FYmIKMmVLFqFY3UtAIBDj8xMcG4oEqPX7261gamrqwMA5OXlAQDKy8vR1taGqVOnhtOMHDkSgwcPRllZGQCgrKwM48aNCwcvAFBaWgqv14sdO3aE00jnEUoTmoea1tZWeL1e2R8RERGlppgDmGAwiLvuugsXXXQRxo4dCwDweDxwOp3Izc2VpS0oKIDH4wmnkQYvoemhaXppvF4vmpubVfOzaNEi5OTkhP+Ki4tjXTUiIiKyuJgDmDlz5mD79u147bXXzMxPzBYsWIC6urrw35EjRxKdJSIiIoqTtFi+NHfuXCxduhTr1q3DoEGDwp8XFhbC5/OhtrZWVgpTXV2NwsLCcJrPPvtMNr9QLyVpGmXPperqarjdbmRmZqrmyeVyweVyxbI6RERElGSiKoERQmDu3Ll4++23sXr1agwdOlQ2feLEiUhPT8eqVavCn1VWVuLw4cMoKSkBAJSUlGDbtm2oqakJp1m5ciXcbjdGjx4dTiOdRyhNaB5ERER0ZouqBGbOnDl45ZVX8O677yI7OzvcZiUnJweZmZnIycnB7NmzMW/ePOTl5cHtduOnP/0pSkpKMHnyZADAtGnTMHr0aNx000149NFH4fF4cP/992POnDnhEpQ77rgDf/zjH3HvvffiJz/5CVavXo033ngDy5YtM3n1iYiIKBlFVQLz3HPPoa6uDpdeeikGDBgQ/nv99dfDaZ544glceeWVmDVrFqZMmYLCwkK89dZb4ekOhwNLly6Fw+FASUkJfvjDH+Lmm2/Gww8/HE4zdOhQLFu2DCtXrsSECRPwhz/8AX/5y19QWlpqwioTERFRsuvWODBWxnFgiIgI4DgwyaZHxoEhIiIiSgQGMERERJR0GMAQERFR0mEAQ0REREmHAQwRERElHQYwRERElHQYwBAREVHSYQBDREREYY9/WIl73tgCqw8TxwCGiIiIwp5evQ//+uIodlR5E50VXQxgiIiIqAtfIJjoLOiK6mGOREREyUAIgd8u24URhdmJzkrSsiU6AxEwgCEiopTz6b6T+Mv6gwCAATkZCc5NcrLZrB3CsAqJiIhSzukmX6KzkJSkDXetHb4wgCEiohRk7f4z1iXteGTxAhgGMERERFqCQYE91fUIBs+MkCgoiWDsFo9gGMAQEVHKMevS+7/v78K0J9bh0RWVJs3R2pIpTmMAQ0REpCHUEPj5tfsTnJOeIS2BsXgBDAMYIiJKPUlUkGApsjYwFm/GywCGiIiIALAEhoiIKKEsfu21LGnJFQMYIiKiHia7ECcsF8lHVgJj8S3HAIaIiFIa28MYJySPP7JbO35hAENERETt2AaGiIjIIix+HbYUaQBj9S3HAIaIiFIaq5CMkw9kZ+0txwCGiIiIAADC4kGLFAMYIiIiAiAfyE5YPJZhAENEREQA5G1gLB6/MIAhIiKidnyYIxERESWdoCSCYRUSERERJQVZGxiLVyIxgCEiopQjrF58IHHPG1tw3z+3JjobABRtYCy+CRnAEBERJUhNfQv+9cVRvL75COqa2xKdnaTCAIaIiFKOzerj4HcISp49ZIUaG2kWWAJDRETUw4TsqcrJwWptTqyWHyUGMERElNKsfBmWFhRZrcTDavlRYgBDRESUIFYrHUqmxs8MYIiIKOVI28BYLUggczCAISKilCOSaEj8ECvkk414iYiIKDIWD8WMAQwREZmmvqUN055Yi8dW7E50VsIYIxiX0iPxrlu3DldddRWKiopgs9nwzjvvyKb/6Ec/gs1mk/1Nnz5dlubUqVO48cYb4Xa7kZubi9mzZ6OhoUGWZuvWrbjkkkuQkZGB4uJiPProo9GvHRER9ahXPzuMPdUNWPzx/kRnJczal+FOVmtAa7HsdBF1ANPY2IgJEyZg8eLFmmmmT5+OY8eOhf9effVV2fQbb7wRO3bswMqVK7F06VKsW7cOt99+e3i61+vFtGnTMGTIEJSXl+Oxxx7Dgw8+iD//+c/RZpeIiHqQP5keZ2wBNguXD1n9l0yL9gszZszAjBkzdNO4XC4UFhaqTtu1axeWL1+Ozz//HOeffz4A4JlnnsEVV1yB3//+9ygqKsLLL78Mn8+HF154AU6nE2PGjEFFRQUef/xxWaBDREREZrJ62NIpLm1g1qxZg/z8fIwYMQJ33nknTp48GZ5WVlaG3NzccPACAFOnToXdbsemTZvCaaZMmQKn0xlOU1paisrKSpw+fVp1ma2trfB6vbI/IiIiq1eFhFgtm1ar0lIyPYCZPn06/v73v2PVqlX43e9+h7Vr12LGjBkIBAIAAI/Hg/z8fNl30tLSkJeXB4/HE05TUFAgSxN6H0qjtGjRIuTk5IT/iouLzV41IiJKQlZvjBpihXhB3ojX2qKuQork+uuvD78eN24cxo8fj7PPPhtr1qzB5ZdfbvbiwhYsWIB58+aF33u9XgYxRERkadLgKlkCLauIezfqYcOGoV+/fti3bx8AoLCwEDU1NbI0fr8fp06dCrebKSwsRHV1tSxN6L1W2xqXywW32y37IyIiskLJhiEWyCcHspM4evQoTp48iQEDBgAASkpKUFtbi/Ly8nCa1atXIxgMYtKkSeE069atQ1tbWzjNypUrMWLECPTp0yfeWSYiohRi6euwpatsrJcjqagDmIaGBlRUVKCiogIAcPDgQVRUVODw4cNoaGjA/PnzsXHjRhw6dAirVq3CNddcg+HDh6O0tBQAMGrUKEyfPh233XYbPvvsM3z66aeYO3curr/+ehQVFQEAfvCDH8DpdGL27NnYsWMHXn/9dTz11FOyKiIiIrIeK3cLtiIrl3hYLT9KUQcwmzdvxrnnnotzzz0XADBv3jyce+65WLhwIRwOB7Zu3Yqrr74a3/zmNzF79mxMnDgRn3zyCVwuV3geL7/8MkaOHInLL78cV1xxBS6++GLZGC85OTn48MMPcfDgQUycOBH33HMPFi5cyC7UREQUNatfiEOs0AYmWbYVEEMj3ksvvVS3a9WKFSsiziMvLw+vvPKKbprx48fjk08+iTZ7RERECta9Kst6/VgsmxbLThd8FhIREaU0qwUGUvJeSIkny48VMqSDAQwREZEFWH3gOKthAENERCnNymGB1aqQ5PmxQIZ0MIAhIqKUZuULsaV7ISU6AxEwgCEiItPY2Is6KtLgygq9kKSsFlApMYAhIqKUZvHrcJgVAgYr5MEoBjBERJTSrHxRtvLDE61WIqTEAIaIiFKaldvASFkhn8LazzaQYQBDRERkAVaLF6yWHyUGMERElNKsfCG2cjdqq2MAQ0REprFKJyTZhdjCF2V5OxNrZdTqwQwDGCIiSmkWvw6HWS1gYCNeIiKiHpYs49FYuReS1TGAISIiShBLj8RrsfwoMYAhIqKUI734Bq1+Je5ghSqbZCoRYgBDRESUILJHCVgsYrDCuDR6GMAQEZFprNL2xCr5iMTKVUhWxwCGiIhMY7NMR+pOrEKKLQ+Jz40+BjBERJRykiRmsdxAdjJWy48CAxgiIkpplgsMZKyVOWtvKzkGMERElNKS5ZpsteDBClVaehjAEBFRyrH6xTdE3m258021twXX/HE93tx8pGfzI31t8U3IAIaIiFJO8jwLSfJa8ua3y3Zhy9E6zP/n1h7Pk1p+rIgBDBERxUUixxHRKtmwGq0B9041+hKQm+TCAIaIiEwjHX/F6nfwViPdXK3+QGLyINiNmoiIznCJvAAmS1sO2bgrknz6/MEE5EaOI/ESEdEZKbFVSMlRkiDfRJ1vWhMUwFh5WykxgCEioriwSglMspAGM/5g4tcg8TnQxwCGiIjiwio1EFauCrHa058tPTKwAgMYIiKKi4T2/rFYYKBFqw2MNZ4oZeUtxwCGiIjiJJF38FbuOq3FyiVFVsQAhoiI4iKhAUySVIVYrQoJGiVCVsQAhoiI4iKRpSAWv/aqslrAYLHsdMEAhoiI4sJqF2Srs0K1V7KUXAEMYIiIKE564vq3+ON9eG7N/q7LtvjFNyRZntlkRWmJzgAREaWmeDdKPdXow2MrKgEAN5UMQW9X5yXNCqUZRsh6IUk+tyWoG5I8nrL2NmQJDBERxUW8L3/S5wUFAvKlJUsJjJTV8my1/CgxgCEiItPYJEUHoidHw7fGwClRS5anZlsRAxgiIoqLeF+Q9UoIkiUUsNpDJ63XrVsbAxgiIoqLnrwgd2kzYoVoIEpWy7HVB9ZjAENERHHBhzlGJntqtuS1LUF1YlYPWqSiDmDWrVuHq666CkVFRbDZbHjnnXdk04UQWLhwIQYMGIDMzExMnToVe/fulaU5deoUbrzxRrjdbuTm5mL27NloaGiQpdm6dSsuueQSZGRkoLi4GI8++mj0a0dERAkT74uh3tyT5TrMXtSxizqAaWxsxIQJE7B48WLV6Y8++iiefvppPP/889i0aRN69eqF0tJStLS0hNPceOON2LFjB1auXImlS5di3bp1uP3228PTvV4vpk2bhiFDhqC8vByPPfYYHnzwQfz5z3+OYRWJiKinyEoUenS5PbgwE8kHjkv8SlitTY6eqMeBmTFjBmbMmKE6TQiBJ598Evfffz+uueYaAMDf//53FBQU4J133sH111+PXbt2Yfny5fj8889x/vnnAwCeeeYZXHHFFfj973+PoqIivPzyy/D5fHjhhRfgdDoxZswYVFRU4PHHH5cFOkREZF09egFULMsKwUC0ZE+jtkCvKqv3ijK1DczBgwfh8XgwderU8Gc5OTmYNGkSysrKAABlZWXIzc0NBy8AMHXqVNjtdmzatCmcZsqUKXA6neE0paWlqKysxOnTp1WX3draCq/XK/sjIqLEiXsVkqy0RzEOTFyXbKbkeXii1ZgawHg8HgBAQUGB7POCgoLwNI/Hg/z8fNn0tLQ05OXlydKozUO6DKVFixYhJycn/FdcXNz9FSIioqgkqhuu8uKfLMGA1bot81lICbBgwQLU1dWF/44cOZLoLBERnXFEgkoULH6tNcRq1V4Wy04XpgYwhYWFAIDq6mrZ59XV1eFphYWFqKmpkU33+/04deqULI3aPKTLUHK5XHC73bI/IiLqWT05smzKDWSXsFx00no2kxWZGsAMHToUhYWFWLVqVfgzr9eLTZs2oaSkBABQUlKC2tpalJeXh9OsXr0awWAQkyZNCqdZt24d2trawmlWrlyJESNGoE+fPmZmmYiITJSoXizK0gurlWZoSaYqG6uJOoBpaGhARUUFKioqALQ33K2oqMDhw4dhs9lw11134Te/+Q3+/e9/Y9u2bbj55ptRVFSE7373uwCAUaNGYfr06bjtttvw2Wef4dNPP8XcuXNx/fXXo6ioCADwgx/8AE6nE7Nnz8aOHTvw+uuv46mnnsK8efNMW3EiIjJfwtrAGE1n6SjBAnmzWLduPVF3o968eTMuu+yy8PtQUHHLLbdgyZIluPfee9HY2Ijbb78dtbW1uPjii7F8+XJkZGSEv/Pyyy9j7ty5uPzyy2G32zFr1iw8/fTT4ek5OTn48MMPMWfOHEycOBH9+vXDwoUL2YWaiMji5G1geq4KKXkb8Vq3F5LFstNF1AHMpZdeqrtT2mw2PPzww3j44Yc10+Tl5eGVV17RXc748ePxySefRJs9IiJKoJ6sEgnqdKNONCGE7Mncmuk0Xhv57pkuZXohERGRtcQ7gBGab7QDmp4o5Sj/6jQu+O0qvFvxdVTfs0IJjN42tRoGMEREZBq9weXMJi+BUeYjrovWdedL5TjR0IqfvVYRMW1P9tqKltXyo8QAhoiIorZ8uwdLPj3Y5XOzqpA8dS1Yvbtat8mCbhuY2BfdbYGg8aUnatwcLcnUKyrqNjBERER3vNQ+FMYFQ/Mwpign/LlZ45pMXtQ+HMfiH5yHmeMHaKSKvrTHjGuyPxBEmkP7/t9hj639isXjBcthCQwREcWsxtsqe2/205XX7zuuOS2oVwITp2jgnje2YOJvPsKpRp9mmqgCGIt1Wz5jB7IjIqIzi19RXSK9AEZRkxITvTFntBvxdi9T//riKOqa2/DPcu3H1dij6EGklRsr9EGyQDyliwEMERHFLBAMyt7LL3pxHgdGZ8yZ+Hfh1p4WcxWSxQIGNuIlIqKUFZDHLz36KAFp7NTTF/+gzgKjCWC0eiElahgYqwVRehjAEBFRzPxBZQTTc20oYikhMCtPehf66JrAWKsXkpTV8qPEAIaIiGKm7DLckyUw+o8SiPdjDOJQAmOBgMFqT8fWwwCGiChJ+QNB/L3sEPZW1ycuD8oApgcHZtNbViLbwETTiFc+z8RXISUTjgNDRJSk/rHxKzz03k4AwKFHZvbYcqWlD11LYHquSkRvWVqLNitPprWB0XidKMJqRUI6WAJDRJSkthypTchy9a5r0ml6F3mz89HTl1qzuoiLRK5EBBbLThcMYIiIKCp67Vx6tBeSwccMxEUcFmC1bssWL4BhAENElKxsCWooIX+IYnzbnuiW9sjSaVdlGfk8WnolMNH8LD0Z8BlhgSwYxgCGiCjFBU0eElc/qOjBNjAJfBq1adVj1q1BssSjDfQwgCEiSmHvVnyNCQ9/iA37Tpg2T1kJTNcx/CUv9S+APn8QNfUtMecjke1N4/GYBOk62BL1MAELB1RKDGCIiJKUkUvcz16rQH2LHz958fO45EEnfokYVFz9x/W48LersP94gwnL1ntnPE/Gl609o2iCD/nDE60eMlgLAxgiomSVoJv0oE7Rh161jtJuT/v4NSt2eGLLR1CvJKjnekCZNR8r1NhoVQH+37oD+Pbv16DaG3uJmdkYwBARJalo7vRjHVxNjdndqLMz0mPLh8Zrtfdm02tXFOumtkD8IiPNz2/f34UDJxrx9Kq9CcuPEgMYIqIzgJkBTFCv8az0tW6g0zmxl9MRUz70HyUQ0ywNM2tzCqMbLAHUGvHGo+1PrBjAEBElqWguotE8YDASo9fcY3XNuO5PZVi+vWsVkfRCGM3ItbJ86HTnThbWG4lXf7orzTphg3VyQkREcWM3MYIRkgdQdxl/RfL2ofd2YtPBU7jjpfIu81A+gkBzWYbHgVFO0xgHxgpRggZZLySLPgsp3WGdjDGAISJKUtFcSsy87OiVdkin1TW1aaYzYxyVRFYhmUVWiiR9mGMiMoPIjYrTHdYJG6yTEyIiikqi7tL1Ck+kF700nbt1eWlD95/e3GVE4Jjm2POsVoUUSRoDGCIi6klmNr7Ua8QrlaZTbRUwowRG+trg7HqirUyscaUVSo3kAVXXDJnZlqq7GMAQESWpaLpRm/k4AXlXaeW0zg/07taDJlSXJPRhjiax8MOoLb8NGcAQEZ0BzCjxCNFqtwHIL8J6JTDShsC6y9K7rOu1gbFcOKBFY1tKqtUS9Uwiq29BBjBEREkqUW1gpBc2ZSmI0Z400oAq9oHfdLpRa1x9eyQWiGKFjOSnJ+MXqz/AUYoBDBFRkkpcI97Oi1xAUZJitOTDjF5IQVl3bmU+ko/WJunJdbHwuHpdMIAhIkpaiYlg9B4XYPTZPrpPtDaaD43XiRbNr6JXmhVO04ORhLxNTtflWimoYQBDRHQGOVbXjJr67j2QL2iwDYzetS6WZyZ1nYdOPrSCgZiWFD9GGvH2bJ67H1j2lLREZ4CIiHpGk8+PkkWrAQBf/uo76NPLGdN8pBe2LlVIBktgjI7Eq8foeDTJQrMKqUfbwESY3jPZMIQlMEREZ4gT9b7w698t3x3zfPRLT4yVwUi/F3t7GO3xaOJxoY1HVY5WQ2RpNZQZ7YWM5yd5sASGiOgMIR0Z9/CpppjnI7vo6rSB0Z2HNAgy2KVabx7Glxv7JdrMOKLVH8C7FVXwNnc+bsFqpUZW75HEAIaIKAUFggJtkvod5bWoO3f1QaH+Wrkco1VIseZFvuzYAqlomDnLP67eh2dW7zO2XAtVIVkJAxiKq1++vQ1HTjdjyY8uMPVpuESkr/TJddhX0yD7TB40xD5v6Z25coA8oVOtI2X0cQS6+dBpcKr5NOoYl9W+DGPfNtK9feXOasPz78lB+fS2qdWwDQzFhRACG/afwMubDmPdnuOoOFqb6CwRnVGUwQsA+CVRS7/esTXgBZQlMLGVfARlJTXaX9Kbn14PnnhcfOP1PKmQnmrEGwgK/PzNLfjHxq90l6W6WAtFNQxgKC5W7PDgB/+3KfzejB4HRKQU3XEVkDQ2mTS0r2a6tXuOY291veb0FTs8nTnQGUBOLzBpaQuEX8d6ejBjLJlomFkSonZOlH4iLcUxuxHvR7uq8c/yo/jVO9t182ChWEUVAxiKi4921SQ6C0RxVdvkwy/+tRWfHzqV6KwY0twWQKu/M4CRXkCFEPB1TNtbXY9bXvgM33linea8HltRGX6tfEik0YcTVno6AyQzLtBGq3e6syij3zVSWa4WtPXUSLz1LX7NaWrbUZhQ3RcPDGASbPn2Y/jes5/iSDd6BMSiLRDEJ3uPo8mnvSOrCQZFTC3TrR7JE0Xrf9/fhdc+P4L/fL4s0VkxbObT68OvpUHDf738BcY/tAInG1px5HTnuSgYFHjyoz3495aq8Gdr9xyXzVOvDYyeryTnvFjPD3rtaKzeg8bn79r1SqsbtdmrYrQ1Yig/Vi1ANz2AefDBB2Gz2WR/I0eODE9vaWnBnDlz0LdvX/Tu3RuzZs1CdbW8MdPhw4cxc+ZMZGVlIT8/H/Pnz4ffH92FNlnc8dIX+PJwLX7x1tYeXe7jK/fgpr9+hjtf+sLwd4JBge89+ym+9+yGLieHZl9AMSqmaVmlJNLsC0ROZJJWfwBLt1bhVGPn2CbK/VDL+r0n8PiHld2q2jx0outNx4mGVry/7Zis9093CSHw//1jM2598XNTL8rS9jAfbPegpS2IdyuqkJPZ2TZmzZ4aPPnRXvz3q1+GP7vrtS9l89EbBkb3UQKKEqBY6PV4iscpyGhJkc1AK96va5u7fKY5+wT1Qnpp41eobfKh4khtz2UgCnEpgRkzZgyOHTsW/lu/vjPqv/vuu/Hee+/hzTffxNq1a1FVVYVrr702PD0QCGDmzJnw+XzYsGEDXnzxRSxZsgQLFy6MR1Yto04yFkBPeLmj8ZbybkrPicZWbDlah4ojtbL87qiqw6iFy/FLlfrUkHjeDf1x9V784l9bLX/Hlex2e7zY/nWd5vTFH+/DqIXLVXtXxMMTK/di7itf4sa/tLe18tS1YNTC5fjJks8jfveHf92Ep1fvwztffh17BlSuUdf88VP818tf4Pk1+2Ofr8Kxuhas2FGNj3bVwKso+u/OLh8K3qSlv9XeFry/7ZjkfWvE+XRpxGtw+fKB7Ax+SUHvuT3xCAbifYrRzrK5Czb6ENATDT6c8/BKzHpug6nLN0tcApi0tDQUFhaG//r16wcAqKurw1//+lc8/vjj+Pa3v42JEyfib3/7GzZs2ICNGzcCAD788EPs3LkTL730Es455xzMmDEDv/71r7F48WL4fD69xZ4x/IEgFr2/C2sqY29nkuaI/qe3S/Z66Z3rM6vaxzJ4ZdPhmPPTHb//cA9e+/wItulcXIH2O543Nx9Bq7/nSglSRSAoMP3JT3DlM+tR36IebIfaRSzoodLEUPCx65gXAPCvL44CAD6uNB6US6tLoqU2KkDornq5pJFrdx2v7wwi9C480gC+rinyDVHoGP72H9aEP/vTugP46/qD4feqPWUU79fvPaEYb0a9ZEXa5qV93tLXyuDD2AU7KI9g4k66iLIDJ+OwAI1u1D1ZAmOpVi764hLA7N27F0VFRRg2bBhuvPFGHD7cfmErLy9HW1sbpk6dGk47cuRIDB48GGVl7fXIZWVlGDduHAoKCsJpSktL4fV6sWPHDs1ltra2wuv1yv5S1b++OIo/rTuAH/0t8p2mlrQYxmRxSAMYyRGVkW6NplStKnXKUg+8ux3z/7kV/7tsVw/lKHX4Jb1XTjRY40ZCWU0Tyz7dHbY4PQl6/d4TmPdGRbiUUxYc6OzioUPy/W3HMOHhDyMuJxTAtAW0L1jKkpFAUKBWERwdONGIx1fu6cyHNE+S1//vT/K2QnpVzoZH1dV43f7e/AuxNM/bv/aisTVy04b3JO2HQrQepinvhdS5f5ndC0k/ENb/rpUKuk2/8kyaNAlLlizB8uXL8dxzz+HgwYO45JJLUF9fD4/HA6fTidzcXNl3CgoK4PG037F4PB5Z8BKaHpqmZdGiRcjJyQn/FRcXm7tiFnL0dNe602ilq5TANPsCuOMf5Xir405WSbrfSof+znQ6Ii6vJ/b5SJeTUM8oaRXH0q1VutUiIe9WfI3b/r7Z0AkrFckf3meNM5hPEcA4UmSgxB/+dRPe+uJrPLai67OK9C5koSkL39WuypVSjtSrPlP58sq/Oq2a7KWyzvFEhEZUoawm13sWkl5gopUwNAshBP66/iDe+kK9erA7gY1y11driKs0/59bunymFTTK2/QkpuePlQKUSEwfiXfGjBnh1+PHj8ekSZMwZMgQvPHGG8jMzDR7cWELFizAvHnzwu+9Xm/KBjFmnKalz0QJeeHTg1i+w4PlOzy49rxBXaZLTzLSEhhXWtcApqeKIaUHudF63dCdTcWRWsx9pb1B4qFHZup+52evVQBob+dx7/SRumlTkey3t0gAI734vrelCs/G0O6kOyfr7tzFGvHVya7VW3qDxgWFgAM2GD1DVBypxchfLddNI6vmCQrc+VK5ajrpKNtGg4+gSvDR+T76KqTQOWf/8Ub8eulOQ9+PmiJbRkpGWtq6BjnpGsG21ijG5vdC0t5HrHF0GxP3sv/c3Fx885vfxL59+1BYWAifz4fa2lpZmurqahQWFgIACgsLu/RKCr0PpVHjcrngdrtlfynL6JVah9rd6okG/QZ70l4DfsnFw24gP/GK6uUX0+i2y1cnG6NenhmlX8lIupkj97DpmZIQv+Qu9qevfinrjdQTjOz3RgWCAk99tBcb9p8Ifxa6u5eVfOocR6FjzGi21u87ETEYlV6gPz90Cic1trH0fBJL8KEMBIzGyGoX+XiWkipvzLTyGekn0GysqxHU9eijBJKoCCbuAUxDQwP279+PAQMGYOLEiUhPT8eqVavC0ysrK3H48GGUlJQAAEpKSrBt2zbU1HQ2UF25ciXcbjdGjx4d7+wmTLzq07WonXwjn8w6X+vVm6uJ1wEYiKEEJqSXs7MAUjkYlxatBqypTrpvWKUExoxcdCcGMTF+wbsVX+OJj/bIRq8OdXM22t3Y7HYS7fPsfO3X+d0dWiUwBh8R0OWBkAZ/XbU2vJG+aeZAdrFe7LV+K83Sqzgecl2eJh4pvYXKaEyvQvr5z3+Oq666CkOGDEFVVRUeeOABOBwO3HDDDcjJycHs2bMxb9485OXlwe1246c//SlKSkowefJkAMC0adMwevRo3HTTTXj00Ufh8Xhw//33Y86cOXC5XGZn1zJ6eqdQO/fqnaAA+UEnbdRpSJxWT5qNaK8nWZK2O01tAfR2RT4cog3cUoWQ/fbW2AZ6v3cwKAw9PDReN5vRzvaQSnVRqJRT78nPasy8FTJaRStt4A+VoEKNWvVP53KN5U/+KAHR5TOzxVpSpKR1ExDUKIIx+5CT/VxC8dta4/A2xPQA5ujRo7jhhhtw8uRJ9O/fHxdffDE2btyI/v37AwCeeOIJ2O12zJo1C62trSgtLcWzzz4b/r7D4cDSpUtx5513oqSkBL169cItt9yChx9+2OysJq14ldUEIlycZQGMRS7k8hKY6LaMTaNbuP53olpEytDr8qrUU9tIbzkBIWCPc6lmtPtbtHwdx5iQXciUd8tdp5mZLeni9EqJQ7Gi8m6+SWdgQ73nGMXSCylk04H4PdpBuTytYyHSb2BkjBp5aUz8zrfRHitWqmEyPYB57bXXdKdnZGRg8eLFWLx4sWaaIUOG4P333zc7a5bW01VIaiLdWVuxJ4o0H93ZgslU75sIsvYKFvnt248ZA3eyevPoThVS7F81pLNEofMz3V5IoTYwJubM6HZ0OGxYvt2DX7273fD+IW1KJf1ObZPP+DhVKj11fre8a+8t2VeMzTnS4gDEfh7U+p5amx615ZpJLyi2OtMDGIq/eN34BSJUC0kPumiLaeN1SEhPfN3ZLkZPRGdqnGPGqKmmM6EXUPx6IUU5Y4NtW/RmG48SGOlvrTdfG2y4Q6OHkhahsk/tqKrDzKfXo2RYX0k6Y/kz4yRTVduMvF5OZKSrDw1htKpLK4hsbPWjlytNuw2MRrVaPA855Wk/0q5rpVJoa4xARkmhOxexeNVLKx8kFw158bsZuUld0pOcVUqrdNvA9EAe418C0/5fr7eOVDz2YaPbMZa7drU2MH/79BAA46Pcal3wjX5HameVF//xyGpc/cf1qtPbvyt/H81+9n/rDmDMAyvw7y1Vmr+VZi8k0weyUx+UFIhvI2izMYBJQvGqbopUpx/sxgEVryqnYDD2ICSeJ4hUY8USGL3dtSfyaGobGJ156fXWkSfsmJU5OepYtrF2b7EcPmqNk6M9T+iNJROtd7e0D3y3p7pBM013Apjfvt8+AvjP39hirBdSoqqQLHJ8G8EAJgnFqwgv4tgF3RjMLG7jwBi8O1WjNTCfnmSqHzZTLNsq3vQCeau00eqO0HGuO2KtSvsYMwMr6fzbou15GIFaD6Joe7hpXfBj0eaPPAOj48BEol2FpLFck3dn6R6ibLMU6RxnpSOLAcwZSvUcF+G8p9WdU3WH78adSjSkF6poS1Gi7Z56JlO7UGrpqSpyU9ugmMyMxXdWIXV+tuuYFzf9dRO2HKntmr77i+xCNg6MySUwavuUP+Igicp5RN9ORCtd5AEaTRwHRmNRmiPxxjFs6DIGTxKdCxnAJKF4XSAiVU2p3TEZFb8qJMnrbrTLsUrPGqvqTqAYL/ptYHosG3En3U/nvvIlPtl7osuDEZXpzCItbYs2uIhErXFypHGWPHUtuOMf5eERi82sBjbyXCOzxoExUgKj97BLMynPzWwDQz3GzItJpJLngIH2Jlr5idcFJdCNIKSnThCpQB7sJTAjEnpVJfrdjaO/a08ktWMq9OR1M9uAqJEGLW06x1cs5yG1ElC1301a+nD/O9uxfIcnPGKxmT11jFSNGu5GHbE0O/aqMjPo3oxGyJtVbmAAdqNOekKY1yYmchuYztdaB3tQACrPieyRKqSoS2AkF2KrtOuwqmgGsuspsfZCknUNjtPyjVq9u7r9+Vo6F2795x/Ft2RMenzFtwRGbyU7X1Z7W+STYgjgtLs+Ry+mY8Fm7AYwnp0MjJzLNb9rak66hwFMkjNzxNFIgZBWY0Jp1VPnE3G1v2um7lRrGe2eSsoxOyyyrWIcB8as/OvNxWibhZ8s2QwAuHxkvmYa/WAsvqVJflkAo1MCE8O8je5T0imuNHmlgTwQ6N4WMHIjGGVhhSZDA9nFcRwYvV6FkZZlpep2ViElIenuY+bFJNY2MGrDmStzFbcqpBhKYNR6d1ipWNSKAjonvETR21v12lz1RA+laHen6vqWLp+FjkfdEhjJ63gEltJSF70eQjF1o5aNLdT+X+03la6XUxHAyC7y3Vx9tfOf8rzQtQ2M+kKj6dEp/1zrtbm/raxEVdkGJsKiLHL4A2AAk/TMbI8QuQQm8nK1dv54Re3dGR1YmiWjpeNnapwjbyytvxF67llIsbWBsUwJkkH6T6CWpjN/2bISGJ2TTXcHstOvJut83SWAka6/weVq5VVtd+pS4qKYHuu+pF0Co17qYvZvq981X39hVjp8GMBYRKwnfVNLYGRPKO06XyNjgWjlp2fawLAKKV6sNJBdfUsbgEjdqLWnmZV/M++K1WbV2QbGWDAWl15Iko2l10snphIY6Q2RwXW0K350MxviqwYwyvem9UJS/1yzF1Jsi9GkN6ZXxCokC50rGcAkuVgbn6pXF3V+pjZbaSlKtL2N4lVsH+jGCcyKDVOtSrp54lWaVumpx4mGVt00q3ZVY9yDH+KJlXtibsTbI1VIBtLIjye9dDrLMfECrkbarVlvu8WyaKMNkKVTlL+5vASmexvAyACARktgIj+NWqsERuO16SUw6q/jsax4YgCT5EScqpDUAiMjA79FO8JkdwW7UQLDbtTGRTPicSyPuthX04DSJ9fh4t+t1k33q3e2AwCeWrU3QhWS9jzMegBod3cZafWM3ryMPIFa+dos0ge8mt4GRqWEQb0aR/p7KUpgYsmDRjq1XUEZaHQpgYn1adRGzpMmBmddlq9z3mQJDPWYWEtg1A4I6QGsdrel1WvAyN25JbtR6xSjkly8q5BW764GALS06UfkvTM6O07G3o3aGoGrXpsSKaM9quIxWqt07BcjI9VGQ70EVK0hbedrZYCjDIK6U61nrApJufwYlqP7PfWg1uyxl3SrkNgGhuJJqB743Sc9gNXmK2/0GmUVUrwCmG60AYimYeqZLt7dqL3NfkPpMp2SAEbvYY56vZAMVl1EI9Kduhqjz/0xOqZNPALLgKQKSa8bdSzlUUaDYuMlUMLQNtBKIhsOomNGkRrxGulNpCbqkXhNDk67U31upXMlA5gk1J3RZ/XIx3PRX67WPqzdiLdbWdMk74oZ+4FoNH8WOnZ7VHeeRG6E0aocuyxdrFVIna+7E1h3t/pGGhAY7WnUNQ/mB2NS0iBL72GOsSxa62Ktl65rGxhFlY6BjGglsUeoQlf7rmZj3Ah50Dpvy29OtZfbXd0ZWdtKp0AGMElIxHDhNULWBkZlxlo9HozcncetG3UM2yK0nvEqyUpF0t/P5JoEALE9QVm3BMZgFVJ31kVWxB/D/iOtQlKvso0877iXwEjbwJg8kJ38+Vrt/9V+U9nIyYrpyuUaqQrWbnjbOfPQfLo+fdpgwBSxBCZy3uJ5TtIrgYm0WCuNmcUAJglJD1Izq2b0HrEOaAdORu4U4jYSr1ndqNkGRldUjXhjaBgbS1taM3ohmXUyVh6HRuYqDQj02pfol05Ip8W3BEb5KIGXb50U1bz6Z7tk741frDunKRuIK0vBDJXAREzROZ8uVUiK95olNRGWolmFJE1jsJdaLGRtYLrsu/oLs1D8wgAmkWI9eZpRhRSpp4hqLySNNiNqFzezxkuIpHuNeNVfK1npjiNRjBb3x0o6vofRfTr2cWCkJTDmrEssm0S6bL2nMOu3DzGWLlayIEuyAIfdJvvNjOwTel2gja6jfiNeY21gtPYv6by12icpL+6xtIGx2WKoQjK9DYx2EB+5BMbUrHQLA5gEivWEE6+qj0hF4lolFmolM8p164kqpHg9C4mFM/HvhWQ3cPFQ0gvCjf6e3WsDo7P/GJittNRFrQRG7ZEXSvHuUaX3MEfpb2asVEP53tjxJ+9GrZgmS2csINValFoj3kjf1RyRPEIetNvOqG8Ts485vVHII+fdOidEBjAJJD3YoilC706pgx5ZYKRyYGrd7clKZjomGK4r7iazxoFJpaHn4yGaXguxVAfZJVdDo92L9UpgjD4LyayfNpaSHHkJTNd17mwDoz2PeLfj8uu0gXHYpSUwkeel2+C246X6s5D05ilPZ+Qmxsjgc+E2MMq4VCcIk6fTz4dm4KxVAmPyb6v/KAH971rpbMgAJoFiPeHEa/ySSI8K0Nrp1e4ClevWI92oo2yQabT4nQGMshGv/vbo7tYyXgKjzejvadbxE8tspNVG+sP065ROaNyxm0XeC0k+f1uUVUhdb2q6Tos0FkvXNjDy9e9OI17px6HzirLqRnkei7UXkqGReGXVY+aS36wqApgY2+8kAgOYBIo5gDG5EWJoHkGdnbp9uvpy1YrklcFEvPb5nngWkvxG0ToHb0+Kd1WFtD2F/ngjxuh3S9YP1M1YnpG5SvfdVp0ARrd0UOWJzmbyy8aB6VyYEEJWhWSkF5nylGK0N6Vs2+pWIRlsA6ORRi2wVW5To4O+ST8e1CdTd1la84vnMScvuVbmIcKXLXQKZACTQLHe/QVMPgGHsqE3OqM0nXK6WiDQ5U4lTg1JunOQy9ZBJ39WuuNIlEhVSLJ2CjHMXxoYKttaxEJvdzOrF5LQOB6MzrctwjD9oU+MlibFuw2MsqGx8sGKkRgpgVEjnaRsOCw/Zxk7VrWDDpUARpFGbx1k85LNt+t0rV1cmlQ+b3N/3O60A7PS+ZABTJwdOdWEZl9AdVqs1/SArM1JbPOQzy9UAqNfIqHdjbrrBUF5kohbFZLB0XTlF1hbx2fS72ovg414Izco7G5VjDSA/O/XvtStUgnRW6LRUovu5Lu7jSyNLjuRpYPyIEv+m0jbwBiJZfTaj+gFa0HZsdspEBRdzkPGqpDUPzdSHa2cv/aAd/rnUiPVWPFtxKt98xbxUQLmZqVbGMDE0d7qelzy6Mf4zhNrVafHWirRnYarqvPrmIc/wny128Cgy2vlgR6vIECvKDTS8o1WIfE5SZH3ue4GqNJAdOOBU3iz/Ei35me0UXZ3flplSU60pTmRni0UuljrzVbeBqYzL2aR5lE2crAinZGyGL1zQrgaO0LVtWx+QnQ5ho2cD42MFh4K1iI9vNFIFZJyeTbYDLaBUX9tBr0AK1IBqJVOhwxg4ujDne0PqDt6ull1uqwLcBTz7c7zf0Kkd0yhWUQabTWgUd+uFggkoht1tD2JIrX5CUnWcWDMqIoJidg+SrKoWEbVVQZANd7WqOehlR+9ZXVnv5RVIQmhKA2JzGhjaP3qTWl+zN9PZW1gJBvVofiNjbWB0b74h2atXvKrPo9gUBFYB4WhEmmtzaQWpCuTdm3EqxWI6AfJmlVImm1gzP1ttZoDAJFvRqw06CcDmDhKd+gf1LEOGy0bideEnamz3Yr6MpTp2tOqH1xaJ6J41ZsabcQrK4ZWGV8j1aqQ/vbpQYx5YAXKvzplyvwiViF18/dVnhS7XSWlW4Wkvh9HS/kYCyPPCpMy2ljZaBuYcAmMobka06bxMEeHPfogVa8KSe0cpPY96WR/MKhoD2jsPKOVxq9yAxdpv9QKmCI9o83QSLwa51sz6D2CJVKAYqUSaQYwceSw629eeV288fmaPQ5M+OQhyVDkNjDqQVRnCYwygOl+PtXo1eVKqR3/sYwDY6FjV9dD7+1Eqz+In7+51ZT5RQq2u3tSUzZiNdKVWu+cbnQgO7OqkIJBefsLI4VQZj+NOnT5M/NapzXYnsNuky3HSDij34i3479qY2b1CCYYVJYKC0MXeq0kskH7Os6Fyt/I6I1ZpHO05vGisW+aHTRIS2ejHfLC6H7bExjAxJFDZWAkqVhHke1O12E1au1W1OYr3XFlxecqVUtd67t7ogRGO13EKiSDAUyyVSeZtd0j9dzp7nZRVncFDNQF6J1o9bJjtPdZJMqgLtqBKY1W8elu2zgH19I8So9/h80mCyyMBGxd21pI3wuVz0LfU59HQIgu4xMZ+T0NBR2aJTDy72gGQ4obPOVvaORRBZF6hXaHXnvHSNuQvZDOENLRRVv9XXsiRTM4mJQZJ2B5A7HQyUN9GSHSImR53iVP1e3pNjAGg7lonq6tJK+DjzKDKUL626sFDt3tmqw8oes9G0htmUpGA1IzeyFJ18FImxDjJTDGpoWyY2ZvJM0qJIct6mNBmd4vK/Ft/6+2b+mV/CqrQozkyUgAE5qv8jdSBtZaQbSyPY10NjabdvCqda4xO4DRa4YQaVksgTlDSE9hLW1dd9iY28CYUDeqVgcaqQrJr3KAKz8PVyFF2TAsVkbHwVA75uQNU40tw0p3H0aYlV35b9x1eqwN0kOUPXK0TqLKbrRajLcbiX0DKbvwS/d5QyUwEUqZOgeYNBaMhRueGlglV5qxU7+0G7VPWoXUJUAz1iZGVqoQiHzeaJ/W+Vp5w6IMFLrTjVr6e4TOhV0v7srvqM9MWVqt/K01S2A01tXsoEEamCr3FzbiJQDynU6tBCbWtixmPMtFLQKX3vSq19t2vWMCFN0rw43x5DOI13VfVmpksAQmdPI12gbGrCqHRDAr4PJHCG67O7aKskGrdhF7J71uyEafhdSd7aPsASO7aBn4fqRGvKFB26IvgYksOyPdQCr5cSsdm2dov16KkrboS5PaVM5/qiUwktd+xXnLr/gNujOQnbwEunMZsjTKqiCNfbBroCWfrvXbi3A7Jvl0s887slJzZXV/xBIY83o3dhcDmDiSHvCRSmBirUKKtWhRevJXG4NBtQpJo5pALRDrUoUUpwhGVkevc0FTGxjN6J140GCQlMr07tgA493ZNeevLJo3cJLUC2AMP0qgGxeGLr2QojwuI91VazWIl/LUdQ7RoDWIpJpeLkfENErSm7Cnbjg3pioOrW2k9jgT5TRAUZWpqEIKCGGopEIridpFPdKI4lqBiHIfU170tfbv0Ne6VreZe97RawMT6RxnpV5IaYnOQCqTBzAqbWBkJR6xBTCxBgZtga6lKbK7bJWdVK3IF5BffELzNbtbrBbpevh07mil6dTa6ei1ufAFOn87M57T05PMirf07tgAZZ1/9PNXblcj+db7zXRLLYLG0kWiDID9EbaRUqSLUmj2WqMSH6trxummNkkejM3X6bAjMz2GAKbjJuz2KcMwMDcTfXs5w9OMjJzcnkdpMCK9ieqYrpJ36b6gLAlU7neRBgdU5kFKWboj/a+WBugaeKul8we7Vm0pH4wZEvo03p0g/Brn8vZl63/XSgEMS2DiSFpnrPawtlirJswIYNQGqIpU0qA2ToIyP6GTXE91o5YGLXonL+lv0dbxW7RJfhO9E7D0t/MZ7DliFWb1mmrTOeG1T4/u4q2kvEPV+i2NHie6VYImtYHp2gOmc5qR7R6IsC+FLo5qNz8A8ME2jzx9QL3dhpIrzY6MWAKYjvmndXROyEh34MO7p7RPiyGAUTuPqQVfWs9jCigCg2BQGApgtH4atXFXlNtS2RRAswRGsW8ozxtav1E4aFWkN/vGSXq+61JaHmH/sVIAwxKYOIpUAiOPgo3PV627X7RkJRcd+dQb3AjQbgchXY/QekZbrxqrNpXARI1PJQhpkZyM9E7A0u8aOUGabfXuapxo8GHWeYNiGkDMDMqieyXpCTeW31pZmqL1exi9UOrV02tVlQohcPhUE4r7ZMl6EGpRDlwnK4ExEMBIt5kNQaQjgDQE4EAQdgSR4WsB6qvhavJgII7DbgvCgWDHdIHsOjvG2A6GP8v0AMjIxfnBbWiz+8Pz6fxOEGkIIMdhR1GbE8Md9bBJu0JDwNbxX/neBtFePOAAJtZ8CWzKBwD0a2zFjxx72qc7IPu+gA3Bjm+H/ts2VwGudAA2XCN2wOcAgsKGYY3ZwNYjuKhpF862+xCErWMtbchvzgR21wM2O8Y27UKGvRUBOOCsysSQlq8xxlYHPxzIbXLAUevFQBxHG9LghwN+2OEPv+7YclolMCq9LJX7urIpgGYbGMUyWiXfCwRFeFnONLvs/BLKm/KGKpSPxlY/fvXudlwxdgCmji5QXXYk3pY2LN/RGfwqn9UXsQrJQtXoDGBM4vMH4VS07G+NEMBIL6DR1HE2+vzh17HuTNLlhU6ksqhcJT91zZ3F1a1t0rx3fq+54/MmxUERr653WgNt6aULraf0ZGS0BObIqWb88u1t+O33xsWU32h5W9rwkyWbAQB9ezlx+Sj1k1Zdcxsy0x1d9kGzSoykv3GrSnsu+R1d9L+18vjQ+j2MVlU0+QLtUUUwAAR8HX9tQMAHV8NRnG37GukI4KzWE8BhGxDwYcOeKvx17R7MHNMXs8bnh9NLvyv9bE7rfrSmtSAdfhR9/E84bQE8l16FdPjRyxcEljyp8v3O1ze3tOCHLh/S4Ue6TaWUxQ/gD8BDAB7KUFnJz4H/dEner2n/9zc7AKdK+pAggFoAxtrxdnWg4w9AHoAHo5nPh50v/9cBIFQQVAvgLeB+oGveWwC81v7yIen0t4FfAkBoG2xp//tUbVt1CAob8Eoa4EgH7OlAmhNwuIA0F35XF0Cd045WpOPsj/sC5dkY1GbHE+le+EQ6WpGO8bvzMT+tHq3C2f7+60Jg82AgLQNIzwTSewHOLIwI7MNJmwPNwoUmuNDQUI/2CNCGoOgsKXIpA5iO/10CmI5j6q/rD+KtL77GW198jUOPzNReUR0rtstL7upb/LL3kY5fK1WjM4CJ1qY/AUc+Q7MtE7UBJwb074cP9zViw5EWzJ1+Dvrl9YVwZqHV3gtH9+xBIQJoQgZaW30AgKVbq2C32XDFuAGy572EiiYbWv2oOFyLycPy4LDb0NwWgA02pDtsaGoLwOmw40RD5/e8zW0QQmDjgVOw24AJxbn44qvTmDSsr+bdus8flAUYPn8QwaCQXUQaWv3wB4JIc7RfENsCQby08bAkv9LGs5079FOr9mJkoRtNPvlBcbrJJ3sfCAps2H8C5xTnavaICAYF9tTU4xv52brrEn6t145Fks7bccA2S9b3iY/24HvnDkT/bBdsNiDdYQ8vU3kyeXnTYfzmu2NVx/qoa2pDdkYaKqvr8dXJJkwfW6iZJwA40dCK1btrcNmIfAgINLT4ERQCw/Oz26fXd/7WO6q8sgCmsdWPdIcdP/rbZ9iw/yQu+UY/vPjjC2XBYmNrAOVfncZ/v/olfjFjJK6aUBSedrrRh492VWPm+AHIcnY9FRw80YiBuZlo9Qdw5FRT+PM3Nn+Fmy4oxNjCzM4Lc20NzrIdQzoCyAoGULX9E/TNsMFl98su3vWNTdh8oBqTh2Qj0x4E/K1AwIerTh3A5LR6pCOAdPgx+LgDeCevy0X/d43VCDp9cMLffuHv+HPapO8DyFwRAD5og1rvmG8D+HbooncCwAvtLy8CcJETwN6OvwiuBzrPoPvb/82Q1swc0v9+BhCx97GADQHYERB2+GFHAHYEO/4709PR2CbaPxN25PbORFaGE/tPNMvSBWFHwOaAX7SnczrTkOl0oqahDaJjGWkOO84bkoeNB07KymFE6MntkvcjCt04u38vADY0twXx0e4a1XQ2CNg7/tDx/1vf6Ite6XYIEcDqXdXhNO4MO84rzkHZvuMQQsBuEx3TgnDagVGFvWG3Afs9tQgG/EhDAINy0tDQ1AK/v728pVeagNMWhL/NhzQEkGbrGuzabQIItrX/AYDkkVtnAZ2NKqrb/3IBfE/6mx4FzpEeKl91/Cm8bkNnYAUALwAHXDY0wYUWOIEdvXCjMw0BWyZq09PDn2fX5KL27WLUNDow29GAemSiQWQit+o0jm4dhGCNF4WoRQMysf3oaYwZmAshgK9rm1Hb1IZxg3IAAJ8fOoXBeVkocMujOX8giMZW+bm5stoLoP18GxAC+483AgAuH5mPVbtruqxb6Dpx9HQT+mQ50cuVuDDCJiw8tOjixYvx2GOPwePxYMKECXjmmWdw4YUXGvqu1+tFTk4O6urq4Ha7TcuTeONHsO18O6bvtoh0NCATTcKFRmSgBS60CCdakI4WONGrdzaO1gu0wokWONEinGgOve5434qOz0Tn5z6koU2ktf9HGnxIRxvSYEtLh88vkO1Kw42Th+DqCUX4YPsxPLN6n+E8Tx6WhyU/vhBLNhzCIx/s7jLd6bAbvsu/pWQIXizrerT3z3ahT1Y69lQ3aH537EA3tn/dfqBde+5AvLulSrcu9tzBufjycK2hfCXCd0YX4MipJuz2eOFAMHzhDV+EbQHZBTn0Os0WCF+80yB53ZHe2VFgno4AnLbO17J52brOV/q5LDiQfRbQLi1IEq2i/RhpCx8raWgTji6fZWRkwOZw4niTQHPQDtidCNjT0dBmgw9pyMrMxIlm0Z5epKENDsU8FcsIf+aAT3KMSr/vR/v/UOARgB1Gx1eJ5Ky+WTh0sj0IHVPkxln9emHZ1mPh6a40O8p/9R2MfWBFxHktvHI0fnLxUADtQfC5v16pm/6jed/C1MfXdiP3sRLtgYzkL1xNZ2t/nZ9lQ1NTE1zwwWnzw4U2uNAGJ9rgsrWF37sk752S96HXGfAhw+ZDFlqQCR8yba3IQvufy9YWOasxCAobGpCBho4gpwGZcGblIOhyY9tJO+rQC71z+2P7aTvqRC/UoTdqRW/UiV6oRS80wwW9/esnFw3FC58e1M3D2IFuvDf34pge4KrH6PXbsiUwr7/+OubNm4fnn38ekyZNwpNPPonS0lJUVlYiPz8/YflalnY5vmzrhSy0oJetBb3QgixbC3qjBVloQW9bi2xaLzTD2XHCz7C1IQNt2vtMM0z/RXyO9hOrb2M62jam4Tqk4VqnQ34C7TiJ+uEI37GF6osDR+xY9rAdfYUdj6TZEehII/0LpoVeOxAQks/Dtecdd2efAbMdXe/U0ASIJhsmd9zpSL8Tfu+xYbyjoxB2K3CDLQg40JFb0VFbHoQNHZ99LVDiEOEc2CFgtwXDr6V3h5217e3vHQggDUE4OtojOGzBjrYJnZ/L/tvaT4rtbQyU0wOS70v+729Pn+4KtN8VJjG/sKtcrB3y97KLdejPEeFinwYfHKrf92nMU+/7fjhgOCDwRZhe392t1rPO6tcrHMDsqPKif7ZLNn1Qn0z0ltxJ93I60OhTD1SL87LCr3MyteuPBuZmonRMIYbn9+5O1rvB1hHOq5xUOw65g41dPzObAwFkorX9z+brCGxakGlrRek33Ni89yiybO3Te3VcQ3qjCb1tzchGc+d/NCHb1ozeaEa6rf284UYz3Gju3K1b2v/Gh1a5AZpVha0iDV70Qq3ojdqO/6H3p0Q2SoNj8LX9NE4JN04hG6dENmrRG0LS92f71158tKsG34mxPU53WTaAefzxx3Hbbbfhxz/+MQDg+eefx7Jly/DCCy/gF7/4RcLytWBLPuoDV0T1nXT424MbNCPL1trxvwUZ8CGzI3LPgA8uxfsM+JBpa/9c+j702mVrj/xDd8xOtMGhuBg6bQE4EUAvaVlpYtqBkkGhi78/dIFHGvxC8hqdwYFfVnogea32uVDMUxJA+MMlA8oAQC0AkQcVQRM7M869bDj++LHxEsIz0cjCbOz2dEZQt148FH9Zr3+nfNfUb2JN5XEA7YPQTR9TGH4/MDcTT11/LgDgldsm4bXPjuDn00ZgymMfq85raL/OAEavsfP6+y4L35nfP3MUfrNsV5c0P5/2Tfz+wz26ebeiCYNysOVonW6aC87qA3dGOlbtrkEDstCALHmQJICn/3Mq9q3ai73VDSg7cLLLPK6/oBivfX5E8amAC20dwU2TJMhpQm80w21rQg4akWtrQI6tMfw6Fw1w2xqRi0ak2wJw2fzojzr0t2msx5fAnxTtkQLChtMdwcxpZOOkcKNPzX8Do6+KvNHiwJIBjM/nQ3l5ORYsWBD+zG63Y+rUqSgrK0tgzoCKB6bhwX/vQNmBkyjKzUSNtwUXDs0DAPy97CsM6ZuFsQNzsGzrMUwelodfXTkaWc40LHp/F5rbAihwZ2DLkVp8WdOAgbmZePW2yTjR2IpTDT6s33cCvXMysKayBhsPnAovc9roAowa4MZlI/Mx740KHDjeiEeuHYd/bPwKO6q8svzZO6ojnPBjVH8nRvbPQH1TM4b1Scfh47U45W1AbX0jnDY/fnbpWXjxk0og0BZuRzD5rFwM7uPCv788AgeCmFicjW1HTqFPpgPnDOyN84rd+PzAcez31CEjHThnYDYO1dThgiE56JuVhq9P1eOTymqcMygbI/KzYANQU9+KT/cdhw0CfXu5cG5xDqpqm7Hb45X0eABCR/eowmzsrfYiKIC8rHTUdrSfGT/QjdzMNBw42Ywjp5sRhA3D890YXuDGjmP12H+iCYPyeqG5TeBEYxt8AeCsfr1xvLENdc1+BGHHyAE5aPYHcXa+G9u+9uKCof2QnelEVV0rDp5sgoAN6elO7DvRjN5ZGZgyohD/9+lhwJ6G+TPG4ERTAJkuF/yw4/OvvPhg54lwiZMfDvxi5hi8s6UaATgwvDAXm494cfu3vonPv/LihY1HccHQfth3ogVV9W3wi/ZSKx/ScO5Z+fiqzoeDp9swrF9vTBtTiOfXtjesuGnyEPz4orNw+R/WorCjTrvJ58fv/3MCFr67Ax5vCy48Kw8VR2vD7XVmjhuAP/y/CZj+5Docq2vBQ1ePgd1uw6hCN6q9LTj/rD44VteCPdX1CAqBCYNy4bDbsOtYPQ6dbMSx2mY0+QL4ZkE2Jg/ri6v+uB4A0NuVhoaOOvSnrj8H5w3ug98s24kVO6rx0NVjcHPJECzbdgwL392B9I7n5Txzw7l44N0dqKyuh8NuU636czrs+GjetzC4bxYuHdEf339e+zh/+dZJ+EZBb3xv8QZcOWEANh86jcZWP57/4UT06eXEx7tr8MH2Y6hv8eM/zu4bvkBec04R9lQ3IDsjDUP79sKtlwxF74w0HDjeiMdX7kH5V6dx1YQi9HY58Opn7ReN4rxMlAzri7IDJ5GfnYHyr07L8vLQ1WPgzkzD3a9vAQA8fcO5GD3Ajev/XIZAUGD62AEY1CcTFUdqsXJnNQDg7P69wu0MLh7eD3MuG459NfW4YtwA5GSmY//xRmSmO8IBxNRR+XjomrHo5XQgy5kGZ5odf11/EL9euhN5vZy4Z9oIXHdBMV749CAOnWiCOzMNV08YiDc2H0Ga3YYbJw/GOcW54Tz/6spR+PbIAkwfW4jcLPkV6j/O7of/OLsfAODQIzPxm6U7IQD88opReG7tftQ2+XB2f3mJyup7voX/evkLnJ3fG1eOG4BP95/A/GkjZdUKt14yDGsqj2P9vhMAgH/MvhBji3LQp5cT1184GGsqj+Pnb27BBWf1wdM3nIs/rT2AfLcLV08owsW/6wykpo7KR+mYQhw+1RSuCp9fOgKThubhnYqvUZSbifJDp/Hg1WM62ukJ/O/7u7F6dw3+MftCnGhoDf9W/3PFSNQ1t+H1z4/g3MF9cKyuGQ9dPQaZ6WnYerQWLW0BTD67L7Iz0tG3lxOfHTyFD3d6sMfTgP+7+Xz8e8vX+NW7OwAAIwqyUVndHlReeFYeLh3ZHzeXnIU0uw03//UzfHboFH580Vn4yUVDIQQw5bGP8e2R+ejb24WHrxkLAPDUtaChtQ2/X7EHm786hWX/fQkK3Blo9AXw3pYqyT43FkIInGjwYevXdVi353g4MBqYm4nRRW7ccsUoXPb7NQCAUQPcuOCsPmgLCCzbWgVvSxuy0IoV/99YPP7vTfBUe5CDRgxwNuGc/jaM6ePHkIwWpLeeRsNpD+xNJ5HRVgt7ax0cNoF+8KKfTXLd6RefKjIjLNkGpqqqCgMHDsSGDRtQUlIS/vzee+/F2rVrsWnTpi7faW1tRWurpHGr14vi4mLT28D0BCEEVu2qwZiBbgzIyZRNCwYFTjS2Ij+7a1P7mvoWuDPSUdfc1qXxlp6WtgBcaXbZCaelLYAmXwB5vfS6M3RfS1sgpjEpohUICpxoaI1qu0i/GwiKLj18uqPJ54c/KOB0xDYmR08LBgVq6ltRmKO+/eL5O4ZOUbHWswvRPg6HK8362zkaoYb2yiBES/lXp3D0dDOuOWdgnHNG3RUMinDplhACrf5gTMeXqcdloA1oOtn+13gCaDoBNJ0Chk8F8oaas4wOSd8GJlqLFi3CQw89lOhsmMJms2n28bfbbarBC4Dw59HusGrpM9IdPXJh7amLt8Nuiyl4CX3X7PFX1Hr9WJndbtMMXoD4/o7dbSBos9lSLngBIGuzYsTEIXmYOCROmSFTSavmbDZbzMeXqcelIx3ILmz/swhLjsTbr18/OBwOVFdXyz6vrq5GYaH6xluwYAHq6urCf0eOKOsNiYiIKFVYMoBxOp2YOHEiVq1aFf4sGAxi1apVsiolKZfLBbfbLfsjIiKi1GTZcux58+bhlltuwfnnn48LL7wQTz75JBobG8O9koiIiOjMZdkA5rrrrsPx48excOFCeDwenHPOOVi+fDkKChLT35yIiIisw5K9kMwQr5F4iYiIKH6MXr8t2QaGiIiISA8DGCIiIko6DGCIiIgo6TCAISIioqTDAIaIiIiSDgMYIiIiSjoMYIiIiCjpMIAhIiKipGPZkXi7KzQ+n9frTXBOiIiIyKjQdTvSOLspG8DU19cDAIqLixOcEyIiIopWfX09cnJyNKen7KMEgsEgqqqqkJ2dDZvNZtp8vV4viouLceTIET6iwATcnubi9jQXt6e5uD3NlarbUwiB+vp6FBUVwW7XbumSsiUwdrsdgwYNitv83W53Su0wicbtaS5uT3Nxe5qL29Ncqbg99UpeQtiIl4iIiJIOAxgiIiJKOgxgouRyufDAAw/A5XIlOispgdvTXNye5uL2NBe3p7nO9O2Zso14iYiIKHWxBIaIiIiSDgMYIiIiSjoMYIiIiCjpMIAhIiKipMMAJkqLFy/GWWedhYyMDEyaNAmfffZZorNkOQ8++CBsNpvsb+TIkeHpLS0tmDNnDvr27YvevXtj1qxZqK6uls3j8OHDmDlzJrKyspCfn4/58+fD7/f39KokxLp163DVVVehqKgINpsN77zzjmy6EAILFy7EgAEDkJmZialTp2Lv3r2yNKdOncKNN94It9uN3NxczJ49Gw0NDbI0W7duxSWXXIKMjAwUFxfj0UcfjfeqJUSk7fmjH/2oy/46ffp0WRpuz06LFi3CBRdcgOzsbOTn5+O73/0uKisrZWnMOsbXrFmD8847Dy6XC8OHD8eSJUvivXo9ysi2vPTSS7vsn3fccYcszRm7LQUZ9tprrwmn0yleeOEFsWPHDnHbbbeJ3NxcUV1dneisWcoDDzwgxowZI44dOxb+O378eHj6HXfcIYqLi8WqVavE5s2bxeTJk8V//Md/hKf7/X4xduxYMXXqVPHll1+K999/X/Tr108sWLAgEavT495//33xy1/+Urz11lsCgHj77bdl0x955BGRk5Mj3nnnHbFlyxZx9dVXi6FDh4rm5uZwmunTp4sJEyaIjRs3ik8++UQMHz5c3HDDDeHpdXV1oqCgQNx4441i+/bt4tVXXxWZmZniT3/6U0+tZo+JtD1vueUWMX36dNn+eurUKVkabs9OpaWl4m9/+5vYvn27qKioEFdccYUYPHiwaGhoCKcx4xg/cOCAyMrKEvPmzRM7d+4UzzzzjHA4HGL58uU9ur7xZGRbfutb3xK33XabbP+sq6sLTz+TtyUDmChceOGFYs6cOeH3gUBAFBUViUWLFiUwV9bzwAMPiAkTJqhOq62tFenp6eLNN98Mf7Zr1y4BQJSVlQkh2i84drtdeDyecJrnnntOuN1u0draGte8W43yghsMBkVhYaF47LHHwp/V1tYKl8slXn31VSGEEDt37hQAxOeffx5O88EHHwibzSa+/vprIYQQzz77rOjTp49se953331ixIgRcV6jxNIKYK655hrN73B76qupqREAxNq1a4UQ5h3j9957rxgzZoxsWdddd50oLS2N9yoljHJbCtEewPzsZz/T/M6ZvC1ZhWSQz+dDeXk5pk6dGv7Mbrdj6tSpKCsrS2DOrGnv3r0oKirCsGHDcOONN+Lw4cMAgPLycrS1tcm248iRIzF48ODwdiwrK8O4ceNQUFAQTlNaWgqv14sdO3b07IpYzMGDB+HxeGTbLycnB5MmTZJtv9zcXJx//vnhNFOnToXdbsemTZvCaaZMmQKn0xlOU1paisrKSpw+fbqH1sY61qxZg/z8fIwYMQJ33nknTp48GZ7G7amvrq4OAJCXlwfAvGO8rKxMNo9QmlQ+3yq3ZcjLL7+Mfv36YezYsViwYAGamprC087kbZmyD3M024kTJxAIBGQ7CQAUFBRg9+7dCcqVNU2aNAlLlizBiBEjcOzYMTz00EO45JJLsH37dng8HjidTuTm5sq+U1BQAI/HAwDweDyq2zk07UwWWn+17SPdfvn5+bLpaWlpyMvLk6UZOnRol3mEpvXp0ycu+bei6dOn49prr8XQoUOxf/9+/M///A9mzJiBsrIyOBwObk8dwWAQd911Fy666CKMHTsWAEw7xrXSeL1eNDc3IzMzMx6rlDBq2xIAfvCDH2DIkCEoKirC1q1bcd9996GyshJvvfUWgDN7WzKAIdPNmDEj/Hr8+PGYNGkShgwZgjfeeCNpDxRKXddff3349bhx4zB+/HicffbZWLNmDS6//PIE5sz65syZg+3bt2P9+vWJzkrS09qWt99+e/j1uHHjMGDAAFx++eXYv38/zj777J7OpqWwCsmgfv36weFwdGlJX11djcLCwgTlKjnk5ubim9/8Jvbt24fCwkL4fD7U1tbK0ki3Y2Fhoep2Dk07k4XWX28/LCwsRE1NjWy63+/HqVOnuI0NGDZsGPr164d9+/YB4PbUMnfuXCxduhQff/wxBg0aFP7crGNcK43b7U65GyGtbalm0qRJACDbP8/UbckAxiCn04mJEydi1apV4c+CwSBWrVqFkpKSBObM+hoaGrB//34MGDAAEydORHp6umw7VlZW4vDhw+HtWFJSgm3btskuGitXroTb7cbo0aN7PP9WMnToUBQWFsq2n9frxaZNm2Tbr7a2FuXl5eE0q1evRjAYDJ/8SkpKsG7dOrS1tYXTrFy5EiNGjEjZ6g6jjh49ipMnT2LAgAEAuD2VhBCYO3cu3n77baxevbpL1ZlZx3hJSYlsHqE0qXS+jbQt1VRUVACAbP88Y7dlolsRJ5PXXntNuFwusWTJErFz505x++23i9zcXFnrbxLinnvuEWvWrBEHDx4Un376qZg6daro16+fqKmpEUK0d7EcPHiwWL16tdi8ebMoKSkRJSUl4e+HugVOmzZNVFRUiOXLl4v+/fufMd2o6+vrxZdffim+/PJLAUA8/vjj4ssvvxRfffWVEKK9G3Vubq549913xdatW8U111yj2o363HPPFZs2bRLr168X3/jGN2Tdfmtra0VBQYG46aabxPbt28Vrr70msrKyUrLbr972rK+vFz//+c9FWVmZOHjwoPjoo4/EeeedJ77xjW+IlpaW8Dy4PTvdeeedIicnR6xZs0bWtbepqSmcxoxjPNT1d/78+WLXrl1i8eLFKdH1VyrStty3b594+OGHxebNm8XBgwfFu+++K4YNGyamTJkSnseZvC0ZwETpmWeeEYMHDxZOp1NceOGFYuPGjYnOkuVcd911YsCAAcLpdIqBAweK6667Tuzbty88vbm5WfzXf/2X6NOnj8jKyhLf+973xLFjx2TzOHTokJgxY4bIzMwU/fr1E/fcc49oa2vr6VVJiI8//lgA6PJ3yy23CCHau1L/6le/EgUFBcLlconLL79cVFZWyuZx8uRJccMNN4jevXsLt9stfvzjH4v6+npZmi1btoiLL75YuFwuMXDgQPHII4/01Cr2KL3t2dTUJKZNmyb69+8v0tPTxZAhQ8Rtt93W5aaE27OT2rYEIP72t7+F05h1jH/88cfinHPOEU6nUwwbNky2jFQQaVsePnxYTJkyReTl5QmXyyWGDx8u5s+fLxsHRogzd1vahBCi58p7iIiIiLqPbWCIiIgo6TCAISIioqTDAIaIiIiSDgMYIiIiSjoMYIiIiCjpMIAhIiKipMMAhoiIiJIOAxgiIiJKOgxgiIiIKOkwgCEiIqKkwwCGiIiIkg4DGCIiIko6/z8SfIo+OCxMIwAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "arclist = load_pypeit_calibration_lines(['HeI', 'NeI', 'ArI'])['wavelength']\n", "trace = FlatTrace(match_im, 256)\n", "arc_sp = BoxcarExtract(match_im, trace, width=5).spectrum\n", "arc_sp.uncertainty = StdDevUncertainty(np.sqrt(arc_sp.flux).value)\n", "continuum = fit_generic_continuum(arc_sp, median_window=51)\n", "arc_sub = Spectrum1D(spectral_axis=arc_sp.spectral_axis, flux=arc_sp.flux - continuum(arc_sp.spectral_axis))\n", "arc_sub.uncertainty = arc_sp.uncertainty\n", "\n", "fig = plt.figure()\n", "plt.plot(arc_sp.spectral_axis, arc_sp.flux)\n", "plt.plot(arc_sp.spectral_axis, continuum(arc_sp.spectral_axis))\n", "plt.show()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Find the emission lines in the extracted and background-subtracted spectrum and try matching it against the linear WCS. Only lines within a portion of the spectrum will be within a 3 pixel tolerance. " ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING: No observer defined on WCS, SpectralCoord will be converted without any velocity frame change [astropy.wcs.wcsapi.fitswcs]\n" ] }, { "data": { "text/html": [ "
QTable length=71\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
pixel_centerwavelength
pixAngstrom
float64float64
68.104027612333073889.75
118.808179729103663950.097
198.880892886391964045.561
299.304367536514064165.354
329.865633917613654201.858
379.18618003329514260.561
413.261290027392534301.311
442.821541056386374336.557
451.038562722366464346.39
......
2051.64082893485246250.134
2066.87834825838956268.2285
2099.3959915460546309.401
2152.6824345705746371.336
2165.7618321550616386.482
2294.2874836450456539.918
2349.4978244025776606.677
2589.07976773539946890.074
2638.8458590374076953.395
2650.65233876953656967.352
" ], "text/plain": [ "\n", " pixel_center wavelength\n", " pix Angstrom \n", " float64 float64 \n", "------------------ ----------\n", " 68.10402761233307 3889.75\n", "118.80817972910366 3950.097\n", "198.88089288639196 4045.561\n", "299.30436753651406 4165.354\n", "329.86563391761365 4201.858\n", " 379.1861800332951 4260.561\n", "413.26129002739253 4301.311\n", "442.82154105638637 4336.557\n", "451.03856272236646 4346.39\n", " ... ...\n", "2051.6408289348524 6250.134\n", "2066.8783482583895 6268.2285\n", " 2099.395991546054 6309.401\n", " 2152.682434570574 6371.336\n", " 2165.761832155061 6386.482\n", " 2294.287483645045 6539.918\n", " 2349.497824402577 6606.677\n", "2589.0797677353994 6890.074\n", " 2638.845859037407 6953.395\n", "2650.6523387695365 6967.352" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cenlist = find_arc_lines(arc_sub, fwhm=3, window=3, noise_factor=10)\n", "matched_list = match_lines_wcs(\n", " pixel_positions=cenlist['centroid'], \n", " catalog_wavelengths=arclist, \n", " spectral_wcs=bc_linear_wcs.spectral, \n", " tolerance=3\n", ")\n", "matched_list" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "image/png": "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fmgkmcbGRmOMMZs2bTIFBQWmvb090qa+vt6UlJSYnp4eY4wx//iP/2jOPvvsqGNee+21ZsGCBRZ/ssyJd46MMYMeD5QP56iurs6cc845MV/je9RnqHNkDN8jY4xZvXq1ufjii+O+HgqFjM/nMw888EDkuSNHjpiioiLzzDPPGGOMaWlpMZLM22+/HWnzwgsvGI/HY/bv32+MMebf//3fzSmnnBI5b+Fjz5gxI9MfyRKJzpMxfYHI1VdfHff1fDhP/d16661m+vTpJhQKOfKalPdTMytXrtSVV16pmpqaqOffeecdHT9+POr5s846S1OmTFFjY6MkqbGxUTNnztSkSZMibRYsWKBgMKgPPvgg0mbg716wYEHkd+SCeOco7KmnntKECRNUVVWlNWvW6PPPP4+8li/n6OOPP9bkyZM1bdo0XX/99dq7d68kvkf9xTtHYfn+PfrFL36hCy64QNdcc43Kysp03nnn6bHHHou83traqvb29qjP6PV6deGFF0Z9l8aNG6cLLrgg0qampkYFBQXaunVrpM2ll16qUaNGRdosWLBAO3fu1B//+EerP+awJTpPYa+++qrKyso0Y8YMrVixQh0dHZHX8uE8hR07dkzr16/X3/zN38jj8TjymuToTe+s9uyzz2rHjh16++23B73W3t6uUaNGady4cVHPT5o0Se3t7ZE2/f9HhV8PvzZUm2AwqC+++EKjR4/O1MexxFDnSJK+/e1va+rUqZo8ebLee+89rV69Wjt37tTPf/5zSflxji688EI9+eSTmjFjhtra2rR27Vpdcsklam5u5nv0J0Odo7Fjx/I9kvTJJ5+ovr5eq1at0l133aW3335b//AP/6BRo0ZpyZIlkc8Z6zP2PwdlZWVRr48YMUKlpaVRbSoqKgb9jvBrp5xyiiWfL1MSnSdJqq2t1V/+5V+qoqJCu3fv1l133aWFCxeqsbFRhYWFeXGewp5//nkdOXJES5culeTMe1veBiL79u3Trbfeqs2bN6u4uNju7jhSMufo7/7u7yL/PXPmTPn9fs2bN0+7d+/W9OnTs9VVWy1cuDDy37NmzdKFF16oqVOn6r//+78df/PLlqHO0bJly/geSQqFQrrgggv0gx/8QJJ03nnnqbm5WY888kjkBovkztO3vvWtSPuZM2dq1qxZmj59ul599VXNmzfPln7b5fHHH9fChQs1efJku7sSV95Ozbzzzjs6dOiQZs+erREjRmjEiBF67bXX9G//9m8aMWKEJk2apGPHjunIkSNR7zt48KB8Pp8kyefzDco0Dj9O1KakpMTxN6lE56i3t3fQey688EJJ0q5duyS5/xzFMm7cOH3pS1/Srl275PP58v57FEv/cxRLPn6P/H6/Kisro5778pe/HJnCCn/OWJ+x/zk4dOhQ1OsnTpxQZ2dnSt83J0t0nmKZNm2aJkyYEPV9cvt5kqTf//73eumll/S3f/u3keeceE3K20Bk3rx5ev/999XU1BT5ueCCC3T99ddH/nvkyJF6+eWXI+/ZuXOn9u7dq+rqaklSdXW13n///agv9ObNm1VSUhL5h1JdXR31O8Jtwr/DyRKdo8LCwkHvaWpqktR3sZDcf45i+eyzz7R79275/X6df/75ef89iqX/OYolH79HX/3qV7Vz586o5373u99p6tSpkqSKigr5fL6ozxgMBrV169ao79KRI0f0zjvvRNps2bJFoVAoEtxVV1fr9ddf1/HjxyNtNm/erBkzZuTEdEOi8xTLH/7wB3V0dER9n9x+niTpiSeeUFlZma688srIc468JqWTgetWAzP3b775ZjNlyhSzZcsWs337dlNdXW2qq6sjr4eXOF1xxRWmqanJNDQ0mIkTJ8Zc4nTHHXeYDz/80Dz88MM5taRwoP7naNeuXeaf/umfzPbt201ra6vZsGGDmTZtmrn00ksj7fPhHN1+++3m1VdfNa2trebXv/61qampMRMmTDCHDh0yxvA9Mmboc8T3qM+2bdvMiBEjzH333Wc+/vhj89RTT5kxY8aY9evXR9rcf//9Zty4cWbDhg3mvffeM1dffXXM5bvnnXee2bp1q3nzzTfNmWeeGbUs9ciRI2bSpEnmhhtuMM3NzebZZ581Y8aMyYllqcYkPk9dXV3me9/7nmlsbDStra3mpZdeMrNnzzZnnnmm6e7ujvwet5+n3t5eM2XKFLN69epBrzntmkQg0s/AQOSLL74w3/nOd8wpp5xixowZY775zW+atra2qPfs2bPHLFy40IwePdpMmDDB3H777eb48eNRbV555RVz7rnnmlGjRplp06aZJ554Igufxhr9z9HevXvNpZdeakpLS01RUZE544wzzB133BFV/8EY95+ja6+91vj9fjNq1Chz6qmnmmuvvTaqpgHfo6HPEd+jP9u4caOpqqoyRUVF5qyzzjL/8R//EfV6KBQyd999t5k0aZIpKioy8+bNMzt37oxq09HRYa677jpz8sknm5KSEnPTTTeZrq6uqDa//e1vzcUXX2yKiorMqaeeau6//37LP1smDXWePv/8c3PFFVeYiRMnmpEjR5qpU6ea5cuXRy1FNcb95+nFF180kgZ9P4xx3jXJY4wxqY+jAAAADF/e5ogAAAD7EYgAAADbEIgAAADbEIgAAADbEIgAAADbEIgAAADbEIgAAADbEIgAAADbEIgAAADbEIgAAADbEIgAAADbEIgAAADb/H81MwlSfZpMrwAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig = plt.figure()\n", "pred_wavelengths = bc_linear_wcs.spectral.pixel_to_world(matched_list['pixel_center'])\n", "residuals = matched_list['wavelength'] - pred_wavelengths.to(u.Angstrom)\n", "plt.scatter(matched_list['wavelength'], residuals)\n", "plt.show()" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "This attempt works pretty well up until about 5500 Angstroms. Red-ward of that, the arc lines become crowded and the grating model diverges further from the linear model. There is enough to start with for fitting a wavelength calibration solution. However, we will need functionality to reject spurious lines from the fitting process. This is often done iteratively. Start with no rejection, perform a fit, enable rejection, and then re-fit. " ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [] } ], "metadata": { "interpreter": { "hash": "856ce4155d48fece3484fc0f3f6d1f121da671faab2c5ff3597623db0d26d01d" }, "kernelspec": { "display_name": "Python 3.9.7 64-bit ('specreduce': conda)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.3" }, "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 } astropy-specreduce-05be828/pyproject.toml000066400000000000000000000060621510537250300206130ustar00rootroot00000000000000[project] name = "specreduce" dynamic = ["version"] authors = [ { name = "Astropy Specreduce contributors", email = "astropy-dev@googlegroups.com" } ] license = {file = "licenses/LICENSE.rst"} description = "Astropy coordinated package for Spectroscopic Reductions" readme = "README.rst" requires-python = ">=3.11" dependencies = [ "numpy>=1.24", "astropy>=5.3", "scipy>=1.10", "specutils>=1.9.1", "matplotlib>=3.10", "gwcs", ] [project.optional-dependencies] test = [ "pytest-astropy", "photutils>=1.0", "tox", ] docs = [ "sphinx-astropy", "photutils>=1.0", "synphot", "nbsphinx", "ipykernel" ] all = [ "photutils>=1.0", "synphot", ] [project.urls] Homepage = "http://astropy.org/" Repository = "https://github.com/astropy/specreduce.git" Documentation = "https://specreduce.readthedocs.io/" [tool.setuptools] include-package-data = true [tool.setuptools.packages] find = {} # Scanning implicit namespaces is active by default [tool.setuptools.package-data] "specreduce.tests" = ["data/*.fits"] [tool.setuptools_scm] version_file = "specreduce/version.py" [build-system] requires = ["setuptools", "setuptools_scm", ] build-backend = 'setuptools.build_meta' [tool.black] line-length = 100 target-version = ['py311', 'py312', 'py313'] [tool.pytest.ini_options] minversion = 7.0 testpaths = [ "specreduce", "docs", ] astropy_header = true doctest_plus = "enabled" text_file_format = "rst" addopts = [ "--color=yes", "--doctest-rst", ] xfail_strict = true filterwarnings = [ "error", "ignore:numpy\\.ufunc size changed:RuntimeWarning", "ignore:numpy\\.ndarray size changed:RuntimeWarning", "ignore:Can\\'t import specreduce_data package", "ignore:.*unclosed self.image.shape[self.crossdisp_axis]: warnings.warn( "background window extends beyond image boundaries " + f"({windows_max} >= {self.image.shape[self.crossdisp_axis]})" ) if windows_min < 0: warnings.warn( "background window extends beyond image boundaries " + f"({windows_min} < 0)" ) # pass trace.trace.data to ignore any mask on the trace bkg_wimage += _ap_weight_image( trace, self.width, self.disp_axis, self.crossdisp_axis, self.image.shape ) if np.any(bkg_wimage > 1): raise ValueError("background regions overlapped") if np.any(np.sum(bkg_wimage, axis=self.crossdisp_axis) == 0): raise ValueError( "background window does not remain in bounds across entire dispersion axis" ) # noqa # check if image contained within background window is fully-nonfinite and raise an error if np.all(img.mask[bkg_wimage > 0]): raise ValueError( "Image is fully masked within background window determined by `width`." ) # noqa if self.statistic == "median": # make it clear in the expose image that partial pixels are fully-weighted bkg_wimage[bkg_wimage > 0] = 1 self.bkg_wimage = bkg_wimage if self.statistic == "average": self._bkg_array = np.ma.average(img, weights=self.bkg_wimage, axis=self.crossdisp_axis) elif self.statistic == "median": # combine where background weight image is 0 with image masked (which already # accounts for non-finite data that wasn't already masked) img.mask = np.logical_or(self.bkg_wimage == 0, self.image.mask) self._bkg_array = np.ma.median(img, axis=self.crossdisp_axis) else: raise ValueError("statistic must be 'average' or 'median'") def _set_traces(self): """Determine `traces` from input. If an integer/float or list if int/float is passed in, use these to construct FlatTrace objects. These values must be positive. If None (which is initialized to an empty list), construct a FlatTrace using the center of image (according to disp. axis). Otherwise, any Trace object or list of Trace objects can be passed in.""" if self.traces == []: # assume a flat trace at the image center if nothing is passed in. trace_pos = self.image.shape[self.disp_axis] / 2.0 self.traces = [FlatTrace(self.image, trace_pos)] if isinstance(self.traces, Trace): # if just one trace, turn it into iterable. self.traces = [self.traces] return # finally, if float/int is passed in convert to FlatTrace(s) if isinstance(self.traces, (float, int)): # for a single number self.traces = [self.traces] if np.all([isinstance(x, (float, int)) for x in self.traces]): self.traces = [FlatTrace(self.image, trace_pos) for trace_pos in self.traces] return else: if not np.all([isinstance(x, Trace) for x in self.traces]): raise ValueError( "`traces` must be a `Trace` object or list of " "`Trace` objects, a number or list of numbers to " "define FlatTraces, or None to use a FlatTrace in " "the middle of the image." ) @classmethod def two_sided(cls, image, trace_object, separation, **kwargs): """ Determine the background from an image for subtraction centered around an input trace. Example: :: trace = FitTrace(image, guess=trace_pos) bg = Background.two_sided(image, trace, bkg_sep, width=bkg_width) Parameters ---------- image : `~astropy.nddata.NDData`-like or array-like Image with 2-D spectral image data. Assumes cross-dispersion (spatial) direction is axis 0 and dispersion (wavelength) direction is axis 1. trace_object: `~specreduce.tracing.Trace` estimated trace of the spectrum to center the background traces separation: float separation from ``trace_object`` for the background regions width : float width of each background aperture in pixels statistic: string statistic to use when computing the background. 'average' will account for partial pixel weights, 'median' will include all partial pixels. disp_axis : int dispersion axis crossdisp_axis : int cross-dispersion axis mask_treatment : string The method for handling masked or non-finite data. Choice of ``filter``, ``omit`, or ``zero_fill``. If `filter` is chosen, masked/non-finite data will be filtered during the fit to each bin/column (along disp. axis) to find the peak. If ``omit`` is chosen, columns along disp_axis with any masked/non-finite data values will be fully masked (i.e, 2D mask is collapsed to 1D and applied). If ``zero_fill`` is chosen, masked/non-finite data will be replaced with 0.0 in the input image, and the mask will then be dropped. For all three options, the input mask (optional on input NDData object) will be combined with a mask generated from any non-finite values in the image data. """ image = _ImageParser._get_data_from_image(image) if image is not None else cls.image kwargs["traces"] = [trace_object - separation, trace_object + separation] return cls(image=image, **kwargs) @classmethod def one_sided(cls, image, trace_object, separation, **kwargs): """ Determine the background from an image for subtraction above or below an input trace. Example: :: trace = FitTrace(image, guess=trace_pos) bg = Background.one_sided(image, trace, bkg_sep, width=bkg_width) Parameters ---------- image : `~astropy.nddata.NDData`-like or array-like Image with 2-D spectral image data. Assumes cross-dispersion (spatial) direction is axis 0 and dispersion (wavelength) direction is axis 1. trace_object: `~specreduce.tracing.Trace` estimated trace of the spectrum to center the background traces separation: float separation from ``trace_object`` for the background, positive will be above the trace, negative below. width : float width of each background aperture in pixels statistic: string statistic to use when computing the background. 'average' will account for partial pixel weights, 'median' will include all partial pixels. disp_axis : int dispersion axis crossdisp_axis : int cross-dispersion axis mask_treatment : string The method for handling masked or non-finite data. Choice of ``filter``, ``omit``, or ``zero_fill``. If `filter` is chosen, masked/non-finite data will be filtered during the fit to each bin/column (along disp. axis) to find the peak. If ``omit`` is chosen, columns along disp_axis with any masked/non-finite data values will be fully masked (i.e, 2D mask is collapsed to 1D and applied). If ``zero_fill`` is chosen, masked/non-finite data will be replaced with 0.0 in the input image, and the mask will then be dropped. For all three options, the input mask (optional on input NDData object) will be combined with a mask generated from any non-finite values in the image data. """ image = _ImageParser._get_data_from_image(image) if image is not None else cls.image kwargs["traces"] = [trace_object + separation] return cls(image=image, **kwargs) def bkg_image(self, image=None): """ Expose the background tiled to the dimension of ``image``. Parameters ---------- image : `~astropy.nddata.NDData`-like or array-like, optional Image with 2-D spectral image data. Assumes cross-dispersion (spatial) direction is axis 0 and dispersion (wavelength) direction is axis 1. If None, will extract the background from ``image`` used to initialize the class. [default: None] Returns ------- spec : `~specutils.Spectrum1D` Spectrum object with same shape as ``image``. """ image = self._parse_image(image) arr = np.tile(self._bkg_array, (image.shape[0], 1)) if SPECUTILS_LT_2: kwargs = {} else: kwargs = {"spectral_axis_index": arr.ndim - 1} return Spectrum( arr * image.unit, spectral_axis=image.spectral_axis, **kwargs ) def bkg_spectrum(self, image=None, bkg_statistic=None): """ Expose the 1D spectrum of the background. Parameters ---------- image : `~astropy.nddata.NDData`-like or array-like, optional Image with 2-D spectral image data. Assumes cross-dispersion (spatial) direction is axis 0 and dispersion (wavelength) direction is axis 1. If None, will extract the background from ``image`` used to initialize the class. [default: None] Returns ------- spec : `~specutils.Spectrum1D` The background 1-D spectrum, with flux expressed in the same units as the input image (or DN if none were provided). """ if bkg_statistic is not None: warnings.warn("'bkg_statistic' is deprecated and will be removed in a future release. " "Please use the 'statistic' argument in the Background initializer instead.", # noqa DeprecationWarning,) return Spectrum(self._bkg_array * self.image.unit, self.image.spectral_axis) def sub_image(self, image=None): """ Subtract the computed background from ``image``. Parameters ---------- image : nddata-compatible image or None image with 2-D spectral image data. If None, will extract the background from ``image`` used to initialize the class. Returns ------- spec : `~specutils.Spectrum1D` Spectrum object with same shape as ``image``. """ image = self._parse_image(image) if not SPECUTILS_LT_2: return image - self.bkg_image(image) # a compare_wcs argument is needed for Spectrum.subtract() in order to # avoid a TypeError from SpectralCoord when image's spectral axis is in # pixels. it is not needed when image's spectral axis has physical units kwargs = {"compare_wcs": None} if image.spectral_axis.unit == u.pix else {} # https://docs.astropy.org/en/stable/nddata/mixins/ndarithmetic.html return image.subtract(self.bkg_image(image), **kwargs) def sub_spectrum(self, image=None): """ Expose the 1D spectrum of the background-subtracted image. Parameters ---------- image : nddata-compatible image or None image with 2-D spectral image data. If None, will extract the background from ``image`` used to initialize the class. Returns ------- spec : `~specutils.Spectrum1D` The background 1-D spectrum, with flux expressed in the same units as the input image (or u.DN if none were provided) and the spectral axis expressed in pixel units. """ sub_image = self.sub_image(image=image) try: return sub_image.collapse(np.nansum, axis=self.crossdisp_axis) except u.UnitTypeError: # can't collapse with a spectral axis in pixels because # SpectralCoord only allows frequency/wavelength equivalent units... ext1d = np.nansum(sub_image.flux, axis=self.crossdisp_axis) return Spectrum(ext1d, spectral_axis=sub_image.spectral_axis) def __rsub__(self, image): """ Subtract the background from an image. """ return self.sub_image(image) astropy-specreduce-05be828/specreduce/calibration_data.py000066400000000000000000000402561510537250300236560ustar00rootroot00000000000000""" Utilities for defining, loading, and handling spectroscopic calibration data """ import warnings from pathlib import Path from typing import Sequence, Literal from urllib.error import URLError from astropy import units as u from astropy.table import Table, vstack, QTable from astropy.utils.data import download_file from astropy.utils.exceptions import AstropyUserWarning from astropy.coordinates import SpectralCoord from specutils.utils.wcs_utils import vac_to_air from specreduce.compat import Spectrum __all__ = [ 'get_available_line_catalogs', 'load_pypeit_calibration_lines', 'load_MAST_calspec', 'load_onedstds', 'AtmosphericExtinction', 'AtmosphericTransmission' ] SUPPORTED_EXTINCTION_MODELS = [ "kpno", "ctio", "apo", "lapalma", "mko", "mtham", "paranal" ] SPECPHOT_DATASETS = [ "bstdscal", "ctiocal", "ctionewcal", "eso", "gemini", "iidscal", "irscal", "oke1990", "redcal", "snfactory", "spec16cal", "spec50cal", "spechayescal" ] PYPEIT_CALIBRATION_LINELISTS = [ 'Ne_IR_MOSFIRE', 'ArII', 'CdI', 'OH_MOSFIRE_H', 'OH_triplespec', 'Ar_IR_MOSFIRE', 'OH_GNIRS', 'ThAr_XSHOOTER_VIS', 'ThAr_MagE', 'HgI', 'NeI', 'XeI', 'OH_MODS', 'ZnI', 'OH_GMOS', 'CuI', 'ThAr_XSHOOTER_VIS_air', 'ThAr_XSHOOTER_UVB', 'OH_NIRES', 'HeI', 'FeI', 'OH_MOSFIRE_J', 'KrI', 'Cd_DeVeny1200', 'Ar_IR_GNIRS', 'OH_MOSFIRE_Y', 'ThAr', 'FeII', 'OH_XSHOOTER', 'OH_FIRE_Echelle', 'OH_MOSFIRE_K', 'OH_R24000', 'Hg_DeVeny1200', 'ArI' ] SPECREDUCE_DATA_URL = ("https://raw.githubusercontent.com/astropy/specreduce-data/" "main/specreduce_data/reference_data/") PYPEIT_DATA_URL = ("https://raw.githubusercontent.com/pypeit/" "pypeit/release/pypeit/data/") def get_available_line_catalogs() -> dict: """ Returns a dictionary of available line catalogs. Currently only ``pypeit`` catalogs are fully supported. """ return { 'pypeit': PYPEIT_CALIBRATION_LINELISTS } def load_pypeit_calibration_lines( lamps: Sequence | None = None, wave_air: bool = False, cache: bool | Literal['update'] = True, show_progress: bool = False ) -> QTable | None: """ Load reference calibration lines from ``pypeit`` linelists. The ``pypeit`` linelists are well-curated and have been tested across a wide range of spectrographs. The available linelists are defined by ``PYPEIT_CALIBRATION_LINELISTS``. Parameters ---------- lamps : Lamp string, comma-separated list of lamps, or sequence of lamps to include in output reference linelist. The parlance of "lamp" is retained here for consistency with its use in ``pypeit`` and elsewhere. In several of the supported cases the "lamp" is the sky itself (e.g. OH lines in the near-IR). The available lamps are defined by ``PYPEIT_CALIBRATION_LINELISTS``. wave_air : If True, convert the vacuum wavelengths used by ``pypeit`` to air wavelengths. cache : Toggle caching of downloaded data show_progress : Show download progress bar Returns ------- linelist: Table containing the combined calibration line list. ``pypeit`` linelists have the following columns: * ``ion``: Ion or molecule generating the line. * ``wavelength``: Vacuum wavelength of the line in Angstroms. * ``NIST``: Flag denoting if NIST is the ultimate reference for the line's wavelength. * ``Instr``: ``pypeit``-specific instrument flag. * ``amplitude``: Amplitude of the line. Beware, not consistent between lists. * ``Source``: Source of the line information. """ if lamps is None: return None if not isinstance(lamps, Sequence): raise ValueError(f"Invalid calibration lamps specification: {lamps}") if isinstance(lamps, str): if ',' in lamps: lamps = [lamp.strip() for lamp in lamps.split(',')] else: lamps = [lamps] linelists = [] for lamp in lamps: if lamp in PYPEIT_CALIBRATION_LINELISTS: data_url = f"{PYPEIT_DATA_URL}/arc_lines/lists/{lamp}_lines.dat" try: data_path = download_file(data_url, cache=cache, show_progress=show_progress, pkgname='specreduce') linelists.append(Table.read(data_path, format='ascii.fixed_width', comment='#')) except URLError as e: warnings.warn(f"Downloading of {data_url} failed: {e}", AstropyUserWarning) else: warnings.warn( f"{lamp} not in the list of supported calibration " f"line lists: {PYPEIT_CALIBRATION_LINELISTS}." ) if len(linelists) == 0: warnings.warn(f"No calibration lines loaded from {lamps}.") linelist = None else: linelist = QTable(vstack(linelists)) linelist.rename_column('wave', 'wavelength') # pypeit linelists use vacuum wavelengths in angstroms linelist['wavelength'] *= u.Angstrom if wave_air: linelist['wavelength'] = vac_to_air(linelist['wavelength']) return linelist def load_MAST_calspec( filename: str | Path, cache: bool | Literal['update'] = True, show_progress: bool = False ) -> Spectrum | None: """ Load a standard star spectrum from the ``calspec`` database at MAST. These spectra are provided in FITS format and are described in detail at: https://www.stsci.edu/hst/instrumentation/reference-data-for-calibration-and-tools/astronomical-catalogs/calspec If ``remote`` is True, the spectrum will be downloaded from MAST. Set ``remote`` to False to load a local file. .. note:: This function requires ``synphot`` to be installed separately. Parameters ---------- filename : FITS filename of a standard star spectrum, e.g. g191b2b_005.fits. If this is a local file, it will be loaded. If not, then a download from MAST will be attempted. cache : Toggle whether downloaded data is cached or not. show_progress : Toggle whether download progress bar is shown. Returns ------- spectrum : If the spectrum can be loaded, return it as a `~specutils.Spectrum`. Otherwise return None. The spectral_axis units are Å and the flux units are milli-Janskys. """ filename = Path(filename) if filename.exists() and filename.is_file(): file_path = filename else: try: data_url = f"https://archive.stsci.edu/hlsps/reference-atlases/cdbs/calspec/{filename}" file_path = download_file(data_url, cache=cache, show_progress=show_progress, pkgname='specreduce') except URLError as e: warnings.warn(f"Downloading of {filename} failed: {e}", AstropyUserWarning) file_path = None if file_path is None: return None else: import synphot _, wave, flux = synphot.specio.read_fits_spec(file_path) # DEV: pllim does not think this is necessary at all but whatever. # the calspec data stores flux in synphot's FLAM units. convert to flux units # supported directly by astropy.units. mJy is chosen since it's the JWST # standard and can easily be converted to/from AB magnitudes. flux_mjy = synphot.units.convert_flux(wave, flux, u.mJy) spectrum = Spectrum(spectral_axis=wave, flux=flux_mjy) return spectrum def load_onedstds( dataset: str = "snfactory", specfile: str = "EG131.dat", cache: bool | Literal['update'] = True, show_progress: bool = False ) -> Spectrum | None: """ This is a convenience function for loading a standard star spectrum from the 'onedstds' dataset in the ``specreduce_data`` package. They will be downloaded from the repository on GitHub and cached by default. Parameters ---------- dataset : Standard star spectrum database. Valid options are described in :ref:`specphot_standards`. specfile : Filename of the standard star spectrum. cache : Enable caching of downloaded data. show_progress : Show download progress bar if data is downloaded. Returns ------- spectrum : If the spectrum can be loaded, return it as a `~specutils.Spectrum`. Otherwise return None. The spectral_axis units are Å and the flux units are milli-Janskys. """ if dataset not in SPECPHOT_DATASETS: msg = (f"Specfied dataset, {dataset}, not in list of supported datasets of " f"spectrophotometric standard stars: f{SPECPHOT_DATASETS}") warnings.warn(msg, AstropyUserWarning) return None try: data_path = download_file(f"{SPECREDUCE_DATA_URL}/onedstds/{dataset}/{specfile}", cache=cache, show_progress=show_progress, pkgname="specreduce") t = Table.read(data_path, format="ascii", names=['wavelength', 'ABmag', 'binsize']) except URLError as e: msg = f"Can't load {specfile} from {dataset}: {e}." warnings.warn(msg, AstropyUserWarning) return None # the specreduce_data standard star spectra all provide wavelengths in angstroms spectral_axis = t['wavelength'].data * u.angstrom # the specreduce_data standard star spectra all provide fluxes in AB mag flux = t['ABmag'].data * u.ABmag flux = flux.to(u.mJy) # convert to linear flux units spectrum = Spectrum(spectral_axis=spectral_axis, flux=flux) return spectrum class AtmosphericExtinction(Spectrum): """ Spectrum container for atmospheric extinction in magnitudes as a function of wavelength. If extinction and spectral_axis are provided, this will use them to build a custom model. If they are not, the 'model' parameter will be used to lookup and load a pre-defined atmospheric extinction model from the ``specreduce_data`` package. Parameters ---------- model : str Name of atmospheric extinction model provided by ``specreduce_data``. Valid options are: * kpno - Kitt Peak National Observatory (default) * ctio - Cerro Tololo International Observatory * apo - Apache Point Observatory * lapalma - Roque de los Muchachos Observatory, La Palma, Canary Islands * mko - Mauna Kea Observatories * mtham - Lick Observatory, Mt. Hamilton station * paranal - European Southern Observatory, Cerro Paranal station extinction : float, `~astropy.units.Quantity`, or `None`, optional Provides extinction data for this spectrum. Used along with spectral_axis to build custom atmospheric extinction model. If no units are provided, assumed to be given in magnitudes. spectral_axis : `~astropy.coordinates.SpectralCoord`, `~astropy.units.Quantity`, or `None`, optional Dispersion information with the same shape as the last (or only) dimension of flux, or one greater than the last dimension of flux if specifying bin edges. Used along with flux to build custom atmospheric extinction model. Attributes ---------- extinction_mag : `~astropy.units.Quantity` Extinction expressed in dimensionless magnitudes transmission : `~astropy.units.Quantity` Extinction expressed as fractional transmission """ # noqa: E501 def __init__( self, model: str = "kpno", extinction: Sequence[float] | u.Quantity | None = None, spectral_axis: SpectralCoord | u.Quantity | None = None, cache: bool | Literal['update'] = True, show_progress: bool = False, **kwargs: str ) -> None: if extinction is not None: if not isinstance(extinction, u.Quantity): warnings.warn( "Input extinction is not a Quanitity. Assuming it is given in magnitudes...", AstropyUserWarning ) extinction = u.Magnitude( extinction, u.MagUnit(u.dimensionless_unscaled) ).to(u.dimensionless_unscaled) # Spectrum wants this to be linear elif isinstance(extinction, (u.LogUnit, u.Magnitude)) or extinction.unit == u.mag: # if in log or magnitudes, recast into Magnitude with dimensionless physical units extinction = u.Magnitude( extinction.value, u.MagUnit(u.dimensionless_unscaled) ).to(u.dimensionless_unscaled) elif extinction.unit != u.dimensionless_unscaled: # if we're given something linear that's not dimensionless_unscaled, # it's an error msg = "Input extinction must have unscaled dimensionless units." raise ValueError(msg) if extinction is None and spectral_axis is None: if model not in SUPPORTED_EXTINCTION_MODELS: msg = ( f"Requested extinction model, {model}, not in list " f"of available models: {SUPPORTED_EXTINCTION_MODELS}" ) raise ValueError(msg) data_file = download_file(f"{SPECREDUCE_DATA_URL}/extinction/{model}extinct.dat", cache=cache, show_progress=show_progress, pkgname='specreduce') t = Table.read(data_file, format="ascii", names=['wavelength', 'extinction']) # the specreduce_data models all provide wavelengths in angstroms spectral_axis = t['wavelength'].data * u.angstrom # the specreduce_data models all provide extinction in magnitudes at an airmass of 1 extinction = u.Magnitude( t['extinction'].data, u.MagUnit(u.dimensionless_unscaled) ).to(u.dimensionless_unscaled) if spectral_axis is None: msg = "Missing spectral axis for input extinction data." raise ValueError(msg) super(AtmosphericExtinction, self).__init__( flux=extinction, spectral_axis=spectral_axis, unit=u.dimensionless_unscaled, **kwargs ) @property def extinction_mag(self) -> u.Quantity: """ This property returns the extinction in magnitudes """ return self.flux.to(u.mag(u.dimensionless_unscaled)) @property def transmission(self) -> u.Quantity: """ This property returns the transmission as a fraction between 0 and 1 """ return self.flux class AtmosphericTransmission(AtmosphericExtinction): """ Spectrum container for atmospheric transmission as a function of wavelength. Parameters ---------- data_file : Name to file containing atmospheric transmission data. Data is assumed to have two columns, wavelength and transmission (unscaled dimensionless). If this isn't provided, a model is built from a pre-calculated table of values from 0.9 to 5.6 microns. The values were generated by the ATRAN model, https://ntrs.nasa.gov/citations/19930010877 (Lord, S. D., 1992, NASA Technical Memorandum 103957). The extinction is given as a linear transmission fraction at an airmass of 1 and 1 mm of precipitable water. wave_unit : Units for spectral axis. """ def __init__( self, data_file: str | Path | None = None, wave_unit: u.Unit = u.um, **kwargs: str ) -> None: if data_file is None: data_file = download_file(f"{SPECREDUCE_DATA_URL}/extinction/atm_trans_am1.0.dat") t = Table.read(data_file, format="ascii", names=['wavelength', 'extinction']) # spectral axis is given in microns spectral_axis = t['wavelength'].data * wave_unit # extinction is given in a dimensionless transmission fraction extinction = t['extinction'].data * u.dimensionless_unscaled super(AtmosphericTransmission, self).__init__( extinction=extinction, spectral_axis=spectral_axis, **kwargs ) astropy-specreduce-05be828/specreduce/compat.py000066400000000000000000000004011510537250300216450ustar00rootroot00000000000000import specutils from astropy.utils import minversion __all__ = ["Spectrum"] SPECUTILS_LT_2 = not minversion(specutils, "2.0.dev") if SPECUTILS_LT_2: from specutils import Spectrum1D as Spectrum else: from specutils import Spectrum # noqa: F401 astropy-specreduce-05be828/specreduce/conftest.py000066400000000000000000000104431510537250300222160ustar00rootroot00000000000000# This file is used to configure the behavior of pytest import numpy as np import pytest from astropy import units as u from astropy.io import fits from astropy.nddata import CCDData, NDData, VarianceUncertainty from astropy.utils.data import get_pkg_data_filename from specutils import SpectralAxis from specreduce.compat import SPECUTILS_LT_2, Spectrum try: from pytest_astropy_header.display import PYTEST_HEADER_MODULES, TESTED_VERSIONS ASTROPY_HEADER = True except ImportError: ASTROPY_HEADER = False # Test image is comprised of 30 rows with 10 columns each. Row content # is row index itself. This makes it easy to predict what should be the # value extracted from a region centered at any arbitrary Y position. def _mk_test_data(imgtype, nrows=30, ncols=10): image_ones = np.ones(shape=(nrows, ncols)) image = image_ones.copy() for j in range(nrows): image[j, ::] *= j if imgtype == "raw": pass # no extra processing elif imgtype == "ccddata": image = CCDData(image, unit=u.Jy) else: # spectrum flux = image * u.DN uncert = VarianceUncertainty(image_ones) if imgtype == "spec_no_axis": if SPECUTILS_LT_2: kwargs = {} else: kwargs = {"spectral_axis_index": image.ndim - 1} image = Spectrum(flux, uncertainty=uncert, **kwargs) else: # "spec" image = Spectrum(flux, spectral_axis=np.arange(ncols) * u.um, uncertainty=uncert) return image @pytest.fixture def mk_test_img_raw(): return _mk_test_data("raw") @pytest.fixture def mk_test_img(): return _mk_test_data("ccddata") @pytest.fixture def mk_test_spec_no_spectral_axis(): return _mk_test_data("spec_no_axis") @pytest.fixture def mk_test_spec_with_spectral_axis(): return _mk_test_data("spec") # Test data file already transposed like this: # fn = download_file('https://stsci.box.com/shared/static/exnkul627fcuhy5akf2gswytud5tazmw.fits', cache=True) # noqa: E501 # img = fits.getdata(fn).T @pytest.fixture def all_images(): np.random.seed(7) filename = get_pkg_data_filename( "data/transposed_det_image_seq5_MIRIMAGE_P750Lexp1_s2d.fits", package="specreduce.tests") img = fits.getdata(filename) flux = img * (u.MJy / u.sr) sax = SpectralAxis(np.linspace(14.377, 3.677, flux.shape[-1]) * u.um) unc = VarianceUncertainty(np.random.rand(*flux.shape)) if SPECUTILS_LT_2: kwargs = {} else: kwargs = {"spectral_axis_index": img.ndim - 1} all_images = {} all_images['arr'] = img all_images['s1d'] = Spectrum(flux, spectral_axis=sax, uncertainty=unc) all_images['s1d_pix'] = Spectrum(flux, uncertainty=unc, **kwargs) all_images['ccd'] = CCDData(img, uncertainty=unc, unit=flux.unit) all_images['ndd'] = NDData(img, uncertainty=unc, unit=flux.unit) all_images['qnt'] = img * flux.unit return all_images @pytest.fixture def spec1d(): np.random.seed(7) flux = np.random.random(50)*u.Jy sa = np.arange(0, 50)*u.pix spec = Spectrum(flux, spectral_axis=sa) return spec @pytest.fixture def spec1d_with_emission_line(): np.random.seed(7) sa = np.arange(0, 200)*u.pix flux = (np.random.randn(200) + 10*np.exp(-0.01*((sa.value-130)**2)) + sa.value/100) * u.Jy spec = Spectrum(flux, spectral_axis=sa) return spec @pytest.fixture def spec1d_with_absorption_line(): np.random.seed(7) sa = np.arange(0, 200)*u.pix flux = (np.random.randn(200) - 10*np.exp(-0.01*((sa.value-130)**2)) + sa.value/100) * u.Jy spec = Spectrum(flux, spectral_axis=sa) return spec def pytest_configure(config): if ASTROPY_HEADER: config.option.astropy_header = True # Customize the following lines to add/remove entries from the list of # packages for which version numbers are displayed when running the tests. PYTEST_HEADER_MODULES.pop('Pandas', None) PYTEST_HEADER_MODULES.pop('h5py', None) PYTEST_HEADER_MODULES['astropy'] = 'astropy' PYTEST_HEADER_MODULES['specutils'] = 'specutils' PYTEST_HEADER_MODULES['photutils'] = 'photutils' PYTEST_HEADER_MODULES['synphot'] = 'synphot' from specreduce import __version__ TESTED_VERSIONS["specreduce"] = __version__ astropy-specreduce-05be828/specreduce/core.py000066400000000000000000000236431510537250300213270ustar00rootroot00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst import inspect from copy import deepcopy from dataclasses import dataclass from typing import Literal import numpy as np from astropy import units as u from astropy.nddata import VarianceUncertainty, NDData from specreduce.compat import SPECUTILS_LT_2, Spectrum __all__ = ["SpecreduceOperation"] MaskingOption = Literal[ "apply", "ignore", "propagate", "zero_fill", "nan_fill", "apply_mask_only", "apply_nan_only" ] ImageLike = np.ndarray | NDData | u.Quantity class _ImageParser: """ Coerces images from accepted formats to Spectrum objects for internal use in specreduce's operation classes. Fills any and all of uncertainty, mask, units, and spectral axis that are missing in the provided image with generic values. Accepted image types are: - `~specutils.Spectrum1D` (preferred) - `~astropy.nddata.ccddata.CCDData` - `~astropy.nddata.ndddata.NDDData` - `~astropy.units.quantity.Quantity` - `~numpy.ndarray` """ # The '_valid_mask_treatment_methods' in the Background, Trace, and Extract # classes is a subset of implemented methods. implemented_mask_treatment_methods = ( "apply", "ignore", "propagate", "zero_fill", "nan_fill", "apply_mask_only", "apply_nan_only", ) def _parse_image( self, image: ImageLike, disp_axis: int = 1, mask_treatment: MaskingOption = "apply" ) -> Spectrum: """ Convert all accepted image types to a consistently formatted Spectrum object. Parameters ---------- image : `~astropy.nddata.NDData`-like or array-like The image to be parsed. If None, defaults to class' own image attribute. disp_axis The index of the image's dispersion axis. Should not be changed until operations can handle variable image orientations. mask_treatment Specifies how to handle masked or non-finite values in the input image. The accepted values are: - ``apply``: The image remains unchanged, and any existing mask is combined\ with a mask derived from non-finite values. - ``ignore``: The image remains unchanged, and any existing mask is dropped. - ``propagate``: The image remains unchanged, and any masked or non-finite pixel\ causes the mask to extend across the entire cross-dispersion axis. - ``zero_fill``: Pixels that are either masked or non-finite are replaced with 0.0,\ and the mask is dropped. - ``nan_fill``: Pixels that are either masked or non-finite are replaced with nan,\ and the mask is dropped. - ``apply_mask_only``: The image and mask are left unmodified. - ``apply_nan_only``: The image is left unmodified, the old mask is dropped, and a\ new mask is created based on non-finite values. Returns ------- Spectrum """ # would be nice to handle (cross)disp_axis consistently across # operations (public attribute? private attribute? argument only?) so # it can be called from self instead of via kwargs... if image is None: # useful for Background's instance methods return self.image return self._get_data_from_image(image, disp_axis=disp_axis, mask_treatment=mask_treatment) @staticmethod def _get_data_from_image( image: ImageLike, disp_axis: int = 1, mask_treatment: MaskingOption = "apply" ) -> Spectrum: """ Extract data array from various input types for `image`. Parameters ---------- image Input image from which data is extracted. This can be a 2D numpy array, Quantity, or an NDData object. disp_axis The dispersion axis of the image. mask_treatment Specifies how to handle masked or non-finite values in the input image. Returns ------- Spectrum """ if isinstance(image, u.quantity.Quantity): img = image.value elif isinstance(image, np.ndarray): img = image else: # NDData, including CCDData and Spectrum img = image.data mask = getattr(image, "mask", None) crossdisp_axis = (disp_axis + 1) % 2 # next, handle masked and non-finite data in image. # A mask will be created from any non-finite image data, and combined # with any additional 'mask' passed in. If image is being parsed within # a specreduce operation that has 'mask_treatment' options, this will be # handled as well. Note that input data may be modified if a fill value # is chosen to handle masked data. The returned image will always have # `image.mask` even if there are no non-finite or masked values. img, mask = _ImageParser._mask_and_nonfinite_data_handling( image=img, mask=mask, mask_treatment=mask_treatment, crossdisp_axis=crossdisp_axis ) # mask (handled above) and uncertainty are set as None when they aren't # specified upon creating a Spectrum object, so we must check whether # these attributes are absent *and* whether they are present but set as None if hasattr(image, "uncertainty"): uncertainty = image.uncertainty else: uncertainty = VarianceUncertainty(np.ones(img.shape)) unit = getattr(image, "unit", u.Unit("DN")) spectral_axis = getattr(image, "spectral_axis", np.arange(img.shape[disp_axis]) * u.pix) if SPECUTILS_LT_2: kwargs = {} else: kwargs = {"spectral_axis_index": img.ndim - 1} img = Spectrum( img * unit, spectral_axis=spectral_axis, uncertainty=uncertainty, mask=mask, **kwargs ) return img @staticmethod def _mask_and_nonfinite_data_handling( image: ImageLike, mask: ImageLike | None = None, mask_treatment: str = "apply", crossdisp_axis: int = 1, ) -> tuple[np.ndarray, np.ndarray]: """ Handle the treatment of masked and non-finite data. All operations in Specreduce can take in a mask for the data as part of the input NDData. There are five options currently implemented for the treatment of masked and non-finite data - apply, ignore, zero_fill, nan_fill, apply_mask_only, and apply_nan_only. Depending on the routine, all or a subset of these three options are valid. Parameters ---------- image : array-like The input image data array that may contain non-finite values. mask : array-like of bool or None An optional Boolean mask array. Non-finite values in the image will be added to this mask. mask_treatment Specifies how to handle masked or non-finite values in the input image. """ if mask_treatment not in _ImageParser.implemented_mask_treatment_methods: raise ValueError( "'mask_treatment' must be one of " f"{_ImageParser.implemented_mask_treatment_methods}" ) if mask is not None and (mask.dtype not in (bool, int)): raise ValueError("'mask' must be a boolean or integer array.") match mask_treatment: case "apply": mask = mask | (~np.isfinite(image)) if mask is not None else ~np.isfinite(image) case "ignore": mask = np.zeros(image.shape, dtype=bool) case "propagate": if mask is None: mask = ~np.isfinite(image) else: mask = mask | (~np.isfinite(image)) mask[:] = mask.any(axis=crossdisp_axis, keepdims=True) case "zero_fill" | "nan_fill": mask = mask | (~np.isfinite(image)) if mask is not None else ~np.isfinite(image) image = deepcopy(image) if mask_treatment == "zero_fill": image[mask] = 0.0 else: image[mask] = np.nan mask[:] = False case "apply_nan_only": mask = ~np.isfinite(image) case "apply_mask_only": mask = mask.copy() if mask is not None else np.zeros(image.shape, dtype=bool) if mask.all(): raise ValueError("Image is fully masked. Check for invalid values.") return image, mask @dataclass class SpecreduceOperation(_ImageParser): """ An operation to perform as part of a spectroscopic reduction pipeline. This class primarily exists to define the basic API for operations: parameters for the operation are provided at object creation, and then the operation object is called with the data objects required for the operation, which then *return* the data objects resulting from the operation. """ def __call__(self): raise NotImplementedError("__call__ on a SpecreduceOperation needs to " "be overridden") @classmethod def as_function(cls, *args, **kwargs): """ Run this operation as a function. Syntactic sugar for e.g., ``Operation.as_function(arg1, arg2, keyword=value)`` maps to ``Operation(arg2, keyword=value)(arg1)`` (if the ``__call__`` of ``Operation`` has only one argument) """ argspec = inspect.getargs(cls.__call__.__code__) if argspec.varargs: raise NotImplementedError( "There is not a way to determine the " "number of inputs of a *args style " "operation" ) ninputs = len(argspec.args) - 1 callargs = args[:ninputs] noncallargs = args[ninputs:] op = cls(*noncallargs, **kwargs) return op(*callargs) astropy-specreduce-05be828/specreduce/extract.py000066400000000000000000001004711510537250300220440ustar00rootroot00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst import warnings from dataclasses import dataclass, field import numpy as np from astropy import units as u from astropy.modeling import Model, models, fitting from astropy.nddata import NDData, VarianceUncertainty from numpy import ndarray from scipy.integrate import trapezoid from scipy.interpolate import RectBivariateSpline from specreduce.compat import Spectrum from specreduce.core import SpecreduceOperation, ImageLike, MaskingOption from specreduce.tracing import Trace, FlatTrace __all__ = ["BoxcarExtract", "HorneExtract", "OptimalExtract"] def _get_boxcar_weights(center, hwidth, npix): """ Compute weights given an aperture center, half width, and number of pixels. Based on `get_boxcar_weights()` from a JDAT Notebook by Karl Gordon: https://github.com/spacetelescope/jdat_notebooks/blob/main/notebooks/MIRI_LRS_spectral_extraction/miri_lrs_spectral_extraction.ipynb Parameters ---------- center : float, required The index of the aperture's center pixel on the larger image's cross-dispersion axis. hwidth : float, required Half of the aperture's width in the cross-dispersion direction. npix : float, required The number of pixels in the larger image's cross-dispersion axis. Returns ------- weights : `~numpy.ndarray` A 2D image with weights assigned to pixels that fall within the defined aperture. """ weights = np.zeros((npix)) if hwidth == 0: # the logic below would return all zeros anyways, so might as well save the time # (negative widths should be avoided by earlier logic!) return weights if center - hwidth > npix - 0.5 or center + hwidth < -0.5: # entire window is out-of-bounds return weights lower_edge = max(-0.5, center - hwidth) # where -0.5 is lower bound of the image upper_edge = min(center + hwidth, npix - 0.5) # where npix-0.5 is upper bound of the image # let's avoid recomputing the round repeatedly int_round_lower_edge = int(round(lower_edge)) int_round_upper_edge = int(round(upper_edge)) # inner pixels that get full weight # the round in conjunction with the +1 handles the half-pixel "offset", # the upper bound doesn't have the +1 because array slicing is inclusive on the lower index and # exclusive on the upper-index # NOTE: round(-0.5) == 0, which is helpful here for the case where lower_edge == -0.5 weights[int_round_lower_edge + 1 : int_round_upper_edge] = 1 # handle edge pixels (for cases where an edge pixel is fully-weighted, this will set it again, # but should still compute a weight of 1. By using N:N+1, we avoid index errors if the edge # is outside the image bounds. But we do need to avoid negative indices which would count # from the end of the array. if int_round_lower_edge >= 0: weights[int_round_lower_edge : int_round_lower_edge + 1] = ( round(lower_edge) + 0.5 - lower_edge ) weights[int_round_upper_edge : int_round_upper_edge + 1] = upper_edge - ( round(upper_edge) - 0.5 ) return weights def _ap_weight_image(trace, width, disp_axis, crossdisp_axis, image_shape): """ Create a weight image that defines the desired extraction aperture. Based on `ap_weight_images()` from a JDAT Notebook by Karl Gordon: https://github.com/spacetelescope/jdat_notebooks/blob/main/notebooks/MIRI_LRS_spectral_extraction/miri_lrs_spectral_extraction.ipynb Parameters ---------- trace : `~specreduce.tracing.Trace`, required trace object width : float, required width of extraction aperture in pixels disp_axis : int, required dispersion axis crossdisp_axis : int, required cross-dispersion axis image_shape : tuple with 2 elements, required size (shape) of image Returns ------- wimage : `~numpy.ndarray` a 2D weight image defining the aperture """ wimage = np.zeros(image_shape) hwidth = 0.5 * width image_sizes = image_shape[crossdisp_axis] # loop in dispersion direction and compute weights. for i in range(image_shape[disp_axis]): # TODO trace must handle transposed data (disp_axis == 0) # pass trace.trace.data[i] to avoid any mask if part of the regions is out-of-bounds # ArrayTrace can have nonfinite or masked data in trace, and this will fail, # so figure out how to handle that... wimage[:, i] = _get_boxcar_weights(trace.trace.data[i], hwidth, image_sizes) return wimage @dataclass class BoxcarExtract(SpecreduceOperation): """ Standard boxcar extraction along a trace. Example: :: trace = FlatTrace(image, trace_pos) extract = BoxcarExtract(image, trace) spectrum = extract(width=width) Parameters ---------- image image with 2-D spectral image data trace_object trace object width width of extraction aperture in pixels disp_axis dispersion axis crossdisp_axis cross-dispersion axis mask_treatment Specifies how to handle masked or non-finite values in the input image. The accepted values are: - ``apply``: The image remains unchanged, and any existing mask is combined\ with a mask derived from non-finite values. - ``ignore``: The image remains unchanged, and any existing mask is dropped. - ``propagate``: The image remains unchanged, and any masked or non-finite pixel\ causes the mask to extend across the entire cross-dispersion axis. - ``zero_fill``: Pixels that are either masked or non-finite are replaced with 0.0,\ and the mask is dropped. - ``nan_fill``: Pixels that are either masked or non-finite are replaced with nan,\ and the mask is dropped. - ``apply_mask_only``: The image and mask are left unmodified. - ``apply_nan_only``: The image is left unmodified, the old mask is dropped, and a\ new mask is created based on non-finite values. Returns ------- spec : `~specutils.Spectrum1D` The extracted 1d spectrum expressed in DN and pixel units """ image: ImageLike trace_object: Trace width: float = 5 disp_axis: int = 1 crossdisp_axis: int = 0 # TODO: should disp_axis and crossdisp_axis be defined in the Trace object? mask_treatment: MaskingOption = "apply" _valid_mask_treatment_methods = ( "apply", "ignore", "propagate", "zero_fill", "nan_fill", "apply_mask_only", "apply_nan_only", ) @property def spectrum(self): return self.__call__() def __call__( self, image: ImageLike | None = None, trace: Trace | None = None, width: float | None = None, disp_axis: int | None = None, crossdisp_axis: int | None = None, ) -> Spectrum: """ Extract the 1D spectrum using the boxcar method. Parameters ---------- image The image with 2-D spectral image data trace The trace object width The width of extraction aperture in pixels disp_axis The dispersion axis crossdisp_axis The cross-dispersion axis Returns ------- spec The extracted 1d spectrum with flux expressed in the same units as the input image, or u.DN, and pixel units """ image = image if image is not None else self.image trace = trace or self.trace_object width = width or self.width disp_axis = disp_axis or self.disp_axis cdisp_axis = crossdisp_axis or self.crossdisp_axis if width <= 0: raise ValueError("The window width must be positive") self.image = self._parse_image( image, disp_axis=disp_axis, mask_treatment=self.mask_treatment ) # Spectrum extraction # =================== # Assign no weight to non-finite pixels outside the window. Non-finite pixels inside # the window will be propagated to the sum if mask treatment is either ``ignore`` or # ``propagate`` or excluded if the chosen mask treatment option is ``apply``. In the # latter case, the flux is calculated as the average of the non-masked pixels inside # the window multiplied by the window width. window_weights = _ap_weight_image(trace, width, disp_axis, cdisp_axis, self.image.shape) if self.mask_treatment == "apply": image_cleaned = np.where(~self.image.mask, self.image.data * window_weights, 0.0) weights = np.where(~self.image.mask, window_weights, 0.0) spectrum = ( image_cleaned.sum(axis=cdisp_axis) / weights.sum(axis=cdisp_axis) * window_weights.sum(axis=cdisp_axis) ) else: image_windowed = np.where(window_weights, self.image.data * window_weights, 0.0) spectrum = np.sum(image_windowed, axis=cdisp_axis) return Spectrum(spectrum * self.image.unit, spectral_axis=self.image.spectral_axis) @dataclass class HorneExtract(SpecreduceOperation): """ Perform a Horne (a.k.a. optimal) extraction on a two-dimensional spectrum. There are two options for fitting the spatial profile used for extraction - by default, a 1D gaussian is fit and as a uniform profile across the spectrum. Alternativley, the ``self profile`` option may be chosen - when this option is chosen, the spatial profile will be sampled (using a default of 10 sample bins, but can be modified with ``spatial_profile``) and interpolated between to produce a smoothly varying spatial profile across the spectrum. If using the Gaussian option for the spatial profile, a background profile may be fit (but not subtracted) simultaneously to the data. By default, this is done with a 2nd degree polynomial. If using the ``interpolated_profile`` option, the background model must be set to None. Parameters ---------- image : `~astropy.nddata.NDData`-like or array-like, required The input 2D spectrum from which to extract a source. An NDData object must specify uncertainty and a mask. An array requires use of the ``variance``, ``mask``, & ``unit`` arguments. trace_object : `~specreduce.tracing.Trace`, required The associated 1D trace object created for the 2D image. disp_axis : int, optional The index of the image's dispersion axis. [default: 1] crossdisp_axis : int, optional The index of the image's cross-dispersion axis. [default: 0] bkgrd_prof : `~astropy.modeling.Model` or None, optional A model for the image's background flux when using the ``gaussian`` spatial profile. If ``spatial_profile`` is set to ``gaussian``, it defaults to ``models.Polynomial1D(2)``. Note that the ``interpolated_profile`` option does not support a background model, so ``bkgrd_prof`` must be left as ``None``. spatial_profile : str or dict, optional The shape of the object profile. The first option is 'gaussian' to fit a uniform 1D gaussian to the average of pixels in the cross-dispersion direction. The other option is 'interpolated_profile' - when this option is used, the profile is sampled in bins and these samples are interpolated between to construct a continuously varying, empirical spatial profile for extraction. For this option, if passed in as a string (i.e spatial_profile='interpolated_profile') the default values for the number of bins used (10) and degree of interpolation (linear in x and y, by default) will be used. To set these parameters, pass in a dictionary with the keys 'n_bins_interpolated_profile' (which accepts an integer number of bins) and 'interp_degree' (which accepts an int, or tuple of ints for x and y degree, respectively). [default: gaussian] variance : `~numpy.ndarray`, optional (Only used if ``image`` is not an NDData object.) The associated variances for each pixel in the image. Must have the same dimensions as ``image``. If all zeros, the variance will be ignored and treated as all ones. If any zeros, those elements will be excluded via masking. If any negative values, an error will be raised. [default: None] mask : `~numpy.ndarray`, optional (Only used if ``image`` is not an NDData object.) Whether to mask each pixel in the image. Must have the same dimensions as ``image``. If blank, all non-NaN pixels are unmasked. [default: None] unit : `~astropy.units.Unit` or str, optional (Only used if ``image`` is not an NDData object.) The associated unit for the data in ``image``. If blank, fluxes are interpreted in DN. [default: None] """ image: NDData trace_object: Trace bkgrd_prof: None | Model = None spatial_profile: str | dict = "gaussian" variance: np.ndarray = field(default=None) mask: np.ndarray = field(default=None) unit: np.ndarray = field(default=None) disp_axis: int = 1 crossdisp_axis: int = 0 # TODO: should disp_axis and crossdisp_axis be defined in the Trace object? @property def spectrum(self): return self.__call__() def _parse_image(self, image, variance=None, mask=None, unit=None, disp_axis=1): """ Convert all accepted image types to a consistently formatted Spectrum object. HorneExtract needs its own version of this method because it is more stringent in its requirements for input images. The extra arguments are needed to handle cases where these parameters were specified as arguments and those where they came as attributes of the image object. Parameters ---------- image : `~astropy.nddata.NDData`-like or array-like, required The image to be parsed. If None, defaults to class' own image attribute. variance : `~numpy.ndarray`, optional (Only used if ``image`` is not an NDData object.) The associated variances for each pixel in the image. Must have the same dimensions as ``image``. If all zeros, the variance will be ignored and treated as all ones. If any zeros, those elements will be excluded via masking. If any negative values, an error will be raised. mask : `~numpy.ndarray`, optional (Only used if ``image`` is not an NDData object.) Whether to mask each pixel in the image. Must have the same dimensions as ``image``. If blank, all non-NaN pixels are unmasked. unit : `~astropy.units.Unit` or str, optional (Only used if ``image`` is not an NDData object.) The associated unit for the data in ``image``. If blank, fluxes are interpreted in DN. disp_axis : int, optional The index of the image's dispersion axis. Should not be changed until operations can handle variable image orientations. [default: 1] """ if isinstance(image, np.ndarray): img = image elif isinstance(image, u.quantity.Quantity): img = image.value else: # NDData, including CCDData and Spectrum img = image.data # mask is set as None when not specified upon creating a Spectrum # object, so we must check whether it is absent *and* whether it's # present but set as None if getattr(image, "mask", None) is not None: mask = image.mask elif mask is not None: pass else: # if user provides no mask at all, don't mask anywhere mask = np.zeros_like(img) if img.shape != mask.shape: raise ValueError("image and mask shapes must match.") # Process uncertainties, converting to variances when able and throwing # an error when uncertainties are missing or less easily converted if hasattr(image, "uncertainty") and image.uncertainty is not None: if image.uncertainty.uncertainty_type == "var": variance = image.uncertainty.array elif image.uncertainty.uncertainty_type == "std": warnings.warn( "image NDData object's uncertainty " "interpreted as standard deviation. if " "incorrect, use VarianceUncertainty when " "assigning image object's uncertainty." ) variance = image.uncertainty.array**2 elif image.uncertainty.uncertainty_type == "ivar": variance = 1 / image.uncertainty.array else: # other options are InverseUncertainty and UnknownUncertainty raise ValueError( "image NDData object has unexpected " "uncertainty type. instead, try " "VarianceUncertainty or StdDevUncertainty." ) elif hasattr(image, "uncertainty") and image.uncertainty is None: # ignore variance arg to focus on updating NDData object raise ValueError("image NDData object lacks uncertainty") else: if variance is None: raise ValueError( "if image is a numpy or Quantity array, a " "variance must be specified. consider " "wrapping it into one object by instead " "passing an NDData image." ) elif image.shape != variance.shape: raise ValueError("image and variance shapes must match") if np.any(variance < 0): raise ValueError("variance must be fully positive") if np.all(variance == 0): # technically would result in infinities, but since they're all # zeros, we can override ones to simulate an unweighted case variance = np.ones_like(variance) if np.any(variance == 0): # exclude such elements by editing the input mask mask[variance == 0] = True # replace the variances to avoid a divide by zero warning variance[variance == 0] = np.nan variance = VarianceUncertainty(variance) unit = getattr(image, "unit", u.Unit(unit) if unit is not None else u.Unit("DN")) spectral_axis = getattr(image, "spectral_axis", np.arange(img.shape[disp_axis]) * u.pix) return Spectrum(img * unit, spectral_axis=spectral_axis, uncertainty=variance, mask=mask) def _fit_gaussian_spatial_profile( self, img: ndarray, disp_axis: int, crossdisp_axis: int, or_mask: ndarray, bkgrd_prof: Model ): """Fit a 1D Gaussian spatial profile to spectrum in `img`. Fits an 1D Gaussian profile to spectrum in `img`. Takes the weighted mean of ``img`` along the cross-dispersion axis all ignoring masked pixels (i.e, takes the mean of each row for a horizontal trace). A Background model (optional) is fit simultaneously. Returns an `astropy.model.Gaussian1D` (or compound model, if `bkgrd_prof` is supplied) fit to data. """ nrows = img.shape[crossdisp_axis] xd_pixels = np.arange(nrows) # co-add signal in each image row, ignore masked pixels coadd = np.ma.masked_array(img, mask=or_mask).mean(disp_axis) # use the sum of brightest row as an inital guess for Gaussian amplitude, # the the location of the brightest row as an initial guess for the mean gauss_prof = models.Gaussian1D(amplitude=coadd.max(), mean=coadd.argmax(), stddev=2) # Fit extraction kernel (Gaussian + background model) to coadded rows # with combined model (must exclude masked indices manually; # LevMarLSQFitter does not) if bkgrd_prof is not None: ext_prof = gauss_prof + bkgrd_prof else: # add a trivial constant model so attribute names are the same ext_prof = gauss_prof + models.Const1D(0, fixed={"amplitude": True}) with warnings.catch_warnings(): warnings.simplefilter("ignore") fitter = fitting.LMLSQFitter() fit_ext_kernel = fitter(ext_prof, xd_pixels[~coadd.mask], coadd.compressed()) return fit_ext_kernel def _fit_spatial_profile( self, img: ndarray, disp_axis: int, crossdisp_axis: int, mask: ndarray, n_bins: int, kx: int, ky: int, ) -> RectBivariateSpline: """ Fit a spatial profile by sampling the median profile along the dispersion direction. This method extracts the spatial profile from an input spectrum by binning the data along the dispersion axis. It calculates the median profile for each bin, normalizes it, and then interpolates between these profiles to create a smooth 2D representation of the spatial profile. The resulting interpolator object can be used to evaluate the spatial profile at any coordinate within the bounds of the data. Parameters ---------- img The 2D array of spectral data to process. disp_axis The image axis corresponding to the dispersion direction. crossdisp_axis The image axis corresponding to the cross-dispersion direction. mask A boolean mask array with the same shape as the image. Values of ``True`` in the mask indicate invalid data points to be ignored during computation. n_bins The number of bins to use along the dispersion axis for sampling the median spatial profile. kx The degree of the spline along the dispersion axis. ky The degree of the spline along the cross-dispersion axis. Returns ------- RectBivariateSpline Interpolator object that provides a smoothed 2D spatial profile. """ img = np.where(~mask, img, np.nan) nrows = img.shape[crossdisp_axis] ncols = img.shape[disp_axis] samples = np.zeros((n_bins, nrows)) sample_locs = np.linspace(0, ncols - 1, n_bins + 1, dtype=int) bin_centers = [ (sample_locs[i] + sample_locs[i + 1]) // 2 for i in range(len(sample_locs) - 1) ] for i in range(n_bins): bin_median = np.nanmedian(img[:, sample_locs[i] : sample_locs[i + 1]], axis=disp_axis) samples[i, :] = bin_median / bin_median.sum() return RectBivariateSpline(x=bin_centers, y=np.arange(nrows), z=samples, kx=kx, ky=ky) def __call__( self, image=None, trace_object=None, disp_axis=None, crossdisp_axis=None, bkgrd_prof=None, spatial_profile=None, n_bins_interpolated_profile=None, interp_degree_interpolated_profile=None, variance=None, mask=None, unit=None, ): """ Run the Horne calculation on a region of an image and extract a 1D spectrum. Parameters ---------- image : `~astropy.nddata.NDData`-like or array-like, required The input 2D spectrum from which to extract a source. An NDData object must specify uncertainty and a mask. An array requires use of the ``variance``, ``mask``, & ``unit`` arguments. trace_object : `~specreduce.tracing.Trace`, required The associated 1D trace object created for the 2D image. disp_axis : int, optional The index of the image's dispersion axis. crossdisp_axis : int, optional The index of the image's cross-dispersion axis. bkgrd_prof : `~astropy.modeling.Model`, optional A model for the image's background flux when using the ``gaussian`` spatial profile. If ``spatial_profile`` is set to ``gaussian``, it defaults to ``models.Polynomial1D(2)``. Note that the ``interpolated_profile`` option does not support a background model, so ``bkgrd_prof`` must be left as ``None``. spatial_profile : str or dict, optional The shape of the object profile. The first option is 'gaussian' to fit a uniform 1D gaussian to the average of pixels in the cross-dispersion direction. The other option is 'interpolated_profile' - when this option is used, the profile is sampled in bins and these samples are interpolated between to construct a continuously varying, empirical spatial profile for extraction. For this option, if passed in as a string (i.e spatial_profile='interpolated_profile') the default values for the number of bins used (10) and degree of interpolation (linear in x and y, by default) will be used. To set these parameters, pass in a dictionary with the keys 'n_bins_interpolated_profile' (which accepts an integer number of bins) and 'interp_degree' (which accepts an int, or tuple of ints for x and y degree, respectively). [default: gaussian] variance : `~numpy.ndarray`, optional (Only used if ``image`` is not an NDData object.) The associated variances for each pixel in the image. Must have the same dimensions as ``image``. If all zeros, the variance will be ignored and treated as all ones. If any zeros, those elements will be excluded via masking. If any negative values, an error will be raised. mask : `~numpy.ndarray`, optional (Only used if ``image`` is not an NDData object.) Whether to mask each pixel in the image. Must have the same dimensions as ``image``. If blank, all non-NaN pixels are unmasked. unit : `~astropy.units.Unit` or str, optional (Only used if ``image`` is not an NDData object.) The associated unit for the data in ``image``. If blank, fluxes are interpreted in DN. Returns ------- spec_1d : `~specutils.Spectrum1D` The final, Horne extracted 1D spectrum. """ image = image if image is not None else self.image trace_object = trace_object if trace_object is not None else self.trace_object disp_axis = disp_axis if disp_axis is not None else self.disp_axis crossdisp_axis = crossdisp_axis if crossdisp_axis is not None else self.crossdisp_axis bkgrd_prof = bkgrd_prof if bkgrd_prof is not None else self.bkgrd_prof profile = spatial_profile if spatial_profile is not None else self.spatial_profile variance = variance if variance is not None else self.variance mask = mask if mask is not None else self.mask unit = unit if unit is not None else self.unit profile_choices = ("gaussian", "interpolated_profile") if not isinstance(profile, (str, dict)): raise ValueError("spatial_profile must be a string or dictionary.") if isinstance(profile, str): profile = dict(name=profile) profile_type = profile["name"].lower() if profile_type not in profile_choices: raise ValueError("spatial_profile must be one of" f"{', '.join(profile_choices)}") n_bins_interpolated_profile = profile.get("n_bins_interpolated_profile", 10) interp_degree_interpolated_profile = profile.get("interp_degree_interpolated_profile", 1) if bkgrd_prof is None and profile_type == 'gaussian': bkgrd_prof = models.Polynomial1D(2) self.image = self._parse_image(image, variance, mask, unit, disp_axis) variance = self.image.uncertainty.represent_as(VarianceUncertainty).array mask = self.image.mask.astype(bool) | (~np.isfinite(self.image.data)) unit = self.image.unit img = self.image.data ncross = img.shape[crossdisp_axis] ndisp = img.shape[disp_axis] # If the trace is not flat, shift the rows in each column # so the image is aligned along the trace: if not isinstance(trace_object, FlatTrace): img = _align_along_trace( img, trace_object.trace, disp_axis=disp_axis, crossdisp_axis=crossdisp_axis ) if profile_type == "gaussian": fit_ext_kernel = self._fit_gaussian_spatial_profile( img, disp_axis, crossdisp_axis, mask, bkgrd_prof ) if isinstance(trace_object, FlatTrace): mean_cross_pix = trace_object.trace else: mean_cross_pix = np.broadcast_to(ncross // 2, ndisp) else: # interpolated_profile # determine interpolation degree from input and make tuple if int # this can also be moved to another method to parse the input # 'spatial_profile' arg, eventually if isinstance(interp_degree_interpolated_profile, int): kx = ky = interp_degree_interpolated_profile else: # if input is tuple of ints if not isinstance(interp_degree_interpolated_profile, tuple): raise ValueError( "``interp_degree_interpolated_profile`` must be ", "an integer or tuple of integers.", ) if not all(isinstance(x, int) for x in interp_degree_interpolated_profile): raise ValueError( "``interp_degree_interpolated_profile`` must be ", "an integer or tuple of integers.", ) kx, ky = interp_degree_interpolated_profile interp_spatial_prof = self._fit_spatial_profile( img, disp_axis, crossdisp_axis, mask, n_bins_interpolated_profile, kx, ky ) # add private attribute to save fit profile. should this be public? self._interp_spatial_prof = interp_spatial_prof xd_pixels = np.arange(ncross) kernel_vals = np.zeros(img.shape) norms = np.full(ndisp, np.nan) valid = ~mask if profile_type == "gaussian": norms[:] = fit_ext_kernel.amplitude_0 * fit_ext_kernel.stddev_0 * np.sqrt(2 * np.pi) for idisp in range(ndisp): if not np.any(valid[:, idisp]): continue if profile_type == "gaussian": fit_ext_kernel.mean_0 = mean_cross_pix[idisp] fitted_col = fit_ext_kernel(xd_pixels) kernel_vals[:, idisp] = fitted_col else: fitted_col = interp_spatial_prof(idisp, xd_pixels) kernel_vals[:, idisp] = fitted_col norms[idisp] = trapezoid(fitted_col, dx=1)[0] with np.errstate(divide="ignore", invalid="ignore"): num = np.sum(np.where(valid, img * kernel_vals / variance, 0.0), axis=crossdisp_axis) den = np.sum(np.where(valid, kernel_vals**2 / variance, 0.0), axis=crossdisp_axis) extraction = (num / den) * norms return Spectrum(extraction * unit, spectral_axis=self.image.spectral_axis) def _align_along_trace(img, trace_array, disp_axis=1, crossdisp_axis=0): """ Given an arbitrary trace ``trace_array`` (an np.ndarray), roll all columns of ``nddata`` to shift the NDData's pixels nearest to the trace to the center of the spatial dimension of the NDData. """ # TODO: this workflow does not support extraction for >2D spectra if not (disp_axis == 1 and crossdisp_axis == 0): # take the transpose to ensure the rows are the cross-disp axis: img = img.T n_rows, n_cols = img.shape # indices of all columns, in their original order rows = np.broadcast_to(np.arange(n_rows)[:, None], img.shape) cols = np.broadcast_to(np.arange(n_cols), img.shape) # we want to "roll" each column so that the trace sits in # the central row of the final image shifts = trace_array.astype(int) - n_rows // 2 # we wrap the indices so we don't index out of bounds shifted_rows = np.mod(rows + shifts[None, :], n_rows) return img[shifted_rows, cols] @dataclass class OptimalExtract(HorneExtract): """ An alias for `HorneExtract`. """ __doc__ += HorneExtract.__doc__ pass astropy-specreduce-05be828/specreduce/fluxcal.py000066400000000000000000000270321510537250300220310ustar00rootroot00000000000000import os import numpy as np from astropy import units as u from astropy.constants import c as cc from astropy.table import Table from scipy.interpolate import UnivariateSpline from specreduce.compat import Spectrum from specreduce.core import SpecreduceOperation __all__ = ['FluxCalibration'] class FluxCalibration(SpecreduceOperation): """ Carries out routine flux calibration operations. Parameters ---------- object_spectrum : a Spectrum object The observed object spectrum to apply the sensfunc to, with the wavelength of the data points in Angstroms as the ``spectral_axis``, and the magnitudes of the data as the ``flux``. airmass : float The value of the airmass. Note: NOT the header keyword. zeropoint : float, optional Conversion factor for mag->flux. (Default is 48.60). """ def __call__(self, object_spectrum, airmass=1.00, zeropoint=48.60): self.object_spectrum = object_spectrum self.airmass = airmass self.zeropoint = zeropoint def mag2flux(self, spec_in=None): """ Convert magnitudes to flux units. This is important for dealing with standards and files from IRAF, which are stored in AB mag units. To be clear, this converts to "PHOTFLAM" units in IRAF-speak. Assumes the common flux zeropoint used in IRAF. Parameters ---------- spec_in : a Spectrum object, optional An input spectrum with wavelength of the data points in Angstroms as the ``spectral_axis`` and magnitudes of the data as the ``flux``. Returns ------- spec_out : specutils.Spectrum Containing both ``flux`` and ``spectral_axis`` data in which the ``flux`` has been properly converted from mag->flux. """ if spec_in is None: spec_in = self.object_spectrum lamb = spec_in.spectral_axis mag = spec_in.flux flux = (10.0**((mag + self.zeropt) / (-2.5))) * (cc.to('AA/s').value / lamb ** 2.0) flux = flux * u.erg / u.s / u.angstrom / (u.cm * u.cm) spec_out = Spectrum(spectral_axis=lamb, flux=flux) return spec_out @staticmethod def obs_extinction(obs_file): """ Load the observatory-specific airmass extinction file from the supplied library Parameters ---------- obs_file : str, {'apoextinct.dat', 'ctioextinct.dat', 'kpnoextinct.dat', 'ormextinct.dat'} The observatory-specific airmass extinction file. If not known for your observatory, use one of the provided files (e.g. `kpnoextinct.dat`). Following IRAF standard, extinction files have 2-column format wavelength (Angstroms), Extinction (Mag per Airmass). Returns ------- Xfile: `~astropy.table.Table` Table with the observatory extinction data. """ if len(obs_file) == 0: raise ValueError('Must select an observatory extinction file.') dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'datasets', 'extinction') if not os.path.isfile(os.path.join(dir, obs_file)): msg = "No valid standard star found at: " + os.path.join(dir, obs_file) raise ValueError(msg) # To read in the airmass extinction curve Xfile = Table.read(os.path.join(dir, obs_file), format='ascii', names=('wave', 'X')) Xfile['wave'].unit = 'AA' return Xfile def airmass_cor(self, Xfile): """ Correct the spectrum based on the airmass. Requires observatory extinction file. Parameters ---------- Xfile : `~astropy.table.Table` The extinction table from `obs_extinction`, with columns ('wave', 'X') that have standard units of: (angstroms, mag/airmass). Returns ------- airmass_cor_spec : specutils.Spectrum The airmass-corrected Spectrum object. """ object_spectrum = self.mag2flux() airmass = self.airmass obj_wave, obj_flux = object_spectrum.spectral_axis, object_spectrum.flux # linear interpol airmass extinction onto observed wavelengths new_X = np.interp(obj_wave.value, Xfile['wave'], Xfile['X']) # air_cor in units of mag/airmass, convert to flux/airmass airmass_ext = 10.0**(0.4 * airmass * new_X) airmass_cor_spec = Spectrum(flux=obj_flux * airmass_ext, spectral_axis=obj_wave) return airmass_cor_spec def onedstd(self, stdstar): """ Load the onedstd from the supplied library. Parameters ---------- stdstar : str Name of the standard star file in the specreduce/datasets/onedstds directory to be used for the flux calibration. The user must provide the subdirectory and file name. For example:: standard_sensfunc(obj_wave, obj_flux, stdstar='spec50cal/bd284211.dat', mode='spline') If no std is supplied, or an improper path is given, raises a ValueError. Returns ------- standard : `~astropy.table.Table` A table with the onedstd data. """ # noqa: E501 std_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'datasets', 'onedstds') if not os.path.isfile(os.path.join(std_dir, stdstar)): msg = "No valid standard star found at: " + os.path.join(std_dir, stdstar) raise ValueError(msg) standard = Table.read(os.path.join(std_dir, stdstar), format='ascii', names=('wave', 'mag', 'width')) standard['wave'].unit = u.angstrom standard['width'].unit = u.angstrom # Standard star spectrum is stored in magnitude units (IRAF conventions) std_flux = self.mag2flux(spec_in=Spectrum(flux=standard['mag'], spectral_axis=standard['wave'])) std_flux = std_flux.flux standard['mag'].unit = u.mag standard.add_column(std_flux, name='flux') return standard def standard_sensfunc(self, standard, mode='linear', polydeg=9, badlines=[6563, 4861, 4341], display=False): """ Compute the standard star sensitivity function. Parameters ---------- standard : `~astropy.table.Table` Output from ``onedstd``, has columns ('wave', 'width', 'mag', 'flux'). mode : str, optional Can be "linear", "spline", or "poly". (Default is linear). polydeg : float, optional If mode='poly', this is the order of the polynomial to fit through. (Default is 9.) display : bool, optional If True, plot the sensfunc. (Default is False.) This requires ``matplotlib`` to be installed. badlines : array-like list A list of values (lines) to mask-out of when generating sensfunc. Returns ------- sensfunc_spec : specutils.Spectrum The sensitivity function in the covered wavelength range for the given standard star. """ spec = self.mag2flux() obj_wave, obj_flux = spec.spectral_axis, spec.flux # Automatically exclude some lines b/c resolution dependent response badlines = np.array(badlines, dtype='float') # Balmer lines # Down-sample (ds) the observed flux to the standard's bins obj_flux_ds = np.array([], dtype=np.float) obj_wave_ds = np.array([], dtype=np.float) std_flux_ds = np.array([], dtype=np.float) for i in range(len(standard['flux'])): rng = np.where((obj_wave.value >= standard['wave'][i] - standard['width'][i] / 2.0) & (obj_wave.value < standard['wave'][i] + standard['width'][i] / 2.0))[0] IsH = np.where((badlines >= standard['wave'][i] - standard['width'][i] / 2.0) & (badlines < standard['wave'][i] + standard['width'][i] / 2.0))[0] # Does this bin contain observed spectra, and no Balmer lines? if (len(rng) > 1) and (len(IsH) == 0): obj_flux_ds = np.append(obj_flux_ds, np.nanmean(obj_flux.value[rng])) obj_wave_ds = np.append(obj_wave_ds, standard['wave'][i]) std_flux_ds = np.append(std_flux_ds, standard['flux'][i]) # the ratio between the standard star catalog flux and observed flux ratio = np.abs(std_flux_ds / obj_flux_ds) # The actual fit the log of this sensfunc ratio # Since IRAF does the 2.5*log(ratio), everything would be in mag units LogSensfunc = np.log10(ratio) # If invalid interpolation mode selected, make it spline if mode.lower() not in ('linear', 'spline', 'poly'): mode = 'spline' import warnings warnings.warn("WARNING: invalid mode set. Changing to default mode 'spline'") # Interpolate the calibration (sensfunc) on to observed wavelength grid if mode.lower() == 'linear': sensfunc2 = np.interp(obj_wave.value, obj_wave_ds, LogSensfunc) elif mode.lower() == 'spline': spl = UnivariateSpline(obj_wave_ds, LogSensfunc, ext=0, k=2, s=0.0025) sensfunc2 = spl(obj_wave.value) elif mode.lower() == 'poly': fit = np.polyfit(obj_wave_ds, LogSensfunc, polydeg) sensfunc2 = np.polyval(fit, obj_wave.value) sensfunc_out = (10 ** sensfunc2) * standard['flux'].unit / obj_flux.unit sensfunc_spec = Spectrum(spectral_axis=obj_wave, flux=sensfunc_out) if display is True: import matplotlib.pyplot as plt plt.figure() plt.plot(obj_wave, obj_flux * sensfunc_out, c="C0", label="Observed x sensfunc", alpha=0.5) # plt.scatter(standard['wave'], std_flux, color='C1', alpha=0.75, label="stdstar") plt.scatter(obj_wave_ds, std_flux_ds, color='C1', alpha=0.75) plt.xlabel("Wavelength") plt.ylabel("Flux") plt.xlim(np.nanmin(obj_wave.value), np.nanmax(obj_wave.value)) plt.ylim(np.nanmin(obj_flux.value * sensfunc_out.value) * 0.98, np.nanmax(obj_flux.value * sensfunc_out.value) * 1.02) # plt.legend() plt.show() return sensfunc_spec def apply_sensfunc(self, sensfunc): """ Apply the derived sensitivity function, converts observed units (e.g. ADU/s) to physical units (e.g., erg/s/cm2/A). Sensitivity function is first linearly interpolated onto the wavelength scale of the observed data, and then directly multiplied. Parameters ---------- sensfunc : `~astropy.table.Table` The output of ``standard_sensfunc``, table has columns ('wave', 'S'). Returns ------- fluxcal_spec : specutils.Spectrum The sensfunc corrected ``Spectrum`` object. """ spec = self.mag2flux() obj_wave, obj_flux = spec.spectral_axis, spec.flux # Sort, in case the sensfunc wavelength axis is backwards ss = np.argsort(obj_wave.value) # Interpolate the sensfunc onto the observed wavelength axis sensfunc2 = np.interp(obj_wave.value, sensfunc['wave'][ss], sensfunc['S'][ss]) object_spectrum = obj_flux * (sensfunc2 * sensfunc['S'].unit) fluxcal_spec = Spectrum(spectral_axis=obj_wave, flux=object_spectrum) return fluxcal_spec astropy-specreduce-05be828/specreduce/line_matching.py000066400000000000000000000106301510537250300231700ustar00rootroot00000000000000import warnings from typing import Sequence import astropy.units as u import numpy as np from astropy.stats import gaussian_fwhm_to_sigma, gaussian_sigma_to_fwhm from astropy.modeling import models from astropy.table import QTable from astropy.wcs import WCS as astropy_WCS from gwcs.wcs import WCS as gWCS from specutils.fitting import find_lines_threshold, fit_lines from specreduce.compat import Spectrum __all__ = [ "find_arc_lines", "match_lines_wcs" ] def find_arc_lines( spectrum: Spectrum, fwhm: float | u.Quantity = 5.0 * u.pix, window: float = 3.0, noise_factor: float = 5.0 ) -> QTable: """ Find arc lines in a spectrum using `~specutils.fitting.find_lines_threshold` and then perform gaussian fits to each detected line to refine position and FWHM. Parameters ---------- spectrum : The extracted arc spectrum to search for lines. It should be background-subtracted and must have an "uncertainty" attribute. fwhm : Estimated full-width half-maximum of the lines in pixels. window : The window size in units of fwhm to use for the gaussian fits. noise_factor : The factor to multiply the uncertainty by to determine the noise threshold in the `~specutils.fitting.find_lines_threshold` routine. Returns ------- QTable A table of detected arc lines and their properties: centroid, fwhm, and amplitude. """ # If fwhm is a float, convert it to a Quantity with the same unit as the spectral axis # of the input spectrum. if not isinstance(fwhm, u.Quantity): fwhm *= spectrum.spectral_axis.unit if fwhm.unit != spectrum.spectral_axis.unit: raise ValueError("fwhm must have the same units as spectrum.spectral_axis.") detected_lines = find_lines_threshold(spectrum, noise_factor=noise_factor) detected_lines = detected_lines[detected_lines['line_type'] == 'emission'] centroids = [] widths = [] amplitudes = [] for r in detected_lines: g_init = models.Gaussian1D( amplitude=spectrum.flux[r['line_center_index']], mean=r['line_center'], stddev=fwhm * gaussian_fwhm_to_sigma ) g_fit = fit_lines(spectrum, g_init, window=window * fwhm) centroids.append(g_fit.mean.value * g_fit.mean.unit) widths.append(g_fit.stddev * gaussian_sigma_to_fwhm) amplitudes.append(g_fit.amplitude.value * g_fit.amplitude.unit) line_table = QTable() line_table['centroid'] = centroids line_table['fwhm'] = widths line_table['amplitude'] = amplitudes return line_table def match_lines_wcs( pixel_positions: Sequence[float], catalog_wavelengths: Sequence[float], spectral_wcs: gWCS | astropy_WCS, tolerance: float = 5.0, ) -> QTable: """ Use an input spectral WCS to match lines in an extracted spectrum to a catalog of known lines. Create matched table of pixel/wavelength positions for lines within a given tolerance of their WCS-predicted positions. Parameters ---------- pixel_positions : The pixel positions of the lines in the calibration spectrum. catalog_wavelengths : The wavelengths of the lines in the catalog. spectral_wcs : The spectral WCS of the calibration spectrum. tolerance : The matching tolerance in pixels Returns ------- QTable A table of the matched lines and their pixel/wavelength positions. """ # This routine uses numpy broadcasting which doesn't always behave with Quantity objects. # Pull out the np.ndarray values to avoid those issues. if isinstance(pixel_positions, u.Quantity): pixel_positions = pixel_positions.value # Extra sanity handling to make sure the input Sequence can be converted to an np.array try: pixel_positions = np.array(pixel_positions, dtype=float) except ValueError as e: raise ValueError(f"pixel_positions must be convertable to np.array with dtype=float: {e}") catalog_pixels = spectral_wcs.world_to_pixel(catalog_wavelengths) separations = pixel_positions[:, np.newaxis] - catalog_pixels matched_loc = np.where(np.abs(separations) < tolerance) matched_table = QTable() matched_table["pixel_center"] = pixel_positions[matched_loc[0]] * u.pix matched_table["wavelength"] = catalog_wavelengths[matched_loc[1]] if len(matched_table) == 0: warnings.warn("No lines matched within the given tolerance.") return matched_table astropy-specreduce-05be828/specreduce/table_utils.py000066400000000000000000000032011510537250300226720ustar00rootroot00000000000000"""Utility functions to parse main NIST table.""" import numpy as np from astropy.table import Table, vstack __all__ = [] def sort_table_by_element(table, elem_list): """Build table based on list of elements Parameters ---------- table: astropy table Table to sort elem_list: list list of strings to sort table by Returns ------- element_filtered_table: astropytable Filtered table based on inputs """ filtered_table_list = [table[np.where(table['Element'] == elem)] for elem in elem_list] element_filtered_table = vstack(filtered_table_list) return element_filtered_table def sort_table_by_wavelength(table, min_wave, max_wave): """Build table off of wavelength ranges Parameters ---------- min_wave: float Lower bound wavelength to filter on max_wave: float Upper bound wavelength to filter on Returns ------- wave_filtered_table: astropytable Filtered table based on inputs """ assert min_wave < max_wave, "Minimum wavelength greater than maximum wavelength." wave_filtered_table = table[ np.where( (table['Wavelength'] >= min_wave) & (table['Wavelength'] <= max_wave) ) ] return wave_filtered_table def main(): """A little example. """ t = Table.read('data/line_lists/NIST/NIST_combined.csv', format='csv') elements = ['He I', 'Ne I', 'Ar I'] sorted_by_elem = sort_table_by_element(t, elements) sorted_by_wave = sort_table_by_wavelength(t, 2000, 3000) print(sorted_by_wave) print(sorted_by_elem) if __name__ == "__main__": main() astropy-specreduce-05be828/specreduce/tests/000077500000000000000000000000001510537250300211575ustar00rootroot00000000000000astropy-specreduce-05be828/specreduce/tests/__init__.py000066400000000000000000000001711510537250300232670ustar00rootroot00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This packages contains affiliated package tests. """ astropy-specreduce-05be828/specreduce/tests/data/000077500000000000000000000000001510537250300220705ustar00rootroot00000000000000transposed_det_image_seq5_MIRIMAGE_P750Lexp1_s2d.fits000066400000000000000000002145001510537250300334660ustar00rootroot00000000000000astropy-specreduce-05be828/specreduce/tests/dataSIMPLE = T / conforms to FITS standard BITPIX = -32 / array data type NAXIS = 2 / number of array dimensions NAXIS1 = 387 NAXIS2 = 44 END ACV^߿V^j꿯ypyt\w0BlA?BrB6G.A*h8§_;$E[B5M>B0=U¾­XB]A%N*nBA@: `86'‡CCnյ8,nTi2 )¦ºrºyB njˆ?b·yBm/IBdҿ>xUhz‚X ]\ŽÄq9T 3(iҕ:L°—zlV])}t”ƒY)B~n@AxZGUxɪCڌopLBNb@€A?TQAUeL>hšcLdQJ-DlYK/_3A˗7B[~5a@E/ BA@O@֓jV@"0HÞ /0@eDV?D:G|'U}7A_A|0Ě??`eD) v$†k7ҍY/o@js#A&DI2F6dy}RlLBL@axAsA0@d /+~[Jz@5'tsDpX b>*oCV@֦z@rx?g߁{0_|A@M@p?G|0h/'/c [)7y/@!F\?4w@д 7.@Ǣ?>;@5T @s)< ߀`"W4h!w]É H jÉ]»$*BP%:On:±=Mv³p,๭ÓS=ڊ‡?!…D[oL|\3Fq@*oª5V)¾^ FQBBrďq—A+¬ZpW_gxYz±Œr醙AN F§:YGV‰WXX6B݃C? haL#yN3zA Iz ;`2l?iF d—%B4/{D)1CDBah]@Twb‹)?:WG *@3I46/@A=ȂA-)A^gEAGm۵ډi?ʊ..|9d;KmAǣ`hk "A;^ \bc,>}A[A-A/SثR}P; EfVL@FA%.9>/&#eg?2@=@-8 >vhB;vm@DFOY&@U@ӿyr>?8`%`tEAٔC?žA @Ĩ2@&ei1Y@Ʋ7oF?t@.+9';@s@A=*A}[܁\p2Vbߏ>R.&^@g"@?@C>Q@-@ /p@@@=EG.V̬e+6j#>@+S5UOfs7r²Ð%mUµYXA}9BMz²^m-?@!A~WB KnÀ$8©A@rCQ¾VºfAP B%I8ٹ YH¿K9wXPAJ B;h)JsG`'_kBQ8~¡cڷSAKٺB$!pA*5@5BA]!)>B5Ad f֎2Z‚n€ƷA1B>BA")xPA>@BpM#”BB@Ur K/=AA62Yg@hac#?iG#~B2WA #1m !cek@ AKRn [% &eJYb܆A[]uAyW\Abw%vxvADX}")?dA I@|s@ulvA%UA@rD[aADAЕmFAcy[wAX/AAKcln@r/"iG }AH4-r@ K? 1@X@[BU.>@3@Q+@@,@qAٿ@ӹ_AAֻ&q!YO]BA=wIMG>") @ܿBAw@v[6?E賗>NNf#0> @a ~2A >^AcIu1˿?8MZ?1? >ddK?f-;#>2Q?j?y?@'WPA1!Al3-[cW B ,3QgI+C CC«94Cž,@SuUB#[0¾EžGj]w5vž¦ B=%A̫¹d\c ֳc&@9դDg4APBH BD:yfKp,=QA@dwA"#$B|1mQDB_ zBXPAE>AqO0Ae2ר~@lr{@jA"Tۇۿ4ڽWI )~. A ́@ E@ᅬ[_@jlg׫N?G?A9) +AlWA֯$ĀzX@;@ A@vA5I '$ba.U.;@= @(@ѡ{AwARB~d.@Rs>BQAŇ dO@I@A.Aɱ ;v}x/8+XBOo@X8dYMX@>e=6w@}PUfmC@GM 4@si@؅g?0䫭K'EQ?[A*?lbiZw{?'@k=䠙SR?Y9 @NSBN‚J#kBԏv<4C~ OA/k´C#BŸ3{Mªe|C\]@½i]ԮRlݶ"@OBA7w™y۵ w?PR2xBTn &0 iB goj/' { ¥ȅ¦?µ0 FŒB0q&@nkAQ!A[µdQEA>}LFHAQg _Œ™=B%A1B7Z`_`:A,M8OU=S4h@>BdPF~}J&ZG;P3J?-g#P;AQ͵?(٥@Pf&v^^ \r_#s~Al;6>2|Cm`ULbAz8/19*[d,L?Mե78æ*U@H|r@-thZ b*|V&@!Bvqp0܀&%: 0bu@A&AY!qA?ږA?ZV> w(j@ihep2U@ JlAAQG6Aj(P^$]l")?85AAۥSA1i@M=tXH&?ujhE:@ {ӂ\@jR@2@e?̵=9c ۶.B?]c<͵»&GúF#~Ðy-èg;7U|½]5)kD82*“j2&A2e¦S\`AMB1"’O߭– ?9B~ë@7vzvnP_@Br8X!c@C OAAA}BCBFO@A>r‚Ii…}B*O2B>@N KVCXoUs6z™6yS@׎4A?M3 WЩA„BR-ÍBDA|88  |@£J-AӦ\@{6T䋲_΀Ok45s6Y@0+ʖ[HTAEB4dA-PAIbWBl1/A6@pb } s}@#K@ BtfA?ɷ]O B.e˖AyAĚbSd@6j[`^a7A>AJ3φĆ@\@ӈa@3(V@ m:k iXmb@|@m}@@21,$p7wATF@rт67Q} L3~ )\"2A.C_@I9@ў MvU?&@0@E@0+ A=iǿ|`gH'aAjB~ In('濖*?i/?[@'@G* (˩@KƼ4ߎ@U?X_uI?JM;@Z@wA(T͓`y/VۇIFE :?-@B*AmÒn,]ÍnU3u :/"?!'B3]wxB%D|̻¬`AHqAwp^Õ&AfIx",0CXmA3A2J[œ]sºBvAt<b%4B&$6p¿(.rBB4 )U7A=5'„,raKvA:ghÊ'e ¡T1ŸPCĜȓ M‰A@a:£KpA"R3 BA |"LBdB#'SFBqA@AyA&".4G43@kk=CT]BA }WB3Ao]B KAeBe^UBW[l0A C#OA >@U0@9kJ%1S@@zA?xFUHu@?BCI@NȅA4zOz]?Sz*j@ 9ATHKQ@XAgaJApA ?) ~R)}>ABA@6o*@eJ?A,uA9Z07 (zYƖp"6?}AA}@@F +c?3r@I9AT5A]'^,>虠r/?X?&E2JPݺǿA|_DA[1ËA|]l^0Bx DP<%žВ~BC]dCL|Mih/}A6CbCmC4#BgBѠ@Ÿ@›EB …`>%+B' \\Q >&A= BX ŸLG8fM–B\?[Ef*A@p!BSB;6A?A1Bu}AGd…Ac:B,+8TX{>}B yMA]?ڟA>4@W#=A{H@th+o!Yh)X #@~1BRDe!?€Th‡0vEB+ F6s-@=[@MX t RA?@]f`LAAF}O~^ӫM?{ɪBH@_gB)̾yMuGb`?@A A@BxK B<\?"xpԌVL"LcAdr!@LiZ@Sx?AF=khYn ?2Ig$ج>R5nݽ!7@m/P+O헀')ț @}&Ðƨw¬o&CnCl/*Ð@km&#UwTv TrB]DU=’.D:Bi&"VrfAP'"BN$yU¢8&f@·#EPn"0.nA´: (*'C0gBXSCAoZ8?doC5AȂ A§\A*hZ­PWLz#԰p¹kM}n8‹ t[k7B^~ozMOA~c)A JJT1S3CU [iW!Q,e[mÃA($B›71ucBGI3>*c j+"\SKSoW8bp9D@K!Gʮ|-@0Uj(j@tAP!A¬)3FG@ \˾AXAx.?n@KTk2Vǰ0A/AMByr8A#բA"=n@q8k+@:Nsmؔׯj?cGwgp¿A3-~8mC @'hbZ&tmB%m^@l,# \'a= HTE)BQA&{~€?"eF=,Bp€)C^)AGA`Tm||RU+; 緿%~@'θ4<.5yOZEA:fA!Kn(+3*fbԿ" wь{!<@b҇@̘FFh@A0??%&nL?+Bl|u.)?6kgoë?=A;6Aڮ.~AM#=cpBA;]j?xAG[QT)U4 o1?yNB@@?|Gt> _?N6@g@QAm3? ,x?gA2 J˹JAW]"ȝOh>AlSAz8eZn_@nL6ʕh$$kuJ@4Aǘ1?ӓ9@ %8&'ը#U}AR?c?S#߁ ‡&C3ZD §wӦ1 9BaXȢ?UBB4=@BG>B?8 Gf:M¥@ 0BN 1vŒov.B-AxQ?4o A6 B-[uHb JZ’tBY^B7zAt@-XB+0aXB :]A}RBBv ܖA}Ab…B8F2^?²B¤qϾNAUo~uBBtWA:z(`AAḆKB@o?@I|“rʝBD%AH)yj\3bA@z6Z>-lWxT3BJAm A'@jp3A$$Baj nB*p`Aҏ\Aga_:Hdӎ+^A0B+~ @ƤAAZAPNvA@俽΋@8dp=xR@5qALA>iWKJ_*`dc k AWBv%AZQ@H@y[3d$ |۵9FA+^yA a@Jin|V@9-@BAW#@@9f@ˏ@)@2ο#^8S'U@@A !TQ=@#r8@6翩@ʵ@W@H=ʣA/VcAžo͔jn#5|eJJ`yL BgÎcE!NP9 C:l~Kѩ/BԼCBDwFC BÖ|pB՟AA“{N kC-kRJrhl8B5P RA'! qtB0q{@;Ac9$4‹ySAB8Bi5h1#A 7@AgzA7'®)DžAI5nSCPyeUkwA 02BAp1OY"pxA+AAx͇ ciH(w)Enzw@%AAYw*6g*ªpªB #m1^}A2z@ }Z-t+B?2D@Hp4ͤ">y>A]P)xA]uBCָjBA\|~9FAA qm5A>F䬲xY |r&%A@y~k ;b,7@eݿ?.A|AB5@_5?u.?QAKq}A 6Lh?i@p`aASǜ@ТB\*@@}AT lc?6}&:2qAy=^s>'"}XuVF\ =z]@+pNAf@t2]T>ܬA nu."@w_ &K!+@ ş@RиNp#k-@Gd>ygD:λ?@$M;%5b! (YCAB 2A?4 T@7 @G0A@ JE9M8Az?_?L`3x/ku?1U9ègbVAX7ê]]ps:RIr,7`wdÄrA ENB­0>p=µwY~UBBQP’RB±¢kA8&OŠ&![qL ¶†lA-c[āyzB0BQgr§#A•‹`P(BB:@6"kŽl]pdBJ"B@8{hH=8\+{z1?.AuNw^KQ HZi ?PAD"C\5wA›hH .D B ZVU&C.T=CSÂBiܛB!r»4OSB²„iq -1>YhBRt6hXBq0Rx²&—ԘPK?Ϙh#¯£ 2A|AJpBAB:UB?jy@aR\-¼ A/V BJ™8An $MN!HA‚-d1@W+@Cu&6TIÜ@]A\i?,7.@GXB B(@U̇"aS @pFA,iq@P#9 J@A^?@Hl@AJj= @@uB?n:?@.@6@bA[=H6@ں,{l`r<_FN@I˧@`?AA(c3 +sUXR}?d>@ZAHzۥ@@ƈuC~Cɂ?}kBv-C6™7?BlBxB{k«:Loušj`1¡<’^%C7K|YY9["^GDkwaA(A*,?^BCSˆ gBB%v _%y#AޱA+ڤ£[rA@BLABBf|||1/AA @~Bn9A@„doBdrBNl@wA< AVWz9XB'z&h A(A 4;@+`?i2Ar‘(LA"=QBJw##B^[9GA{V3AD@zf[]A)B`@AYB.WW4F7Tr@UοuAyP$%[B9AA4@QWѡAIɿ$`@A@ATA?q( ޻0KvwA(h@*&DiA'Mi@k@1uZ8^?K ?Q.)\k$@>㽺Sw?C@ɗwAKU ?M+Eٚ?@IA9HA9f[?`A UA@ r0zms@T2xW{cz3h?d?Fg6@$,-?.@ִ?_8N ?FH@ƣl"z>#@`;A@M* '@-Ŀ.Rle)/ÐkZ{HBi ;jB drG)""`5BHC' åd@d%nvJZ_s:^=˼°b¯A S!CeZpB[[BB`-A$%Š8B&lfB'NF2A#&B-C( §&~ɟpBB.¢Œ?KAvS"©]dIT_?+`BAjќ„!]d2^VBzt+:;A4J$[BD@D+AU›=h>"qo, iAMAq/ˆg'7)AIE\_1A&u@ :pV›BtS=A-Aj5셿^y{A AF%R#x@DA+(@_!NA~w/7er@{J$A|ZVj@ϲA?Q{)CAAqfY@7 iGۨ@GӘ7@FUwQ#"AFՄG@̯0Ad7UH@@DN@M~F0<<?)Ax@jBj@pA@- q?'72x>ڿ6@ @G?BZ)4Bô-06ѮAc}»B$p)ª&fB<~BPI_WAf"OzGT([G\]BeO?^DFAw]QB7H{AGÁXF"9“Aa¤­O]--Nc96.@cÿ[ 4@SA"{Aq²ž^AAy\B¥S@CpB3 YBbBE1BB|:e‹PAmB*B6 LB%AdA5B%B3,`( B=BkAJѷBE ?gA'B4h)L‡.HA{ZZA0NW.^g@r!A!M* =WkAfк\?2@@6TTtǾAAƿȤ:a /!@ 77T@B @Ǚ{4>wp}ֶB^Z{p@@/黳A͟@ %Z@B+8t@A?IGBJ=@Ȓ?:,scAJ@\ziA*\E|O3C/hwZ*c?aAY,aTGÄWii\*@BAЕA|;?5A?}!@@AKu)A@1J n4@.UAN<@fAKA5|Ay[@Lz@(W@0E@E+ 3@G@;EXz-@j?ܔAS?CxBqGDBˮAo@g8|AaPFAsi¸I>_]@tVAA=g:]lv1Bp= B@!Ajk(A u( rU[ zB*eNBkAQj)G+AkfAAAک=zQiAQ5 YxB1@_@o`$y|:&8@]AA#]Kn4]1Avo#AO@:AA% 9w+b]@JrA2R] u4BAAv˝@3Bo5،F?yLv^? 1AC?D1u|т#AG<@0bAs$VB=@5A'odkAb1d@i8@Xf>Ȓo|DAw0vfP,:ۮAB }@-H0_ Žmg>uA v!0ţMi2N̒R@&QpqF@IAK1Nɮ!i.?M?K&ANG?e\A -@¿1GVRx&9)A* ,@!A_hq4@heD@>?#¿y'e {WG?r$F~>o@U/k>P@$@YHRºDX%S`GABsQCRMoBAN"ߍF£<L,Z/@/5F),`B^3Ŵ¹_CXA@F'+&*2OC~4YCPAoÐB>B:DRB֢d*,'p̍=3&B0& pZ@/gqvROvwe¯GGT¥]@=<`l`ʢ%vBvL+?pS=xvx>[Aw;mք<02IiA;5vy=/f6‡d"VI¸ĭA@iZ .OCi3O,PNBm" BdAr\=Q @}V.HSqk@q?'YO?/hMAAD?t" 4J?n`-T?@[Z@-`(z7.L"S@$9RO@[?A'u{<ȁ&w@ʀX1B,EAuÄ/z\‘BTpX;jW^Ȼ®yÚ5}Yoǽ¾ >BB: L+VjALÌ}^|C7ٵ5BBx…9[¨s<7AG©ߑ2Q _Th)cBkU|B$;f@W\€s'†0:hBs'/A U*Rv .A2:A9+$¡8ѣB1@sGj|AAwh #|Qٽއ$X0Bא jS)hACQ//1I`@>yAefӏ>X@?`@ B"{(@^}{ZRrAS @\(#A7@(=YAA0Bz?,6+C'+7YLA*X?X@\l'bω4GhAZ,b*R@s2z)a;{P/v }m~A\?xU,/^?왡>%!Y?SMc2A`A^)]?P4\BAV( VjR{C?-x<@'@Hy#@UԼ'?N55b@_pY 6]?y@ ƹ- !AFQXdFZ)>E<3= @ m?/q߾m^i@U@Ȥ:dΨB+&vsqAbhfI·uAT1Bl3oPcBAB&80B'LÃBc#qB?RA0&b¿s?X@2>^"2užSBYA,v-AA~j.FT€ЪAB/'‹/qtWBM?5lA'mWcA@+#Lm'^ƒ_)A"QFAw_A.eWE>U9WnܿFAZ)A@HA:`4nARq,AG[g@ (n AWI@(E@fAW7RMuApA2f?.f@T@DA~uAAg@A['@d,2p@.EAY?zUHA?k@A6B{Aun3K*&AMB?wL" ?xS?˶@U/AA!'zUXS@DARN<ؑi7{^@@Ev'BA'AxAŒ)f@k8]D@0,[E@s3> A@A[۬A$T>H@vAA&}IjnsAT)0 h@@0^,@nWB}b+W@]) ސ?A{7c$A4Jyϡ?!@NvO@^7?@sq@ >K̩?_;A@ջCâCC~kf( ‚&× Ѿho@;Sº&TA%6›8B_BB ABAŒ`k;oA=Ba3^kA Bhy3~m fGZA/NAAdQBAZJ!UB;AsAE>@%A Zvv=S/A ^̌RAUZt%"A39B€-h@NB8]C!M5|\J}hQAn @YAI;@S@c8kAA& -i@b$>Wظ@Qb@Ɠ#A|A@74A-z#@?fA@`>sA$@<|xAEkÌ&HK;XCS4G®pxsi?fMCC9†uPCC7B@ܡgAVƒ!y(zD;GAfѾ$Gpm:c?j—'A65B@yWAwB_N!AV4aıEªŸfA[}@@-Aj=rdt?&oHྀ>eA$?=ɛ@F@mCA\?ό?&RA?h@[ At@MJO?:ArjJ@A@(?A]AGA AErAϘANKAoAS zA'A]xAmA4B bAB9 B28BhBVYfByBqB*B垵CC g_ClQCbC2qCBBgٽ# gXB(.B!N¹-A]BZa·¥Qs’B%#BB7DmB>Z?JUil"FFCŠnNƒ[oŸDº€BfGRuheB4ZAA#BAG tQ-]BīXdBX F曞gKJٜO|r¤";ql,+CȱšCY1+sSV!2A˜z]A G3C8oxIB;>{?cAi@rÆAC xxy@Je@0@]|A@?9&A("٤gQYH2v_&Q@1B  h@&Au"m?=W}BAJ Ao;ZYdhB r e{E ]'A,]ӷeA$5Z@aEGc-@A\8@Av9Kپ@~UoىA=OB5cA@/A+A$@/A,NAkA1AALA`gnQAy(FA@NABK@ظx@Rz#A)AtAB BA bAA/tAABF,A! APAV/AwAOiABcBxB,BHB"BBPB̍BqBB@BCyCCC.C'MC.CCEPC6XCGC9[XCYICH>CnpC|CCoC^IC8C۸2"B{%ZB>l[C[BIlB̩C)Ž/Cee@.ŠgB,B'JG%Bbn8B/S\AʉKB4B}BZCSPC WC|BC9*DM~µ`cŠC!rBBPBT6BdB͊.B%BB-'!B/A!MDC0[BD"B1! hB9NOb@P;BW&A%B>BBmBH)BvZAtBCB>yBv!BSBSiQm@sA6xBABd8BB"DBI,BPBBHB`oBWBKtBEDBBBBCB8M~B B!BC+WC%5C%C bC33CGC5,CCK CdPD=jdDPDVJ]DeDuDfDoDD]DLDـDDDDďDÝD8dE IE9EGE!BE6E>E[EhfEjEIE)EE"EEIEgkCr@]C*B DCźdB9CCCAaDCCelCCC C)xCkhCC[9CCz Cy?C MCC}CCC C%CnC*CQ$C9C4C6C7 CDzCw^Ca~CV CIC4CDC]]CCC{3CC9CCdC(3C! CAC&C6CC0?CD1C8COD0D D1D^bD ,PD [D5D oD :pD DD ЅDRDpDKD"D2D'5D(KD%D'D!D)ʥD.D+@D0kD-ÔD3D6SD9vD7AD@JDASDF WDHרDOUDPDHDMDZDYDcgD`6D\DjhDb1D6DfDXaDD DP:D,CD2q D~$HDQ8DSDI.DfD MD8D6TDXDڿDaD\GDSRDK/DAOGDFduDRDPlDS 1Dx|Dn)DfB~Dy\D\DDDpDnDEavDisDxD^NDEdDy)DJ.D@Dn2CD)DDaD~DՏDMDk"DvDtD&DRDdDxcDDEDeDDdDsDkDrDDpD}DMDDz7D~DPMDDxDD3DuDJDjDD|D{JD\DIDDmD5DsSDʨDЭD_D+gDDԒDDD3DۂDagDDbDDED{2D DdD"DpDD3DDoEDWEfEE?EqE]yE aEEE E\E:EDExE1EGE!#EE(%E%E.bE.JZE.jE3gE4E:/E9E;qEBkEAEI2EFAEGoERbETEXhE]E[HE^E`FEg{EimElErEoEpjEuVEz@E{E-E\EVEEpEo#Eb#EX;EEwEqEEyWEk:EEEBeE EtnEE`+EEsEڲEYE?E\EFѷFBCF HF IF FFNbFnF[eF$F&F)אF/F4BPF:QFL}$FTեFTFXF]cFm5ZFrq"FwFzFFNFFFՔFbF}tFFȪF9(F-F G^ G ,UG 0)G&vGPgGG=G7SE:BY[DDD)SDDRDD3DxDD\DD8DDкDnD*DʹD~D"|DfDDD_,D[D߉vDD7D+DwDDDD D};DsJD E<DE$jDWEDDE LENEE6IE .E ǻEENEbEn EDEOEIEjuE' E"w#E"(E(E!rEE&KE!0E+-E"xE'SE)p.E%^E-ŸE)`E4;E=5E7E44E8GE9E9fE>E=FEAEE<3EFEH:EHQEOzEPEPuEXVETEZER?E]E[)Ea-EfEiE^EmEetEruEq ^EvF EsE~CE9EPE%nEWEsE6aEEELEEE-E8E E1EhEUE|E/EEחEqEoEKE7E E EmNEbjEdEESEEEłEņ1EHEˉE7E7=E E$EC-E|E5VE E4EZEtE.ExEEoE^ESFcFYFSF ~lFMFFF#|F%zkF$BF%F)F+4F.gF2IF5gF7EkF;JF>GFC?FJFNUFOFScnFXF[ڮFaFhjFpFy F~HFF#'F.FYFlFF+!FFmdF"FoFSFFFcFF FuF֝BFbF"FFvFbTG6G G)GGG"G%˂G+G1xG9!GPoGGYGY&$G_PGfX4GaGi GEwEBDDΚDDDLDq;DލDXDŮDvDcDD(EDDRDrDE FE E&DE EŁEYE GEEBEtEEEEE\EEcEE9E-E 5E*E&}E'E;TPE-+[E5 E*Y(E2E:9bE@E:E? 6EAEACE?!EBEOEP"xEVETEUEY/EX%lEXäERFEZE^E[{E^Ej"EgQEfEdEue!Es]EwfErɉEqLEpEzKEv EyEwѤEqEEEsEE"ELEE:nEEْEOLE“Ey3EEE%EEEE6E(E3EExEmEE[EnEE)EZOE`pE+1ELEeEETE£EmEEǶ(EiE̊rEiGEҙEӶEׁEEEIE₌EE*PEEOE&E$EGEEFFF,FbFF +FFyF6FFghF|F$F8IF0;FF F F"dAF%iF'F,*F3JF;*FD*+FL]FMoFL FMFSX*FUrwFWwF]F_އFb}Fg,8kE=lE@E<{EB8lEEmE@E@&EJEH'ELEKEOELߦES\EXo0EXFE]E]E\E[EeŀEe4KEaREnNEg8QEsEqZEoOEtE{ECErEE[EEEyEyE\E9E4|EEEEEUNEVEE\EiZEEE8E{mEEEEE4EE`EEME|UEsELEE!TE EyE͌EF EOEWEpTE޽EEGE E,2EpkEgE}E"XEEpE2CF2FFyxF1FaxF|FFF,F(F FIF"1F&+F'BF)F-J.F1fF3F;_F>!F>hF@jFEenFJvFOlFU_F[F`?FbFdFiUFm{FpfFq_F|YF FEFbFFRFaF+FJFlFF?F3KFpFFgFFLF(F?FFjFgF-G.GG?G Gn G#G)G)4JG/zG:G=G?#G:EBϯD0D`"qDPC9D@.D+DL̑DZ DK|D7D7uxD3 Df,dD^EDamD&TDQDgDQ9xDD DVUD\(DW=DTD[DcDXD"DD|Dx\4DcyDaDZDDVDDvD-Dz#D_DbrDPDDz(D#DiLDr 6DD DDZ DKDDn,EDDaDDDDkD&D0D̓D D-DDȠDDDn DMDD?DDDZDcDD̵DوD8DD~DD%DDrXDD'D/GDWDD .D=DƞDv#D_D,DьDvDRDDجDoDчD(DDDmD1DDD|DD |EiEvlEE(E S{E E E thEEJEEdE\EGElEYEEE &E#E$oE'E'E,E/E0E2E4E6cE:E>lEB6|PCDAC%Ce0E0KC#sCxCCUCCN,C9C#Cs2lC̀Cg_B$C5CCCxoC[CC 5C]dCCd_CC CACCxCUrCIiC `CCMC3CC]CUCBCC[^CKCy>CPCRCC KC=ClCaC$CNC{̘CCCPCCC@CCYCzCeCXC9DBCvCTC uC9CCCd]CCywC*C~ CCCZCCC%4CC]CC4CCCC%LCGDWCqC#CfCDDDJD wD DD$#D dD DD DD"GD DDGDFD|DD' DBD+/D(rD)gD1D"D4D7D9_D0ND3rD;fD;4D; DAЮDODJ4DSBDLDKKDMDTҮDQBDX˾D\~0Dh Dc`Dc>qDicDo3@DnDdDwDzDtDwP`Dp*DD9D#D\2DDwDWDDDD^lD#DTDD Dx@D1SDDtDVDDƋD DtMD~fD֗D23DˆDD2DEUD(EdEFELE6EEEE";E'9E36E5E:GE7E<}EKENEWGETEZlEgEEOEEhZEEDEEeEWEEpEgEœEF-FcEE[D1VASA%}C37n@4 ^ClCOYo;/$BS{Bs CbBTBSC3K—AB|ƒs]BxBB`G2sA&?&BB;BzWgÐ?•HB &BؠC 4;B?<:@ZAB)AyKAA>B LnSo_BAo^BՓB5[BZB6'e/wB4JvBBbBJL B$5BA A=B+AKaBBnQAB7;BBO{RB@A8iBc;@ϪBBoAWB4B<5AJB-@-XB iBh,B`B>YBlyBq`BtAzBKBڸB8B/BB}tKBB_ABBqBB)BTBBbF0B9m"B-B( BBB{BBBeBpBCKGBB BJBBΩBtJBKCByBBϛBnCBCC2CDbCC C ;0$z( ~A1A|R A#پ^WgϞAXAȑyB$Q @ A{;hAPAAyKP=c?A@!V=s\?>%A&AAF:C@wq@sIAp'`A8ADKATh0@Kiп,ȫu@EAďYAo?RZo@"gA9Q@i/3A[Ar/D\3@UBp AJ@vAfƾ-sRb. AA\?]A垯A|?=o@"AJA5ApAC?LB@AjAYAArAAԬAgB BZB0BH'BqBBjiBcA.AݾnB'ANB:ݑBGBUBF+ByBT 2BBMfBBwBi?B/BBTBĴeB@B+B BA{C CC|C*OC)CL-cCNCvFCHCqCCwCCC}CwCLAz>B9žgBb$aHCB\CV^Ú@D ‘:"C-בA BpC#B\ »6DB-C;!tBO@ܫ) \H/&# kVBF%Jz6\]`J7RuAqVḼVY_ɖA8P Ibn*y?ŏY?o(4@{cnd"A .޸6VA'&@օA^k5As#K?¾yEE2?)]W9@t#\#@п;]@7]rҖ-;A^u=j@74?ղ)˽yI@\!>S)@Y@JAAM@-@ב@@E#@m'@gAg@cA|AAvA{Ax*AA1AB B RAB%A/A7l5`=Ϫr6~FI),k-gC\B;BF 9 Âm4!CѾCX':AWR¤J†@<=f9>¼ [«6†85C(Aؗ´duHOAuA݉ZC'F ݶ‘ nAsy{VBe˜@$Y]g§˜9?}PR@ Y£Z@ѱ*8C{0[B޶6ȏ[9zA}5A ¯]CEvBf\N-5%r8ڑB^:eAstAkB@(B4ࣚ}@p5GD@@cA j;?B2za?DԚA?ClC@1KABeDq\ҎlCIyAo0}]YzAF W_I[.̲}`IAIB&\Ͽ$u@!,HA<& E}?!ru@T@"?#޽=޺@E<Č15`jcA@ ;M>OYA`A`)bl۾Ź _p6+s?iRA )XA~?HFA@=C\@ @.>@@QW*] {d@ GZ-7ؕ'GA,~> I=U=e0H>|}vQ@]A5`D?r"@7?Ak,Y@O?_I߁0l=YB`aۘ3 S@A4A+C Y)B4 B!"A60zBrBCF*8=B+B8 =W% $BCv"8A1N-54>šQQA?{ۼB6CC;AcÙP8 E}Sa.A"{Au"ï%BZcpBB\5AGh%9An7' ŸeDm9J¦4AA.2(ZœZAQSF{A}#A@$AD&BC]ߝAmonB<}g,S,¢AA1A*Bڴ/tbBC<fAhK\NzG@+@;iG=/r@9p T@42?7fO[j-ECAx-BQTDW…®c-;S¨ABjABu:p¸ A;o-«7ޠ>\²^‹AS£;|[Y^…e A,n2C-BX%o8[ABA1š&yBU$#$?wr M<5{:?PB:¾4„UZ ^l;Bt2f^`'2B :@M,WFKo b)BfkB$&Aw2Bt%QAO?WGngA~XJrA(r&-mA PA.:zA€[cQtA+@Z%PCLNAk?Ƚ g^@WA^AtsrˆdQ2?%fwwdEl#bifXWA6nA9LAB{Am)Dh4~0AL'AiU⼍SKAZAHCZb2A(M+Y8*A?hbJkno=>??drnA\.#$ @_XTAv2˅WhBZt\@/Ay$Q5d;V AޞD:.@6_7LAqt =dͽg8Sz"]S?:̬$Q@[:~,t̜ Ateb\#߄])@@\UDvZ ;@?TF<:.DB. [~2*B*;BE7;BU}v5A kLB{-ì\tvRjE)d@¤$§-åtš”f[-5aTH?`Cs|:¶9!{nœB)m{B )%B<Œ ¡jB#´hϋ¸6ApNA  “q™=CBB}BϫBy m— AOY– ,$BJaIsV++lD~B%‹mBV*}ov(B@S'U“+>o@LA:Af>p*yBA:@WA\b@#?//*X B=v?鿂B[^GBAG@(&h>uj)8L//A4w>}VA(2=3AvhO*=UA]@d(nPYX@Nӡ]hf.?@HA&@}l ~A^f1P뿺FB@}_Y!?z?kˇ6 u4Sθ@>@@(3[?1 @nWM `;'?!#+A96@9A8m#!E('W>}"A@RoVCŚ‮n@sg~'\Ax6ߙlqDu>@b5)T:Kw왢i-ӿAM.տ`Vq`B|CDf´ÆBª|+HaLuDIaHBiÂ[S(ª5|㵝i6\ JNA*;Bn0LSX+zãC8BCƶBսu* (WC440b7Biw^}Š?%b?AA-=y½~AT"TAZB4@qG µ*šxxt½_/%Bh$•mBT˜gQbA_ ‹9Y‡1B5I9Q@FΘyBB:.[w_p:95zR?7W]gA͇J‚MHND@6ݕgrA9oA5VG$,@A*?QA"S 1??/+o@I@A$G\BAU?P \1@Auk]>=”1Ac@8^nAhd@!>A3&@ʵͿV`@᣿.5A{]~"@ @$)bHFI?ШfA+vɘ"RmxB94]37O>=358|"HA` 0@1j>cnCz#d{ó,B 1@0M A .pwB9&~TœCU(<§H7“d/AI2H0@œ¹|B-TABmB (-@m?0B|a$6(BpBNmRN0~:c/i …A76CA.c}AB&mgB@>A tBQ¥,BXy†+q JZAS6YBqyB6IIZ>ރ§kA.@H2$LtC8AbX?V|EAtN¦mX ~A&Cn<"93M80p xU>y!yBA‚ fIBEl\@ 6!ۊTz/Jjlr=14`AB;Z AHAy~YB2BO~B (۸cBMB At8A.;,kΎ@^FAAj8Aɦ \A2BA?F.;JB*,4i@Q>25@?$E{7w—׭dAZE*uAA^A5zAO!f  A[AoyB8@ A6ANh|@@3j!?,v|?ٍzp>@OL V@A?Ҹ_A%2|BG@£@+\8&BafAd&4C 2BEJUl+ǚB\f=SA³&CµB]bBoARr@:d2@ڍCLqr(F俹?BėzBsE^';<#חJ[”~A$BA10 B"BXCA'aBPoLVB3Atastropy-specreduce-05be828/specreduce/tests/test_background.py000066400000000000000000000335221510537250300247140ustar00rootroot00000000000000import astropy.units as u import numpy as np import pytest from astropy.nddata import NDData from specreduce.background import Background from specreduce.compat import Spectrum from specreduce.tracing import FlatTrace, ArrayTrace def test_background( mk_test_img_raw, mk_test_spec_no_spectral_axis, mk_test_spec_with_spectral_axis ): img = mk_test_img_raw image = mk_test_spec_no_spectral_axis image_um = mk_test_spec_with_spectral_axis # # Try combinations of extraction center, and even/odd # extraction aperture sizes. # trace_pos = 15 trace = FlatTrace(image, trace_pos) bkg_sep = 5 bkg_width = 2 # all the following should be equivalent, whether image's spectral axis # is in pixels or physical units: bg1 = Background(image, [trace - bkg_sep, trace + bkg_sep], width=bkg_width) bg2 = Background.two_sided(image, trace, bkg_sep, width=bkg_width) bg3 = Background.two_sided(image, trace_pos, bkg_sep, width=bkg_width) assert np.allclose(bg1.bkg_image().flux, bg2.bkg_image().flux) assert np.allclose(bg1.bkg_image().flux, bg3.bkg_image().flux) bg4 = Background(image_um, [trace - bkg_sep, trace + bkg_sep], width=bkg_width) bg5 = Background.two_sided(image_um, trace, bkg_sep, width=bkg_width) bg6 = Background.two_sided(image_um, trace_pos, bkg_sep, width=bkg_width) assert np.allclose(bg1.bkg_image().flux, bg4.bkg_image().flux) assert np.allclose(bg1.bkg_image().flux, bg5.bkg_image().flux) assert np.allclose(bg1.bkg_image().flux, bg6.bkg_image().flux) # test that creating a one_sided background works Background.one_sided(image, trace, bkg_sep, width=bkg_width) # test that passing a single trace works bg = Background(image, trace, width=bkg_width) # test that image subtraction works sub1 = image - bg1 sub2 = bg1.sub_image(image) sub3 = bg1.sub_image() assert np.allclose(sub1.flux, sub2.flux) assert np.allclose(sub2.flux, sub3.flux) sub4 = image_um - bg4 sub5 = bg4.sub_image(image_um) sub6 = bg4.sub_image() assert np.allclose(sub1.flux, sub4.flux) assert np.allclose(sub4.flux, sub5.flux) assert np.allclose(sub5.flux, sub6.flux) bkg_spec = bg1.bkg_spectrum() assert isinstance(bkg_spec, Spectrum) sub_spec = bg1.sub_spectrum() assert isinstance(sub_spec, Spectrum) # test that width==0 results in no background bg = Background.two_sided(image, trace, bkg_sep, width=0) assert np.all(bg.bkg_image().flux == 0) # test that any NaNs in input image (whether in or outside the window) don't # propagate to _bkg_array (which affects bkg_image and sub_image methods) or # the final 1D spectra. img[0, 0] = np.nan # out of window img[trace_pos, 0] = np.nan # in window stats = ["average", "median"] for st in stats: bg = Background(img, trace - bkg_sep, width=bkg_width, statistic=st) assert np.isnan(bg.image.flux).sum() == 2 assert np.isnan(bg._bkg_array).sum() == 0 assert np.isnan(bg.bkg_spectrum().flux).sum() == 0 assert np.isnan(bg.sub_spectrum().flux).sum() == 0 with pytest.warns(DeprecationWarning, match="bkg_statistic.*deprecated"): bg.bkg_spectrum(bkg_statistic="mean") def test_warnings_errors(mk_test_spec_no_spectral_axis): image = mk_test_spec_no_spectral_axis # image.shape (30, 10) with pytest.warns(match="background window extends beyond image boundaries"): Background.two_sided(image, 25, 4, width=3) # bottom of top window near/on top-edge of image (these should warn, but not fail) with pytest.warns(match="background window extends beyond image boundaries"): Background.two_sided(image, 25, 8, width=5) with pytest.warns(match="background window extends beyond image boundaries"): Background.two_sided(image, 25, 8, width=6) with pytest.warns(match="background window extends beyond image boundaries"): Background.two_sided(image, 25, 8, width=7) with pytest.warns(match="background window extends beyond image boundaries"): Background.two_sided(image, 7, 5, width=6) trace = ArrayTrace(image, trace=np.arange(10) + 20) # from 20 to 29 with pytest.warns(match="background window extends beyond image boundaries"): with pytest.raises( ValueError, match="background window does not remain in bounds across entire dispersion axis", ): # noqa # 20 + 10 - 3 = 27 (lower edge of window on-image at right side of trace) # 29 + 10 - 3 = 36 (lower edge of window off-image at right side of trace) Background.one_sided(image, trace, 10, width=3) with pytest.raises(ValueError, match="width must be positive"): Background.two_sided(image, 25, 2, width=-1) def test_trace_inputs(mk_test_img_raw): """ Tests for the input argument 'traces' to `Background`. This should accept a list of or a single Trace object, or a list of or a single (positive) number to define a FlatTrace. """ image = mk_test_img_raw # When `Background` object is created with no Trace object passed in it should # create a FlatTrace in the middle of the image (according to disp. axis) background = Background(image, width=5) assert np.all(background.traces[0].trace.data == image.shape[1] / 2.0) # FlatTrace(s) should be created if number or list of numbers is passed in for `traces` background = Background(image, 10.0, width=5) assert isinstance(background.traces[0], FlatTrace) assert background.traces[0].trace_pos == 10.0 traces = [10.0, 15] background = Background(image, traces, width=5) for i, trace_pos in enumerate(traces): assert background.traces[i].trace_pos == trace_pos # make sure error is raised if input for `traces` is invalid match_str = ( "objects, a number or list of numbers to define FlatTraces, " + "or None to use a FlatTrace in the middle of the image." ) with pytest.raises(ValueError, match=match_str): Background(image, "non_valid_trace_pos") class TestMasksBackground: """ Various test functions to test how masked and non-finite data is handled in `Background. """ def mk_img(self, nrows=4, ncols=5, nan_slices=None): """ Make a simple gradient image to test masking in Background. Optionally add NaNs to data with `nan_slices`. Returned array is in u.DN. """ img = np.tile((np.arange(1.0, ncols + 1)), (nrows, 1)) if nan_slices: # add nans in data for s in nan_slices: img[s] = np.nan return img * u.DN @pytest.mark.parametrize("mask", ["apply", "propagate", "zero_fill"]) def test_fully_masked_column(self, mask): """ Test background with some fully-masked columns (not fully masked image). In this case, the background value for that fully-masked column should be 0.0, with no error or warning raised. """ img = self.mk_img(nrows=10, ncols=10) img[:, 0:1] = np.nan bkg = Background(img, traces=FlatTrace(img, 6), mask_treatment=mask) assert np.all(bkg.bkg_image().data[:, 0:1] == 0.0) @pytest.mark.parametrize("mask", ["apply", "propagate"]) def test_fully_masked_image(self, mask): """ Test that the appropriate error is raised by `Background` when image is fully masked/NaN. """ with pytest.raises(ValueError, match="Image is fully masked."): # fully NaN image img = self.mk_img() * np.nan Background(img, traces=FlatTrace(self.mk_img(), 2), mask_treatment=mask) with pytest.raises(ValueError, match="Image is fully masked."): # fully masked image (should be equivalent) img = NDData(np.ones((4, 5)), mask=np.ones((4, 5), dtype=bool)) Background(img, traces=FlatTrace(self.mk_img(), 2), mask_treatment=mask) # Now test that an image that isn't fully masked, but is fully masked # within the window determined by `width`, produces the correct result. msg = "Image is fully masked within background window determined by `width`." with pytest.raises(ValueError, match=msg): img = self.mk_img(nrows=12, ncols=12, nan_slices=[np.s_[3:10, :]]) Background(img, traces=FlatTrace(img, 6), width=7) @pytest.mark.filterwarnings("ignore:background window extends beyond image boundaries") @pytest.mark.parametrize( "method,expected", [ ("apply", np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0])), ( "propagate", np.array([0.0, 2.0, 3.0, 0.0, 5.0, 6.0, 7.0, 0.0, 9.0, 10.0, 11.0, 12.0]), ), ( "zero_fill", np.array( [ 0.58333333, 2.0, 3.0, 2.33333333, 5.0, 6.0, 7.0, 7.33333333, 9.0, 10.0, 11.0, 12.0, ] ), ), ], ) def test_mask_treatment_bkg_img_spectrum(self, method, expected): """ This test function tests `Background.bkg_image` and `Background.bkg_spectrum` when there is masked data. It also tests background subtracting the image, and returning the spectrum of the background subtracted image. This test is parameterized over all currently implemented mask handling methods to test that they work as intended. The window size is set to use the entire image array, so warning about background window is ignored.""" img_size = 12 # square 12 x 12 image # make image, set some value to nan, which will be masked in the function image1 = self.mk_img( nrows=img_size, ncols=img_size, nan_slices=[np.s_[5:10, 0], np.s_[7:12, 3], np.s_[2, 7]] ) # also make an image that doesn't have nonf data values, but has # masked values at the same locations, to make sure they give the same # results mask = ~np.isfinite(image1) dat = self.mk_img(nrows=img_size, ncols=img_size) image2 = NDData(dat, mask=mask) for image in [image1, image2]: # construct a flat trace in center of image trace = FlatTrace(image, img_size / 2) # create 'Background' object with `mask_treatment` set # 'width' should be > size of image to use all pix (but warning will # be raised, which we ignore.) background = Background(image, mask_treatment=method, traces=trace, width=img_size + 1) # test background image matches 'expected' bk_img = background.bkg_image() # change this and following assertions to assert_quantity_allclose once # issue #213 is fixed np.testing.assert_allclose(bk_img.flux.value, np.tile(expected, (img_size, 1))) # test background spectrum matches 'expected' bk_spec = background.bkg_spectrum() np.testing.assert_allclose(bk_spec.flux.value, expected) def test_sub_bkg_image(self): """ Test that masked and non-finite data is handled correctly when subtracting background from image, for all currently implemented masking options. """ # make image, set some value to nan, which will be masked in the function image = self.mk_img( nrows=12, ncols=12, nan_slices=[np.s_[5:10, 0], np.s_[7:12, 3], np.s_[2, 7]] ) # Calculate a background value using mask_treatment = 'apply'. # For 'apply', the flag applies to how masked values are handled during # calculation of background for each column, but nonfinite data will # remain in input data array background_apply = Background( image, mask_treatment="apply", traces=FlatTrace(image, 6), width=2 ) subtracted_img_apply = background_apply.sub_image() assert np.all(np.isfinite(subtracted_img_apply.data) == np.isfinite(image.data)) # Calculate a background value using mask_treatment = 'propagate'. The input # 2d mask is reduced to a 1d mask to mask out full columns in the # presence of any nans - this means that (as tested above in # `test_mask_treatment_bkg_img_spectrum`) those columns will have 0.0 # background. In this case, image.mask is expanded to mask full # columns - the image itself will not have full columns set to np.nan, # so there are still valid background subtracted data values in this # case, but the corresponding mask for that entire column will be masked. background_propagate = Background( image, mask_treatment="propagate", traces=FlatTrace(image, 6), width=2 ) subtracted_img_propagate = background_propagate.sub_image() assert np.all(np.isfinite(subtracted_img_propagate.data) == np.isfinite(image.data)) # Calculate a background value using mask_treatment = 'zero_fill'. Data # values at masked locations are set to 0 in the image array, and the # background value calculated for that column will be subtracted # resulting in a negative value. The resulting background subtracted # image should be fully finite and the mask should be zero everywhere # (all unmasked) background_zero_fill = Background( image, mask_treatment="zero_fill", traces=FlatTrace(image, 6), width=2 ) subtracted_img_zero_fill = background_zero_fill.sub_image() assert np.all(np.isfinite(subtracted_img_zero_fill.data)) assert np.all(subtracted_img_zero_fill.mask == 0) astropy-specreduce-05be828/specreduce/tests/test_core.py000066400000000000000000000010511510537250300235150ustar00rootroot00000000000000import pytest from specreduce.core import SpecreduceOperation def test_sro_call(): sro = SpecreduceOperation() with pytest.raises(NotImplementedError): sro() def test_sro_as_function(): class TestSRO(SpecreduceOperation): def __call__(self, x): return x**2 assert TestSRO.as_function(6) == 36 class TestSRO(SpecreduceOperation): def __call__(self, *nargs): return 5 with pytest.raises(NotImplementedError, match="There is not a way"): TestSRO.as_function(6) == 36 astropy-specreduce-05be828/specreduce/tests/test_extinction.py000066400000000000000000000050601510537250300247550ustar00rootroot00000000000000import numpy as np import pytest from astropy import units as u from astropy.utils.exceptions import AstropyUserWarning from specreduce.calibration_data import ( AtmosphericExtinction, AtmosphericTransmission, SUPPORTED_EXTINCTION_MODELS ) @pytest.mark.remote_data def test_supported_models(): """ Test loading of supported models """ for model in SUPPORTED_EXTINCTION_MODELS: ext = AtmosphericExtinction(model=model) assert len(ext.extinction_mag) > 0 assert len(ext.transmission) > 0 @pytest.mark.remote_data def test_custom_mag_model(): """ Test creation of custom model from Quantity arrays """ wave = np.linspace(0.3, 2.0, 50) extinction = u.Magnitude(1. / wave, u.MagUnit(u.dimensionless_unscaled)) ext = AtmosphericExtinction(extinction=extinction, spectral_axis=wave * u.um) assert len(ext.extinction_mag) > 0 assert len(ext.transmission) > 0 @pytest.mark.remote_data def test_custom_raw_mag_model(): """ Test creation of custom model from Quantity arrays """ wave = np.linspace(0.3, 2.0, 50) extinction = 1. / wave * u.mag ext = AtmosphericExtinction(extinction=extinction, spectral_axis=wave * u.um) assert len(ext.extinction_mag) > 0 assert len(ext.transmission) > 0 @pytest.mark.remote_data def test_custom_linear_model(): """ Test creation of custom model from Quantity arrays """ wave = np.linspace(0.3, 2.0, 50) extinction = 1. / wave * u.dimensionless_unscaled ext = AtmosphericExtinction(extinction=extinction, spectral_axis=wave * u.um) assert len(ext.extinction_mag) > 0 assert len(ext.transmission) > 0 @pytest.mark.remote_data def test_unsupported_model(): """ Test loading of a nonexistent model """ with pytest.raises(ValueError, match='Requested extinction model,'): AtmosphericExtinction(model='bad_model') @pytest.mark.remote_data def test_missing_extinction_unit(): """ Test creation of custom model from Quantity arrays """ wave = np.linspace(0.3, 2.0, 50) extinction = 1. / wave with pytest.warns(AstropyUserWarning): ext = AtmosphericExtinction(extinction=extinction, spectral_axis=wave * u.um) assert len(ext.extinction_mag) > 0 assert len(ext.transmission) > 0 @pytest.mark.remote_data def test_transmission_model(): """ Test creating of default atmospheric transmission model """ ext = AtmosphericTransmission() assert len(ext.transmission) > 0 with pytest.warns(RuntimeWarning): assert len(ext.extinction_mag) > 0 astropy-specreduce-05be828/specreduce/tests/test_extract.py000066400000000000000000000411421510537250300242440ustar00rootroot00000000000000import numpy as np import pytest from astropy import units as u from astropy.modeling import models from astropy.nddata import NDData, VarianceUncertainty, UnknownUncertainty, StdDevUncertainty from astropy.tests.helper import assert_quantity_allclose from specreduce.background import Background from specreduce.compat import Spectrum from specreduce.extract import BoxcarExtract, HorneExtract, OptimalExtract, _align_along_trace from specreduce.tracing import FitTrace, FlatTrace, ArrayTrace def add_gaussian_source(image, amps=2, stddevs=2, means=None): """Modify `image.data` to add a horizontal spectrum across the image. Each column can have a different amplitude, stddev or mean position if these are arrays (otherwise, constant across image). """ nrows, ncols = image.shape if means is None: means = nrows // 2 if not isinstance(means, np.ndarray): means = np.ones(ncols) * means if not isinstance(amps, np.ndarray): amps = np.ones(ncols) * amps if not isinstance(stddevs, np.ndarray): stddevs = np.ones(ncols) * stddevs for i, col in enumerate(range(ncols)): mod = models.Gaussian1D(amplitude=amps[i], mean=means[i], stddev=stddevs[i]) image.data[:, i] = mod(np.arange(nrows)) def test_boxcar_extraction(mk_test_img): # Try combinations of extraction center, and even/odd extraction aperture sizes. image = mk_test_img trace = FlatTrace(image, 15.0) boxcar = BoxcarExtract(image, trace) spectrum = boxcar.spectrum assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 75.0)) assert spectrum.unit is not None and spectrum.unit == u.Jy trace.set_position(14.5) spectrum = boxcar() assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 72.5)) trace.set_position(14.7) spectrum = boxcar() assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 73.5)) trace.set_position(15.0) boxcar.width = 6 spectrum = boxcar() assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 90.0)) trace.set_position(14.5) spectrum = boxcar(width=6) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 87.0)) trace.set_position(15.0) spectrum = boxcar(width=4.5) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 67.5)) trace.set_position(15.0) spectrum = boxcar(width=4.7) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 70.5)) trace.set_position(14.3) spectrum = boxcar(width=4.7) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 67.15)) def test_boxcar_nonfinite_handling(mk_test_img): image = mk_test_img image.data[14, 2] = np.nan image.data[14, 4] = np.inf trace = FlatTrace(image, 15.0) spectrum = BoxcarExtract(image, trace, width=6, mask_treatment="ignore")() target = np.full_like(spectrum.flux.value, 90.0) target[2] = np.nan target[4] = np.inf np.testing.assert_equal(spectrum.flux.value, target) spectrum = BoxcarExtract(image, trace, width=6, mask_treatment="apply")() target[[2, 4]] = 91.2 np.testing.assert_allclose(spectrum.flux.value, target, rtol=1e-8) def test_boxcar_outside_image_condition(mk_test_img): # Trace is such that extraction aperture lays partially outside the image image = mk_test_img trace = FlatTrace(image, 3.0) boxcar = BoxcarExtract(image, trace, mask_treatment="apply") spectrum = boxcar(width=10.0) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 32.0)) boxcar = BoxcarExtract(image, trace, mask_treatment="ignore") spectrum = boxcar(width=10.0) assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 32.0)) def test_boxcar_array_trace(mk_test_img): image = mk_test_img trace_array = np.ones_like(image[1]) * 15.0 trace = ArrayTrace(image, trace_array) boxcar = BoxcarExtract(image, trace) spectrum = boxcar() assert np.allclose(spectrum.flux.value, np.full_like(spectrum.flux.value, 75.0)) def test_horne_image_validation(mk_test_img): # # Test HorneExtract scenarios specific to its use with an image of # type `~numpy.ndarray` (instead of the default `~astropy.nddata.NDData`). # image = mk_test_img trace = FlatTrace(image, 15.0) extract = OptimalExtract(image.data, trace) # equivalent to HorneExtract # an array-type image must come with a variance argument with pytest.raises(ValueError, match=r".*variance must be specified.*"): ext = extract() # an NDData-type image can't have an empty uncertainty attribute with pytest.raises(ValueError, match=r".*NDData object lacks uncertainty"): ext = extract(image=image) # a warning should be raised if uncertainty is StdDevUncertainty with pytest.warns(UserWarning, match="image NDData object's uncertainty"): err = StdDevUncertainty(np.ones_like(image)) image.uncertainty = err ext = extract(image=image) # an NDData-type image's uncertainty must be of type VarianceUncertainty # or type StdDevUncertainty with pytest.raises(ValueError, match=r".*unexpected uncertainty type.*"): err = UnknownUncertainty(np.ones_like(image)) image.uncertainty = err ext = extract(image=image) # an array-type image must have the same dimensions as its variance argument with pytest.raises(ValueError, match=r".*shapes must match.*"): # remember variance, mask, and unit args are only checked if image # object doesn't have those attributes (e.g., numpy and Quantity arrays) err = np.ones_like(image[0]) ext = extract(image=image.data, variance=err) # an array-type image must have the same dimensions as its mask argument with pytest.raises(ValueError, match=r".*shapes must match.*"): err = np.ones_like(image) mask = np.zeros_like(image[0]) ext = extract(image=image.data, variance=err, mask=mask) # an array-type image given without mask and unit arguments is fine # and produces an extraction with flux in DN and spectral axis in pixels err = np.ones_like(image) ext = extract(image=image.data, variance=err, mask=None, unit=None) assert ext.unit == u.Unit("DN") assert np.all(ext.spectral_axis == np.arange(image.shape[extract.disp_axis]) * u.pix) # ignore Astropy warning for extractions that aren't best fit with a Gaussian: @pytest.mark.filterwarnings("ignore:The fit may be unsuccessful") def test_horne_variance_errors(mk_test_img): image = mk_test_img trace = FlatTrace(image, 3.0) # all zeros are treated as non-weighted (i.e., as non-zero fluxes) image.uncertainty = VarianceUncertainty(np.zeros_like(image)) image.mask = np.zeros_like(image) extract = HorneExtract(image, trace) ext = extract.spectrum assert not np.all(ext == 0) # single zero value adjusts mask and does not raise error err = np.ones_like(image) err[0][0] = 0 image.uncertainty = VarianceUncertainty(err) ext = extract(image) assert not np.all(ext == 1) # single negative value raises error err = image.uncertainty.array err[0][0] = -1 with pytest.raises(ValueError, match="variance must be fully positive"): # remember variance, mask, and unit args are only checked if image # object doesn't have those attributes (e.g., numpy and Quantity arrays) ext = extract(image=image.data, variance=err, mask=image.mask, unit=u.Jy) @pytest.mark.filterwarnings("ignore:The fit may be unsuccessful") def test_horne_non_flat_trace(): # create a synthetic "2D spectrum" and its non-flat trace n_rows, n_cols = (10, 50) original = np.zeros((n_rows, n_cols)) original[n_rows // 2] = 1 # create small offsets along each column to specify a non-flat trace trace_offset = np.polyval([2e-3, -0.01, 0], np.arange(n_cols)).astype(int) exact_trace = n_rows // 2 - trace_offset # re-index the array with the offsets applied to the trace (make it non-flat): rows = np.broadcast_to(np.arange(n_rows)[:, None], original.shape) cols = np.broadcast_to(np.arange(n_cols), original.shape) roll_rows = np.mod(rows + trace_offset[None, :], n_rows) rolled = original[roll_rows, cols] # all zeros are treated as non-weighted (give non-zero fluxes) err = 0.1 * np.ones_like(rolled) mask = np.zeros_like(rolled).astype(bool) # unroll the trace using the Horne extract utility function for alignment: unrolled = _align_along_trace(rolled, n_rows // 2 - trace_offset) # ensure that mask is correctly unrolled back to its original alignment: np.testing.assert_allclose(unrolled, original) # Extract the spectrum from the non-flat image+trace extract_non_flat = HorneExtract( rolled, ArrayTrace(rolled, exact_trace), variance=err, mask=mask, unit=u.Jy )() # Also extract the spectrum from the image after alignment with a flat trace extract_flat = HorneExtract( unrolled, FlatTrace(unrolled, n_rows // 2), variance=err, mask=mask, unit=u.Jy )() # ensure both extractions are equivalent: assert_quantity_allclose(extract_non_flat.flux, extract_flat.flux) def test_horne_bad_profile(mk_test_img): image = mk_test_img trace = FlatTrace(image, 3.0) extract = HorneExtract( image.data, trace, spatial_profile="bad_profile_name", variance=np.ones(image.data.shape) ) with pytest.raises(ValueError, match="spatial_profile must be one of"): extract.spectrum extract = HorneExtract( image.data, trace, spatial_profile=models.Polynomial1D(2), variance=np.ones(image.data.shape), ) with pytest.raises(ValueError, match="spatial_profile must be a"): extract.spectrum def test_horne_nonfinite_column(mk_test_img): image = mk_test_img image.data[:, 4] = np.nan trace = FlatTrace(image, 3.0) extract = HorneExtract( image.data, trace, spatial_profile="gaussian", variance=np.ones(image.data.shape) ) sp = extract.spectrum assert np.isnan(sp.flux.value[4]) assert np.all(np.isfinite(sp.flux.value[:4])) assert np.all(np.isfinite(sp.flux.value[5:])) def test_horne_no_bkgrnd(mk_test_img): # Test HorneExtract when using bkgrd_prof=None image = mk_test_img trace = FlatTrace(image, 3.0) extract = HorneExtract(image.data, trace, bkgrd_prof=None, variance=np.ones(image.data.shape)) assert len(extract.spectrum.flux) == 10 def test_horne_interpolated_profile(mk_test_img): # basic test for HorneExtract using the spatial_profile == `interpolated_profile` # option add a perfectly gaussian source and make sure gaussian extraction # and self-profile extraction agree (since self=gaussian in this case) image = mk_test_img add_gaussian_source(image) # add source across image, flat trace trace = FlatTrace(image, image.shape[0] // 2) # horne extraction using spatial_profile=='Gaussian' horne_extract_gauss = HorneExtract( image.data, trace, spatial_profile="gaussian", bkgrd_prof=None, variance=np.ones(image.data.shape), ) # horne extraction with spatial_profile=='interpolated_profile' horne_extract_self = HorneExtract( image.data, trace, spatial_profile={"name": "interpolated_profile", "n_bins_interpolated_profile": 3}, bkgrd_prof=None, variance=np.ones(image.data.shape), ) assert_quantity_allclose(horne_extract_gauss.spectrum.flux, horne_extract_self.spectrum.flux) horne_extract_self = HorneExtract( image.data, trace, spatial_profile={"name": "interpolated_profile", "n_bins_interpolated_profile": 3}, variance=np.ones(image.data.shape), ) def test_horne_interpolated_profile_norm(mk_test_img): # ensure that when using spatial_profile == `interpolated_profile`, the fit profile # represents the shape as a funciton of wavelength, and correctly accounts # for variations in trace position and flux. image = mk_test_img nrows, ncols = image.shape # create sawtooth pattern trace. right now, the _align_along_trace function # will rectify the trace to the integer-pixel level, so in this test # case the specturm will be totally straightened out. trace_shape = np.ones(ncols) * nrows // 2 trace_shape[::2] += 4 trace = ArrayTrace(image, trace_shape) # add gaussian source to image with increasing amplitude and that follows # along the trace. looks like a sawtooth pattern of increasing brightness add_gaussian_source(image, amps=np.linspace(1, 5, image.shape[1]), means=trace_shape) # horne extraction with spatial_profile=='interpolated_profile' # also tests that non-default parameters in the input dictionary format work ex = HorneExtract( image.data, trace, spatial_profile={ "name": "interpolated_profile", "n_bins_interpolated_profile": 3, "interp_degree_interpolated_profile": (1, 1), }, bkgrd_prof=None, variance=np.ones(image.data.shape), ) # need to run produce extract.spectrum to access _interp_spatial_prof ex.spectrum # evaulate interpolated profile on entire grid interp_prof = ex._interp_spatial_prof(np.arange(ncols), np.arange(nrows)).T # the shifting position and amplitude should be accounted for, so the fit # spatial profile should just represent the shape as a function of # wavelength in this case, that is a gaussian with the area normalized at # each wavelength and a constant mean position # make sure that the fit spatial prof is normalized correctly assert_quantity_allclose(np.sum(interp_prof, axis=0), 1.0) # and that shifts in trace position are accounted for (to integer level) assert np.all(np.argmax(interp_prof, axis=0) == nrows // 2) def test_horne_interpolated_nbins_fails(mk_test_img): # make sure that HorneProfile spatial_profile='interpolated_profile' correctly # fails when the number of samples is greater than the size of the image image = mk_test_img trace = FlatTrace(image, 5) with pytest.raises(ValueError): ex = HorneExtract( image.data, trace, spatial_profile={"name": "interpolated_profile", "n_bins_interpolated_profile": 100}, ) ex.spectrum class TestMasksExtract: def mk_flat_gauss_img(self, nrows=200, ncols=160, nan_slices=None, add_noise=True): """ Makes a flat gaussian image for testing, with optional added gaussian nosie and optional data values set to NaN. Variance is included, which is required by HorneExtract. Returns a Spectrum with flux, spectral axis, and uncertainty. """ sigma_pix = 4 col_model = models.Gaussian1D(amplitude=1, mean=nrows / 2, stddev=sigma_pix) spec2dvar = np.ones((nrows, ncols)) noise = 0 if add_noise: np.random.seed(7) sigma_noise = 1 noise = np.random.normal(scale=sigma_noise, size=(nrows, ncols)) index_arr = np.tile(np.arange(nrows), (ncols, 1)) img = col_model(index_arr.T) + noise if nan_slices: # add nans in data for s in nan_slices: img[s] = np.nan wave = np.arange(0, img.shape[1], 1) objectspec = Spectrum( spectral_axis=wave * u.m, flux=img * u.Jy, uncertainty=VarianceUncertainty(spec2dvar * u.Jy * u.Jy), ) return objectspec def test_boxcar_fully_masked(self): """ Test that the appropriate error is raised by `BoxcarExtract` when image is fully masked/NaN. """ return img = self.mk_flat_gauss_img() trace = FitTrace(img) with pytest.raises(ValueError, match="Image is fully masked."): # fully NaN image img = np.zeros((4, 5)) * np.nan Background(img, traces=trace, width=2) with pytest.raises(ValueError, match="Image is fully masked."): # fully masked image (should be equivalent) img = NDData(np.ones((4, 5)), mask=np.ones((4, 5))) Background(img, traces=trace, width=2) # Now test that an image that isn't fully masked, but is fully masked # within the window determined by `width`, produces the correct result msg = "Image is fully masked within background window determined by `width`." with pytest.raises(ValueError, match=msg): img = self.mk_img(nrows=12, ncols=12, nan_slices=[np.s_[3:10, :]]) Background(img, traces=FlatTrace(img, 6), width=7) astropy-specreduce-05be828/specreduce/tests/test_image_parsing.py000066400000000000000000000075761510537250300254140ustar00rootroot00000000000000import numpy as np from astropy import units as u from specreduce.compat import Spectrum from specreduce.core import _ImageParser from specreduce.extract import HorneExtract from specreduce.tracing import FlatTrace # (for use inside tests) def compare_images(all_images, key, collection, compare='s1d'): # save default values used for spectral axis and uncertainty when they are not # available from the image object or provided by the user unc_def = np.ones_like(all_images['arr']) sax_def = np.arange(unc_def.shape[1]) * u.pix # was input converted to Spectrum? assert isinstance(collection[key], Spectrum), (f"image '{key}' not " "of type Spectrum") # do key's fluxes match its comparison's fluxes? assert np.allclose(collection[key].data, collection[compare].data), (f"images '{key}' and " f"'{compare}' have unequal " "flux values") # if the image came with a spectral axis, was it kept? if not, was the # default spectral axis in pixels applied? sax_provided = hasattr(all_images[key], 'spectral_axis') assert np.allclose(collection[key].spectral_axis, (all_images[key].spectral_axis if sax_provided else sax_def)), (f"spectral axis of image '{key}' does " f"not match {'input' if sax_provided else 'default'}") # if the image came with an uncertainty, was it kept? if not, was the # default uncertainty created? unc_provided = hasattr(all_images[key], 'uncertainty') assert np.allclose(collection[key].uncertainty.array, (all_images[key].uncertainty.array if unc_provided else unc_def)), (f"uncertainty of image '{key}' does " f"not match {'input' if unc_provided else 'default'}") # were masks created despite none being given? (all indices should be False) assert (getattr(collection[key], 'mask', None) is not None), f"no mask was created for image '{key}'" assert np.all(collection[key].mask == 0), ("mask not all False " f"for image '{key}'") # test consistency of general image parser results def test_parse_general(all_images): all_images_parsed = {k: _ImageParser()._parse_image(im) for k, im in all_images.items()} for key in all_images_parsed.keys(): compare_images(all_images, key, all_images_parsed) # use verified general image parser results to check HorneExtract's image parser def test_parse_horne(all_images): # save default values used for uncertainty when it is # available from the image object or provided by the user unc_def = np.ones_like(all_images['arr']) # HorneExtract's parser is more stringent than the general one, hence the # separate test. Given proper inputs, both should produce the same results. images_collection = {k: {} for k in all_images.keys()} for key, col in images_collection.items(): img = all_images[key] col['general'] = _ImageParser()._parse_image(img) if hasattr(all_images[key], 'uncertainty'): defaults = {} else: # save default values of attributes used in general parser when # they are not available from the image object. HorneExtract always # requires a variance, so it's chosen here to be on equal footing # with the general case defaults = {'variance': unc_def, 'mask': ~np.isfinite(img), 'unit': getattr(img, 'unit', u.DN)} col[key] = HorneExtract(img, FlatTrace(img, 2))._parse_image(img, **defaults) compare_images(all_images, key, col, compare='general') astropy-specreduce-05be828/specreduce/tests/test_line_matching.py000066400000000000000000000076411510537250300254010ustar00rootroot00000000000000import numpy as np import pytest from astropy.wcs import WCS from astropy.modeling import models from astropy.nddata import StdDevUncertainty from specutils.fitting import fit_generic_continuum from specreduce.calibration_data import load_pypeit_calibration_lines from specreduce.compat import Spectrum from specreduce.extract import BoxcarExtract from specreduce.line_matching import match_lines_wcs, find_arc_lines from specreduce.tracing import FlatTrace from specreduce.utils.synth_data import make_2d_arc_image @pytest.fixture def mk_test_data(): """ Create test data for the line matching routines. """ non_linear_header = { 'CTYPE1': 'AWAV-GRA', # Grating dispersion function with air wavelengths 'CUNIT1': 'Angstrom', # Dispersion units 'CRPIX1': 519.8, # Reference pixel [pix] 'CRVAL1': 7245.2, # Reference value [Angstrom] 'CDELT1': 2.956, # Linear dispersion [Angstrom/pix] 'PV1_0': 4.5e5, # Grating density [1/m] 'PV1_1': 1, # Diffraction order 'PV1_2': 27.0, # Incident angle [deg] 'PV1_3': 1.765, # Reference refraction 'PV1_4': -1.077e6, # Refraction derivative [1/m] 'CTYPE2': 'PIXEL', # Spatial detector coordinates 'CUNIT2': 'pix', # Spatial units 'CRPIX2': 1, # Reference pixel 'CRVAL2': 0, # Reference value 'CDELT2': 1 # Spatial units per pixel } linear_header = { 'CTYPE1': 'AWAV', # Grating dispersion function with air wavelengths 'CUNIT1': 'Angstrom', # Dispersion units 'CRPIX1': 519.8, # Reference pixel [pix] 'CRVAL1': 7245.2, # Reference value [Angstrom] 'CDELT1': 2.956, # Linear dispersion [Angstrom/pix] 'CTYPE2': 'PIXEL', # Spatial detector coordinates 'CUNIT2': 'pix', # Spatial units 'CRPIX2': 1, # Reference pixel 'CRVAL2': 0, # Reference value 'CDELT2': 1 # Spatial units per pixel } non_linear_wcs = WCS(header=non_linear_header) linear_wcs = WCS(header=linear_header) tilt_mod = models.Legendre1D(degree=2, c0=50, c1=0, c2=100) match_im = make_2d_arc_image( nx=1400, ny=1024, linelists=['HeI', 'NeI'], wcs=linear_wcs, line_fwhm=5, tilt_func=tilt_mod, amplitude_scale=5e-4 ) arclist = load_pypeit_calibration_lines(['HeI', 'NeI'])['wavelength'] trace = FlatTrace(match_im, 512) arc_sp = BoxcarExtract(match_im, trace, width=5).spectrum arc_sp.uncertainty = StdDevUncertainty(np.sqrt(arc_sp.flux).value) continuum = fit_generic_continuum(arc_sp, median_window=51) arc_sub = Spectrum( spectral_axis=arc_sp.spectral_axis, flux=arc_sp.flux - continuum(arc_sp.spectral_axis) ) arc_sub.uncertainty = arc_sp.uncertainty return linear_wcs, non_linear_wcs, arclist, arc_sub @pytest.mark.remote_data @pytest.mark.filterwarnings("ignore:No observer defined on WCS") @pytest.mark.filterwarnings("ignore:Model is linear in parameters") def test_find_arc_lines(mk_test_data): """ Test the find_arc_lines routine. """ _, _, _, arc_sub = mk_test_data lines = find_arc_lines(arc_sub, fwhm=5, window=5, noise_factor=5) assert len(lines) > 1 @pytest.mark.remote_data @pytest.mark.filterwarnings("ignore:No observer defined on WCS") @pytest.mark.filterwarnings("ignore:Model is linear in parameters") def test_match_lines_wcs(mk_test_data): """ Test the match_lines_wcs routine. """ linear_wcs, _, arclist, arc_sub = mk_test_data lines = find_arc_lines(arc_sub, fwhm=5, window=5, noise_factor=5) matched_lines = match_lines_wcs( pixel_positions=lines['centroid'], catalog_wavelengths=arclist, spectral_wcs=linear_wcs.spectral, tolerance=5 ) assert len(matched_lines) > 1 astropy-specreduce-05be828/specreduce/tests/test_linelists.py000066400000000000000000000052341510537250300246020ustar00rootroot00000000000000import pytest from specreduce.calibration_data import load_pypeit_calibration_lines @pytest.mark.remote_data def test_pypeit_single(): """ Test to load a single linelist from ``pypeit`` by passing a string. """ line_tab = load_pypeit_calibration_lines('HeI', cache=True, show_progress=False) assert line_tab is not None assert "HeI" in line_tab['ion'] assert sorted(list(line_tab.columns)) == [ 'Instr', 'NIST', 'Source', 'amplitude', 'ion', 'wavelength' ] @pytest.mark.remote_data def test_pypeit_list(): """ Test to load and combine a set of linelists from ``pypeit`` by passing a list. """ line_tab = load_pypeit_calibration_lines(['HeI', 'NeI'], cache=True, show_progress=False) assert line_tab is not None assert "HeI" in line_tab['ion'] assert "NeI" in line_tab['ion'] @pytest.mark.remote_data def test_pypeit_comma_list(): """ Test to load and combine a set of linelists from ``pypeit`` by passing a comma-separated list. """ line_tab = load_pypeit_calibration_lines("HeI, NeI", cache=True, show_progress=False) assert line_tab is not None assert "HeI" in line_tab['ion'] assert "NeI" in line_tab['ion'] @pytest.mark.remote_data def test_pypeit_nonexisting_lamp(): """ Test to make sure a warning is raised if the lamp list includes a bad lamp name. """ with pytest.warns(UserWarning, match='NeJ not in the list'): load_pypeit_calibration_lines(["HeI", "NeJ"], cache=True, show_progress=False) @pytest.mark.remote_data def test_pypeit_empty(): """ Test to make sure None is returned if an empty list is passed. """ with pytest.warns(UserWarning, match='No calibration lines'): line_tab = load_pypeit_calibration_lines([], cache=True, show_progress=False) assert line_tab is None @pytest.mark.remote_data def test_pypeit_none(): """ Test to make sure None is returned if calibration lamp list is None. """ line_tab = load_pypeit_calibration_lines(None, cache=True, show_progress=False) assert line_tab is None @pytest.mark.remote_data def test_pypeit_input_validation(): """ Check that bad inputs for ``pypeit`` linelists raise the appropriate warnings and exceptions """ with pytest.raises(ValueError, match='.*Invalid calibration lamps specification.*'): _ = load_pypeit_calibration_lines({}, cache=True, show_progress=False) with pytest.warns() as record: _ = load_pypeit_calibration_lines(['HeI', 'ArIII'], cache=True, show_progress=False) if not record: pytest.fails("Expected warning about nonexistant linelist for ArIII.") astropy-specreduce-05be828/specreduce/tests/test_mask_treatment.py000066400000000000000000000135301510537250300256100ustar00rootroot00000000000000from copy import deepcopy import pytest import numpy as np from astropy.units import DN from astropy.nddata import NDData from specreduce.core import _ImageParser def mk_image(): image = np.ones((3, 5)) mask = np.zeros(image.shape, dtype=bool) image[1, 3] = np.nan mask[[0, 1], [1, 0]] = 1 return NDData(image * DN, mask=mask) def test_bad_option(): image = mk_image() with pytest.raises(ValueError, match="'mask_treatment' must be one of"): _ImageParser()._parse_image(image, disp_axis=1, mask_treatment="bad") def test_bad_mask_type(): image = mk_image() image.mask = image.mask.astype(float) with pytest.raises(ValueError, match="'mask' must be a boolean or integer array."): _ImageParser()._parse_image(image, disp_axis=1, mask_treatment="apply") def test_apply(): image = mk_image() parsed_image = _ImageParser()._parse_image(deepcopy(image), disp_axis=1, mask_treatment="apply") np.testing.assert_array_equal(parsed_image.data, image.data) mask_true = np.zeros(image.data.shape, dtype=bool) mask_true[[0, 1, 1], [1, 0, 3]] = 1 np.testing.assert_array_equal(parsed_image.mask, mask_true) image.mask = None parsed_image = _ImageParser()._parse_image(deepcopy(image), disp_axis=1, mask_treatment="apply") np.testing.assert_array_equal(parsed_image.data, image.data) mask_true = np.zeros(image.data.shape, dtype=bool) mask_true[1, 3] = 1 np.testing.assert_array_equal(parsed_image.mask, mask_true) def test_ignore(): image = mk_image() parsed_image = _ImageParser()._parse_image(image, disp_axis=1, mask_treatment="ignore") np.testing.assert_array_equal(parsed_image.data, image.data) mask_true = np.zeros(image.data.shape, dtype=bool) np.testing.assert_array_equal(parsed_image.mask, mask_true) image.mask = None parsed_image = _ImageParser()._parse_image(image, disp_axis=1, mask_treatment="ignore") np.testing.assert_array_equal(parsed_image.data, image.data) mask_true = np.zeros(image.data.shape, dtype=bool) np.testing.assert_array_equal(parsed_image.mask, mask_true) def test_propagate(): image = mk_image() parsed_image = _ImageParser()._parse_image(image, disp_axis=1, mask_treatment="propagate") np.testing.assert_array_equal(parsed_image.data, image.data) mask_true = np.zeros(image.data.shape, dtype=bool) mask_true[:, [0, 1, 3]] = 1 np.testing.assert_array_equal(parsed_image.mask, mask_true) image.mask = None parsed_image = _ImageParser()._parse_image(image, disp_axis=1, mask_treatment="propagate") np.testing.assert_array_equal(parsed_image.data, image.data) mask_true = np.zeros(image.data.shape, dtype=bool) mask_true[:, 3] = 1 np.testing.assert_array_equal(parsed_image.mask, mask_true) def test_zero_fill(): image = mk_image() parsed_image = _ImageParser()._parse_image(image, disp_axis=1, mask_treatment="zero_fill") image_true = np.ones(image.data.shape) image_true[[0, 1, 1], [1, 0, 3]] = 0 np.testing.assert_array_equal(parsed_image.data, image_true) mask_true = np.zeros(image.data.shape, dtype=bool) np.testing.assert_array_equal(parsed_image.mask, mask_true) image.mask = None parsed_image = _ImageParser()._parse_image(image, disp_axis=1, mask_treatment="zero_fill") image_true = np.ones(image.data.shape) image_true[1, 3] = 0 np.testing.assert_array_equal(parsed_image.data, image_true) mask_true = np.zeros(image.data.shape, dtype=bool) np.testing.assert_array_equal(parsed_image.mask, mask_true) def test_nan_fill(): image = mk_image() parsed_image = _ImageParser()._parse_image(image, disp_axis=1, mask_treatment="nan_fill") image_true = np.ones(image.data.shape) image_true[[0, 1, 1], [1, 0, 3]] = np.nan np.testing.assert_array_equal(parsed_image.data, image_true) mask_true = np.zeros(image.data.shape, dtype=bool) np.testing.assert_array_equal(parsed_image.mask, mask_true) image.mask = None parsed_image = _ImageParser()._parse_image(image, disp_axis=1, mask_treatment="nan_fill") image_true = np.ones(image.data.shape) image_true[1, 3] = np.nan np.testing.assert_array_equal(parsed_image.data, image_true) mask_true = np.zeros(image.data.shape, dtype=bool) np.testing.assert_array_equal(parsed_image.mask, mask_true) def test_apply_nan_only(): image = mk_image() parsed_image = _ImageParser()._parse_image(image, disp_axis=1, mask_treatment="apply_nan_only") np.testing.assert_array_equal(parsed_image.data, image.data) mask_true = np.zeros(image.data.shape, dtype=bool) mask_true[1, 3] = 1 np.testing.assert_array_equal(parsed_image.mask, mask_true) image.mask = None parsed_image = _ImageParser()._parse_image(image, disp_axis=1, mask_treatment="apply_nan_only") np.testing.assert_array_equal(parsed_image.data, image.data) mask_true = np.zeros(image.data.shape, dtype=bool) mask_true[1, 3] = 1 np.testing.assert_array_equal(parsed_image.mask, mask_true) def test_apply_mask_only(): image = mk_image() parsed_image = _ImageParser()._parse_image(image, disp_axis=1, mask_treatment="apply_mask_only") np.testing.assert_array_equal(parsed_image.data, image.data) mask_true = np.zeros(image.data.shape, dtype=bool) mask_true[[0, 1], [1, 0]] = 1 np.testing.assert_array_equal(parsed_image.mask, mask_true) image.mask = None parsed_image = _ImageParser()._parse_image(image, disp_axis=1, mask_treatment="apply_mask_only") np.testing.assert_array_equal(parsed_image.data, image.data) mask_true = np.zeros(image.data.shape, dtype=bool) np.testing.assert_array_equal(parsed_image.mask, mask_true) def test_fully_masked(): image = mk_image() image.mask[:] = 1 with pytest.raises(ValueError, match="Image is fully masked."): _ImageParser()._parse_image(image, disp_axis=1, mask_treatment="apply") astropy-specreduce-05be828/specreduce/tests/test_specphot_stds.py000066400000000000000000000020761510537250300254570ustar00rootroot00000000000000import pytest from astropy.utils.exceptions import AstropyUserWarning from specreduce.calibration_data import load_MAST_calspec, load_onedstds @pytest.mark.remote_data def test_load_MAST(): sp = load_MAST_calspec("g191b2b_005.fits", show_progress=False) assert sp is not None assert len(sp.spectral_axis) > 0 @pytest.mark.remote_data def test_load_MAST_bad_filename(): with pytest.warns(AstropyUserWarning, match="Downloading of"): sp = load_MAST_calspec("j191b2b_005.fits", show_progress=False) assert sp is None @pytest.mark.remote_data def test_load_onedstds(): sp = load_onedstds() assert sp is not None assert len(sp.spectral_axis) > 0 @pytest.mark.remote_data def test_load_onedstds_bad_dataset(): with pytest.warns(AstropyUserWarning, match="Specfied dataset,"): sp = load_onedstds("snffactory") assert sp is None @pytest.mark.remote_data def test_load_onedstds_bad_specfile(): with pytest.warns(AstropyUserWarning, match="Can't load"): sp = load_onedstds(specfile="FG131.dat") assert sp is None astropy-specreduce-05be828/specreduce/tests/test_synth_data.py000066400000000000000000000122631510537250300247320ustar00rootroot00000000000000import pytest from astropy import units as u from astropy.modeling import models from astropy.nddata import CCDData from astropy.wcs import WCS from specreduce.utils.synth_data import make_2d_trace_image, make_2d_arc_image, make_2d_spec_image def test_make_2d_trace_image(): ccdim = make_2d_trace_image( nx=3000, ny=1000, background=5, trace_center=None, trace_order=3, trace_coeffs={'c0': 0, 'c1': 50, 'c2': 100}, profile=models.Gaussian1D(amplitude=100, stddev=10) ) assert ccdim.data.shape == (1000, 3000) assert isinstance(ccdim, CCDData) @pytest.mark.remote_data @pytest.mark.filterwarnings("ignore:No observer defined on WCS") def test_make_2d_arc_image_defaults(): ccdim = make_2d_arc_image() assert isinstance(ccdim, CCDData) @pytest.mark.remote_data @pytest.mark.filterwarnings("ignore:No observer defined on WCS") def test_make_2d_arc_pass_wcs(): nx = 3000 ny = 1000 wave_unit = u.Angstrom extent = [3000, 6000] # test passing a valid WCS with dispersion along X wcs = WCS(naxis=2) wcs.wcs.ctype[0] = 'WAVE' wcs.wcs.ctype[1] = 'PIXEL' wcs.wcs.cunit[0] = wave_unit wcs.wcs.cunit[1] = u.pixel wcs.wcs.crval[0] = extent[0] wcs.wcs.cdelt[0] = (extent[1] - extent[0]) / nx wcs.wcs.crval[1] = 0 wcs.wcs.cdelt[1] = 1 ccdim = make_2d_arc_image( nx=nx, ny=ny, extent=None, wave_unit=None, wcs=wcs ) assert ccdim.data.shape == (1000, 3000) assert isinstance(ccdim, CCDData) # test passing a tilt model tilt_model = models.Chebyshev1D(degree=2, c0=50, c1=0, c2=100) ccdim = make_2d_arc_image( nx=nx, ny=ny, extent=None, wave_unit=None, wcs=wcs, tilt_func=tilt_model ) assert ccdim.data.shape == (1000, 3000) assert isinstance(ccdim, CCDData) # make sure WCS without spectral axis gets rejected wcs.wcs.ctype[0] = 'PIXEL' assert wcs.spectral.naxis == 0 with pytest.raises(ValueError, match='Provided WCS must have a spectral axis'): ccdim = make_2d_arc_image( nx=nx, ny=ny, extent=None, wave_unit=None, wcs=wcs ) # test passing valid WCS with dispersion along Y while using air wavelengths wcs = WCS(naxis=2) wcs.wcs.ctype[1] = 'AWAV' wcs.wcs.ctype[0] = 'PIXEL' wcs.wcs.cunit[1] = wave_unit wcs.wcs.cunit[0] = u.pixel wcs.wcs.crval[1] = extent[0] wcs.wcs.cdelt[1] = (extent[1] - extent[0]) / nx wcs.wcs.crval[0] = 0 wcs.wcs.cdelt[0] = 1 ccdim = make_2d_arc_image( nx=ny, ny=nx, extent=None, wave_unit=None, wave_air=True, wcs=wcs, tilt_func=tilt_model ) assert ccdim.data.shape == (3000, 1000) assert isinstance(ccdim, CCDData) # make sure no WCS and no extent gets rejected with pytest.raises(ValueError, match='Must specify either a wavelength extent or a WCS'): ccdim = make_2d_arc_image( nx=nx, ny=ny, extent=None, wave_unit=None, wcs=None ) # make sure if extent is provided, it has the right length with pytest.raises(ValueError, match='Wavelength extent must be of length 2'): ccdim = make_2d_arc_image( nx=nx, ny=ny, extent=[1, 2, 3], wave_unit=None, wcs=None ) # make sure a 1D WCS gets rejected wcs = WCS(naxis=1) wcs.wcs.ctype[0] = 'WAVE' wcs.wcs.cunit[0] = wave_unit wcs.wcs.crval[0] = extent[0] wcs.wcs.cdelt[0] = (extent[1] - extent[0]) / nx with pytest.raises(ValueError, match='WCS must have NAXIS=2 for a 2D image'): ccdim = make_2d_arc_image( nx=nx, ny=ny, extent=None, wave_unit=None, wcs=wcs ) # make sure a WCS with no spectral axis gets rejected wcs = WCS(naxis=2) wcs.wcs.ctype[1] = 'PIXEL' wcs.wcs.ctype[0] = 'PIXEL' wcs.wcs.cunit[1] = u.pixel wcs.wcs.cunit[0] = u.pixel wcs.wcs.crval[1] = extent[0] wcs.wcs.cdelt[1] = (extent[1] - extent[0]) / nx wcs.wcs.crval[0] = 0 wcs.wcs.cdelt[0] = 1 with pytest.raises(ValueError, match='Provided WCS must have a spectral axis'): ccdim = make_2d_arc_image( nx=nx, ny=ny, extent=None, wave_unit=None, wcs=wcs ) # make sure invalid wave_unit is caught with pytest.raises(ValueError, match='Wavelength unit must be a length unit'): ccdim = make_2d_arc_image( nx=nx, ny=ny, extent=[100, 300], wave_unit=u.pixel ) # make sure a non-polynomial tilt_func gets rejected with pytest.raises( ValueError, match='The only tilt functions currently supported are 1D polynomials' ): ccdim = make_2d_arc_image( tilt_func=models.Gaussian1D ) @pytest.mark.remote_data @pytest.mark.filterwarnings("ignore:No observer defined on WCS") def test_make_2d_spec_image_defaults(): ccdim = make_2d_spec_image() assert isinstance(ccdim, CCDData) astropy-specreduce-05be828/specreduce/tests/test_tracing.py000066400000000000000000000501751510537250300242270ustar00rootroot00000000000000import numpy as np import pytest from astropy.modeling import fitting, models from astropy.nddata import NDData import astropy.units as u from specreduce.utils.synth_data import make_2d_trace_image from specreduce.tracing import Trace, FlatTrace, ArrayTrace, FitTrace IM = make_2d_trace_image() def mk_img(nrows=200, ncols=160, nan_slices=None, add_noise=True): """ Makes a gaussian image for testing, with optional added gaussian nosie and optional data values set to NaN. """ # NOTE: Will move this to a fixture at some point. sigma_pix = 4 col_model = models.Gaussian1D(amplitude=1, mean=nrows / 2, stddev=sigma_pix) noise = 0 if add_noise: np.random.seed(7) sigma_noise = 1 noise = np.random.normal(scale=sigma_noise, size=(nrows, ncols)) index_arr = np.tile(np.arange(nrows), (ncols, 1)) img = col_model(index_arr.T) + noise if nan_slices: # add nans in data for s in nan_slices: img[s] = np.nan return img * u.DN # test basic trace class def test_basic_trace(): t_pos = IM.shape[0] / 2 t = Trace(IM) assert t[0] == t_pos assert t[0] == t[-1] assert t.shape[0] == IM.shape[1] t.shift(100) assert t[0] == 600.0 t.shift(-1000) assert np.ma.is_masked(t[0]) # test flat traces def test_flat_trace(): t = FlatTrace(IM, 550.0) assert t.trace_pos == 550 assert t[0] == 550.0 assert t[0] == t[-1] t.set_position(400.0) assert t[0] == 400.0 def test_negative_flat_trace_err(): # make sure correct error is raised when trying to create FlatTrace with # negative trace_pos with pytest.raises(ValueError, match="must be positive."): FlatTrace(IM, trace_pos=-1) with pytest.raises(ValueError, match="must be positive."): FlatTrace(IM, trace_pos=0) # test array traces def test_array_trace(): arr = np.ones_like(IM[0]) * 550.0 t = ArrayTrace(IM, arr) assert t[0] == 550.0 assert t[0] == t[-1] t.shift(100) assert t[0] == 650.0 t.shift(-1000) assert np.ma.is_masked(t[0]) arr_long = np.ones(5000) * 550.0 t_long = ArrayTrace(IM, arr_long) assert t_long.shape[0] == IM.shape[1] arr_short = np.ones(50) * 550.0 t_short = ArrayTrace(IM, arr_short) assert t_short[0] == 550.0 assert np.ma.is_masked(t_short[-1]) assert t_short.shape[0] == IM.shape[1] # make sure nonfinite data in input `trace` is masked arr[0:5] = np.nan t = ArrayTrace(IM, arr) assert np.all(t.trace.mask[0:5]) assert np.all(t.trace.mask[5:] == 0) # test fitted traces @pytest.mark.filterwarnings("ignore:Model is linear in parameters") def test_fit_trace(): # create image (process adapted from compare_extractions.ipynb) np.random.seed(7) nrows = 200 ncols = 160 sigma_pix = 4 sigma_noise = 1 col_model = models.Gaussian1D(amplitude=1, mean=nrows / 2, stddev=sigma_pix) noise = np.random.normal(scale=sigma_noise, size=(nrows, ncols)) index_arr = np.tile(np.arange(nrows), (ncols, 1)) img = col_model(index_arr.T) + noise # calculate trace on normal image t = FitTrace(img, bins=20) # test shifting shift_up = int(-img.shape[0] / 4) t_shift_up = t.trace + shift_up shift_out = img.shape[0] t.shift(shift_up) assert np.sum(t.trace == t_shift_up) == t.trace.size, "valid shift failed" t.shift(shift_out) assert t.trace.mask.all(), "invalid values not masked" # test peak_method and trace_model options tg = FitTrace(img, bins=20, peak_method="gaussian", trace_model=models.Legendre1D(3)) tc = FitTrace(img, bins=20, peak_method="centroid", trace_model=models.Chebyshev1D(2)) tm = FitTrace(img, bins=20, peak_method="max", trace_model=models.Spline1D(degree=3)) # traces should all be close to 100 # (values may need to be updated on changes to seed, noise, etc.) assert np.max(abs(tg.trace - 100)) < sigma_pix assert np.max(abs(tc.trace - 100)) < 3 * sigma_pix assert np.max(abs(tm.trace - 100)) < 6 * sigma_pix with pytest.raises(ValueError): t = FitTrace(img, peak_method="invalid") window = 10 guess = int(nrows / 2) img_win_nans = img.copy() img_win_nans[guess - window : guess + window] = np.nan # ensure float bin values trigger a warning but no issues otherwise with pytest.warns(UserWarning, match="TRACE: Converting bins to int"): FitTrace(img, bins=20.0, trace_model=models.Polynomial1D(2)) # ensure non-equipped models are rejected with pytest.raises(ValueError, match=r"trace_model must be one of"): FitTrace(img, trace_model=models.Hermite1D(3)) # ensure a bin number below 4 is rejected with pytest.raises(ValueError, match="bins must be >= 4"): FitTrace(img, bins=3) # ensure a bin number below degree of trace model is rejected with pytest.raises(ValueError, match="bins must be > "): FitTrace(img, bins=4, trace_model=models.Chebyshev1D(5)) # ensure number of bins greater than number of dispersion pixels is rejected with pytest.raises(ValueError, match=r"bins must be <"): FitTrace(img, bins=ncols + 1) def test_fit_trace_gaussian_all_zero(): """ Test fit_trace when peak_method is 'gaussian', which uses DogBoxLSQFitter for the fit for each bin peak and does not work well with all-zero columns. In this case, an all zero bin should fall back to NaN to for its' peak to be filtered out in the final fit for the trace. """ img = mk_img(ncols=100) # add some all-zero columns so there is an all-zero bin img[:, 10:20] = 0 t = FitTrace(img, bins=10, peak_method='gaussian') # this is a pretty flat trace, so make sure the fit reflects that assert np.all((t.trace >= 99) & (t.trace <= 101)) @pytest.mark.filterwarnings("ignore:The fit may be unsuccessful") @pytest.mark.filterwarnings("ignore:Model is linear in parameters") class TestMasksTracing: """ There are three currently implemented options for masking in FitTrace: filter, omit, and zero_fill. Trace, FlatTrace, and ArrayTrace do not have `mask_treatment` options as input because masked/nonfinite values in the data are not relevant for those trace types as they are not affected by masked input data. The tests in this class test masking options for FitTrace, as well as some basic tests (errors, etc) for the other trace types. """ def test_flat_and_basic_trace_mask(self): """ Mask handling is not relevant for basic and flat trace - nans or masked values in the input image will not impact the trace value. The attribute should be initialized though, and be one of the valid options ([None] in this case), for consistancy with all other Specreduce operations. Note that unlike FitTrace, a fully-masked image should NOT result in an error raised because the trace does not depend on the data. """ img = mk_img(nrows=5, ncols=5) basic_trace = Trace(img) assert basic_trace.mask_treatment is None flat_trace = FlatTrace(img, trace_pos=2) assert flat_trace.mask_treatment is None arr = [1, 2, np.nan, 3, 4] array_trace = ArrayTrace(img, arr) assert array_trace.mask_treatment is None def test_array_trace_masking(self): """ The `trace` input to ArrayTrace can be a masked array, or an array containing nonfinite data which will be converted to a masked array. Additionally, if any padding needs to be added, the returned trace will be a masked array. Otherwise, it should be a regular array. Even though an ArrayTrace may have nans or masked values in the input 1D array for the trace, `mask_treatment_method` refers to how masked values in the input data should be treated. Nans / masked values passed in the array trace should be considered intentional, so also test that `mask_treatment` is initialized to None. """ img = mk_img(nrows=10, ncols=10) # non-finite data in input trace should be masked out trace_arr = np.array((1, 2, np.nan, 4, 5)) array_trace = ArrayTrace(img, trace_arr) assert array_trace.trace.mask[2] assert isinstance(array_trace.trace, np.ma.MaskedArray) # and combined with any input masked data trace_arr = np.ma.MaskedArray([1, 2, np.nan, 4, 5], mask=[1, 0, 0, 0, 0]) array_trace = ArrayTrace(img, trace_arr) assert array_trace.trace.mask[0] assert array_trace.trace.mask[2] assert isinstance(array_trace.trace, np.ma.MaskedArray) # check that mask_treatment is None as there are no valid choices assert array_trace.mask_treatment is None # check that if array is fully finite and not masked, that the returned # trace is a normal array, not a masked array trace = ArrayTrace(img, np.ones(100)) assert isinstance(trace.trace, np.ndarray) assert not isinstance(trace.trace, np.ma.MaskedArray) # ensure correct warning is raised when entire trace is masked. trace_arr = np.ma.MaskedArray([1, 2, np.nan, 4, 5], mask=[1, 1, 0, 1, 1]) with pytest.warns(UserWarning, match=r"Entire trace array is masked."): array_trace = ArrayTrace(img, trace_arr) def test_fit_trace_fully_masked_image(self): """ Test that the correct warning is raised when a fully masked image is encountered. Also test that when a non-fully masked image is provided, but `window` is set and the image is fully masked within that window, that the correct error is raised. """ # make simple gaussian image. img = mk_img() # create same-shaped variations of image with nans in data array # which will be masked within FitTrace. nrows = 200 ncols = 160 img_all_nans = np.tile(np.nan, (nrows, ncols)) # error on trace of all-nan image with pytest.raises(ValueError, match=r"Image is fully masked. Check for invalid values."): FitTrace(img_all_nans) window = 10 guess = int(nrows / 2) img_win_nans = img.copy() img_win_nans[guess - window : guess + window] = np.nan # error on trace of otherwise valid image with all-nan window around guess with pytest.raises(ValueError, match="pixels in window region are masked"): FitTrace(img_win_nans, guess=guess, window=window) def test_fit_trace_fully_masked_columns_warn_msg(self): """ Test that the correct warning message is raised when fully masked columns (in a not-fully-masked image) are encountered in FitTrace. These columns will be set to NaN and filtered from the final all-bin fit (as tested in test_fit_trace_fully_masked_cols), but a warning message is raised. """ img = mk_img() # test that warning (dependent on choice of `peak_method`) is raised when a # few bins are masked, and that theyre listed individually mask = np.zeros(img.shape, dtype=bool) mask[:, 100] = 1 mask[:, 20] = 1 mask[:, 30] = 1 nddat = NDData(data=img, mask=mask, unit=u.DN) match_str = "All pixels in bins 20, 30, 100 are fully masked. Setting bin peaks to NaN." with pytest.warns(UserWarning, match=match_str): FitTrace(nddat, peak_method="max") with pytest.warns(UserWarning, match=match_str): FitTrace(nddat, peak_method="centroid") with pytest.warns(UserWarning, match=match_str): FitTrace(nddat, peak_method="gaussian") # and when many bins are masked, that the message is consolidated mask = np.zeros(img.shape, dtype=bool) mask[:, 0:21] = 1 nddat = NDData(data=img, mask=mask, unit=u.DN) with pytest.warns( UserWarning, match="All pixels in bins " "0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ..., 20 are " "fully masked. Setting bin peaks to NaN.", ): FitTrace(nddat) @pytest.mark.filterwarnings("ignore:All pixels in bins") @pytest.mark.parametrize("mask_treatment", ["apply", "propagate", "apply_nan_only"]) def test_fit_trace_fully_masked_cols(self, mask_treatment): """ Create a test image with some fully-nan/masked columns, and test that when the final fit to all bin peaks is done for the trace, that these fully-masked columns are set to NaN and filtered during the final all-bin fit. Ignore the warning that is produced when this case is encountered (that is tested in `test_fit_trace_fully_masked_cols_warn_msg`.) """ img = mk_img(nrows=10, ncols=11) # set some columns fully to nan, which will be masked out img[:, 7] = np.nan img[:, 4] = np.nan img[:, 0] = np.nan # also create an image that doesn't have nans in the data, but # is masked in the same locations, to make sure that is equivilant. # test peak_method = 'max' truth = [ 1.6346154, 2.2371795, 2.8397436, 3.4423077, 4.0448718, 4.6474359, 5.25, 5.8525641, 6.4551282, 7.0576923, 7.6602564, ] max_trace = FitTrace(img, peak_method="max", mask_treatment=mask_treatment) np.testing.assert_allclose(truth, max_trace.trace, atol=0.1) # peak_method = 'gaussian' truth = [ 1.947455, 2.383634, 2.8198131, 3.2559921, 3.6921712, 4.1283502, 4.5645293, 5.0007083, 5.4368874, 5.8730665, 6.3092455, ] max_trace = FitTrace(img, peak_method="gaussian", mask_treatment=mask_treatment) np.testing.assert_allclose(truth, max_trace.trace, atol=0.1) # peak_method = 'centroid' truth = [ 2.5318835, 2.782069, 3.0322546, 3.2824402, 3.5326257, 3.7828113, 4.0329969, 4.2831824, 4.533368, 4.7835536, 5.0337391, ] max_trace = FitTrace(img, peak_method="centroid", mask_treatment=mask_treatment) np.testing.assert_allclose(truth, max_trace.trace, atol=0.1) @pytest.mark.filterwarnings("ignore:All pixels in bins") @pytest.mark.parametrize( "peak_method,expected", [ ("max", [5.0, 3.0, 5.0, 5.0, 7.0, 5.0, np.nan, 5.0, 5.0, 5.0, 2.0, 5.0]), ("gaussian", [5.0, 5.0, 5.0, 5.0, 5.0, 5.0, np.nan, 5.0, 5.0, 5.0, 1.576, 5.0]), ( "centroid", [ 4.27108332, 2.24060342, 4.27108332, 4.27108332, 6.66827608, 4.27108332, np.nan, 4.27108332, 4.27108332, 4.27108332, 1.19673467, 4.27108332, ], ), ], ) def test_mask_treatment_apply(self, peak_method, expected): """ Test for mask_treatment=apply for FitTrace. With this masking option, masked and non-finite data should be filtered when determining bin/column peak. Fully masked bins should be omitted from the final all-bin-peak fit for the Trace. Parametrized over different `peak_method` options. """ # Make an image with some non-finite values. image1 = mk_img( nan_slices=[np.s_[4:8, 1:2], np.s_[2:7, 4:5], np.s_[:, 6:7], np.s_[3:9, 10:11]], nrows=10, ncols=12, add_noise=False, ) # Also make an image that doesn't have nonf data values, but has masked # values at the same locations, to make sure they give the same results. mask = ~np.isfinite(image1) dat = mk_img(nrows=10, ncols=12, add_noise=False) image2 = NDData(dat, mask=mask) for imgg in [image1, image2]: # run FitTrace, with the testing-only flag _save_bin_peaks_testing set # to True to return the bin peak values before fitting the trace trace = FitTrace(imgg, peak_method=peak_method, _save_bin_peaks_testing=True) x_bins, y_bins = trace._bin_peaks np.testing.assert_allclose(y_bins, expected, atol=0.1) # check that final fit to all bins, accouting for fully-masked bins, # matches the trace fitter = fitting.LMLSQFitter() mask = np.isfinite(y_bins) all_bin_fit = fitter(trace.trace_model, x_bins[mask], y_bins[mask]) all_bin_fit = all_bin_fit((np.arange(12))) np.testing.assert_allclose(trace.trace, all_bin_fit) @pytest.mark.filterwarnings("ignore:All pixels in bins") @pytest.mark.parametrize("peak_method", ["max", "gaussian", "centroid"]) def test_mask_treatment_unsupported(self, peak_method): """ Test to ensure the unsupported mask treatment methods for FitTrace raise a `ValueError`. Parametrized over different `peak_method` options. """ image = mk_img( nan_slices=[np.s_[4:8, 1:2], np.s_[2:7, 4:5], np.s_[:, 6:7], np.s_[3:9, 10:11]], nrows=10, ncols=12, add_noise=False, ) for method in "ignore", "zero_fill", "nan_fill", "apply_mask_only": with pytest.raises(ValueError): FitTrace(image, peak_method=peak_method, mask_treatment=method) @pytest.mark.filterwarnings("ignore:All pixels in bins") @pytest.mark.parametrize( "peak_method,expected", [ ("max", [5.0, np.nan, 5.0, 5.0, np.nan, 5.0, np.nan, 5.0, 5.0, 5.0, np.nan, 5.0]), ("gaussian", [5.0, np.nan, 5.0, 5.0, np.nan, 5.0, np.nan, 5.0, 5.0, 5.0, np.nan, 5.0]), ( "centroid", [ 4.27108332, np.nan, 4.27108332, 4.27108332, np.nan, 4.27108332, np.nan, 4.27108332, 4.27108332, 4.27108332, np.nan, 4.27108332, ], ), ], ) def test_mask_treatment_propagate(self, peak_method, expected): """ Test for mask_treatment=`propagate` for FitTrace. Columns (assuming disp_axis==1) with any masked data values will be fully masked and therefore not contribute to the bin peaks. Parametrized over different `peak_method` options. """ # Make an image with some non-finite values. image1 = mk_img( nan_slices=[np.s_[4:8, 1:2], np.s_[2:7, 4:5], np.s_[:, 6:7], np.s_[3:9, 10:11]], nrows=10, ncols=12, add_noise=False, ) # Also make an image that doesn't have non-finite data values, but has masked # values at the same locations, to make sure those cases are equivalent mask = ~np.isfinite(image1) dat = mk_img(nrows=10, ncols=12, add_noise=False) image2 = NDData(dat, mask=mask) for imgg in [image1, image2]: # run FitTrace, with the testing-only flag _save_bin_peaks_testing set # to True to return the bin peak values before fitting the trace trace = FitTrace( imgg, peak_method=peak_method, mask_treatment="propagate", _save_bin_peaks_testing=True, ) x_bins, y_bins = trace._bin_peaks np.testing.assert_allclose(y_bins, expected) # check that final fit to all bins, accouting for fully-masked bins, # matches the trace fitter = fitting.LevMarLSQFitter() mask = np.isfinite(y_bins) all_bin_fit = fitter(trace.trace_model, x_bins[mask], y_bins[mask]) all_bin_fit = all_bin_fit((np.arange(12))) np.testing.assert_allclose(trace.trace, all_bin_fit) astropy-specreduce-05be828/specreduce/tests/test_utils.py000066400000000000000000000177551510537250300237470ustar00rootroot00000000000000import astropy.units as u import numpy as np import pytest from astropy.modeling import fitting, models from astropy.nddata import NDData from specreduce.compat import SPECUTILS_LT_2, Spectrum from specreduce.tracing import FitTrace from specreduce.utils.utils import measure_cross_dispersion_profile def mk_gaussian_img(nrows=20, ncols=16, mean=10, stddev=4): """ Makes a simple horizontal gaussian image.""" # note: this should become a fixture eventually, since other tests use # similar functions to generate test data. np.random.seed(7) col_model = models.Gaussian1D(amplitude=1, mean=mean, stddev=stddev) index_arr = np.tile(np.arange(nrows), (ncols, 1)) return col_model(index_arr.T) def mk_img_non_flat_trace(nrows=40, ncols=100, amp=10, stddev=2): """ Makes an image with a gaussian source that has a non-flat trace dispersed along the x axis. """ spec2d = np.zeros((nrows, ncols)) for ii in range(spec2d.shape[1]): mgaus = models.Gaussian1D(amplitude=amp, mean=(9.+(20/spec2d.shape[1])*ii), stddev=stddev) rg = np.arange(0, spec2d.shape[0], 1) gaus = mgaus(rg) spec2d[:, ii] = gaus return spec2d class TestMeasureCrossDispersionProfile(): @pytest.mark.parametrize('pixel', [None, 1, [1, 2, 3]]) @pytest.mark.parametrize('width', [10, 9]) def test_measure_cross_dispersion_profile(self, pixel, width): """ Basic test for `measure_cross_dispersion_profile`. Parametrized over different options for `pixel` to test using all wavelengths, a single wavelength, and a set of wavelengths, as well as different input types (plain array, quantity, Spectrum, and NDData), as well as `width` to use a window of all rows and a smaller window. """ # test a few input formats images = [] mean = 5.0 stddev = 4.0 dat = mk_gaussian_img(nrows=10, ncols=10, mean=mean, stddev=stddev) images.append(dat) # test unitless images.append(dat * u.DN) images.append(NDData(dat * u.DN)) if SPECUTILS_LT_2: kwargs = {} else: kwargs = {"spectral_axis_index": dat.ndim - 1} images.append(Spectrum(flux=dat * u.DN, **kwargs)) for img in images: # use a flat trace at trace_pos=10, a window of width 10 around the trace # and use all 20 columns in image to create an average (median) # cross dispersion profile cdp = measure_cross_dispersion_profile(img, width=width, pixel=pixel) # make sure that if we fit a gaussian to the measured average profile, # that we get out the same profile that was used to create the image. # this should be exact since theres no noise in the image fitter = fitting.LevMarLSQFitter() mod = models.Gaussian1D() fit_model = fitter(mod, np.arange(width), cdp) assert fit_model.mean.value == np.where(cdp == max(cdp))[0][0] assert fit_model.stddev.value == stddev # test passing in a FlatTrace, and check the profile cdp = measure_cross_dispersion_profile(img, width=width, pixel=pixel) fit_model = fitter(mod, np.arange(width), cdp) assert fit_model.mean.value == np.where(cdp == max(cdp))[0][0] np.testing.assert_allclose(fit_model.stddev.value, stddev) @pytest.mark.filterwarnings("ignore:Model is linear in parameters") def test_cross_dispersion_profile_non_flat_trace(self): """ Test measure_cross_dispersion_profile with a non-flat trace. Tests with 'align_along_trace' set to both True and False, to account for the changing center of the trace and measure the true profile shape, or to 'blur' the profile, respectivley. """ image = mk_img_non_flat_trace() # fit the trace trace_fit = FitTrace(image) # when not aligning along trace and using the entire image # rows for the window, the center of the profile should follow # the shape of the trace peak_locs = [9, 10, 12, 13, 15, 16, 17, 19, 20, 22, 23, 24, 26, 27, 29] for i, pixel in enumerate(range(0, image.shape[1], 7)): profile = measure_cross_dispersion_profile(image, trace=trace_fit, width=None, pixel=pixel, align_along_trace=False, statistic='average') peak_loc = (np.where(profile == max(profile))[0][0]) assert peak_loc == peak_locs[i] # when align_along_trace = True, the shape of the profile should # not change since (there is some wiggling around though due to the # fact that the trace is rolled to the nearest integer value. this can # be smoothed with an interpolation option later on, but it is 'rough' # for now). In this test case, the peak positions will all either # be at pixel 20 or 21. for i, pixel in enumerate(range(0, image.shape[1], 7)): profile = measure_cross_dispersion_profile(image, trace=trace_fit, width=None, pixel=pixel, align_along_trace=True, statistic='average') peak_loc = (np.where(profile == max(profile))[0][0]) assert peak_loc in [20, 21] def test_errors_warnings(self): img = mk_gaussian_img(nrows=10, ncols=10) with pytest.raises(ValueError, match='`crossdisp_axis` must be 0 or 1'): measure_cross_dispersion_profile(img, crossdisp_axis=2) with pytest.raises(ValueError, match='`trace` must be Trace object, ' 'number to specify the location ' 'of a FlatTrace, or None to use ' 'center of image.'): measure_cross_dispersion_profile(img, trace='not a trace or a number') with pytest.raises(ValueError, match="`statistic` must be 'median' " "or 'average'."): measure_cross_dispersion_profile(img, statistic='n/a') with pytest.raises(ValueError, match='Both `pixel` and `pixel_range` ' 'can not be set simultaneously.'): measure_cross_dispersion_profile(img, pixel=2, pixel_range=(2, 3)) with pytest.raises(ValueError, match='`pixels` must be an integer, ' 'or list of integers to specify ' 'where the crossdisperion profile ' 'should be measured.'): measure_cross_dispersion_profile(img, pixel='str') with pytest.raises(ValueError, match='`pixel_range` must be a tuple ' 'of integers.'): measure_cross_dispersion_profile(img, pixel_range=(2, 3, 5)) with pytest.raises(ValueError, match='Pixels chosen to measure cross ' 'dispersion profile are out of ' 'image bounds.'): measure_cross_dispersion_profile(img, pixel_range=(2, 12)) with pytest.raises(ValueError, match='`width` must be an integer, ' 'or None to use all ' 'cross-dispersion pixels.'): measure_cross_dispersion_profile(img, width='.') astropy-specreduce-05be828/specreduce/tests/test_wavecal1d.py000066400000000000000000000324171510537250300244460ustar00rootroot00000000000000# specreduce/tests/test_wavecal1d.py import astropy.units as u import numpy as np import pytest from astropy.modeling import models from astropy.nddata import StdDevUncertainty from matplotlib import pyplot as plt from matplotlib.figure import Figure from numpy import array from specreduce.compat import Spectrum from specreduce.wavecal1d import WavelengthCalibration1D ref_pixel = 250 pix_bounds = (0, 500) p2w = models.Shift(-ref_pixel) | models.Polynomial1D(degree=3, c0=1, c1=0.2, c2=0.001) @pytest.fixture def mk_lines(): obs_lines = ref_pixel + array([1, 2, 5, 8, 10]) cat_lines = p2w(ref_pixel + array([1, 3, 5, 7, 8, 10])) return obs_lines, cat_lines @pytest.fixture def mk_matched_lines(): obs_lines = ref_pixel + array([1, 2, 5, 8, 10]) cat_lines = p2w(obs_lines) return obs_lines, cat_lines @pytest.fixture def mk_wc(mk_lines): obs_lines, cat_lines = mk_lines return WavelengthCalibration1D( obs_lines=obs_lines, line_lists=cat_lines, pix_bounds=(0, 10), ref_pixel=ref_pixel, ) @pytest.fixture def mk_good_wc_with_transform(mk_lines): obs_lines, cat_lines = mk_lines wc = WavelengthCalibration1D( obs_lines=obs_lines, line_lists=cat_lines, pix_bounds=pix_bounds, ref_pixel=ref_pixel, ) wc.solution.p2w = p2w return wc @pytest.fixture def mk_arc(): return Spectrum( flux=np.ones(pix_bounds[1]) * u.DN, spectral_axis=np.arange(pix_bounds[1]) * u.pix, uncertainty=StdDevUncertainty(np.ones(pix_bounds[1])), ) def test_init(mk_arc, mk_lines): arc = mk_arc obs_lines, cat_lines = mk_lines WavelengthCalibration1D(arc_spectra=arc, line_lists=cat_lines, ref_pixel=ref_pixel) WavelengthCalibration1D( obs_lines=obs_lines, line_lists=cat_lines, pix_bounds=(0, 10), ref_pixel=ref_pixel, ) with pytest.raises(ValueError, match="Only one of arc_spectra or obs_lines can be provided."): WavelengthCalibration1D(arc_spectra=arc, obs_lines=obs_lines, ref_pixel=ref_pixel) arc = Spectrum( flux=np.array([[1, 2, 3, 4, 5]]) * u.DN, spectral_axis=np.array([1, 2, 3, 4, 5]) * u.angstrom, ) with pytest.raises(ValueError, match="The arc spectrum must be one dimensional."): WavelengthCalibration1D(arc_spectra=arc, ref_pixel=ref_pixel) with pytest.raises(ValueError, match="Must give pixel bounds when"): WavelengthCalibration1D(obs_lines=obs_lines, ref_pixel=ref_pixel) def test_init_line_list(mk_arc): arc = mk_arc WavelengthCalibration1D(arc_spectra=arc, line_lists=["ArI"]) WavelengthCalibration1D(arc_spectra=arc, line_lists="ArI") WavelengthCalibration1D(arc_spectra=arc, line_lists=[array([0.1])]) WavelengthCalibration1D(arc_spectra=arc, line_lists=array([0.1])) WavelengthCalibration1D(arc_spectra=[arc, arc], line_lists=[["ArI"], ["ArI"]]) WavelengthCalibration1D(arc_spectra=[arc, arc], line_lists=["ArI", ["ArI"]]) WavelengthCalibration1D(arc_spectra=[arc, arc], line_lists=["ArI", "ArI"]) WavelengthCalibration1D(arc_spectra=[arc, arc], line_lists=[array([0.1]), array([0.1])]) WavelengthCalibration1D(arc_spectra=[arc, arc], line_lists=[array([0.1, 0.3]), ["ArI"]]) with pytest.raises(ValueError, match="The number of line lists"): WavelengthCalibration1D(arc_spectra=[arc, arc], line_lists=[["ArI"]]) def test_find_lines(mocker, mk_arc): wc = WavelengthCalibration1D(arc_spectra=mk_arc) mock_find_arc_lines = mocker.patch("specreduce.wavecal1d.find_arc_lines") mock_find_arc_lines.return_value = {"centroid": np.array([5.0]) * u.angstrom} wc.find_lines(fwhm=2.0, noise_factor=1.5) assert wc._obs_lines is not None assert len(wc._obs_lines) == 1 wc = WavelengthCalibration1D() with pytest.raises(ValueError, match="Must provide arc spectra to find lines."): wc.find_lines(fwhm=2.0, noise_factor=1.5) def test_fit_lines(mk_matched_lines): lo, lc = mk_matched_lines wc = WavelengthCalibration1D(pix_bounds=pix_bounds, ref_pixel=ref_pixel) wc.fit_lines(pixels=lo, wavelengths=lc) assert wc.solution.p2w is not None assert wc.solution.p2w[1].degree == wc.degree wc = WavelengthCalibration1D( obs_lines=lo, line_lists=lc, pix_bounds=pix_bounds, ref_pixel=ref_pixel ) wc.fit_lines(pixels=lo, wavelengths=lc, match_cat=True, match_obs=True) assert wc.solution.p2w is not None assert wc.solution.p2w[1].degree == wc.degree wc = WavelengthCalibration1D(pix_bounds=pix_bounds, ref_pixel=ref_pixel) with pytest.warns(UserWarning, match="The degree of the polynomial"): wc.fit_lines(degree=5, pixels=lo[:3], wavelengths=lc[:3]) with pytest.raises(ValueError, match="Cannot fit without catalog"): wc.fit_lines(pixels=lo, wavelengths=lc, match_cat=True, match_obs=True) with pytest.raises(ValueError, match="Cannot fit without observed"): wc.fit_lines(pixels=lo, wavelengths=lc, match_cat=False, match_obs=True) def test_observed_lines(mk_lines): wc = WavelengthCalibration1D() assert wc.observed_lines is None obs_lines, cat_lines = mk_lines wc = WavelengthCalibration1D(obs_lines=obs_lines, pix_bounds=pix_bounds, ref_pixel=ref_pixel) assert len(wc.observed_lines) == 1 assert wc.observed_lines[0].shape == (len(obs_lines), 2) assert wc.observed_lines[0].mask.shape == (len(obs_lines), 2) np.testing.assert_allclose(wc.observed_lines[0].data[:, 0], obs_lines) assert np.all(wc.observed_lines[0].mask[:, 0] == 0) wc.observed_lines = obs_lines assert len(wc.observed_lines) == 1 assert wc.observed_lines[0].mask.shape == (len(obs_lines), 2) np.testing.assert_allclose(wc.observed_lines[0].data[:, 0], obs_lines) assert np.all(wc.observed_lines[0].mask[:, 0] == 0) wc.observed_lines = wc.observed_lines assert len(wc.observed_lines) == 1 assert wc.observed_lines[0].mask.shape == (len(obs_lines), 2) np.testing.assert_allclose(wc.observed_lines[0].data[:, 0], obs_lines) assert np.all(wc.observed_lines[0].mask[:, 0] == 0) # Line locations and amplitudes assert wc.observed_line_locations[0].shape == (len(obs_lines),) np.testing.assert_allclose(wc.observed_line_locations[0], obs_lines) assert wc.observed_line_amplitudes[0].shape == (len(obs_lines),) np.testing.assert_allclose(wc.observed_line_amplitudes[0], 0.0) def test_catalog_lines(mk_lines): wc = WavelengthCalibration1D(ref_pixel=ref_pixel) assert wc.catalog_lines is None obs_lines, cat_lines = mk_lines wc = WavelengthCalibration1D( obs_lines=obs_lines, line_lists=cat_lines, pix_bounds=pix_bounds, ref_pixel=ref_pixel ) assert len(wc.catalog_lines) == 1 assert wc.catalog_lines[0].shape == (len(cat_lines), 2) np.testing.assert_allclose(wc.catalog_lines[0].data[:, 0], cat_lines) assert np.all(wc.catalog_lines[0].data[:, 1] == 0) wc.catalog_lines = cat_lines assert len(wc.catalog_lines) == 1 np.testing.assert_allclose(wc.catalog_lines[0].data[:, 0], cat_lines) assert np.all(wc.catalog_lines[0].data[:, 1] == 0) wc.catalog_lines = wc.catalog_lines assert len(wc.catalog_lines) == 1 np.testing.assert_allclose(wc.catalog_lines[0].data[:, 0], cat_lines) assert np.all(wc.catalog_lines[0].data[:, 1] == 0) def test_fit_lines_raises_error_for_mismatched_sizes(): pixels = array([2, 4, 6]) wavelengths = p2w(array([2, 4, 5, 6])) wc = WavelengthCalibration1D(pix_bounds=pix_bounds, ref_pixel=ref_pixel) with pytest.raises(ValueError, match="The sizes of pixel and wavelength arrays must match."): wc.fit_lines(pixels=pixels, wavelengths=wavelengths) def test_fit_lines_raises_error_for_insufficient_lines(): pixels = [5] wavelengths = p2w(pixels) wc = WavelengthCalibration1D(pix_bounds=pix_bounds, ref_pixel=ref_pixel) with pytest.raises(ValueError, match="Need at least two lines for a fit"): wc.fit_lines(pixels=pixels, wavelengths=wavelengths) def test_fit_lines_raises_error_for_missing_pixel_bounds(): pixels = [2, 4, 6, 8] wavelengths = p2w(pixels) wc = WavelengthCalibration1D(ref_pixel=ref_pixel) with pytest.raises(ValueError, match="Cannot fit without pixel bounds set."): wc.fit_lines(pixels=pixels, wavelengths=wavelengths) def test_fit_global(): p2w = models.Shift(-ref_pixel) | models.Polynomial1D(degree=3, c0=650, c1=50.0, c2=-0.001) lines_obs = ref_pixel + array([2, 4, 4.5, 5, 6, 6.3, 8]) lines_cat = p2w(ref_pixel + array([1, 2, 2.3, 4, 5, 6, 6.3, 7, 8, 9, 10])) wavelength_bounds = (649, 651) dispersion_bounds = (49, 51) wc = WavelengthCalibration1D( obs_lines=lines_obs, line_lists=lines_cat, pix_bounds=pix_bounds, ref_pixel=ref_pixel ) ws = wc.fit_dispersion(wavelength_bounds, dispersion_bounds, popsize=10, refine_fit=True) np.testing.assert_allclose(ws.p2w[1].parameters, [650.0, 50.0, -0.001, 0.0], atol=1e-4) assert wc._fit is not None assert wc._fit.success assert wc.solution.p2w is not None wc = WavelengthCalibration1D( obs_lines=lines_obs, line_lists=lines_cat, pix_bounds=pix_bounds, ref_pixel=ref_pixel ) wc.fit_dispersion(wavelength_bounds, dispersion_bounds, popsize=10, refine_fit=False) def test_rms(mk_good_wc_with_transform): wc = mk_good_wc_with_transform assert np.isclose(wc.rms(space="wavelength"), 0) # Perfect match, so RMS should be zero assert np.isclose(wc.rms(space="pixel"), 0) # Perfect match, so RMS should be zero with pytest.raises(ValueError, match="Space must be either 'pixel' or 'wavelength'"): wc.rms(space="wavelenght") def test_remove_unmatched_lines(mk_good_wc_with_transform): wc = mk_good_wc_with_transform wc.match_lines() wc.remove_unmatched_lines() assert wc.catalog_lines[0].size == wc.observed_lines[0].size def test_plot_lines_with_valid_input(): wc = WavelengthCalibration1D(ref_pixel=ref_pixel) wc.observed_lines = [np.ma.masked_array([100, 200, 300], mask=[False, True, False])] wc._cat_lines = wc.observed_lines fig = wc._plot_lines(kind="observed", frames=0, figsize=(8, 4), plot_labels=True) assert isinstance(fig, Figure) assert fig.axes[0].has_data() fig = wc._plot_lines(kind="catalog", frames=0, figsize=(8, 4), plot_labels=True) assert isinstance(fig, Figure) assert fig.axes[0].has_data() fig, ax = plt.subplots(1, 1) fig = wc._plot_lines(kind="catalog", frames=0, axes=ax, plot_labels=True) assert isinstance(fig, Figure) assert fig.axes[0].has_data() fig, axs = plt.subplots(1, 2) fig = wc._plot_lines(kind="catalog", frames=0, axes=axs, plot_labels=True) assert isinstance(fig, Figure) assert fig.axes[0].has_data() fig = wc._plot_lines(kind="observed", frames=0, axes=axs, plot_labels=True) assert isinstance(fig, Figure) assert fig.axes[0].has_data() def test_plot_lines_raises_for_missing_transform(mk_wc): wc = mk_wc with pytest.raises(ValueError, match="Cannot map between pixels and"): wc._plot_lines(kind="observed", map_x=True) def test_plot_lines_calls_transform_correctly(mk_good_wc_with_transform): wc = mk_good_wc_with_transform wc._plot_lines(kind="observed", map_x=True) wc._plot_lines(kind="catalog", map_x=True) def test_plot_catalog_lines(mk_wc): wc = mk_wc wc.catalog_lines = [np.ma.masked_array([400, 500, 600], mask=[False, True, False])] fig = wc.plot_catalog_lines(frames=0, figsize=(10, 6), plot_labels=True, map_to_pix=False) assert isinstance(fig, Figure) assert fig.axes[0].has_data() fig, ax = plt.subplots(1, 1) fig = wc.plot_catalog_lines(frames=0, axes=ax, plot_labels=True) assert isinstance(fig, Figure) assert fig.axes[0].has_data() fig, axs = plt.subplots(1, 2) fig = wc.plot_catalog_lines(frames=[0], axes=axs, plot_labels=False) assert isinstance(fig, Figure) assert fig.axes[0].has_data() def test_plot_observed_lines(mk_good_wc_with_transform, mk_arc): wc = mk_good_wc_with_transform wc.observed_lines = [np.ma.masked_array([100, 200, 300], mask=[False, True, False])] wc.arc_spectra = [mk_arc] for frames in [None, 0]: fig = wc.plot_observed_lines(frames=frames, figsize=(10, 5), plot_labels=True) assert isinstance(fig, Figure) assert fig.axes[0].has_data() assert len(fig.axes) == 1 def test_plot_fit(mk_arc, mk_good_wc_with_transform): wc = mk_good_wc_with_transform wc.arc_spectra = [mk_arc] for frames in [None, 0]: fig = wc.plot_fit(frames=frames, figsize=(12, 6), plot_labels=True) assert isinstance(fig, Figure) assert len(fig.axes) == 2 assert fig.axes[0].has_data() assert fig.axes[1].has_data() wc.plot_fit(frames=frames, figsize=(12, 6), plot_labels=True, obs_to_wav=True) def test_plot_residuals(mk_good_wc_with_transform): wc = mk_good_wc_with_transform fig = wc.plot_residuals(space="pixel", figsize=(8, 4)) assert isinstance(fig, Figure) assert fig.axes[0].has_data() fig = wc.plot_residuals(space="wavelength", figsize=(8, 4)) assert isinstance(fig, Figure) assert fig.axes[0].has_data() fig, ax = plt.subplots(1, 1) wc.plot_residuals(ax=ax, space="wavelength", figsize=(8, 4)) with pytest.raises(ValueError, match="Invalid space specified"): wc.plot_residuals(space="wavelenght", figsize=(8, 4)) astropy-specreduce-05be828/specreduce/tests/test_wavelength_calibration.py000066400000000000000000000126411510537250300273070ustar00rootroot00000000000000import numpy as np import pytest from astropy import units as u from astropy.modeling.fitting import LinearLSQFitter from astropy.modeling.models import Polynomial1D from astropy.table import QTable from astropy.tests.helper import assert_quantity_allclose from numpy.testing import assert_allclose from specreduce import WavelengthCalibration1D def test_linear_from_list(spec1d): centers = [0, 10, 20, 30] w = [5000, 5100, 5198, 5305]*u.AA test = WavelengthCalibration1D(spec1d, line_pixels=centers, line_wavelengths=w) spec2 = test.apply_to_spectrum(spec1d) assert_quantity_allclose(spec2.spectral_axis[0], 4998.8*u.AA) assert_quantity_allclose(spec2.spectral_axis[-1], 5495.169999*u.AA) def test_wavelength_from_table(spec1d): centers = [0, 10, 20, 30] w = [5000, 5100, 5198, 5305]*u.AA table = QTable([w], names=["wavelength"]) WavelengthCalibration1D(spec1d, line_pixels=centers, line_wavelengths=table) def test_linear_from_table(spec1d): centers = [0, 10, 20, 30] w = [5000, 5100, 5198, 5305]*u.AA table = QTable([centers, w], names=["pixel_center", "wavelength"]) test = WavelengthCalibration1D(spec1d, matched_line_list=table) spec2 = test.apply_to_spectrum(spec1d) assert_quantity_allclose(spec2.spectral_axis[0], 4998.8*u.AA) assert_quantity_allclose(spec2.spectral_axis[-1], 5495.169999*u.AA) def test_poly_from_table(spec1d): # This test is mostly to prove that you can use other models centers = [0, 10, 20, 30, 40] w = [5005, 5110, 5214, 5330, 5438]*u.AA table = QTable([centers, w], names=["pixel_center", "wavelength"]) test = WavelengthCalibration1D(spec1d, matched_line_list=table, input_model=Polynomial1D(2), fitter=LinearLSQFitter()) test.apply_to_spectrum(spec1d) assert_allclose(test.fitted_model.parameters, [5.00477143e+03, 1.03457143e+01, 1.28571429e-02]) def test_replace_spectrum(spec1d, spec1d_with_emission_line): centers = [0, 10, 20, 30]*u.pix w = [5000, 5100, 5198, 5305]*u.AA test = WavelengthCalibration1D(spec1d, line_pixels=centers, line_wavelengths=w) # Accessing this property causes fits the model and caches the resulting WCS test.wcs assert "wcs" in test.__dict__ # Replace the input spectrum, which should clear the cached properties test.input_spectrum = spec1d_with_emission_line assert "wcs" not in test.__dict__ def test_expected_errors(spec1d): centers = [0, 10, 20, 30, 40] w = [5005, 5110, 5214, 5330, 5438]*u.AA table = QTable([centers, w], names=["pixel_center", "wavelength"]) with pytest.raises(ValueError, match="Cannot specify line_wavelengths separately"): WavelengthCalibration1D(spec1d, matched_line_list=table, line_wavelengths=w) with pytest.raises(ValueError, match="must have the same length"): w2 = [5005, 5110, 5214, 5330, 5438, 5500]*u.AA WavelengthCalibration1D(spec1d, line_pixels=centers, line_wavelengths=w2) with pytest.raises(ValueError, match="astropy.units.Quantity array or" " as an astropy.table.QTable"): w2 = [5005, 5110, 5214, 5330, 5438] WavelengthCalibration1D(spec1d, line_pixels=centers, line_wavelengths=w2) with pytest.raises(ValueError, match="specify at least one"): WavelengthCalibration1D(spec1d, line_pixels=centers) def test_fit_residuals(spec1d): # test that fit residuals are all 0 when input is perfectly linear and model # is a linear model centers = np.array([0, 10, 20, 30]) w = (0.5 * centers + 2) * u.AA test = WavelengthCalibration1D(spec1d, line_pixels=centers, line_wavelengths=w) test.apply_to_spectrum(spec1d) # have to apply for residuals to be computed assert_quantity_allclose(test.residuals, 0.*u.AA, atol=1e-07*u.AA) def test_fit_residuals_access(spec1d): # make sure that accessing residuals can be called before wcs/apply_to_spectrum centers = np.array([0, 10, 20, 30]) w = (0.5 * centers + 2) * u.AA test = WavelengthCalibration1D(spec1d, line_pixels=centers, line_wavelengths=w) test.residuals test.wcs def test_unsorted_pixels_wavelengths(spec1d): # make sure an error is raised if input matched pixels/wavelengths are # not strictly increasing or decreasing. centers = np.array([0, 10, 5, 30]) w = (0.5 * centers + 2) * u.AA with pytest.raises(ValueError, match='Pixels must be strictly increasing or decreasing.'): WavelengthCalibration1D(spec1d, line_pixels=centers, line_wavelengths=w) # now test that it fails when wavelengths are unsorted centers = np.array([0, 10, 20, 30]) w = np.array([2, 5, 6, 1]) * u.AA with pytest.raises(ValueError, match='Wavelengths must be strictly increasing or decreasing.'): WavelengthCalibration1D(spec1d, line_pixels=centers, line_wavelengths=w) # and same if those wavelengths are provided in a table table = QTable([w], names=["wavelength"]) with pytest.raises(ValueError, match='Wavelengths must be strictly increasing or decreasing.'): WavelengthCalibration1D(spec1d, line_pixels=centers, line_wavelengths=table) # and again with decreasing pixels but unsorted wavelengths with pytest.raises(ValueError, match='Wavelengths must be strictly increasing or decreasing.'): WavelengthCalibration1D(spec1d, line_pixels=centers[::-1], line_wavelengths=w) astropy-specreduce-05be828/specreduce/tests/test_wavesol1d.py000066400000000000000000000105151510537250300244770ustar00rootroot00000000000000import astropy.units as u import numpy as np import pytest from astropy.modeling import models from astropy.modeling.polynomial import Polynomial1D from astropy.nddata import StdDevUncertainty from gwcs import wcs from specreduce.wavesol1d import _diff_poly1d, WavelengthSolution1D from specreduce.compat import Spectrum ref_pixel = 250.0 p2w = models.Shift(ref_pixel) | models.Polynomial1D(degree=3, c0=1, c1=0.2, c2=0.001) pix_bounds = (0, 500) wav_bounds = p2w(pix_bounds) @pytest.fixture def mk_ws_without_transform(): return WavelengthSolution1D(None, pix_bounds, u.angstrom) @pytest.fixture def mk_ws_with_transform(): return WavelengthSolution1D(p2w, pix_bounds, u.angstrom) @pytest.fixture def mk_spectrum(): return Spectrum( flux=np.ones(pix_bounds[1]) * u.DN, spectral_axis=np.arange(pix_bounds[1]) * u.pix, uncertainty=StdDevUncertainty(np.ones(pix_bounds[1])), ) def test_diff_poly1d(): p = _diff_poly1d(Polynomial1D(3, c0=1.0, c1=2.0, c2=3.0, c3=4.0)) np.testing.assert_array_equal(p.parameters, [2.0, 6.0, 12.0]) def test_init(): ws = WavelengthSolution1D(p2w, pix_bounds, u.angstrom) assert ws._p2w is p2w assert ws.bounds_pix == pix_bounds assert ws.unit == u.angstrom assert "w2p" not in ws.__dict__ assert "p2d_dldx" not in ws.__dict__ assert "gwcs" not in ws.__dict__ # Test that the cached properties are created correctly ws.w2p(0.5) assert "w2p" in ws.__dict__ ws.p2w_dldx(pix_bounds[0]) assert "p2w_dldx" in ws.__dict__ wcs = ws.gwcs # noqa: F841 assert "gwcs" in ws.__dict__ # Test that the cached properties are deleted correctly ws.p2w = p2w assert "w2p" not in ws.__dict__ assert "p2d_dldx" not in ws.__dict__ assert "gwcs" not in ws.__dict__ ws = WavelengthSolution1D(p2w, pix_bounds, u.micron) assert ws.unit == u.micron ws = WavelengthSolution1D(None, pix_bounds, u.angstrom) assert ws._p2w is None def test_resample(mk_spectrum, mk_ws_with_transform, mk_ws_without_transform): ws = mk_ws_with_transform spectrum = mk_spectrum # Resample a spectrum with uncertainty resampled = ws.resample(spectrum, nbins=50) assert resampled is not None assert len(resampled.flux) == 50 assert resampled.flux.unit == u.DN / u.angstrom pix_edges = np.arange(spectrum.spectral_axis.size + 1) - 0.5 f0 = (spectrum.flux.value * np.diff(ws._p2w(pix_edges))).sum() f1 = (resampled.flux.value * np.diff(resampled.spectral_axis.value)[0]).sum() np.testing.assert_approx_equal(f0, f1, 5) resampled = ws.resample(spectrum, wlbounds=wav_bounds) resampled = ws.resample(spectrum, bin_edges=np.linspace(*wav_bounds, num=50)) # Resample a spectrum without uncertainty spectrum.uncertainty = None resampled = ws.resample(spectrum, nbins=50) assert resampled.uncertainty is not None ws = mk_ws_without_transform with pytest.raises(ValueError, match="Wavelength solution not set."): ws.resample(mk_spectrum) ws = mk_ws_with_transform with pytest.raises(ValueError, match="Number of bins must be non-zero and positive"): ws.resample(mk_spectrum, nbins=-5) def test_pix_to_wav(mk_ws_with_transform): ws = mk_ws_with_transform pix = np.array([1, 2, 3, 4, 5]) np.testing.assert_array_equal(ws.pix_to_wav(pix), p2w(pix)) pix = np.ma.masked_array([1, 2, 3], mask=[0, 1, 0]) wav = ws.pix_to_wav(pix) np.testing.assert_array_equal(wav.data, p2w(pix.data)) np.testing.assert_array_equal(wav.mask, np.array([0, 1, 0])) def test_wav_to_pix(mk_ws_with_transform): ws = mk_ws_with_transform pix_values_orig = np.array([1, 2, 3, 4, 5]) pix_values_tran = ws.wav_to_pix(ws.pix_to_wav(pix_values_orig)) np.testing.assert_array_almost_equal(pix_values_orig, pix_values_tran) pix_values_orig = np.ma.masked_array([1, 2, 3, 4, 5], mask=[0, 1, 0, 1, 0]) pix_values_tran = ws.wav_to_pix(ws.pix_to_wav(pix_values_orig)) np.testing.assert_array_almost_equal(pix_values_orig.data, pix_values_tran.data) np.testing.assert_array_almost_equal(pix_values_orig.mask, pix_values_tran.mask) def test_wcs_creates_valid_gwcs_object(mk_ws_with_transform): wc = mk_ws_with_transform wcs_obj = wc.gwcs assert wcs_obj is not None assert isinstance(wcs_obj, wcs.WCS) assert wcs_obj.output_frame.unit[0] == u.angstrom astropy-specreduce-05be828/specreduce/tracing.py000066400000000000000000000475301510537250300220270ustar00rootroot00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst import warnings from copy import deepcopy from dataclasses import dataclass, field from typing import Literal import numpy as np from astropy.modeling import Model, fitting, models from astropy.nddata import NDData from astropy.stats import gaussian_sigma_to_fwhm from astropy.utils.decorators import deprecated from specreduce.core import _ImageParser __all__ = ["Trace", "FlatTrace", "ArrayTrace", "FitTrace"] @dataclass class Trace: """ Basic tracing class that by default traces the middle of the image. Parameters ---------- image : `~astropy.nddata.NDData`-like or array-like, required Image to be traced Attributes ---------- shape : tuple Shape of the array describing the trace """ image: NDData def __post_init__(self): self.trace_pos = self.image.shape[0] / 2 self.trace = np.ones_like(self.image[0]) * self.trace_pos # masking options not relevant for basic Trace self._mask_treatment = None self._valid_mask_treatment_methods = [None] # eventually move this to common SpecreduceOperation base class self.validate_masking_options() def __getitem__(self, i): return self.trace[i] @property def shape(self): return self.trace.shape def validate_masking_options(self): if self.mask_treatment not in self.valid_mask_treatment_methods: raise ValueError( f"`mask_treatment` {self.mask_treatment} not one " f"of {self.valid_mask_treatment_methods}" ) # noqa def shift(self, delta): """ Shift the trace by delta pixels perpendicular to the axis being traced Parameters ---------- delta : float Shift to be applied to the trace """ # act on self.trace.data to ignore the mask and then re-mask when calling _bound_trace self.trace = np.asarray(self.trace.data) + delta self._bound_trace() def _bound_trace(self): """ Mask trace positions that are outside the upper/lower bounds of the image. """ ny = self.image.shape[0] self.trace = np.ma.masked_outside(self.trace, 0, ny - 1) def __add__(self, delta): """ Return a copy of the trace shifted "forward" by delta pixels perpendicular to the axis being traced """ copy = deepcopy(self) copy.shift(delta) return copy def __sub__(self, delta): """ Return a copy of the trace shifted "backward" by delta pixels perpendicular to the axis being traced """ return self.__add__(-delta) @property def mask_treatment(self): return self._mask_treatment @property def valid_mask_treatment_methods(self): return self._valid_mask_treatment_methods @dataclass class FlatTrace(Trace, _ImageParser): """ Trace that is constant along the axis being traced. Example: :: trace = FlatTrace(image, trace_pos) Parameters ---------- trace_pos : float Position of the trace """ trace_pos: float def __post_init__(self): self.image = self._parse_image(self.image) self.set_position(self.trace_pos) # masking options not relevant for basic Trace self._mask_treatment = None self._valid_mask_treatment_methods = [None] def set_position(self, trace_pos): """ Set the trace position within the image Parameters ---------- trace_pos : float Position of the trace """ if trace_pos < 1: raise ValueError("`trace_pos` must be positive.") self.trace_pos = trace_pos self.trace = np.ones_like(self.image.data[0]) * self.trace_pos self._bound_trace() @dataclass class ArrayTrace(Trace, _ImageParser): """ Define a trace given an array of trace positions. Parameters ---------- trace : `numpy.ndarray` or `numpy.ma.MaskedArray` Array containing trace positions. """ trace: np.ndarray def __post_init__(self): # masking options not relevant for ArrayTrace. any non-finite or masked # data in `image` will not affect array trace self._mask_treatment = None self._valid_mask_treatment_methods = [None] # masked array will have a .data, regular array will not. trace_data = getattr(self.trace, "data", self.trace) # but we do need to mask uncaught non-finite values in input trace array # which should also be combined with any existing mask in the input `trace` if hasattr(self.trace, "mask"): total_mask = np.logical_or(self.trace.mask, ~np.isfinite(trace_data)) else: total_mask = ~np.isfinite(trace_data) # always work with masked array, even if there is no masked # or nonfinite data, in case padding is needed. if not, mask will be # dropped at the end and a regular array will be returned. self.trace = np.ma.MaskedArray(trace_data, total_mask) self.image = self._parse_image(self.image) nx = self.image.shape[1] nt = len(self.trace) if nt != nx: if nt > nx: # truncate trace to fit image self.trace = self.trace[0:nx] else: # assume trace starts at beginning of image and pad out trace to fit. # padding will be the last value of the trace, but will be masked out. padding = np.ma.MaskedArray(np.ones(nx - nt) * self.trace[-1], mask=True) self.trace = np.ma.hstack([self.trace, padding]) self._bound_trace() # warn if entire trace is masked if np.all(self.trace.mask): warnings.warn("Entire trace array is masked.") # and return plain array if nothing is masked if not np.any(self.trace.mask): self.trace = self.trace.data @dataclass class FitTrace(Trace, _ImageParser): """ Trace the spectrum aperture in an image. Bins along the image's dispersion (wavelength) direction, finds each bin's peak cross-dispersion (spatial) pixel, and uses a model to interpolate the function fitted to the peaks as a final trace. The number of bins, peak finding algorithm, and model used for fitting are customizable by the user. Example: :: trace = FitTrace(image, peak_method='gaussian', guess=trace_pos) Parameters ---------- image : `~astropy.nddata.NDData`-like or array-like, required The image over which to run the trace. Assumes cross-dispersion (spatial) direction is axis 0 and dispersion (wavelength) direction is axis 1. bins : int, optional The number of bins in the dispersion (wavelength) direction into which to divide the image. If not set, defaults to one bin per dispersion (wavelength) pixel in the given image. If set, requires at least 4 or N bins for a degree N ``trace_model``, whichever is greater. [default: ``None``] guess : int, optional A guess at the trace's location in the cross-dispersion (spatial) direction. If set, overrides the normal max peak finder. Good for tracing a fainter source if multiple traces are present. [default: ``None``] window : int, optional Fit the trace to a region with size ``window * 2`` around the guess position. Useful for tracing faint sources if multiple traces are present, but potentially bad if the trace is substantially bent or warped. [default: ``None``] disp_bounds The lower and upper bounds of the pixel range along the dispersion axis that is used when fitting the trace model. If ``None``, defaults to the entire range of pixels along the dispersion axis. [default: ``None``] trace_model : one of `~astropy.modeling.polynomial.Chebyshev1D`,\ `~astropy.modeling.polynomial.Legendre1D`,\ `~astropy.modeling.polynomial.Polynomial1D`,\ or `~astropy.modeling.spline.Spline1D`, optional The 1-D polynomial model used to fit the trace to the bins' peak pixels. Spline1D models are fit with Astropy's 'SplineSmoothingFitter', generic linear models are fit with the 'LinearLSQFitter', while the other models are fit with the 'LMLSQFitter'. [default: ``models.Polynomial1D(degree=1)``] peak_method : string, optional One of ``gaussian``, ``centroid``, or ``max``. ``gaussian``: Fits a gaussian to the window within each bin and adopts the central value as the peak. May work best with fewer bins on faint targets. (Based on the "kosmos" algorithm from James Davenport's same-named repository.) ``centroid``: Takes the centroid of the window within in bin. ``max``: Saves the position with the maximum flux in each bin. [default: ``max``] mask_treatment Specifies how to handle masked or non-finite values in the input image. The fit cannot handle non-finite values, so only the ``apply``, ``propagate``, ``apply_nan_only`` options are supported. The ``apply`` option combines the existing mask with the mask derived from non-finite values, ``propagate`` expands the mask along the cross-dispersion axis (that is, a masked pixel results in the whole cross-dispersion slice being masked), and ``apply_nan_only`` drops the existing mask and replaces it with a mask derived from non-finite values. """ bins: int | None = None guess: float | None = None window: int | None = None disp_bounds: tuple[float, float] | None = None trace_model: Model = field(default=models.Polynomial1D(degree=1)) peak_method: Literal["gaussian", "centroid", "max"] = "max" _crossdisp_axis: int = 0 _disp_axis: int = 1 mask_treatment: Literal["apply", "propagate", "apply_nan_only"] = "apply" _valid_mask_treatment_methods = ("apply", "propagate", "apply_nan_only") # for testing purposes only, save bin peaks if requested _save_bin_peaks_testing: bool = True def __post_init__(self): # Parse image, including masked/nonfinite data handling based on # choice of `mask_treatment`. returns a Spectrum1D if self.mask_treatment not in self._valid_mask_treatment_methods: raise ValueError( "`mask_treatment` must be one of " f"{self._valid_mask_treatment_methods}" ) self.image = self._parse_image( self.image, disp_axis=self._disp_axis, mask_treatment=self.mask_treatment ) # _parse_image returns a Spectrum1D. convert this to a masked array # for ease of calculations here (even if there is no masked data). # Note: uncertainties are dropped, this should also be addressed at # some point probably across the package. img = np.ma.masked_array(self.image.data, self.image.mask) self._mask_temp = self.image.mask # validate input arguments valid_peak_methods = ("gaussian", "centroid", "max") if self.peak_method not in valid_peak_methods: raise ValueError(f"peak_method must be one of {valid_peak_methods}") if self._crossdisp_axis != 0: raise ValueError("cross-dispersion axis must equal 0") if self._disp_axis != 1: raise ValueError("dispersion axis must equal 1") valid_models = (models.Spline1D, models.Legendre1D, models.Chebyshev1D, models.Polynomial1D) if not isinstance(self.trace_model, valid_models): raise ValueError( "trace_model must be one of " f"{', '.join([m.name for m in valid_models])}." ) self.dlim = self.disp_bounds if self.disp_bounds is not None else (0, img.shape[ self._disp_axis]) cols = self.dlim[1] model_deg = self.trace_model.degree if self.bins is None: self.bins = cols elif self.bins < 4: # many of the Astropy model fitters require four points at minimum raise ValueError("bins must be >= 4") elif self.bins <= model_deg: raise ValueError(f"bins must be > {model_deg} for " f"a degree {model_deg} model.") elif self.bins > cols: raise ValueError( f"bins must be <= {cols}, the length of the " "image's spatial direction" ) if not isinstance(self.bins, int): warnings.warn("TRACE: Converting bins to int") self.bins = int(self.bins) if self.window is not None and ( self.window > img.shape[self._disp_axis] or self.window < 1 ): raise ValueError( f"window must be >= 2 and less than {cols}, the " "length of the image's spatial direction" ) elif self.window is not None and not isinstance(self.window, int): warnings.warn("TRACE: Converting window to int") self.window = int(self.window) # fit the trace self._fit_trace(img) def _fit_trace(self, img): yy = np.arange(img.shape[self._crossdisp_axis]) # set max peak location by user choice or wavelength with max avg flux ztot = img.mean(axis=self._disp_axis) peak_y = self.guess if self.guess is not None else ztot.argmax() # NOTE: peak finder can be bad if multiple objects are on slit if self.peak_method == "gaussian": # guess the peak width as the FWHM, roughly converted to gaussian sigma yy_above_half_max = np.sum(ztot > (ztot.max() / 2)) width_guess = yy_above_half_max / gaussian_sigma_to_fwhm # enforce some (maybe sensible?) rules about trace peak width width_guess = 2 if width_guess < 2 else 25 if width_guess > 25 else width_guess # fit a Gaussian to peak for fall-back answer, but don't use yet g1d_init = models.Gaussian1D(amplitude=ztot.max(), mean=peak_y, stddev=width_guess) offset_init = models.Const1D(np.ma.median(ztot)) profile = g1d_init + offset_init fitter = fitting.DogBoxLSQFitter() popt_tot = fitter(profile, yy, ztot) # restrict fit to window (if one exists) ilum2 = ( yy if self.window is None else yy[np.arange(peak_y - self.window, peak_y + self.window, dtype=int)] ) # check if everything in window region is masked if img[ilum2].mask.all(): raise ValueError( "All pixels in window region are masked. Check " "for invalid values or use a larger window value." ) x_bins = np.linspace(self.dlim[0], self.dlim[1], self.bins + 1, dtype=int) y_bins = np.tile(np.nan, self.bins) warn_bins = [] for i in range(self.bins): # binned columns, averaged along disp. axis. # or just a single, unbinned column if no bins z_i = img[ilum2, x_bins[i] : x_bins[i + 1]].mean(axis=self._disp_axis) # if this bin is fully masked, set bin peak to NaN so it can be # filtered in the final fit to all bin peaks for the trace if z_i.mask.all() or (~np.isfinite(z_i)).all(): warn_bins.append(i) y_bins[i] = np.nan continue if self.peak_method == "gaussian": # if bin is fully 0, set bin peak to nan so it doesn't bias the # all-bin fit. DogBoxLSQFitter, which is always used for the bin # center fits when peak_method is gaussian, does not like all zeros. if np.all(z_i == 0.0): y_bins[i] = np.nan continue peak_y_i = ilum2[z_i.argmax()] yy_i_above_half_max = np.sum(z_i > (z_i.max() / 2)) width_guess_i = yy_i_above_half_max / gaussian_sigma_to_fwhm # NOTE: original KOSMOS code mandated width be greater than 2 # (to avoid cosmic rays) and less than 25 (to avoid fitting noise). # we should extract values from img to derive similar limits # width_guess_i = (2 if width_guess_i < 2 # else 25 if width_guess_i > 25 # else width_guess_i) g1d_init_i = models.Gaussian1D( amplitude=z_i.max(), mean=peak_y_i, stddev=width_guess_i ) offset_init_i = models.Const1D(np.ma.median(z_i)) profile_i = g1d_init_i + offset_init_i popt_i = fitter(profile_i, ilum2[~z_i.mask], z_i.data[~z_i.mask]) # if gaussian fits off chip, then fall back to previous answer if not ilum2.min() <= popt_i.mean_0 <= ilum2.max(): y_bins[i] = popt_tot.mean_0.value else: y_bins[i] = popt_i.mean_0.value popt_tot = popt_i elif self.peak_method == "centroid": z_i_cumsum = np.cumsum(z_i) # find the interpolated index where the cumulative array reaches # half the total cumulative values y_bins[i] = np.interp(z_i_cumsum[-1] / 2.0, z_i_cumsum, ilum2) # NOTE this reflects current behavior, should eventually be changed # to set to nan by default (or zero fill / interpoate option once # available) elif self.peak_method == "max": # TODO: implement smoothing with provided width y_bins[i] = ilum2[z_i.argmax()] # NOTE: a fully masked should eventually be changed to set to # nan by default (or zero fill / interpoate option once available) # warn about fully-masked bins if len(warn_bins) > 0: # if there are a ton of bins, we don't want to print them all out if len(warn_bins) > 20: warn_bins = warn_bins[0:10] + ["..."] + [warn_bins[-1]] warnings.warn( f"All pixels in {'bins' if len(warn_bins) else 'bin'} " f"{', '.join([str(x) for x in warn_bins])}" " are fully masked. Setting bin" f" peak{'s' if len(warn_bins) else ''} to NaN." ) # recenter bin positions x_bins = (x_bins[:-1] + x_bins[1:]) / 2 # interpolate the fitted trace over the entire wavelength axis # for testing purposes only, save bin peaks if requested if self._save_bin_peaks_testing: self._bin_peaks = (x_bins, y_bins) # filter non-finite bin peaks before filtering to all bin peaks y_finite = np.where(np.isfinite(y_bins))[0] if y_finite.size > 0: x_bins = x_bins[y_finite] y_bins = y_bins[y_finite] # use given model to bin y-values; interpolate over all wavelengths if isinstance(self.trace_model, models.Spline1D): fitter = fitting.SplineSmoothingFitter() elif self.trace_model.linear: fitter = fitting.LinearLSQFitter() else: fitter = fitting.LMLSQFitter() self._y_bins = y_bins self.trace_model_fit = fitter(self.trace_model, x_bins, y_bins) trace_x = np.arange(img.shape[self._disp_axis]) trace_y = self.trace_model_fit(trace_x) else: warnings.warn("TRACE ERROR: No valid points found in trace") trace_y = np.tile(np.nan, img.shape[self._disp_axis]) self.trace = np.ma.masked_invalid(trace_y) @deprecated("1.3", alternative="FitTrace") @dataclass class KosmosTrace(FitTrace): """ This class is pending deprecation. Please use `FitTrace` instead. """ __doc__ += FitTrace.__doc__ pass astropy-specreduce-05be828/specreduce/utils/000077500000000000000000000000001510537250300211555ustar00rootroot00000000000000astropy-specreduce-05be828/specreduce/utils/__init__.py000066400000000000000000000001171510537250300232650ustar00rootroot00000000000000""" General purpose utilities for specreduce """ from .utils import * # noqa astropy-specreduce-05be828/specreduce/utils/synth_data.py000066400000000000000000000341161510537250300236720ustar00rootroot00000000000000# Licensed under a 3-clause BSD style license - see ../../licenses/LICENSE.rst import warnings from typing import Sequence import numpy as np from astropy import units as u from astropy.modeling import models, Model from astropy.nddata import CCDData from astropy.stats import gaussian_fwhm_to_sigma from astropy.wcs import WCS from specreduce.calibration_data import load_pypeit_calibration_lines __all__ = [ 'make_2d_trace_image', 'make_2d_arc_image', 'make_2d_spec_image' ] def make_2d_trace_image( nx: int = 3000, ny: int = 1000, background: int | float = 5, trace_center: int | float | None = None, trace_order: int = 3, trace_coeffs: dict[str, int | float] = {'c0': 0, 'c1': 50, 'c2': 100}, profile: Model = models.Moffat1D(amplitude=10, alpha=0.1), add_noise: bool = True ) -> CCDData: """ Create synthetic 2D spectroscopic image with a single source. The spatial (y-axis) position of the source along the dispersion (x-axis) direction is modeled using a Chebyshev polynomial. The flux units are counts and the noise is modeled as Poisson. Parameters ---------- nx : Size of image in X axis which is assumed to be the dispersion axis ny : Size of image in Y axis which is assumed to be the spatial axis background : Level of constant background in counts trace_center : Zeropoint of the trace. If None, then use center of Y (spatial) axis. trace_order : Order of the Chebyshev polynomial used to model the source's trace trace_coeffs : Dict containing the Chebyshev polynomial coefficients to use in the trace model profile : Model to use for the source's spatial profile add_noise : If True, add Poisson noise to the image Returns ------- ccd_im : CCDData instance containing synthetic 2D spectroscopic image """ x = np.arange(nx) y = np.arange(ny) xx, yy = np.meshgrid(x, y) if trace_center is None: trace_center = ny / 2 trace_mod = models.Chebyshev1D(degree=trace_order, **trace_coeffs) trace = yy - trace_center + trace_mod(xx/nx) z = background + profile(trace) if add_noise: from photutils.datasets import apply_poisson_noise trace_image = apply_poisson_noise(z) else: trace_image = z ccd_im = CCDData(trace_image, unit=u.count) return ccd_im def make_2d_arc_image( nx: int = 3000, ny: int = 1000, wcs: WCS | None = None, extent: Sequence[int | float] = (3500, 7000), wave_unit: u.Unit = u.Angstrom, wave_air: bool = False, background: int | float = 5, line_fwhm: float = 5., linelists: list[str] = ['HeI'], amplitude_scale: float = 1., tilt_func: Model = models.Legendre1D(degree=0), add_noise: bool = True ) -> CCDData: """ Create synthetic 2D spectroscopic image of reference emission lines, e.g. a calibration arc lamp. Currently, linelists from ``pypeit`` are supported and are selected by string or list of strings that is passed to `~specreduce.calibration_data.load_pypeit_calibration_lines`. If a ``wcs`` is not provided, one is created using ``extent`` and ``wave_unit`` with dispersion along the X axis. Parameters ---------- nx : Size of image in X axis which is assumed to be the dispersion axis ny : Size of image in Y axis which is assumed to be the spatial axis wcs : 2D WCS to apply to the image. Must have a spectral axis defined along with appropriate spectral wavelength units. extent : If ``wcs`` is not provided, this defines the beginning and end wavelengths of the dispersion axis. wave_unit : If ``wcs`` is not provided, this defines the wavelength units of the dispersion axis. wave_air : If True, convert the vacuum wavelengths used by ``pypeit`` to air wavelengths. background : Level of constant background in counts line_fwhm : Gaussian FWHM of the emission lines in pixels linelists : Specification for linelists to load from ``pypeit`` amplitude_scale : Scale factor to apply to amplitudes provided in the linelists tilt_func : The tilt function to apply along the cross-dispersion axis to simulate tilted or curved emission lines. add_noise : If True, add Poisson noise to the image; requires ``photutils`` to be installed. Returns ------- ccd_im : CCDData instance containing synthetic 2D spectroscopic image Examples -------- This is an example of modeling a spectrograph whose output is curved in the cross-dispersion direction: .. plot:: :include-source: import matplotlib.pyplot as plt import numpy as np from astropy.modeling import models import astropy.units as u from specreduce.utils.synth_data import make_2d_arc_image model_deg2 = models.Legendre1D(degree=2, c0=50, c1=0, c2=100) im = make_2d_arc_image( linelists=['HeI', 'ArI', 'ArII'], line_fwhm=3, tilt_func=model_deg2 ) fig = plt.figure(figsize=(10, 6)) plt.imshow(im) The FITS WCS standard implements ideal world coordinate functions based on the physics of simple dispersers. This is described in detail by Paper III, https://www.aanda.org/articles/aa/pdf/2006/05/aa3818-05.pdf. This can be used to model a non-linear dispersion relation based on the properties of a spectrograph. This example recreates Figure 5 in that paper using a spectrograph with a 450 lines/mm volume phase holographic grism. Standard gratings only use the first three ``PV`` terms: .. plot:: :include-source: import numpy as np import matplotlib.pyplot as plt from astropy.wcs import WCS import astropy.units as u from specreduce.utils.synth_data import make_2d_arc_image non_linear_header = { 'CTYPE1': 'AWAV-GRA', # Grating dispersion function with air wavelengths 'CUNIT1': 'Angstrom', # Dispersion units 'CRPIX1': 719.8, # Reference pixel [pix] 'CRVAL1': 7245.2, # Reference value [Angstrom] 'CDELT1': 2.956, # Linear dispersion [Angstrom/pix] 'PV1_0': 4.5e5, # Grating density [1/m] 'PV1_1': 1, # Diffraction order 'PV1_2': 27.0, # Incident angle [deg] 'PV1_3': 1.765, # Reference refraction 'PV1_4': -1.077e6, # Refraction derivative [1/m] 'CTYPE2': 'PIXEL', # Spatial detector coordinates 'CUNIT2': 'pix', # Spatial units 'CRPIX2': 1, # Reference pixel 'CRVAL2': 0, # Reference value 'CDELT2': 1 # Spatial units per pixel } linear_header = { 'CTYPE1': 'AWAV', # Grating dispersion function with air wavelengths 'CUNIT1': 'Angstrom', # Dispersion units 'CRPIX1': 719.8, # Reference pixel [pix] 'CRVAL1': 7245.2, # Reference value [Angstrom] 'CDELT1': 2.956, # Linear dispersion [Angstrom/pix] 'CTYPE2': 'PIXEL', # Spatial detector coordinates 'CUNIT2': 'pix', # Spatial units 'CRPIX2': 1, # Reference pixel 'CRVAL2': 0, # Reference value 'CDELT2': 1 # Spatial units per pixel } non_linear_wcs = WCS(non_linear_header) linear_wcs = WCS(linear_header) # this re-creates Paper III, Figure 5 pix_array = 200 + np.arange(1400) nlin = non_linear_wcs.spectral.pixel_to_world(pix_array) lin = linear_wcs.spectral.pixel_to_world(pix_array) resid = (nlin - lin).to(u.Angstrom) plt.plot(pix_array, resid) plt.xlabel("Pixel") plt.ylabel("Correction (Angstrom)") plt.show() nlin_im = make_2d_arc_image( nx=600, ny=512, linelists=['HeI', 'NeI'], line_fwhm=3, wave_air=True, wcs=non_linear_wcs ) lin_im = make_2d_arc_image( nx=600, ny=512, linelists=['HeI', 'NeI'], line_fwhm=3, wave_air=True, wcs=linear_wcs ) # subtracting the linear simulation from the non-linear one shows how the # positions of lines diverge between the two cases plt.imshow(nlin_im.data - lin_im.data) plt.show() """ if wcs is None: if extent is None: raise ValueError("Must specify either a wavelength extent or a WCS.") if len(extent) != 2: raise ValueError("Wavelength extent must be of length 2.") if u.get_physical_type(wave_unit) != 'length': raise ValueError("Wavelength unit must be a length unit.") wcs = WCS(naxis=2) wcs.wcs.ctype[0] = 'WAVE' wcs.wcs.ctype[1] = 'PIXEL' wcs.wcs.cunit[0] = wave_unit wcs.wcs.cunit[1] = u.pixel wcs.wcs.crval[0] = extent[0] wcs.wcs.cdelt[0] = (extent[1] - extent[0]) / nx wcs.wcs.crval[1] = 0 wcs.wcs.cdelt[1] = 1 else: if wcs.spectral.naxis != 1: raise ValueError("Provided WCS must have a spectral axis.") if wcs.naxis != 2: raise ValueError("WCS must have NAXIS=2 for a 2D image.") x = np.arange(nx) y = np.arange(ny) xx, yy = np.meshgrid(x, y) is_spectral = [a['coordinate_type'] == "spectral" for a in wcs.get_axis_types()] if is_spectral[0]: disp_axis = 0 else: disp_axis = 1 if tilt_func is not None: if not isinstance( tilt_func, (models.Legendre1D, models.Chebyshev1D, models.Polynomial1D, models.Hermite1D) ): raise ValueError( "The only tilt functions currently supported are 1D polynomials " "from astropy.models." ) if disp_axis == 0: xx = xx + tilt_func((yy - ny/2)/ny) else: yy = yy + tilt_func((xx - nx/2)/nx) z = background + np.zeros((ny, nx)) linelist = load_pypeit_calibration_lines(linelists, wave_air=wave_air) if linelist is not None: with warnings.catch_warnings(): warnings.filterwarnings("ignore", message="No observer defined on WCS.*") line_disp_positions = wcs.spectral.world_to_pixel(linelist['wavelength']) line_sigma = gaussian_fwhm_to_sigma * line_fwhm for line_pos, ampl in zip(line_disp_positions, linelist['amplitude']): line_mod = models.Gaussian1D( amplitude=ampl * amplitude_scale, mean=line_pos, stddev=line_sigma ) if disp_axis == 0: z += line_mod(xx) else: z += line_mod(yy) if add_noise: from photutils.datasets import apply_poisson_noise arc_image = apply_poisson_noise(z) else: arc_image = z ccd_im = CCDData(arc_image, unit=u.count, wcs=wcs) return ccd_im def make_2d_spec_image( nx: int = 3000, ny: int = 1000, wcs: WCS | None = None, extent: Sequence[int | float] = (6500, 9500), wave_unit: u.Unit = u.Angstrom, wave_air: bool = False, background: int | float = 5, line_fwhm: float = 5., linelists: list[str] = ['OH_GMOS'], amplitude_scale: float = 1., tilt_func: Model = models.Legendre1D(degree=0), trace_center: int | float | None = None, trace_order: int = 3, trace_coeffs: dict[str, int | float] = {'c0': 0, 'c1': 50, 'c2': 100}, source_profile: Model = models.Moffat1D(amplitude=10, alpha=0.1), add_noise: bool = True ) -> CCDData: """ Make a synthetic 2D spectrum image containing both emission lines and a trace of a continuum source. Parameters ---------- nx : Number of pixels in the dispersion direction. ny : Number of pixels in the spatial direction. wcs : 2D WCS to apply to the image. Must have a spectral axis defined along with appropriate spectral wavelength units. extent : If ``wcs`` is not provided, this defines the beginning and end wavelengths of the dispersion axis. wave_unit : If ``wcs`` is not provided, this defines the wavelength units of the dispersion axis. wave_air : If True, convert the vacuum wavelengths used by ``pypeit`` to air wavelengths. background : Constant background level in counts. line_fwhm : Gaussian FWHM of the emission lines in pixels linelists : Specification for linelists to load from ``pypeit`` amplitude_scale : Scale factor to apply to amplitudes provided in the linelists tilt_func : The tilt function to apply along the cross-dispersion axis to simulate tilted or curved emission lines. trace_center : Zeropoint of the trace. If None, then use center of Y (spatial) axis. trace_order : Order of the Chebyshev polynomial used to model the source's trace trace_coeffs : Dict containing the Chebyshev polynomial coefficients to use in the trace model source_profile : Model to use for the source's spatial profile add_noise : If True, add Poisson noise to the image; requires ``photutils`` to be installed. Returns ------- ccd_im : CCDData instance containing synthetic 2D spectroscopic image """ arc_image = make_2d_arc_image( nx=nx, ny=ny, wcs=wcs, extent=extent, wave_unit=wave_unit, wave_air=wave_air, background=0, line_fwhm=line_fwhm, linelists=linelists, amplitude_scale=amplitude_scale, tilt_func=tilt_func, add_noise=False ) trace_image = make_2d_trace_image( nx=nx, ny=ny, background=0, trace_center=trace_center, trace_order=trace_order, trace_coeffs=trace_coeffs, profile=source_profile, add_noise=False ) spec_image = arc_image.data + trace_image.data + background if add_noise: from photutils.datasets import apply_poisson_noise spec_image = apply_poisson_noise(spec_image) ccd_im = CCDData(spec_image, unit=u.count, wcs=arc_image.wcs) return ccd_im astropy-specreduce-05be828/specreduce/utils/utils.py000066400000000000000000000237201510537250300226730ustar00rootroot00000000000000import numpy as np from specreduce.core import _ImageParser from specreduce.tracing import Trace, FlatTrace from specreduce.extract import _ap_weight_image, _align_along_trace __all__ = ['measure_cross_dispersion_profile', '_align_along_trace'] def measure_cross_dispersion_profile(image, trace=None, crossdisp_axis=0, width=None, pixel=None, pixel_range=None, statistic='median', align_along_trace=True): """ Return a 1D (quantity) array of the cross-dispersion profile measured at a specified pixel value ('wavelength', but potentially before calibration), or the average profile across several pixel values (or range of pixel values) along the dispersion axis. If a single number is specified for `pixel`, then the profile at that pixel (i.e wavelength) will be returned. If several pixels are specified in a list or array, then they will be averaged (median or average, set by `statistic` which defaults to median). Alternatively, `pixel_range` can be specified as a tuple of integers specifying the minimum and maximum pixel range to average the profile. `pixel` and `pixel_range` cannot be set simultaneously, and the default is `pixel_range`=(min_image, max_image) to return an average profile across the entire wavelength range of the image. The window in the cross dispersion axis for measuring the profile at the pixel(s) specified is determined by `width` and `trace`. If a trace is provided (either as a Trace object, or as a number specifying the location on the cross-dispersion axis of a FlatTrace object) that will determine the center of the profile on the cross-dispersion axis. Otherwise, if `trace` is None, the center of the image will be the center of the returned profile (i.e., the center row assuming a horizontal trace). If `width` is none, a window size of half the image in the cross-dispersion axis will be used to measure the cross dispersion profile. Otherwise, an integer value can be set for `width` which will determine the size of the window around the trace used to measure the profile (this window moves with the trace if trace is not flat). By default, if a non-flat trace is used the image will be aligned along the trace. This can be controlled with the 'align_along_trace' parameter. Parameters ---------- image : `~astropy.nddata.NDData`-like or array-like, required 2D image to measure cross-dispersion profile. trace : Trace object, int, float, or None A Trace object, a number to specify a FlatTrace, or None to use the middle of the image. This is the position that defines the center of the cross-dispersion profile. [default: None] crossdisp_axis : int, optional The index of the image's cross-dispersion axis. [default: 0] width : tuple of int or None Width around 'trace' to calculate profile. If None, then all rows in the cross-dispersion axis will be used. [default: None] pixel: int, list of int, or None Pixel value(s) along the dispersion axis to return cross-dispersion profile. If several specified in list, then the average (method set by `statistic`) profile will be calculated. If None, and `pixel_range` is set, then `pixel_range` will be used. [default: None] pixel_range: tuple of int or None Tuple of (min, max) defining the pixel range (along dispersion axis) to calculate average cross-dispersion profile, up to and not inclusive of max. If None, and `pixel` is not None, `pixel` will be used. If None and `pixel` is also None, this will be interpreted as using the entire dispersion axis to generate an average profile for the whole image. [default: None] statistic: 'median' or 'average' If `pixel` specifies multiple pixels, or `pixel_range` is specified, an average profile will be returned. This can be either `median` (default) or `average` (mean). This is ignored if only one pixel is specified. [default: median] align_along_trace: bool Relevant only for non-flat traces. If True, "roll" each column so that the trace sits in the central row before calculating average profile. This will prevent any 'blurring' from averaging a non-flat trace at different pixel/wavelengths. [default: True] """ if crossdisp_axis != 0 and crossdisp_axis != 1: raise ValueError('`crossdisp_axis` must be 0 or 1.') crossdisp_axis = int(crossdisp_axis) disp_axis = 1 if crossdisp_axis == 0 else 0 unit = getattr(image, 'unit', None) # parse image, which will return a spectrum1D (note: this is not ideal, # but will be addressed at some point) parser = _ImageParser() image = parser._parse_image(image, disp_axis=disp_axis) # which we then need to make back into a masked array # again this way of parsing the image is not ideal but # thats just how it is for now. image = np.ma.MaskedArray(image.data, mask=image.mask) # transpose if disp_axis = 0 just for simplicity of calculations # image is already copied so this won't modify input if disp_axis == 0: image = image.T nrows = image.shape[crossdisp_axis] ncols = image.shape[disp_axis] if not isinstance(trace, Trace): # `trace` can be a trace obj if trace is None: # if None, make a FlatTrace in the center of image trace_pos = nrows / 2 trace = FlatTrace(image, trace_pos) elif isinstance(trace, (float, int)): # if float/int make a FlatTrace trace = FlatTrace(image, trace) else: raise ValueError('`trace` must be Trace object, number to specify ' 'the location of a FlatTrace, or None to use center' ' of image.') if statistic not in ['median', 'average']: raise ValueError("`statistic` must be 'median' or 'average'.") # determine if there is one pixel/wavelength selected or many as either a # list or a tuple to specify a range if pixel is not None: if pixel_range is not None: raise ValueError('Both `pixel` and `pixel_range` can not be set' ' simultaneously.') if isinstance(pixel, (int, float)): pixels = np.array([int(pixel)]) elif np.all([isinstance(x, (int, float)) for x in pixel]): pixels = np.array([int(x) for x in pixel]) else: raise ValueError('`pixels` must be an integer, or list of integers ' 'to specify where the crossdisperion profile should ' 'be measured.') else: # range is specified if pixel_range is None: pixels = np.arange(0, ncols) else: # if not None, it should be a lower and upper bound if len(pixel_range) != 2: raise ValueError('`pixel_range` must be a tuple of integers.') pixels = np.arange(min(pixel_range), max(pixel_range)) # now that we have all pixels that should be included in the profile, make # sure that they are within image bounds. # note: Should just warn instead and clip out out-of-bounds pixels, and only # warn if there are none left? if np.any(pixels < 0) or np.any(pixels > ncols - 1): raise ValueError('Pixels chosen to measure cross dispersion profile are' ' out of image bounds.') # now that we know which pixel(s) on the disp. axis we want to include # figure out the range/window of pixels along the crossdisp axis to measure # the profile if width is None: # if None, use all rows width = nrows elif isinstance(width, (float, int)): width = int(width) else: raise ValueError('`width` must be an integer, or None to use all ' 'cross-dispersion pixels.') width = int(width) # rectify trace, if _align_along_trace is True and trace is not flat aligned_trace = None if align_along_trace: if not isinstance(trace, FlatTrace): # note: img was transposed according to `crossdisp_axis`: disp_axis will always be 1 aligned_trace = _align_along_trace(image, trace.trace, disp_axis=1, crossdisp_axis=0) # new trace will be a flat trace at the center of the image trace_pos = nrows / 2 trace = FlatTrace(aligned_trace, trace_pos) # create a weight image based on the trace and 'width' to mask around trace if width == nrows: wimg = np.zeros(image.shape) else: wimg = _ap_weight_image(trace, width, disp_axis, crossdisp_axis, image.shape) # invert mask to include, not exclude, pixels around trace wimg = (1 - wimg).astype(int) # now that we have figured out the mask for the window in cross-disp. axis, # select only the pixel(s) we want to include in measuring the avg. profile pixel_mask = np.ones((image.shape)) pixel_mask[:, pixels] = 0 # combine these masks to isolate the rows and cols used to measure profile combined_mask = np.logical_or(pixel_mask, wimg) if aligned_trace is not None: masked_arr = np.ma.MaskedArray(aligned_trace, combined_mask) else: masked_arr = np.ma.MaskedArray(image.data, combined_mask) # and measure the cross dispersion profile. if multiple pixels/wavelengths, # this will be an average. we already transposed data based on disp_axis so # axis is always 1 for this calculation if statistic == 'average': avg_prof = np.ma.mean(masked_arr, axis=1) else: # must be median, we already checked. avg_prof = np.ma.median(masked_arr, axis=1) # and get profile avg_prof = avg_prof.data[~avg_prof.mask] # and re-apply original unit, if there was one if unit is not None: avg_prof *= unit return avg_prof astropy-specreduce-05be828/specreduce/wavecal1d.py000066400000000000000000001267501510537250300222510ustar00rootroot00000000000000import warnings from functools import cached_property from math import isclose from typing import Sequence, Literal import astropy.units as u import numpy as np from astropy.modeling import models, Model, fitting, CompoundModel from matplotlib.pyplot import Axes, Figure, setp, subplots from numpy.ma import MaskedArray from numpy.typing import ArrayLike from scipy import optimize, ndimage from scipy.spatial import KDTree from specreduce.calibration_data import load_pypeit_calibration_lines from specreduce.compat import Spectrum from specreduce.line_matching import find_arc_lines __all__ = ["WavelengthCalibration1D"] from specreduce.wavesol1d import WavelengthSolution1D def _format_linelist(lst: ArrayLike) -> MaskedArray: """Force a line list into a MaskedArray with a shape of (n, 2) where n is the number of lines. Parameters ---------- lst Input array of centroids or centroids with amplitudes. Must be either: - A 1D array with a shape [n] for centroids. - A 2D array with a shape [n, 2] for centroids and amplitudes. Returns ------- numpy.ma.MaskedArray Formatted and standardized line list array with shape [n, 2], where each row contains a line centroid and amplitude. Raises ------ ValueError If the input line list does not meet the specified dimensional or shape requirements. """ lst: MaskedArray = MaskedArray(lst, copy=True) lst.mask = np.ma.getmaskarray(lst) if lst.ndim > 2 or lst.ndim == 2 and lst.shape[1] > 2: raise ValueError( "Line lists must be 1D with a shape [n] (centroids) or " "2D with a shape [n, 2] (centroids and amplitudes)." ) if lst.ndim == 1: lst = MaskedArray(np.tile(lst[:, None], [1, 2])) lst[:, 1] = 0.0 lst.mask[:, :] = lst.mask.any(axis=1)[:, None] return lst[np.argsort(lst.data[:, 0])] def _unclutter_text_boxes(labels: Sequence) -> None: """Remove overlapping labels from the plot. Removes overlapping text labels from a set of matplotlib label objects. The function iterates over all combinations of labels, checks for overlaps among their bounding boxes, and removes the label with the lower z-order in case of an overlap. Parameters ---------- labels A list of matplotlib.text.Text objects. """ to_remove = set() for i in range(len(labels)): for j in range(i + 1, len(labels)): l1 = labels[i] l2 = labels[j] bbox1 = l1.get_window_extent() bbox2 = l2.get_window_extent() if bbox1.overlaps(bbox2): if l1.zorder < l2.zorder: to_remove.add(l1) else: to_remove.add(l2) for label in to_remove: label.remove() class WavelengthCalibration1D: def __init__( self, arc_spectra: Spectrum | Sequence[Spectrum] | None = None, obs_lines: ArrayLike | Sequence[ArrayLike] | None = None, line_lists: ArrayLike | None = None, unit: u.Unit = u.angstrom, ref_pixel: float | None = None, pix_bounds: tuple[int, int] | None = None, line_list_bounds: None | tuple[float, float] = None, n_strogest_lines: None | int = None, wave_air: bool = False, ) -> None: """A class for wavelength calibration of one-dimensional spectra. This class is designed to facilitate wavelength calibration of one-dimensional spectra, with support for both direct input of line lists and observed spectra. It uses a polynomial model for fitting the wavelength solution and offers features to incorporate catalog lines and observed line positions. Parameters ---------- arc_spectra Arc spectra provided as ``Spectrum`` objects for wavelength fitting, by default None. This parameter and ``obs_lines`` cannot be provided simultaneously. obs_lines Pixel positions of observed spectral lines for wavelength fitting, by default None. This parameter and ``arc_spectra`` cannot be provided simultaneously. line_lists Catalogs of spectral line wavelengths for wavelength calibration. Provide either an array of line wavelengths or a list of `PypeIt `_ catalog names. If `None`, no line lists are used. You can query the list of available catalog names via `~specreduce.calibration_data.get_available_line_catalogs`. unit The unit of the wavelength calibration, by default ``astropy.units.Angstrom``. ref_pixel The reference pixel in which the wavelength solution will be centered. pix_bounds Lower and upper pixel bounds for fitting, defined as a tuple (min, max). If ``obs_lines`` is provided, this parameter is mandatory. line_list_bounds Wavelength bounds as a tuple (min, max) for filtering usable spectral lines from the provided line lists. n_strogest_lines The number of strongest lines to be included from the line lists. If `None`, all are included. wave_air Boolean indicating whether the input wavelengths correspond to air rather than vacuum; by default `False`, meaning vacuum wavelengths. """ self.unit = unit self._unit_str = unit.to_string("latex") self.degree = None self.ref_pixel = ref_pixel self.nframes = 0 if ref_pixel is not None and ref_pixel < 0: raise ValueError("Reference pixel must be positive.") self.arc_spectra: list[Spectrum] | None = None self.bounds_pix: tuple[int, int] | None = pix_bounds self.bounds_wav: tuple[float, float] | None = None self._cat_lines: list[MaskedArray] | None = None self._obs_lines: list[MaskedArray] | None = None self._trees: list[KDTree] | None = None self._fit: optimize.OptimizeResult | None = None self.solution = WavelengthSolution1D(None, pix_bounds, unit) # Read and store the observational data if given. The user can provide either a list of arc # spectra as Spectrum objects or a list of line pixel position arrays. An attempt to give # both raises an error. if arc_spectra is not None and obs_lines is not None: raise ValueError("Only one of arc_spectra or obs_lines can be provided.") if arc_spectra is not None: self.arc_spectra = [arc_spectra] if isinstance(arc_spectra, Spectrum) else arc_spectra self.nframes = len(self.arc_spectra) for s in self.arc_spectra: if s.data.ndim > 1: raise ValueError("The arc spectrum must be one dimensional.") if len(set([s.data.size for s in self.arc_spectra])) != 1: raise ValueError("All arc spectra must have the same length.") self.bounds_pix = (0, self.arc_spectra[0].shape[0]) self.solution.bounds_pix = self.bounds_pix if self.ref_pixel is None: self.ref_pixel = self.arc_spectra[0].data.size / 2 elif obs_lines is not None: self.observed_lines = obs_lines self.nframes = len(self._obs_lines) if self.bounds_pix is None: raise ValueError("Must give pixel bounds when providing observed line positions.") if self.ref_pixel is None: raise ValueError("Must give reference pixel when providing observed lines.") # Read the line lists if given. The user can provide an array of line wavelength positions # or a list of line list names (used by `load_pypeit_calibration_lines`) for each arc # spectrum. if line_lists is not None: if not isinstance(line_lists, (tuple, list)): line_lists = [line_lists] if len(line_lists) != self.nframes: raise ValueError("The number of line lists must match the number of arc spectra.") self._read_linelists( line_lists, line_list_bounds=line_list_bounds, wave_air=wave_air, n_strongest=n_strogest_lines, ) def _line_match_distance(self, x: ArrayLike, model: Model, max_distance: float = 100) -> float: """Compute the sum of distances between catalog lines and transformed observed lines. This function evaluates the pixel-to-wavelength model at the observed line positions, queries the nearest catalog line (via KDTree), and sums the distances after clipping them at `max_distance`. The result is suitable as a scalar objective for global optimization of the wavelength solution. Parameters ---------- x Pixel-to-wavelength model parameters (e.g., Polynomial1D coefficients c0..cN). model The pixel-to-wavelength model to be evaluated. max_distance Upper bound used to clip individual distances before summation. Returns ------- float Sum of nearest-neighbor distances between transformed observed lines and catalog lines. """ total_distance = 0.0 for t, l in zip(self._trees, self.observed_line_locations): transformed_lines = model.evaluate(l, -self.ref_pixel, *x)[:, None] total_distance += np.clip(t.query(transformed_lines)[0], 0, max_distance).sum() return total_distance def _read_linelists( self, line_lists: Sequence, line_list_bounds: None | tuple[float, float] = None, wave_air: bool = False, n_strongest: None | int = None, ) -> None: """Read and processes line lists. Parameters ---------- line_lists A collection of line lists that can either be arrays of wavelengths or `PypeIt `_ lamp names. You can query the list of available catalog names via `~specreduce.calibration_data.get_available_line_catalogs`. line_list_bounds A tuple specifying the minimum and maximum wavelength bounds. Only wavelengths within this range are retained. wave_air If True, convert the vacuum wavelengths used by `PypeIt `_ to air wavelengths. n_strongest The number of strongest lines to be used. If `None`, all lines are used. """ lines = [] for lst in line_lists: if isinstance(lst, np.ndarray): lines.append(lst) else: if isinstance(lst, str): lst = [lst] lines.append([]) for ll in lst: line_table = load_pypeit_calibration_lines(ll, wave_air=wave_air) if n_strongest is not None: ix = np.argsort(line_table["amplitude"].value)[::-1] lines[-1].append(line_table[ix][:n_strongest]["wavelength"].to( self.unit).value) else: lines[-1].append(line_table["wavelength"].to(self.unit).value) lines[-1] = np.ma.masked_array(np.sort(np.concatenate(lines[-1]))) if line_list_bounds is not None: for i, lst in enumerate(lines): lines[i] = lst[(lst >= line_list_bounds[0]) & (lst <= line_list_bounds[1])] self.catalog_lines = lines self._create_trees() def _create_trees(self) -> None: """Initialize the KDTree instances for the current set of catalog line locations.""" self._trees = [KDTree(lst.compressed()[:, None]) for lst in self.catalog_line_locations] def find_lines(self, fwhm: float, noise_factor: float = 1.0) -> None: """Find lines in the provided arc spectra. Determines the spectral lines within each spectrum of the arc spectra based on the provided initial guess for the line Full Width at Half Maximum (FWHM). Parameters ---------- fwhm Initial guess for the FWHM for the spectral lines, used as a parameter in the ``find_arc_lines`` function to locate and identify spectral arc lines. noise_factor The factor to multiply the uncertainty by to determine the noise threshold in the `~specutils.fitting.find_lines_threshold` routine. """ if self.arc_spectra is None: raise ValueError("Must provide arc spectra to find lines.") line_lists = [] for i, arc in enumerate(self.arc_spectra): lines = find_arc_lines(arc, fwhm, noise_factor=noise_factor) ix = np.round(lines["centroid"].value).astype(int) if np.any((ix < 0) | (ix >= arc.shape[0])): raise ValueError( "Error in arc line identification. Try increasing ``noise_factor``." ) amplitudes = ndimage.maximum_filter1d(arc.flux.value, 5)[ix] line_lists.append( np.ma.masked_array(np.transpose([lines["centroid"].value, amplitudes])) ) self.observed_lines = line_lists def _create_model(self, degree: int, coeffs: None | ArrayLike = None) -> CompoundModel: """Initialize the polynomial model with the given degree and an optional base model. This method sets up a polynomial transformation based on the reference pixel and degree. If coefficients are provided, they are copied to the initialized model up to the degree specified. Parameters ---------- degree Degree of the polynomial model to be initialized. coeffs Optional initial polynomial coefficients. """ self.degree = degree pars = {} if coeffs is not None: nc = min(degree + 1, len(coeffs)) pars = {f"c{i}": c for i, c in enumerate(coeffs[:nc])} return models.Shift(-self.ref_pixel) | models.Polynomial1D(self.degree, **pars) def fit_lines( self, pixels: ArrayLike, wavelengths: ArrayLike, degree: int = 3, match_obs: bool = False, match_cat: bool = False, refine_fit: bool = True, refine_max_distance: float = 5.0, refined_fit_degree: int | None = None, ) -> WavelengthSolution1D: """Fit the pixel-to-wavelength model using provided line pairs. This method fits the pixel-to-wavelength transformation using explicitly provided pairs of pixel coordinates and their corresponding wavelengths via a linear least-squares fit Optionally, the provided pixel and wavelength values can be "snapped" to the nearest values present in the internally stored observed line list and catalog line list, respectively. This allows the inputs to be approximate, as the snapping step selects the nearest precise centroids and catalog values when available. Parameters ---------- pixels An array of pixel positions corresponding to known spectral lines. wavelengths An array of the same size as ``pixels``, containing the known wavelengths corresponding to the given pixel positions. degree The polynomial degree for the wavelength solution. match_obs If True, snap the input ``pixels`` values to the nearest pixel values found in ``self.observed_line_locations`` (if available). This helps ensure the fit uses the precise centroids detected by `find_lines` or provided initially. match_cat If True, snap the input ``wavelengths`` values to the nearest wavelength values found in ``self.catalog_line_locations`` (if available). This ensures the fit uses the precise catalog wavelengths. refine_fit If True (default), automatically call the ``refine_fit`` method immediately after the global optimization to improve the solution using a least-squares fit on matched lines. refine_max_distance Maximum allowed separation between catalog and observed lines for them to be considered a match during ``refine_fit``. Ignored if ``refine_fit`` is False. refined_fit_degree The polynomial degree for the refined fit. Can be higher than ``degree``. If ``None``, equals to ``degree``. """ pixels = np.asarray(pixels) wavelengths = np.asarray(wavelengths) if pixels.size != wavelengths.size: raise ValueError("The sizes of pixel and wavelength arrays must match.") nlines = pixels.size if nlines < 2: raise ValueError("Need at least two lines for a fit") if self.bounds_pix is None: raise ValueError("Cannot fit without pixel bounds set.") # Match the input wavelengths to catalog lines. if match_cat: if self._cat_lines is None: raise ValueError("Cannot fit without catalog lines set.") tree = KDTree( np.concatenate([c.compressed() for c in self.catalog_line_locations])[:, None] ) ix = tree.query(wavelengths[:, None])[1] wavelengths = tree.data[ix][:, 0] # Match the input pixel values to observed pixel values. if match_obs: if self._obs_lines is None: raise ValueError("Cannot fit without observed lines set.") tree = KDTree( np.concatenate([c.compressed() for c in self.observed_line_locations])[:, None] ) ix = tree.query(pixels[:, None])[1] pixels = tree.data[ix][:, 0] fitter = fitting.LinearLSQFitter() shift, model = self._create_model(degree) if model.degree > nlines: warnings.warn( "The degree of the polynomial model is higher than the number of lines. " "Fixing the higher-order coefficients to zero." ) for i in range(nlines, model.degree + 1): model.fixed[f"c{i}"] = True model = fitter(model, pixels - self.ref_pixel, wavelengths) for i in range(model.degree + 1): model.fixed[f"c{i}"] = False self.solution.p2w = shift | model can_match = self._cat_lines is not None and self._obs_lines is not None if refine_fit and can_match: self.refine_fit(refined_fit_degree, max_match_distance=refine_max_distance) else: if can_match: self.match_lines() return self.solution def fit_dispersion( self, wavelength_bounds: tuple[float, float], dispersion_bounds: tuple[float, float], higher_order_limits: Sequence[float] | None = None, degree: int = 3, popsize: int = 30, max_distance: float = 100, refine_fit: bool = True, refine_max_distance: float = 5.0, refined_fit_degree: int | None = None, ) -> WavelengthSolution1D: """Calculate a wavelength solution using all the catalog and observed lines. This method estimates a wavelength solution without pre-matched pixel–wavelength pairs, making it suitable for automated pipelines on stable, well-characterized spectrographs. It uses differential evolution to optimize the polynomial parameters that minimize the distance between the predicted wavelengths of the observed lines and their nearest catalog lines. The resulting solution can optionally be refined with a least-squares fit to automatically matched lines. Parameters ---------- wavelength_bounds (min, max) bounds for the wavelength at ``ref_pixel``; used as an optimization constraint. dispersion_bounds (min, max) bounds for the dispersion d(wavelength)/d(pixel) at ``ref_pixel``; used as an optimization constraint. higher_order_limits Absolute limits for the higher-order polynomial coefficients. Each coefficient is constrained to [-limit, limit]. If provided, the number of limits must equal (polynomial degree - 1). degree The polynomial degree for the wavelength solution. popsize Population size for ``scipy.optimize.differential_evolution``. Larger values can improve the chance of finding the global minimum at the cost of additional time. max_distance Maximum wavelength separation used when associating observed and catalog lines in the optimization. Distances larger than this threshold are clipped to this value in the cost function to limit the impact of outliers. refine_fit If True (default), call ``refine_fit`` after global optimization to improve the solution using a least-squares fit on matched lines. refine_max_distance Maximum allowed separation between catalog and observed lines for them to be considered a match during ``refine_fit``. Ignored if ``refine_fit`` is False. refined_fit_degree The polynomial degree for the refined fit. Can be higher than ``degree``. If ``None``, equals to ``degree``. """ # Define bounds for differential_evolution. bounds = [np.asarray(wavelength_bounds), np.asarray(dispersion_bounds)] model = self._create_model(degree) if higher_order_limits is not None: if len(higher_order_limits) != model[1].degree - 1: raise ValueError( "The number of higher-order limits must match the degree of the polynomial " "model minus one." ) for v in higher_order_limits: bounds.append(np.asarray([-v, v])) else: for i in range(2, model[1].degree + 1): bounds.append( np.array([-1, 1]) * 10 ** (np.log10(np.mean(dispersion_bounds)) - 2 * i) ) bounds = np.array(bounds) self._fit = optimize.differential_evolution( lambda x: self._line_match_distance(x, model, max_distance), bounds=bounds, popsize=popsize, init="sobol", ) self.solution.p2w = self._create_model(degree, coeffs=self._fit.x) can_match = self._cat_lines is not None and self._obs_lines is not None if refine_fit: self.refine_fit(refined_fit_degree, max_match_distance=refine_max_distance) else: if can_match: self.match_lines() return self.solution def refine_fit( self, degree: None | int = None, max_match_distance: float = 5.0, max_iter: int = 5 ) -> WavelengthSolution1D: """Refine the pixel-to-wavelength transformation fit. Fits (or re-fits) the polynomial wavelength solution using the currently matched pixel–wavelength pairs. Optionally adjusts the polynomial degree, filters matches by a maximum pixel-space separation, and iterates the fit. Parameters ---------- degree The polynomial degree for the wavelength solution. If ``None``, the degree previously set by the `~WavelengthCalibration1D.fit_lines` or `~WavelengthCalibration1D.fit_dispersion` method will be used. max_match_distance Maximum allowable distance used to identify matched pixel and wavelength data points. Points exceeding the bound will not be considered in the fit. max_iter Maximum number of fitting iterations. """ # Create a new model with the current parameters if degree is specified. if degree is not None and degree != self.degree: model = self._create_model(degree, coeffs=self.solution.p2w[1].parameters) else: model = self.solution.p2w shift, poly = model fitter = fitting.LinearLSQFitter() rms = np.nan for i in range(max_iter): self.match_lines(max_match_distance) matched_pix = np.ma.concatenate(self.observed_line_locations).compressed() matched_wav = np.ma.concatenate(self.catalog_line_locations).compressed() rms_new = np.sqrt(((matched_wav - model(matched_pix)) ** 2).mean()) if isclose(rms_new, rms): break model = shift | fitter(poly, matched_pix - self.ref_pixel, matched_wav) rms = rms_new self.solution.p2w = model return self.solution @property def degree(self) -> None | int: return self._degree @degree.setter def degree(self, degree: int | None): if degree is not None and degree < 1: raise ValueError("Degree must be at least 1.") self._degree = degree @property def observed_lines(self) -> None | list[MaskedArray]: """Pixel positions and amplitudes of the observed lines as a list of masked arrays.""" return self._obs_lines @cached_property def observed_line_locations(self) -> None | list[MaskedArray]: """Pixel positions of the observed lines as a list of masked arrays.""" if self._obs_lines is None: return None else: return [line[:, 0] for line in self._obs_lines] @cached_property def observed_line_amplitudes(self) -> None | list[MaskedArray]: """Amplitudes of the observed lines as a list of masked arrays.""" if self._obs_lines is None: return None else: return [line[:, 1] for line in self._obs_lines] @observed_lines.setter def observed_lines(self, line_lists: ArrayLike | list[ArrayLike]): if not isinstance(line_lists, Sequence): line_lists = [line_lists] self._obs_lines = [] for lst in line_lists: self._obs_lines.append(_format_linelist(lst)) if hasattr(self, "observed_line_locations"): del self.observed_line_locations if hasattr(self, "observed_line_amplitudes"): del self.observed_line_amplitudes @property def catalog_lines(self) -> None | list[MaskedArray]: """Catalog line wavelengths as a list of masked arrays.""" return self._cat_lines @cached_property def catalog_line_locations(self) -> None | list[MaskedArray]: """Pixel positions of the catalog lines as a list of masked arrays.""" if self._cat_lines is None: return None else: return [line[:, 0] for line in self._cat_lines] @cached_property def catalog_line_amplitudes(self) -> None | list[MaskedArray]: """Amplitudes of the catalog lines as a list of masked arrays.""" if self._obs_lines is None: return None else: return [line[:, 1] for line in self._cat_lines] @catalog_lines.setter def catalog_lines(self, line_lists: ArrayLike | list[ArrayLike]): if not isinstance(line_lists, Sequence): line_lists = [line_lists] self._cat_lines = [] for lst in line_lists: self._cat_lines.append(_format_linelist(lst)) if hasattr(self, "catalog_line_locations"): del self.catalog_line_locations if hasattr(self, "catalog_line_amplitudes"): del self.catalog_line_amplitudes def match_lines(self, max_distance: float = 5) -> None: """Match the observed lines to theoretical lines. Parameters ---------- max_distance The maximum allowed distance between the catalog and observed lines for them to be considered a match. """ for iframe, tree in enumerate(self._trees): l, ix = tree.query( self.solution.p2w(self.observed_line_locations[iframe].data)[:, None], distance_upper_bound=max_distance, ) m = np.isfinite(l) # Check for observed lines that match a catalog line. # Remove all but the nearest match. This isn't an optimal solution, # we could also iterate the match by removing the currently matched # lines, but this works for now. uix, cnt = np.unique(ix[m], return_counts=True) if any(n := cnt > 1): for i, c in zip(uix[n], cnt[n]): s = ix == i r = np.zeros(c, dtype=bool) r[np.argmin(l[s])] = True m[s] = r self._cat_lines[iframe].mask[:, :] = True self._cat_lines[iframe].mask[ix[m], :] = False self._obs_lines[iframe].mask[:, :] = ~m[:, None] def remove_unmatched_lines(self) -> None: """Remove unmatched lines from observation and catalog line data.""" self.observed_lines = [lst.compressed().reshape([-1, 2]) for lst in self._obs_lines] self.catalog_lines = [lst.compressed().reshape([-1, 2]) for lst in self._cat_lines] self._create_trees() def rms(self, space: Literal["pixel", "wavelength"] = "wavelength") -> float: """Compute the RMS of the residuals between matched lines in the pixel or wavelength space. Parameters ---------- space The space in which to calculate the RMS residual. If 'wavelength', the calculation is performed in the wavelength space. If 'pixel', it is performed in the pixel space. Default is 'wavelength'. Returns ------- float """ self.match_lines() mpix = np.ma.concatenate(self.observed_line_locations).compressed() mwav = np.ma.concatenate(self.catalog_line_locations).compressed() if space == "wavelength": return np.sqrt(((mwav - self.solution.p2w(mpix)) ** 2).mean()) elif space == "pixel": return np.sqrt(((mpix - self.solution.w2p(mwav)) ** 2).mean()) else: raise ValueError("Space must be either 'pixel' or 'wavelength'") def _plot_lines( self, kind: Literal["observed", "catalog"], frames: int | Sequence[int] | None = None, axes: Axes | Sequence[Axes] | None = None, figsize: tuple[float, float] | None = None, plot_labels: bool | Sequence[bool] = True, map_x: bool = False, label_kwargs: dict | None = None, ) -> Figure: """ Plot lines with optional features such as wavelength mapping and label customization. Parameters ---------- kind Specifies the line list to plot. frames Frame indices to plot. If None, all frames are plotted. axes Axes object(s) where the lines should be plotted. If None, new Axes are generated. figsize Size of the figure to use if creating new Axes. Ignored if axes are provided. plot_labels Flag(s) indicating whether to display labels for the lines. If a single value is provided, it is applied to all frames. map_x If True, maps the x-axis values between pixel and wavelength space. label_kwargs Additional keyword arguments to customize the label style. Returns ------- Figure The Figure object containing the plotted spectral lines. """ largs = dict(backgroundcolor="w", rotation=90, size="small") if label_kwargs is not None: largs.update(label_kwargs) if frames is None: frames = np.arange(self.nframes) else: frames = np.atleast_1d(frames) if axes is None: fig, axes = subplots( frames.size, 1, figsize=figsize, constrained_layout=True, sharex="all" ) elif isinstance(axes, Axes): fig = axes.figure axes = [axes] else: fig = axes[0].figure axes = np.atleast_1d(axes) if isinstance(plot_labels, bool): plot_labels = np.full(frames.size, plot_labels, dtype=bool) if map_x and self.solution.p2w is None: raise ValueError("Cannot map between pixels and wavelengths without a fitted model.") if kind == "observed": transform = self.solution.pix_to_wav if map_x else lambda x: x linelists = self.observed_lines spectra = self.arc_spectra lc = "C0" else: transform = self.solution.wav_to_pix if map_x else lambda x: x linelists = self.catalog_lines spectra = None lc = "C1" ypad = 1.3 labels = [] for iframe, (ax, frame) in enumerate(zip(axes, frames)): if spectra is not None: spc = self.arc_spectra[iframe] vmax = np.nanmax(spc.flux.value) ax.plot(transform(spc.spectral_axis.value), spc.flux.value / vmax, "k") else: vmax = 1.0 if linelists is not None: labels.append([]) # Loop over individual lines in the line list. for i in range(linelists[iframe].shape[0]): c, a = linelists[iframe].data[i] ls = "-" if linelists[iframe].mask[i, 0] == 0 else ":" ax.plot(transform([c, c]), [a / vmax + 0.1, 1.27], c=lc, ls=ls, zorder=-100) if plot_labels[iframe]: lloc = transform(c) labels[-1].append( ax.text( lloc, ypad, np.round(lloc, 4 - 1 - int(np.floor(np.log10(lloc)))), ha="center", va="top", **largs, ) ) labels[-1][-1].set_clip_on(True) labels[-1][-1].zorder = a if (kind == "observed" and not map_x) or (kind == "catalog" and map_x): xlabel = "Pixel" else: xlabel = f"Wavelength {self._unit_str}" if kind == "catalog": axes[0].xaxis.set_label_position("top") axes[0].xaxis.tick_top() setp(axes[0], xlabel=xlabel) for ax in axes[1:]: ax.set_xticklabels([]) else: setp(axes[-1], xlabel=xlabel) for ax in axes[:-1]: ax.set_xticklabels([]) xlims = np.array([ax.get_xlim() for ax in axes]) setp(axes, xlim=(xlims[:, 0].min(), xlims[:, 1].max()), yticks=[]) if linelists is not None: fig.canvas.draw() for i in range(len(frames)): if plot_labels[i]: # Calculate the label bounding box upper limits and adjust the y-axis limits. tr_to_data = axes[i].transData.inverted() ymax = -np.inf for lb in labels[i]: ymax = max(ymax, tr_to_data.transform(lb.get_window_extent().p1)[1]) setp(axes[i], ylim=(-0.04, ymax * 1.06)) # Remove the overlapping labels prioritizing the high-amplitude lines. _unclutter_text_boxes(labels[i]) return fig def plot_catalog_lines( self, frames: int | Sequence[int] | None = None, axes: Axes | Sequence[Axes] | None = None, figsize: tuple[float, float] | None = None, plot_labels: bool | Sequence[bool] = True, map_to_pix: bool = False, label_kwargs: dict | None = None, ) -> Figure: """Plot the catalog lines. Parameters ---------- frames Specifies the frames to be plotted. If an integer, only one frame is plotted. If a sequence, the specified frames are plotted. If None, default selection or all frames are plotted. axes The matplotlib axes where catalog data will be plotted. If provided, the function will plot on these axes. If None, new axes will be created. figsize Specifies the dimensions of the figure as (width, height). If None, the default dimensions are used. plot_labels If True, the numerical values associated with the catalog data will be displayed in the plot. If False, only the graphical representation of the lines will be shown. map_to_pix Indicates whether the catalog data should be mapped to pixel coordinates before plotting. If True, the data is converted to pixel coordinates. label_kwargs Specifies the keyword arguments for the line label text objects. Returns ------- Figure The matplotlib figure containing the plotted catalog lines. """ return self._plot_lines( "catalog", frames=frames, axes=axes, figsize=figsize, plot_labels=plot_labels, map_x=map_to_pix, label_kwargs=label_kwargs, ) def plot_observed_lines( self, frames: int | Sequence[int] | None = None, axes: Axes | Sequence[Axes] | None = None, figsize: tuple[float, float] | None = None, plot_labels: bool | Sequence[bool] = True, map_to_wav: bool = False, label_kwargs: dict | None = None, ) -> Figure: """Plot observed spectral lines for the given arc spectra. Parameters ---------- frames Specifies the frame(s) for which the plot is to be generated. If None, all frames are plotted. When an integer is provided, a single frame is used. For a sequence of integers, multiple frames are plotted. axes Axes object(s) to plot the spectral lines on. If None, new axes are created. figsize Dimensions of the figure to be created, specified as a tuple (width, height). Ignored if ``axes`` is provided. plot_labels If True, plots the numerical values of the observed lines at their respective locations on the graph. map_to_wav Determines whether to map the x-axis values to wavelengths. label_kwargs Specifies the keyword arguments for the line label text objects. Returns ------- Figure The matplotlib figure containing the observed lines plot. """ fig = self._plot_lines( "observed", frames=frames, axes=axes, figsize=figsize, plot_labels=plot_labels, map_x=map_to_wav, label_kwargs=label_kwargs, ) for ax in fig.axes: ax.autoscale(True, "x", tight=True) return fig def plot_fit( self, frames: Sequence[int] | int | None = None, figsize: tuple[float, float] | None = None, plot_labels: bool = True, obs_to_wav: bool = False, cat_to_pix: bool = False, label_kwargs: dict | None = None, ) -> Figure: """Plot the fitted catalog and observed lines for the specified arc spectra. Parameters ---------- frames The indices of the frames to plot. If `None`, all frames from 0 to ``self.nframes - 1`` are plotted. figsize Defines the width and height of the figure in inches. If `None`, the default size is used. plot_labels If `True`, print line locations over the plotted lines. Can also be a list with the same length as ``frames``. obs_to_wav If `True`, transform the x-axis of observed lines to the wavelength domain using `self._p2w`, if available. cat_to_pix If `True`, transforms catalog data points to pixel values before plotting. label_kwargs Specifies the keyword arguments for the line label text objects. Returns ------- matplotlib.figure.Figure The figure object containing the generated subplots. """ if frames is None: frames = np.arange(self.nframes) else: frames = np.atleast_1d(frames) fig, axs = subplots(2 * frames.size, 1, constrained_layout=True, figsize=figsize) self.plot_catalog_lines( frames, axs[0::2], plot_labels=plot_labels, map_to_pix=cat_to_pix, label_kwargs=label_kwargs, ) self.plot_observed_lines( frames, axs[1::2], plot_labels=plot_labels, map_to_wav=obs_to_wav, label_kwargs=label_kwargs, ) xlims = np.array([ax.get_xlim() for ax in axs[::2]]) if obs_to_wav: setp(axs, xlim=(xlims[:, 0].min(), xlims[:, 1].max())) else: setp(axs[::2], xlim=(xlims[:, 0].min(), xlims[:, 1].max())) setp(axs[0], yticks=[], xlabel=f"Wavelength [{self._unit_str}]") for ax in axs[1:-1]: ax.set_xlabel("") ax.set_xticklabels("") axs[0].xaxis.set_label_position("top") axs[0].xaxis.tick_top() return fig def plot_residuals( self, ax: Axes | None = None, space: Literal["pixel", "wavelength"] = "wavelength", figsize: tuple[float, float] | None = None, ) -> Figure: """Plot the residuals of pixel-to-wavelength or wavelength-to-pixel transformation. Parameters ---------- ax Matplotlib Axes object to plot on. If None, a new figure and axes are created. space The reference space used for plotting residuals. Options are 'pixel' for residuals in pixel space or 'wavelength' for residuals in wavelength space. figsize The size of the figure in inches, if a new figure is created. Returns ------- matplotlib.figure.Figure """ if ax is None: fig, ax = subplots(figsize=figsize, constrained_layout=True) else: fig = ax.figure self.match_lines() mpix = np.ma.concatenate(self.observed_line_locations).compressed() mwav = np.ma.concatenate(self.catalog_line_locations).compressed() if space == "wavelength": twav = self.solution.pix_to_wav(mpix) ax.plot(mwav, mwav - twav, ".") ax.text( 0.98, 0.95, f"RMS = {np.sqrt(((mwav - twav) ** 2).mean()):4.2f} {self._unit_str}", transform=ax.transAxes, ha="right", va="top", ) setp( ax, xlabel=f"Wavelength [{self._unit_str}]", ylabel=f"Residuals [{self._unit_str}]", ) elif space == "pixel": tpix = self.solution.wav_to_pix(mwav) ax.plot(mpix, mpix - tpix, ".") ax.text( 0.98, 0.95, f"RMS = {np.sqrt(((mpix - tpix) ** 2).mean()):4.2f} pix", transform=ax.transAxes, ha="right", va="top", ) setp(ax, xlabel="Pixel", ylabel="Residuals [pix]") else: raise ValueError("Invalid space specified for plotting residuals.") ax.axhline(0, c="k", lw=1, ls="--") return fig astropy-specreduce-05be828/specreduce/wavelength_calibration.py000066400000000000000000000254711510537250300251130ustar00rootroot00000000000000from functools import cached_property import numpy as np from astropy import units as u from astropy.modeling.fitting import LMLSQFitter, LinearLSQFitter from astropy.modeling.models import Linear1D from astropy.table import QTable, hstack from gwcs import coordinate_frames as cf from gwcs import wcs from specreduce.compat import Spectrum __all__ = [ 'WavelengthCalibration1D' ] def _check_arr_monotonic(arr): # returns True if ``arr`` is either strictly increasing or strictly # decreasing, otherwise returns False. sorted_increasing = np.all(arr[1:] >= arr[:-1]) sorted_decreasing = np.all(arr[1:] <= arr[:-1]) return sorted_increasing or sorted_decreasing class WavelengthCalibration1D(): def __init__(self, input_spectrum, matched_line_list=None, line_pixels=None, line_wavelengths=None, catalog=None, input_model=Linear1D(), fitter=None): """ input_spectrum: `~specutils.Spectrum1D` A one-dimensional Spectrum calibration spectrum from an arc lamp or similar. matched_line_list: `~astropy.table.QTable`, optional An `~astropy.table.QTable` table with (minimally) columns named "pixel_center" and "wavelength" with known corresponding line pixel centers and wavelengths populated. line_pixels: list, array, `~astropy.table.QTable`, optional List or array of line pixel locations to anchor the wavelength solution fit. Can also be input as an `~astropy.table.QTable` table with (minimally) a column named "pixel_center". line_wavelengths: `~astropy.units.Quantity`, `~astropy.table.QTable`, optional `astropy.units.Quantity` array of line wavelength values corresponding to the line pixels defined in ``line_list``, assumed to be in the same order. Can also be input as an `~astropy.table.QTable` with (minimally) a "wavelength" column. catalog: list, str, `~astropy.table.QTable`, optional The name of a catalog of line wavelengths to load and use in automated and template-matching line matching. NOTE: This option is currently not implemented. input_model: `~astropy.modeling.Model` The model to fit for the wavelength solution. Defaults to a linear model. fitter: `~astropy.modeling.fitting.Fitter`, optional The fitter to use in optimizing the model fit. Defaults to `~astropy.modeling.fitting.LinearLSQFitter` if the model to fit is linear or `~astropy.modeling.fitting.LMLSQFitter` if the model to fit is non-linear. Note that either ``matched_line_list`` or ``line_pixels`` must be specified, and if ``matched_line_list`` is not input, at least one of ``line_wavelengths`` or ``catalog`` must be specified. """ self._input_spectrum = input_spectrum self._input_model = input_model self._cached_properties = ['fitted_model', 'residuals', 'wcs'] self.fitter = fitter self._potential_wavelengths = None self._catalog = catalog if not isinstance(input_spectrum, Spectrum): raise ValueError('Input spectrum must be Spectrum.') # We use either line_pixels or matched_line_list to create self._matched_line_list, # and check that various requirements are fulfilled by the input args. if matched_line_list is not None: pixel_arg = "matched_line_list" if not isinstance(matched_line_list, QTable): raise ValueError("matched_line_list must be an astropy.table.QTable.") self._matched_line_list = matched_line_list elif line_pixels is not None: pixel_arg = "line_pixels" if isinstance(line_pixels, (list, np.ndarray)): self._matched_line_list = QTable([line_pixels], names=["pixel_center"]) elif isinstance(line_pixels, QTable): self._matched_line_list = line_pixels else: raise ValueError("Either matched_line_list or line_pixels must be specified.") if "pixel_center" not in self._matched_line_list.columns: raise ValueError(f"{pixel_arg} must have a 'pixel_center' column.") if self._matched_line_list["pixel_center"].unit is None: self._matched_line_list["pixel_center"].unit = u.pix # check that pixels are monotonic if not _check_arr_monotonic(self._matched_line_list["pixel_center"]): raise ValueError('Pixels must be strictly increasing or decreasing.') # now that pixels have been determined from input, figure out wavelengths. if (line_wavelengths is None and catalog is None and "wavelength" not in self._matched_line_list.columns): raise ValueError("You must specify at least one of line_wavelengths, " "catalog, or 'wavelength' column in matched_line_list.") # Sanity checks on line_wavelengths value if line_wavelengths is not None: if (isinstance(self._matched_line_list, QTable) and "wavelength" in self._matched_line_list.columns): raise ValueError("Cannot specify line_wavelengths separately if there is" " a 'wavelength' column in matched_line_list.") if len(line_wavelengths) != len(self._matched_line_list): raise ValueError("If line_wavelengths is specified, it must have the same " f"length as {pixel_arg}") if not isinstance(line_wavelengths, (u.Quantity, QTable)): raise ValueError("line_wavelengths must be specified as an astropy.units.Quantity" " array or as an astropy.table.QTable") # make sure wavelengths (or freq) are monotonic and add wavelengths # to _matched_line_list if isinstance(line_wavelengths, u.Quantity): if not _check_arr_monotonic(line_wavelengths): if str(line_wavelengths.unit.physical_type) == "frequency": raise ValueError('Frequencies must be strictly increasing or decreasing.') raise ValueError('Wavelengths must be strictly increasing or decreasing.') self._matched_line_list["wavelength"] = line_wavelengths elif isinstance(line_wavelengths, QTable): if not _check_arr_monotonic(line_wavelengths['wavelength']): raise ValueError('Wavelengths must be strictly increasing or decreasing.') self._matched_line_list = hstack([self._matched_line_list, line_wavelengths]) # Parse desired catalogs of lines for matching. if catalog is not None: # For now we avoid going into the later logic and just throw an error raise NotImplementedError("No catalogs are available yet, please input " "wavelengths with line_wavelengths or as a " f"column in {pixel_arg}") if isinstance(catalog, QTable): if "wavelength" not in catalog.columns: raise ValueError("Catalog table must have a 'wavelength' column.") self._catalog = catalog else: # This will need to be updated to match up with Tim's catalog code if isinstance(catalog, list): self._catalog = catalog else: self._catalog = [catalog] for cat in self._catalog: if isinstance(cat, str): if cat not in self._available_catalogs: raise ValueError(f"Line list '{cat}' is not an available catalog.") def identify_lines(self): """ ToDo: Code matching algorithm between line pixel locations and potential line wavelengths from catalogs. """ pass def _clear_cache(self, *attrs): """ provide convenience function to clearing the cache for cached_properties """ if not len(attrs): attrs = self._cached_properties for attr in attrs: if attr in self.__dict__: del self.__dict__[attr] @property def available_catalogs(self): return self._available_catalogs @property def input_spectrum(self): return self._input_spectrum @input_spectrum.setter def input_spectrum(self, new_spectrum): # We want to clear the refined locations if a new calibration spectrum is provided self._clear_cache() self._input_spectrum = new_spectrum @property def input_model(self): return self._input_model @input_model.setter def input_model(self, input_model): self._clear_cache() self._input_model = input_model @cached_property def fitted_model(self): # computes and returns WCS after fitting self.model to self.refined_pixels x = self._matched_line_list["pixel_center"] y = self._matched_line_list["wavelength"] if self.fitter is None: # Flexible defaulting if self.fitter is None if self.input_model.linear: fitter = LinearLSQFitter(calc_uncertainties=True) else: fitter = LMLSQFitter(calc_uncertainties=True) else: fitter = self.fitter # Fit the model return fitter(self.input_model, x, y) @cached_property def residuals(self): """ calculate fit residuals between matched line list pixel centers and wavelengths and the evaluated fit model. """ x = self._matched_line_list["pixel_center"] y = self._matched_line_list["wavelength"] # Get the fit residuals by evaulating model return y - self.fitted_model(x) @cached_property def wcs(self): # Build a GWCS pipeline from the fitted model pixel_frame = cf.CoordinateFrame(1, "SPECTRAL", [0,], axes_names=["x",], unit=[u.pix,]) spectral_frame = cf.SpectralFrame(axes_names=["wavelength",], unit=[self._matched_line_list["wavelength"].unit,]) pipeline = [(pixel_frame, self.fitted_model), (spectral_frame, None)] wcsobj = wcs.WCS(pipeline) return wcsobj def apply_to_spectrum(self, spectrum=None): # returns Spectrum with wavelength calibration applied # actual line refinement and WCS solution should already be done so that this can # be called on multiple science sources spectrum = self.input_spectrum if spectrum is None else spectrum updated_spectrum = Spectrum(spectrum.flux, wcs=self.wcs, mask=spectrum.mask, uncertainty=spectrum.uncertainty) return updated_spectrum astropy-specreduce-05be828/specreduce/wavesol1d.py000066400000000000000000000217201510537250300222760ustar00rootroot00000000000000from functools import cached_property from typing import Callable import astropy.units as u import gwcs import numpy as np from astropy.modeling import models, CompoundModel from astropy.nddata import VarianceUncertainty from gwcs import coordinate_frames from numpy.ma import MaskedArray from numpy.typing import ArrayLike, NDArray from scipy.interpolate import interp1d from specreduce.compat import Spectrum __all__ = ["WavelengthSolution1D"] def _diff_poly1d(m: models.Polynomial1D) -> models.Polynomial1D: """Compute the derivative of a Polynomial1D model. Computes the derivative of a Polynomial1D model and returns a new Polynomial1D model representing the derivative. The coefficients of the input model are used to calculate the coefficients of the derivative model. For a Polynomial1D of degree n, the derivative is a Polynomial1D of degree n-1. Parameters ---------- m A Polynomial1D model for which the derivative is to be computed. Returns ------- A new Polynomial1D model representing the derivative of the input Polynomial1D model. """ coeffs = {f"c{i-1}": i * getattr(m, f"c{i}").value for i in range(1, m.degree + 1)} return models.Polynomial1D(m.degree - 1, **coeffs) class WavelengthSolution1D: def __init__( self, p2w: None | CompoundModel, bounds_pix: tuple[int, int], unit: u.Unit, ) -> None: """Class defining a one-dimensional wavelength solution. This class manages the mapping between pixel positions and wavelength values in a 1D spectrum, supporting both forward and reverse transformations. It provides methods for resampling spectra in the pixel-to-wavelength space while conserving flux, and integrates with GWCS for coordinate transformations. Initializes an object with pixel-to-wavelength transformation, pixel bounds, and measurement unit. Also, converts the unit to its LaTeX string representation. Parameters ---------- p2w The pixel-to-wavelength transformation model. If None, no transformation will be set. bounds_pix The lower and upper pixel bounds defining the range of the spectrum. unit The wavelength unit. """ self.unit = unit self._unit_str = unit.to_string("latex") self.bounds_pix: tuple[int, int] = bounds_pix self.bounds_wav: tuple[float, float] | None = None self._p2w: None | CompoundModel = None self.p2w = p2w @property def p2w(self) -> None | CompoundModel: """Pixel-to-wavelength transformation.""" return self._p2w @p2w.setter def p2w(self, m: CompoundModel) -> None: self._p2w = m self.ref_pixel = m[0].offset.value if m is not None else None if "p2w_dldx" in self.__dict__: del self.p2w_dldx if "w2p" in self.__dict__: del self.w2p if "gwcs" in self.__dict__: del self.gwcs @cached_property def p2w_dldx(self) -> CompoundModel: """Partial derivative of the pixel-to-wavelength transformation, (d lambda) / (d pix).""" return models.Shift(self._p2w.offset_0) | _diff_poly1d(self._p2w[1]) @cached_property def w2p(self) -> Callable: """Wavelength-to-pixel transformation.""" p = np.arange(self.bounds_pix[0] - 2, self.bounds_pix[1] + 2) self.bounds_wav = self.p2w(self.bounds_pix) return interp1d(self.p2w(p), p, bounds_error=False, fill_value=np.nan) def pix_to_wav(self, pix: float | ArrayLike) -> float | NDArray | MaskedArray: """Map pixel values into wavelength values. Parameters ---------- pix The pixel value(s) to be transformed into wavelength value(s). Returns ------- Transformed wavelength value(s) corresponding to the input pixel value(s). """ if isinstance(pix, MaskedArray): wav = self.p2w(pix.data) return np.ma.masked_array(wav, mask=pix.mask) else: return self.p2w(pix) def wav_to_pix(self, wav: float | ArrayLike) -> float | NDArray | MaskedArray: """Map wavelength values into pixel values. Parameters ---------- wav The wavelength value(s) to be converted into pixel value(s). Returns ------- The corresponding pixel value(s) for the input wavelength(s). """ if isinstance(wav, MaskedArray): pix = self.w2p(wav.data) return np.ma.masked_array(pix, mask=wav.mask) else: return self.w2p(wav) @cached_property def gwcs(self) -> gwcs.wcs.WCS: """GWCS object defining the mapping between pixel and spectral coordinate frames.""" pixel_frame = coordinate_frames.CoordinateFrame( 1, "SPECTRAL", (0,), axes_names=["x"], unit=[u.pix] ) spectral_frame = coordinate_frames.SpectralFrame( axes_names=("wavelength",), unit=[self.unit] ) pipeline = [(pixel_frame, self._p2w), (spectral_frame, None)] return gwcs.wcs.WCS(pipeline) def resample( self, spectrum: "Spectrum", nbins: int | None = None, wlbounds: tuple[float, float] | None = None, bin_edges: ArrayLike | None = None, ) -> Spectrum: """Bin the given pixel-space 1D spectrum to a wavelength space conserving the flux. This method bins a pixel-space spectrum to a wavelength space using the computed pixel-to-wavelength and wavelength-to-pixel transformations and their derivatives with respect to the spectral axis. The binning is exact and conserves the integrated flux. Parameters ---------- spectrum A Spectrum instance containing the flux to be resampled over the wavelength space. nbins The number of bins for resampling. If not provided, it defaults to the size of the input spectrum. wlbounds A tuple specifying the starting and ending wavelengths for resampling. If not provided, the wavelength bounds are inferred from the object's methods and the entire flux array is used. bin_edges Explicit bin edges in the wavelength space. Should be an 1D array-like [e_0, e_1, ..., e_n] with n = nbins + 1. The bins are created as [[e_0, e_1], [e_1, e_2], ..., [e_n-1, n]]. If provided, ``nbins`` and ``wlbounds`` are ignored. Returns ------- 1D spectrum binned to the specified wavelength bins. """ if nbins is not None and nbins < 0: raise ValueError("Number of bins must be non-zero and positive.") if self._p2w is None: raise ValueError("Wavelength solution not set.") flux = spectrum.flux.value pixels = spectrum.spectral_axis.value if spectrum.uncertainty is not None: ucty = spectrum.uncertainty.represent_as(VarianceUncertainty).array ucty_type = type(spectrum.uncertainty) else: ucty = np.zeros_like(flux) ucty_type = VarianceUncertainty npix = flux.size nbins = npix if nbins is None else nbins if wlbounds is None: l1, l2 = self.p2w(pixels[[0, -1]] + np.array([-0.5, 0.5])) else: l1, l2 = wlbounds if bin_edges is not None: bin_edges_wav = np.asarray(bin_edges) nbins = bin_edges_wav.size - 1 else: bin_edges_wav = np.linspace(l1, l2, num=nbins + 1) bin_edges_pix = np.clip(self.w2p(bin_edges_wav) + 0.5, 0, npix - 1e-12) bin_edge_ix = np.floor(bin_edges_pix).astype(int) bin_edge_w = bin_edges_pix - bin_edge_ix bin_centers_wav = 0.5 * (bin_edges_wav[:-1] + bin_edges_wav[1:]) flux_wl = np.zeros(nbins) ucty_wl = np.zeros(nbins) weights = np.zeros(npix) dldx = np.diff(self.p2w(np.arange(pixels[0], pixels[-1] + 2) - 0.5)) for i in range(nbins): i1, i2 = bin_edge_ix[i : i + 2] weights[:] = 0.0 if i1 != i2: weights[i1 + 1 : i2] = 1.0 weights[i1] = 1 - bin_edge_w[i] weights[i2] = bin_edge_w[i + 1] sl = slice(i1, i2 + 1) w = weights[sl] flux_wl[i] = (w * flux[sl] * dldx[sl]).sum() ucty_wl[i] = (w**2 * ucty[sl] * dldx[sl]).sum() else: fracw = bin_edges_pix[i + 1] - bin_edges_pix[i] flux_wl[i] = fracw * flux[i1] * dldx[i1] ucty_wl[i] = fracw**2 * ucty[i1] * dldx[i1] bin_widths_wav = np.diff(bin_edges_wav) flux_wl = flux_wl / bin_widths_wav * spectrum.flux.unit / self.unit ucty_wl = VarianceUncertainty(ucty_wl / bin_widths_wav**2).represent_as(ucty_type) return Spectrum(flux_wl, bin_centers_wav * self.unit, uncertainty=ucty_wl) astropy-specreduce-05be828/tox.ini000066400000000000000000000052511510537250300172110ustar00rootroot00000000000000[tox] envlist = py{311,312,313}-test{,-alldeps}{,-oldestdeps,-devdeps,-predeps}{,-cov} linkcheck codestyle [testenv] # Pass through the following environment variables which may be needed for the CI passenv = HOME,WINDIR,CI setenv = devdeps: PIP_EXTRA_INDEX_URL = https://pypi.anaconda.org/astropy/simple https://pypi.anaconda.org/liberfa/simple https://pypi.anaconda.org/scientific-python-nightly-wheels/simple # Run the tests in a temporary directory to make sure that we don't import # this package from the source tree changedir = .tmp/{envname} # tox environments are constructed with so-called 'factors' (or terms) # separated by hyphens, e.g. test-devdeps-cov. Lines below starting with factor: # will only take effect if that factor is included in the environment name. To # see a list of example environments that can be run, along with a description, # run: # # tox -l -v # description = run tests alldeps: with optional dependencies oldestdeps: with the oldest supported version of key dependencies devdeps: with the latest developer version of key dependencies predeps: with pre-releases of key dependencies cov: with test coverage # The following provides some specific pinnings for key packages deps = devdeps: numpy>=0.0.dev0 devdeps: scipy>=0.0.dev0 devdeps: pyerfa>=0.0.dev0 devdeps: astropy>=0.0.dev0 devdeps: git+https://github.com/astropy/specutils.git#egg=specutils devdeps: photutils>=0.0.dev0 devdeps: git+https://github.com/spacetelescope/synphot_refactor.git#egg=synphot oldestdeps: numpy==1.24.* oldestdeps: astropy==5.3.* oldestdeps: scipy==1.10.* oldestdeps: matplotlib==3.7.* oldestdeps: photutils==1.0.* oldestdeps: specutils==1.9.* # The following indicates which extras_require from setup.cfg will be installed extras = test alldeps: all install_command = !devdeps: python -I -m pip install # Force dev dependency with C-extension (synphot) to also build with numpy-dev devdeps: python -I -m pip install -v --pre commands = pip freeze !cov: pytest --pyargs specreduce {toxinidir}/docs {posargs} cov: pytest --pyargs specreduce {toxinidir}/docs --cov specreduce --cov-config={toxinidir}/pyproject.toml {posargs} cov: coverage xml -o {toxinidir}/coverage.xml pip_pre = predeps: true !predeps: false [testenv:linkcheck] changedir = docs description = check the links in the HTML docs extras = docs commands = pip freeze sphinx-build -W -b linkcheck . _build/html [testenv:codestyle] skip_install = true changedir = . description = check code style, e.g., with flake8 deps = flake8 commands = flake8 specreduce --count --extend-ignore E203