Open in Colab: https://colab.research.google.com/github/casangi/cngi_prototype/blob/master/docs/verification.ipynb


CASA Mapping

CASA today has a complex interface that intertwines many use cases and target audiences, including interactive users and automated pipelines. The primary interface for most is the CASA task list. CASA tasks themselves range from simple functions to complex applications and are meant for a wide variety of purposes.

Here we map the current CASA task list to where the equivalent functionality will (eventually) live in the next generation software. In some cases this is not a one to one mapping, as tasks may be split in to multiple functions, or multiple tasks may be handled by a single function.

The future design thinking is to separate functionality into CNGI, ngCASA, and Application layers. The primary focus of this demonstration package is the CNGI layer, containing core mathematics and operations directly on datastructures themselves. Some preliminary ngCASA level design and prototyping work exists to build confidence that the CNGI level will suffice for next generation science performance. Very little application layer work has been done to date, but this will (eventually) be the layer that most users interact with, and tailored to specific use cases. Refer to the Introduction section for more information.

Tasks marked with N/A or “direct on xarray dataset” are no longer needed due to fundamental changes in data storage and access in CNGI.

  1. accor - ngCASA TBD

  2. apparentsens - ngCASA TBD

  3. applycal - ngCASA TBD

  4. asdmsummary - cngi.conversion TBD

  5. bandpass - ngCASA TBD

  6. blcal - ngCASA TBD

  7. browsetable - ng Application TBD

  8. calstat - ngCASA TBD

  9. clearcal - ngCASA TBD

  10. clearstat - N/A

  11. concat - cngi.vis.join_vis

  12. conjugatevis - cngi direct on xarray dataset

  13. cvel - cngi.vis.regrid TBD

  14. cvel2 - cngi.vis.regrid TBD

  15. deconvolve - ngCASA TBD

  16. delmod - N/A

  17. exportasdm - cngi.conversion.save_asdm TBD

  18. exportfits - cngi.conversion.save_image TBD

  19. exportuvfits - cngi.conversion.save_ms TBD

  20. feather - ngCASA TBD

  21. fixplanets - ngCASA TBD

  22. fixvis - cngi.vis.phase_shift TBD

  23. flagcmd - ngCASA TBD

  24. flagdata - ngCASA TBD

  25. flagmanager - ngCASA TBD

  26. fluxscale - ngCASA TBD

  27. fringefit - ngCASA TBD

  28. ft - ngCASA TBD

  29. gaincal - ngCASA TBD

  30. gencal - ngCASA TBD

  31. hanningsmooth - cngi.vis.chan_smooth

  32. imcollapse - cngi direct on xarray dataset

  33. imcontsub - cngi.image.cont_sub

  34. imdev - cngi.image.statistics + direct on xarray dataset

  35. imfit - cngi.image.fit_gaussian

  36. imhead - cngi direct on xarray dataset

  37. imhistory - cngi stored in xarray dataset attributes

  38. immath - cngi direct on xarray dataset

  39. immoments - cngi.image.moments

  40. impbcor - ngCASA TBD

  41. importasdm - cngi.conversion.convert_asdm

  42. importatca - cngi.conversion TBD

  43. importfits - cngi.conversion.convert_image

  44. importfitsidi - cngi.conversion TBD

  45. importgmrt - cngi.conversion TBD

  46. importmiriad - cngi.conversion TBD

  47. importuvfits - cngi.conversion.convert_ms

  48. importvla - cngi.conversion TBD

  49. impv - cngi.image.posvel TBD

  50. imrebin - cngi.image.rebin

  51. imreframe - cngi.image.reframe

  52. imregrid - cngi.image.regrid TBD

  53. imsmooth - cngi.image.smooth

  54. imstat - cngi.image.statistics

  55. imsubimage - cngi direct on xarray dataset

  56. imtrans - cngi direct on xarray dataset

  57. imval - cngi direct on xarray dataset

  58. imview - ng Application TBD

  59. initweights - ngCASA TBD

  60. listcal - cngi direct on xarray dataset

  61. listfits - TBD

  62. listhistory - cngi stored in xarray dataset attributes

  63. listobs - cngi direct on xarray dataset

  64. listpartition - N/A

  65. listsdm - cngi direct on xarray dataset

  66. listvis - cngi direct on xarray dataset

  67. makemask - cngi.image.mask

  68. mstransform - cngi.vis.join_vis, cngi.vis.chan_average, cngi.vis.regrid TBD, cngi.vis.time_average

  69. msuvbin - ngCASA TBD

  70. msview - ng Application TBD

  71. nrobeamaverage - ngCASA TBD

  72. partition - N/A

  73. plotants - ng Application TBD

  74. plotbandpass - ng Application TBD

  75. plotcal - ng Application TBD

  76. plotms - ng Application TBD

  77. plotprofilemap - ng Application TBD

  78. plotweather - ng Application TBD

  79. polcal - ngCASA TBD

  80. polfromgain - ngCASA TBD

  81. predictcomp - ngCASA TBD

  82. rerefant - ngCASA TBD

  83. rmfit - cngi.image.rmfit TBD

  84. rmtables - N/A

  85. sdbaseline - cngi.vis.sd_fit TBD + direct on xarray dataset

  86. sdcal - ngCASA TBD

  87. sdfit - cngi.vis.sdfit TBD

  88. sdfixscan - cngi.image.sd_fix_scan TBD

  89. sdgaincal - ngCASA TBD

  90. sdimaging - ngCASA TBD

  91. sdintimaging - ng Application TBD

  92. sdpolaverage - cngi.vis.sd_pol_average TBD

  93. sdsidebandsplit - ngCASA TBD

  94. sdsmooth - cngi.vis.chan_smooth

  95. sdtimeaverage - cngi.vis.time_average

  96. setjy - ngCASA TBD

  97. simalma - ng Application TBD

  98. simanalyze - ng Application TBD

  99. simobserve - ng Application TBD

  100. slsearch - cngi.external TBD

  101. smoothcal - ngCASA TBD

  102. specfit - cngi.image.spec_fit

  103. specflux - cngi.image.spec_flux TBD

  104. specsmooth - cngi.image.spec_smooth TBD

  105. splattotable - cngi.external TBD

  106. split - cngi.vis.chan_average, cngi.vis.time_average + cngi.vis.split_dataset

  107. spxfit - cngi.image.spx_fit TBD

  108. statwt - ngCASA TBD

  109. tclean - ng Application TBD

  110. tsdimaging - ng Application TBD

  111. uvcontsub - cngi.uv_cont_fit

  112. uvmodelfit - cngi.uv_model_fit TBD

  113. uvsub - cngi direct on xarray dataset

  114. viewer - CARTA

  115. virtualconcat - N/A

  116. vishead - cngi direct on xarray dataset

  117. visstat - cngi direct on xarray dataset

  118. widebandpbcor - ngCASA TBD

  119. wvrgcal - ngCASA TBD

In the following sections we demonstrate how current CASA tasks may be satisfied in the new mapping to CNGI capabilities.

Note: This is a concept demonstration only and not meant to verify scientific accuracy

This section like most others may be run by readers in Google Colab using the provided link in the header. The first step in exdecution is to install necessary components and generate data to be used in the demonstration comparison to CASA6

