Source code for admit.at.Template_AT

""".. _Template-AT-api:

   **Template_AT** --- Cube manipulation template.
   -----------------------------------------------

   This module defines the Template_AT class.
"""
import sys, os
import numpy as np

import admit
import admit.util.bdp_types as bt

[docs]class Template_AT(admit.Task): """ Image cube manipulation sample template. This task demonstrates several ways of manipulating a generic position-position-frequency (or velocity) data cube. It can be used as a template by users developing their own cube analysis routines. This template demonstrates the following transformations: - scale the intensity at all points in the cube by a specified value - extract a 2-D position-position image from the (scaled) cube at a specified frequency (channel number) - extract a 1-D spectrum from the (scaled) cube at the specified spatial position (pixel coordinates) Each of these operations is controlled by keywords. **Keywords** **cubescale**: float The value by which to scale the cube intensity; default: 2.0. **imgslice**: int Frequency (pixel index) of the 2-D image plane to extract from the cube; default: 0 (the first spectral channel). **specpos**: 2-tuple of int The 2-D (spatial) pixel position from which to extract the 1-D cube spectrum; default: (0,0). **Input BDPs** **SpwCube_BDP**: count: 1 Input 3-D data cube; e.g., as output from an `Ingest_AT <Ingest_AT.html>`_, `ContinuumSub_AT <ContinuumSub_AT.html>`_ or `LineCube_AT <LineCube_AT.html>`_. **Output BDPs** **SpwCube_BDP**: count: 1 Output scaled 3-D data cube. **Image_BDP**: count: 1 Output 2-D image sliced from the cube. **Table_BDP**: count: 1 Output 1-D spectrum extracted from the cube. Parameters ---------- keyval : dict, optional Dictionary of keyword:value pairs. Attributes ---------- _version : str Version ID string. Notes ----- Whenever the expected type or number of keywords or input/output BDPs changes, the __init__ method must be updated accordingly. """ def __init__(self, **keyval): keys = {"cubescale" : 2.0, "imgslice" : 0, "specpos" : (0,0)} admit.Task.__init__(self, keys, keyval) self._version = "1.0.0" self.set_bdp_in ([(admit.SpwCube_BDP, 1, bt.REQUIRED)]) self.set_bdp_out([(admit.SpwCube_BDP, 1), (admit.Image_BDP, 1), (admit.Table_BDP, 1)])
[docs] def summary(self): """ Summary data dictionary. Template_AT adds the following to ADMIT summary: .. table:: :class: borderless +----------+----------+-----------------------------------+ | Key | type | Description | +==========+==========+===================================+ | spectra | list | Plots of cube slice and spectrum. | +----------+----------+-----------------------------------+ | template | table | Template data product statistics. | +----------+----------+-----------------------------------+ Parameters ---------- None Returns ------- dict Dictionary of SummaryEntry """ if hasattr(self,"_summary"): return self._summary else: return {}
[docs] def userdata(self): """ User data dictionary. Parameters ---------- None Returns ------- dict The user data dictionary from the AT, for merging into the ADMIT user data object. """ if hasattr(self,"_userdata"): return self._userdata else: return {}
[docs] def run(self): """ Task run method. Outputs three sample data products from a single input data cube: 1. A cube scaled by the value of *cubescale*. 2. An image sliced from the cube at frequency *imgfreq*. 3. A spectrum extracted from the cube at position *specpos*. Parameters ---------- None Returns ------- None """ self._summary = {} # BDP output uses the alias name if provided, else a flow-unique name. stem = self._alias if not stem: stem = "template%d" % (self.id()) # The input data cube BDP. ibdp = self._bdp_in[0] # The data cube is a CASA image on disk. # Get its file name, read it in and convert to a NumPy array. # The entire cube is read into memory (large cubes may exceed RAM!) # Any masked pixels are converted to zero. istem = ibdp.getimagefile(bt.CASA) ifile = ibdp.baseDir() + istem icube = admit.casautil.getdata(ifile, zeromask=True).data assert len(icube.shape) == 3, "Only 3-D data cubes supported" admit.logging.info((istem + " dimensions: (%d, %d, %d)") % icube.shape) # =================================================================== # 1. Scale the entire cube by 'cubescale'. # =================================================================== cubescale = self.getkey('cubescale') ocube = icube * cubescale ocubestem = "%s_cube" % stem ocubefile = self.baseDir() + ocubestem # # Create a CASA ouput image (no mask information). admit.casautil.putdata_raw(ocubefile+".im", ocube, ifile) # # Output the result as a new SpwCube. image = admit.Image(description="Template 3-D Cube") image.addimage(admit.imagedescriptor(ocubefile+".im", format=bt.CASA)) obdp1 = admit.SpwCube_BDP(ocubestem) obdp1.addimage(image) self.addoutput(obdp1) # =================================================================== # 2. Slice a 2-D image from the cube at frequency 'imgslice'. # =================================================================== # # The frequency axis is the third array index. # Clip slice to be in range. imgslice = max(0, min(ocube.shape[2]-1, self.getkey('imgslice'))) oimg = ocube[:, :, imgslice] oimgstem = "%s_img" % stem oimgfile = self.baseDir() + oimgstem # # Create a CASA format ouput image. # @TODO Does not work for 3-D -> 2-D output. #admit.casautil.putdata_raw(oimgfile+".im", oimg, ifile) # # Create a PNG format output image. # Image data must be rotated to match matplotlib axis order. oimgtitle="Template Image Slice @ channel %d" % imgslice aplot = admit.APlot(figno=1, abspath=self.baseDir(), pmode=admit.PlotControl.BATCH, ptype=admit.PlotControl.PNG) aplot.map1(np.rot90(oimg), xlab="R.A. (pixels)", ylab="Dec (pixels)", title=oimgtitle, figname=oimgstem) aplot.final() # # Output data product referencing both image formats. image = admit.Image(description="Template 2-D Image") image.addimage(admit.imagedescriptor(oimgfile+".im", format=bt.CASA)) image.addimage(admit.imagedescriptor(oimgstem+".png", format=bt.PNG)) obdp2 = admit.Image_BDP(oimgstem) obdp2.addimage(image) self.addoutput(obdp2) # =================================================================== # 3. Extract a 1-D spectrum from the cube at position 'specpos'. # =================================================================== # # Clip position to be in range. specpos = self.getkey('specpos') specpos = (max(0, min(ocube.shape[0]-1, specpos[0])), max(0, min(ocube.shape[1]-1, specpos[1]))) ospec = ocube[specpos[0], specpos[1], :] ochan = np.arange(ospec.shape[0]) ospecstem = "%s_spec" % stem # # Create a PNG plot (standalone). ospectitle = "Template Spectrum @ position %s" % str(specpos) aplot = admit.APlot(figno=2, abspath=self.baseDir(), pmode=admit.PlotControl.BATCH, ptype=admit.PlotControl.PNG) aplot.plotter(x=ochan, y=[ospec], xlab="Channel", ylab="Intensity", title=ospectitle, figname=ospecstem) aplot.final() # # Output data product (spectrum table). obdp3 = admit.Table_BDP(ospecstem) obdp3.table.description = "Template 1-D Spectrum" obdp3.table.columns = ["Channel", "Spectrum @ (%d, %d)" % specpos] obdp3.table.setData(np.transpose(np.vstack([ochan, ospec]))) self.addoutput(obdp3) # =================================================================== # Populate example summary object. # =================================================================== # # NOTE: Summary.py, etc., must be updated to recognize this and # for Template_AT to appear in the HTML summary. stats = admit.Table() stats.description = "Template Data Product Statistics" stats.columns = ["Statistic", "InCube", "OutCube", "Image", "Spectrum"] stats.setData( np.array([ ["Min", np.amin(icube), np.amin(ocube), np.amin(oimg), np.amin(ospec)], ["Max", np.amax(icube), np.amax(ocube), np.amax(oimg), np.amax(ospec)] ])) # # Data product statistics table. keys = "cubescale=%s imgslice=%d specpos=%s" % \ (str(cubescale), imgslice, str(specpos)) self._summary["template"] = admit.SummaryEntry([stats.serialize()], "Template_AT", self.id(True), keys) # # Plots for the image and spectrum. ocubeim = ocubestem+".im" spec_description = [ [0, 0, "", "", oimgstem+".png", oimgstem+"_thumb.png", oimgtitle, ocubeim], [specpos[0], specpos[1], "", "Channel", ospecstem+".png", ospecstem+"_thumb.png", ospectitle, ocubeim]] self._summary["spectra"] = admit.SummaryEntry(spec_description, "Template_AT", self.id(True), keys)