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 using namespace casacore;
13
oskar_ms_create_baseline_indices(oskar_MeasurementSet * p,unsigned int num_baselines)14 static void oskar_ms_create_baseline_indices(oskar_MeasurementSet* p,
15 unsigned int num_baselines)
16 {
17 bool write_auto_corr = false, write_cross_corr = false;
18 unsigned int num_stations = p->num_stations;
19 size_t size_bytes = num_baselines * sizeof(unsigned int);
20 p->a1 = (unsigned int*) realloc(p->a1, size_bytes);
21 p->a2 = (unsigned int*) realloc(p->a2, size_bytes);
22 if (num_baselines == num_stations * (num_stations + 1) / 2)
23 {
24 write_auto_corr = true;
25 write_cross_corr = true;
26 }
27 else if (num_baselines == num_stations * (num_stations - 1) / 2)
28 {
29 write_auto_corr = false;
30 write_cross_corr = true;
31 }
32 else if (num_baselines == num_stations)
33 {
34 write_auto_corr = true;
35 write_cross_corr = false;
36 }
37 if (write_cross_corr || write_auto_corr)
38 {
39 for (unsigned int s1 = 0, i = 0; s1 < num_stations; ++s1)
40 {
41 if (write_auto_corr)
42 {
43 p->a1[i] = s1;
44 p->a2[i] = s1;
45 ++i;
46 }
47 if (write_cross_corr)
48 {
49 for (unsigned int s2 = s1 + 1; s2 < num_stations; ++i, ++s2)
50 {
51 p->a1[i] = s1;
52 p->a2[i] = s2;
53 }
54 }
55 }
56 }
57 else
58 {
59 memset(p->a1, 0, num_baselines * sizeof(int));
60 memset(p->a2, 0, num_baselines * sizeof(int));
61 }
62 }
63
64 template <typename T>
oskar_ms_write_coords(oskar_MeasurementSet * p,unsigned int start_row,unsigned int num_baselines,const T * uu,const T * vv,const T * ww,double exposure_sec,double interval_sec,double time_stamp)65 void oskar_ms_write_coords(oskar_MeasurementSet* p,
66 unsigned int start_row, unsigned int num_baselines,
67 const T* uu, const T* vv, const T* ww,
68 double exposure_sec, double interval_sec, double time_stamp)
69 {
70 // Allocate storage for a (u,v,w) coordinate and a visibility weight.
71 Vector<Double> uvw(3);
72 Vector<Float> weight(p->num_pols, 1.0), sigma(p->num_pols, 1.0);
73
74 // Get references to columns.
75 #ifdef OSKAR_MS_NEW
76 ArrayColumn<Double>& col_uvw = p->msmc.uvw;
77 ScalarColumn<Int>& col_antenna1 = p->msmc.antenna1;
78 ScalarColumn<Int>& col_antenna2 = p->msmc.antenna2;
79 ArrayColumn<Float>& col_weight = p->msmc.weight;
80 ArrayColumn<Float>& col_sigma = p->msmc.sigma;
81 ScalarColumn<Double>& col_exposure = p->msmc.exposure;
82 ScalarColumn<Double>& col_interval = p->msmc.interval;
83 ScalarColumn<Double>& col_time = p->msmc.time;
84 ScalarColumn<Double>& col_timeCentroid = p->msmc.timeCentroid;
85 #else
86 MSMainColumns* msmc = p->msmc;
87 if (!msmc) return;
88 ArrayColumn<Double>& col_uvw = msmc->uvw();
89 ScalarColumn<Int>& col_antenna1 = msmc->antenna1();
90 ScalarColumn<Int>& col_antenna2 = msmc->antenna2();
91 ArrayColumn<Float>& col_weight = msmc->weight();
92 ArrayColumn<Float>& col_sigma = msmc->sigma();
93 ScalarColumn<Double>& col_exposure = msmc->exposure();
94 ScalarColumn<Double>& col_interval = msmc->interval();
95 ScalarColumn<Double>& col_time = msmc->time();
96 ScalarColumn<Double>& col_timeCentroid = msmc->timeCentroid();
97 #endif
98
99 // Add new rows if required.
100 oskar_ms_ensure_num_rows(p, start_row + num_baselines);
101
102 // Create baseline antenna indices if required.
103 if (!p->a1 || !p->a2)
104 {
105 oskar_ms_create_baseline_indices(p, num_baselines);
106 }
107
108 // Loop over rows to add.
109 for (unsigned int r = 0; r < num_baselines; ++r)
110 {
111 // Write the data to the Measurement Set.
112 unsigned int row = r + start_row;
113 uvw(0) = uu[r]; uvw(1) = vv[r]; uvw(2) = ww[r];
114 col_uvw.put(row, uvw);
115 col_antenna1.put(row, p->a1[r]);
116 col_antenna2.put(row, p->a2[r]);
117 col_weight.put(row, weight);
118 col_sigma.put(row, sigma);
119 col_exposure.put(row, exposure_sec);
120 col_interval.put(row, interval_sec);
121 col_time.put(row, time_stamp);
122 col_timeCentroid.put(row, time_stamp);
123 }
124
125 // Update time range if required.
126 if (time_stamp < p->start_time)
127 {
128 p->start_time = time_stamp - interval_sec/2.0;
129 }
130 if (time_stamp > p->end_time)
131 {
132 p->end_time = time_stamp + interval_sec/2.0;
133 }
134 p->time_inc_sec = interval_sec;
135 p->data_written = 1;
136 }
137
oskar_ms_write_coords_d(oskar_MeasurementSet * p,unsigned int start_row,unsigned int num_baselines,const double * uu,const double * vv,const double * ww,double exposure_sec,double interval_sec,double time_stamp)138 void oskar_ms_write_coords_d(oskar_MeasurementSet* p,
139 unsigned int start_row, unsigned int num_baselines,
140 const double* uu, const double* vv, const double* ww,
141 double exposure_sec, double interval_sec, double time_stamp)
142 {
143 oskar_ms_write_coords(p, start_row, num_baselines, uu, vv, ww,
144 exposure_sec, interval_sec, time_stamp);
145 }
146
oskar_ms_write_coords_f(oskar_MeasurementSet * p,unsigned int start_row,unsigned int num_baselines,const float * uu,const float * vv,const float * ww,double exposure_sec,double interval_sec,double time_stamp)147 void oskar_ms_write_coords_f(oskar_MeasurementSet* p,
148 unsigned int start_row, unsigned int num_baselines,
149 const float* uu, const float* vv, const float* ww,
150 double exposure_sec, double interval_sec, double time_stamp)
151 {
152 oskar_ms_write_coords(p, start_row, num_baselines, uu, vv, ww,
153 exposure_sec, interval_sec, time_stamp);
154 }
155
156 template <typename T>
oskar_ms_write_vis(oskar_MeasurementSet * p,unsigned int start_row,unsigned int start_channel,unsigned int num_channels,unsigned int num_baselines,const T * vis)157 void oskar_ms_write_vis(oskar_MeasurementSet* p,
158 unsigned int start_row, unsigned int start_channel,
159 unsigned int num_channels, unsigned int num_baselines, const T* vis)
160 {
161 // Allocate storage for the block of visibility data.
162 unsigned int num_pols = p->num_pols;
163 IPosition shape(3, num_pols, num_channels, num_baselines);
164 Array<Complex> vis_data(shape);
165
166 // Copy visibility data into the array,
167 // swapping baseline and channel dimensions.
168 float* out = (float*) vis_data.data();
169 for (unsigned int c = 0; c < num_channels; ++c)
170 {
171 for (unsigned int b = 0; b < num_baselines; ++b)
172 {
173 for (unsigned int p = 0; p < num_pols; ++p)
174 {
175 unsigned int i = (num_pols * (c * num_baselines + b) + p) << 1;
176 unsigned int j = (num_pols * (b * num_channels + c) + p) << 1;
177 out[j] = vis[i];
178 out[j + 1] = vis[i + 1];
179 }
180 }
181 }
182
183 // Add new rows if required.
184 oskar_ms_ensure_num_rows(p, start_row + num_baselines);
185
186 // Create the slicers for the column.
187 IPosition start1(1, start_row);
188 IPosition length1(1, num_baselines);
189 Slicer row_range(start1, length1);
190 IPosition start2(2, 0, start_channel);
191 IPosition length2(2, num_pols, num_channels);
192 Slicer array_section(start2, length2);
193
194 // Write visibilities to DATA column.
195 #ifdef OSKAR_MS_NEW
196 ArrayColumn<Complex>& col_data = p->msmc.data;
197 #else
198 ArrayColumn<Complex>& col_data = p->msmc->data();
199 #endif
200 col_data.putColumnRange(row_range, array_section, vis_data);
201 p->data_written = 1;
202 }
203
oskar_ms_write_vis_d(oskar_MeasurementSet * p,unsigned int start_row,unsigned int start_channel,unsigned int num_channels,unsigned int num_baselines,const double * vis)204 void oskar_ms_write_vis_d(oskar_MeasurementSet* p,
205 unsigned int start_row, unsigned int start_channel,
206 unsigned int num_channels, unsigned int num_baselines,
207 const double* vis)
208 {
209 oskar_ms_write_vis(p, start_row, start_channel,
210 num_channels, num_baselines, vis);
211 }
212
oskar_ms_write_vis_f(oskar_MeasurementSet * p,unsigned int start_row,unsigned int start_channel,unsigned int num_channels,unsigned int num_baselines,const float * vis)213 void oskar_ms_write_vis_f(oskar_MeasurementSet* p,
214 unsigned int start_row, unsigned int start_channel,
215 unsigned int num_channels, unsigned int num_baselines,
216 const float* vis)
217 {
218 oskar_ms_write_vis(p, start_row, start_channel,
219 num_channels, num_baselines, vis);
220 }
221