diff --git a/hipercam/ccd.py b/hipercam/ccd.py index 6bd10b6..ce44c25 100644 --- a/hipercam/ccd.py +++ b/hipercam/ccd.py @@ -9,14 +9,15 @@ """ import warnings -import numpy as np from collections import OrderedDict +import numpy as np from astropy.io import fits + from .core import * from .group import * -from .window import * from .header import * +from .window import * __all__ = ("CCD", "MCCD", "get_ccd_info", "trim_ultracam") @@ -209,7 +210,6 @@ def whdul(self, hdul=None, cnam=None, xoff=0, yoff=0): # Now 1 HDU per Window for n, (wnam, wind) in enumerate(self.items()): - if cnam is None: extnam = "W:{:s}".format(wnam) else: @@ -271,7 +271,6 @@ def rhdul(cls, hdul, cnam=None): first = True for hdu in hdul: - # The header of the HDU head = hdu.header @@ -346,7 +345,6 @@ def rmhdul(cls, hdul): first = True for hdu in hdul: - # The header of the HDU head = hdu.header @@ -539,7 +537,6 @@ def crop(self, ccd): # wind through the Windows of the template CCD for twnam, twind in ccd.items(): - # for each one, search for a surrounding Window in # the CCD we are chopping down to. if it succeeds, # we break out of the loop to avoid the exception @@ -581,13 +578,15 @@ def is_data(self): return len(self) and (self.head["DSTATUS"] if "DSTATUS" in self.head else True) def __repr__(self): - return "{:s}(winds={:s}, nxtot={!r}, nytot={!r}, nxpad={!r}, nypad={!r})".format( - self.__class__.__name__, - super().__repr__(), - self.nxtot, - self.nytot, - self.nxpad, - self.nypad, + return ( + "{:s}(winds={:s}, nxtot={!r}, nytot={!r}, nxpad={!r}, nypad={!r})".format( + self.__class__.__name__, + super().__repr__(), + self.nxtot, + self.nytot, + self.nxpad, + self.nypad, + ) ) @@ -712,7 +711,7 @@ def read(cls, fname): """ with fits.open(fname) as hdul: mccd = cls.rhdul(hdul) - mccd.head['FILENAME'] = fname + mccd.head["FILENAME"] = fname return mccd @classmethod @@ -823,6 +822,34 @@ def set_const(self, val): ccd.set_const(val) +def crop_calib_frame_to(mccd: MCCD, calib_frame: MCCD, calib_type: str) -> MCCD: + """Applies a calibration frame to an MCCD, returning the result as a new MCCD. + + Exists purely to provide a nice error message to the end user + if the calibration frame is not compatible with the MCCD. + + Arguments:: + + mccd : MCCD + the MCCD to which the calibration frame is to be applied. This is not + modified in place. + + calib_frame : MCCD + the calibration frame to be applied. This is not modified in place. + + calib_type : str + the type of calibration frame, e.g. 'bias', 'dark' or + 'flat'. + """ + try: + calib_frame = calib_frame.crop(mccd) + except HipercamError as err: + raise HipercamError( + f"failed to crop {calib_type} frame to match data format. Check format of {calib_type} frame." + ) from err + return calib_frame + + def get_ccd_info(fname): """Routine to return some useful basic information from an MCCD file without reading the whole thing in. It returns an OrderedDict keyed on the CCD @@ -920,6 +947,5 @@ def trim_ultracam(mccd, ncol, nrow): else: warnings.warn( - "encountered a CCD window with no output" - " amplifier location defined" + "encountered a CCD window with no output amplifier location defined" ) diff --git a/hipercam/reduction.py b/hipercam/reduction.py index c0d85c6..5d98f51 100644 --- a/hipercam/reduction.py +++ b/hipercam/reduction.py @@ -7,6 +7,7 @@ import numpy as np import hipercam as hcam from hipercam import utils, fitting +from hipercam.ccd import crop_calib_frame_to from trm.pgplot import ( pgpap, @@ -603,24 +604,24 @@ def crop(self, mccd): """ if self.bias is not None: - self.bias = self.bias.crop(mccd) + self.bias = crop_calib_frame_to(mccd, self.bias, "bias") if self.dark is not None: - self.dark = self.dark.crop(mccd) + self.dark = crop_calib_frame_to(mccd, self.dark, "dark") if self.flat is not None: - self.flat = self.flat.crop(mccd) + self.flat = crop_calib_frame_to(mccd, self.flat, "flat") if self.fmap is not None: - self.fmap = self.fmap.crop(mccd) + self.fmap = crop_calib_frame_to(mccd, self.fmap, "fmap") nhalf = self["calibration"]["nhalf"] self.fpair = self.fpair.crop(mccd, nhalf) if isinstance(self.readout, hcam.MCCD): - self.readout = self.readout.crop(mccd) + self.readout = crop_calib_frame_to(mccd, self.readout, "readout") if isinstance(self.gain, hcam.MCCD): - self.gain = self.gain.crop(mccd) + self.gain = crop_calib_frame_to(mccd, self.gain, "gain") def setup_plots(rfile, ccds, nx, plot_lims, implot=True, lplot=True): diff --git a/hipercam/scripts/aligntool.py b/hipercam/scripts/aligntool.py index 16be8a5..90fb0be 100644 --- a/hipercam/scripts/aligntool.py +++ b/hipercam/scripts/aligntool.py @@ -22,6 +22,7 @@ import hipercam as hcam from hipercam import spooler from hipercam.extraction import findStars +from hipercam.ccd import crop_calib_frame_to __all__ = [ "aligntool", @@ -532,7 +533,7 @@ def aligntool(args=None): if n == 0 and bias is not None: # crop the bias on the first frame only - bias = bias.crop(mccd) + bias = crop_calib_frame_to(mccd, bias, "bias") ccd = mccd[ccdnam] ref_ccd = ref_mccd[rccdnam] diff --git a/hipercam/scripts/combine.py b/hipercam/scripts/combine.py index 89a9097..b9d6338 100644 --- a/hipercam/scripts/combine.py +++ b/hipercam/scripts/combine.py @@ -8,6 +8,7 @@ from trm.cline import Cline import hipercam as hcam +from hipercam.ccd import crop_calib_frame_to from hipercam import support, spooler __all__ = [ @@ -208,15 +209,15 @@ def combine(args=None): if bias is not None: # crop the bias - bias = bias.crop(template) + bias = crop_calib_frame_to(template, bias, "bias") if dark is not None: # crop the dark - dark = dark.crop(template) + dark = crop_calib_frame_to(template, dark, "dark") if flat is not None: # crop the flat - flat = flat.crop(template) + flat = crop_calib_frame_to(template, flat, "flat") # Now process each file CCD by CCD to reduce the memory # footprint diff --git a/hipercam/scripts/filtid.py b/hipercam/scripts/filtid.py index be651ef..99a57c6 100644 --- a/hipercam/scripts/filtid.py +++ b/hipercam/scripts/filtid.py @@ -10,6 +10,7 @@ from trm.cline import Cline import hipercam as hcam +from hipercam.ccd import crop_calib_frame_to from hipercam import spooler, defect __all__ = [ @@ -256,7 +257,7 @@ def filtid(args=None): if nframe == 0: # crop the bias on the first frame only - bias = bias.crop(mccd) + bias = crop_calib_frame_to(mccd, bias, "bias") # bias subtraction mccd -= bias diff --git a/hipercam/scripts/ftargets.py b/hipercam/scripts/ftargets.py index 89ab6a1..b704c09 100644 --- a/hipercam/scripts/ftargets.py +++ b/hipercam/scripts/ftargets.py @@ -16,6 +16,7 @@ import hipercam as hcam from hipercam import core, spooler, defect +from hipercam.ccd import crop_calib_frame_to from hipercam.extraction import findStars __all__ = [ @@ -503,11 +504,11 @@ def ftargets(args=None): if n == 0: if bias is not None: # crop the bias on the first frame only - bias = bias.crop(mccd) + bias = crop_calib_frame_to(mccd, bias, "bias") if flat is not None: # crop the flat on the first frame only - flat = flat.crop(mccd) + flat = crop_calib_frame_to(mccd, flat, "flat") # compute maximum length of window name strings lsmax = 0 diff --git a/hipercam/scripts/grab.py b/hipercam/scripts/grab.py index 2696db8..99ef599 100644 --- a/hipercam/scripts/grab.py +++ b/hipercam/scripts/grab.py @@ -12,6 +12,7 @@ from trm.cline import Cline import hipercam as hcam +from hipercam.ccd import crop_calib_frame_to from hipercam import fringe, spooler, utils __all__ = [ @@ -379,16 +380,16 @@ def grab(args=None): if nframe == first: # First time through, need to manipulate calibration data if bias is not None: - bias = bias.crop(mccd) + bias = crop_calib_frame_to(mccd, bias, "bias") bexpose = bias.head.get("EXPTIME", 0.0) else: bexpose = 0. if flat is not None: - flat = flat.crop(mccd) + flat = crop_calib_frame_to(mccd, flat, "flat") if dark is not None: - dark = dark.crop(mccd) + dark = crop_calib_frame_to(mccd, dark, "dark") if fmap is not None: - fmap = fmap.crop(mccd) + fmap = crop_calib_frame_to(mccd, fmap, "fmap") fpair = fpair.crop(mccd, nhalf) # now any time through, apply calibrations diff --git a/hipercam/scripts/joinup.py b/hipercam/scripts/joinup.py index 0d6c6ba..d5a15dc 100644 --- a/hipercam/scripts/joinup.py +++ b/hipercam/scripts/joinup.py @@ -11,6 +11,7 @@ from trm.cline import Cline import hipercam as hcam +from hipercam.ccd import crop_calib_frame_to from hipercam import defect, fringe, spooler __all__ = [ @@ -483,17 +484,17 @@ def joinup(args=None): if nframe == first: if bias is not None: # crop the bias on the first frame only - bias = bias.crop(mccd) + bias = crop_calib_frame_to(mccd, bias, "bias") bexpose = bias.head.get("EXPTIME", 0.0) else: bexpose = 0.0 if dark is not None: - dark = dark.crop(mccd) + dark = crop_calib_frame_to(mccd, dark, "dark") if flat is not None: # crop the flat on the first frame only - flat = flat.crop(mccd) + flat = crop_calib_frame_to(mccd, flat, "flat") if fmap is not None: - fmap = fmap.crop(mccd) + fmap = crop_calib_frame_to(mccd, fmap, "fmap") fpair = fpair.crop(mccd, nhalf) for nc, cnam in enumerate(ccds): diff --git a/hipercam/scripts/makemovie.py b/hipercam/scripts/makemovie.py index c5d2ebb..30e1d4f 100644 --- a/hipercam/scripts/makemovie.py +++ b/hipercam/scripts/makemovie.py @@ -13,6 +13,7 @@ from trm.cline import Cline import hipercam as hcam +from hipercam.ccd import crop_calib_frame_to from hipercam import defect, fringe, hlog, mpl, spooler import requests @@ -629,22 +630,22 @@ def makemovie(args=None): if bias is not None: # crop the bias on the first frame only - bias = bias.crop(mccd) + bias = crop_calib_frame_to(mccd, bias, 'bias') bexpose = bias.head.get("EXPTIME", 0.0) else: bexpose = 0. if dark is not None: # crop the dark on the first frame only - dark = dark.crop(mccd) + dark = crop_calib_frame_to(mccd, dark, 'dark') if flat is not None: # crop the flat on the first frame only - flat = flat.crop(mccd) + flat = crop_calib_frame_to(mccd, flat, 'flat') if fmap is not None: # crop the fringe map and pair file - fmap = fmap.crop(mccd) + fmap = crop_calib_frame_to(mccd, fmap, 'fmap') fpair = fpair.crop(mccd, nhalf) # wind through the CCDs to display, accumulating stuff diff --git a/hipercam/scripts/ncal.py b/hipercam/scripts/ncal.py index 2585ddf..7186c2b 100644 --- a/hipercam/scripts/ncal.py +++ b/hipercam/scripts/ncal.py @@ -17,6 +17,7 @@ from trm.cline import Cline import hipercam as hcam +from hipercam.ccd import crop_calib_frame_to from hipercam import defect, fringe, mpl, spooler from hipercam.mpl import Params @@ -296,18 +297,18 @@ def ncal(args=None): if bias is not None: # crop the bias on the first frame only - bias = bias.crop(mccd) + bias = crop_calib_frame_to(mccd, bias, 'bias') bexpose = bias.head.get("EXPTIME", 0.0) else: bexpose = 0. if dark is not None: # crop the dark on the first frame only - dark = dark.crop(mccd) + dark = crop_calib_frame_to(mccd, dark, 'dark') if flat is not None: # crop the flat on the first frame only - flat = flat.crop(mccd) + flat = crop_calib_frame_to(mccd, flat, 'flat') # extract the CCD of interest ccd = mccd[cnam] diff --git a/hipercam/scripts/nrtplot.py b/hipercam/scripts/nrtplot.py index ab3040a..09cc45b 100644 --- a/hipercam/scripts/nrtplot.py +++ b/hipercam/scripts/nrtplot.py @@ -19,6 +19,7 @@ from trm.cline import Cline import hipercam as hcam +from hipercam.ccd import crop_calib_frame_to from hipercam import defect, fringe, mpl, spooler from hipercam.mpl import Params @@ -882,22 +883,22 @@ def nrtplot(args=None): if bias is not None: # crop the bias on the first frame only - bias = bias.crop(mccd) + bias = crop_calib_frame_to(mccd, bias, 'bias') bexpose = bias.head.get("EXPTIME", 0.0) else: bexpose = 0.0 if dark is not None: # crop the dark on the first frame only - dark = dark.crop(mccd) + dark = crop_calib_frame_to(mccd, dark, 'dark') if flat is not None: # crop the flat on the first frame only - flat = flat.crop(mccd) + flat = crop_calib_frame_to(mccd, flat, 'flat') if fmap is not None: # crop the fringe map and pair file - fmap = fmap.crop(mccd) + fmap = crop_calib_frame_to(mccd, fmap, 'fmap') fpair = fpair.crop(mccd, nhalf) if setup: diff --git a/hipercam/scripts/rtplot.py b/hipercam/scripts/rtplot.py index d285dac..4f0acfd 100644 --- a/hipercam/scripts/rtplot.py +++ b/hipercam/scripts/rtplot.py @@ -10,6 +10,7 @@ from trm.cline import Cline import hipercam as hcam +from hipercam.ccd import crop_calib_frame_to from hipercam import spooler, defect import requests @@ -658,11 +659,11 @@ def rtplot(args=None): if nframe == 0: if bias is not None: # crop the bias on the first frame only - bias = bias.crop(mccd) + bias = crop_calib_frame_to(mccd, bias, 'bias') if flat is not None: # crop the flat on the first frame only - flat = flat.crop(mccd) + flat = crop_calib_frame_to(mccd, flat, 'flat') if setup: # Get windows from driver. Fair bit of error checking