[1]:
import os, warnings
warnings.simplefilter("ignore", category=RuntimeWarning)  # suppress warnings about nan-slices
print("installing casa6 and cngi (takes a few minutes)...")
os.system("apt-get install libgfortran3")
os.system("pip install casatasks==6.3.0.48")
os.system("pip install casadata")
os.system("pip install cngi-prototype==0.0.92")

print("downloading MeasurementSet from CASAguide First Look at Imaging...")
!gdown -q --id 1N9QSs2Hbhi-BrEHx5PA54WigXt8GGgx1
!tar -xzf sis14_twhya_calibrated_flagged.ms.tar.gz
!mv sis14_twhya_calibrated_flagged.ms twhya.ms
print('converting ms...')
installing casa6 and cngi (takes a few minutes)...
downloading MeasurementSet from CASAguide First Look at Imaging...
converting ms...
[2]:
from casatasks import tclean
from cngi.conversion import convert_ms, convert_image
from cngi.image import implot
from cngi.vis import visplot
import numpy as np
import matplotlib.pyplot as plt

mxds = convert_ms('twhya.ms')

print("running tclean to generate an image")
tclean(vis='twhya.ms', imagename='twhya', field='5', spw='',
       specmode='cube', deconvolver='hogbom', nterms=1, imsize=[250,250], gridder='standard', cell=['0.1arcsec'],
       nchan=10, weighting='natural', threshold='0mJy', niter=100, interactive=False, savemodel='modelcolumn',
       usemask='auto-multithresh')

image_xds = convert_image('twhya.image')
mxds = convert_ms('twhya.ms')  # reconvert to get MODEL_DATA col
Completed ddi 0  process time 22.91 s
Completed subtables  process time 1.06 s

running tclean to generate an image
converting Image...
processed image in 1.3743491 seconds
Completed ddi 0  process time 26.86 s
Completed subtables  process time 1.10 s

cngi.vis Module

Demonstration of CASA functions to be handled by the CNGI visibility module.

Note: this is a demonstration of mechanics only and is not intended for science


listobs

Note the mechanism for retrieving data from the MeasurementSet is fundamentally different, but the data itself is the same

[3]:
# CASA 6
from casatasks import listobs

listobs(vis='twhya.ms', listfile='obslist.txt', verbose=False, overwrite=True)
!cat obslist.txt
================================================================================
           MeasurementSet Name:  /content/twhya.ms      MS Version 2
================================================================================
   Observer: cqi     Project: uid://A002/X327408/X6f
Observation: ALMA(26 antennas)
Data records: 80563       Total elapsed time = 5647.68 seconds
   Observed from   19-Nov-2012/07:36:57.0   to   19-Nov-2012/09:11:04.7 (UTC)

Fields: 5
  ID   Code Name                RA               Decl           Epoch   SrcId      nRows
  0    none J0522-364           05:22:57.984648 -36.27.30.85128 J2000   0           4200
  2    none Ceres               06:10:15.950590 +23.22.06.90668 J2000   2           3800
  3    none J1037-295           10:37:16.079736 -29.34.02.81316 J2000   3          16000
  5    none TW Hya              11:01:51.796000 -34.42.17.36600 J2000   4          53161
  6    none 3c279               12:56:11.166576 -05.47.21.52464 J2000   5           3402
Spectral Windows:  (1 unique spectral windows and 1 unique polarization setups)
  SpwID  Name                           #Chans   Frame   Ch0(MHz)  ChanWid(kHz)  TotBW(kHz) CtrFreq(MHz) BBC Num  Corrs
  0      ALMA_RB_07#BB_2#SW-01#FULL_RES    384   TOPO  372533.086       610.352    234375.0 372649.9688        2  XX  YY
Antennas: 21 'name'='station'
   ID=   1-4: 'DA42'='A050', 'DA44'='A068', 'DA45'='A070', 'DA46'='A067',
   ID=   5-9: 'DA48'='A046', 'DA49'='A029', 'DA50'='A045', 'DV02'='A077',
   ID= 10-15: 'DV05'='A082', 'DV06'='A037', 'DV08'='A021', 'DV10'='A071',
   ID= 16-19: 'DV13'='A072', 'DV15'='A074', 'DV16'='A069', 'DV17'='A138',
   ID= 20-24: 'DV18'='A053', 'DV19'='A008', 'DV20'='A020', 'DV22'='A011',
   ID= 25-25: 'DV23'='A007'
[4]:
# CNGI
#print('Observation ', mxds.OBSERVATION.compute().data_vars)
#print('Field ', mxds.FIELD.compute().data_vars)
#print('Spectral Window ', mxds.SPECTRAL_WINDOW.compute().data_vars)
#print('Source ', mxds.SOURCE.compute().data_vars)
#print('Antenna ', mxds.ANTENNA.compute().data_vars)
print(mxds.dims)
print(mxds.coords)
Frozen(SortedKeysDict({'antenna_ids': 26, 'field_ids': 7, 'feed_ids': 26, 'observation_ids': 1, 'polarization_ids': 1, 'source_ids': 5, 'spw_ids': 1, 'state_ids': 20}))
Coordinates:
  * antenna_ids       (antenna_ids) int64 0 1 2 3 4 5 6 ... 19 20 21 22 23 24 25
    antennas          (antenna_ids) <U16 'DA41' 'DA42' 'DA44' ... 'DV22' 'DV23'
  * field_ids         (field_ids) int64 0 1 2 3 4 5 6
    fields            (field_ids) <U9 'J0522-364' 'J0539+145' ... '3c279'
  * feed_ids          (feed_ids) int64 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0
  * observation_ids   (observation_ids) int64 0
    observations      (observation_ids) <U23 'uid://A002/X327408/X6f'
  * polarization_ids  (polarization_ids) int64 0
  * source_ids        (source_ids) int64 0 1 2 3 4
    sources           (source_ids) <U9 'J0522-364' 'Ceres' ... 'TW Hya' '3c279'
  * spw_ids           (spw_ids) int64 0
  * state_ids         (state_ids) int64 0 1 2 3 4 5 6 7 ... 13 14 15 16 17 18 19

listvis

Note the mechanism for retrieving data from the MeasurementSet is fundamentally different, but the data itself is the same

[5]:
# CASA 6
from casatasks import listvis

os.system("rm -fr vislist.txt")
listvis(vis='twhya.ms', field="J1037-295", timerange='<07:53:00', antenna='DA46',
        spw='*:30~40', datacolumn='data', listfile='vislist.txt')
!tail -n 18 vislist.txt
Units of columns are: Date/Time(YYMMDD/HH:MM:SS UT), UVDist(wavelength), Phase(deg), UVW(m)
FIELD: 3
SPW: 0
Date/Time:                           XX:                  YY:
2012/11/19/      Intrf UVDist  Chn     Amp     Phs  Wt F    Amp     Phs  Wt F         U         V         W
------------|---------|------|----|---------------------|--------------------|---------|---------|---------|
  07:52:57.2 DA46-DV23  65292   30: 14.690   -18.7   9    6.279    40.7  17       44.17     28.46     43.89
  07:52:57.2 DA46-DV23  65292   31:  1.951    62.0   9    1.091   132.5  17       44.17     28.46     43.89
  07:52:57.2 DA46-DV23  65292   32: 12.303    -5.4   9    1.837    83.7  17       44.17     28.46     43.89
  07:52:57.2 DA46-DV23  65292   33: 32.372   -63.7   9    9.889   -18.0  17       44.17     28.46     43.89
  07:52:57.2 DA46-DV23  65292   34: 13.741    61.8   9   19.342   -45.3  17       44.17     28.46     43.89
  07:52:57.2 DA46-DV23  65292   35: 14.456   109.7   9   10.931   -75.3  17       44.17     28.46     43.89
  07:52:57.2 DA46-DV23  65292   36: 10.487     4.9   9   11.387   -79.9  17       44.17     28.46     43.89
  07:52:57.2 DA46-DV23  65292   37:  9.204  -136.4   9    5.963  -166.3  17       44.17     28.46     43.89
  07:52:57.2 DA46-DV23  65292   38: 33.276     1.9   9    4.406    67.3  17       44.17     28.46     43.89
  07:52:57.2 DA46-DV23  65292   39: 16.079   108.8   9    8.067   172.0  17       44.17     28.46     43.89
  07:52:57.2 DA46-DV23  65292   40: 16.795   -20.8   9    9.997    96.8  17       44.17     28.46     43.89
