Skip to content

Commit 46bf3fa

Browse files
authored
Merge pull request #2053 from pypeit/bino_maskdef
MMT BINOSPEC SLITMASK DESIGN
2 parents b4bb517 + 74b2358 commit 46bf3fa

File tree

9 files changed

+1484
-834
lines changed

9 files changed

+1484
-834
lines changed

doc/releases/1.18.2dev.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ Instrument-specific Updates
6363
is significant.
6464
- Updated the `gain` and `ronoise` values for Gemini/GMOS spectrographs to account
6565
for the different values measured in each amplifier.
66+
- Enables MMT/Binospec reductions to match the slitmask design input to the
67+
detected slits, similar to procedures used for Keck/DEIMOS, Keck/MOSFIRE, etc.
6668

6769
Script Changes
6870
--------------
@@ -72,8 +74,6 @@ Script Changes
7274
wavelength grid. This rectified 2D image must be used only for quick-look visualization
7375
purposes, and not for scientific analysis.
7476

75-
76-
7777
Datamodel Changes
7878
-----------------
7979

@@ -91,7 +91,6 @@ Under-the-hood Improvements
9191
allow PypeIt-produced ".fits" files regardless of a given spectrograph's
9292
raw data extension.
9393

94-
9594
Bug Fixes
9695
---------
9796

pypeit/edgetrace.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646

4747
from pypeit import log
4848
from pypeit import PypeItError
49+
from pypeit import PypeItBitMaskError
4950
from pypeit import utils
5051
from pypeit import sampling
5152
from pypeit import slittrace
@@ -4465,7 +4466,7 @@ def maskdesign_matching(self, debug=False):
44654466
self.maskfile = maskfiles[0] if isinstance(maskfiles, list) else maskfiles
44664467
omodel_bspat, omodel_tspat, sortindx, self.slitmask = \
44674468
self.spectrograph.get_maskdef_slitedges(
4468-
ccdnum=self.traceimg.detector.det,
4469+
det=self.traceimg.detector.det,
44694470
binning=self.traceimg.detector.binning,
44704471
filename=maskfiles,
44714472
trc_path=str(Path(self.traceimg.files[0]).parent),

pypeit/spectrographs/gemini_gmos.py

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -598,30 +598,30 @@ def allowed_mosaics(self):
598598
def default_mosaic(self):
599599
return self.allowed_mosaics[0]
600600

601-
602-
def get_slitmask(self, filename):
601+
def get_slitmask(self, filename:str, det:int=1):
603602
"""
604-
Parse the slitmask data from a MOSFIRE file into :attr:`slitmask`, a
603+
Parse the slitmask data from a raw file into :attr:`slitmask`, a
605604
:class:`~pypeit.spectrographs.slitmask.SlitMask` object.
606605
607-
This can be used for multi-object slitmask, but it it's not good
608-
for "LONGSLIT" nor "long2pos". Both "LONGSLIT" and "long2pos" have emtpy/incomplete
609-
binTable where the slitmask data are stored.
610-
611-
612-
Args:
613-
filename (:obj:`str`):
614-
Name of the file to read.
606+
Parameters
607+
----------
608+
filename : :obj:`str`
609+
Name of the file to read.
610+
det : :obj:`int`, optional
611+
1-indexed detector number to read the slitmask for. Ignored for
612+
Gemini/GMOS.
615613
616-
Returns:
617-
:class:`~pypeit.spectrographs.slitmask.SlitMask`: The slitmask
618-
data read from the file. The returned object is the same as
619-
:attr:`slitmask`.
614+
Returns
615+
-------
616+
:class:`~pypeit.spectrographs.slitmask.SlitMask`
617+
The slitmask data read from the file. The returned object is the
618+
same as :attr:`slitmask`.
620619
"""
621620
# Open the file
622621
mask_tbl = Table.read(filename, format='fits')
623622

624-
# Projected distance (in arcsec) of the object from the left and right (top and bot) edges of the slit
623+
# Projected distance (in arcsec) of the object from the left and right
624+
# (top and bot) edges of the slit
625625
slit_length = mask_tbl['slitsize_y'].to('arcsec').value # arcsec
626626
topdist = np.round(slit_length/2. -
627627
mask_tbl['slitpos_y'].to('arcsec').value, 3)
@@ -698,24 +698,43 @@ def get_slitmask(self, filename):
698698
posx_pa=posx_pa)
699699
return self.slitmask
700700

