def drizzle_arrays(insci, inwht, input_wcs, output_wcs, outsci, outwht, outcon, uniqid=1, xmin=None, xmax=None, ymin=None, ymax=None, pixfrac=1.0, kernel='square', fillval="INDEF", wtscale=1.0): """ Low level routine for performing 'drizzle' operation on one image. The interface is compatible with STScI code. All images are Python ndarrays, instead of filenames. File handling (input and output) is performed by the calling routine. Parameters ---------- insci : 2d array A 2d numpy array containing the input image to be drizzled. inwht : 2d array A 2d numpy array containing the pixel by pixel weighting. Must have the same dimensions as insci. If none is supplied, the weighting is set to one. input_wcs : gwcs.WCS object The world coordinate system of the input image. output_wcs : gwcs.WCS object The world coordinate system of the output image. outsci : 2d array A 2d numpy array containing the output image produced by drizzling. On the first call it should be set to zero. Subsequent calls it will hold the intermediate results. This is modified in-place. outwht : 2d array A 2d numpy array containing the output counts. On the first call it should be set to zero. On subsequent calls it will hold the intermediate results. This is modified in-place. outcon : 2d or 3d array, optional A 2d or 3d numpy array holding a bitmap of which image was an input for each output pixel. Should be integer zero on first call. Subsequent calls hold intermediate results. This is modified in-place. uniqid : int, optional The id number of the input image. Should be one the first time this function is called and incremented by one on each subsequent call. xmin : float, optional This and the following three parameters set a bounding rectangle on the input image. Only pixels on the input image inside this rectangle will have their flux added to the output image. Xmin sets the minimum value of the x dimension. The x dimension is the dimension that varies quickest on the image. If the value is zero, no minimum will be set in the x dimension. All four parameters are zero based, counting starts at zero. xmax : float, optional Sets the maximum value of the x dimension on the bounding box of the input image. If the value is zero, no maximum will be set in the x dimension, the full x dimension of the output image is the bounding box. ymin : float, optional Sets the minimum value in the y dimension on the bounding box. The y dimension varies less rapidly than the x and represents the line index on the input image. If the value is zero, no minimum will be set in the y dimension. ymax : float, optional Sets the maximum value in the y dimension. If the value is zero, no maximum will be set in the y dimension, the full x dimension of the output image is the bounding box. pixfrac : float, optional The fraction of a pixel that the pixel flux is confined to. The default value of 1 has the pixel flux evenly spread across the image. A value of 0.5 confines it to half a pixel in the linear dimension, so the flux is confined to a quarter of the pixel area when the square kernel is used. kernel: str, optional The name of the kernel used to combine the input. The choice of kernel controls the distribution of flux over the kernel. The kernel names are: "square", "gaussian", "point", "tophat", "turbo", "lanczos2", and "lanczos3". The square kernel is the default. fillval: str, optional The value a pixel is set to in the output if the input image does not overlap it. The default value of INDEF does not set a value. Returns ------- A tuple with three values: a version string, the number of pixels on the input image that do not overlap the output image, and the number of complete lines on the input image that do not overlap the output input image. """ # Insure that the fillval parameter gets properly interpreted for use with tdriz if util.is_blank(str(fillval)): fillval = 'INDEF' else: fillval = str(fillval) if (insci.dtype > np.float32): insci = insci.astype(np.float32) # Add input weight image if it was not passed in if inwht is None: inwht = np.ones_like(insci) # Compute what plane of the context image this input would # correspond to: planeid = int((uniqid - 1) / 32) # Check if the context image has this many planes if outcon.ndim == 3: nplanes = outcon.shape[0] elif outcon.ndim == 2: nplanes = 1 else: nplanes = 0 if nplanes <= planeid: raise IndexError("Not enough planes in drizzle context image") # Alias context image to the requested plane if 3d if outcon.ndim == 3: outcon = outcon[planeid] if xmin is xmax is ymin is ymax is None: bb = input_wcs.bounding_box ((x1, x2), (y1, y2)) = bb xmin = int(min(x1, x2)) ymin = int(min(y1, y2)) xmax = int(max(x1, x2)) ymax = int(max(y1, y2)) # Compute the mapping between the input and output pixel coordinates # for use in drizzle.cdrizzle.tdriz pixmap = resample_utils.calc_gwcs_pixmap(input_wcs, output_wcs, insci.shape) log.debug(f"Pixmap shape: {pixmap[:,:,0].shape}") log.debug(f"Input Sci shape: {insci.shape}") log.debug(f"Output Sci shape: {outsci.shape}") log.info(f"Drizzling {insci.shape} --> {outsci.shape}") _vers, _nmiss, _nskip = cdrizzle.tdriz( insci, inwht, pixmap, outsci, outwht, outcon, uniqid=uniqid, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, pixfrac=pixfrac, kernel=kernel, in_units="cps", expscale=1.0, wtscale=wtscale, fillstr=fillval )
def __init__(self, product, outwcs=None, single=False, wt_scl="exptime", pixfrac=1.0, kernel="square", fillval="INDEF"): """ Create a new Drizzle output object and set the drizzle parameters. Parameters ---------- product : str, optional A data model containing results from a previous run. The three extensions SCI, WHT, and CTX contain the combined image, total counts and image id bitmap, repectively. The WCS of the combined image is also read from the SCI extension. outwcs : `gwcs.WCS` The world coordinate system (WCS) of the resampled image. If not provided, the WCS is taken from product. wt_scl : str, optional How each input image should be scaled. The choices are `exptime` which scales each image by its exposure time, `expsq` which scales each image by the exposure time squared, or an empty string, which allows each input image to be scaled individually. pixfrac : float, optional The fraction of a pixel that the pixel flux is confined to. The default value of 1 has the pixel flux evenly spread across the image. A value of 0.5 confines it to half a pixel in the linear dimension, so the flux is confined to a quarter of the pixel area when the square kernel is used. kernel : str, optional The name of the kernel used to combine the inputs. The choice of kernel controls the distribution of flux over the kernel. The kernel names are: "square", "gaussian", "point", "tophat", "turbo", "lanczos2", and "lanczos3". The square kernel is the default. fillval : str, otional The value a pixel is set to in the output if the input image does not overlap it. The default value of INDEF does not set a value. """ # Initialize the object fields self.outsci = None self.outwht = None self.outcon = None self.outexptime = 0.0 self.uniqid = 0 self.wt_scl = wt_scl self.kernel = kernel self.fillval = fillval self.pixfrac = pixfrac self.sciext = "SCI" self.whtext = "WHT" self.conext = "CON" out_units = "cps" self.outexptime = product.meta.resample.product_exposure_time or 0.0 self.outsci = product.data if outwcs: self.outwcs = outwcs else: self.outwcs = product.meta.wcs self.outwht = product.wht self.outcon = product.con if self.outcon.ndim == 2: self.outcon = np.reshape( self.outcon, (1, self.outcon.shape[0], self.outcon.shape[1])) elif self.outcon.ndim == 3: pass else: raise ValueError("Drizzle context image has wrong dimensions: \ {0}".format(product)) # Check field values if not self.outwcs: raise ValueError("Either an existing file or wcs must be supplied") if util.is_blank(self.wt_scl): self.wt_scl = '' elif self.wt_scl != "exptime" and self.wt_scl != "expsq": raise ValueError("Illegal value for wt_scl: %s" % self.wt_scl) if out_units == "counts": np.divide(self.outsci, self.outexptime, self.outsci) elif out_units != "cps": raise ValueError("Illegal value for out_units: %s" % out_units)
def __init__(self, product="", outwcs=None, single=False, wt_scl="exptime", pixfrac=1.0, kernel="square", fillval="INDEF"): """ Create a new Drizzle output object and set the drizzle parameters. All parameters are optional, but either infile or outwcs must be supplied. If infile initializes the object from a file written after a previous run of drizzle. Results from the previous run will be combined with new results. The value passed in outwcs will be ignored. If infile is not set, outwcs will be used to initilize a new run of drizzle. Parameters ---------- product : str, optional A data model containing results from a previous run. The three extensions SCI, WHT, and CTX contain the combined image, total counts and image id bitmap, repectively. The WCS of the combined image is also read from the SCI extension. outwcs : wcs, optional The world coordinate system (WCS) of the combined image. This parameter must be present if no input file is given and is ignored if one is. wt_scl : str, optional How each input image should be scaled. The choices are `exptime` which scales each image by its exposure time, `expsq` which scales each image by the exposure time squared, or an empty string, which allows each input image to be scaled individually. pixfrac : float, optional The fraction of a pixel that the pixel flux is confined to. The default value of 1 has the pixel flux evenly spread across the image. A value of 0.5 confines it to half a pixel in the linear dimension, so the flux is confined to a quarter of the pixel area when the square kernel is used. kernel : str, optional The name of the kernel used to combine the inputs. The choice of kernel controls the distribution of flux over the kernel. The kernel names are: "square", "gaussian", "point", "tophat", "turbo", "lanczos2", and "lanczos3". The square kernel is the default. fillval : str, otional The value a pixel is set to in the output if the input image does not overlap it. The default value of INDEF does not set a value. """ # Initialize the object fields self.outsci = None self.outwht = None self.outcon = None self.outexptime = 0.0 self.uniqid = 0 self.outwcs = outwcs self.wt_scl = wt_scl self.kernel = kernel self.fillval = fillval self.pixfrac = float(pixfrac) self.sciext = "SCI" self.whtext = "WHT" self.conext = "CON" out_units = "cps" self.outexptime = product.meta.resample.product_exposure_time or 0.0 self.uniqid = product.meta.resample.pointings or 0 self.sciext = product.meta.resample.product_data_extname or "SCI" self.whtext = product.meta.resample.product_weight_extname or "WHT" self.conext = product.meta.resample.product_context_extname or "CON" self.wt_scl = product.meta.resample.drizzle_weight_scale or wt_scl self.kernel = product.meta.resample.drizzle_kernel or kernel self.fillval = product.meta.resample.drizzle_fill_value or fillval self.pixfrac = product.meta.resample.drizzle_pixel_fraction or pixfrac self.out_units = out_units = product.meta.resample.drizzle_output_units or "cps" self.outsci = product.data self.outwcs = product.meta.wcs self.outwht = product.wht self.outcon = product.con if self.outcon.ndim == 2: self.outcon = np.reshape(self.outcon, (1, self.outcon.shape[0], self.outcon.shape[1])) elif self.outcon.ndim == 3: pass else: msg = ("Drizzle context image has wrong dimensions: " + product) raise ValueError(msg) # Check field values if self.outwcs: pass else: raise ValueError("Either an existing file or wcs must be supplied to Drizzle") if util.is_blank(self.wt_scl): self.wt_scl = '' elif self.wt_scl != "exptime" and self.wt_scl != "expsq": raise ValueError("Illegal value for wt_scl: %s" % out_units) if out_units == "counts": np.divide(self.outsci, self.outexptime, self.outsci) elif out_units != "cps": raise ValueError("Illegal value for wt_scl: %s" % out_units)
def dodrizzle(insci, input_wcs, inwht, output_wcs, outsci, outwht, outcon, expin, in_units, wt_scl, pscale_ratio=1.0, uniqid=1, xmin=0, xmax=0, ymin=0, ymax=0, pixfrac=1.0, kernel='square', fillval="INDEF"): """ Low level routine for performing 'drizzle' operation on one image. The interface is compatible with STScI code. All images are Python ndarrays, instead of filenames. File handling (input and output) is performed by the calling routine. Parameters ---------- insci : 2d array A 2d numpy array containing the input image to be drizzled. input_wcs : gwcs.WCS object The world coordinate system of the input image. inwht : 2d array A 2d numpy array containing the pixel by pixel weighting. Must have the same dimensions as insci. If none is supplied, the weghting is set to one. output_wcs : gwcs.WCS object The world coordinate system of the output image. outsci : 2d array A 2d numpy array containing the output image produced by drizzling. On the first call it should be set to zero. Subsequent calls it will hold the intermediate results outwht : 2d array A 2d numpy array containing the output counts. On the first call it should be set to zero. On subsequent calls it will hold the intermediate results. outcon : 2d or 3d array, optional A 2d or 3d numpy array holding a bitmap of which image was an input for each output pixel. Should be integer zero on first call. Subsequent calls hold intermediate results. expin : float The exposure time of the input image, a positive number. The exposure time is used to scale the image if the units are counts. in_units : str The units of the input image. The units can either be "counts" or "cps" (counts per second.) wt_scl : float A scaling factor applied to the pixel by pixel weighting. wcslin_pscale : float, optional The pixel scale of the input image. Conceptually, this is the linear dimension of a side of a pixel in the input image, but it is not limited to this and can be set to change how the drizzling algorithm operates. uniqid : int, optional The id number of the input image. Should be one the first time this function is called and incremented by one on each subsequent call. xmin : float, optional This and the following three parameters set a bounding rectangle on the input image. Only pixels on the input image inside this rectangle will have their flux added to the output image. Xmin sets the minimum value of the x dimension. The x dimension is the dimension that varies quickest on the image. If the value is zero, no minimum will be set in the x dimension. All four parameters are zero based, counting starts at zero. xmax : float, optional Sets the maximum value of the x dimension on the bounding box of the input image. If the value is zero, no maximum will be set in the x dimension, the full x dimension of the output image is the bounding box. ymin : float, optional Sets the minimum value in the y dimension on the bounding box. The y dimension varies less rapidly than the x and represents the line index on the input image. If the value is zero, no minimum will be set in the y dimension. ymax : float, optional Sets the maximum value in the y dimension. If the value is zero, no maximum will be set in the y dimension, the full x dimension of the output image is the bounding box. pixfrac : float, optional The fraction of a pixel that the pixel flux is confined to. The default value of 1 has the pixel flux evenly spread across the image. A value of 0.5 confines it to half a pixel in the linear dimension, so the flux is confined to a quarter of the pixel area when the square kernel is used. kernel: str, optional The name of the kernel used to combine the input. The choice of kernel controls the distribution of flux over the kernel. The kernel names are: "square", "gaussian", "point", "tophat", "turbo", "lanczos2", and "lanczos3". The square kernel is the default. fillval: str, optional The value a pixel is set to in the output if the input image does not overlap it. The default value of INDEF does not set a value. Returns ------- A tuple with three values: a version string, the number of pixels on the input image that do not overlap the output image, and the number of complete lines on the input image that do not overlap the output input image. """ # Insure that the fillval parameter gets properly interpreted for use with tdriz if util.is_blank(fillval): fillval = 'INDEF' else: fillval = str(fillval) if in_units == 'cps': expscale = 1.0 else: expscale = expin # Add input weight image if it was not passed in if (insci.dtype > np.float32): insci = insci.astype(np.float32) if inwht is None: inwht = np.ones_like(insci) if xmax is None or xmax == xmin: xmax = insci.shape[1] if ymax is None or ymax == ymin: ymax = insci.shape[0] # Compute what plane of the context image this input would # correspond to: planeid = int((uniqid - 1) / 32) # Check if the context image has this many planes if outcon.ndim == 3: nplanes = outcon.shape[0] elif outcon.ndim == 2: nplanes = 1 else: nplanes = 0 if nplanes <= planeid: raise IndexError("Not enough planes in drizzle context image") # Alias context image to the requested plane if 3d if outcon.ndim == 3: outcon = outcon[planeid] # Compute the mapping between the input and output pixel coordinates # for use in drizzle.cdrizzle.tdriz pixmap = resample_utils.calc_gwcs_pixmap(input_wcs, output_wcs, insci.shape) # Temporary fix for tdriz not handling NaNs correctly; set NaNs to map # off the output image and set the weight to zero pixmap[np.isnan(pixmap)] = -10 # print("Number of NaNs: ", len(np.isnan(pixmap)) / 2) # inwht[np.isnan(pixmap[:,:,0])] = 0. log.debug("Pixmap shape: {}".format(pixmap[:, :, 0].shape)) log.debug("Input Sci shape: {}".format(insci.shape)) log.debug("Output Sci shape: {}".format(outsci.shape)) # y_mid = pixmap.shape[0] // 2 # x_mid = pixmap.shape[1] // 2 # print("x slice: ", pixmap[y_mid,:,0]) # print("y slice: ", pixmap[:,x_mid,1]) # print("insci: ", insci) # Call 'drizzle' to perform image combination log.info('Drizzling {} --> {}'.format(insci.shape, outsci.shape)) _vers, nmiss, nskip = cdrizzle.tdriz(insci, inwht, pixmap, outsci, outwht, outcon, uniqid=uniqid, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, scale=pscale_ratio, pixfrac=pixfrac, kernel=kernel, in_units=in_units, expscale=expscale, wtscale=wt_scl, fillstr=fillval) return _vers, nmiss, nskip
def dodrizzle(insci, input_wcs, inwht, output_wcs, outsci, outwht, outcon, expin, in_units, wt_scl, pscale_ratio=1.0, uniqid=1, xmin=0, xmax=0, ymin=0, ymax=0, pixfrac=1.0, kernel='square', fillval="INDEF"): """ Low level routine for performing 'drizzle' operation.on one image. The interface is compatible with STScI code. All images are Python ndarrays, instead of filenames. File handling (input and output) is performed by the calling routine. Parameters ---------- insci : 2d array A 2d numpy array containing the input image to be drizzled. it is an error to not supply an image. input_wcs : 2d array The world coordinate system of the input image. inwht : 2d array A 2d numpy array containing the pixel by pixel weighting. Must have the same dimensions as insci. If none is supplied, the weghting is set to one. output_wcs : wcs The world coordinate system of the output image. outsci : 2d array A 2d numpy array containing the output image produced by drizzling. On the first call it should be set to zero. Subsequent calls it will hold the intermediate results outwht : 2d array A 2d numpy array containing the output counts. On the first call it should be set to zero. On subsequent calls it will hold the intermediate results. outcon : 2d or 3d array, optional A 2d or 3d numpy array holding a bitmap of which image was an input for each output pixel. Should be integer zero on first call. Subsequent calls hold intermediate results. expin : float The exposure time of the input image, a positive number. The exposure time is used to scale the image if the units are counts. in_units : str The units of the input image. The units can either be "counts" or "cps" (counts per second.) wt_scl : float A scaling factor applied to the pixel by pixel weighting. wcslin_pscale : float, optional The pixel scale of the input image. Conceptually, this is the linear dimension of a side of a pixel in the input image, but it is not limited to this and can be set to change how the drizzling algorithm operates. uniqid : int, optional The id number of the input image. Should be one the first time this function is called and incremented by one on each subsequent call. xmin : float, optional This and the following three parameters set a bounding rectangle on the input image. Only pixels on the input image inside this rectangle will have their flux added to the output image. Xmin sets the minimum value of the x dimension. The x dimension is the dimension that varies quickest on the image. If the value is zero, no minimum will be set in the x dimension. All four parameters are zero based, counting starts at zero. xmax : float, optional Sets the maximum value of the x dimension on the bounding box of the input image. If the value is zero, no maximum will be set in the x dimension, the full x dimension of the output image is the bounding box. ymin : float, optional Sets the minimum value in the y dimension on the bounding box. The y dimension varies less rapidly than the x and represents the line index on the input image. If the value is zero, no minimum will be set in the y dimension. ymax : float, optional Sets the maximum value in the y dimension. If the value is zero, no maximum will be set in the y dimension, the full x dimension of the output image is the bounding box. pixfrac : float, optional The fraction of a pixel that the pixel flux is confined to. The default value of 1 has the pixel flux evenly spread across the image. A value of 0.5 confines it to half a pixel in the linear dimension, so the flux is confined to a quarter of the pixel area when the square kernel is used. kernel: str, optional The name of the kernel used to combine the input. The choice of kernel controls the distribution of flux over the kernel. The kernel names are: "square", "gaussian", "point", "tophat", "turbo", "lanczos2", and "lanczos3". The square kernel is the default. fillval: str, optional The value a pixel is set to in the output if the input image does not overlap it. The default value of INDEF does not set a value. Returns ------- A tuple with three values: a version string, the number of pixels on the input image that do not overlap the output image, and the number of complete lines on the input image that do not overlap the output input image. """ # Insure that the fillval parameter gets properly interpreted for use with tdriz if util.is_blank(fillval): fillval = 'INDEF' else: fillval = str(fillval) if in_units == 'cps': expscale = 1.0 else: expscale = expin # Add input weight image if it was not passed in if (insci.dtype > np.float32): insci = insci.astype(np.float32) if inwht is None: inwht = np.ones_like(insci) if xmax is None or xmax == xmin: xmax = insci.shape[1] if ymax is None or ymax == ymin: ymax = insci.shape[0] # Compute what plane of the context image this input would # correspond to: planeid = int((uniqid - 1) / 32) # Check if the context image has this many planes if outcon.ndim == 3: nplanes = outcon.shape[0] elif outcon.ndim == 2: nplanes = 1 else: nplanes = 0 if nplanes <= planeid: raise IndexError("Not enough planes in drizzle context image") # Alias context image to the requested plane if 3d if outcon.ndim == 3: outcon = outcon[planeid] # Compute the mapping between the input and output pixel coordinates pixmap = resample_utils.calc_gwcs_pixmap(input_wcs, output_wcs) # # Call 'drizzle' to perform image combination # This call to 'cdriz.tdriz' uses the new C syntax # _vers, nmiss, nskip = cdrizzle.tdriz( insci, inwht, pixmap, outsci, outwht, outcon, uniqid=uniqid, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, scale=pscale_ratio, pixfrac=pixfrac, kernel=kernel, in_units=in_units, expscale=expscale, wtscale=wt_scl, fillstr=fillval) return _vers, nmiss, nskip