1 /*
2 * Copyright (c) 2011-2021, The OSKAR Developers.
3 * See the LICENSE file at the top-level directory of this distribution.
4 */
5
6 #include "ms/oskar_measurement_set.h"
7 #include "ms/private_ms.h"
8
9 #include <tables/Tables.h>
10 #include <casa/Arrays/Vector.h>
11
12 #include <cstdlib>
13 #include <cstdio>
14
15 using namespace casacore;
16
_oskar_ms_open(const char * filename,bool readonly)17 static oskar_MeasurementSet* _oskar_ms_open(const char* filename, bool readonly)
18 {
19 oskar_MeasurementSet* p = (oskar_MeasurementSet*)
20 calloc(1, sizeof(oskar_MeasurementSet));
21 p->num_receptors = 2;
22 Vector<Double> range(2, 0.0);
23
24 try
25 {
26 // Create the MeasurementSet. Storage managers are recreated as needed.
27 TableLock::LockOption lock = TableLock::PermanentLocking;
28 Table::TableOption mode = Table::Update;
29 if (readonly)
30 {
31 lock = TableLock::NoLocking;
32 mode = Table::Old;
33 }
34 #ifdef OSKAR_MS_NEW
35 p->ms = new Table(filename, lock, mode);
36 bind_refs(p);
37 #else
38 p->ms = new MeasurementSet(filename, lock, mode);
39
40 // Create the MSMainColumns and MSColumns objects for accessing data
41 // in the main table and subtables.
42 p->msc = new MSColumns(*(p->ms));
43 p->msmc = new MSMainColumns(*(p->ms));
44 #endif
45 }
46 catch (AipsError& e)
47 {
48 fprintf(stderr, "Caught AipsError: %s\n", e.what());
49 fflush(stderr);
50 oskar_ms_close(p);
51 return 0;
52 }
53
54 #ifdef OSKAR_MS_NEW
55 Table spw(p->ms->tableName() + "/SPECTRAL_WINDOW", Table::Old);
56 Table field(p->ms->tableName() + "/FIELD", Table::Old);
57 const int num_spectral_windows = spw.nrow();
58 const int num_fields = field.nrow();
59 #else
60 const int num_spectral_windows = p->ms->spectralWindow().nrow();
61 const int num_fields = p->ms->field().nrow();
62 #endif
63
64 // Refuse to open if there is more than one spectral window.
65 if (num_spectral_windows != 1)
66 {
67 fprintf(stderr, "OSKAR can read Measurement Sets with one spectral "
68 "window only. Use 'split' or 'mstransform' in CASA to select "
69 "the spectral window first.\n");
70 fflush(stderr);
71 oskar_ms_close(p);
72 return 0;
73 }
74
75 // Refuse to open if there is more than one field.
76 if (num_fields != 1)
77 {
78 fprintf(stderr, "OSKAR can read Measurement Sets with one target "
79 "field only. Use 'split' or 'mstransform' in CASA to select "
80 "the target field first.\n");
81 fflush(stderr);
82 oskar_ms_close(p);
83 return 0;
84 }
85
86 #ifdef OSKAR_MS_NEW
87 // Get the data dimensions.
88 Table pol(p->ms->tableName() + "/POLARIZATION", Table::Old);
89 ScalarColumn<Int> numCorr(pol, "NUM_CORR");
90 if (pol.nrow() > 0)
91 {
92 p->num_pols = numCorr.get(0);
93 }
94 if (num_spectral_windows > 0)
95 {
96 ScalarColumn<Int> numChan(spw, "NUM_CHAN");
97 ScalarColumn<Double> refFrequency(spw, "REF_FREQUENCY");
98 ArrayColumn<Double> chanWidth(spw, "CHAN_WIDTH");
99 p->num_channels = numChan.get(0);
100 p->freq_start_hz = refFrequency.get(0);
101 p->freq_inc_hz = (chanWidth.get(0))(IPosition(1, 0));
102 }
103 Table antenna(p->ms->tableName() + "/ANTENNA", Table::Old);
104 p->num_stations = antenna.nrow();
105 if (p->ms->nrow() > 0)
106 {
107 p->time_inc_sec = p->msmc.interval.get(0);
108 }
109
110 // Get the phase centre.
111 if (num_fields > 0)
112 {
113 ArrayColumn<Double> phaseDir(field, "PHASE_DIR");
114 Matrix<Double> dir;
115 phaseDir.get(0, dir);
116 if (dir.nrow() > 1)
117 {
118 p->phase_centre_rad[0] = dir(0, 0);
119 p->phase_centre_rad[1] = dir(1, 0);
120 }
121 }
122
123 // Get the time range.
124 Table observation(p->ms->tableName() + "/OBSERVATION", Table::Old);
125 ArrayColumn<Double> timeRange(observation, "TIME_RANGE");
126 if (observation.nrow() > 0)
127 {
128 timeRange.get(0, range);
129 }
130 #else
131 // Get the data dimensions.
132 if (p->ms->polarization().nrow() > 0)
133 p->num_pols = p->msc->polarization().numCorr().get(0);
134 if (num_spectral_windows > 0)
135 {
136 p->num_channels = p->msc->spectralWindow().numChan().get(0);
137 p->freq_start_hz = p->msc->spectralWindow().refFrequency().get(0);
138 p->freq_inc_hz = (p->msc->spectralWindow().chanWidth().get(0))(
139 IPosition(1, 0));
140 }
141 p->num_stations = p->ms->antenna().nrow();
142 if (p->ms->nrow() > 0)
143 p->time_inc_sec = p->msc->interval().get(0);
144
145 // Get the phase centre.
146 if (num_fields > 0)
147 {
148 Vector<MDirection> dir;
149 p->msc->field().phaseDirMeasCol().get(0, dir, true);
150 if (dir.size() > 0)
151 {
152 Vector<Double> v = dir(0).getAngle().getValue();
153 p->phase_centre_rad[0] = v(0);
154 p->phase_centre_rad[1] = v(1);
155 }
156 }
157
158 // Get the time range.
159 if (p->msc->observation().nrow() > 0)
160 p->msc->observation().timeRange().get(0, range);
161 #endif
162 p->start_time = range[0];
163 p->end_time = range[1];
164
165 return p;
166 }
167
oskar_ms_open(const char * filename)168 oskar_MeasurementSet* oskar_ms_open(const char* filename)
169 {
170 return _oskar_ms_open(filename, false);
171 }
172
oskar_ms_open_readonly(const char * filename)173 oskar_MeasurementSet* oskar_ms_open_readonly(const char* filename)
174 {
175 return _oskar_ms_open(filename, true);
176 }
177