Source code for admit.bdp.LineList_BDP

""" **LineList_BDP** --- LineID_AT data (line information and spectra).
    -------------------------------------------------------------------

    This module defines the LineList_BDP class.
"""
# system imports
import numpy as np
import copy

# ADMIT imports
from admit.bdp.Table_BDP import Table_BDP
from admit.bdp.Image_BDP import Image_BDP
from admit.util.Table import Table
from admit.util import Spectrum
import admit.util.utils as utils
from admit.util import LineData


[docs]class LineList_BDP(Table_BDP, Image_BDP): """ LineList BDP class. This class contains a list of spectral lines identified by the LineID AT. The columns in the table are: fullname (name of the molecule "U" for unknown), formula (chemical formula), frequency (rest frequency in GHz), uid (unique identifier consisting of the formula and rest frequency), transition (molecular, vibrational or electronic transition), velocity (relative to the rest velocity), El (lower state energy in K), Eu (upper state energy in K), linestrength (line strength of the transition in Debye^2), peakintensity (peak intensity of the transition in Jy/bm), peakoffset (offset of the peak from rest in km/s), fwhm (full width half max of the line in km/s), startchan (starting channel in the spectral window), endchan (ending channel in the spectral window), and sigma (intensity of the line relative to the noise level). Parameters ---------- xmlFile : str Output XML file name. keyval : dict Dictionary of keyword:value pairs. Attributes ---------- table : Table Instance of the Table class to hold the spectral line information. veltype : str Velocity definition used for the spectrum. Default: "vlsr" ra : str The RA of where the spectrum was taken. Default: "" dec : str The declination of where the spectrum was taken. Default: "" spectra : Table Instance of the Table class to hold spectra. """ def __init__(self, xmlFile=None, **keyval): Table_BDP.__init__(self, xmlFile) Image_BDP.__init__(self, xmlFile) self.veltype = "vlsr" self.ra = "" self.dec = "" self.table.setkey("columns", utils.linelist_columns) self.table.setkey("units", utils.linelist_units) self.table.description="Identified Spectral Lines" self.table.data = np.array([], dtype=object) self.spectra = Table() self.spectra.setkey("columns", ["channel", "frequency", "intensity", "mask", "continuum", "noise"]) self.spectra.setkey("units", ["", "GHz", "", "", "", ""]) self.setkey(keyval) self._version= "0.2.0"
[docs] def addSpectrum(self, spectrum, name, replace=False): """ Method to add a spectrum to the BDP Parameters ---------- spectrum : Spectrum object The spectrum to add to the BDP name : str The name of the spectrum to add (e.g. cubestats) replace : bool If True replace the spectrum with the existing name. Returns ------- None """ # turn the data into a table plane contin = spectrum.contin(masked=False) if contin is None: contin = np.zeros(len(spectrum)) if isinstance(contin, int) or isinstance(contin, float): contin = np.array([contin] * len(spectrum)) noise = np.array([spectrum.noise()] * len(spectrum)) data = np.column_stack((spectrum.chans(False), spectrum.freq(False), spectrum.spec(csub=False, masked=False), spectrum.mask(), contin, noise)) # see if a plane already exists with the given name if name in self.spectra.planes: if replace: print "NOT IMPLEMENTED YET" #self.spectra.replace(name, spectrum) return else: raise Exception("Name %s already exists in Table." % (name)) # if this is the first one if self.spectra.shape()[0] == 0: self.spectra.addPlane(data, name) return chans = [] chans.append(self.spectra.getColumnByName("channel", typ=np.int32)) # since all planes must have the same shape (numpy restriction) then make sure that they # all have the same shape before trying to combine them if len(chans[0]) == len(spectrum.chans()) and chans[0][0] == spectrum.chans(False)[0] and \ chans[0][1] == spectrum.chans()[-1]: self.spectra.addPlane(data, name) return # they are not the same shape (length really) then the shorter ones need to be padded at # one or both ends # check for alignment of the channel axis prependspec = int(max(0, chans[0][0] - spectrum.chans(False)[0])) appendspec = int(max(0, spectrum.chans(False)[-1] - chans[0][-1])) prependdata = int(max(0, spectrum.chans(False)[0] - chans[0][0])) appenddata = int(max(0, chans[0][-1] - spectrum.chans(False)[-1])) finaldata = {} # if the plane being added is smaller then pad it by taking the entries from the main table # setting the spectra to 0.0 and set the mask to True (bad data) if appenddata != 0 or prependdata != 0: temp = self.spectra.getPlane(0) pps = temp[:prependdata] pps[:, 2] = 0.0 pps[:, 3] = True pps[:, 4] = 0.0 if appenddata != 0: aps = temp[-appenddata:] else: aps = temp[:0] aps[:, 2] = 0.0 aps[:, 3] = True aps[:, 4] = 0.0 finaldata[name] = np.vstack((pps, data, aps)) else: finaldata[name] = data # if the main table is smaller then pad all planes by taking the entries from the new plane # setting the spectra to 0.0 and set the mask to True (bad data) if prependspec != 0 or appendspec != 0: spec = {} if len(self.spectra.shape()) == 2: spec[self.spectra.planes[0]] = copy.deepcopy(self.spectra.getPlane(0)) else: for i in range(self.spectra.shape()[2]): spec[self.spectra.planes[i]] = copy.deepcopy(self.spectra.getPlane(i)) self.spectra.clear() pps = data[:prependspec] pps[:, 2] = 0.0 pps[:, 3] = True pps[:, 4] = 0.0 if appendspec != 0: aps = data[-appendspec:] else: aps = data[:0] aps[:, 2] = 0.0 aps[:, 3] = True aps[:, 4] = 0.0 for sname, values in spec.iteritems(): finaldata[sname] = np.vstack((pps, values, aps)) # put it all together for pname, plane in finaldata.iteritems(): self.spectra.addPlane(plane, pname)
[docs] def getSpectraNames(self): """ Method to get the names of the spectra Parameters ---------- None Returns ------- List of strings containing the names """ return self.spectra.planes
[docs] def getSpectrum(self, name): """ Method to get a specific spectrum by name Parameters ---------- name : str The name of the spectrum to get Returns ------- Spectrum instance containing the spectrum """ if name not in self.spectra.planes: raise Exception("Spectrum %s does not exist." % (name)) plane = self.spectra.planes.index(name) chans = self.spectra.getColumnByName("channel", plane, np.int32) freq = self.spectra.getColumnByName("frequency", plane, np.float64) spec = self.spectra.getColumnByName("intensity", plane, np.float64) mask = self.spectra.getColumnByName("mask", plane, np.bool) noise = self.spectra.getColumnByName("noise", plane, np.float64)[0] contin = self.spectra.getColumnByName("continuum", plane, np.float64) spectrum = Spectrum(spec=spec, freq=freq, chans=chans, mask=mask, contin=contin, noise=noise) return spectrum
[docs] def addRow(self, row): """ Method to add a row to the table Parameters ---------- row : LineData object LineData object containing the data Returns ------- None """ data = [] # build the row from the data for col in utils.linelist_columns: data.append(row.getkey(col)) self.table.addRow(data)
def __len__(self): return len(self.table)
[docs] def getall(self): """ Method to get all rows from the table as a list of LineData objects Parameters ---------- None Returns ------- List of LineData objects, one for each row in the table. """ planes = self.getSpectraNames() tempspec = None if len(planes) > 0: tempspec = self.getSpectrum(planes[0]) rows = [] for i in range(len(self)): row = self.table.getRow(i) ld = LineData(name=row[self.table.columns.index("name")], uid=row[self.table.columns.index("uid")], transition=row[self.table.columns.index("transition")], energies=[row[self.table.columns.index("El")], row[self.table.columns.index("Eu")]], linestrength=float(row[self.table.columns.index("linestrength")]), frequency=float(row[self.table.columns.index("frequency")]), blend=int(row[self.table.columns.index("blend")]), chans=[row[self.table.columns.index("startchan")], row[self.table.columns.index("endchan")]], formula=row[self.table.columns.index("formula")], velocity=row[self.table.columns.index("velocity")], peakintensity=row[self.table.columns.index("peakintensity")], peakoffset=row[self.table.columns.index("peakoffset")], fwhm=row[self.table.columns.index("fwhm")], peakrms=row[self.table.columns.index("peakrms")], force=row[self.table.columns.index("force")]) if tempspec is not None: frqs = [tempspec.getfreq(row[self.table.columns.index("startchan")]), tempspec.getfreq(row[self.table.columns.index("endchan")])] frqs.sort() ld.setkey("freqs", frqs) rows.append(ld) return rows