PyNOT-redux 2.1.2__tar.gz → 2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pynot_redux-2.1.2 → pynot_redux-2.2}/PKG-INFO +14 -2
- {pynot_redux-2.1.2 → pynot_redux-2.2}/PyNOT_redux.egg-info/PKG-INFO +14 -2
- {pynot_redux-2.1.2 → pynot_redux-2.2}/PyNOT_redux.egg-info/SOURCES.txt +21 -1
- pynot_redux-2.2/pynot/VERSION +1 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/data/io.py +8 -6
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/data/organizer.py +6 -1
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/extract_gui.py +13 -31
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/fitsio.py +35 -15
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/identify_gui.py +31 -3
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/main.py +52 -1
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/redux.py +2 -2
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/scombine.py +31 -16
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/skysub.py +1 -0
- pynot_redux-2.2/pynot/viewer/__init__.py +0 -0
- pynot_redux-2.2/pynot/viewer/containers.py +82 -0
- pynot_redux-2.2/pynot/viewer/default_linelists.json +103 -0
- pynot_redux-2.2/pynot/viewer/dust.py +149 -0
- pynot_redux-2.2/pynot/viewer/linelists.py +170 -0
- pynot_redux-2.2/pynot/viewer/messages.py +34 -0
- pynot_redux-2.2/pynot/viewer/models.py +300 -0
- pynot_redux-2.2/pynot/viewer/notes.py +255 -0
- pynot_redux-2.2/pynot/viewer/spectrum.py +386 -0
- pynot_redux-2.2/pynot/viewer/tablemodels.py +258 -0
- pynot_redux-2.2/pynot/viewer/targets.py +115 -0
- pynot_redux-2.2/pynot/viewer/templates/Assef_2010.dat +323 -0
- pynot_redux-2.2/pynot/viewer/templates/FeII.Vestergaard.dat +4182 -0
- pynot_redux-2.2/pynot/viewer/templates/FeIII.Vestergaard.dat +4182 -0
- pynot_redux-2.2/pynot/viewer/templates/Hernan_Caballero_quasar_NIR_template.txt +512 -0
- pynot_redux-2.2/pynot/viewer/templates/QSO_selsing.dat +5334 -0
- pynot_redux-2.2/pynot/viewer/templates/QSO_template.Krawczyk_all.dat +273 -0
- pynot_redux-2.2/pynot/viewer/templates/QSO_template.Krawczyk_high.dat +273 -0
- pynot_redux-2.2/pynot/viewer/templates/QSO_template.Krawczyk_low.dat +273 -0
- pynot_redux-2.2/pynot/viewer/viewer.py +944 -0
- pynot_redux-2.1.2/pynot/VERSION +0 -1
- {pynot_redux-2.1.2 → pynot_redux-2.2}/.gitattributes +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/.github/dependabot.yml +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/.gitignore +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/LICENSE +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/MANIFEST.in +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/PyNOT_redux.egg-info/dependency_links.txt +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/PyNOT_redux.egg-info/entry_points.txt +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/PyNOT_redux.egg-info/requires.txt +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/PyNOT_redux.egg-info/top_level.txt +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/README.md +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/.extract_msg +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/.identify_msg +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/.instrument.cfg +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/.response_msg +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/__init__.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/alfosc.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/HeAr_linelist.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/HeNe_linelist.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/ThAr_linelist.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/al-gr18_pixeltable.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/al-gr19_pixeltable.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/al-gr4_pixeltable.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/al-gr7_pixeltable.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/alfosc_filters.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/default_options.yml +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/default_options_img.yml +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/ef-gr13_pixeltable.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/ef-gr14_pixeltable.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/ef-gr1_pixeltable.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/ef-gr3_pixeltable.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/efosc_filters.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/lapalma.ext +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/lasilla.ext +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/paranal.ext +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/std/bd174708.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/std/bd262606.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/std/bd332642.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/std/bd75325.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/std/eg21.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/std/feige110.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/std/feige34.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/std/gd153.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/std/gd50.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/std/gd71.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/std/hd19445.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/std/hd84937.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/std/hd93521.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/std/he3.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/std/hiltner600.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/std/ltt3864.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/std/tcs_namelist.txt +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calib/std/wolf1346.dat +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/calibs.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/data/__init__.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/data/alfosc.rules +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/data/efosc.rules +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/data/help/welcome_msg_extract.html +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/data/help/welcome_msg_identify.html +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/data/help/welcome_msg_response.html +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/data/obs.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/efosc.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/extraction.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/functions.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/images.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/insconfig.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/logging.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/operations.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/phot.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/phot_redux.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/reports.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/response.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/response_gui.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/scired.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/tasks.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/transients.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/txtio.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/wavecal.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/wcs.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pynot/welcome.py +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/pyproject.toml +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/requirements.txt +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/setup.cfg +0 -0
- {pynot_redux-2.1.2 → pynot_redux-2.2}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: PyNOT-redux
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2
|
|
4
4
|
Summary: Data Reduction Pipeline for NOT/ALFOSC
|
|
5
5
|
Home-page: https://github.com/jkrogager/PyNOT
|
|
6
6
|
Author: Jens-Kristian Krogager
|
|
@@ -28,6 +28,18 @@ Requires-Dist: sep
|
|
|
28
28
|
Requires-Dist: astroalign
|
|
29
29
|
Requires-Dist: astroquery
|
|
30
30
|
Requires-Dist: beautifulsoup4
|
|
31
|
+
Dynamic: author
|
|
32
|
+
Dynamic: author-email
|
|
33
|
+
Dynamic: classifier
|
|
34
|
+
Dynamic: description
|
|
35
|
+
Dynamic: description-content-type
|
|
36
|
+
Dynamic: home-page
|
|
37
|
+
Dynamic: keywords
|
|
38
|
+
Dynamic: license
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
Dynamic: requires-dist
|
|
41
|
+
Dynamic: requires-python
|
|
42
|
+
Dynamic: summary
|
|
31
43
|
|
|
32
44
|
# PyNOT-redux
|
|
33
45
|
A Data Processing Pipeline for ALFOSC at the Nordic Optical Telescope
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: PyNOT-redux
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2
|
|
4
4
|
Summary: Data Reduction Pipeline for NOT/ALFOSC
|
|
5
5
|
Home-page: https://github.com/jkrogager/PyNOT
|
|
6
6
|
Author: Jens-Kristian Krogager
|
|
@@ -28,6 +28,18 @@ Requires-Dist: sep
|
|
|
28
28
|
Requires-Dist: astroalign
|
|
29
29
|
Requires-Dist: astroquery
|
|
30
30
|
Requires-Dist: beautifulsoup4
|
|
31
|
+
Dynamic: author
|
|
32
|
+
Dynamic: author-email
|
|
33
|
+
Dynamic: classifier
|
|
34
|
+
Dynamic: description
|
|
35
|
+
Dynamic: description-content-type
|
|
36
|
+
Dynamic: home-page
|
|
37
|
+
Dynamic: keywords
|
|
38
|
+
Dynamic: license
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
Dynamic: requires-dist
|
|
41
|
+
Dynamic: requires-python
|
|
42
|
+
Dynamic: summary
|
|
31
43
|
|
|
32
44
|
# PyNOT-redux
|
|
33
45
|
A Data Processing Pipeline for ALFOSC at the Nordic Optical Telescope
|
|
@@ -91,4 +91,24 @@ pynot/data/obs.py
|
|
|
91
91
|
pynot/data/organizer.py
|
|
92
92
|
pynot/data/help/welcome_msg_extract.html
|
|
93
93
|
pynot/data/help/welcome_msg_identify.html
|
|
94
|
-
pynot/data/help/welcome_msg_response.html
|
|
94
|
+
pynot/data/help/welcome_msg_response.html
|
|
95
|
+
pynot/viewer/__init__.py
|
|
96
|
+
pynot/viewer/containers.py
|
|
97
|
+
pynot/viewer/default_linelists.json
|
|
98
|
+
pynot/viewer/dust.py
|
|
99
|
+
pynot/viewer/linelists.py
|
|
100
|
+
pynot/viewer/messages.py
|
|
101
|
+
pynot/viewer/models.py
|
|
102
|
+
pynot/viewer/notes.py
|
|
103
|
+
pynot/viewer/spectrum.py
|
|
104
|
+
pynot/viewer/tablemodels.py
|
|
105
|
+
pynot/viewer/targets.py
|
|
106
|
+
pynot/viewer/viewer.py
|
|
107
|
+
pynot/viewer/templates/Assef_2010.dat
|
|
108
|
+
pynot/viewer/templates/FeII.Vestergaard.dat
|
|
109
|
+
pynot/viewer/templates/FeIII.Vestergaard.dat
|
|
110
|
+
pynot/viewer/templates/Hernan_Caballero_quasar_NIR_template.txt
|
|
111
|
+
pynot/viewer/templates/QSO_selsing.dat
|
|
112
|
+
pynot/viewer/templates/QSO_template.Krawczyk_all.dat
|
|
113
|
+
pynot/viewer/templates/QSO_template.Krawczyk_high.dat
|
|
114
|
+
pynot/viewer/templates/QSO_template.Krawczyk_low.dat
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.2
|
|
@@ -23,6 +23,7 @@ def get_header_info(fname):
|
|
|
23
23
|
slit = hdr['SLIT']
|
|
24
24
|
filter = '...'
|
|
25
25
|
shape = "..."
|
|
26
|
+
binning = "NxM_NA"
|
|
26
27
|
else:
|
|
27
28
|
hdr = instrument.get_header(fname)
|
|
28
29
|
object = instrument.get_object(hdr)
|
|
@@ -31,7 +32,8 @@ def get_header_info(fname):
|
|
|
31
32
|
slit = instrument.get_slit(hdr)
|
|
32
33
|
filter = instrument.get_filter(hdr)
|
|
33
34
|
shape = "%ix%i" % (hdr['NAXIS1'], hdr['NAXIS2'])
|
|
34
|
-
|
|
35
|
+
binning = instrument.get_binning_from_hdr(hdr)
|
|
36
|
+
return object, exptime, grism, slit, filter, shape, binning
|
|
35
37
|
|
|
36
38
|
|
|
37
39
|
def save_database(database, output_fname):
|
|
@@ -46,20 +48,20 @@ def save_database(database, output_fname):
|
|
|
46
48
|
for fname in sorted_files:
|
|
47
49
|
try:
|
|
48
50
|
if fname[0] == '#':
|
|
49
|
-
object, exptime, grism, slit, filter, shape = get_header_info(fname[1:])
|
|
51
|
+
object, exptime, grism, slit, filter, shape, binning = get_header_info(fname[1:])
|
|
50
52
|
else:
|
|
51
|
-
object, exptime, grism, slit, filter, shape = get_header_info(fname)
|
|
53
|
+
object, exptime, grism, slit, filter, shape, binning = get_header_info(fname)
|
|
52
54
|
except FileNotFoundError:
|
|
53
55
|
print("[WARNING] - File not found: %s" % fname)
|
|
54
56
|
continue
|
|
55
57
|
except Exception:
|
|
56
58
|
print("[WARNING] - Problem reading header information: %s" % fname)
|
|
57
|
-
object, exptime, grism, slit, filter, shape = '-', '-', '-', '-', '-', '-'
|
|
58
|
-
file_list.append((fname, filetype, object, exptime, grism, slit, filter, shape))
|
|
59
|
+
object, exptime, grism, slit, filter, shape, binning = '-', '-', '-', '-', '-', '-', '-'
|
|
60
|
+
file_list.append((fname, filetype, object, exptime, grism, slit, filter, shape, binning))
|
|
59
61
|
file_list = np.array(file_list, dtype=str)
|
|
60
62
|
if len(file_list) == 0:
|
|
61
63
|
continue
|
|
62
|
-
header_names = ('FILENAME', 'TYPE', 'OBJECT', 'EXPTIME', 'GRISM', 'SLIT', 'FILTER', 'SHAPE')
|
|
64
|
+
header_names = ('FILENAME', 'TYPE', 'OBJECT', 'EXPTIME', 'GRISM', 'SLIT', 'FILTER', 'SHAPE', 'BINNING')
|
|
63
65
|
max_len = np.max(veclen(file_list), 0)
|
|
64
66
|
max_len = np.max([max_len, [len(n) for n in header_names]], 0)
|
|
65
67
|
line_fmt = " ".join(["%-{}s".format(n) for n in max_len])
|
|
@@ -200,7 +200,8 @@ def sort_bias(file_list, date=False):
|
|
|
200
200
|
for fname in file_list:
|
|
201
201
|
hdr = instrument.get_header(fname)
|
|
202
202
|
size = "%ix%i" % (hdr['NAXIS1'], hdr['NAXIS2'])
|
|
203
|
-
|
|
203
|
+
binning = instrument.get_binning_from_hdr(hdr)
|
|
204
|
+
file_id = f"{size}_{binning}"
|
|
204
205
|
if date:
|
|
205
206
|
date_str = instrument.get_date(hdr)
|
|
206
207
|
if 'T' in date_str:
|
|
@@ -677,6 +678,10 @@ class RawImage(object):
|
|
|
677
678
|
criteria.append(this_filter == self.filter)
|
|
678
679
|
criteria_name.append('filter')
|
|
679
680
|
|
|
681
|
+
if debug:
|
|
682
|
+
print(criteria_name)
|
|
683
|
+
print(criteria)
|
|
684
|
+
|
|
680
685
|
if np.all(criteria):
|
|
681
686
|
matches.append(fname)
|
|
682
687
|
all_times.append(this_mjd)
|
|
@@ -51,27 +51,6 @@ def run_gui(input_fname, output_fname, app=None, **ext_kwargs):
|
|
|
51
51
|
del gui
|
|
52
52
|
|
|
53
53
|
|
|
54
|
-
# def save_ascii_spectrum(fname, wl, flux, err, hdr, bg=None):
|
|
55
|
-
# """Write spectrum to an ascii text file with header saved to separate text file."""
|
|
56
|
-
# if bg is not None:
|
|
57
|
-
# data_table = np.column_stack([wl, flux, err, bg])
|
|
58
|
-
# fmt = "%12.4f % .3e %.3e %.3e"
|
|
59
|
-
# col_names = "# Wavelength Flux Error Sky"
|
|
60
|
-
# else:
|
|
61
|
-
# data_table = np.column_stack([wl, flux, err])
|
|
62
|
-
# fmt = "%12.4f % .3e %.3e"
|
|
63
|
-
# col_names = "# Wavelength Flux Error"
|
|
64
|
-
#
|
|
65
|
-
# basename, ext = os.path.splitext(fname)
|
|
66
|
-
# header_fname = basename + '_hdr.txt'
|
|
67
|
-
#
|
|
68
|
-
# with open(fname, 'w') as output:
|
|
69
|
-
# output.write(col_names + "\n")
|
|
70
|
-
# np.savetxt(output, data_table, fmt=fmt)
|
|
71
|
-
# hdr.tofile(header_fname, sep='\n', endcard=False, padding=False, overwrite=True)
|
|
72
|
-
# return True, "File saved successfully"
|
|
73
|
-
|
|
74
|
-
|
|
75
54
|
def get_FWHM(y, x=None):
|
|
76
55
|
"""
|
|
77
56
|
Measure the FWHM of the profile given as `y`.
|
|
@@ -285,8 +264,8 @@ class BackgroundModel(object):
|
|
|
285
264
|
self.patches[index].remove()
|
|
286
265
|
self.patches.pop(index)
|
|
287
266
|
self.ranges[index] = [i_low, i_high]
|
|
288
|
-
self.vlines[index][0].set_xdata(i_low)
|
|
289
|
-
self.vlines[index][1].set_xdata(i_high)
|
|
267
|
+
self.vlines[index][0].set_xdata([i_low])
|
|
268
|
+
self.vlines[index][1].set_xdata([i_high])
|
|
290
269
|
patch = self.axis.axvspan(i_low, i_high, color='#29b6f6', alpha=0.3, picker=True)
|
|
291
270
|
self.patches.insert(index, patch)
|
|
292
271
|
|
|
@@ -407,13 +386,13 @@ class TraceModel(object):
|
|
|
407
386
|
|
|
408
387
|
def set_centroid(self, cen):
|
|
409
388
|
self.cen = cen
|
|
410
|
-
self.vlines[1].set_xdata(cen)
|
|
389
|
+
self.vlines[1].set_xdata([cen])
|
|
411
390
|
|
|
412
391
|
def set_range(self, lower, upper):
|
|
413
392
|
self.lower = lower
|
|
414
393
|
self.upper = upper
|
|
415
|
-
self.vlines[0].set_xdata(lower)
|
|
416
|
-
self.vlines[2].set_xdata(upper)
|
|
394
|
+
self.vlines[0].set_xdata([lower])
|
|
395
|
+
self.vlines[2].set_xdata([upper])
|
|
417
396
|
|
|
418
397
|
def get_range(self):
|
|
419
398
|
return (self.lower, self.upper)
|
|
@@ -1380,11 +1359,11 @@ class ExtractGUI(QtWidgets.QMainWindow):
|
|
|
1380
1359
|
|
|
1381
1360
|
elif artist.get_label() == 'lower':
|
|
1382
1361
|
trace_model.lower = new_position
|
|
1383
|
-
artist.set_xdata(new_position)
|
|
1362
|
+
artist.set_xdata([new_position])
|
|
1384
1363
|
|
|
1385
1364
|
elif artist.get_label() == 'upper':
|
|
1386
1365
|
trace_model.upper = new_position
|
|
1387
|
-
artist.set_xdata(new_position)
|
|
1366
|
+
artist.set_xdata([new_position])
|
|
1388
1367
|
self.canvas_spsf.draw()
|
|
1389
1368
|
|
|
1390
1369
|
def on_release(self, event):
|
|
@@ -1394,12 +1373,12 @@ class ExtractGUI(QtWidgets.QMainWindow):
|
|
|
1394
1373
|
if artist.get_label() == 'lower':
|
|
1395
1374
|
if trace_model.lower > trace_model.cen - 1:
|
|
1396
1375
|
trace_model.lower = trace_model.cen - 1
|
|
1397
|
-
artist.set_xdata(trace_model.cen - 1)
|
|
1376
|
+
artist.set_xdata([trace_model.cen - 1])
|
|
1398
1377
|
self.canvas_spsf.draw()
|
|
1399
1378
|
elif artist.get_label() == 'upper':
|
|
1400
1379
|
if trace_model.upper < trace_model.cen + 1:
|
|
1401
1380
|
trace_model.upper = trace_model.cen + 1
|
|
1402
|
-
artist.set_xdata(trace_model.cen + 1)
|
|
1381
|
+
artist.set_xdata([trace_model.cen + 1])
|
|
1403
1382
|
self.canvas_spsf.draw()
|
|
1404
1383
|
centroid_shift = trace_model.cen - old_centroid
|
|
1405
1384
|
if np.abs(centroid_shift) > 0:
|
|
@@ -1669,7 +1648,10 @@ class ExtractGUI(QtWidgets.QMainWindow):
|
|
|
1669
1648
|
def update_xmask_in_points(self):
|
|
1670
1649
|
# Clear old shapes:
|
|
1671
1650
|
for item in self.xmask:
|
|
1672
|
-
|
|
1651
|
+
try:
|
|
1652
|
+
item.remove()
|
|
1653
|
+
except NotImplementedError:
|
|
1654
|
+
pass
|
|
1673
1655
|
self.xmask = list()
|
|
1674
1656
|
xmin, xmax, ymin, ymax = self.get_limits()
|
|
1675
1657
|
if xmin > 0 or xmax < self.image2d.data.shape[1]+1:
|
|
@@ -3,6 +3,8 @@ __author__ = "Jens-Kristian Krogager"
|
|
|
3
3
|
|
|
4
4
|
import warnings
|
|
5
5
|
from astropy.io import fits
|
|
6
|
+
from astropy import units as u
|
|
7
|
+
from astropy.table import QTable
|
|
6
8
|
import numpy as np
|
|
7
9
|
import os
|
|
8
10
|
|
|
@@ -129,17 +131,17 @@ def get_wavelength_from_header(hdr):
|
|
|
129
131
|
|
|
130
132
|
# -- These names are used to define proper column names for Wavelength, Flux and Error:
|
|
131
133
|
wavelength_column_names = ['wl', 'lam', 'lambda', 'loglam', 'wave', 'wavelength', 'awav']
|
|
132
|
-
flux_column_names = ['data', 'spec', 'flux', 'flam', 'fnu', 'flux_density']
|
|
133
|
-
error_column_names = ['err', 'sig', 'error', 'ivar', 'sigma', 'var']
|
|
134
|
+
flux_column_names = ['data', 'spec', 'flux', 'flam', 'fnu', 'flux_density', 'reduced_flux']
|
|
135
|
+
error_column_names = ['err', 'sig', 'error', 'ivar', 'sigma', 'var', 'err_flux', 'flux_ivar', 'flux_var', 'flux_err']
|
|
134
136
|
mask_column_names = ['mask', 'qual', 'dq', 'qc']
|
|
135
137
|
|
|
136
138
|
# -- These names are used to define proper ImageHDU names for Flux and Error:
|
|
137
139
|
flux_HDU_names = ['FLUX', 'SCI', 'FLAM', 'FNU']
|
|
138
|
-
error_HDU_names = ['ERR', 'ERRS', 'SIG', 'SIGMA', 'ERROR', 'ERRORS', 'IVAR', 'VAR']
|
|
140
|
+
error_HDU_names = ['ERR', 'ERRS', 'SIG', 'SIGMA', 'ERROR', 'ERRORS', 'IVAR', 'VAR', 'ERR_FLUX']
|
|
139
141
|
mask_HDU_names = ['MASK', 'QUAL', 'QC', 'DQ']
|
|
140
142
|
|
|
141
143
|
|
|
142
|
-
def get_spectrum_fits_table(
|
|
144
|
+
def get_spectrum_fits_table(table_hdu):
|
|
143
145
|
"""
|
|
144
146
|
Scan the TableData for columns containing wavelength, flux, error and mask.
|
|
145
147
|
All arrays of {wavelength, flux and error} must be present.
|
|
@@ -163,7 +165,12 @@ def get_spectrum_fits_table(tbdata):
|
|
|
163
165
|
Numpy boolean array of pixel mask. `True` if the pixel is 'good',
|
|
164
166
|
`False` if the pixel is bad and should not be used.
|
|
165
167
|
"""
|
|
166
|
-
|
|
168
|
+
tbdata = QTable.read(table_hdu)
|
|
169
|
+
# table_names = [name.lower() for name in tbdata.names]
|
|
170
|
+
for colname in tbdata.colnames:
|
|
171
|
+
tbdata.rename_column(colname, colname.lower())
|
|
172
|
+
table_names = tbdata.colnames
|
|
173
|
+
|
|
167
174
|
wl_in_table = False
|
|
168
175
|
for colname in wavelength_column_names:
|
|
169
176
|
if colname in table_names:
|
|
@@ -185,9 +192,10 @@ def get_spectrum_fits_table(tbdata):
|
|
|
185
192
|
for colname in error_column_names:
|
|
186
193
|
if colname in table_names:
|
|
187
194
|
error_in_table = True
|
|
188
|
-
if
|
|
189
|
-
|
|
190
|
-
|
|
195
|
+
if 'ivar' in colname.lower():
|
|
196
|
+
with np.errstate(divide='ignore', invalid='ignore'):
|
|
197
|
+
error = 1 / np.sqrt(tbdata[colname])
|
|
198
|
+
elif 'var' in colname.lower():
|
|
191
199
|
error = np.sqrt(tbdata[colname])
|
|
192
200
|
else:
|
|
193
201
|
error = tbdata[colname]
|
|
@@ -208,6 +216,7 @@ def get_spectrum_fits_table(tbdata):
|
|
|
208
216
|
|
|
209
217
|
return wavelength.flatten(), data.flatten(), error.flatten(), mask.flatten()
|
|
210
218
|
|
|
219
|
+
|
|
211
220
|
# Hack the doc-string of the function to input the variable names:
|
|
212
221
|
output_column_names = {'WL_COL_NAMES': wavelength_column_names,
|
|
213
222
|
'FLUX_COL_NAMES': flux_column_names,
|
|
@@ -270,6 +279,7 @@ def get_spectrum_hdulist(HDUlist):
|
|
|
270
279
|
|
|
271
280
|
return data, error, mask, data_hdr
|
|
272
281
|
|
|
282
|
+
|
|
273
283
|
# Hack the doc-string of the function to input the variable names:
|
|
274
284
|
output_hdu_names = {'FLUX_HDU_NAMES': flux_HDU_names,
|
|
275
285
|
'ERR_HDU_NAMES': error_HDU_names}
|
|
@@ -363,17 +373,19 @@ def load_fits_spectrum(fname, ext=None, iraf_obj=None):
|
|
|
363
373
|
else:
|
|
364
374
|
is_fits_table = isinstance(HDUlist[1], fits.BinTableHDU) or isinstance(HDUlist[1], fits.TableHDU)
|
|
365
375
|
if is_fits_table:
|
|
366
|
-
if ext:
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
376
|
+
if not ext:
|
|
377
|
+
ext = 1
|
|
378
|
+
|
|
379
|
+
table_hdu = HDUlist[ext]
|
|
380
|
+
tbdata = table_hdu.data
|
|
381
|
+
data_hdr = table_hdu.header
|
|
372
382
|
|
|
373
383
|
has_multi_extensions = len(HDUlist) > 2
|
|
374
384
|
if has_multi_extensions and (ext is None):
|
|
375
385
|
msg = "[WARNING] - More than one data extension detected in the file"
|
|
376
|
-
wavelength, data, error, mask = get_spectrum_fits_table(
|
|
386
|
+
wavelength, data, error, mask = get_spectrum_fits_table(table_hdu)
|
|
387
|
+
if 'CUNIT1' in data_hdr:
|
|
388
|
+
wavelength *= u.Unit(data_hdr['CUNIT1'])
|
|
377
389
|
return wavelength, data, error, mask, data_hdr, msg
|
|
378
390
|
|
|
379
391
|
elif len(HDUlist) == 2:
|
|
@@ -536,3 +548,11 @@ def create_error_image(base_fname, overwrite=False):
|
|
|
536
548
|
hdu.append(ext)
|
|
537
549
|
output_msg = " - Successfully created an error image"
|
|
538
550
|
return output_msg
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
def detect_4most_MEC(fname):
|
|
554
|
+
prim = fits.getheader(fname)
|
|
555
|
+
is_qmost = prim.get('INSTRUME', 'NONE').strip() == 'QMOST'
|
|
556
|
+
hdr = fits.getheader(fname, 1)
|
|
557
|
+
has_mec_extname = hdr.get('EXTNAME') in ['OBMETATAB', 'SPECTAB', 'FIBMETATAB']
|
|
558
|
+
return is_qmost & has_mec_extname
|
|
@@ -21,6 +21,7 @@ from PyQt5 import QtWidgets
|
|
|
21
21
|
from scipy.optimize import curve_fit
|
|
22
22
|
from numpy.polynomial import Chebyshev
|
|
23
23
|
from astropy.io import fits
|
|
24
|
+
from astropy.table import Table
|
|
24
25
|
|
|
25
26
|
from pynot import instrument
|
|
26
27
|
from pynot.data import organizer
|
|
@@ -226,7 +227,7 @@ def load_linelist(fname):
|
|
|
226
227
|
|
|
227
228
|
class GraphicInterface(QtWidgets.QMainWindow):
|
|
228
229
|
def __init__(self, arc_fname='', grism_name='', pixtable='', linelist_fname='', output='',
|
|
229
|
-
dispaxis=2, order_wl=3, air=False, loc=-1, parent=None, locked=False
|
|
230
|
+
dispaxis=2, order_wl=3, air=False, loc=-1, parent=None, locked=False):
|
|
230
231
|
QtWidgets.QMainWindow.__init__(self, parent)
|
|
231
232
|
self.setWindowTitle('PyNOT: Identify Arc Lines')
|
|
232
233
|
self._main = QtWidgets.QWidget()
|
|
@@ -572,9 +573,9 @@ class GraphicInterface(QtWidgets.QMainWindow):
|
|
|
572
573
|
self.reftable.setItem(rowPosition, 1, item2)
|
|
573
574
|
|
|
574
575
|
def load_spectrum(self, arc_fname=None):
|
|
575
|
-
if arc_fname
|
|
576
|
+
if not arc_fname:
|
|
576
577
|
current_dir = './'
|
|
577
|
-
filters = "FITS files (*.fits | *.fit)"
|
|
578
|
+
filters = "FITS or txt files (*.fits | *.fit | *.txt | *.csv)"
|
|
578
579
|
arc_fname = QtWidgets.QFileDialog.getOpenFileName(self, 'Open Pixeltable', current_dir, filters)
|
|
579
580
|
arc_fname = str(arc_fname[0])
|
|
580
581
|
if self.first_time_open:
|
|
@@ -583,6 +584,31 @@ class GraphicInterface(QtWidgets.QMainWindow):
|
|
|
583
584
|
self.first_time_open = False
|
|
584
585
|
|
|
585
586
|
if arc_fname:
|
|
587
|
+
|
|
588
|
+
try:
|
|
589
|
+
tab1d = Table.read(arc_fname, hdu=1, format='fits')
|
|
590
|
+
self.pix = tab1d['pixel']
|
|
591
|
+
self.arc1d = tab1d['flux']
|
|
592
|
+
self.update_arc1d()
|
|
593
|
+
return
|
|
594
|
+
|
|
595
|
+
except (OSError, ValueError):
|
|
596
|
+
try:
|
|
597
|
+
tab1d = Table.read(arc_fname, format='ascii')
|
|
598
|
+
tab1d.rename_column(tab1d.colnames[0], 'pixel')
|
|
599
|
+
tab1d.rename_column(tab1d.colnames[1], 'flux')
|
|
600
|
+
self.pix = tab1d['pixel']
|
|
601
|
+
self.arc1d = tab1d['flux']
|
|
602
|
+
self.update_arc1d()
|
|
603
|
+
return
|
|
604
|
+
except Exception:
|
|
605
|
+
if 'fits' in arc_fname.lower():
|
|
606
|
+
pass
|
|
607
|
+
else:
|
|
608
|
+
error_msg = "Could not read the spectrum. Must be a FITS or ASCII table, or a FITS 2D image"
|
|
609
|
+
QtWidgets.QMessageBox.critical(None, 'Invalid Format!', error_msg)
|
|
610
|
+
return
|
|
611
|
+
|
|
586
612
|
self.arc_fname = arc_fname
|
|
587
613
|
with fits.open(arc_fname) as hdu:
|
|
588
614
|
primhdr = hdu[0].header
|
|
@@ -647,7 +673,9 @@ class GraphicInterface(QtWidgets.QMainWindow):
|
|
|
647
673
|
|
|
648
674
|
self.arc1d = np.nanmean(self.arc_image_data[:, ilow:ihigh], axis=1)
|
|
649
675
|
self.pix = instrument.create_pixel_array(self.primhdr, self.dispaxis)
|
|
676
|
+
self.update_arc1d()
|
|
650
677
|
|
|
678
|
+
def update_arc1d(self):
|
|
651
679
|
self.ax.lines[0].set_data(self.pix, self.arc1d)
|
|
652
680
|
self.ax.relim()
|
|
653
681
|
self.ax.autoscale()
|
|
@@ -372,6 +372,10 @@ def main(inspect=False):
|
|
|
372
372
|
help="Set this option for 2D spectra of extended sources to turn off automatic localization")
|
|
373
373
|
parser_scomb.add_argument("--mef", action="store_false",
|
|
374
374
|
help="Set this option to save output as a multiextension FITS file instead of a FITS table.")
|
|
375
|
+
parser_scomb.add_argument("--imin", type=int, default=0,
|
|
376
|
+
help="Slice each input spectrum along dispersion axis [imin:imax], only for 1D spectra")
|
|
377
|
+
parser_scomb.add_argument("--imax", type=int, default=None,
|
|
378
|
+
help="Slice each input spectrum along dispersion axis [imin:imax], only for 1D spectra")
|
|
375
379
|
|
|
376
380
|
|
|
377
381
|
# -- extract :: Extraction of 1D spectrum from 2D
|
|
@@ -389,6 +393,31 @@ def main(inspect=False):
|
|
|
389
393
|
set_default_pars(parser_ext, section='extract', default_type=int,
|
|
390
394
|
ignore_pars=['interactive'])
|
|
391
395
|
|
|
396
|
+
# -- view :: View 1D spectra in an interactive window
|
|
397
|
+
parser_view = tasks.add_parser('view', formatter_class=set_help_width(31),
|
|
398
|
+
help="Display and interact with 1D spectra")
|
|
399
|
+
parser_view.add_argument("files", type=str, nargs='*',
|
|
400
|
+
help="Filenames of spectral data to load. Each file is loaded as one target")
|
|
401
|
+
parser_view.add_argument("-t", "--table", type=str,
|
|
402
|
+
help="Filename of association table. Each line in the file gives a comma-separated list of filenames. "
|
|
403
|
+
"All files in one line are loaded as a single target.")
|
|
404
|
+
parser_view.add_argument("-c", "--container", action="store_true",
|
|
405
|
+
help="Load the file(s) as a FITS container "
|
|
406
|
+
"(such as 4MOST MEC, SDSS bricks, or a large collection of files)")
|
|
407
|
+
parser_view.add_argument("-l", "--list", type=str, default='',
|
|
408
|
+
help="File list. Name of a text file where each line is the path of one spectrum."
|
|
409
|
+
"(Useful for loading many files in `container` mode with `-c`)")
|
|
410
|
+
# redshift_table=None, z_col=None, name_col=None, cls_col=None
|
|
411
|
+
parser_view.add_argument("-z", type=str, default='',
|
|
412
|
+
help="Filename of redshift catalog with a name, redshift and spectral type column. "
|
|
413
|
+
"Set column names using `--ncol`, `--zcol`, `--tcol`")
|
|
414
|
+
parser_view.add_argument("--ncol", type=str, default='',
|
|
415
|
+
help="Name of the target name column in `-z REDSHIFT_TABLE`")
|
|
416
|
+
parser_view.add_argument("--zcol", type=str, default='',
|
|
417
|
+
help="Name of the redshift column in `-z REDSHIFT_TABLE`")
|
|
418
|
+
parser_view.add_argument("--tcol", type=str, default='',
|
|
419
|
+
help="Name of the spectral type column in `-z REDSHIFT_TABLE`")
|
|
420
|
+
|
|
392
421
|
|
|
393
422
|
# Spectral Redux:
|
|
394
423
|
parser_redux = tasks.add_parser('spex', formatter_class=set_help_width(30),
|
|
@@ -770,7 +799,7 @@ def main(inspect=False):
|
|
|
770
799
|
|
|
771
800
|
if data_is_1d:
|
|
772
801
|
out_args = combine_1d(filelist, output=args.output, method=args.method,
|
|
773
|
-
scale=args.scale, table_output=args.mef)
|
|
802
|
+
scale=args.scale, table_output=args.mef, imin=args.imin, imax=args.imax)
|
|
774
803
|
else:
|
|
775
804
|
out_args = combine_2d(filelist, output=args.output, method=args.method, trim=args.trim,
|
|
776
805
|
scale=args.scale, extended=args.extended, dispaxis=args.axis)
|
|
@@ -796,6 +825,28 @@ def main(inspect=False):
|
|
|
796
825
|
gui.show()
|
|
797
826
|
app.exit(app.exec_())
|
|
798
827
|
|
|
828
|
+
elif task == 'view':
|
|
829
|
+
from PyQt5 import QtWidgets
|
|
830
|
+
from pynot.viewer.viewer import MainWindow
|
|
831
|
+
|
|
832
|
+
app = QtWidgets.QApplication(sys.argv)
|
|
833
|
+
screenSize = app.primaryScreen().size()
|
|
834
|
+
ratio = 0.85
|
|
835
|
+
if args.list:
|
|
836
|
+
with open(args.list) as l:
|
|
837
|
+
input_files = [line.strip() for line in l.readlines()]
|
|
838
|
+
else:
|
|
839
|
+
input_files = args.files
|
|
840
|
+
main = MainWindow(input_files,
|
|
841
|
+
assn_table=args.table,
|
|
842
|
+
container_mode=args.container,
|
|
843
|
+
width=ratio*screenSize.width(),
|
|
844
|
+
height=ratio*screenSize.height(),
|
|
845
|
+
redshift_table=args.z,
|
|
846
|
+
z_col=args.zcol, name_col=args.ncol, cls_col=args.tcol,
|
|
847
|
+
)
|
|
848
|
+
main.show()
|
|
849
|
+
app.exit(app.exec_())
|
|
799
850
|
|
|
800
851
|
# -- Imaging tasks:
|
|
801
852
|
elif task == 'phot':
|
|
@@ -193,13 +193,13 @@ def run_pipeline(options_fname, object_id=None, verbose=True, interactive=False,
|
|
|
193
193
|
identify_all = options['identify']['all']
|
|
194
194
|
local_pixtables = glob.glob(os.path.join(output_base, "arcs", "pixtab_*.dat"))
|
|
195
195
|
for fname in local_pixtables:
|
|
196
|
-
pixtab_id = os.path.splitext(fname)[0].split('_')[1]
|
|
196
|
+
pixtab_id = os.path.splitext(os.path.basename(fname))[0].split('_')[1]
|
|
197
197
|
status[pixtab_id] = fname
|
|
198
198
|
cached_pixtables = glob.glob(os.path.join(calib_dir, "*_pixeltable.dat"))
|
|
199
199
|
for fname in cached_pixtables:
|
|
200
200
|
# TODO: Potentially use `basename(fname)` to split
|
|
201
201
|
# This avoids bugs if the filename contains more than one `_`
|
|
202
|
-
pixtab_id = fname.split('_')[0]
|
|
202
|
+
pixtab_id = os.path.basename(fname).split('_')[0]
|
|
203
203
|
status[pixtab_id] = fname
|
|
204
204
|
|
|
205
205
|
|
|
@@ -5,7 +5,7 @@ from functools import reduce
|
|
|
5
5
|
import warnings
|
|
6
6
|
|
|
7
7
|
from pynot.functions import get_version_number
|
|
8
|
-
from pynot.fitsio import load_fits_spectrum, save_fitstable_spectrum, save_fits_spectrum
|
|
8
|
+
from pynot.fitsio import load_fits_spectrum, save_fitstable_spectrum, save_fits_spectrum, error_HDU_names
|
|
9
9
|
from pynot.txtio import load_ascii_spectrum
|
|
10
10
|
|
|
11
11
|
|
|
@@ -55,18 +55,26 @@ def combine_2d(files, output=None, method='mean', scale=False, extended=False, d
|
|
|
55
55
|
hdr = fits.getheader(fname)
|
|
56
56
|
data2D = fits.getdata(fname)
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
for err_name in error_HDU_names:
|
|
59
|
+
try:
|
|
60
|
+
err2D = fits.getdata(fname, err_name)
|
|
61
|
+
err2D[err2D <= 0.] = np.nanmedian(err2D)*100
|
|
62
|
+
msg.append(f" - Loaded error image extension: {err_name}")
|
|
63
|
+
break
|
|
64
|
+
except KeyError:
|
|
65
|
+
pass
|
|
66
|
+
else:
|
|
63
67
|
msg.append("[WARNING] - No ERR extension could be found in the FITS file!")
|
|
64
68
|
err2D = np.ones_like(data2D)
|
|
65
69
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
for mask_name in ['MASK', 'QUAL']:
|
|
71
|
+
try:
|
|
72
|
+
mask2D = fits.getdata(fname, mask_name)
|
|
73
|
+
msg.append(f" - Loaded mask image extension: {mask_name}")
|
|
74
|
+
break
|
|
75
|
+
except KeyError:
|
|
76
|
+
pass
|
|
77
|
+
else:
|
|
70
78
|
msg.append("[WARNING] - No MASK extension could be found in the FITS file!")
|
|
71
79
|
mask2D = np.zeros_like(data2D)
|
|
72
80
|
|
|
@@ -345,7 +353,7 @@ def combine_2d(files, output=None, method='mean', scale=False, extended=False, d
|
|
|
345
353
|
|
|
346
354
|
|
|
347
355
|
|
|
348
|
-
def combine_1d(files, output=None, method='mean', scale=False, table_output=True):
|
|
356
|
+
def combine_1d(files, output=None, method='mean', scale=False, table_output=True, imin=0, imax=None):
|
|
349
357
|
"""Combine a list of 1d-spectra using either median or mean combination.
|
|
350
358
|
For median combination, only the overlapping parts of the spectra will be
|
|
351
359
|
combined. The mean combination uses a weighted average over the entire
|
|
@@ -368,6 +376,12 @@ def combine_1d(files, output=None, method='mean', scale=False, table_output=True
|
|
|
368
376
|
|
|
369
377
|
table_output : bool [default=True]
|
|
370
378
|
Use FITS table for the output format? Otherwise use a MultiExtension Fits File
|
|
379
|
+
|
|
380
|
+
imin : int
|
|
381
|
+
Apply slicing to each spectrum from imin to imax.
|
|
382
|
+
|
|
383
|
+
imax : int | None
|
|
384
|
+
Apply slicing to each spectrum from imin to imax.
|
|
371
385
|
"""
|
|
372
386
|
|
|
373
387
|
wl_all = list()
|
|
@@ -377,6 +391,7 @@ def combine_1d(files, output=None, method='mean', scale=False, table_output=True
|
|
|
377
391
|
size_all = list()
|
|
378
392
|
scales = list()
|
|
379
393
|
|
|
394
|
+
cut = slice(imin, imax)
|
|
380
395
|
msg = list()
|
|
381
396
|
for fname in files:
|
|
382
397
|
if fname.endswith('.fits') or fname.endswith('.fit'):
|
|
@@ -393,11 +408,11 @@ def combine_1d(files, output=None, method='mean', scale=False, table_output=True
|
|
|
393
408
|
msg.append(load_msg)
|
|
394
409
|
msg.append(" - Loaded ASCII spectrum: %s" % fname)
|
|
395
410
|
|
|
396
|
-
wl_all.append(wl)
|
|
397
|
-
flux_all.append(flux)
|
|
398
|
-
err_all.append(err)
|
|
399
|
-
mask_all.append(mask)
|
|
400
|
-
size_all.append(len(wl))
|
|
411
|
+
wl_all.append(wl[cut])
|
|
412
|
+
flux_all.append(flux[cut])
|
|
413
|
+
err_all.append(err[cut])
|
|
414
|
+
mask_all.append(mask[cut])
|
|
415
|
+
size_all.append(len(wl[cut]))
|
|
401
416
|
if scale:
|
|
402
417
|
nonzero = flux.nonzero()[0]
|
|
403
418
|
idx_0 = min(nonzero) + len(nonzero)/2
|
|
@@ -30,6 +30,7 @@ def fit_background_row(x, row, mask=None, order_bg=3, med_kernel=15, kappa=5):
|
|
|
30
30
|
mask = np.ones(len(row), dtype=bool)
|
|
31
31
|
|
|
32
32
|
# Median filter the data to remove outliers:
|
|
33
|
+
row = row.astype(np.float64)
|
|
33
34
|
med_row = median_filter(row, med_kernel)
|
|
34
35
|
noise = mad(row) * 1.4826
|
|
35
36
|
this_mask = mask * (np.abs(row - med_row) < kappa*noise)
|
|
File without changes
|