701-
def get_maskdef_slitedges(self, ccdnum=None, filename=None, debug=None,
702-
trc_path:str=None, binning=None):
703-
""" Determine the slit edges from the mask file
701+
def get_maskdef_slitedges(self, filename:str=None, det:1=None, debug:bool=None,
702+
binning:str=None, trc_path:str=None):
703+
"""
704+
Provides the slit edges positions predicted by the slitmask design.
704705
705-
Here, we take advantage of the WCS solution from the input
706-
`wcs_file`, which should be an alighment image from the observations.
706+
For Gemini/GMOS, we take advantage of the WCS solution from the input
707+
``wcs_file``, which should be an alignment image from the observations.
707708
708-
Args:
709-
binning(str, optional): spec,spat binning of the flat field image
710-
filename (:obj:`list`, optional): Name the mask design info
711-
debug (:obj:`bool`, optional): Debug
712-
ccdnum (:obj:`int`, optional): detector number
713-
trc_path (:obj:`str`, optional): path to location of the mask design file
709+
Parameters
710+
----------
711+
filename : :obj:`str`, :obj:`list`, optional:
712+
Name of the file holding the mask design info or the maskfile and
713+
wcs_file in that order
714+
det : :obj:`int`, optional
715+
Detector number. Ignored by Gemini/GMOS.
716+
debug : :obj:`bool`, optional
717+
Flag to run in debugging mode
718+
trc_path : str, optional
719+
Path to the first trace file used to generate the trace flat
720+
binning : str, optional
721+
String with the comma-separated number of pixels binned in each
722+
dimension of the flat-field image. Order must be spectral then
723+
spatial.
714724
715-
Returns:
716-
:obj:`tuple`: Three `numpy.ndarray`_ and a :class:`~pypeit.spectrographs.slitmask.SlitMask`.
717-
Two arrays are the predictions of the slit edges from the slitmask design and
718-
one contains the indices to order the slits from left to right in the PypeIt orientation
725+
Returns
726+
-------
727+
top_edges : :class:`numpy.ndarray`
728+
Predicted locations of the top edges of the slits in spatial pixel
729+
coordinates.
730+
bot_edges : :class:`numpy.ndarray`
731+
Predicted locations of the bottom edges of the slits in spatial pixel
732+
coordinates.
733+
sortindx : :class:`numpy.ndarray`
734+
Indices of the slits in the provided ``slitmask`` object that orders
735+
the slits from left to right, in the PypeIt orientation.
736+
slitmask : :class:`~pypeit.spectrographs.slitmask.SlitMask`
737+
Slit mask metadata read from the provided input file(s).
719738
"""
720739
# check if the binning is provided, even if optional, it's needed for this spectrograph
721740
if binning is None:

pypeit/spectrographs/keck_deimos.py

Lines changed: 56 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,19 +1035,24 @@ def get_telescope_offset(self, file_list):
10351035

10361036
return np.array(tel_off)
10371037

1038-
def get_slitmask(self, filename:str):
1038+
def get_slitmask(self, filename:str, det:int=1):
10391039
"""
1040-
Parse the slitmask data from a DEIMOS file into :attr:`slitmask`, a
1040+
Parse the slitmask data from a raw file into :attr:`slitmask`, a
10411041
:class:`~pypeit.spectrographs.slitmask.SlitMask` object.
10421042
1043-
Args:
1044-
filename (:obj:`str`):
1045-
Name of the file to read.
1043+
Parameters
1044+
----------
1045+
filename : :obj:`str`
1046+
Name of the file to read.
1047+
det : :obj:`int`, optional
1048+
1-indexed detector number to read the slitmask for. Ignored for
1049+
Keck/DEIMOS.
10461050
1047-
Returns:
1048-
:class:`~pypeit.spectrographs.slitmask.SlitMask`: The slitmask
1049-
data read from the file. The returned object is the same as
1050-
:attr:`slitmask`.
1051+
Returns
1052+
-------
1053+
:class:`~pypeit.spectrographs.slitmask.SlitMask`
1054+
The slitmask data read from the file. The returned object is the
1055+
same as :attr:`slitmask`.
10511056
"""
10521057
self.slitmask = slitmask.load_keck_deimoslris(filename, self.name)
10531058
return self.slitmask
@@ -1345,30 +1350,44 @@ def mask_to_pixel_coordinates(self, x=None, y=None, wave=None, order=1, filename
13451350
# Use the detector map to convert to the detector coordinates
13461351
return (x_img, y_img) + self.detector_map.ccd_coordinates(x_img, y_img, in_mm=False)
13471352

1348-
def get_maskdef_slitedges(self, ccdnum=None, filename=None, debug=None,
1349-
trc_path=None, binning=None):
1353+
def get_maskdef_slitedges(self, filename:str=None, det:1=None, debug:bool=None,
1354+
binning:str=None, trc_path:str=None):
13501355
"""
1351-
Provides the slit edges positions predicted by the slitmask design using
1352-
the mask coordinates already converted from mm to pixels by the method
1353-
`mask_to_pixel_coordinates`.
1356+
Provides the slit edges positions predicted by the slitmask design.
13541357
1355-
If not already instantiated, the :attr:`slitmask`, :attr:`amap`,
1356-
and :attr:`bmap` attributes are instantiated. If so, a file must be provided.
1357-
1358-
Args:
1359-
ccdnum (:obj:`int`):
1360-
Detector number
1361-
filename (:obj:`str`, optional):
1362-
The filename to use to (re)instantiate the :attr:`slitmask` and :attr:`grating`.
1363-
Default is None, i.e., to use previously instantiated attributes.
1364-
debug (:obj:`bool`, optional):
1365-
Run in debug mode.
1358+
If not already instantiated, the :attr:`slitmask`, :attr:`amap`, and
1359+
:attr:`bmap` attributes are instantiated; in this case, a file must be
1360+
provided.
13661361
1367-
Returns:
1368-
:obj:`tuple`: Three `numpy.ndarray`_ and a :class:`~pypeit.spectrographs.slitmask.SlitMask`.
1369-
Two arrays are the predictions of the slit edges from the slitmask design and
1370-
one contains the indices to order the slits from left to right in the PypeIt orientation
1362+
Parameters
1363+
----------
1364+
filename : :obj:`str`, :obj:`list`, optional:
1365+
Name of the file holding the mask design info or the maskfile and
1366+
wcs_file in that order
1367+
det : :obj:`int`, optional
1368+
Detector number
1369+
debug : :obj:`bool`, optional
1370+
Flag to run in debugging mode
1371+
trc_path : str, optional
1372+
Path to the first trace file used to generate the trace flat
1373+
binning : str, optional
1374+
String with the comma-separated number of pixels binned in each
1375+
dimension of the flat-field image. Order must be spectral then
1376+
spatial.
13711377
1378+
Returns
1379+
-------
1380+
top_edges : :class:`numpy.ndarray`
1381+
Predicted locations of the top edges of the slits in spatial pixel
1382+
coordinates.
1383+
bot_edges : :class:`numpy.ndarray`
1384+
Predicted locations of the bottom edges of the slits in spatial pixel
1385+
coordinates.
1386+
sortindx : :class:`numpy.ndarray`
1387+
Indices of the slits in the provided ``slitmask`` object that orders
1388+
the slits from left to right, in the PypeIt orientation.
1389+
slitmask : :class:`~pypeit.spectrographs.slitmask.SlitMask`
1390+
Slit mask metadata read from the provided input file(s).
13721391
"""
13731392
# Re-initiate slitmask and amap and bmap
13741393
if filename is not None:
@@ -1385,11 +1404,11 @@ def get_maskdef_slitedges(self, ccdnum=None, filename=None, debug=None,
13851404
if self.slitmask is None:
13861405
raise PypeItError('Unable to read slitmask design info. Provide a file.')
13871406

1388-
if ccdnum is None:
1407+
if det is None:
13891408
raise PypeItError('A detector number must be provided')
13901409

1391-
# parse ccdnum
1392-
nimg, _ccdnum = self.validate_det(ccdnum)
1410+
# parse the detector
1411+
nimg, _det = self.validate_det(det)
13931412

13941413
# Match left and right edges separately
13951414
# Sort slits in mm from the slit-mask design
@@ -1412,10 +1431,10 @@ def get_maskdef_slitedges(self, ccdnum=None, filename=None, debug=None,
14121431
for i in range(omodel_bspat.size):
14131432
# We "flag" the left and right traces predicted by the optical model that are outside of the
14141433
# current detector, by giving a value of -1.
1415-
thisccd_b = np.logical_or(ccd_b[i, :] == _ccdnum[0], ccd_b[i, :] == _ccdnum[1]) if nimg == 2 \
1416-
else ccd_b[i, :] == _ccdnum[0]
1417-
thisccd_t = np.logical_or(ccd_t[i, :] == _ccdnum[0], ccd_t[i, :] == _ccdnum[1]) if nimg == 2 \
1418-
else ccd_t[i, :] == _ccdnum[0]
1434+
thisccd_b = np.logical_or(ccd_b[i, :] == _det[0], ccd_b[i, :] == _det[1]) if nimg == 2 \
1435+
else ccd_b[i, :] == _det[0]
1436+
thisccd_t = np.logical_or(ccd_t[i, :] == _det[0], ccd_t[i, :] == _det[1]) if nimg == 2 \
1437+
else ccd_t[i, :] == _det[0]
14191438
# bottom
14201439
omodel_bspat[i] = -1 if bedge_pix[i, thisccd_b].shape[0] < 10 else \
14211440
np.median(bedge_pix[i, thisccd_b])
@@ -1429,7 +1448,7 @@ def get_maskdef_slitedges(self, ccdnum=None, filename=None, debug=None,
14291448
npt_img = whgood.shape[0] // 2
14301449
# This is hard-coded for DEIMOS, since it refers to the detectors configuration
14311450
if nimg == 1:
1432-
whgood = whgood[:npt_img] if _ccdnum[0] <= 4 else whgood[npt_img:]
1451+
whgood = whgood[:npt_img] if _det[0] <= 4 else whgood[npt_img:]
14331452
if omodel_bspat[i] == -1 and omodel_tspat[i] >= 0:
14341453
omodel_bspat[i] = omodel_tspat[i] - np.median((tedge_img - bedge_img)[i, whgood])
14351454
if omodel_tspat[i] == -1 and omodel_bspat[i] >= 0:

0 commit comments

Comments
 (0)