Line data Source code
1 : //# SDPosInterpolator.cc: Implementation of SDPosInterpolator class
2 : //# Copyright (C) 1997,1998,1999,2000,2001,2002,2003
3 : //# Associated Universities, Inc. Washington DC, USA.
4 : //#
5 : //# This library is free software; you can redistribute it and/or modify it
6 : //# under the terms of the GNU Library General Public License as published by
7 : //# the Free Software Foundation; either version 2 of the License, or (at your
8 : //# option) any later version.
9 : //#
10 : //# This library is distributed in the hope that it will be useful, but WITHOUT
11 : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13 : //# License for more details.
14 : //#
15 : //# You should have received a copy of the GNU Library General Public License
16 : //# along with this library; if not, write to the Free Software Foundation,
17 : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
18 : //#
19 : //# Correspondence concerning AIPS++ should be addressed as follows:
20 : //# Internet email: casa-feedback@nrao.edu.
21 : //# Postal address: AIPS++ Project Office
22 : //# National Radio Astronomy Observatory
23 : //# 520 Edgemont Road
24 : //# Charlottesville, VA 22903-2475 USA
25 : //#
26 : //# $Id$
27 :
28 : #include <synthesis/Utilities/SDPosInterpolator.h>
29 :
30 : using namespace casacore;
31 : namespace casa {
32 :
33 0 : SDPosInterpolator::SDPosInterpolator(
34 : const VisBuffer& vb,
35 0 : const String& pointingDirCol_p) {
36 0 : const auto & pointingColumns = vb.msColumns().pointing();
37 0 : const auto nant = static_cast<size_t>(vb.msColumns().antenna().nrow());
38 0 : setup(pointingColumns, pointingDirCol_p, nant);
39 0 : }
40 0 : SDPosInterpolator::SDPosInterpolator(
41 : const vi::VisBuffer2& vb,
42 0 : const String& pointingDirCol_p) {
43 0 : const auto & pointingColumns = vb.subtableColumns().pointing();
44 0 : const auto nant = static_cast<size_t>(vb.subtableColumns().antenna().nrow());
45 0 : setup(pointingColumns, pointingDirCol_p, nant);
46 0 : }
47 0 : SDPosInterpolator::SDPosInterpolator(
48 : const MSPointing& pointingTable,
49 : const String& columnName,
50 0 : const size_t nant){
51 0 : MSPointingColumns pointingColumns{pointingTable};
52 0 : setup(pointingColumns, columnName, nant);
53 0 : }
54 209 : SDPosInterpolator::SDPosInterpolator(
55 : const MSPointingColumns& pointingColumns,
56 : const String& columnName,
57 209 : const size_t nant){
58 209 : setup(pointingColumns, columnName, nant);
59 209 : }
60 258 : SDPosInterpolator::SDPosInterpolator(
61 : const Vector<Vector<Double> >& time,
62 258 : const Vector<Vector<Vector<Double> > >& dir) {
63 258 : setup(time, dir);
64 258 : }
65 467 : SDPosInterpolator::~SDPosInterpolator() {}
66 :
67 258 : void SDPosInterpolator::setup(
68 : const Vector<Vector<Double> >& time,
69 : const Vector<Vector<Vector<Double> > >& dir) {
70 : //(1)get number of pointing data for each antennaID
71 258 : Int nant = time.nelements();
72 258 : Vector<uInt> nPointingData(nant);
73 258 : nPointingData = 0;
74 546 : for (Int iant = 0; iant < nant; ++iant) {
75 288 : nPointingData(iant) = time(iant).nelements();
76 : }
77 :
78 : //(2)setup spline coefficients for each antenna ID
79 258 : timePointing.resize(nant);
80 258 : dirPointing.resize(nant);
81 258 : splineCoeff.resize(nant);
82 258 : doSplineInterpolation.resize(nant);
83 258 : doSplineInterpolation = false;
84 546 : for (Int i = 0; i < nant; ++i) {
85 288 : if (nPointingData(i) < 4) continue;
86 :
87 288 : doSplineInterpolation(i) = true;
88 288 : timePointing(i).resize(nPointingData(i));
89 288 : dirPointing(i).resize(nPointingData(i));
90 288 : splineCoeff(i).resize(nPointingData(i) - 1);
91 1127129 : for (uInt j = 0; j < dirPointing(i).nelements(); ++j) {
92 1126841 : dirPointing(i)(j).resize(2);
93 : }
94 1126841 : for (uInt j = 0; j < splineCoeff(i).nelements(); ++j) {
95 1126553 : splineCoeff(i)(j).resize(2);
96 1126553 : splineCoeff(i)(j)(0).resize(4); // x
97 1126553 : splineCoeff(i)(j)(1).resize(4); // y
98 : }
99 :
100 288 : Int npoi = nPointingData(i);
101 1127129 : for (Int j = 0; j < npoi; ++j) {
102 1126841 : timePointing(i)(j) = time(i)(j);
103 3380523 : for (Int k = 0; k < 2; ++k) {
104 2253682 : dirPointing(i)(j)(k) = dir(i)(j)(k);
105 : }
106 : }
107 :
108 288 : calcSplineCoeff(timePointing(i), dirPointing(i), splineCoeff(i));
109 : }
110 :
111 : //(3) keep time range
112 258 : timeRangeStart.resize(nant);
113 258 : timeRangeEnd.resize(nant);
114 546 : for (Int iant = 0; iant < nant; ++iant) {
115 288 : timeRangeStart(iant) = timePointing(iant)(0);
116 288 : timeRangeEnd(iant) = timePointing(iant)(timePointing(iant).nelements()-1);
117 : }
118 258 : }
119 :
120 209 : void SDPosInterpolator::setup(
121 : const MSPointingColumns& act_mspc,
122 : const String& pointingDirCol_p,
123 : size_t nant) {
124 0 : auto check_col = [&](Bool isnull){
125 0 : if (isnull) {
126 0 : cerr << "No " << pointingDirCol_p << " column in POINTING table" << endl;
127 : }
128 209 : };
129 209 : std::function<Vector<Double>(Int)> get_direction;
130 :
131 : //(0)check POINTING table and set function to obtain direction data
132 209 : if (pointingDirCol_p == "TARGET") {
133 0 : get_direction = [&](Int idx){
134 0 : return act_mspc.targetMeas(idx).getAngle("rad").getValue();
135 0 : };
136 209 : } else if (pointingDirCol_p == "POINTING_OFFSET") {
137 0 : check_col(act_mspc.pointingOffsetMeasCol().isNull());
138 0 : get_direction = [&](Int idx){
139 0 : return act_mspc.pointingOffsetMeas(idx).getAngle("rad").getValue();
140 0 : };
141 209 : } else if (pointingDirCol_p == "SOURCE_OFFSET") {
142 0 : check_col(act_mspc.sourceOffsetMeasCol().isNull());
143 0 : get_direction = [&](Int idx){
144 0 : return act_mspc.sourceOffsetMeas(idx).getAngle("rad").getValue();
145 0 : };
146 209 : } else if (pointingDirCol_p == "ENCODER") {
147 0 : check_col(act_mspc.encoderMeas().isNull());
148 0 : get_direction = [&](Int idx){
149 0 : return act_mspc.encoderMeas()(idx).getAngle("rad").getValue();
150 0 : };
151 : } else {
152 25058 : get_direction = [&](Int idx){
153 50116 : return act_mspc.directionMeas(idx).getAngle("rad").getValue();
154 209 : };
155 : }
156 :
157 : //(1)get number of pointing data for each antennaID
158 209 : Vector<uInt> nPointingData(nant, 0);
159 209 : auto pointingRows = static_cast<size_t>(act_mspc.nrow());
160 25267 : for (size_t row = 0; row < pointingRows ; ++row) {
161 25058 : nPointingData(act_mspc.antennaId()(row)) += 1;
162 : }
163 :
164 : //(2)setup spline coefficients for each antenna ID that
165 : // appear in the main table (spectral data) if there
166 : // are enough number of pointing data (4 or more).
167 : // in case there exists antenna ID for which not enough
168 : // (i.e., 1, 2 or 3) pointing data are given, linear
169 : // interpolation is applied for that antenna ID as
170 : // previously done.
171 209 : timePointing.resize(nant);
172 209 : dirPointing.resize(nant);
173 209 : splineCoeff.resize(nant);
174 209 : doSplineInterpolation.resize(nant);
175 209 : doSplineInterpolation = false;
176 814 : for (uInt i = 0; i < nant; ++i) {
177 605 : if (nPointingData(i) < 4) continue;
178 :
179 605 : doSplineInterpolation(i) = true;
180 605 : timePointing(i).resize(nPointingData(i));
181 605 : dirPointing(i).resize(nPointingData(i));
182 605 : splineCoeff(i).resize(nPointingData(i) - 1);
183 25663 : for (uInt j = 0; j < dirPointing(i).nelements(); ++j) {
184 25058 : dirPointing(i)(j).resize(2);
185 : }
186 25058 : for (uInt j = 0; j < splineCoeff(i).nelements(); ++j) {
187 24453 : splineCoeff(i)(j).resize(2);
188 24453 : splineCoeff(i)(j)(0).resize(4); // x
189 24453 : splineCoeff(i)(j)(1).resize(4); // y
190 : }
191 :
192 : //set ptime array etc. need for spline calculation...
193 605 : size_t tidx = 0;
194 75559 : for (size_t j = 0; j < pointingRows; ++j) {
195 74954 : if (act_mspc.antennaId()(j) != i) continue;
196 :
197 25058 : timePointing(i)(tidx) = act_mspc.time()(j);
198 25058 : dirPointing(i)(tidx) = get_direction(j);
199 25058 : tidx++;
200 : }
201 :
202 605 : calcSplineCoeff(timePointing(i), dirPointing(i), splineCoeff(i));
203 : }
204 :
205 : //(3) keep time range
206 209 : timeRangeStart.resize(nant);
207 209 : timeRangeEnd.resize(nant);
208 814 : for (size_t iant = 0; iant < nant; ++iant) {
209 605 : timeRangeStart(iant) = timePointing(iant)(0);
210 605 : timeRangeEnd(iant) = timePointing(iant)(timePointing(iant).nelements()-1);
211 : }
212 209 : }
213 :
214 893 : void SDPosInterpolator::calcSplineCoeff(const Vector<Double>& time,
215 : const Vector<Vector<Double> >& dir,
216 : Vector<Vector<Vector<Double> > >& coeff) {
217 893 : Vector<Double> h, vx, vy;
218 893 : Vector<Double> a;
219 893 : Vector<Double> c;
220 893 : Vector<Double> alpha, beta, gamma;
221 893 : Vector<Double> wx, wy;
222 893 : Vector<Double> ux, uy;
223 :
224 893 : Int const num_data = time.nelements();
225 893 : h.resize(num_data-1);
226 893 : vx.resize(num_data-1);
227 893 : vy.resize(num_data-1);
228 893 : a.resize(num_data-1);
229 893 : c.resize(num_data-1);
230 893 : alpha.resize(num_data-1);
231 893 : beta.resize(num_data-1);
232 893 : gamma.resize(num_data-1);
233 893 : wx.resize(num_data-1);
234 893 : wy.resize(num_data-1);
235 893 : ux.resize(num_data);
236 893 : uy.resize(num_data);
237 :
238 893 : h(0) = time(1) - time(0);
239 1151006 : for (Int i = 1; i < num_data-1; ++i) {
240 1150113 : h(i) = time(i+1) - time(i);
241 1150113 : vx(i) = 6.0*((dir(i+1)(0)-dir(i)(0))/h(i) - (dir(i)(0)-dir(i-1)(0))/h(i-1));
242 1150113 : vy(i) = 6.0*((dir(i+1)(1)-dir(i)(1))/h(i) - (dir(i)(1)-dir(i-1)(1))/h(i-1));
243 1150113 : a(i) = 2.0*(time(i+1) - time(i-1));
244 1150113 : c(i) = h(i);
245 1150113 : gamma(i) = c(i);
246 : }
247 893 : alpha(2) = c(1)/a(1);
248 1149220 : for (Int i = 3; i < num_data-1; ++i) {
249 1148327 : alpha(i) = c(i-1)/(a(i-1) - alpha(i-1)*c(i-2));
250 : }
251 893 : beta(1) = a(1);
252 1149220 : for (Int i = 2; i < num_data-2; ++i) {
253 1148327 : beta(i) = c(i)/alpha(i+1);
254 : }
255 893 : beta(num_data-2) = a(num_data-2) - alpha(num_data-2) * c(num_data-3);
256 893 : wx(0) = 0.0;
257 893 : wx(1) = vx(1);
258 893 : wy(0) = 0.0;
259 893 : wy(1) = vy(1);
260 1150113 : for (Int i = 2; i < num_data-1; ++i) {
261 1149220 : wx(i) = vx(i) - alpha(i)*wx(i-1);
262 1149220 : wy(i) = vy(i) - alpha(i)*wy(i-1);
263 : }
264 893 : ux(num_data-1) = 0.0;
265 893 : uy(num_data-1) = 0.0;
266 1151006 : for (Int i = num_data-2; i >= 1; --i) {
267 1150113 : ux(i) = (wx(i) - gamma(i)*ux(i+1))/beta(i);
268 1150113 : uy(i) = (wy(i) - gamma(i)*uy(i+1))/beta(i);
269 : }
270 893 : ux(0) = 0.0;
271 893 : uy(0) = 0.0;
272 :
273 1151899 : for (Int i = 0; i < num_data-1; ++i) {
274 1151006 : coeff(i)(0)(0) = dir(i)(0);
275 1151006 : coeff(i)(1)(0) = dir(i)(1);
276 1151006 : const auto dt = time(i+1)-time(i);
277 1151006 : coeff(i)(0)(1) = (dir(i+1)(0)-dir(i)(0))/dt - dt*(2.0*ux(i)+ux(i+1))/6.0;
278 1151006 : coeff(i)(1)(1) = (dir(i+1)(1)-dir(i)(1))/dt - dt*(2.0*uy(i)+uy(i+1))/6.0;
279 1151006 : coeff(i)(0)(2) = ux(i)/2.0;
280 1151006 : coeff(i)(1)(2) = uy(i)/2.0;
281 1151006 : coeff(i)(0)(3) = (ux(i+1)-ux(i))/dt/6.0;
282 1151006 : coeff(i)(1)(3) = (uy(i+1)-uy(i))/dt/6.0;
283 : }
284 893 : }
285 :
286 24621 : MDirection SDPosInterpolator::interpolateDirectionMeasSpline(
287 : const MSPointingColumns& mspc,
288 : const Double& time,
289 : const Int& index,
290 : const Int& antid) {
291 24621 : Int lastIndex = timePointing(antid).nelements() - 1;
292 24621 : Int aindex = lastIndex;
293 351601 : for (uInt i = 0; i < timePointing(antid).nelements(); ++i) {
294 351529 : if (time < timePointing(antid)(i)) {
295 24549 : aindex = i-1;
296 24549 : break;
297 : }
298 : }
299 24621 : if (aindex < 0) aindex = 0;
300 24621 : if (lastIndex <= aindex) aindex = lastIndex - 1;
301 :
302 24621 : auto const &coeff = splineCoeff(antid)(aindex);
303 24621 : Double dt = time - timePointing(antid)(aindex);
304 24621 : Vector<Double> newdir(2);
305 : // Why don't we use Horner's method here ?
306 49242 : newdir(0) =
307 24621 : coeff(0)(0) + coeff(0)(1)*dt + coeff(0)(2)*dt*dt + coeff(0)(3)*dt*dt*dt;
308 49242 : newdir(1) =
309 24621 : coeff(1)(0) + coeff(1)(1)*dt + coeff(1)(2)*dt*dt + coeff(1)(3)*dt*dt*dt;
310 :
311 24621 : Quantity rDirLon(newdir(0), "rad");
312 24621 : Quantity rDirLat(newdir(1), "rad");
313 24621 : auto const &directionMeasColumn = mspc.directionMeasCol();
314 24621 : MDirection::Ref rf(directionMeasColumn.measDesc().getRefCode());
315 24621 : if (directionMeasColumn.measDesc().isRefCodeVariable()) {
316 0 : rf = mspc.directionMeas(index).getRef();
317 : }
318 :
319 49242 : return MDirection(rDirLon, rDirLat, rf);
320 24621 : }
321 :
322 258 : Vector<Vector<Vector<Vector<Double> > > > SDPosInterpolator::getSplineCoeff() {
323 258 : return splineCoeff;
324 : }
325 :
326 24583 : Bool SDPosInterpolator::inTimeRange(const Double& time, const Int& antid) {
327 24583 : Bool inrange = false;
328 24583 : if ((timeRangeStart(antid) <= time) && (time <= timeRangeEnd(antid))) {
329 24393 : inrange = true;
330 : }
331 24583 : return inrange;
332 : }
333 :
334 : } //#End casa namespace
|