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