------------|---------|------|----|---------------------|--------------------|---------|---------|---------|
[6]:
# CNGI
field_id = mxds.field_ids[np.where(mxds.fields == "J1037-295")][0]
selection = mxds.xds0.isel(chan=range(30,40)).sel(time='2012-11-19T07:52').where(mxds.xds0.FIELD_ID == field_id, drop=True).compute()
print(selection)
<xarray.Dataset>
Dimensions:         (baseline: 190, chan: 10, pol: 2, pol_id: 1, spw_id: 1, time: 3, uvw_index: 3)
Coordinates:
  * time            (time) datetime64[ns] 2012-11-19T07:52:45.072000504 ... 2...
  * baseline        (baseline) int64 0 1 2 3 4 5 6 ... 201 202 203 207 208 209
  * chan            (chan) float64 3.726e+11 3.726e+11 ... 3.726e+11 3.726e+11
    chan_width      (chan) float64 6.104e+05 6.104e+05 ... 6.104e+05 6.104e+05
    effective_bw    (chan) float64 6.104e+05 6.104e+05 ... 6.104e+05 6.104e+05
  * pol             (pol) int64 9 12
  * pol_id          (pol_id) int64 0
    resolution      (chan) float64 6.104e+05 6.104e+05 ... 6.104e+05 6.104e+05
  * spw_id          (spw_id) int64 0
    field_ids       int64 3
    fields          <U9 'J1037-295'
