# image-based line finding and baseline subtraction. from abc import abstractmethod import contextlib import os import shutil import sys from typing import Any, Dict, List, Tuple, Union import uuid import numpy as np from numpy import array, uint64 from casatasks import casalog from casatasks.private.ialib import write_image_history from casatasks.private.sdutil import (sdtask_decorator, table_manager, tool_manager) from casatasks.private.task_imsmooth import imsmooth from casatasks.private.task_sdbaseline import sdbaseline from casatasks.private.task_sdsmooth import sdsmooth from casatasks.private.update_spw import sets_to_spwchan, spwchan_to_sets from casatools import image, quanta, table DATACOLUMN = 'DATA' OVERWRITE = True IMAGE_STACK_MAX_HEIGHT = 5 MS_STACK_MAX_HEIGHT = 3 qa = quanta() do_not_erase_temporary_files = False dump_tasks = False class AbstractFolder: """Abstract class has Image/MeasurementSet file path. This class and child classes are wrapper of CasaImage/MeasurementSet file. The wrapped path could be decided to erase by which child classes are implemented. """ has_file = False def __init__(self, file: str = None) -> None: """Initialize a Folder object.""" if not os.path.exists(file): raise ValueError(f'file {file} is not found') self.path = file self.has_file = True @abstractmethod def erase(self) -> None: """Erase the file pointed path.""" raise RuntimeError('Not implemented') class _EraseableFolder(AbstractFolder): """Image/MeasurementSet file path class. The file path is permitted to erase.""" def __init__(self, file: str = None) -> None: super().__init__(file) _eraseable_folder_register.register(self) def erase(self, dry_run: bool = True) -> None: if self.has_file: if dry_run: casalog.post(f'[DRY RUN] erase file: {self.path}', 'DEBUG2') else: casalog.post(f'erase file: {self.path}', 'DEBUG2') if os.path.exists(self.path): shutil.rmtree(self.path) if not os.path.exists(self.path): self.has_file = False else: casalog.post(f'not found the file to erase: {self.path}', 'WARN') class _UnerasableFolder(AbstractFolder): """Image/MeasurementSet file path class. The file path is NOT permitted to erase.""" def erase(self, dry_run: bool = True) -> None: casalog.post(f'un-erase file: {self.path}', 'DEBUG2') class _EraseableFolderRegister(): """Class of the register of folders that need to be erased.""" _register = dict() def register(self, folder: _EraseableFolder): if isinstance(folder, _EraseableFolder) and folder.path not in self._register.keys(): self._register[folder.path] = folder else: raise ValueError('Irregal folder would be appended', 'SEVERE') def clear(self, dry_run: bool = True): if not dry_run: for path, folder in self._register.items(): if not folder.has_file: raise RuntimeError('Invalid code execution state', 'SEVERE') elif not os.path.exists(path): raise RuntimeError(f'File not found: {path}', 'SEVERE') else: folder.erase(dry_run) self._register.clear() casalog.post('cleaned up _EraseableFolderRegister', 'DEBUG2') def pop(self, key: str) -> _EraseableFolder: return self._register.pop(key) _eraseable_folder_register = _EraseableFolderRegister() class AbstractFileStack: """CasaImage/MeasurementSet file path stack to be processed by tasks in imbaseline. The paths of CasaImage or MeasurementSet are wrapped by AbstractFolder class. Implementation classes of AbstractFileStack are _EraseableFolder/Un_EraseableFolder, the _EraseableFolder class erases the path holden by a property 'path' when execute cleaning process, and the Un_EraseableFolder class doesn't erase it. If this class is used to stack a path of CasaImage, the bottom of it must be the input image(an argument 'imagename'). """ def __init__(self, top: AbstractFolder = None, max_height=None) -> None: """Initialize a FileStack object.""" self.stack = [] self.max_height = max_height if isinstance(top, AbstractFolder): self.push(top) def push(self, file: AbstractFolder = None) -> None: """Push a folder into the stack.""" if not isinstance(file, AbstractFolder): raise ValueError(f'cannot append {file.path}') elif self.height() == self.max_height: raise RuntimeError('stack is full') else: casalog.post(f'push {file.path} into the stack', 'DEBUG2') self.stack.append(file) def pop(self) -> AbstractFolder: """Return and remove the top of the stack. The stack object should have input CasaImage or converted MeasurementSet at bottom, so if pop() is called when stack height is zero, then it raises RuntimeError. """ if self.height() <= 1: raise RuntimeError('the stack cannot pop') return self.stack.pop() def peak(self) -> AbstractFolder: """Return a pointer of the top of the stack.""" if len(self.stack) > 0: picked = self.stack[-1] casalog.post(f'pick from the stack: {picked.path}', 'DEBUG2') return self.stack[len(self.stack) - 1] else: raise RuntimeError('the stack is empty') def subpeak(self) -> AbstractFolder: """Return a pointer of a next of the top of the stack.""" if len(self.stack) > 1: picked = self.stack[len(self.stack) - 2] casalog.post(f'pick from sub peak of the stack: {picked.path}', 'DEBUG2') return self.stack[len(self.stack) - 2] else: raise RuntimeError('the stack has only one stuff') def bottom(self) -> AbstractFolder: """Return a pointer of the bottom of the stack.""" if len(self.stack) > 0: picked = self.stack[0] casalog.post(f'pick from bottom of the stack: {picked.path}', 'DEBUG2') return self.stack[0] else: raise RuntimeError('the stack has not have enough stuff') def clear(self, dry_run: bool = True) -> None: """Do erase method of all of the stack and clear the stack.""" self.stack.clear() def height(self) -> int: """Return height of the stack.""" return len(self.stack) class _CasaImageStack(AbstractFileStack): """FileStack for CasaImage.""" def __init__(self, top: AbstractFolder = None) -> None: super().__init__(top=top, max_height=IMAGE_STACK_MAX_HEIGHT) class _MeasurementSetStack(AbstractFileStack): """FileStack for MeasurementSet.""" def __init__(self) -> None: super().__init__(max_height=MS_STACK_MAX_HEIGHT) self.spsmoothed = False self.kwidth = 5 @contextlib.contextmanager def _stack_manager(initial_image=None): image_stack = _CasaImageStack(top=_UnerasableFolder(initial_image)) ms_stack = _MeasurementSetStack() try: yield image_stack, ms_stack finally: image_stack.clear() ms_stack.clear() class AbstractValidatable: """Abstract class to enforce implementing validation method. A class that inherits this class is that require parameter validation of it. """ @abstractmethod def validate(self) -> None: """Validate the object.""" raise RuntimeError('Not implemented') class _ImageShape(AbstractValidatable): """Shape parameters of input image. These parameters are been getting in Image2MS, using in MS2Image. """ def __init__(self, im_shape: np.ndarray = None, axis_dir: np.ndarray = None, axis_sp: int = None, axis_pol: int = None) -> None: self.im_shape = im_shape self.axis_dir = axis_dir self.axis_sp = axis_sp self.axis_pol = axis_pol self.dir_shape = self.im_shape[self.axis_dir] self.im_nrow = np.prod(self.dir_shape) self.im_nchan = self.im_shape[self.axis_sp] if self.axis_sp > 0 else 1 self.im_npol = self.im_shape[self.axis_pol] if self.axis_pol > 0 else 1 def validate(self) -> None: if not len(self.axis_dir): raise ValueError(f'invalid value: axis_dir {self.axis_dir}') if not (self.axis_sp in [-1, 2, 3] and self.axis_pol in [-1, 2, 3] and self.axis_sp != self.axis_pol): raise ValueError(f'invalid value: sp:{self.axis_sp} or pol:{self.axis_pol}') # if im_nchan is too few, say, <10, sdbaseline should abort if self.im_nchan < 10: raise ValueError(f'nchan {self.im_nchan} is too few to perform baseline subtraction') if len(self.im_shape) < 3: raise ValueError(f'invalid value: im_shape {self.im_shape}') if len(self.dir_shape) < 2: raise ValueError(f'invalid value: dir_shape {self.dir_shape}') def _get_image_shape(imagepath: str) -> _ImageShape: if not os.path.exists(imagepath): raise ValueError(f"path '{imagepath}' is not found") shape = None with tool_manager(imagepath, image) as ia: try: cs = ia.coordsys() shape = _ImageShape( ia.shape(), cs.findcoordinate('direction')['world'], __get_axis_position(cs.findcoordinate('spectral')['world']), # 3 or 2 or -1 __get_axis_position(cs.findcoordinate('stokes')['world']) # 2 or 3 or -1 ) finally: cs.done() if shape.im_shape.shape[0] < 3: raise ValueError(f"image '{imagepath}' is invalid") shape.validate() casalog.post(f'image shape is {shape.im_shape}, direciton {shape.dir_shape} ' f'({shape.im_nrow} pixels), npol {shape.im_npol}, nchan {shape.im_nchan}', 'DEBUG2') return shape def __get_axis_position(val: array = None) -> int: if val is not None and len(val) > 0: return val[0].item() return -1 @sdtask_decorator def imbaseline(imagename=None, linefile=None, output_cont=None, bloutput=None, maskmode=None, chans=None, thresh=None, avg_limit=None, minwidth=None, edge=None, blfunc=None, order=None, npiece=None, applyfft=None, fftthresh=None, addwn=None, rejwn=None, blparam=None, clipniter=None, clipthresh=None, dirkernel=None, major=None, minor=None, pa=None, kimage=None, scale=None, spkernel=None, kwidth=None) -> None: """Execute imbaseline. All specifications of arguments are defined in: https://open-jira.nrao.edu/browse/CAS-13520 The task executes several processes as follows: (1) do direction plane smoothing of input casa image (execute imsmooth) (2) convert casa image into MeasurementSet (a pixel of image corresponds to a line of MS) (3) do spectral smoothing of MS (execute sdsmooth) (4) do baselining (execute sdbaseline) (5) convert MS into casa image, and subtract results """ _validate_imagename(imagename) linefile = _prepare_linefile(linefile, imagename) with _stack_manager(imagename) as (image_stack, ms_stack): try: input_image_shape = _get_image_shape(image_stack.peak().path) # do direction plane smoothing _ImsmoothMethods.execute(dirkernel, major, minor, pa, kimage, scale, image_stack) # convert casaimage into MeasurementSet _Image2MSMethods.execute(DATACOLUMN, input_image_shape, image_stack, ms_stack) # do spectral smoothing _SdsmoothMethods.execute(DATACOLUMN, spkernel, kwidth, image_stack, ms_stack, input_image_shape) # do baselining _SdbaselineMethods.execute(DATACOLUMN, bloutput, maskmode, chans, thresh, avg_limit, minwidth, edge, blfunc, order, npiece, applyfft, fftthresh, addwn, rejwn, blparam, clipniter, clipthresh, image_stack, ms_stack, input_image_shape) # convert MeasurementSet into image and subtract results _ImageSubtractionMethods.execute(linefile, image_stack) if output_cont: _ImageSubtractionMethods.get_continuum_image(image_stack) finally: _do_post_processing(linefile) def _validate_imagename(imagename: str = None) -> None: if not os.path.exists(imagename): raise ValueError(f'Error: file {imagename} is not found.', 'SEVERE') def _prepare_linefile(linefile: str = None, imagename: str = None) -> str: if linefile == '' or linefile is None: linefile = os.path.basename(imagename).rstrip('/') + '_bs' if not OVERWRITE and os.path.exists(linefile): raise ValueError(f'Error: file {linefile} already exists, please delete before continuing.', 'SEVERE') return linefile def _generate_temporary_filename(prefix: str = '', ext: str = '') -> str: if prefix and prefix[-1] != '-': prefix = prefix + '-' if ext != '': ext = '.' + ext while True: filename = prefix + str(uuid.uuid4()) + ext if not os.path.exists(filename): return filename def _copy_image_file(infile: str = None, outfile: str = None) -> None: if not os.path.exists(infile): raise Exception(f'Image files not found, infile: {infile}') ia = image() try: ok = ia.fromimage(infile=infile, outfile=outfile) if not ok: raise Exception(f'Some error occured, infile: {infile}, outfile: {outfile}') finally: ia.done() def _do_post_processing(outfile) -> None: """Execute some post-processes of imbaseline.""" _eraseable_folder_register.clear(dry_run=do_not_erase_temporary_files) __write_image_history(outfile) def __write_image_history(outfile) -> None: with tool_manager(outfile, image) as outia: try: param_names = imbaseline.__code__.co_varnames[:imbaseline.__code__.co_argcount] vars = locals() param_vals = [vars[p] for p in param_names] write_image_history(outia, sys._getframe().f_code.co_name, param_names, param_vals, casalog) except Exception as instance: casalog.post(f'*** Error "{instance}" updating HISTORY', 'WARN') class _ImageSubtractionMethods(): @staticmethod def execute(linefile: str = None, image_stack: AbstractFileStack = None) -> None: """Execute image subtraction. The output image is computed as follows: - in case any smoothing (along direction and/or frequency) is executed output_image = input_image - (smoothed_image - smoothed_and_subtracted_image) - in case no smoothing is executed output_image = subtracted_image """ if image_stack.height() <= 2: # any smoothing were not executed output_image = image_stack.pop().path _eraseable_folder_register.pop(output_image) os.rename(output_image, linefile) image_stack.push(_UnerasableFolder(linefile)) else: smoothed_image = image_stack.subpeak().path subtracted_image = image_stack.peak().path base_image = image_stack.bottom().path _copy_image_file(base_image, linefile) _ImageSubtractionMethods.__subtract_image(smoothed_image, subtracted_image) _ImageSubtractionMethods.__subtract_image(linefile, smoothed_image) image_stack.push(_UnerasableFolder(linefile)) @staticmethod def get_continuum_image(image_stack: AbstractFileStack = None) -> None: """Compute 'input_image - output_image'.""" base_image = image_stack.bottom().path output_image = os.path.basename(base_image) + '.cont' _copy_image_file(base_image, output_image) linefile = image_stack.peak().path _ImageSubtractionMethods.__subtract_image(output_image, linefile) @staticmethod def __subtract_image(operand_a: str = None, operand_b: str = None) -> None: """Subtract image chunk.""" image_array = None with tool_manager(operand_b, image) as ia: image_array = ia.getchunk() with tool_manager(operand_a, image) as ia: ia.putchunk(pixels=ia.getchunk() - image_array, locking=True) class _ImsmoothMethods(): """Methoods for Imsmooth execution.""" @staticmethod def execute(dirkernel: str = None, major: str = None, minor: str = None, pa: str = None, kimage: str = None, scale: float = None, stack: AbstractFileStack = None) -> None: """Call casatasks.imsmooth task if dirkernel is specified.""" if not _ImsmoothMethods.require(dirkernel): casalog.post('omit image smoothing', 'INFO') return casalog.post('execute image smoothing', 'INFO') infile = stack.peak().path outfile = _generate_temporary_filename('dirsmooth', 'im') imsmooth(**_ImsmoothParams(infile, outfile, dirkernel, major, minor, pa, kimage, scale)()) stack.push(_EraseableFolder(outfile)) @staticmethod def require(dirkernel: str = 'none') -> None: if not dirkernel: dirkernel = 'none' if dirkernel == 'none': return False elif dirkernel in ['image', 'boxcar', 'gaussian']: return True else: raise ValueError(f'Unsupported direction smoothing kernel, {dirkernel}', 'SEVERE') class _SdsmoothMethods(): """Methoods for Sdsmooth execution.""" @staticmethod def execute(datacolumn: str = None, spkernel: str = None, kwidth: int = None, image_stack: AbstractFileStack = None, ms_stack: AbstractFileStack = None, image_shape: _ImageShape = None) -> None: """Call casatasks.sdsmooth task if spkernel is specified.""" if not _SdsmoothMethods.require(spkernel): casalog.post('omit spectral smoothing', 'INFO') return casalog.post('execute spectral smoothing', 'INFO') input_ms = ms_stack.peak().path output_ms = _generate_temporary_filename('spsmooth', 'ms') base_image = image_stack.bottom().path params = _SdsmoothParams(input_ms, output_ms, datacolumn.lower(), spkernel, kwidth) sdsmooth(**params()) ms_stack.push(_EraseableFolder(output_ms)) output_image = _MS2ImageMethods.convert(base_image, output_ms, image_shape, datacolumn) image_stack.push(_EraseableFolder(output_image)) ms_stack.spsmoothed = True ms_stack.kwidth = params.kwidth @staticmethod def require(spkernel: str = 'none') -> None: if not spkernel: spkernel = 'none' if spkernel == 'none': return False elif spkernel in ['boxcar', 'gaussian']: return True else: raise ValueError(f'Unsupported spectral smoothing kernel, {spkernel}', 'SEVERE') class _SdbaselineMethods(): """Methoods for Sdbaseline execution.""" @staticmethod def execute(datacolumn: str = None, bloutput: str = None, maskmode: str = None, chans: str = None, thresh: float = None, avg_limit: int = None, minwidth: int = None, edge: List[int] = None, blfunc: str = None, order: int = None, npiece: int = None, applyfft: bool = None, fftthresh: float = None, addwn: List[int] = None, rejwn: List[int] = None, blparam: str = None, clipniter: int = None, clipthresh: float = None, image_stack: AbstractFileStack = None, ms_stack: AbstractFileStack = None, image_shape: _ImageShape = None) -> None: """Call casatasks.sdbaseline task.""" casalog.post('execute spectral baselining', 'INFO') input_ms = ms_stack.peak().path output_ms = _generate_temporary_filename('baseline', 'ms') base_image = image_stack.bottom().path sdbaseline(**_SdbaselineParams(input_ms, output_ms, datacolumn.lower(), bloutput, maskmode, chans, thresh, avg_limit, minwidth, edge, blfunc, order, npiece, applyfft, fftthresh, addwn, rejwn, blparam, clipniter, clipthresh, ms_stack.spsmoothed, image_shape, ms_stack.kwidth)()) ms_stack.push(_EraseableFolder(output_ms)) output_image = _MS2ImageMethods.convert(base_image, output_ms, image_shape, datacolumn) image_stack.push(_EraseableFolder(output_image)) blparam_name = input_ms + '_blparam.' + _SdbaselineParams.FIXED_PARAM['blformat'] if os.path.exists(blparam_name): _SdbaselineMethods.__rename_blparam_filename(blparam_name, base_image) @staticmethod def __rename_blparam_filename(filename: str = None, basename: str = None) -> str: if not os.path.exists(filename): return None newname = os.path.basename(basename) + '.ms_blparam.' + \ _SdbaselineParams.FIXED_PARAM['blformat'] if os.path.exists(newname): return filename try: os.rename(filename, newname) except Exception: casalog.post(f'rename failure:from {filename} to {newname}', 'SEVERE') return filename return newname class _ImsmoothParams(AbstractValidatable): """Parameter manipulation class for execution of casatasks.imsmooth.""" FIXED_PARAM = dict( targetres=False, mask='', beam={}, region='', box='', chans='', stokes='', stretch=False, overwrite=True ) def __init__(self, infile: str = None, outfile: str = None, dirkernel: str = 'none', major: str = '', minor: str = '', pa: str = '', kimage: str = '', scale: int = -1.0) -> None: self.infile = infile self.outfile = outfile # dirkernel options: none(default)/gaussian/boxcar/image self.kernel = dirkernel if dirkernel is not None else 'none' # subparameter for dirkernel = gaussian/boxcar self.major = major if major is not None else '' self.minor = minor if minor is not None else '' self.pa = pa if pa is not None else '' # subparameter for dirkernel = image self.kimage = kimage if kimage is not None else '' self.scale = scale if scale is not None else -1.0 self.validate() def validate(self) -> None: self.__validate_dirkernel() def __validate_dirkernel(self) -> None: if self.kernel == 'image': self.major = self.minor = self.pa = '' if self.kimage != '' and not os.path.exists(self.kimage): raise ValueError(f'Error: file {self.kimage} is not found.', 'SEVERE') elif self.kernel == 'gaussian' or self.kernel == 'boxcar': self.kimage = '' self.scale = -1.0 elif self.kernel != 'none': raise ValueError(f'Unsupported maskmode, {self.kernel}', 'SEVERE') def __call__(self) -> Union[List[Any], Dict[str, str]]: """Convert the class into arguments of imsmooth(). __log_origin is for callabletask.log_origin_setter """ retval = dict(self.FIXED_PARAM, imagename=self.infile, kernel=self.kernel, major=self.major, minor=self.minor, pa=self.pa, kimage=self.kimage, scale=self.scale, outfile=self.outfile, __log_origin='imbaseline') if dump_tasks: print(_dump_tasks('imsmooth', retval)) return retval class _SdsmoothParams(AbstractValidatable): """Parameter manipulation class for execution of casatasks.sdsmooth.""" FIXED_PARAM = dict( spw='', field='', antenna='', timerange='', scan='', pol='', intent='', reindex=True, overwrite=True ) def __init__(self, infile: str = None, outfile: str = None, datacolumn: str = None, spkernel: str = 'none', kwidth: int = 5) -> None: self.infile = infile self.outfile = outfile self.datacolumn = datacolumn self.kernel = spkernel if spkernel is not None else 'none' # none(default)/gaussian/boxcar self.kwidth = kwidth if kwidth is not None else 5 # gaussian/boxcar self.validate() def validate(self) -> None: self.__validate_spkernel() def __validate_spkernel(self) -> None: if self.kernel == 'none': self.kwidth = 5 elif not (self.kernel == 'gaussian' or self.kernel == 'boxcar'): raise ValueError(f'Unsupported maskmode, {self.kernel}', 'SEVERE') def __call__(self) -> Dict[str, Any]: """Convert the class into arguments of sdsmooth(). __log_origin is for sdutil.callabletask_decorator. """ retval = dict(self.FIXED_PARAM, infile=self.infile, datacolumn=self.datacolumn, kernel=self.kernel, kwidth=self.kwidth, outfile=self.outfile, __log_origin='imbaseline') if dump_tasks: print(_dump_tasks('sdsmooth', retval)) return retval class _SdbaselineParams(AbstractValidatable): """Parameter manipulation class for execution of casatasks.sdbaseline.""" FIXED_PARAM = dict( antenna='', field='', timerange='', scan='', pol='', intent='', reindex=True, blmode='fit', dosubtract=True, blformat='csv', bltable='', updateweight=False, sigmavalue='stddev', showprogress=False, minnrow=1000, fftmethod='fft', verbose=False, overwrite=True ) def __init__(self, infile: str = None, outfile: str = None, datacolumn: str = None, bloutput: str = '', maskmode: str = 'list', chans: str = '', thresh: float = 5.0, avg_limit: int = 4, minwidth: int = 4, edge: List[int] = [0, 0], blfunc: str = 'poly', order: int = 5, npiece: int = 3, applyfft: bool = True, fftthresh: float = 3.0, addwn: List = [0], rejwn: List = [], blparam: str = '', clipniter: int = 0, clipthresh: float = 3.0, spsmoothed: bool = False, image_shape: _ImageShape = None, kwidth: int = None) -> None: self.infile = infile self.outfile = outfile self.datacolumn = datacolumn self.bloutput = bloutput if bloutput is not None else '' # maskmode: list(default)/auto self.maskmode = maskmode.lower() if maskmode is not None else 'list' # subparam for maskmode = list self.spw = self.__chans2spw(chans, self.maskmode) # subparam for maskmode = auto self.thresh = thresh if thresh is not None else 5.0 self.avg_limit = avg_limit if avg_limit is not None else 4 self.minwidth = minwidth if minwidth is not None else 4 self.edge = edge if edge is not None else [0, 0] # poly(default)/chebyshev/cspline/sinusoid/variable self.blfunc = blfunc.lower() if blfunc is not None else 'poly' # subparam for blfunc = poly/chebyshev self.order = order if order is not None else 5 # subparam for blfunc = cspline self.npiece = npiece if npiece is not None else 3 # subparam for blfunc = sinusoid self.applyfft = applyfft if applyfft is not None else True self.fftthresh = fftthresh if fftthresh is not None else 3.0 self.addwn = addwn if addwn is not None else [0] self.rejwn = rejwn if rejwn is not None else [] # subparam for blfunc = variable self.blparam = blparam if blparam is not None else '' self.clipniter = clipniter if clipniter is not None else 0 self.clipthresh = clipthresh if clipthresh is not None else 3.0 if spsmoothed: spw = '0' left_edge = kwidth // 2 right_edge = image_shape.im_nchan - kwidth // 2 if self.spw: coverage = set(list(range(left_edge, right_edge))) sets = dict() for i, s in spwchan_to_sets(self.infile, self.spw).items(): sets[i] = s & coverage spw = sets_to_spwchan(sets) else: spw = f'0:{left_edge}~{right_edge-1}' self.spw = spw if not self.spw: self.spw = '0' def __chans2spw(self, chans: str, maskmode) -> str: if not chans or maskmode != 'list': return '' return chans def validate(self) -> None: self.__validate_maskmode() self.__validate_blfunc() def __validate_maskmode(self) -> None: if not (self.maskmode == 'list' or self.maskmode == 'auto'): raise ValueError(f'Unsupported maskmode, {self.maskmode}', 'SEVERE') def __validate_blfunc(self) -> None: def is_valid_blfunc(self) -> None: return self.blfunc == 'poly' or self.blfunc == 'chebyshev' or self.blfunc == 'cspline' \ or self.blfunc == 'sinusoid' or self.blfunc == 'variable' if not is_valid_blfunc(self): raise ValueError(f'Unsupported blfunc, {self.blfunc}', 'SEVERE') if self.blfunc == 'variable' and not os.path.exists(self.blparam): raise ValueError(f'input file {self.blparam} does not exists', 'SEVERE') def __call__(self) -> Dict[str, Any]: """Convert the class into arguments of sdbaseline(). __log_origin is for sdutil.callabletask_decorator. """ retval = dict(self.FIXED_PARAM, infile=self.infile, datacolumn=self.datacolumn, maskmode=self.maskmode, thresh=self.thresh, avg_limit=self.avg_limit, minwidth=self.minwidth, edge=self.edge, bloutput=self.bloutput, blfunc=self.blfunc, order=self.order, npiece=self.npiece, applyfft=self.applyfft, fftthresh=self.fftthresh, addwn=self.addwn, rejwn=self.rejwn, clipthresh=self.clipthresh, clipniter=self.clipniter, blparam=self.blparam, outfile=self.outfile, spw=self.spw, __log_origin='imbaseline') if dump_tasks: print(_dump_tasks('sdbaseline', retval)) return retval class _Image2MSParams(AbstractValidatable): """Parameter manipulation class for executing image2ms().""" def __init__(self, infile: str = None, outfile: str = None, datacolumn: str = 'DATA', input_image_shape: _ImageShape = None) -> None: self.infile = infile self.outfile = outfile self.datacolumn = datacolumn self.im_shape = input_image_shape.im_shape self.axis_dir = input_image_shape.axis_dir self.axis_sp = input_image_shape.axis_sp self.axis_pol = input_image_shape.axis_pol self.dir_shape = input_image_shape.dir_shape self.im_nrow = input_image_shape.im_nrow self.im_nchan = input_image_shape.im_nchan self.im_npol = input_image_shape.im_npol self.validate() def validate(self) -> None: self.__validate_outfile() def __validate_outfile(self) -> None: if os.path.exists(self.outfile): raise ValueError(f'Folder exists: {self.outfile}') class _Image2MSMethods(): """Methods for converting image to MeasurementSet.""" @staticmethod def execute(datacolumn: str = None, input_image_shape: _ImageShape = None, image_stack: AbstractFileStack = None, ms_stack: AbstractFileStack = None) -> None: """Convert a casaimage to a MeasurementSet.""" casalog.post('convert casaimage to MeasurementSet', 'INFO') infile = image_stack.peak().path outfile = _generate_temporary_filename('img2ms', 'ms') _Image2MSMethods.__image2ms(_Image2MSParams(infile, outfile, datacolumn, input_image_shape)) ms_stack.push(_EraseableFolder(outfile)) @staticmethod def __image2ms(params: _Image2MSParams = None) -> None: """Convert CasaImage into MeasurementSet.""" _Image2MSMethods.__create_empty_ms(params) _Image2MSMethods.__put_parametes_from_image_to_ms(params) @staticmethod def __create_empty_ms(params: _Image2MSParams = None) -> None: _Image2MSMethods.__cleanup_ms_path(params) _Image2MSMethods.__create_maintable(params) _Image2MSMethods.__create_antenna_table(params) _Image2MSMethods.__create_data_description_table(params) _Image2MSMethods.__create_feed_table(params) _Image2MSMethods.__create_field_table(params) _Image2MSMethods.__create_flag_cmd_table(params) _Image2MSMethods.__create_history_table(params) _Image2MSMethods.__create_observation_table(params) _Image2MSMethods.__create_pointing_table(params) _Image2MSMethods.__create_polarization_table(params) _Image2MSMethods.__create_processor_table(params) _Image2MSMethods.__create_source_table(params) _Image2MSMethods.__create_special_window_table(params) _Image2MSMethods.__create_state_table(params) @staticmethod def __generate_time_list(nrow_req: int) -> np.ndarray: mjd_sec = qa.convert(qa.quantity('1995-04-13T09:19:00'), 's')['value'] # dummy timestamp interval = 30.0 return mjd_sec + np.arange(nrow_req) * interval @staticmethod def __create_maintable(params: _Image2MSParams = None) -> None: tb = table() try: tb.create(params.outfile, _EmptyMSBaseInformation.ms_desc, dminfo=_EmptyMSBaseInformation.ms_dminfo) tb.putkeyword(keyword='MS_VERSION', value=2) nrow = tb.nrows() nrow_req = params.im_nrow * params.im_npol nrow = tb.nrows() if nrow != nrow_req: tb.addrows(nrow_req) ddid = tb.getcol('DATA_DESC_ID') ddid[:] = 0 tb.putcol('DATA_DESC_ID', ddid) dummy = np.zeros(nrow_req, dtype=int) tb.putcol('ANTENNA1', dummy) tb.putcol('ANTENNA2', dummy) tb.putcol('STATE_ID', dummy) time_list = _Image2MSMethods.__generate_time_list(nrow_req) tb.putcol('TIME', time_list) casalog.post(f'number of rows {nrow}, number of image pixels {params.im_nrow}, ' f'number of pols {params.im_npol}, ' f'required rows {nrow_req}', 'DEBUG2') finally: tb.close() @staticmethod def __create_antenna_table(params: _Image2MSParams = None) -> None: _Image2MSMethods.__create_subtable(params.outfile, 'ANTENNA', _EmptyMSBaseInformation.antenna_desc, _EmptyMSBaseInformation.antenna_dminfo) with table_manager(os.path.join(params.outfile, 'ANTENNA'), nomodify=False) as tb: tb.addrows(1) @staticmethod def __create_data_description_table(params: _Image2MSParams = None) -> None: _Image2MSMethods.__create_subtable(params.outfile, 'DATA_DESCRIPTION', _EmptyMSBaseInformation.data_description_desc, _EmptyMSBaseInformation.data_description_dminfo) with table_manager(os.path.join(params.outfile, 'DATA_DESCRIPTION'), nomodify=False) as tb: tb.addrows(1) tb.putcell('SPECTRAL_WINDOW_ID', 0, 0) tb.putcell('POLARIZATION_ID', 0, 0) @staticmethod def __create_feed_table(params: _Image2MSParams = None) -> None: _Image2MSMethods.__create_subtable(params.outfile, 'FEED', _EmptyMSBaseInformation.feed_desc, _EmptyMSBaseInformation.feed_dminfo) with table_manager(os.path.join(params.outfile, 'FEED'), nomodify=False) as tb: tb.addrows(1) @staticmethod def __create_field_table(params: _Image2MSParams = None) -> None: _Image2MSMethods.__create_subtable(params.outfile, 'FIELD', _EmptyMSBaseInformation.field_desc, _EmptyMSBaseInformation.field_dminfo) with table_manager(os.path.join(params.outfile, 'FIELD'), nomodify=False) as tb: tb.addrows(1) tb.putcell('DELAY_DIR', 0, np.zeros((2, 1))) tb.putcell('PHASE_DIR', 0, np.zeros((2, 1))) tb.putcell('REFERENCE_DIR', 0, np.zeros((2, 1))) @staticmethod def __create_flag_cmd_table(params: _Image2MSParams = None) -> None: _Image2MSMethods.__create_subtable(params.outfile, 'FLAG_CMD', _EmptyMSBaseInformation.flag_cmd_desc, _EmptyMSBaseInformation.flag_cmd_dminfo) @staticmethod def __create_history_table(params: _Image2MSParams = None) -> None: _Image2MSMethods.__create_subtable(params.outfile, 'HISTORY', _EmptyMSBaseInformation.history_desc, _EmptyMSBaseInformation.history_dminfo) @staticmethod def __create_observation_table(params: _Image2MSParams = None) -> None: _Image2MSMethods.__create_subtable(params.outfile, 'OBSERVATION', _EmptyMSBaseInformation.observation_desc, _EmptyMSBaseInformation.observation_dminfo) with table_manager(os.path.join(params.outfile, 'OBSERVATION'), nomodify=False) as tb: tb.addrows(1) @staticmethod def __create_pointing_table(params: _Image2MSParams = None) -> None: _Image2MSMethods.__create_subtable(params.outfile, 'POINTING', _EmptyMSBaseInformation.pointing_desc, _EmptyMSBaseInformation.pointing_dminfo) @staticmethod def __create_polarization_table(params: _Image2MSParams = None) -> None: _Image2MSMethods.__create_subtable(params.outfile, 'POLARIZATION', _EmptyMSBaseInformation.polarization_desc, _EmptyMSBaseInformation.polarization_dminfo) with table_manager(os.path.join(params.outfile, 'POLARIZATION'), nomodify=False) as tb: corr_type = np.ones(1, dtype=int) corr_product = np.ones(2, dtype=int).reshape((2, 1)) if tb.nrows() == 0: tb.addrows(1) tb.putcell('NUM_CORR', 0, 1) tb.putcell('CORR_TYPE', 0, corr_type) tb.putcell('CORR_PRODUCT', 0, corr_product) @staticmethod def __create_processor_table(params: _Image2MSParams = None) -> None: _Image2MSMethods.__create_subtable(params.outfile, 'PROCESSOR', _EmptyMSBaseInformation.processor_desc, _EmptyMSBaseInformation.processor_dminfo) @staticmethod def __create_source_table(params: _Image2MSParams = None) -> None: _Image2MSMethods.__create_subtable(params.outfile, 'SOURCE', _EmptyMSBaseInformation.source_desc, _EmptyMSBaseInformation.source_dminfo) @staticmethod def __create_special_window_table(params: _Image2MSParams = None) -> None: _Image2MSMethods.__create_subtable(params.outfile, 'SPECTRAL_WINDOW', _EmptyMSBaseInformation.special_window_desc, _EmptyMSBaseInformation.special_window_dminfo) with table_manager(os.path.join(params.outfile, 'SPECTRAL_WINDOW'), nomodify=False) as tb: cw = np.ones(params.im_nchan, dtype=float) * 1e6 cf = 1e9 + np.arange(params.im_nchan, dtype=float) * 1e6 if tb.nrows() == 0: tb.addrows(1) tb.putcell('NUM_CHAN', 0, params.im_nchan) tb.putcell('CHAN_FREQ', 0, cf) tb.putcell('CHAN_WIDTH', 0, cw) tb.putcell('RESOLUTION', 0, cw) tb.putcell('EFFECTIVE_BW', 0, cw) tb.putcell('TOTAL_BANDWIDTH', 0, cw.sum()) @staticmethod def __create_state_table(params: _Image2MSParams = None) -> None: _Image2MSMethods.__create_subtable(params.outfile, 'STATE', _EmptyMSBaseInformation.state_desc, _EmptyMSBaseInformation.state_dminfo) with table_manager(os.path.join(params.outfile, 'STATE'), nomodify=False) as tb: if tb.nrows() == 0: tb.addrows(1) tb.putcell('OBS_MODE', 0, 'OBSERVE_TARGET#ON_SOURCE_IMAGE_DOMAIN') @staticmethod def __cleanup_ms_path(params, overwrite: bool = True) -> None: exists = os.path.exists(params.outfile) if overwrite and exists: shutil.rmtree(params.outfile) return exists @staticmethod def __create_subtable(outfile: str = None, subtable: str = None, desc: str = None, dminfo: str = None) -> None: tb = table() try: tb.create(f'{outfile}/{subtable}', desc, dminfo=dminfo) finally: tb.close() with table_manager(outfile, nomodify=False) as tb: tb.putkeyword(subtable, f'Table: {outfile}/{subtable}') @staticmethod def __put_parametes_from_image_to_ms(params: _Image2MSParams = None) -> None: _Image2MSMethods.__put_image_parameters_into_ms( params, *_Image2MSMethods.__get_image_parameters(params)) @staticmethod def __get_image_parameters(params: _Image2MSParams = None) -> Tuple[np.array, int]: # get image array and mask from the image with tool_manager(params.infile, image) as ia: arr = ia.getchunk() msk = ia.getchunk(getmask=True) # put image array slices to MS DATA column # axis indices for spatial, spectral and polarization axes xax, yax = params.axis_dir spax = params.axis_sp if params.axis_pol > 0: polax = params.axis_pol else: arr = np.expand_dims(arr, axis=3) msk = np.expand_dims(msk, axis=3) polax = 3 casalog.post(f'axis index: {xax} {yax} {polax} {spax}', 'DEBUG2') return arr, msk, xax, yax, spax, polax @staticmethod def __put_image_parameters_into_ms(params: _Image2MSParams, image_array: np.array, mask_array: np.array, axis_x: int, axis_y: int, axis_sp: int, axis_pol: int) -> None: # which data column to use with table_manager(params.outfile, nomodify=False) as tb: # also set FLAG, SIGMA, WEIGHT, and UVW index_list = [0, 0, 0, 0] index_list[axis_sp] = np.arange(params.im_nchan) nx, ny = params.dir_shape irow = 0 wgt = np.ones(1, dtype=float) uvw = np.zeros(3, dtype=float) for ix in range(nx): index_list[axis_x] = ix for iy in range(ny): index_list[axis_y] = iy for ip in range(params.im_npol): index_list[axis_pol] = ip slice = tuple(index_list) cell = image_array[slice] mask = np.logical_not(mask_array[slice]) casalog.post(f'slice={slice}, cell={cell}', 'DEBUG2') tb.putcell(params.datacolumn, irow, np.expand_dims(cell, axis=0)) tb.putcell('FLAG', irow, np.expand_dims(mask, axis=0)) tb.putcell('SIGMA', irow, wgt) tb.putcell('WEIGHT', irow, wgt) tb.putcell('UVW', irow, uvw) irow += 1 class _MS2ImageMethods(): @staticmethod def convert(base_image: str = None, input_ms: str = None, input_image_shape: _ImageShape = None, datacolumn: str = None) -> None: output_image = _MS2ImageMethods.__change_file_extension(input_ms, 'im') _copy_image_file(base_image, output_image) # mask data is also copied in this method image_array = _MS2ImageMethods.__make_image_array(input_image_shape, input_ms, datacolumn) _MS2ImageMethods.__output_image(output_image, image_array) return output_image @staticmethod def __change_file_extension(path: str = None, ext: str = None) -> str: if not os.path.exists(path): RuntimeError(f'cannot find path: {path}') base, oldext = os.path.splitext(path) new_path = base_path = f'{base}.{ext}' i = 0 while True: if not os.path.exists(new_path): break new_path = base_path + f'.{i}' i += 1 if i > 10: raise RuntimeError('some file system error occured') return new_path @staticmethod def __make_image_array(input_image_shape: _ImageShape = None, infile: str = None, datacolumn: str = None) -> np.array: nx, ny = input_image_shape.dir_shape image_array = np.empty((nx, ny, input_image_shape.im_nchan)) pos = 0 with table_manager(infile) as tb: for i in range(nx): for j in range(ny): image_array[i][j] = tb.getcell(datacolumn, pos)[0].real pos += 1 if input_image_shape.axis_pol > 0: image_array = np.expand_dims(image_array, input_image_shape.axis_pol) return image_array @staticmethod def __output_image(outfile: str = None, image_array: np.array = None) -> None: with tool_manager(outfile, image) as ia: ia.putchunk(pixels=image_array, locking=True) def _dump_tasks(taskname: str, vals: dict): cmd = f'{taskname}(' arr = [] for key, val in vals.items(): if key != '__log_origin': quote = '' if type(val) in (bool, int, float) else '\'' arr.append(f'{key}={quote}{val}{quote}') cmd += ', '.join(arr) cmd += ')' return cmd class _EmptyMSBaseInformation: """The Parameters class for creating an empty MeasurementSet. This class contains dictionaries to create an empty MS using table.create(), and it has no method. Dictionaries have two types; desc(desctiption) and dminfo(data management infomation), these are used as arguments of table.create(), and for a table creating, it needs a desc dict and a dminfo dict. so there are dicts of twice of table amount in a MeasurementSet. """ ms_desc = { 'ANTENNA1': {'comment': 'ID of first antenna in interferometer', 'dataManagerGroup': 'SSM', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'ANTENNA2': {'comment': 'ID of second antenna in interferometer', 'dataManagerGroup': 'SSM', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'ARRAY_ID': {'comment': 'ID of array or subarray', 'dataManagerGroup': 'ISMData', 'dataManagerType': 'IncrementalStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'DATA': {'comment': 'The data column', 'dataManagerGroup': 'TiledData', 'dataManagerType': 'TiledShapeStMan', 'keywords': {}, 'maxlen': 0, 'ndim': 2, 'option': 0, 'valueType': 'complex'}, 'DATA_DESC_ID': {'comment': 'The data description table index', 'dataManagerGroup': 'SSM', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'EXPOSURE': {'comment': 'The effective integration time', 'dataManagerGroup': 'ISMData', 'dataManagerType': 'IncrementalStMan', 'keywords': {'QuantumUnits': np.array(['s'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, 'FEED1': {'comment': 'The feed index for ANTENNA1', 'dataManagerGroup': 'ISMData', 'dataManagerType': 'IncrementalStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'FEED2': {'comment': 'The feed index for ANTENNA2', 'dataManagerGroup': 'ISMData', 'dataManagerType': 'IncrementalStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'FIELD_ID': {'comment': 'Unique id for this pointing', 'dataManagerGroup': 'ISMData', 'dataManagerType': 'IncrementalStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'FLAG': {'comment': 'The data flags, array of bools with same shape as data', 'dataManagerGroup': 'TiledFlag', 'dataManagerType': 'TiledShapeStMan', 'keywords': {}, 'maxlen': 0, 'ndim': 2, 'option': 0, 'valueType': 'boolean'}, 'FLAG_CATEGORY': {'comment': 'The flag category, NUM_CAT flags for each datum', 'dataManagerGroup': 'TiledFlagCategory', 'dataManagerType': 'TiledShapeStMan', 'keywords': {'CATEGORY': np.array(['FLAG_CMD', 'ORIGINAL', 'USER'], dtype='<U16')}, 'maxlen': 0, 'ndim': 3, 'option': 0, 'valueType': 'boolean'}, 'FLAG_ROW': {'comment': 'Row flag - flag all data in this row if True', 'dataManagerGroup': 'ISMData', 'dataManagerType': 'IncrementalStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'boolean'}, 'INTERVAL': {'comment': 'The sampling interval', 'dataManagerGroup': 'ISMData', 'dataManagerType': 'IncrementalStMan', 'keywords': {'QuantumUnits': np.array(['s'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, 'OBSERVATION_ID': {'comment': 'ID for this observation, index in OBSERVATION table', 'dataManagerGroup': 'ISMData', 'dataManagerType': 'IncrementalStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'PROCESSOR_ID': {'comment': 'Id for backend processor, index in PROCESSOR table', 'dataManagerGroup': 'ISMData', 'dataManagerType': 'IncrementalStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'SCAN_NUMBER': {'comment': 'Sequential scan number from on-line system', 'dataManagerGroup': 'ISMData', 'dataManagerType': 'IncrementalStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'SIGMA': {'comment': 'Estimated rms noise for channel with unity bandpass response', 'dataManagerGroup': 'TiledSigma', 'dataManagerType': 'TiledShapeStMan', 'keywords': {}, 'maxlen': 0, 'ndim': 1, 'option': 0, 'valueType': 'float'}, 'STATE_ID': {'comment': 'ID for this observing state', 'dataManagerGroup': 'ISMData', 'dataManagerType': 'IncrementalStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'TIME': {'comment': 'Modified Julian Day', 'dataManagerGroup': 'ISMData', 'dataManagerType': 'IncrementalStMan', 'keywords': {'MEASINFO': {'Ref': 'TAI', 'type': 'epoch'}, 'QuantumUnits': np.array(['s'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, 'TIME_CENTROID': {'comment': 'Modified Julian Day', 'dataManagerGroup': 'ISMData', 'dataManagerType': 'IncrementalStMan', 'keywords': {'MEASINFO': {'Ref': 'TAI', 'type': 'epoch'}, 'QuantumUnits': np.array(['s'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, 'UVW': {'comment': 'Vector with uvw coordinates (in meters)', 'dataManagerGroup': 'TiledUVW', 'dataManagerType': 'TiledColumnStMan', 'keywords': {'MEASINFO': {'Ref': 'J2000', 'type': 'uvw'}, 'QuantumUnits': np.array(['m', 'm', 'm'], dtype='<U16')}, 'maxlen': 0, 'ndim': 1, 'option': 5, 'shape': np.array([3]), 'valueType': 'double'}, 'WEIGHT': {'comment': 'Weight for each polarization spectrum', 'dataManagerGroup': 'TiledWgt', 'dataManagerType': 'TiledShapeStMan', 'keywords': {}, 'maxlen': 0, 'ndim': 1, 'option': 0, 'valueType': 'float'}, 'WEIGHT_SPECTRUM': {'comment': 'Weight for each data point', 'dataManagerGroup': 'TiledWgtSpectrum', 'dataManagerType': 'TiledShapeStMan', 'keywords': {}, 'maxlen': 0, 'ndim': 2, 'option': 0, 'valueType': 'float'}, } ms_dminfo = { '*1': {'COLUMNS': array(['ARRAY_ID', 'EXPOSURE', 'FEED1', 'FEED2', 'FIELD_ID', 'FLAG_ROW', 'INTERVAL', 'OBSERVATION_ID', 'PROCESSOR_ID', 'SCAN_NUMBER', 'STATE_ID', 'TIME', 'TIME_CENTROID'], dtype='<U16'), 'NAME': 'ISMData', 'SEQNR': 0, 'SPEC': {'BUCKETSIZE': 62456, 'MaxCacheSize': 1, 'PERSCACHESIZE': 1}, 'TYPE': 'IncrementalStMan'}, '*2': {'COLUMNS': array(['ANTENNA1', 'ANTENNA2', 'DATA_DESC_ID'], dtype='<U16'), 'NAME': 'SSM', 'SEQNR': 1, 'SPEC': {'BUCKETSIZE': 32768, 'IndexLength': 198, 'MaxCacheSize': 2, 'PERSCACHESIZE': 2}, 'TYPE': 'StandardStMan'}, '*3': {'COLUMNS': array(['DATA'], dtype='<U16'), 'NAME': 'TiledData', 'SEQNR': 2, 'SPEC': {'DEFAULTTILESHAPE': array([2, 63, 1040]), 'HYPERCUBES': {'*1': {'BucketSize': 1048320, 'CellShape': array([2, 63]), 'CubeShape': array([2, 63, 22653]), 'ID': {}, 'TileShape': array([2, 63, 1040])}}, 'IndexSize': 1, 'MAXIMUMCACHESIZE': 0, 'MaxCacheSize': 0, 'SEQNR': 2}, 'TYPE': 'TiledShapeStMan'}, '*4': {'COLUMNS': array(['FLAG'], dtype='<U16'), 'NAME': 'TiledFlag', 'SEQNR': 3, 'SPEC': {'DEFAULTTILESHAPE': array([2, 63, 1040]), 'HYPERCUBES': {'*1': {'BucketSize': 16380, 'CellShape': array([2, 63]), 'CubeShape': array([2, 63, 22653]), 'ID': {}, 'TileShape': array([2, 63, 1040])}}, 'IndexSize': 1, 'MAXIMUMCACHESIZE': 0, 'MaxCacheSize': 0, 'SEQNR': 3}, 'TYPE': 'TiledShapeStMan'}, '*5': {'COLUMNS': array(['FLAG_CATEGORY'], dtype='<U16'), 'NAME': 'TiledFlagCategory', 'SEQNR': 4, 'SPEC': {'DEFAULTTILESHAPE': array([2, 63, 1, 1040]), 'HYPERCUBES': {}, 'IndexSize': 0, 'MAXIMUMCACHESIZE': 0, 'MaxCacheSize': 0, 'SEQNR': 4}, 'TYPE': 'TiledShapeStMan'}, '*6': {'COLUMNS': array(['WEIGHT_SPECTRUM'], dtype='<U16'), 'NAME': 'TiledWgtSpectrum', 'SEQNR': 5, 'SPEC': {'DEFAULTTILESHAPE': array([2, 63, 1040]), 'HYPERCUBES': {'*1': {'BucketSize': 524160, 'CellShape': array([2, 63]), 'CubeShape': array([2, 63, 22653]), 'ID': {}, 'TileShape': array([2, 63, 1040])}}, 'IndexSize': 1, 'MAXIMUMCACHESIZE': 0, 'MaxCacheSize': 0, 'SEQNR': 5}, 'TYPE': 'TiledShapeStMan'}, '*7': {'COLUMNS': array(['UVW'], dtype='<U16'), 'NAME': 'TiledUVW', 'SEQNR': 6, 'SPEC': {'DEFAULTTILESHAPE': array([3, 1024]), 'HYPERCUBES': {'*1': {'BucketSize': 24576, 'CellShape': array([3]), 'CubeShape': array([3, 22653]), 'ID': {}, 'TileShape': array([3, 1024])}}, 'MAXIMUMCACHESIZE': 0, 'MaxCacheSize': 0, 'SEQNR': 6}, 'TYPE': 'TiledColumnStMan'}, '*8': {'COLUMNS': array(['WEIGHT'], dtype='<U16'), 'NAME': 'TiledWgt', 'SEQNR': 7, 'SPEC': {'DEFAULTTILESHAPE': array([2, 1040]), 'HYPERCUBES': {'*1': {'BucketSize': 8320, 'CellShape': array([2]), 'CubeShape': array([2, 22653]), 'ID': {}, 'TileShape': array([2, 1040])}}, 'IndexSize': 1, 'MAXIMUMCACHESIZE': 0, 'MaxCacheSize': 0, 'SEQNR': 7}, 'TYPE': 'TiledShapeStMan'}, '*9': {'COLUMNS': array(['SIGMA'], dtype='<U16'), 'NAME': 'TiledSigma', 'SEQNR': 8, 'SPEC': {'DEFAULTTILESHAPE': array([2, 1040]), 'HYPERCUBES': {'*1': {'BucketSize': 8320, 'CellShape': array([2]), 'CubeShape': array([2, 22653]), 'ID': {}, 'TileShape': array([2, 1040])}}, 'IndexSize': 1, 'MAXIMUMCACHESIZE': 0, 'MaxCacheSize': 0, 'SEQNR': 8}, 'TYPE': 'TiledShapeStMan'} } antenna_desc = { 'DISH_DIAMETER': {'comment': 'Physical diameter of dish', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'QuantumUnits': array(['m'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, 'FLAG_ROW': {'comment': 'Flag for this row', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'boolean'}, 'MOUNT': {'comment': 'Mount type e.g. alt-az, equatorial, etc.', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'NAME': {'comment': 'Antenna name, e.g. VLA22, CA03', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'ARRAY_NAME': 'VLA'}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'OFFSET': {'comment': 'Axes offset of mount to FEED REFERENCE point', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'Ref': 'ITRF', 'type': 'position'}, 'QuantumUnits': array(['m', 'm', 'm'], dtype='<U16')}, 'maxlen': 0, 'ndim': 1, 'option': 5, 'shape': array([3]), 'valueType': 'double'}, 'POSITION': {'comment': 'Antenna X,Y,Z phase reference position', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'ARRAY_POSITION': array([0., 0., 0.]), 'MEASINFO': {'Ref': 'ITRF', 'type': 'position'}, 'QuantumUnits': array(['m', 'm', 'm'], dtype='<U16')}, 'maxlen': 0, 'ndim': 1, 'option': 5, 'shape': array([3]), 'valueType': 'double'}, 'STATION': {'comment': 'Station (antenna pad) name', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'TYPE': {'comment': 'Antenna type (e.g. SPACE-BASED)', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, '_define_hypercolumn_': {}, '_keywords_': {'DEGPDY': 360.9856341442, 'GSTIA0': 3.5030897164680597, 'RDATE': 4304481539.999771, 'TIMSYS': 'TAI'}, '_private_keywords_': {} } antenna_dminfo = { '*1': {'COLUMNS': array(['DISH_DIAMETER', 'FLAG_ROW', 'MOUNT', 'NAME', 'OFFSET', 'POSITION', 'STATION', 'TYPE'], dtype='<U16'), 'NAME': 'StandardStMan', 'SEQNR': 0, 'SPEC': {'BUCKETSIZE': 3332, 'IndexLength': 126, 'MaxCacheSize': 2, 'PERSCACHESIZE': 2}, 'TYPE': 'StandardStMan' } } data_description_desc = { 'FLAG_ROW': {'comment': 'Flag this row', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'boolean'}, 'POLARIZATION_ID': {'comment': 'Pointer to polarization table', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'SPECTRAL_WINDOW_ID': {'comment': 'Pointer to spectralwindow table', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, '_define_hypercolumn_': {}, '_keywords_': {}, '_private_keywords_': {} } data_description_dminfo = { '*1': {'COLUMNS': array(['FLAG_ROW', 'POLARIZATION_ID', 'SPECTRAL_WINDOW_ID'], dtype='<U19'), 'NAME': 'StandardStMan', 'SEQNR': 0, 'SPEC': {'BUCKETSIZE': 260, 'IndexLength': 126, 'MaxCacheSize': 2, 'PERSCACHESIZE': 2}, 'TYPE': 'StandardStMan' } } feed_desc = { 'ANTENNA_ID': {'comment': 'ID of antenna in this array', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'BEAM_ID': {'comment': 'Id for BEAM model', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'BEAM_OFFSET': {'comment': 'Beam position offset (on sky but in antennareference frame)', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'Ref': 'J2000', 'type': 'direction'}, 'QuantumUnits': array(['rad', 'rad'], dtype='<U16')}, 'maxlen': 0, 'ndim': 2, 'option': 0, 'valueType': 'double'}, 'FEED_ID': {'comment': 'Feed id', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'INTERVAL': {'comment': 'Interval for which this set of parameters is accurate', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'QuantumUnits': array(['s'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, 'NUM_RECEPTORS': {'comment': 'Number of receptors on this feed (probably 1 or 2)', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'POLARIZATION_TYPE': {'comment': 'Type of polarization to which a given RECEPTOR responds', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'ndim': 1, 'option': 0, 'valueType': 'string'}, 'POL_RESPONSE': {'comment': 'D-matrix i.e. leakage between two receptors', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'ndim': 2, 'option': 0, 'valueType': 'complex'}, 'POSITION': {'comment': 'Position of feed relative to feed reference position', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'Ref': 'ITRF', 'type': 'position'}, 'QuantumUnits': array(['m', 'm', 'm'], dtype='<U16')}, 'maxlen': 0, 'ndim': 1, 'option': 5, 'shape': array([3]), 'valueType': 'double'}, 'RECEPTOR_ANGLE': {'comment': 'The reference angle for polarization', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'QuantumUnits': array(['rad'], dtype='<U16')}, 'maxlen': 0, 'ndim': 1, 'option': 0, 'valueType': 'double'}, 'SPECTRAL_WINDOW_ID': {'comment': 'ID for this spectral window setup', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'TIME': {'comment': 'Midpoint of time for which this set of parameters is accurate', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'Ref': 'TAI', 'type': 'epoch'}, 'QuantumUnits': array(['s'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, '_define_hypercolumn_': {}, '_keywords_': {}, '_private_keywords_': {}} feed_dminfo = { '*1': {'COLUMNS': array(['ANTENNA_ID', 'BEAM_ID', 'BEAM_OFFSET', 'FEED_ID', 'INTERVAL', 'NUM_RECEPTORS', 'POLARIZATION_TYPE', 'POL_RESPONSE', 'POSITION', 'RECEPTOR_ANGLE', 'SPECTRAL_WINDOW_ID', 'TIME'], dtype='<U19'), 'NAME': 'StandardStMan', 'SEQNR': 0, 'SPEC': {'BUCKETSIZE': 3072, 'IndexLength': 126, 'MaxCacheSize': 2, 'PERSCACHESIZE': 2}, 'TYPE': 'StandardStMan'}} field_desc = { 'CODE': {'comment': 'Special characteristics of field, e.g. Bandpass calibrator', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'DELAY_DIR': {'comment': 'Direction of delay center (e.g. RA, DEC)as polynomial in time.', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'Ref': 'J2000', 'type': 'direction'}, 'QuantumUnits': array(['rad', 'rad'], dtype='<U16')}, 'maxlen': 0, 'ndim': 2, 'option': 0, 'valueType': 'double'}, 'FLAG_ROW': {'comment': 'Row Flag', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'boolean'}, 'NAME': {'comment': 'Name of this field', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'NUM_POLY': {'comment': 'Polynomial order of _DIR columns', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'PHASE_DIR': {'comment': 'Direction of phase center (e.g. RA, DEC).', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'Ref': 'J2000', 'type': 'direction'}, 'QuantumUnits': array(['rad', 'rad'], dtype='<U16')}, 'maxlen': 0, 'ndim': 2, 'option': 0, 'valueType': 'double'}, 'REFERENCE_DIR': { 'comment': 'Direction of REFERENCE center (e.g. RA, DEC).as polynomial in time.', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'Ref': 'J2000', 'type': 'direction'}, 'QuantumUnits': array(['rad', 'rad'], dtype='<U16')}, 'maxlen': 0, 'ndim': 2, 'option': 0, 'valueType': 'double'}, 'SOURCE_ID': {'comment': 'Source id', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'TIME': {'comment': 'Time origin for direction and rate', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'Ref': 'TAI', 'type': 'epoch'}, 'QuantumUnits': array(['s'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, '_define_hypercolumn_': {}, '_keywords_': {}, '_private_keywords_': {}} field_dminfo = { '*1': {'COLUMNS': array(['CODE', 'DELAY_DIR', 'FLAG_ROW', 'NAME', 'NUM_POLY', 'PHASE_DIR', 'REFERENCE_DIR', 'SOURCE_ID', 'TIME'], dtype='<U16'), 'NAME': 'StandardStMan', 'SEQNR': 0, 'SPEC': {'BUCKETSIZE': 2052, 'IndexLength': 126, 'MaxCacheSize': 2, 'PERSCACHESIZE': 2}, 'TYPE': 'StandardStMan'}} flag_cmd_desc = { 'APPLIED': {'comment': 'True if flag has been applied to main table', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'boolean'}, 'COMMAND': {'comment': 'Flagging command', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'INTERVAL': {'comment': 'Time interval for which this flag is valid', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'QuantumUnits': array(['s'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, 'LEVEL': {'comment': 'Flag level - revision level ', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'REASON': {'comment': 'Flag reason', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'SEVERITY': {'comment': 'Severity code (0-10) ', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'TIME': {'comment': 'Midpoint of interval for which this flag is valid', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'Ref': 'TAI', 'type': 'epoch'}, 'QuantumUnits': array(['s'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, 'TYPE': {'comment': 'Type of flag (FLAG or UNFLAG)', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, '_define_hypercolumn_': {}, '_keywords_': {}, '_private_keywords_': {}} flag_cmd_dminfo = { '*1': {'COLUMNS': array(['APPLIED', 'COMMAND', 'INTERVAL', 'LEVEL', 'REASON', 'SEVERITY', 'TIME', 'TYPE'], dtype='<U16'), 'NAME': 'StandardStMan', 'SEQNR': 0, 'SPEC': {'BUCKETSIZE': 1924, 'IndexLength': 118, 'MaxCacheSize': 2, 'PERSCACHESIZE': 2}, 'TYPE': 'StandardStMan'}} history_desc = { 'APPLICATION': {'comment': 'Application name', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'APP_PARAMS': {'comment': 'Application parameters', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'ndim': 1, 'option': 0, 'valueType': 'string'}, 'CLI_COMMAND': {'comment': 'CLI command sequence', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'ndim': 1, 'option': 0, 'valueType': 'string'}, 'MESSAGE': {'comment': 'Log message', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'OBJECT_ID': {'comment': 'Originating ObjectID', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'OBSERVATION_ID': {'comment': 'Observation id (index in OBSERVATION table)', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'ORIGIN': {'comment': '(Source code) origin from which message originated', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'PRIORITY': {'comment': 'Message priority', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'TIME': {'comment': 'Timestamp of message', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'Ref': 'TAI', 'type': 'epoch'}, 'QuantumUnits': array(['s'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, '_define_hypercolumn_': {}, '_keywords_': {}, '_private_keywords_': {}} history_dminfo = { '*1': {'COLUMNS': array(['APPLICATION', 'APP_PARAMS', 'CLI_COMMAND', 'MESSAGE', 'OBJECT_ID', 'OBSERVATION_ID', 'ORIGIN', 'PRIORITY', 'TIME'], dtype='<U16'), 'NAME': 'StandardStMan', 'SEQNR': 0, 'SPEC': {'BUCKETSIZE': 2816, 'IndexLength': 126, 'MaxCacheSize': 2, 'PERSCACHESIZE': 2}, 'TYPE': 'StandardStMan'}} observation_desc = { 'FLAG_ROW': {'comment': 'Row flag', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'boolean'}, 'LOG': {'comment': 'Observing log', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'ndim': 1, 'option': 0, 'valueType': 'string'}, 'OBSERVER': {'comment': 'Name of observer(s)', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'PROJECT': {'comment': 'Project identification string', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'RELEASE_DATE': {'comment': 'Release date when data becomes public', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'Ref': 'TAI', 'type': 'epoch'}, 'QuantumUnits': array(['s'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, 'SCHEDULE': {'comment': 'Observing schedule', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'ndim': 1, 'option': 0, 'valueType': 'string'}, 'SCHEDULE_TYPE': {'comment': 'Observing schedule type', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'TELESCOPE_NAME': {'comment': 'Telescope Name (e.g. WSRT, VLBA)', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'TIME_RANGE': {'comment': 'Start and end of observation', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'Ref': 'TAI', 'type': 'epoch'}, 'QuantumUnits': array(['s'], dtype='<U16')}, 'maxlen': 0, 'ndim': 1, 'option': 5, 'shape': array([2]), 'valueType': 'double'}, '_define_hypercolumn_': {}, '_keywords_': {}, '_private_keywords_': {}} observation_dminfo = { '*1': {'COLUMNS': array(['FLAG_ROW', 'LOG', 'OBSERVER', 'PROJECT', 'RELEASE_DATE', 'SCHEDULE', 'SCHEDULE_TYPE', 'TELESCOPE_NAME', 'TIME_RANGE'], dtype='<U16'), 'NAME': 'StandardStMan', 'SEQNR': 0, 'SPEC': {'BUCKETSIZE': 3076, 'IndexLength': 126, 'MaxCacheSize': 2, 'PERSCACHESIZE': 2}, 'TYPE': 'StandardStMan'}} pointing_desc = { 'ANTENNA_ID': {'comment': 'Antenna Id', 'dataManagerGroup': 'SSMPointing', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'DIRECTION': {'comment': 'Antenna pointing direction as polynomial in time', 'dataManagerGroup': 'ISMPointing', 'dataManagerType': 'IncrementalStMan', 'keywords': {'MEASINFO': {'Ref': 'J2000', 'type': 'direction'}, 'QuantumUnits': array(['rad', 'rad'], dtype='<U16')}, 'maxlen': 0, 'ndim': 2, 'option': 0, 'valueType': 'double'}, 'INTERVAL': {'comment': 'Time interval', 'dataManagerGroup': 'ISMPointing', 'dataManagerType': 'IncrementalStMan', 'keywords': {'QuantumUnits': array(['s'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, 'NAME': {'comment': 'Pointing position name', 'dataManagerGroup': 'ISMPointing', 'dataManagerType': 'IncrementalStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'NUM_POLY': {'comment': 'Series order', 'dataManagerGroup': 'ISMPointing', 'dataManagerType': 'IncrementalStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'TARGET': {'comment': 'target direction as polynomial in time', 'dataManagerGroup': 'ISMPointing', 'dataManagerType': 'IncrementalStMan', 'keywords': {'MEASINFO': {'Ref': 'J2000', 'type': 'direction'}, 'QuantumUnits': array(['rad', 'rad'], dtype='<U16')}, 'maxlen': 0, 'ndim': -1, 'option': 0, 'valueType': 'double'}, 'TIME': {'comment': 'Time interval midpoint', 'dataManagerGroup': 'ISMPointing', 'dataManagerType': 'IncrementalStMan', 'keywords': {'MEASINFO': {'Ref': 'TAI', 'type': 'epoch'}, 'QuantumUnits': array(['s'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, 'TIME_ORIGIN': {'comment': 'Time origin for direction', 'dataManagerGroup': 'ISMPointing', 'dataManagerType': 'IncrementalStMan', 'keywords': {'MEASINFO': {'Ref': 'TAI', 'type': 'epoch'}, 'QuantumUnits': array(['s'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, 'TRACKING': {'comment': 'Tracking flag - True if on position', 'dataManagerGroup': 'ISMPointing', 'dataManagerType': 'IncrementalStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'boolean'}, '_define_hypercolumn_': {}, '_keywords_': {}, '_private_keywords_': {}} pointing_dminfo = { '*1': {'COLUMNS': array(['DIRECTION', 'INTERVAL', 'NAME', 'NUM_POLY', 'TARGET', 'TIME', 'TIME_ORIGIN', 'TRACKING'], dtype='<U16'), 'NAME': 'ISMPointing', 'SEQNR': 0, 'SPEC': {'BUCKETSIZE': 38436, 'MaxCacheSize': 1, 'PERSCACHESIZE': 1}, 'TYPE': 'IncrementalStMan'}, '*2': {'COLUMNS': array(['ANTENNA_ID'], dtype='<U16'), 'NAME': 'SSMPointing', 'SEQNR': 1, 'SPEC': {'BUCKETSIZE': 32768, 'IndexLength': 118, 'MaxCacheSize': 2, 'PERSCACHESIZE': 2}, 'TYPE': 'StandardStMan'}} polarization_desc = { 'CORR_PRODUCT': {'comment': 'Indices describing receptors of feed going into correlation', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'ndim': 2, 'option': 0, 'valueType': 'int'}, 'CORR_TYPE': {'comment': 'The polarization type for each correlation product, as a Stokes enum.', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'ndim': 1, 'option': 0, 'valueType': 'int'}, 'FLAG_ROW': {'comment': 'Row flag', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'boolean'}, 'NUM_CORR': {'comment': 'Number of correlation products', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, '_define_hypercolumn_': {}, '_keywords_': {}, '_private_keywords_': {}} polarization_dminfo = { '*1': {'COLUMNS': array(['CORR_PRODUCT', 'CORR_TYPE', 'FLAG_ROW', 'NUM_CORR'], dtype='<U16'), 'NAME': 'StandardStMan', 'SEQNR': 0, 'SPEC': {'BUCKETSIZE': 644, 'IndexLength': 126, 'MaxCacheSize': 2, 'PERSCACHESIZE': 2}, 'TYPE': 'StandardStMan'}} processor_desc = { 'FLAG_ROW': {'comment': 'Row flag', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'boolean'}, 'MODE_ID': {'comment': 'Processor mode id', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'SUB_TYPE': {'comment': 'Processor sub type', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'TYPE': {'comment': 'Processor type', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'TYPE_ID': {'comment': 'Processor type id', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, '_define_hypercolumn_': {}, '_keywords_': {}, '_private_keywords_': {}} processor_dminfo = { '*1': {'COLUMNS': array(['FLAG_ROW', 'MODE_ID', 'SUB_TYPE', 'TYPE', 'TYPE_ID'], dtype='<U16'), 'NAME': 'StandardStMan', 'SEQNR': 0, 'SPEC': {'BUCKETSIZE': 1028, 'IndexLength': 118, 'MaxCacheSize': 2, 'PERSCACHESIZE': 2}, 'TYPE': 'StandardStMan'}} source_desc = { 'CALIBRATION_GROUP': {'comment': 'Number of grouping for calibration purpose.', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'CODE': {'comment': 'Special characteristics of source, e.g. Bandpass calibrator', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'DIRECTION': {'comment': 'Direction (e.g. RA, DEC).', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'Ref': 'J2000', 'type': 'direction'}, 'QuantumUnits': array(['rad', 'rad'], dtype='<U16')}, 'maxlen': 0, 'ndim': 1, 'option': 5, 'shape': array([2]), 'valueType': 'double'}, 'INTERVAL': {'comment': 'Interval of time for which this set of parameters is accurate', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'QuantumUnits': array(['s'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, 'NAME': {'comment': 'Name of source as given during observations', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'NUM_LINES': {'comment': 'Number of spectral lines', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'POSITION': {'comment': 'Position (e.g. for solar system objects', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'Ref': 'ITRF', 'type': 'position'}, 'QuantumUnits': array(['m', 'm', 'm'], dtype='<U16')}, 'maxlen': 0, 'ndim': -1, 'option': 0, 'valueType': 'double'}, 'PROPER_MOTION': {'comment': 'Proper motion', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'QuantumUnits': array(['rad/s'], dtype='<U16')}, 'maxlen': 0, 'ndim': 1, 'option': 5, 'shape': array([2]), 'valueType': 'double'}, 'REST_FREQUENCY': {'comment': 'Line rest frequency', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'Ref': 'LSRK', 'type': 'frequency'}, 'QuantumUnits': array(['Hz'], dtype='<U16')}, 'maxlen': 0, 'ndim': -1, 'option': 0, 'valueType': 'double'}, 'SOURCE_ID': {'comment': 'Source id', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'SOURCE_MODEL': {'comment': 'Component Source Model', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'record'}, 'SPECTRAL_WINDOW_ID': {'comment': 'ID for this spectral window setup', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'SYSVEL': {'comment': 'Systemic velocity at reference', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'Ref': 'LSRK', 'type': 'radialvelocity'}, 'QuantumUnits': array(['m/s'], dtype='<U16')}, 'maxlen': 0, 'ndim': -1, 'option': 0, 'valueType': 'double'}, 'TIME': {'comment': 'Midpoint of time for which this set of parameters is accurate.', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'Ref': 'TAI', 'type': 'epoch'}, 'QuantumUnits': array(['s'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, 'TRANSITION': {'comment': 'Line Transition name', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'ndim': -1, 'option': 0, 'valueType': 'string'}, '_define_hypercolumn_': {}, '_keywords_': {}, '_private_keywords_': {}} source_dminfo = { '*1': {'COLUMNS': array(['CALIBRATION_GROUP', 'CODE', 'DIRECTION', 'INTERVAL', 'NAME', 'NUM_LINES', 'POSITION', 'PROPER_MOTION', 'REST_FREQUENCY', 'SOURCE_ID', 'SOURCE_MODEL', 'SPECTRAL_WINDOW_ID', 'SYSVEL', 'TIME', 'TRANSITION'], dtype='<U19'), 'NAME': 'StandardStMan', 'SEQNR': 0, 'SPEC': {'BUCKETSIZE': 4224, 'IndexLength': 126, 'MaxCacheSize': 2, 'PERSCACHESIZE': 2}, 'TYPE': 'StandardStMan'}} special_window_desc = { 'CHAN_FREQ': {'comment': 'Center frequencies for each channel in the data matrix', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'TabRefCodes': array([0, 1, 2, 3, 4, 5, 6, 7, 8, 64], dtype=uint64), 'TabRefTypes': array(['REST', 'LSRK', 'LSRD', 'BARY', 'GEO', 'TOPO', 'GALACTO', 'LGROUP', 'CMB', 'Undefined'], dtype='<U16'), 'VarRefCol': 'MEAS_FREQ_REF', 'type': 'frequency'}, 'QuantumUnits': array(['Hz'], dtype='<U16')}, 'maxlen': 0, 'ndim': 1, 'option': 0, 'valueType': 'double'}, 'CHAN_WIDTH': {'comment': 'Channel width for each channel', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'QuantumUnits': array(['Hz'], dtype='<U16')}, 'maxlen': 0, 'ndim': 1, 'option': 0, 'valueType': 'double'}, 'EFFECTIVE_BW': {'comment': 'Effective noise bandwidth of each channel', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'QuantumUnits': array(['Hz'], dtype='<U16')}, 'maxlen': 0, 'ndim': 1, 'option': 0, 'valueType': 'double'}, 'FLAG_ROW': {'comment': 'Row flag', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'boolean'}, 'FREQ_GROUP': {'comment': 'Frequency group', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'FREQ_GROUP_NAME': {'comment': 'Frequency group name', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'IF_CONV_CHAIN': {'comment': 'The IF conversion chain number', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'MEAS_FREQ_REF': {'comment': 'Frequency Measure reference', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'NAME': {'comment': 'Spectral window name', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'NET_SIDEBAND': {'comment': 'Net sideband', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'NUM_CHAN': {'comment': 'Number of spectral channels', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, 'REF_FREQUENCY': { 'comment': 'The reference frequency', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'MEASINFO': {'TabRefCodes': array([0, 1, 2, 3, 4, 5, 6, 7, 8, 64], dtype=uint64), 'TabRefTypes': array(['REST', 'LSRK', 'LSRD', 'BARY', 'GEO', 'TOPO', 'GALACTO', 'LGROUP', 'CMB', 'Undefined'], dtype='<U16'), 'VarRefCol': 'MEAS_FREQ_REF', 'type': 'frequency'}, 'QuantumUnits': array(['Hz'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, 'RESOLUTION': {'comment': 'The effective noise bandwidth for each channel', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'QuantumUnits': array(['Hz'], dtype='<U16')}, 'maxlen': 0, 'ndim': 1, 'option': 0, 'valueType': 'double'}, 'TOTAL_BANDWIDTH': { 'comment': 'The total bandwidth for this window', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'QuantumUnits': array(['Hz'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, '_define_hypercolumn_': {}, '_keywords_': {}, '_private_keywords_': {}} special_window_dminfo = { '*1': {'COLUMNS': array(['CHAN_FREQ', 'CHAN_WIDTH', 'EFFECTIVE_BW', 'FLAG_ROW', 'FREQ_GROUP', 'FREQ_GROUP_NAME', 'IF_CONV_CHAIN', 'MEAS_FREQ_REF', 'NAME', 'NET_SIDEBAND', 'NUM_CHAN', 'REF_FREQUENCY', 'RESOLUTION', 'TOTAL_BANDWIDTH'], dtype='<U16'), 'NAME': 'StandardStMan', 'SEQNR': 0, 'SPEC': {'BUCKETSIZE': 2948, 'IndexLength': 126, 'MaxCacheSize': 2, 'PERSCACHESIZE': 2}, 'TYPE': 'StandardStMan'}} state_desc = { 'CAL': {'comment': 'Noise calibration temperature', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'QuantumUnits': array(['K'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, 'FLAG_ROW': {'comment': 'Row flag', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'boolean'}, 'LOAD': {'comment': 'Load temperature', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {'QuantumUnits': array(['K'], dtype='<U16')}, 'maxlen': 0, 'option': 0, 'valueType': 'double'}, 'OBS_MODE': {'comment': 'Observing mode, e.g., OFF_SPECTRUM', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'string'}, 'REF': {'comment': 'True for a reference observation', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'boolean'}, 'SIG': {'comment': 'True for a source observation', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'boolean'}, 'SUB_SCAN': {'comment': 'Sub scan number, relative to scan number', 'dataManagerGroup': 'StandardStMan', 'dataManagerType': 'StandardStMan', 'keywords': {}, 'maxlen': 0, 'option': 0, 'valueType': 'int'}, '_define_hypercolumn_': {}, '_keywords_': {}, '_private_keywords_': {}} state_dminfo = { '*1': {'COLUMNS': array(['CAL', 'FLAG_ROW', 'LOAD', 'OBS_MODE', 'REF', 'SIG', 'SUB_SCAN'], dtype='<U16'), 'NAME': 'StandardStMan', 'SEQNR': 0, 'SPEC': {'BUCKETSIZE': 1036, 'IndexLength': 118, 'MaxCacheSize': 2, 'PERSCACHESIZE': 2}, 'TYPE': 'StandardStMan'}}