From 8db26c02b8d7cf4daa5d5ba58838b3d0ca7ac74c Mon Sep 17 00:00:00 2001 From: Karl Gordon Date: Wed, 6 Nov 2024 13:07:40 -0500 Subject: [PATCH 01/14] adding IUE and MIRI LRS to mocking --- measure_extinction/merge_obsspec.py | 118 +++++++++--------- .../utils/make_obsdata_from_model.py | 55 +++++++- 2 files changed, 110 insertions(+), 63 deletions(-) diff --git a/measure_extinction/merge_obsspec.py b/measure_extinction/merge_obsspec.py index f1e981b..e3c4b48 100644 --- a/measure_extinction/merge_obsspec.py +++ b/measure_extinction/merge_obsspec.py @@ -8,6 +8,7 @@ "merge_spex_obsspec", "merge_nircam_ss_obsspec", "merge_irs_obsspec", + "merge_miri_lrs_obspec", "merge_miri_ifu_obsspec", ] @@ -50,68 +51,6 @@ def _wavegrid(resolution, wave_range): return (full_wave, full_wave_min, full_wave_max) -def merge_iue_obsspec(obstables, output_resolution=1000): - """ - Merge one or more IUE 1D spectra into a single spectrum - on a uniform wavelength scale - - Parameters - ---------- - obstables : list of astropy Table objects - list of tables containing the observed IUE spectra - usually the result of reading tables - - output_resolution : float - output resolution of spectra - input spectrum assumed to be at the appropriate resolution - - Returns - ------- - output_table : astropy Table object - merged spectra - """ - wave_range = [1000.0, 3400.0] * u.angstrom - - iwave_range = wave_range.to(u.angstrom).value - full_wave, full_wave_min, full_wave_max = _wavegrid(output_resolution, iwave_range) - - n_waves = len(full_wave) - full_flux = np.zeros((n_waves), dtype=float) - full_unc = np.zeros((n_waves), dtype=float) - full_npts = np.zeros((n_waves), dtype=int) - for ctable in obstables: - # may want to add in the SYS-ERROR, but need to be careful - # to propagate it correctly, SYS-ERROR will not reduce with - # multiple spectra or measurements in a wavelength bin - cuncs = ctable["STAT-ERROR"].data - cwaves = ctable["WAVELENGTH"].data - cfluxes = ctable["FLUX"].data - cnpts = ctable["NPTS"].data - for k in range(n_waves): - (indxs,) = np.where( - (cwaves >= full_wave_min[k]) & (cwaves < full_wave_max[k]) & (cnpts > 0) - ) - if len(indxs) > 0: - weights = 1.0 / np.square(cuncs[indxs]) - full_flux[k] += np.sum(weights * cfluxes[indxs]) - full_unc[k] += np.sum(weights) - full_npts[k] += len(indxs) - - # divide by the net weights - (indxs,) = np.where(full_npts > 0) - if len(indxs) > 0: - full_flux[indxs] /= full_unc[indxs] - full_unc[indxs] = np.sqrt(1.0 / full_unc[indxs]) - - otable = Table() - otable["WAVELENGTH"] = Column(full_wave, unit=u.angstrom) - otable["FLUX"] = Column(full_flux, unit=u.erg / (u.s * u.cm * u.cm * u.angstrom)) - otable["SIGMA"] = Column(full_unc, unit=u.erg / (u.s * u.cm * u.cm * u.angstrom)) - otable["NPTS"] = Column(full_npts) - - return otable - - def merge_stis_obsspec(obstables, waveregion="UV", output_resolution=1000): """ Merge one or more STIS 1D spectra into a single spectrum @@ -345,6 +284,34 @@ def merge_gen_obsspec(obstables, wave_range, output_resolution=100): return otable +def merge_iue_obsspec(obstables, output_resolution=1000): + """ + Merge one or more IUE 1D spectra into a single spectrum + on a uniform wavelength scale + + Parameters + ---------- + obstables : list of astropy Table objects + list of tables containing the observed IUE spectra + usually the result of reading tables + + output_resolution : float + output resolution of spectra + input spectrum assumed to be at the appropriate resolution + + Returns + ------- + output_table : astropy Table object + merged spectra + """ + wave_range = [1000.0, 3400.0] * u.angstrom + + otable = merge_gen_obsspec( + obstables, wave_range, output_resolution=output_resolution, + ) + return otable + + def merge_irs_obsspec(obstables, output_resolution=150): """ Merge one or more Spitzer IRS 1D spectra into a single spectrum @@ -426,6 +393,33 @@ def merge_nircam_ss_obsspec(obstables, output_resolution=1600): return otable +def merge_miri_lrs_obsspec(obstables, output_resolution=100): + """ + Merge one or more MIRI LRS spectra into a single spectrum + on a uniform wavelength scale + + Parameters + ---------- + obstables : list of astropy Table objects + list of tables containing the observed IRS spectra + usually the result of reading tables + + output_resolution : float + output resolution of spectra + input spectrum assumed to be at the appropriate resolution + + Returns + ------- + output_table : astropy Table object + merged spectra + """ + wave_range = [5.0, 13.0] * u.micron + otable = merge_gen_obsspec( + obstables, wave_range, output_resolution=output_resolution, + ) + return otable + + def merge_miri_ifu_obsspec(obstables, output_resolution=3000): """ Merge one or more MIRI IFU 1D spectra into a single spectrum diff --git a/measure_extinction/utils/make_obsdata_from_model.py b/measure_extinction/utils/make_obsdata_from_model.py index 7d16956..69aad06 100644 --- a/measure_extinction/utils/make_obsdata_from_model.py +++ b/measure_extinction/utils/make_obsdata_from_model.py @@ -15,10 +15,12 @@ from measure_extinction.stardata import BandData from measure_extinction.merge_obsspec import ( + merge_iue_obsspec, merge_stis_obsspec, merge_irs_obsspec, merge_niriss_soss_obsspec, merge_nircam_ss_obsspec, + merge_miri_lrs_obsspec, merge_miri_ifu_obsspec, ) from measure_extinction.utils.mock_spectra_data import mock_stis_data @@ -311,6 +313,27 @@ def make_obsdata_from_model( "%s/Models/%s_full.fits" % (output_path, output_filebase), overwrite=True ) + iue_file = "%s_iue.fits" % (output_filebase) + if not only_dat: + # IUE mock observation + # Resolution approximately 300 + iue_fwhm_pix = rbres / 300.0 + g = Gaussian1DKernel(stddev=iue_fwhm_pix / 2.355) + # Convolve data + nflux = convolve(otable["FLUX"].data, g) + + iue_table = QTable() + iue_table["WAVELENGTH"] = otable["WAVELENGTH"] + iue_table["FLUX"] = nflux * fluxunit + iue_table["NPTS"] = otable["NPTS"] + iue_table["ERROR"] = Column(np.full((len(iue_table)), 1.0)) * fluxunit + + rb_iue = merge_iue_obsspec([iue_table]) + rb_iue["SIGMA"] = rb_iue["FLUX"] * 0.0 + rb_iue.write("%s/Models/%s" % (output_path, iue_file), overwrite=True) + + specinfo["IUE"] = iue_file + stis_uv_file = "%s_stis_uv.fits" % (output_filebase) stis_opt_file = "%s_stis_opt.fits" % (output_filebase) if not only_dat: @@ -391,6 +414,27 @@ def make_obsdata_from_model( specinfo["NIRCam_SS"] = nrc_file + miri_lrs_file = "%s_miri_lrs.fits" % (output_filebase) + if not only_dat: + # MIRI LRS mock observation + # Resolution approximately 100 + miri_lrs_fwhm_pix = rbres / 100.0 + g = Gaussian1DKernel(stddev=miri_lrs_fwhm_pix / 2.355) + # Convolve data + nflux = convolve(otable["FLUX"].data, g) + + miri_lrs_table = QTable() + miri_lrs_table["WAVELENGTH"] = otable["WAVELENGTH"] + miri_lrs_table["FLUX"] = nflux * fluxunit + miri_lrs_table["NPTS"] = otable["NPTS"] + miri_lrs_table["ERROR"] = Column(np.full((len(miri_lrs_table)), 1.0)) * fluxunit + + rb_miri_lrs = merge_miri_lrs_obsspec([miri_lrs_table]) + rb_miri_lrs["SIGMA"] = rb_miri_lrs["FLUX"] * 0.0 + rb_miri_lrs.write("%s/Models/%s" % (output_path, miri_lrs_file), overwrite=True) + + specinfo["MIRI_LRS"] = miri_lrs_file + mrs_file = "%s_miri_ifu.fits" % (output_filebase) if not only_dat: # Webb MIRI IFU mock observation @@ -482,14 +526,23 @@ def make_obsdata_from_model( "g-", ) + (indxs,) = np.where(rb_iue["NPTS"] > 0) + ax.plot(rb_iue["WAVELENGTH"][indxs].to(u.micron), rb_iue["FLUX"][indxs], "r-") + (indxs,) = np.where(rb_nrc["NPTS"] > 0) ax.plot(rb_nrc["WAVELENGTH"][indxs].to(u.micron), rb_nrc["FLUX"][indxs], "c-") (indxs,) = np.where(rb_lrs["NPTS"] > 0) ax.plot(rb_lrs["WAVELENGTH"][indxs].to(u.micron), rb_lrs["FLUX"][indxs], "r:") + (indxs,) = np.where(rb_nrc["NPTS"] > 0) + ax.plot(rb_nrc["WAVELENGTH"][indxs].to(u.micron), rb_nrc["FLUX"][indxs], "r-") + + (indxs,) = np.where(rb_miri_lrs["NPTS"] > 0) + ax.plot(rb_miri_lrs["WAVELENGTH"][indxs].to(u.micron), rb_miri_lrs["FLUX"][indxs], "r--") + (indxs,) = np.where(rb_mrs["NPTS"] > 0) - ax.plot(rb_mrs["WAVELENGTH"][indxs].to(u.micron), rb_mrs["FLUX"][indxs], "r-") + ax.plot(rb_mrs["WAVELENGTH"][indxs].to(u.micron), rb_mrs["FLUX"][indxs], "g-") ax.set_xscale("log") ax.set_yscale("log") From 76d03da8551d6af50378980329557910b4eddba6 Mon Sep 17 00:00:00 2001 From: Karl Gordon Date: Wed, 6 Nov 2024 13:17:11 -0500 Subject: [PATCH 02/14] fixing minor --- .../utils/make_obsdata_from_model.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/measure_extinction/utils/make_obsdata_from_model.py b/measure_extinction/utils/make_obsdata_from_model.py index 69aad06..9e99291 100644 --- a/measure_extinction/utils/make_obsdata_from_model.py +++ b/measure_extinction/utils/make_obsdata_from_model.py @@ -381,15 +381,15 @@ def make_obsdata_from_model( # Convolve data nflux = convolve(otable["FLUX"].data, g) - nrc_table = QTable() - nrc_table["WAVELENGTH"] = otable["WAVELENGTH"] - nrc_table["FLUX"] = nflux * fluxunit - nrc_table["NPTS"] = otable["NPTS"] - nrc_table["ERROR"] = Column(np.full((len(nrc_table)), 1.0)) * fluxunit + niriss_table = QTable() + niriss_table["WAVELENGTH"] = otable["WAVELENGTH"] + niriss_table["FLUX"] = nflux * fluxunit + niriss_table["NPTS"] = otable["NPTS"] + niriss_table["ERROR"] = Column(np.full((len(niriss_table)), 1.0)) * fluxunit - rb_nrc = merge_niriss_soss_obsspec([nrc_table]) - rb_nrc["SIGMA"] = rb_nrc["FLUX"] * 0.0 - rb_nrc.write("%s/Models/%s" % (output_path, nrs_file), overwrite=True) + rb_niriss = merge_niriss_soss_obsspec([niriss_table]) + rb_niriss["SIGMA"] = rb_niriss["FLUX"] * 0.0 + rb_niriss.write("%s/Models/%s" % (output_path, nrs_file), overwrite=True) specinfo["NIRISS_SOSS"] = nrs_file @@ -535,6 +535,9 @@ def make_obsdata_from_model( (indxs,) = np.where(rb_lrs["NPTS"] > 0) ax.plot(rb_lrs["WAVELENGTH"][indxs].to(u.micron), rb_lrs["FLUX"][indxs], "r:") + (indxs,) = np.where(rb_niriss["NPTS"] > 0) + ax.plot(rb_niriss["WAVELENGTH"][indxs].to(u.micron), rb_niriss["FLUX"][indxs], "r-") + (indxs,) = np.where(rb_nrc["NPTS"] > 0) ax.plot(rb_nrc["WAVELENGTH"][indxs].to(u.micron), rb_nrc["FLUX"][indxs], "r-") From a34e7a5b57989fa918ca93989892c3ca1c5179e3 Mon Sep 17 00:00:00 2001 From: Karl Gordon Date: Mon, 18 Nov 2024 12:36:50 -0500 Subject: [PATCH 03/14] fix typo --- measure_extinction/merge_obsspec.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/measure_extinction/merge_obsspec.py b/measure_extinction/merge_obsspec.py index e3c4b48..bd20c9b 100644 --- a/measure_extinction/merge_obsspec.py +++ b/measure_extinction/merge_obsspec.py @@ -8,7 +8,7 @@ "merge_spex_obsspec", "merge_nircam_ss_obsspec", "merge_irs_obsspec", - "merge_miri_lrs_obspec", + "merge_miri_lrs_obsspec", "merge_miri_ifu_obsspec", ] From 915df907035224e7a9cfe98bbddd1030753f5139 Mon Sep 17 00:00:00 2001 From: Karl Gordon Date: Fri, 22 Nov 2024 10:11:24 -0500 Subject: [PATCH 04/14] adding miri_lrs read and fix docstrings --- measure_extinction/stardata.py | 38 +++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/measure_extinction/stardata.py b/measure_extinction/stardata.py index a3ce335..0024608 100644 --- a/measure_extinction/stardata.py +++ b/measure_extinction/stardata.py @@ -497,7 +497,9 @@ def get_band_fluxes(self): _flux1_nu *= u.erg / (u.cm * u.cm * u.s * u.Hz) _flux1 = _flux1_nu.to( fluxunit, - equivalencies=u.spectral_density(poss_bands[pband_name][1] * u.micron), + equivalencies=u.spectral_density( + poss_bands[pband_name][1] * u.micron + ), ) _flux2_nu = np.power( 10.0, (-0.4 * (_mag_vals[0] - _mag_vals[1] + 48.60)) @@ -505,7 +507,9 @@ def get_band_fluxes(self): _flux2_nu *= u.erg / (u.cm * u.cm * u.s * u.Hz) _flux2 = _flux2_nu.to( fluxunit, - equivalencies=u.spectral_density(poss_bands[pband_name][1] * u.micron), + equivalencies=u.spectral_density( + poss_bands[pband_name][1] * u.micron + ), ) self.band_fluxes[pband_name] = ( 0.5 * (_flux1.value + _flux2.value), @@ -760,7 +764,7 @@ def read_stis(self, line, path="./"): ---------- line : string formatted line from DAT file - example: 'STIS = hd029647_stis.fits' + example: 'STIS = hd029647_stis.fits' or 'STIS_Opt = hd029647_stis_Opt.fits' path : string, optional location of the FITS files path @@ -882,7 +886,31 @@ def read_nircam_ss(self, line, path="./"): ---------- line : string formatted line from DAT file - example: 'NIRCam_SS = hd029647_irs.fits' + example: 'NIRCam_SS = hd029647_nircam_ss.fits' + + path : string, optional + location of the FITS files path + + Returns + ------- + Updates self.(file, wave_range, waves, flux, uncs, npts, n_waves) + """ + self.read_spectra(line, path) + + self.fluxes = self.fluxes.to( + fluxunit, equivalencies=u.spectral_density(self.waves) + ) + self.uncs = self.uncs.to(fluxunit, equivalencies=u.spectral_density(self.waves)) + + def read_miri_lrs(self, line, path="./"): + """ + Read in Webb/MRS LRS spectra + + Parameters + ---------- + line : string + formatted line from DAT file + example: 'MIRI_LRS = hd029647_miri_lrs.fits' path : string, optional location of the FITS files path @@ -906,7 +934,7 @@ def read_miri_ifu(self, line, path="./"): ---------- line : string formatted line from DAT file - example: 'MIRI_IFU = hd029647_irs.fits' + example: 'MIRI_IFU = hd029647_miri_ifu.fits' path : string, optional location of the FITS files path From 8749d38b79c3661bb6374206dd75e19e86cebb4e Mon Sep 17 00:00:00 2001 From: Karl Gordon Date: Fri, 22 Nov 2024 11:02:43 -0500 Subject: [PATCH 05/14] expanding data formats documentation --- docs/code_capabilities.rst | 5 ++- docs/data_formats.rst | 85 ++++++++++++++++++++++++++++++++++---- docs/index.rst | 2 +- docs/model_standards.rst | 2 + 4 files changed, 85 insertions(+), 9 deletions(-) diff --git a/docs/code_capabilities.rst b/docs/code_capabilities.rst index 35a06ce..8233a1d 100644 --- a/docs/code_capabilities.rst +++ b/docs/code_capabilities.rst @@ -83,9 +83,12 @@ The member functions of SpecData include: * read_spectra: generic read for a spectrum in a specifically formatted FITS file * read_fuse: read a FUSE spectrum * read_iue: read an IUE spectrum (includes cutting data > 3200 A) -* read_stis: read a Hubble/STIS spectrum +* read_stis: read a Hubble/STIS spectrum (either UV or optical range) * read_spex: read a IRTF/SpeX spectrum (includes scaling by corfacs) * read_irs: read a Spitzer/IRS spectrum (includes scaling by corfacs, cutting above some wavelength) +* read_nircam_ss: read in NIRCam/slitless spectrum +* read_miri_lrs: read in Webb/MIRI LRS spectrum +* read_miri_iuf: read in Webb/MIRI MRS spectrum * rebin_constres: rebin spectrum to a constant input resolution ExtData diff --git a/docs/data_formats.rst b/docs/data_formats.rst index 7a2711b..9796d8b 100644 --- a/docs/data_formats.rst +++ b/docs/data_formats.rst @@ -4,19 +4,90 @@ Data Formats ############ +The data for each stars is stored in a combination of an ASCII "DAT" file +and FITS "spectra" files. + DAT file ======== -Document the format of the DAT file +The ASCII file is the only required file. This file gives the photometry +and links to the FITS files that contain the spectroscopy. Many dat files +for stars used in literature dust extinction curves are provided in the +`extstar_data repository _`. + +An example of +such a file (for a star from Valencic et al. 2004) that gives the Johnson photometry, +location of IUE spectrum, and spectral types is below. This includes the +photometry and associated uncertainties in Vega magnitudes. Comments taking +an entire line are allowed if they start with a "#" character. + +:: + + # data file for observations of HD 38023 + V = 8.870 +/- 0.020 + B = 9.190 +/- 0.030 + U = 8.870 +/- 0.030 + J = 8.080 +/- 0.020 + H = 7.990 +/- 0.060 + K = 7.900 +/- 0.020 + IUE = IUE_Data/hd038023_iue.fits + sptype = B4V + uvsptype = B4IV + +A more complicated example giving photometry and spectroscopy from different sources +is below (from a star from Gordon et al. 2021; Decleir et al. 2022 among other studies). +The Johnson photometry is provide mainly as colors in this example. Photometry +rom IRAC/IRS/MIPS is provide in mJy. The different photometry units are converted to the +measure_extinction internal units when read into StarData. In addition, there are comments +provide after data using the ";" character. + +:: + + # data file for observations of HD 29647 + V = 8.31 +/- 0.017 ; UBVRI ref = Slutskij, Stalbovskij & Shevchenko 1980 (1980SvAL....6..397S) + (U-B) = 0.47 +/- 0.030 + (B-V) = 0.91 +/- 0.019 + (V-R) = 0.96 +/- 0.024 + (V-I) = 1.71 +/- 0.030 + J = 5.960 +/- 0.030 ; JHK ref = IRSA 2MASS All-Sky Point Source Catalog + H = 5.593 +/- 0.021 + K = 5.363 +/- 0.020 + # IRAC 1 and 2 seem off + IRAC1 = 2.23E+03 +/- 4.45E+01 mJy + IRAC2 = 1.50E+03 +/- 3.00E+01 mJy + IRAC3 = 1.06E+03 +/- 2.16E+01 mJy + IRAC4 = 5.42E+02 +/- 1.09E+01 mJy + IRS15 = 3.14E+02 +/- 6.51E+00 mJy + MIPS24 = 6.76E+01 +/- 1.89E+00 mJy + # WISE have extended source contamination, contaminated by scattered moonlight + # WISE 1, 2 and 3 spurious detection of scattered light halo + # WISE 1 and 2 seem off, have saturated pixels + WISE1 = 5.179 +/- 0.150 ; WISE ref = IRSA AllWISE Source Catalog + WISE2 = 4.905 +/- 0.068 + WISE3 = 4.882 +/- 0.023 + WISE4 = 3.821 +/- 0.033 + IUE = IUE_Data/hd029647_iue.fits + SpeX_SXD = SpeX_Data/hd029647_SXD_spex.fits + SpeX_LXD = SpeX_Data/hd029647_LXD_spex.fits + IRS = IRS_Data/hd029647_irs.fits + sptype = B7IV ; sptype ref = Murakawa, Tamura & Nagata 2000 (2000ApJS..128..603M) + uvsptype = B8III ; uvsptype ref = Valencic+2004 (2004ApJ...616..912V) + Spectra ======= -FITS binary table files to give the spectra. -Columns, header, etc. +The spectra are stored in FITS files with standard columns and wavelength grids. +The standard columns are "WAVELENGTH", "FLUX", "SIGMA", and "NPTS". These files +are created using the "merge_xxx_spec" functions provide in +:class:`~measure_extinction.merge_obsspec`. These ensure that all the spectra +from a specific source (e.g., IUE) have the same wavelength grid, units, and standard +columns. -Ingest of spectra in to format needed for this package. -Merge spectra and put on a common wavelength grid. +For some of the types of spectra (e.g., IUE, STIS, SpeX, NIRCam SS), +there are commandline code in the `measure_extinction/utils` subdirectory to +create such files from the commandline. -IUE example? Large + Small aperture observations give higher -dynamic range. +When using a stellar model for the comparison, each type of spectra supported is +simulated/mocked using code in the `measure_extinction/utils` subdirectory. +See :ref:`_model_standards`. diff --git a/docs/index.rst b/docs/index.rst index 97d83d2..cf83b5b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -30,8 +30,8 @@ User Documentation Extinction Calculation Capabilities + Data Formats Plotting - Observed Data Formats Stellar Models as Standards Reporting Issues diff --git a/docs/model_standards.rst b/docs/model_standards.rst index 2efe864..5116803 100644 --- a/docs/model_standards.rst +++ b/docs/model_standards.rst @@ -1,3 +1,5 @@ +.. _model_standards: + =========================== Stellar Models as Standards =========================== From 3af6017032397575c088a9e3b8f2903f9279564d Mon Sep 17 00:00:00 2001 From: Karl Gordon Date: Fri, 22 Nov 2024 11:18:56 -0500 Subject: [PATCH 06/14] fixing doc link --- docs/data_formats.rst | 2 +- docs/model_standards.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/data_formats.rst b/docs/data_formats.rst index 9796d8b..d7a6f94 100644 --- a/docs/data_formats.rst +++ b/docs/data_formats.rst @@ -90,4 +90,4 @@ create such files from the commandline. When using a stellar model for the comparison, each type of spectra supported is simulated/mocked using code in the `measure_extinction/utils` subdirectory. -See :ref:`_model_standards`. +See :ref:`model standards`. diff --git a/docs/model_standards.rst b/docs/model_standards.rst index 5116803..ce3a625 100644 --- a/docs/model_standards.rst +++ b/docs/model_standards.rst @@ -1,4 +1,4 @@ -.. _model_standards: +.. _model standards: =========================== Stellar Models as Standards From 9052aeefcb6b90906bb246bddbed1b9aef2519bb Mon Sep 17 00:00:00 2001 From: Karl Gordon Date: Fri, 22 Nov 2024 12:32:46 -0500 Subject: [PATCH 07/14] adding first merge tests --- .../tests/test_merge_obsspec.py | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 measure_extinction/tests/test_merge_obsspec.py diff --git a/measure_extinction/tests/test_merge_obsspec.py b/measure_extinction/tests/test_merge_obsspec.py new file mode 100644 index 0000000..1814417 --- /dev/null +++ b/measure_extinction/tests/test_merge_obsspec.py @@ -0,0 +1,56 @@ +import numpy as np +import astropy.units as u +from astropy.table import QTable + +from measure_extinction.merge_obsspec import fluxunit, _wavegrid, merge_miri_lrs_obsspec + + +def _check_genmerge(wave_range, resolution): + + wave1_info = _wavegrid(resolution, wave_range.value) + wave1 = wave1_info[0] * wave_range.unit + nwaves = len(wave1) + spec1 = np.full(nwaves, 1.0) * fluxunit + itable1 = QTable() + itable1["WAVELENGTH"] = wave1 + itable1["FLUX"] = np.full(nwaves, 1.0) * fluxunit + itable1["ERROR"] = 0.01 * itable1["FLUX"] + itable1["NPTS"] = np.full(nwaves, 1) + + itable2 = QTable() + itable2["WAVELENGTH"] = wave1 + itable2["FLUX"] = np.full(nwaves, 2.0) * fluxunit + # uncertainties are 1/2 of the first table + # same amplitude uncertainties = equal weighting + itable2["ERROR"] = 0.005 * itable2["FLUX"] + itable2["NPTS"] = np.full(nwaves, 1) + + # merge into standard format + otable = merge_miri_lrs_obsspec([itable1, itable2]) + + # check standard format + for ckey in ["WAVELENGTH", "FLUX", "SIGMA", "NPTS"]: + assert ckey in otable.keys() + + nowaves = len(otable["WAVELENGTH"]) + np.testing.assert_allclose(otable["FLUX"], np.full(nowaves, 1.5)) + + +def test_miri_lrs(): + + # generate mock spectra + wave_range = [0.4, 15.0] * u.micron + resolution = 150.0 + _check_genmerge(wave_range, resolution) + + +def test_miri_mrs(): + + # generate mock spectra + wave_range = [4.5, 32.0] * u.micron + resolution = 4000. + _check_genmerge(wave_range, resolution) + + +if __name__ == "__main__": + test_miri_lrs() From 5362ce540fa6955bb182000fde7ef7385ea53641 Mon Sep 17 00:00:00 2001 From: Karl Gordon Date: Fri, 22 Nov 2024 12:35:52 -0500 Subject: [PATCH 08/14] remove unused variable --- measure_extinction/tests/test_merge_obsspec.py | 1 - 1 file changed, 1 deletion(-) diff --git a/measure_extinction/tests/test_merge_obsspec.py b/measure_extinction/tests/test_merge_obsspec.py index 1814417..622aa0b 100644 --- a/measure_extinction/tests/test_merge_obsspec.py +++ b/measure_extinction/tests/test_merge_obsspec.py @@ -10,7 +10,6 @@ def _check_genmerge(wave_range, resolution): wave1_info = _wavegrid(resolution, wave_range.value) wave1 = wave1_info[0] * wave_range.unit nwaves = len(wave1) - spec1 = np.full(nwaves, 1.0) * fluxunit itable1 = QTable() itable1["WAVELENGTH"] = wave1 itable1["FLUX"] = np.full(nwaves, 1.0) * fluxunit From 90eec3447cb8d77ec0f59bf645d4bae65a3d65a3 Mon Sep 17 00:00:00 2001 From: Karl Gordon Date: Wed, 27 Nov 2024 16:37:20 -0500 Subject: [PATCH 09/14] adding more tests --- .../tests/test_merge_obsspec.py | 58 ++++++++++++++----- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/measure_extinction/tests/test_merge_obsspec.py b/measure_extinction/tests/test_merge_obsspec.py index 622aa0b..d2c4f6a 100644 --- a/measure_extinction/tests/test_merge_obsspec.py +++ b/measure_extinction/tests/test_merge_obsspec.py @@ -2,10 +2,21 @@ import astropy.units as u from astropy.table import QTable -from measure_extinction.merge_obsspec import fluxunit, _wavegrid, merge_miri_lrs_obsspec - - -def _check_genmerge(wave_range, resolution): +from measure_extinction.merge_obsspec import ( + fluxunit, + _wavegrid, + merge_iue_obsspec, + merge_irs_obsspec, + merge_niriss_soss_obsspec, + merge_nircam_ss_obsspec, + merge_miri_lrs_obsspec, + merge_miri_ifu_obsspec, +) + +# still need to add merging of STIS spectroscopy +# more complicated due to UV/optical options + +def _check_genmerge(wave_range, resolution, mergefunc): wave1_info = _wavegrid(resolution, wave_range.value) wave1 = wave1_info[0] * wave_range.unit @@ -25,7 +36,7 @@ def _check_genmerge(wave_range, resolution): itable2["NPTS"] = np.full(nwaves, 1) # merge into standard format - otable = merge_miri_lrs_obsspec([itable1, itable2]) + otable = mergefunc([itable1, itable2]) # check standard format for ckey in ["WAVELENGTH", "FLUX", "SIGMA", "NPTS"]: @@ -35,21 +46,38 @@ def _check_genmerge(wave_range, resolution): np.testing.assert_allclose(otable["FLUX"], np.full(nowaves, 1.5)) -def test_miri_lrs(): +def test_miri_iue(): + wave_range = [1000.0, 3400.0] * u.angstrom + resolution = 1000.0 + _check_genmerge(wave_range, resolution, merge_iue_obsspec) + + +def test_irs(): + wave_range = [5.0, 40.0] * u.micron + resolution = 150.0 + _check_genmerge(wave_range, resolution, merge_irs_obsspec) + - # generate mock spectra +def test_niriss_soss(): + wave_range = [0.85, 2.75] * u.micron + resolution = 700.0 + _check_genmerge(wave_range, resolution, merge_niriss_soss_obsspec) + + +def test_nircam_ss(): + wave_range = [2.35, 5.55] * u.micron + resolution = 1600.0 + _check_genmerge(wave_range, resolution, merge_nircam_ss_obsspec) + + +def test_miri_lrs(): wave_range = [0.4, 15.0] * u.micron resolution = 150.0 - _check_genmerge(wave_range, resolution) + _check_genmerge(wave_range, resolution, merge_miri_lrs_obsspec) def test_miri_mrs(): - - # generate mock spectra wave_range = [4.5, 32.0] * u.micron - resolution = 4000. - _check_genmerge(wave_range, resolution) - + resolution = 4000.0 + _check_genmerge(wave_range, resolution, merge_miri_ifu_obsspec) -if __name__ == "__main__": - test_miri_lrs() From 5877157e2241e5f1b1a36a2f04f7b05476a72276 Mon Sep 17 00:00:00 2001 From: Karl Gordon Date: Wed, 27 Nov 2024 17:49:56 -0500 Subject: [PATCH 10/14] pkg_resources to importlib update --- measure_extinction/plotting/plot_ext.py | 17 +++++++-------- measure_extinction/plotting/plot_spec.py | 10 +++------ measure_extinction/stardata.py | 4 ++-- measure_extinction/tests/test_calc_ext.py | 14 ++++++------- measure_extinction/tests/test_extdata.py | 21 +++++++++---------- measure_extinction/tests/test_plot_ext.py | 6 +++--- measure_extinction/tests/test_plot_spec.py | 4 ++-- measure_extinction/tests/test_stardata.py | 7 +++---- measure_extinction/utils/calc_ext.py | 16 +++++--------- measure_extinction/utils/helpers.py | 14 ++++++++++++- .../utils/make_all_tlusty_obsdata.py | 2 -- .../utils/make_obsdata_from_model.py | 9 ++------ measure_extinction/utils/merge_iue_spec.py | 9 +++----- .../utils/merge_miri_ifu_spec.py | 7 ++----- measure_extinction/utils/merge_nircam_spec.py | 7 ++----- measure_extinction/utils/merge_spex_spec.py | 9 ++------ measure_extinction/utils/merge_stis_spec.py | 7 ++----- measure_extinction/utils/mock_spectra_data.py | 5 +++-- measure_extinction/utils/plot_bandpasses.py | 9 ++++---- measure_extinction/utils/plot_modspec.py | 5 ----- measure_extinction/utils/scale_spex_spec.py | 8 +++---- 21 files changed, 78 insertions(+), 112 deletions(-) diff --git a/measure_extinction/plotting/plot_ext.py b/measure_extinction/plotting/plot_ext.py index f18e521..9b995ed 100755 --- a/measure_extinction/plotting/plot_ext.py +++ b/measure_extinction/plotting/plot_ext.py @@ -1,8 +1,3 @@ -#!/usr/bin/env python - -from __future__ import absolute_import, division, print_function, unicode_literals - -import pkg_resources import argparse import warnings import matplotlib.pyplot as plt @@ -11,6 +6,7 @@ import pandas as pd import os +from measure_extinction.utils.helpers import get_datapath from measure_extinction.extdata import ExtData from dust_extinction.parameter_averages import CCM89 @@ -92,8 +88,9 @@ def plot_average( Plots the average extinction curve """ # read in the average extinction curve (if it exists) - if os.path.isfile(path + filename): - average = ExtData(path + filename) + fname = f"{path}/{filename}" + if os.path.isfile(fname): + average = ExtData(fname) else: warnings.warn( "An average extinction curve with the name " @@ -331,8 +328,8 @@ def plot_HI(ax, wavenum=False): Indicates HI-lines on the plot """ # read in HI-lines - path = pkg_resources.resource_filename("measure_extinction", "data/") - table = pd.read_table(path + "HI_lines.list", sep=r"\s+", comment="#") + data_path = get_datapath() + table = pd.read_table(f"{data_path}/HI_lines.list", sep=r"\s+", comment="#") # group lines by series series_groups = table.groupby("n'") colors = plt.get_cmap("tab10") @@ -805,7 +802,7 @@ def main(): parser.add_argument( "--path", help="path to the data files", - default=pkg_resources.resource_filename("measure_extinction", "data/"), + default=get_datapath(), ) parser.add_argument("--alax", help="plot A(lambda)/A(X)", action="store_true") parser.add_argument( diff --git a/measure_extinction/plotting/plot_spec.py b/measure_extinction/plotting/plot_spec.py index 141fd0c..db800ca 100755 --- a/measure_extinction/plotting/plot_spec.py +++ b/measure_extinction/plotting/plot_spec.py @@ -1,14 +1,10 @@ -#!/usr/bin/env python - -from __future__ import absolute_import, division, print_function, unicode_literals - -import pkg_resources import argparse import matplotlib.pyplot as plt import numpy as np import astropy.units as u import pandas as pd +from measure_extinction.utils.helpers import get_datapath from measure_extinction.stardata import StarData @@ -26,7 +22,7 @@ def plot_HI(path, ax): Indicates HI-lines on the plot """ # read in HI-lines - table = pd.read_table(path + "HI_lines.list", sep=r"\s+", comment="#") + table = pd.read_table(f"{path}/HI_lines.list", sep=r"\s+", comment="#") # group lines by series series_groups = table.groupby("n'") colors = plt.get_cmap("tab10") @@ -479,7 +475,7 @@ def main(): parser.add_argument( "--path", help="path to the data files", - default=pkg_resources.resource_filename("measure_extinction", "data/"), + default=get_datapath(), ) parser.add_argument("--mlam4", help="plot lambda^4*F(lambda)", action="store_true") parser.add_argument("--HI_lines", help="indicate the HI-lines", action="store_true") diff --git a/measure_extinction/stardata.py b/measure_extinction/stardata.py index 0024608..fb5bca7 100644 --- a/measure_extinction/stardata.py +++ b/measure_extinction/stardata.py @@ -595,7 +595,7 @@ def _getspecfilename(line, path): eqpos = line.find("=") tfile = line[eqpos + 2 :].rstrip() - return path + tfile + return f"{path}/{tfile}" class SpecData: @@ -1102,7 +1102,7 @@ def read(self, deredden=False, only_bands=None): """ # open and read all the lines in the file - f = open(self.path + self.file, "r") + f = open(f"{self.path}/{self.file}", "r") self.datfile_lines = list(f) f.close() # get the photometric band data diff --git a/measure_extinction/tests/test_calc_ext.py b/measure_extinction/tests/test_calc_ext.py index 7476837..f19f1f2 100644 --- a/measure_extinction/tests/test_calc_ext.py +++ b/measure_extinction/tests/test_calc_ext.py @@ -1,22 +1,22 @@ -import pkg_resources import os +from measure_extinction.utils.helpers import get_datapath from measure_extinction.utils.calc_ext import calc_extinction, calc_ave_ext def test_calc_extinction(): - # get the location of the data files - data_path = pkg_resources.resource_filename("measure_extinction", "data/") - redstarname = "HD229238" compstarname = "HD204172" + # get the location of the data files + data_path = get_datapath() + # calculate the extinction curve calc_extinction(redstarname, compstarname, data_path, savepath=data_path) # check if an extinction curve has been calculated and saved to a fits file assert os.path.isfile( - data_path + "%s_%s_ext.fits" % (redstarname.lower(), compstarname.lower()) + f"{data_path}/{redstarname.lower()}_{compstarname.lower()}_ext.fits" ), ( "No FITS file has been created with the extinction curve of reddened star " + redstarname @@ -27,7 +27,7 @@ def test_calc_extinction(): def test_calc_ave_ext(): # get the location of the data files - data_path = pkg_resources.resource_filename("measure_extinction", "data/") + data_path = get_datapath() # list the same starpair 3 times so that an average curve will be calculated (it needs at least 3 sightlines) starpair_list = ["HD229238_HD204172", "HD229238_HD204172", "HD229238_HD204172"] @@ -38,5 +38,5 @@ def test_calc_ave_ext(): # check if the average extinction curve has been calculated and saved to a fits file assert os.path.isfile( - data_path + "average_ext.fits" + f"{data_path}/average_ext.fits" ), "No FITS file has been created with the average extinction curve" diff --git a/measure_extinction/tests/test_extdata.py b/measure_extinction/tests/test_extdata.py index 67fd1c7..72f5f0a 100644 --- a/measure_extinction/tests/test_extdata.py +++ b/measure_extinction/tests/test_extdata.py @@ -1,15 +1,14 @@ -import pkg_resources - import astropy.units as u import numpy as np +from measure_extinction.utils.helpers import get_datapath from measure_extinction.stardata import StarData from measure_extinction.extdata import ExtData, _hierarch_keywords, _get_column_val def test_calc_ext(): # get the location of the data files - data_path = pkg_resources.resource_filename("measure_extinction", "data/") + data_path = get_datapath() # read in the observed data of the stars redstar = StarData("hd229238.dat", path=data_path) @@ -34,7 +33,7 @@ def test_calc_ext(): def test_get_fitdata(): - data_path = pkg_resources.resource_filename("measure_extinction", "data/") + data_path = get_datapath() # read in the observed data of the stars redstar = StarData("hd229238.dat", path=data_path) @@ -62,7 +61,7 @@ def test_get_fitdata(): def test_calc_AV_RV(): # get the location of the data files - data_path = pkg_resources.resource_filename("measure_extinction", "data/") + data_path = get_datapath() # read in the observed data of the stars redstar = StarData("hd229238.dat", path=data_path) @@ -100,17 +99,17 @@ def test_get_column_val(): def test_fit_band_ext(): # only for alax=False (for now) # get the location of the data files - data_path = pkg_resources.resource_filename("measure_extinction", "data/") + data_path = get_datapath() # read in the extinction curve data - extdata = ExtData(data_path + "hd229238_hd204172_ext.fits") + extdata = ExtData(f"{data_path}/hd229238_hd204172_ext.fits") # fit the extinction curve with a powerlaw based on the band data extdata.fit_band_ext() # test the fitting results waves, exts, res = np.loadtxt( - data_path + "fit_band_ext_result_hd229238_hd204172.txt", unpack=True + f"{data_path}/fit_band_ext_result_hd229238_hd204172.txt", unpack=True ) np.testing.assert_almost_equal(extdata.model["waves"], waves) np.testing.assert_almost_equal(extdata.model["exts"], exts) @@ -124,17 +123,17 @@ def test_fit_band_ext(): # only for alax=False (for now) def test_fit_spex_ext(): # only for alax=False (for now) # get the location of the data files - data_path = pkg_resources.resource_filename("measure_extinction", "data/") + data_path = get_datapath() # read in the extinction curve data - extdata = ExtData(data_path + "hd229238_hd204172_ext.fits") + extdata = ExtData(f"{data_path}/hd229238_hd204172_ext.fits") # fit the extinction curve with a powerlaw based on the SpeX data extdata.fit_spex_ext() # test the fitting results waves, exts, res = np.loadtxt( - data_path + "fit_spex_ext_result_hd229238_hd204172.txt", unpack=True + f"{data_path}/fit_spex_ext_result_hd229238_hd204172.txt", unpack=True ) np.testing.assert_almost_equal(extdata.model["waves"], waves) np.testing.assert_almost_equal(extdata.model["exts"], exts) diff --git a/measure_extinction/tests/test_plot_ext.py b/measure_extinction/tests/test_plot_ext.py index 2405afd..4dc55fd 100644 --- a/measure_extinction/tests/test_plot_ext.py +++ b/measure_extinction/tests/test_plot_ext.py @@ -1,8 +1,8 @@ -import pkg_resources import os import warnings import pytest +from measure_extinction.utils.helpers import get_datapath from measure_extinction.plotting.plot_ext import ( plot_multi_extinction, plot_extinction, @@ -13,7 +13,7 @@ @pytest.mark.skip(reason="failing due to changes in matplotlib") def test_plot_extinction(): # get the location of the data files - data_path = pkg_resources.resource_filename("measure_extinction", "data/") + data_path = get_datapath() starpair = "HD229238_HD204172" # plot the extinction curve @@ -105,7 +105,7 @@ def test_plot_extinction(): def test_plot_average(): # get the location of the data files - data_path = pkg_resources.resource_filename("measure_extinction", "data/") + data_path = get_datapath() # plot the average extinction curve in a separate figure # with the default settings diff --git a/measure_extinction/tests/test_plot_spec.py b/measure_extinction/tests/test_plot_spec.py index 6b05876..7eb67ca 100644 --- a/measure_extinction/tests/test_plot_spec.py +++ b/measure_extinction/tests/test_plot_spec.py @@ -1,12 +1,12 @@ -import pkg_resources import os +from measure_extinction.utils.helpers import get_datapath from measure_extinction.plotting.plot_spec import plot_multi_spectra, plot_spectrum def test_plot_spectra(): # get the location of the data files - data_path = pkg_resources.resource_filename("measure_extinction", "data/") + data_path = get_datapath() starlist = ["hd229238", "hd204172"] # plot the spectra in separate figures diff --git a/measure_extinction/tests/test_stardata.py b/measure_extinction/tests/test_stardata.py index 2029b7b..9042af2 100644 --- a/measure_extinction/tests/test_stardata.py +++ b/measure_extinction/tests/test_stardata.py @@ -1,13 +1,12 @@ -import pkg_resources - import astropy.units as u +from measure_extinction.utils.helpers import get_datapath from measure_extinction.stardata import StarData def test_load_stardata(): # get the location of the data files - data_path = pkg_resources.resource_filename("measure_extinction", "data/") + data_path = get_datapath() # read in the observed data on the star star = StarData("hd229238.dat", path=data_path) @@ -18,7 +17,7 @@ def test_load_stardata(): def test_units_stardata(): # get the location of the data files - data_path = pkg_resources.resource_filename("measure_extinction", "data/") + data_path = get_datapath() # read in the observed data of the star star = StarData("hd229238.dat", path=data_path) diff --git a/measure_extinction/utils/calc_ext.py b/measure_extinction/utils/calc_ext.py index d249720..bc49b6f 100644 --- a/measure_extinction/utils/calc_ext.py +++ b/measure_extinction/utils/calc_ext.py @@ -1,10 +1,6 @@ -#!/usr/bin/env python - -from __future__ import absolute_import, division, print_function, unicode_literals - -import pkg_resources import argparse +from measure_extinction.utils.helpers import get_datapath from measure_extinction.stardata import StarData from measure_extinction.extdata import ExtData, AverageExtData @@ -31,9 +27,7 @@ def calc_extinction( extdata.trans_elv_elvebv() elif alav: extdata.trans_elv_alav() - extdata.save( - savepath + "%s_%s_ext.fits" % (redstarname.lower(), compstarname.lower()) - ) + extdata.save(f"{savepath}/{redstarname.lower()}_{compstarname.lower()}_ext.fits") def calc_ave_ext( @@ -65,10 +59,10 @@ def calc_ave_ext( """ extdatas = [] for starpair in starpair_list: - extdata = ExtData("%s%s_ext.fits" % (path, starpair.lower())) + extdata = ExtData(f"{path}/{starpair.lower()}_ext.fits") extdatas.append(extdata) average = AverageExtData(extdatas, min_number=min_number, mask=mask) - average.save(path + outname) + average.save(f"{path}/{outname}") def main(): @@ -79,7 +73,7 @@ def main(): parser.add_argument( "--path", help="path to data files", - default=pkg_resources.resource_filename("measure_extinction", "data/"), + default=get_datapath(), ) parser.add_argument( "--deredden", diff --git a/measure_extinction/utils/helpers.py b/measure_extinction/utils/helpers.py index 206c3df..73b4c34 100644 --- a/measure_extinction/utils/helpers.py +++ b/measure_extinction/utils/helpers.py @@ -1,6 +1,7 @@ import os +import importlib.resources as importlib_resources -__all__ = ["get_full_starfile"] +__all__ = ["get_full_starfile", "get_datapath"] def get_full_starfile(starname): @@ -25,3 +26,14 @@ def get_full_starfile(starname): def_path = "./" return fstarname, def_path + + +def get_datapath(): + """ + Determine the location of the data distributed along with the package + """ + # get the location of the data files + ref = importlib_resources.files("measure_extinction") / "data" + with importlib_resources.as_file(ref) as cdata_path: + data_path = str(cdata_path) + return data_path diff --git a/measure_extinction/utils/make_all_tlusty_obsdata.py b/measure_extinction/utils/make_all_tlusty_obsdata.py index 90b8696..9d8c211 100644 --- a/measure_extinction/utils/make_all_tlusty_obsdata.py +++ b/measure_extinction/utils/make_all_tlusty_obsdata.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python - import glob import argparse diff --git a/measure_extinction/utils/make_obsdata_from_model.py b/measure_extinction/utils/make_obsdata_from_model.py index 9e99291..479d5ef 100644 --- a/measure_extinction/utils/make_obsdata_from_model.py +++ b/measure_extinction/utils/make_obsdata_from_model.py @@ -1,7 +1,3 @@ -#!/usr/bin/env python - -import pkg_resources - import numpy as np import matplotlib.pyplot as plt from scipy.interpolate import interp1d @@ -13,6 +9,7 @@ from synphot import SpectralElement import stsynphot as STS +from measure_extinction.utils.helpers import get_datapath from measure_extinction.stardata import BandData from measure_extinction.merge_obsspec import ( merge_iue_obsspec, @@ -123,9 +120,7 @@ def get_phot(mwave, mflux, band_names, band_resp_filenames): bdata = BandData("BAND") # path for non-HST band response curves - data_path = pkg_resources.resource_filename( - "measure_extinction", "data/Band_RespCurves/" - ) + data_path = f"{get_datapath()}/Band_RespCurves/" # compute the fluxes in each band for k, cband in enumerate(band_names): diff --git a/measure_extinction/utils/merge_iue_spec.py b/measure_extinction/utils/merge_iue_spec.py index baa9ef2..ba06deb 100644 --- a/measure_extinction/utils/merge_iue_spec.py +++ b/measure_extinction/utils/merge_iue_spec.py @@ -1,8 +1,5 @@ import argparse -# import numpy as np -import pkg_resources - # from astropy.table import Table # from measure_extinction.merge_obsspec import merge_iue_obsspec @@ -16,12 +13,12 @@ parser.add_argument( "--inpath", help="path where original data files are stored", - default=pkg_resources.resource_filename("measure_extinction", "data/Orig"), + default="./", ) parser.add_argument( "--outpath", help="path where merged spectra will be stored", - default=pkg_resources.resource_filename("measure_extinction", "data/Out"), + default="./", ) parser.add_argument("--outname", help="Output filebase") parser.add_argument("--png", help="save figure as a png file", action="store_true") @@ -30,7 +27,7 @@ args = parser.parse_args() # incomplete - code to read in the files needed - # use_small capabiliy needed + # use_small capability needed # recalibration by Massa & Fitzpatrick IDL code needs to be recoded in python # iue_mergespec = merge_iue_obsspec(stable) diff --git a/measure_extinction/utils/merge_miri_ifu_spec.py b/measure_extinction/utils/merge_miri_ifu_spec.py index 4537c70..f565ce7 100644 --- a/measure_extinction/utils/merge_miri_ifu_spec.py +++ b/measure_extinction/utils/merge_miri_ifu_spec.py @@ -1,9 +1,6 @@ -#!/usr/bin/env python - import glob import argparse import numpy as np -import pkg_resources import matplotlib.pyplot as plt from astropy.table import QTable @@ -23,12 +20,12 @@ parser.add_argument( "--inpath", help="path where original data files are stored", - default=pkg_resources.resource_filename("measure_extinction", "data/Orig"), + default="./", ) parser.add_argument( "--outpath", help="path where merged spectra will be stored", - default=pkg_resources.resource_filename("measure_extinction", "data/Out"), + default="./", ) parser.add_argument("--outname", help="Output filebase") parser.add_argument("--png", help="save figure as a png file", action="store_true") diff --git a/measure_extinction/utils/merge_nircam_spec.py b/measure_extinction/utils/merge_nircam_spec.py index 9bea778..7428a64 100644 --- a/measure_extinction/utils/merge_nircam_spec.py +++ b/measure_extinction/utils/merge_nircam_spec.py @@ -1,9 +1,6 @@ -#!/usr/bin/env python - import glob import argparse import numpy as np -import pkg_resources import matplotlib.pyplot as plt from astropy.table import QTable @@ -23,12 +20,12 @@ parser.add_argument( "--inpath", help="path where original data files are stored", - default=pkg_resources.resource_filename("measure_extinction", "data/Orig"), + default="./", ) parser.add_argument( "--outpath", help="path where merged spectra will be stored", - default=pkg_resources.resource_filename("measure_extinction", "data/Out"), + default="./", ) parser.add_argument("--outname", help="Output filebase") parser.add_argument("--png", help="save figure as a png file", action="store_true") diff --git a/measure_extinction/utils/merge_spex_spec.py b/measure_extinction/utils/merge_spex_spec.py index cedee35..8268b79 100644 --- a/measure_extinction/utils/merge_spex_spec.py +++ b/measure_extinction/utils/merge_spex_spec.py @@ -1,9 +1,4 @@ -#!/usr/bin/env python - -from __future__ import absolute_import, division, print_function, unicode_literals - import argparse -import pkg_resources import os from astropy.table import Table @@ -58,12 +53,12 @@ def merge_spex(starname, inpath, outpath): parser.add_argument( "--inpath", help="path where original SpeX ASCII files are stored", - default=pkg_resources.resource_filename("measure_extinction", "data/Orig/NIR"), + default="./", ) parser.add_argument( "--outpath", help="path where merged SpeX spectra will be stored", - default=pkg_resources.resource_filename("measure_extinction", "data/Spectra"), + default="./", ) args = parser.parse_args() diff --git a/measure_extinction/utils/merge_stis_spec.py b/measure_extinction/utils/merge_stis_spec.py index 93bc27e..720b660 100644 --- a/measure_extinction/utils/merge_stis_spec.py +++ b/measure_extinction/utils/merge_stis_spec.py @@ -1,9 +1,6 @@ -#!/usr/bin/env python - import glob import argparse import numpy as np -import pkg_resources import matplotlib.pyplot as plt from astropy.table import Table @@ -38,12 +35,12 @@ def read_stis_archive_format(filename): parser.add_argument( "--inpath", help="path where original data files are stored", - default=pkg_resources.resource_filename("measure_extinction", "data/Orig"), + default="./", ) parser.add_argument( "--outpath", help="path where merged spectra will be stored", - default=pkg_resources.resource_filename("measure_extinction", "data/Out"), + default="./", ) parser.add_argument( "--ralph", action="store_true", help="Ralph Bohlin reduced data" diff --git a/measure_extinction/utils/mock_spectra_data.py b/measure_extinction/utils/mock_spectra_data.py index 4ddd463..2e0dcf6 100644 --- a/measure_extinction/utils/mock_spectra_data.py +++ b/measure_extinction/utils/mock_spectra_data.py @@ -1,10 +1,11 @@ -import pkg_resources import argparse import numpy as np import matplotlib.pyplot as plt from astropy.table import QTable import astropy.units as u +from measure_extinction.utils.helpers import get_datapath + __all__ = ["mock_stis_data"] @@ -55,7 +56,7 @@ def mock_stis_single_grating(moddata, gname="G140L", applylsfs=True): nlsfs = len(gtags) - data_path = pkg_resources.resource_filename("measure_extinction", "utils/STIS_LSF/") + data_path = f"{get_datapath()}/../utils/STIS_LSF/" lsfs = [] for i, ctag in enumerate(gtags): a = QTable.read( diff --git a/measure_extinction/utils/plot_bandpasses.py b/measure_extinction/utils/plot_bandpasses.py index 0074ba0..4b00355 100644 --- a/measure_extinction/utils/plot_bandpasses.py +++ b/measure_extinction/utils/plot_bandpasses.py @@ -1,7 +1,8 @@ from matplotlib import pyplot as plt -import pkg_resources from synphot import SpectralElement +from measure_extinction.utils.helpers import get_datapath + def plot_bandpasses(bands): # create the figure @@ -9,7 +10,7 @@ def plot_bandpasses(bands): # plot all response curves for band in bands: - bp = SpectralElement.from_file("%s%s.dat" % (band_path, band)) + bp = SpectralElement.from_file(f"{band_path}/{band}.dat") if "MIPS" in band: wavelengths = bp.waveset * 10**4 else: @@ -24,9 +25,7 @@ def plot_bandpasses(bands): if __name__ == "__main__": # path for band response curves - band_path = pkg_resources.resource_filename( - "measure_extinction", "data/Band_RespCurves/" - ) + band_path = f"{get_datapath()}/Band_RespCurves/" # define the different bandpasses bands = [ diff --git a/measure_extinction/utils/plot_modspec.py b/measure_extinction/utils/plot_modspec.py index 74b416e..0b631c8 100644 --- a/measure_extinction/utils/plot_modspec.py +++ b/measure_extinction/utils/plot_modspec.py @@ -1,8 +1,3 @@ -#!/usr/bin/env python - -from __future__ import absolute_import, division, print_function, unicode_literals - -# import pkg_resources import glob import argparse import matplotlib.pyplot as plt diff --git a/measure_extinction/utils/scale_spex_spec.py b/measure_extinction/utils/scale_spex_spec.py index b6684a1..a3ee535 100644 --- a/measure_extinction/utils/scale_spex_spec.py +++ b/measure_extinction/utils/scale_spex_spec.py @@ -7,8 +7,8 @@ import argparse import numpy as np import astropy.units as u -import pkg_resources +from measure_extinction.utils.helpers import get_datapath # function to get photometry from a spectrum def get_phot(spec, bands): @@ -37,9 +37,7 @@ def get_phot(spec, bands): ) # path for band response curves - band_path = pkg_resources.resource_filename( - "measure_extinction", "data/Band_RespCurves/" - ) + band_path = f"{get_datapath()}/Band_RespCurves/" # dictionary linking the bands to their response curves bandnames = { @@ -190,7 +188,7 @@ def calc_save_corfac_spex(starname, path): parser.add_argument( "--path", help="path where data files are stored", - default=pkg_resources.resource_filename("measure_extinction", "data/"), + default=get_datapath(), ) args = parser.parse_args() From d39c3aa65b05b35a4da35b19a7dfbcf3eefe2968 Mon Sep 17 00:00:00 2001 From: Karl Gordon Date: Wed, 27 Nov 2024 17:55:34 -0500 Subject: [PATCH 11/14] fixing codestyle --- measure_extinction/tests/test_merge_obsspec.py | 2 +- measure_extinction/utils/scale_spex_spec.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/measure_extinction/tests/test_merge_obsspec.py b/measure_extinction/tests/test_merge_obsspec.py index d2c4f6a..983022b 100644 --- a/measure_extinction/tests/test_merge_obsspec.py +++ b/measure_extinction/tests/test_merge_obsspec.py @@ -16,6 +16,7 @@ # still need to add merging of STIS spectroscopy # more complicated due to UV/optical options + def _check_genmerge(wave_range, resolution, mergefunc): wave1_info = _wavegrid(resolution, wave_range.value) @@ -80,4 +81,3 @@ def test_miri_mrs(): wave_range = [4.5, 32.0] * u.micron resolution = 4000.0 _check_genmerge(wave_range, resolution, merge_miri_ifu_obsspec) - diff --git a/measure_extinction/utils/scale_spex_spec.py b/measure_extinction/utils/scale_spex_spec.py index a3ee535..0149df8 100644 --- a/measure_extinction/utils/scale_spex_spec.py +++ b/measure_extinction/utils/scale_spex_spec.py @@ -10,6 +10,7 @@ from measure_extinction.utils.helpers import get_datapath + # function to get photometry from a spectrum def get_phot(spec, bands): """ From 5bd317fc04eaf7410f1a561f7d37c890ae04c94e Mon Sep 17 00:00:00 2001 From: Karl Gordon Date: Wed, 4 Dec 2024 10:31:56 -0500 Subject: [PATCH 12/14] typo --- docs/code_capabilities.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/code_capabilities.rst b/docs/code_capabilities.rst index 8233a1d..7dba7aa 100644 --- a/docs/code_capabilities.rst +++ b/docs/code_capabilities.rst @@ -88,7 +88,7 @@ The member functions of SpecData include: * read_irs: read a Spitzer/IRS spectrum (includes scaling by corfacs, cutting above some wavelength) * read_nircam_ss: read in NIRCam/slitless spectrum * read_miri_lrs: read in Webb/MIRI LRS spectrum -* read_miri_iuf: read in Webb/MIRI MRS spectrum +* read_miri_ifu: read in Webb/MIRI MRS spectrum * rebin_constres: rebin spectrum to a constant input resolution ExtData From 4e0d87b09654abe9bba03d85667b68c0d1762856 Mon Sep 17 00:00:00 2001 From: Karl Gordon Date: Wed, 4 Dec 2024 10:46:18 -0500 Subject: [PATCH 13/14] updating WFC3 wavelengths to pivot wavelengths --- measure_extinction/stardata.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/measure_extinction/stardata.py b/measure_extinction/stardata.py index fb5bca7..703829d 100644 --- a/measure_extinction/stardata.py +++ b/measure_extinction/stardata.py @@ -213,9 +213,11 @@ def get_poss_bands(): "WFC3_F110W", "WFC3_F160W", ] + # from Calamida et al. 2022 (Amp C) _wfc3_band_waves = np.array( - [0.2710, 0.3355, 0.4773, 0.6243, 0.7651, 0.8053, 1.1534, 1.5369] + [0.270330, 0.335465, 0.477217, 0.624196, 0.764830, 0.802932, 1.153446, 1.536918] ) + _wfc3_photflam = np.array( [ 3.223e-18, From aa17a864f65c129c1f437c585c551342b9b79367 Mon Sep 17 00:00:00 2001 From: Karl Gordon Date: Tue, 10 Dec 2024 13:00:40 -0500 Subject: [PATCH 14/14] addressing PR comments --- docs/code_capabilities.rst | 2 +- docs/data_formats.rst | 12 +++---- measure_extinction/merge_obsspec.py | 36 +++++++++---------- measure_extinction/stardata.py | 2 +- .../tests/test_merge_obsspec.py | 4 +-- .../utils/make_obsdata_from_model.py | 8 ++--- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/docs/code_capabilities.rst b/docs/code_capabilities.rst index 7dba7aa..57a77d3 100644 --- a/docs/code_capabilities.rst +++ b/docs/code_capabilities.rst @@ -86,7 +86,7 @@ The member functions of SpecData include: * read_stis: read a Hubble/STIS spectrum (either UV or optical range) * read_spex: read a IRTF/SpeX spectrum (includes scaling by corfacs) * read_irs: read a Spitzer/IRS spectrum (includes scaling by corfacs, cutting above some wavelength) -* read_nircam_ss: read in NIRCam/slitless spectrum +* read_nircam_ss: read in Webb/NIRCam slitless spectrum * read_miri_lrs: read in Webb/MIRI LRS spectrum * read_miri_ifu: read in Webb/MIRI MRS spectrum * rebin_constres: rebin spectrum to a constant input resolution diff --git a/docs/data_formats.rst b/docs/data_formats.rst index d7a6f94..66e49ed 100644 --- a/docs/data_formats.rst +++ b/docs/data_formats.rst @@ -4,7 +4,7 @@ Data Formats ############ -The data for each stars is stored in a combination of an ASCII "DAT" file +The data for each stars are stored in a combination of an ASCII "DAT" file and FITS "spectra" files. DAT file @@ -36,10 +36,10 @@ an entire line are allowed if they start with a "#" character. A more complicated example giving photometry and spectroscopy from different sources is below (from a star from Gordon et al. 2021; Decleir et al. 2022 among other studies). -The Johnson photometry is provide mainly as colors in this example. Photometry -rom IRAC/IRS/MIPS is provide in mJy. The different photometry units are converted to the +The Johnson photometry is provided mainly as colors in this example. Photometry +from IRAC/IRS/MIPS is provided in mJy. The different photometry units are converted to the measure_extinction internal units when read into StarData. In addition, there are comments -provide after data using the ";" character. +provided after data using the ";" character. :: @@ -79,13 +79,13 @@ Spectra The spectra are stored in FITS files with standard columns and wavelength grids. The standard columns are "WAVELENGTH", "FLUX", "SIGMA", and "NPTS". These files -are created using the "merge_xxx_spec" functions provide in +are created using the "merge_xxx_spec" functions provided in :class:`~measure_extinction.merge_obsspec`. These ensure that all the spectra from a specific source (e.g., IUE) have the same wavelength grid, units, and standard columns. For some of the types of spectra (e.g., IUE, STIS, SpeX, NIRCam SS), -there are commandline code in the `measure_extinction/utils` subdirectory to +there is commandline code in the `measure_extinction/utils` subdirectory to create such files from the commandline. When using a stellar model for the comparison, each type of spectra supported is diff --git a/measure_extinction/merge_obsspec.py b/measure_extinction/merge_obsspec.py index bd20c9b..6ae51ba 100644 --- a/measure_extinction/merge_obsspec.py +++ b/measure_extinction/merge_obsspec.py @@ -68,12 +68,12 @@ def merge_stis_obsspec(obstables, waveregion="UV", output_resolution=1000): output_resolution : float output resolution of spectra - input spectrum assumed to be at the appropriate resolution + input spectrum assumed to be at the observed resolution Returns ------- output_table : astropy Table object - merged spectra + merged spectrum """ if waveregion == "UV": wave_range = [1000.0, 3400.0] * u.angstrom @@ -142,12 +142,12 @@ def merge_spex_obsspec(obstable, mask=[], output_resolution=2000): output_resolution : float [default=2000] output resolution of spectrum - input spectrum assumed to be at the appropriate resolution + input spectrum assumed to be at the observed resolution Returns ------- output_table : astropy Table object - merged spectra + merged spectrum """ waves = obstable["WAVELENGTH"].data * 1e4 fluxes = obstable["FLUX"].data @@ -232,12 +232,12 @@ def merge_gen_obsspec(obstables, wave_range, output_resolution=100): output_resolution : float output resolution of spectra - input spectrum assumed to be at the appropriate resolution + input spectrum assumed to be at the observed resolution Returns ------- output_table : astropy Table object - merged spectra + merged spectrum """ iwave_range = wave_range.to(u.angstrom).value full_wave, full_wave_min, full_wave_max = _wavegrid(output_resolution, iwave_range) @@ -297,12 +297,12 @@ def merge_iue_obsspec(obstables, output_resolution=1000): output_resolution : float output resolution of spectra - input spectrum assumed to be at the appropriate resolution + input spectrum assumed to be at the observed resolution Returns ------- output_table : astropy Table object - merged spectra + merged spectrum """ wave_range = [1000.0, 3400.0] * u.angstrom @@ -325,12 +325,12 @@ def merge_irs_obsspec(obstables, output_resolution=150): output_resolution : float output resolution of spectra - input spectrum assumed to be at the appropriate resolution + input spectrum assumed to be at the observed resolution Returns ------- output_table : astropy Table object - merged spectra + merged spectrum """ wave_range = [5.0, 40.0] * u.micron otable = merge_gen_obsspec( @@ -352,12 +352,12 @@ def merge_niriss_soss_obsspec(obstables, output_resolution=700): output_resolution : float output resolution of spectra - input spectrum assumed to be at the appropriate resolution + input spectrum assumed to be at the observed resolution Returns ------- output_table : astropy Table object - merged spectra + merged spectrum """ wave_range = [0.85, 2.75] * u.micron otable = merge_gen_obsspec( @@ -379,12 +379,12 @@ def merge_nircam_ss_obsspec(obstables, output_resolution=1600): output_resolution : float output resolution of spectra - input spectrum assumed to be at the appropriate resolution + input spectrum assumed to be at the observed resolution Returns ------- output_table : astropy Table object - merged spectra + merged spectrum """ wave_range = [2.35, 5.55] * u.micron otable = merge_gen_obsspec( @@ -406,12 +406,12 @@ def merge_miri_lrs_obsspec(obstables, output_resolution=100): output_resolution : float output resolution of spectra - input spectrum assumed to be at the appropriate resolution + input spectrum assumed to be at the observed resolution Returns ------- output_table : astropy Table object - merged spectra + merged spectrum """ wave_range = [5.0, 13.0] * u.micron otable = merge_gen_obsspec( @@ -433,12 +433,12 @@ def merge_miri_ifu_obsspec(obstables, output_resolution=3000): output_resolution : float output resolution of spectra - input spectrum assumed to be at the appropriate resolution + input spectrum assumed to be at the observed resolution Returns ------- output_table : astropy Table object - merged spectra + merged spectrum """ wave_range = [4.8, 29.0] * u.micron otable = merge_gen_obsspec( diff --git a/measure_extinction/stardata.py b/measure_extinction/stardata.py index 703829d..240dd43 100644 --- a/measure_extinction/stardata.py +++ b/measure_extinction/stardata.py @@ -906,7 +906,7 @@ def read_nircam_ss(self, line, path="./"): def read_miri_lrs(self, line, path="./"): """ - Read in Webb/MRS LRS spectra + Read in Webb/MIRI LRS spectra Parameters ---------- diff --git a/measure_extinction/tests/test_merge_obsspec.py b/measure_extinction/tests/test_merge_obsspec.py index 983022b..529cb9e 100644 --- a/measure_extinction/tests/test_merge_obsspec.py +++ b/measure_extinction/tests/test_merge_obsspec.py @@ -47,7 +47,7 @@ def _check_genmerge(wave_range, resolution, mergefunc): np.testing.assert_allclose(otable["FLUX"], np.full(nowaves, 1.5)) -def test_miri_iue(): +def test_iue(): wave_range = [1000.0, 3400.0] * u.angstrom resolution = 1000.0 _check_genmerge(wave_range, resolution, merge_iue_obsspec) @@ -72,7 +72,7 @@ def test_nircam_ss(): def test_miri_lrs(): - wave_range = [0.4, 15.0] * u.micron + wave_range = [4.0, 15.0] * u.micron resolution = 150.0 _check_genmerge(wave_range, resolution, merge_miri_lrs_obsspec) diff --git a/measure_extinction/utils/make_obsdata_from_model.py b/measure_extinction/utils/make_obsdata_from_model.py index 479d5ef..06c84a2 100644 --- a/measure_extinction/utils/make_obsdata_from_model.py +++ b/measure_extinction/utils/make_obsdata_from_model.py @@ -314,16 +314,19 @@ def make_obsdata_from_model( # Resolution approximately 300 iue_fwhm_pix = rbres / 300.0 g = Gaussian1DKernel(stddev=iue_fwhm_pix / 2.355) - # Convolve data + # Convolve data to give the expected observed spectral resolution nflux = convolve(otable["FLUX"].data, g) iue_table = QTable() iue_table["WAVELENGTH"] = otable["WAVELENGTH"] iue_table["FLUX"] = nflux * fluxunit + # number of models points in the rebinned spectrum iue_table["NPTS"] = otable["NPTS"] + # no error in the models, hence required for the merge function iue_table["ERROR"] = Column(np.full((len(iue_table)), 1.0)) * fluxunit rb_iue = merge_iue_obsspec([iue_table]) + # set the uncertainties to zero as this is a model rb_iue["SIGMA"] = rb_iue["FLUX"] * 0.0 rb_iue.write("%s/Models/%s" % (output_path, iue_file), overwrite=True) @@ -533,9 +536,6 @@ def make_obsdata_from_model( (indxs,) = np.where(rb_niriss["NPTS"] > 0) ax.plot(rb_niriss["WAVELENGTH"][indxs].to(u.micron), rb_niriss["FLUX"][indxs], "r-") - (indxs,) = np.where(rb_nrc["NPTS"] > 0) - ax.plot(rb_nrc["WAVELENGTH"][indxs].to(u.micron), rb_nrc["FLUX"][indxs], "r-") - (indxs,) = np.where(rb_miri_lrs["NPTS"] > 0) ax.plot(rb_miri_lrs["WAVELENGTH"][indxs].to(u.micron), rb_miri_lrs["FLUX"][indxs], "r--")