Dimensions without coordinates: uvw_index
Data variables: (12/18)
    ANTENNA1        (baseline, time) float64 1.0 1.0 1.0 1.0 ... 24.0 24.0 24.0
    ANTENNA2        (baseline, time) float64 2.0 2.0 2.0 3.0 ... 25.0 25.0 25.0
    ARRAY_ID        (time, baseline) float64 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0
    DATA            (time, baseline, chan, pol) complex128 (-2.60023474693298...
    DATA_WEIGHT     (time, baseline, chan, pol) float64 12.39 21.67 ... 14.35
    EXPOSURE        (time, baseline) float64 6.048 6.048 6.048 ... 6.048 6.048
    ...              ...
    OBSERVATION_ID  (time, baseline) float64 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0
    PROCESSOR_ID    (time, baseline) float64 2.0 2.0 2.0 2.0 ... 2.0 2.0 2.0 2.0
    SCAN_NUMBER     (time, baseline) float64 10.0 10.0 10.0 ... 10.0 10.0 10.0
    STATE_ID        (time, baseline) float64 8.0 8.0 8.0 8.0 ... 8.0 8.0 8.0 8.0
    TIME_CENTROID   (time, baseline) float64 4.86e+09 4.86e+09 ... 4.86e+09
    UVW             (time, baseline, uvw_index) float64 115.4 -56.68 ... 22.89
Attributes: (12/14)
    assoc_nature:     ['', '', '', '', '', '', '', '', '', '', '', '', '', ''...
    bbc_no:           2
    corr_product:     [[0, 0], [1, 1]]
    data_groups:      [{'0': {'data': 'DATA', 'flag': 'FLAG', 'id': '0', 'uvw...
    freq_group:       0
    freq_group_name:
    ...               ...
    name:             ALMA_RB_07#BB_2#SW-01#FULL_RES
    net_sideband:     2
    num_chan:         384
    num_corr:         2
    ref_frequency:    372533086425.9812
    total_bandwidth:  234375000.0

concat

[7]:
# CASA 6
from casatasks import concat, split

# first we need to create two ms's, then concat them
split('twhya.ms', 'ms1.ms', field='J0522-364', datacolumn='DATA')
split('twhya.ms', 'ms2.ms', field='Ceres', datacolumn='DATA')
concat(['ms1.ms', 'ms2.ms'], 'concatms.ms')
listobs(vis='concatms.ms', listfile='obslist.txt', verbose=False, overwrite=True)
!cat obslist.txt

================================================================================
           MeasurementSet Name:  /content/concatms.ms      MS Version 2
================================================================================
   Observer: cqi     Project: uid://A002/X327408/X6f
Observation: ALMA(26 antennas)
Data records: 8000       Total elapsed time = 604.272 seconds
   Observed from   19-Nov-2012/07:36:57.0   to   19-Nov-2012/07:47:01.2 (UTC)

Fields: 2
  ID   Code Name                RA               Decl           Epoch   SrcId      nRows
  0    none J0522-364           05:22:57.984648 -36.27.30.85128 J2000   0           4200
  1    none Ceres               06:10:15.950590 +23.22.06.90668 J2000   1           3800
Spectral Windows:  (1 unique spectral windows and 1 unique polarization setups)
  SpwID  Name                           #Chans   Frame   Ch0(MHz)  ChanWid(kHz)  TotBW(kHz) CtrFreq(MHz) BBC Num  Corrs
  0      ALMA_RB_07#BB_2#SW-01#FULL_RES    384   TOPO  372533.086       610.352    234375.0 372649.9688        2  XX  YY
Antennas: 21 'name'='station'
   ID=   1-4: 'DA42'='A050', 'DA44'='A068', 'DA45'='A070', 'DA46'='A067',
   ID=   5-9: 'DA48'='A046', 'DA49'='A029', 'DA50'='A045', 'DV02'='A077',
   ID= 10-15: 'DV05'='A082', 'DV06'='A037', 'DV08'='A021', 'DV10'='A071',
   ID= 16-19: 'DV13'='A072', 'DV15'='A074', 'DV16'='A069', 'DV17'='A138',
   ID= 20-24: 'DV18'='A053', 'DV19'='A008', 'DV20'='A020', 'DV22'='A011',
   ID= 25-25: 'DV23'='A007'
[8]:
# CNGI
from cngi.vis import join_dataset

mxds1 = convert_ms('ms1.ms')
mxds2 = convert_ms('ms2.ms')
jmxds = join_dataset(mxds1, mxds2)

print(jmxds.dims)
print(jmxds.coords)
Completed ddi 0  process time 1.64 s
Completed subtables  process time 1.06 s

Completed ddi 0  process time 1.61 s
Completed subtables  process time 1.07 s

Warning: reference value -1 in subtable WEATHER does not exist in ANTENNA.antenna_id!
Frozen(SortedKeysDict({'antenna_ids': 26, 'field_ids': 2, 'feed_ids': 26, 'observation_ids': 1, 'polarization_ids': 1, 'source_ids': 2, 'spw_ids': 1, 'state_ids': 20}))
Coordinates:
  * antenna_ids       (antenna_ids) int64 0 1 2 3 4 5 6 ... 19 20 21 22 23 24 25
    antennas          (antenna_ids) <U16 'DA41' 'DA42' 'DA44' ... 'DV22' 'DV23'
  * field_ids         (field_ids) int64 0 1
    fields            (field_ids) object 'J0522-364' 'Ceres'
  * feed_ids          (feed_ids) int64 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0
  * observation_ids   (observation_ids) int64 0
    observations      (observation_ids) <U23 'uid://A002/X327408/X6f'
  * polarization_ids  (polarization_ids) int64 0
  * source_ids        (source_ids) int64 0 1
    sources           (source_ids) object 'J0522-364' 'J1037-295'
  * spw_ids           (spw_ids) int64 0
  * state_ids         (state_ids) int64 0 1 2 3 4 5 6 7 ... 13 14 15 16 17 18 19

conjugatevis

[9]:
# CASA 6
from casatasks import conjugatevis

conjugatevis(vis='twhya.ms', outputvis='casa6.conj.ms', overwrite=True)

casa_xds = convert_ms('casa6.conj.ms').xds0
visplot(casa_xds.DATA.imag[:,100,:,0], axis=['time','chan'])
Completed ddi 0  process time 27.06 s
Completed subtables  process time 1.10 s

_images/verification_16_1.png
[10]:
# CNGI
cngi_xda = mxds.xds0.DATA.conj()

visplot(cngi_xda.imag[:,100,:,0], axis=['time','chan'])
_images/verification_17_0.png
[11]:
# Delta
print('max delta : ', np.nanmax(np.abs((casa_xds.DATA - cngi_xda).values)))
max delta :  0.0

hanningsmooth

[12]:
# CASA6
from casatasks import hanningsmooth

hanningsmooth(vis='twhya.ms', outputvis='casa6.smooth.ms', datacolumn='data')

casa_xds = convert_ms('casa6.smooth.ms').xds0
visplot(casa_xds.DATA, axis='chan')
Completed ddi 0  process time 22.05 s
Completed subtables  process time 1.06 s

_images/verification_20_1.png
[13]:
# CNGI
from cngi.vis import apply_flags, chan_smooth

cngi_xds = chan_smooth(mxds, 'xds0').xds0

visplot(cngi_xds.DATA, axis='chan')
_images/verification_21_0.png
[14]:
# Delta
print('max delta : ', np.nanmax(np.abs((casa_xds.DATA - cngi_xds.DATA).values)))
max delta :  6.104260637590507e-05

mstransform

chanaverage

[15]:
# CASA 6
from casatasks import mstransform

os.system("rm -fr casa6.avg.ms")
mstransform(vis='twhya.ms', outputvis='casa6.avg.ms', datacolumn='DATA', chanaverage=True, chanbin=3)

casa_xds = convert_ms('casa6.avg.ms').xds0
visplot(casa_xds.DATA[100,:,:,0], axis=['chan', 'baseline'])
Completed ddi 0  process time 8.50 s
Completed subtables  process time 1.04 s

_images/verification_25_1.png
[16]:
# CNGI
from cngi.vis import chan_average

cngi_xds = chan_average(mxds, 'xds0', width=3).xds0

visplot(cngi_xds.DATA[100,:,:,0], axis=['chan', 'baseline'])
_images/verification_26_0.png
[17]:
# Delta
print('max delta : ', np.nanmax(np.abs((casa_xds.DATA[100,:,:,0] - cngi_xds.DATA[100,:,:,0]).values)))
max delta :  1.5973847098419519e-06

timeaverage

[18]:
# CASA 6
from casatasks import mstransform

os.system("rm -fr casa6.tavg.ms")
mstransform(vis='twhya.ms', outputvis='casa6.tavg.ms', datacolumn='DATA', timeaverage=True, timebin='25s', timespan='state')

casa_xds = convert_ms('casa6.tavg.ms').xds0
visplot(casa_xds.DATA[:,:,100,0], axis='time')
Completed ddi 0  process time 4.47 s
Completed subtables  process time 1.04 s

_images/verification_29_1.png
[19]:
# CNGI
from cngi.vis import time_average

mxds2 = mxds.assign_attrs({'xds1':mxds.xds0.chunk(400, 210, 64, 1)}) # increase chunk size to avoid warnings
cngi_xds = time_average(mxds2, 'xds1', bin=5, span='state').xds1

visplot(cngi_xds.DATA[:,:,100,0], axis='time')
_images/verification_30_0.png
[20]:
# Delta
print('max delta : ', np.nanmax(np.abs((casa_xds.DATA[:,:,100,0] - cngi_xds.DATA[:,:,100,0]).values)))
max delta :  5.173171442074411e-06

sdsmooth - TBD

likely to be demonstrated as satisfied by cngi.vis.chan_smooth


sdtimeaverage - TBD

likely to be demonstrated as satisfied by cngi.vis.time_average


split

[21]:
# CASA 6
from casatasks import split

os.system("rm -fr casa6.split.ms")
split(vis='twhya.ms', outputvis='casa6.split.ms', datacolumn='DATA', spw='*:30~100', field='3', width=3)

casa_xds = convert_ms('casa6.split.ms').xds0
visplot(casa_xds.DATA, axis=['chan', 'time'])
Completed ddi 0  process time 0.81 s
Completed subtables  process time 1.06 s

_images/verification_35_1.png
[22]:
# CNGI
from cngi.vis import chan_average

selection = mxds.xds0.isel(chan=range(30,101)).where(mxds.xds0.FIELD_ID == 3, drop=True)
cngi_xds = chan_average(mxds.assign_attrs({'xds1':selection}), 'xds1', width=3).xds1

visplot(cngi_xds.DATA, axis=['chan', 'time'])
_images/verification_36_0.png
[23]:
# Delta
print('max delta : ', np.nanmax(np.abs((casa_xds.DATA - cngi_xds.DATA).values)))
max delta :  2.132480599880018e-06

uvcontsub

[24]:
# CASA 6
from casatasks import uvcontsub

uvcontsub(vis='twhya.ms', field="5", combine='scan', fitspw='0:200~300', excludechans=True, fitorder=1, want_cont=True)

casa_cont_xds = convert_ms('twhya.ms.cont').xds0

visplot(casa_cont_xds.DATA[10,10,:,0], axis=['chan'])
Completed ddi 0  process time 12.90 s
Completed subtables  process time 1.31 s

_images/verification_39_1.png
[25]:
# CNGI
from cngi.vis import uv_cont_fit

selection = mxds.xds0.where(mxds.xds0.FIELD_ID == 5, drop=True)
cngi_xds = uv_cont_fit(mxds.assign_attrs({'xds1':selection}), 'xds1', source='DATA', target='CONTFIT', fitorder=1, excludechans=list(range(200,300))).xds1

visplot(cngi_xds.CONTFIT[10,10,:,0], axis=['chan'])
_images/verification_40_0.png
[26]:
# Delta
print('max delta : ', np.nanmax(np.abs((casa_cont_xds.DATA - cngi_xds.CONTFIT).values)))
max delta :  0.44718851662412784

uvsub

[27]:
# CASA 6
from casatasks import uvsub

os.system('cp -r twhya.ms uvsub.ms')
uvsub('uvsub.ms')

casa_xds = convert_ms('uvsub.ms').xds0

visplot(casa_xds.DATA[310,10,:,0], axis=['chan'], drawplot=False)
visplot(casa_xds.CORRECTED_DATA[310,10,:,0], axis=['chan'], overplot=True)
Completed ddi 0  process time 48.04 s
Completed subtables  process time 1.20 s

_images/verification_43_1.png
[28]:
# CNGI
from cngi.vis import apply_flags

cngi_xda = mxds.xds0.DATA - mxds.xds0.MODEL_DATA

visplot(mxds.xds0.DATA[310,10,:,0], axis=['chan'], drawplot=False)
visplot(cngi_xda[310,10,:,0], axis=['chan'], overplot=True)
_images/verification_44_0.png
[29]:
# Delta
print('max delta : ', np.nanmax(np.abs((casa_xds.CORRECTED_DATA - cngi_xda).values)))
max delta :  3.0517578125e-05

vishead

Note the mechanism for retrieving data from the MeasurementSet is fundamentally different, but the data itself is the same

[30]:
# CASA 6
from casatasks import vishead

vishead(vis='twhya.ms', mode='list')
[30]:
{'field': (array(['J0522-364', 'J0539+145', 'Ceres', 'J1037-295', 'TW Hya', 'TW Hya',
         '3c279'], dtype='<U16'), {}),
 'freq_group_name': (array([''], dtype='<U16'), {}),
 'observer': (array(['cqi'], dtype='<U16'), {}),
 'project': (array(['uid://A002/X327408/X6f'], dtype='<U23'), {}),
 'release_date': (array([0.]),
  {'MEASINFO': {'Ref': 'UTC', 'type': 'epoch'},
   'QuantumUnits': array(['s'], dtype='<U16')}),
 'schedule': ({'r1': array([['SchedulingBlock uid://A002/X327408/X73'],
          ['ExecBlock uid://A002/X554543/X207']], dtype='<U39')}, {}),
 'schedule_type': (array(['ALMA'], dtype='<U16'), {}),
 'spw_name': (array(['ALMA_RB_07#BB_2#SW-01#FULL_RES'], dtype='<U31'), {}),
 'telescope': (array(['ALMA'], dtype='<U16'), {})}
[31]:
# CNGI
print(mxds)
<xarray.Dataset>
Dimensions:           (antenna_ids: 26, feed_ids: 26, field_ids: 7, observation_ids: 1, polarization_ids: 1, source_ids: 5, spw_ids: 1, state_ids: 20)
Coordinates:
  * antenna_ids       (antenna_ids) int64 0 1 2 3 4 5 6 ... 19 20 21 22 23 24 25
    antennas          (antenna_ids) <U16 'DA41' 'DA42' 'DA44' ... 'DV22' 'DV23'
  * field_ids         (field_ids) int64 0 1 2 3 4 5 6
    fields            (field_ids) <U9 'J0522-364' 'J0539+145' ... '3c279'
  * feed_ids          (feed_ids) int64 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0
  * observation_ids   (observation_ids) int64 0
    observations      (observation_ids) <U23 'uid://A002/X327408/X6f'
  * polarization_ids  (polarization_ids) int64 0
  * source_ids        (source_ids) int64 0 1 2 3 4
    sources           (source_ids) <U9 'J0522-364' 'Ceres' ... 'TW Hya' '3c279'
  * spw_ids           (spw_ids) int64 0
  * state_ids         (state_ids) int64 0 1 2 3 4 5 6 7 ... 13 14 15 16 17 18 19
Data variables:
    *empty*
Attributes: (12/17)
    xds0:             <xarray.Dataset>\nDimensions:         (baseline: 210, c...
    ANTENNA:          <xarray.Dataset>\nDimensions:        (antenna_id: 26, d...
    ASDM_ANTENNA:     <xarray.Dataset>\nDimensions:         (d0: 26, d1: 3)\n...
    ASDM_CALWVR:      <xarray.Dataset>\nDimensions:            (d0: 702, d1: ...
    ASDM_RECEIVER:    <xarray.Dataset>\nDimensions:           (d0: 26, d1: 2,...
    ASDM_STATION:     <xarray.Dataset>\nDimensions:    (d0: 28, d1: 3)\nDimen...
    ...               ...
    POLARIZATION:     <xarray.Dataset>\nDimensions:       (d0: 1, d1: 2, d2: ...
    PROCESSOR:        <xarray.Dataset>\nDimensions:   (d0: 3)\nCoordinates:\n...
    SOURCE:           <xarray.Dataset>\nDimensions:             (d0: 5, d1: 2...
    SPECTRAL_WINDOW:  <xarray.Dataset>\nDimensions:             (d1: 384, d2:...
    STATE:            <xarray.Dataset>\nDimensions:   (state_id: 20)\nCoordin...
    WEATHER:          <xarray.Dataset>\nDimensions:                 (d0: 385,...

visstat

[32]:
# CASA 6
from casatasks import visstat

casa_dict = visstat(vis='twhya.ms', axis='real', datacolumn='data')['DATA_DESC_ID=0']
print(casa_dict['max'], casa_dict['stddev'])
106.0803451538086 8.556056451642778
[33]:
# CNGI
from cngi.vis import apply_flags

cngi_max = apply_flags(mxds, 'xds0').xds0.DATA.real.max().values
cngi_std = apply_flags(mxds, 'xds0').xds0.DATA.real.std().values

print(cngi_max, cngi_std)
106.0803451538086 8.556056382448858
[34]:
# Delta
print('max delta : ', np.max(np.abs([casa_dict['max'] - cngi_max, casa_dict['stddev'] - cngi_std])))
max delta :  6.919391992710189e-08

cngi.image Module

Demonstration of CASA functions to be handled by the CNGI image module.

Note: this is a demonstration of mechanics only and is not intended for science

imhead

Note the mechanism for retrieving data from the image is fundamentally different, but the data itself is the same

[35]:
# CASA6
from casatasks import imhead

casa_dict = imhead(imagename='twhya.image', mode='summary')
casa_dict
[35]:
{'axisnames': array(['Right Ascension', 'Declination', 'Stokes', 'Frequency'],
       dtype='<U16'),
 'axisunits': array(['rad', 'rad', '', 'Hz'], dtype='<U16'),
 'defaultmask': 'mask0',
 'hasmask': True,
 'imagetype': 'Intensity',
 'incr': array([-4.84813681e-07,  4.84813681e-07,  1.00000000e+00,  6.10330159e+05]),
 'masks': array(['mask0'], dtype='<U16'),
 'messages': array([], dtype='<U16'),
 'ndim': 4,
 'perplanebeams': {'beams': {'*0': {'*0': {'major': {'unit': 'arcsec',
      'value': 0.6526992917060852},
     'minor': {'unit': 'arcsec', 'value': 0.5043594837188721},
     'positionangle': {'unit': 'deg', 'value': -65.8895263671875}}},
   '*1': {'*0': {'major': {'unit': 'arcsec', 'value': 0.6526992917060852},
     'minor': {'unit': 'arcsec', 'value': 0.5043594837188721},
     'positionangle': {'unit': 'deg', 'value': -65.8895263671875}}},
   '*2': {'*0': {'major': {'unit': 'arcsec', 'value': 0.652698278427124},
     'minor': {'unit': 'arcsec', 'value': 0.50435870885849},
     'positionangle': {'unit': 'deg', 'value': -65.88955688476562}}},
   '*3': {'*0': {'major': {'unit': 'arcsec', 'value': 0.6526971459388733},
     'minor': {'unit': 'arcsec', 'value': 0.5043579339981079},
     'positionangle': {'unit': 'deg', 'value': -65.88956451416016}}},
   '*4': {'*0': {'major': {'unit': 'arcsec', 'value': 0.6526962518692017},
     'minor': {'unit': 'arcsec', 'value': 0.5043571591377258},
     'positionangle': {'unit': 'deg', 'value': -65.88956451416016}}},
   '*5': {'*0': {'major': {'unit': 'arcsec', 'value': 0.6526952385902405},
     'minor': {'unit': 'arcsec', 'value': 0.5043563842773438},
     'positionangle': {'unit': 'deg', 'value': -65.88957977294922}}},
   '*6': {'*0': {'major': {'unit': 'arcsec', 'value': 0.6526942849159241},
     'minor': {'unit': 'arcsec', 'value': 0.5043556690216064},
     'positionangle': {'unit': 'deg', 'value': -65.88958740234375}}},
   '*7': {'*0': {'major': {'unit': 'arcsec', 'value': 0.6526930928230286},
     'minor': {'unit': 'arcsec', 'value': 0.5043548941612244},
     'positionangle': {'unit': 'deg', 'value': -65.88959503173828}}},
   '*8': {'*0': {'major': {'unit': 'arcsec', 'value': 0.6526919603347778},
     'minor': {'unit': 'arcsec', 'value': 0.5043540000915527},
     'positionangle': {'unit': 'deg', 'value': -65.88961029052734}}},
   '*9': {'*0': {'major': {'unit': 'arcsec', 'value': 0.6526909470558167},
     'minor': {'unit': 'arcsec', 'value': 0.5043532848358154},
     'positionangle': {'unit': 'deg', 'value': -65.88957214355469}}}},
  'nChannels': 10,
  'nStokes': 1},
 'refpix': array([125., 125.,   0.,   0.]),
 'refval': array([ 2.88792330e+00, -6.05713443e-01,  1.00000000e+00,  3.72520023e+11]),
 'shape': array([250, 250,   1,  10]),
 'tileshape': array([125,  50,   1,   5]),
 'unit': 'Jy/beam'}
[36]:
# CNGI
print(image_xds)
<xarray.Dataset>
Dimensions:          (chan: 10, l: 250, m: 250, pol: 1, time: 1)
Coordinates:
  * chan             (chan) float64 3.725e+11 3.725e+11 ... 3.725e+11 3.725e+11
    declination      (l, m) float64 dask.array<chunksize=(250, 250), meta=np.ndarray>
  * l                (l) float64 6.06e-05 6.012e-05 ... -5.963e-05 -6.012e-05
  * m                (m) float64 -6.06e-05 -6.012e-05 ... 5.963e-05 6.012e-05
  * pol              (pol) float64 1.0
    right_ascension  (l, m) float64 dask.array<chunksize=(250, 250), meta=np.ndarray>
  * time             (time) datetime64[ns] 2012-11-19T07:56:26.544000626
Data variables:
    AUTOMASK         (l, m, time, chan, pol) float64 dask.array<chunksize=(250, 250, 1, 1, 1), meta=np.ndarray>
    IMAGE            (l, m, time, chan, pol) float64 dask.array<chunksize=(250, 250, 1, 1, 1), meta=np.ndarray>
    IMAGE_MASK0      (l, m, time, chan, pol) bool dask.array<chunksize=(250, 250, 1, 1, 1), meta=np.ndarray>
    MODEL            (l, m, time, chan, pol) float64 dask.array<chunksize=(250, 250, 1, 1, 1), meta=np.ndarray>
    PB               (l, m, time, chan, pol) float64 dask.array<chunksize=(250, 250, 1, 1, 1), meta=np.ndarray>
    PB_MASK0         (l, m, time, chan, pol) bool dask.array<chunksize=(250, 250, 1, 1, 1), meta=np.ndarray>
    PSF              (l, m, time, chan, pol) float64 dask.array<chunksize=(250, 250, 1, 1, 1), meta=np.ndarray>
    RESIDUAL         (l, m, time, chan, pol) float64 dask.array<chunksize=(250, 250, 1, 1, 1), meta=np.ndarray>
    RESIDUAL_MASK0   (l, m, time, chan, pol) bool dask.array<chunksize=(250, 250, 1, 1, 1), meta=np.ndarray>
    SUMWT            (time, chan, pol) float64 dask.array<chunksize=(1, 1, 1), meta=np.ndarray>
Attributes: (12/19)
    axisnames:            ['Right Ascension', 'Declination', 'Time', 'Frequen...
    axisunits:            ['rad', 'rad', 'datetime64[ns]', 'Hz', '']
    commonbeam:           [0.6526992917060852, 0.5043594837188721, -65.889526...
    commonbeam_units:     ['arcsec', 'arcsec', 'deg']
    date_observation:     2012/11/19/07
    direction_reference:  j2000
    ...                   ...
    restoringbeam:        [0.6526992917060852, 0.5043594837188721, -65.889526...
    spectral__reference:  lsrk
    telescope:            alma
    telescope_position:   [2.22514e+06m, -5.44031e+06m, -2.48103e+06m] (itrf)
    unit:                 Jy/beam
    velocity__type:       radio
[37]:
# Delta
print('max delta : ', np.abs(casa_dict['incr'] - image_xds.incr).max())
max delta :  0.0

imval

Note the mechanism for retrieving data from the image is fundamentally different, but the data itself is the same

[38]:
# CASA6
from casatasks import imval

casa_dict = imval('twhya.image', box='85,100,86,102', chans='2')
casa_dict
[38]:
{'axes': [[0, 'Right Ascension'],
  [1, 'Declination'],
  [3, 'Frequency'],
  [2, 'Stokes']],
 'blc': [85, 100, 0, 2],
 'coords': array([[[ 2.88794689e+00, -6.05725563e-01,  1.00000000e+00,
           3.72521243e+11],
         [ 2.88794689e+00, -6.05725079e-01,  1.00000000e+00,
           3.72521243e+11],
         [ 2.88794689e+00, -6.05724594e-01,  1.00000000e+00,
           3.72521243e+11]],

        [[ 2.88794630e+00, -6.05725563e-01,  1.00000000e+00,
           3.72521243e+11],
         [ 2.88794630e+00, -6.05725079e-01,  1.00000000e+00,
           3.72521243e+11],
         [ 2.88794630e+00, -6.05724594e-01,  1.00000000e+00,
           3.72521243e+11]]]),
 'data': array([[0.01665862, 0.02118381, 0.02057032],
        [0.00525612, 0.00775176, 0.00969939]]),
 'mask': array([[ True,  True,  True],
        [ True,  True,  True]]),
 'trc': [86, 102, 0, 2],
 'unit': 'Jy/beam'}
[39]:
# CNGI
cngi_xds = image_xds.isel(l=range(85,87), m=range(100,103), chan=2).compute()
print(cngi_xds)
<xarray.Dataset>
Dimensions:          (l: 2, m: 3, pol: 1, time: 1)
Coordinates:
    chan             float64 3.725e+11
    declination      (l, m) float64 -0.6057 -0.6057 -0.6057 ... -0.6057 -0.6057
  * l                (l) float64 1.939e-05 1.891e-05
  * m                (m) float64 -1.212e-05 -1.164e-05 -1.115e-05
  * pol              (pol) float64 1.0
    right_ascension  (l, m) float64 2.888 2.888 2.888 2.888 2.888 2.888
  * time             (time) datetime64[ns] 2012-11-19T07:56:26.544000626
Data variables:
    AUTOMASK         (l, m, time, pol) float64 0.0 0.0 0.0 0.0 0.0 0.0
    IMAGE            (l, m, time, pol) float64 0.01666 0.02118 ... 0.009699
    IMAGE_MASK0      (l, m, time, pol) bool True True True True True True
    MODEL            (l, m, time, pol) float64 0.0 0.0 0.0 0.0 0.0 0.0
    PB               (l, m, time, pol) float64 0.8004 0.8046 ... 0.8115 0.8156
    PB_MASK0         (l, m, time, pol) bool True True True True True True
    PSF              (l, m, time, pol) float64 -0.01334 -0.01428 ... 0.0001316
    RESIDUAL         (l, m, time, pol) float64 0.01666 0.02118 ... 0.009699
    RESIDUAL_MASK0   (l, m, time, pol) bool True True True True True True
    SUMWT            (time, pol) float64 1.13e+07
Attributes: (12/19)
    axisnames:            ['Right Ascension', 'Declination', 'Time', 'Frequen...
    axisunits:            ['rad', 'rad', 'datetime64[ns]', 'Hz', '']
    commonbeam:           [0.6526992917060852, 0.5043594837188721, -65.889526...
    commonbeam_units:     ['arcsec', 'arcsec', 'deg']
    date_observation:     2012/11/19/07
    direction_reference:  j2000
    ...                   ...
    restoringbeam:        [0.6526992917060852, 0.5043594837188721, -65.889526...
    spectral__reference:  lsrk
    telescope:            alma
    telescope_position:   [2.22514e+06m, -5.44031e+06m, -2.48103e+06m] (itrf)
    unit:                 Jy/beam
    velocity__type:       radio
[40]:
# Delta
print('max delta : ', np.abs(casa_dict['data'] - cngi_xds.IMAGE.values.squeeze()).max())
max delta :  0.0

imcollapse

[41]:
# CASA6
from casatasks import imcollapse

imcollapse('twhya.image', function='sum', axes=[2,3], outfile='casa6.collapse.image', overwrite=True)

casa_xds = convert_image('casa6.collapse.image')
implot(casa_xds.IMAGE)
converting Image...
processed image in 0.21397114 seconds
_images/verification_63_1.png
[42]:
# CNGI
cngi_xds = image_xds.where(image_xds.IMAGE_MASK0).sum(dim=['chan','pol'])

implot(cngi_xds.IMAGE)
_images/verification_64_0.png
[43]:
# Delta
print('max delta : ', np.abs((casa_xds.IMAGE - cngi_xds.IMAGE).values).max())
max delta :  1.1920928955078125e-07

imcontsub

Apparently someone the naming of line and continuum files is reversed

[44]:
# CASA6
from casatasks import imcontsub

os.system('rm -fr casa6.*.image')
imcontsub(imagename="twhya.image", linefile="casa6.line.image", contfile="casa6.cont.image", fitorder=2, chans='1~3,7~9')

casa_linefit = convert_image('casa6.line.image')
casa_contsub = convert_image('casa6.cont.image')

implot(casa_linefit.IMAGE.where(casa_linefit.IMAGE_MASK0))
implot(casa_contsub.IMAGE.where(casa_contsub.IMAGE_MASK0))
converting Image...
processed image in 0.38849592 seconds
converting Image...
processed image in 0.37773752 seconds
_images/verification_67_1.png
_images/verification_67_2.png
[45]:
# CNGI
from cngi.image import cont_sub

cngi_xds = cont_sub(image_xds.where(image_xds.IMAGE_MASK0), dv='IMAGE', fitorder=2, chans=[1,2,3,7,8,9], linename='LINE', contname='CONTINUUM')

implot(cngi_xds.LINE)
implot(cngi_xds.CONTINUUM)
_images/verification_68_0.png
_images/verification_68_1.png
[46]:
# Delta
print('max delta : ', np.nanmax(np.abs((casa_linefit.IMAGE - cngi_xds.CONTINUUM).values)))
print('max delta : ', np.nanmax(np.abs((casa_contsub.IMAGE.where(casa_contsub.IMAGE_MASK0) - cngi_xds.LINE).values)))
max delta :  1.4396755787515758e-08
max delta :  1.4896446964840493e-08

imdev - TBD

Pending implementation of statistics, this will likely be done directly on the xds by calling xds.rolling() with the new statistics function


immath

Note that only ‘evalexpr’ mode is shown here. ‘spix’ mode should instead use cngi.image.spixfit and ‘poli’/’pola’ modes should compute the math manually

[47]:
# CASA6
from casatasks import immath

os.system("rm -fr casa6.math.image")
immath(imagename='twhya.image', expr='sin(IM0)', outfile='casa6.math.image')

casa_xds = convert_image('casa6.math.image')
implot(casa_xds.IMAGE)
converting Image...
processed image in 0.39214063 seconds
_images/verification_72_1.png
[48]:
# CNGI
cngi_xda = np.sin(image_xds.IMAGE)

implot(cngi_xda)
_images/verification_73_0.png
[49]:
# Delta
print('max delta : ', np.abs((casa_xds.IMAGE - cngi_xda).values).max())
max delta :  1.4870845721492998e-08

immoments

[50]:
# CASA6
from casatasks import immoments

os.system('rm -rf casa6.immoments.image*')
immoments(imagename='twhya.image', axis='spectral', moments=[0], outfile='casa6.immoments.image')

casa_xds = convert_image('casa6.immoments.image')

implot(casa_xds.IMAGE)
converting Image...
processed image in 0.20693302 seconds
_images/verification_76_1.png
[51]:
# CNGI
from cngi.image import moments

cngi_xds = moments(image_xds.where(image_xds.IMAGE_MASK0), moment=[0])

implot(cngi_xds.MOMENTS_INTEGRATED)
_images/verification_77_0.png
[52]:
# Delta
print('max delta : ', np.abs((casa_xds.IMAGE - cngi_xds.MOMENTS_INTEGRATED).values).max())
max delta :  5.094286832374451e-07

imrebin

Note that CASA bins pixels starting from the edge of the mask/region. CNGI bins pixels starting from the edge of the image (ignoring values in masked pixels). This creates a discrepency in output at the edge of masks.

[53]:
# CASA6
from casatasks import imrebin

imrebin(imagename='twhya.image', outfile='casa6.rebin.image', factor=3, overwrite=True)

casa_xds = convert_image('casa6.rebin.image')
implot(casa_xds.IMAGE)
converting Image...
processed image in 0.2709217 seconds
_images/verification_80_1.png
[54]:
# CNGI
from cngi.image import rebin

cngi_xds = rebin(image_xds.where(image_xds.IMAGE_MASK0), axis='l', factor=3)

implot(cngi_xds.IMAGE)
_images/verification_81_0.png
[55]:
# Delta
print('max delta : ', np.abs((casa_xds.IMAGE - cngi_xds.IMAGE).values).max())
max delta :  0.05339271823565166

imsmooth

Note there is currently a discrepency in output that is not understood

[56]:
# CASA6
from casatasks import imsmooth

imsmooth('twhya.image', kernel='gaussian', targetres=True, outfile='casa6.smooth.image',
         overwrite=True, beam = {"major": "1arcsec", "minor": "1arcsec", "pa": "30deg"});

casa_xds = convert_image('casa6.smooth.image')
implot(casa_xds.IMAGE)
converting Image...
processed image in 0.38987756 seconds
_images/verification_84_1.png
[57]:
# CNGI
from cngi.image import smooth

cngi_xds = smooth(image_xds.where(image_xds.IMAGE_MASK0, other=0), kernel='gaussian', size=[1., 1., 30.],
                  current=image_xds.commonbeam, name='TARGET_BEAM')

implot(cngi_xds.IMAGE)
_images/verification_85_0.png
[58]:
# Delta
print('max delta : ', np.abs((casa_xds.IMAGE - cngi_xds.IMAGE).values).max())
max delta :  0.3243054985856718

imsubimage

[59]:
# CASA6
from casatasks import imsubimage

imsubimage('twhya.image', outfile='casa6.subimage.image', box='85,100,134,149', overwrite=True)

casa_xds = convert_image('casa6.subimage.image')
implot(casa_xds.IMAGE)
converting Image...
processed image in 0.1738503 seconds
_images/verification_88_1.png
[60]:
# CNGI
cngi_xds = image_xds.isel(l=range(85,135), m=range(100,150))

implot(cngi_xds.IMAGE)
_images/verification_89_0.png
[61]:
# Delta
print('max delta : ', np.abs((casa_xds.IMAGE - cngi_xds.IMAGE).values).max())
max delta :  0.0

imstat

[62]:
# CASA6
from casatasks import imstat

casa_stats = imstat('twhya.image')

casa_stats
[62]:
{'blc': array([0, 0, 0, 0]),
 'blcf': '11:01:52.810, -34.42.29.866, I, 3.7252e+11Hz',
 'flux': array([6.27340375]),
 'max': array([0.36960047]),
 'maxpos': array([120, 127,   0,   1]),
 'maxposf': '11:01:51.837, -34.42.17.166, I, 3.725206e+11Hz',
 'mean': array([0.00110953]),
 'medabsdevmed': array([0.01520567]),
 'median': array([0.]),
 'min': array([-0.10551776]),
 'minpos': array([ 94, 193,   0,   3]),
 'minposf': '11:01:52.047, -34.42.10.566, I, 3.725219e+11Hz',
 'npts': array([429530.]),
 'q1': array([-0.01529752]),
 'q3': array([0.01509237]),
 'quartile': array([0.03038988]),
 'rms': array([0.02771565]),
 'sigma': array([0.02769347]),
 'sum': array([476.57430563]),
 'sumsq': array([329.94660415]),
 'trc': array([249, 249,   0,   9]),
 'trcf': '11:01:50.790, -34.42.04.966, I, 3.725255e+11Hz'}
[63]:
# CNGI
from cngi.image import statistics

cngi_stats = statistics(image_xds, compute=True).statistics

cngi_stats
[63]:
{'blc': array([0, 0, 0, 0, 0]),
 'blcf': ['11:01:52.80971154',
  '-34.42.29.86573768',
  '2012-11-19T07:56:26.544000626',
  372520022603.63745,
  1.0],
 'max': 0.36960047483444214,
 'maxpos': [120, 127, 0, 1, 0],
 'maxposf': ['11:01:51.83654673',
  '-34.42.17.16599958',
  '2012-11-19T07:56:26.544000626',
  372520632933.7965,
  1.0],
 'mean': 0.0005451506748828763,
 'medabsdevmed': 0.014964754227548838,
 'median': 0.0,
 'min': -0.10752750933170319,
 'minpos': [27, 199, 0, 3, 0],
 'minposf': ['11:01:52.59069674',
  '-34.42.09.96583877',
  '2012-11-19T07:56:26.544000626',
  372521853594.1146,
  1.0],
 'npts': 625000,
 'q1': -0.01533513329923153,
 'q3': 0.014549590414389968,
 'quartile': 0.029884723713621497,
 'rms': 0.026438209534621095,
 'sigma': 0.026432588487286,
 'sum': 340.71917180179764,
 'sumsq': 436.8618271228311,
 'trc': array([249, 249,   0,   9,   0]),
 'trcf': ['11:01:50.79048222',
  '-34.42.04.96574187',
  '2012-11-19T07:56:26.544000626',
  372525515575.069,
  1.0]}
[64]:
# Delta
print('max delta : ', np.abs([casa_stats['medabsdevmed']-cngi_stats['medabsdevmed'], casa_stats['q1']-cngi_stats['q1']]).max())
max delta :  0.00024092057719826698

imtrans

Note the image converter will swap the transposed axes back, so we have to work around that here to show the effect

[65]:
# CASA6
from casatasks import imtrans

os.system("rm -fr casa6.trans.image")
imtrans('twhya.image', outfile='casa6.trans.image', order='1023')

casa_image = imval('casa6.trans.image', box='0,0,249,249', chans='2')['data']

plt.imshow(casa_image)
[65]:
<matplotlib.image.AxesImage at 0x7f5de9a22690>
_images/verification_96_1.png
[66]:
# CNGI
cngi_xds = image_xds.transpose('m','l','time','chan','pol')

plt.imshow(cngi_xds.IMAGE[:,:,0,2,0].values)
[66]:
<matplotlib.image.AxesImage at 0x7f5de7798950>
_images/verification_97_1.png
[67]:
# Delta
print('max delta : ', np.abs(casa_image - cngi_xds.IMAGE[:,:,0,2,0].values).max())
max delta :  0.0

makemask

[68]:
# CASA6
from casatasks import makemask

makemask(mode='copy', inpimage='twhya.image', inpmask='box[[2.887905rad, -0.60573rad], [2.887935rad, -0.60570rad]]',
         output='casa6.makemask.image', overwrite=True)

casa_xds = convert_image('casa6.makemask.image')
implot(casa_xds.IMAGE)
converting Image...
processed image in 0.22030282 seconds
_images/verification_100_1.png
[69]:
# CNGI
from cngi.image import region

# note that CASA swaps the meaning of 0/1 between regions and masks, CNGI does not
# so replicating the values of a CASA mask requires us to use a CNGI region
cngi_xds = region(image_xds, 'MASK1', ra=[2.887905, 2.887935], dec=[-0.60573, -0.60570])

implot(cngi_xds.MASK1)
_images/verification_101_0.png
[70]:
# Delta
print('max delta : ', np.abs((casa_xds.IMAGE - cngi_xds.MASK1).values).max())
max delta :  0.0

specfit

[71]:
from casatasks import specfit

os.system('rm -fr casa6.specfit.image')
rc = specfit('twhya.image', box="125,125,125,125", model='casa6.specfit.image', pampest=1.5, pcenterest=0, pfwhmest=5, ngauss=1, multifit=False)

casa_xds = convert_image('casa6.specfit.image')
implot(casa_xds.IMAGE[0,0,0,:,0], axis=['chan'])
converting Image...
processed image in 0.16069746 seconds
_images/verification_104_1.png
[72]:
from cngi.image import spec_fit

cngi_xds = spec_fit(image_xds, dv='IMAGE', pixel=(125,125), sigma=2000, name='FIT')

implot(cngi_xds.FIT, axis='chan', overplot=True)
_images/verification_105_0.png
[73]:
# Delta
print('max delta : ', np.abs((casa_xds.IMAGE[0,0,0,:,0] - cngi_xds.FIT).values).max())
max delta :  0.04620384288038856