69 const Index do_norm) {
75 const Index n_ant = antenna_dza.nelem();
81 assert(do_norm >= 0 && do_norm <= 1);
84 const Index n_ar_pol =
95 const Index n_ar_za = aresponse_za_grid.
nelem();
96 const Index pol_step = n_ar_pol > 1;
99 assert(n_ar_pol == 1 || n_ar_pol >= n_pol);
102 assert(n_ar_aa == 1);
108 const Index nfpol = n_f * n_pol;
111 H.
resize(n_ant * nfpol, n_za * nfpol);
118 Vector aresponse(n_ar_za, 0.0);
121 for (
Index ia = 0; ia < n_ant; ia++) {
122 Vector shifted_aresponse_za_grid = aresponse_za_grid;
123 shifted_aresponse_za_grid += antenna_dza[ia];
129 for (
Index f = 0; f < n_f; f++) {
131 for (
Index ip = 0; ip < n_pol; ip++) {
136 Index new_antenna = 1;
143 }
else if (f == 0 && ip == 0)
151 if (ip == 0 || pol_step)
156 gridpos(gp_za, aresponse_za_grid, aresponse_za_grid);
159 Matrix aresponse_matrix(1, n_ar_za);
165 aresponse = aresponse_matrix(0,
joker);
175 hza, aresponse, shifted_aresponse_za_grid,
za_grid);
185 const Index ii = f * n_pol + ip;
187 hrow[
Range(ii, n_za, nfpol)] = hza;
216 if( mblock_dlos.
ncols() != 2 )
217 throw runtime_error(
"For the gridded_dlos option, *mblock_dlos_grid* "
218 "must have two columns.");
222 for(
Index i=0; i<n_dlos-1 && mblock_dlos(i+1,0) > mblock_dlos(i,0); i++ ) {
226 throw runtime_error(
"For the gridded_dlos option, the number of za angles "
227 "(among dlos directions) must be >= 2.");
228 if( n_dlos % nza > 0 )
229 throw runtime_error(
"For the gridded_dlos option, the number of dlos angles "
230 "must be a product of two integers.");
231 const Index naa = n_dlos / nza;
234 for(
Index i=0; i<n_dlos; i++ ) {
235 if(i>=nza &&
abs(mblock_dlos(i,0)-mblock_dlos(i-nza,0)) > 1e-6 ) {
237 os <<
"Zenith angle of dlos " << i <<
" (0-based) differs to zenith "
238 <<
"angle of dlos " << i-nza <<
", while they need to be equal "
239 <<
"to form rectangular grid.";
240 throw std::runtime_error(os.str());
242 if(
abs(mblock_dlos(i,1)-
aa_grid[i/nza]) > 1e-6) {
244 os <<
"Azimuth angle of dlos " << i <<
" (0-based) differs to azimuth "
245 <<
"angle " << (i/nza)*nza <<
", while they need to be equal "
246 <<
"to form rectangular grid.";
247 throw std::runtime_error(os.str());
260 const Index n_ar_pol =
269 const Index n_ar_f = aresponse_f_grid.
nelem();
270 const Index n_ar_za = aresponse_za_grid.
nelem();
271 const Index n_ar_aa = aresponse_aa_grid.
nelem();
272 const Index pol_step = n_ar_pol > 1;
275 assert(n_ar_pol == 1 || n_ar_pol >= n_pol);
281 const Index nfpol = n_f * n_pol;
284 H.
resize(n_ant * nfpol, n_dlos * nfpol);
291 Matrix aresponse(n_ar_za, n_ar_aa, 0.0);
297 for (
Index ia = 0; ia < n_ant; ia++) {
302 for (
Index f = 0; f < n_f; f++) {
304 for (
Index ip = 0; ip < n_pol; ip++) {
309 Index new_antenna = 1;
316 }
else if (f == 0 && ip == 0)
324 if (ip == 0 || pol_step) {
328 gridpos(gp_za, aresponse_za_grid, aresponse_za_grid);
329 gridpos(gp_aa, aresponse_aa_grid, aresponse_aa_grid);
330 Tensor4 itw(1, n_ar_za, n_ar_aa, 8);
332 Tensor3 aresponse_matrix(1, n_ar_za, n_ar_aa);
339 aresponse = aresponse_matrix(0,
joker,
joker);
350 Vector zas = aresponse_za_grid;
354 os <<
"The zenith angle grid in *mblock_dlos_grid* is too narrow. "
355 <<
"It must be extended downwards with at least "
356 <<
za_grid[0]-zas[0] <<
" deg.";
357 throw std::runtime_error(os.str());
359 if( zas[n_ar_za-1] >
za_grid[nza-1] ) {
361 os <<
"The zenith angle grid in *mblock_dlos_grid* is too narrow. "
362 <<
"It must be extended upwards with at least "
363 << zas[n_ar_za-1] -
za_grid[nza-1] <<
" deg.";
364 throw std::runtime_error(os.str());
370 Vector aas = aresponse_aa_grid;
374 os <<
"The azimuth angle grid in *mblock_dlos_grid* is too narrow. "
375 <<
"It must be extended downwards with at least "
376 <<
aa_grid[0]-aas[0] <<
" deg.";
377 throw std::runtime_error(os.str());
379 if( aas[n_ar_aa-1] >
aa_grid[naa-1] ) {
381 os <<
"The azimuth angle grid in *mblock_dlos_grid* is too narrow. "
382 <<
"It must be extended upwards with at least "
383 << aas[n_ar_aa-1] -
aa_grid[naa-1] <<
" deg.";
384 throw std::runtime_error(os.str());
391 Tensor3 itw(n_ar_za, n_ar_za, 4);
398 for (
Index iaa = 0; iaa < n_ar_aa; iaa++) {
399 const Index a = gp_aa[iaa].idx;
400 const Index b = a + 1;
402 for (
Index iza = 0; iza < n_ar_za; iza++) {
404 const Index z = gp_za[iza].idx;
407 if( itw(iza,iaa,0) > 1e-9 ) {
408 hza[a*nza+z] += aresponse(iza,iaa) * itw(iza,iaa,0);
410 if( itw(iza,iaa,1) > 1e-9 ) {
411 hza[b*nza+z] += aresponse(iza,iaa) * itw(iza,iaa,1);
413 if( itw(iza,iaa,2) > 1e-9 ) {
414 hza[a*nza+
x] += aresponse(iza,iaa) * itw(iza,iaa,2);
416 if( itw(iza,iaa,3) > 1e-9 ) {
417 hza[b*nza+
x] += aresponse(iza,iaa) * itw(iza,iaa,3);
428 const Index ii = f * n_pol + ip;
430 hrow[
Range(ii, n_dlos, nfpol)] = hza;
467 const Index n_ar_pol =
476 const Index n_ar_f = aresponse_f_grid.
nelem();
477 const Index n_ar_za = aresponse_za_grid.
nelem();
478 const Index n_ar_aa = aresponse_aa_grid.
nelem();
479 const Index pol_step = n_ar_pol > 1;
482 assert(n_ar_pol == 1 || n_ar_pol >= n_pol);
488 const Index nfpol = n_f * n_pol;
491 H.
resize(n_ant * nfpol, n_dlos * nfpol);
498 Matrix aresponse(n_ar_za, n_ar_aa, 0.0);
504 for (
Index ia = 0; ia < n_ant; ia++) {
509 for (
Index f = 0; f < n_f; f++) {
511 for (
Index ip = 0; ip < n_pol; ip++) {
516 Index new_antenna = 1;
523 }
else if (f == 0 && ip == 0)
531 if (ip == 0 || pol_step) {
535 gridpos(gp_za, aresponse_za_grid, aresponse_za_grid);
536 gridpos(gp_aa, aresponse_aa_grid, aresponse_aa_grid);
537 Tensor4 itw(1, n_ar_za, n_ar_aa, 8);
539 Tensor3 aresponse_matrix(1, n_ar_za, n_ar_aa);
546 aresponse = aresponse_matrix(0,
joker,
joker);
555 for (
Index l = 0; l < n_dlos; l++) {
558 if (mblock_dlos.
ncols() > 1) {
559 aa += mblock_dlos(l, 1);
567 if (za < aresponse_za_grid[0] ||
568 za > aresponse_za_grid[n_ar_za - 1] ||
569 aa < aresponse_aa_grid[0] ||
570 aa > aresponse_aa_grid[n_ar_aa - 1]) {
581 interp(value, itw, aresponse, gp_za, gp_aa);
592 const Index ii = f * n_pol + ip;
594 hrow[
Range(ii, n_dlos, nfpol)] = hza;
612 assert(dx_si <= xwidth_si);
617 const Index n = (
Index)floor(2 * xwidth_si / dx_si) + 1;
620 const Numeric dd = si * xwidth_si;
635 const Index n =
x.nelem();
639 for (
Index i = 0; i < n; i++)
640 y[i] = a * exp(-0.5 *
pow((
x[i] -
x0) / si, 2.0));
652 const Index& do_norm) {
661 assert(filter_grid.
nelem() == nrp);
662 assert(fabs(
last(filter_grid) + filter_grid[0]) < 1e3);
690 const Numeric lim_high = -filter_grid[0];
694 list<Numeric> l_mixer;
697 l_mixer.push_back(fabs(
f_grid[i] -
lo));
700 l_mixer.push_back(lim_high);
705 for (list<Numeric>::iterator li = l_mixer.begin(); li != l_mixer.end();
725 row_temp, filter.
data, filter_grid, if_grid, f_mixer[i], -f_mixer[i]);
728 if (do_norm) row_temp /= row_temp.
sum();
731 for (
Index p = 0; p < n_pol; p++) {
733 for (
Index a = 0; a < n_sp; a++) {
737 a *
f_grid.nelem() * n_pol + p,
f_grid.nelem(), n_pol)] = row_temp;
751 assert(H(0, 1) == 0);
752 assert(H(1, 0) == 0);
758 assert(H(2, 0) == 0);
759 assert(H(0, 2) == 0);
767 assert(H(2, 3) == 0);
793 for (
Index i = 0; i < nch; i++) {
794 if (mm_pol[i] ==
"AMSU-H") {
797 }
else if (mm_pol[i] ==
"AMSU-V") {
800 }
else if (mm_pol[i] ==
"ISMAR-H") {
803 }
else if (mm_pol[i] ==
"ISMAR-V") {
806 }
else if (mm_pol[i] ==
"MARSS-H") {
809 }
else if (mm_pol[i] ==
"MARSS-V") {
812 }
else if (mm_pol[i] ==
"H" || mm_pol[i] ==
"V" || mm_pol[i] ==
"LHC" ||
813 mm_pol[i] ==
"RHC") {
818 os <<
"Unknown polarisation " << mm_pol[i];
819 throw std::runtime_error(os.str());
832 for (
Index i = 0; i < nch; i++) {
851 }
else if (pol[i] ==
"H") {
853 }
else if (pol[i] ==
"LHC")
856 }
else if (pol[i] ==
"RHC")
875 if (rot[i] ==
"none") {
889 if (rot[i] ==
"AMSU") {
893 }
else if (rot[i] ==
"ISMAR") {
897 }
else if (rot[i] ==
"MARSS") {
923 mult(Hc, Hpol, Hrot);
929 hrow[i0 + s] = Hc(0, s);
948 const Index n = nf * npol * nlos;
956 for (
Index ilos = 0; ilos < nlos; ilos++) {
957 const Index i2 = ilos * nf * npol;
959 for (
Index ifr = 0; ifr < nf; ifr++) {
960 const Index i3 = i2 + ifr * npol;
962 for (
Index ip = 0; ip < npol; ip++) {
963 const Index i = i3 + ip;
981 const Index& do_norm) {
985 assert(ch_response.
nelem() == 1 || ch_response.
nelem() == ch_f.
nelem());
996 const Index nin = n_sp * nin_f * n_pol;
997 const Index nout = n_sp * nout_f * n_pol;
1006 Vector weights_long(nin, 0.0);
1008 for (
Index ifr = 0; ifr < nout_f; ifr++) {
1009 const Index irp = ifr * freq_full;
1012 ch_response_f = ch_response[irp].get_numeric_grid(
GFIELD1_F_GRID);
1013 ch_response_f += ch_f[ifr];
1017 weights, ch_response[irp].
data, ch_response_f, sensor_f);
1020 if (do_norm) weights /= weights.
sum();
1024 for (
Index sp = 0; sp < n_sp; sp++) {
1025 for (
Index pol = 0; pol < n_pol; pol++) {
1027 weights_long[
Range(sp * nin_f * n_pol + pol, nin_f, n_pol)] = weights;
1030 H.
insert_row(sp * nout_f * n_pol + ifr * n_pol + pol, weights_long);
1043 const Index& ipol_1based,
1047 if (ipol_1based < 1 || ipol_1based > 10)
1048 throw runtime_error(
"Valid polarization indices are 1 to 10 (1-based).");
1055 s2p[3] = {0, 0, 0, 1};
1058 s2p[6] = {nv, 0, nv};
1059 s2p[7] = {nv, 0, -nv};
1060 s2p[8] = {nv, 0, 0, nv};
1061 s2p[9] = {nv, 0, 0, -nv};
1063 const Index l = s2p[ipol_1based - 1].
nelem();
1066 os <<
"You have selected polarization with 1-based index: " << ipol_1based
1068 <<
"but this polarization demands stokes_dim >= " << l << endl
1069 <<
"while the actual values of stokes_dim is " <<
stokes_dim;
1070 throw std::runtime_error(os.str());
1073 w[
Range(0, l)] = s2p[ipol_1based - 1];
1112 assert(fmax.
nelem() == nf);
1113 assert(i >= 0 && i < nf);
1114 assert(j >= 0 && j < nf);
1115 assert(fmin[i] <= fmin[j]);
1124 if (fmax[i] >= fmin[j]) {
1129 if (fmax[j] > fmax[i]) fmax[i] = fmax[j];
1134 Index n_behind = nf - 1 - j;
1139 if (n_behind > 0) fmin[
Range(j, n_behind)] = dummy[
Range(j + 1, n_behind)];
1144 if (n_behind > 0) fmax[
Range(j, n_behind)] = dummy[
Range(j + 1, n_behind)];
1170 os <<
"There must be at least one channel.\n"
1171 <<
"(The vector *f_backend* must have at least one element.)";
1172 throw runtime_error(os.str());
1178 os <<
"Variables *f_backend_multi* and *backend_channel_response_multi*\n"
1179 <<
"must have same number of bands for each LO.";
1180 throw runtime_error(os.str());
1184 for (
Index i = 0; i < n_chan; ++i) {
1186 const Vector& backend_f_grid =
1191 os <<
"The frequency grid for the backend channel response of\n"
1192 <<
"channel " << i <<
" is not strictly increasing.\n";
1193 os <<
"It is: " << backend_f_grid <<
"\n";
1194 throw runtime_error(os.str());
1200 out2 <<
" Original channel characteristics:\n"
1201 <<
" min nominal max (all in Hz):\n";
1208 for (
Index idx = 0; idx < n_chan; ++idx) {
1210 if (backend_filter.
nelem() >
1212 for (
Index idy = 1; idy < backend_filter.
nelem(); ++idy) {
1213 if ((backend_filter[idy] > 0) && (backend_filter[idy - 1] == 0)) {
1223 throw std::runtime_error(
1224 "No passbands found.\n"
1225 "*backend_channel_response* must be zero around the passbands.\n"
1226 "backend_channel_response.data = [0, >0, >0, 0]\n"
1227 "Borders between passbands are identified as [...0,0...]");
1234 for (
Index idx = 0; idx < n_chan; ++idx) {
1267 const Vector& backend_f_grid =
1270 if (backend_filter.
nelem() >=
1273 for (
Index idy = 1; idy < backend_filter.
nelem(); ++idy) {
1275 fmin_pb[pbIdx] =
f_backend[idx] + backend_f_grid[0];
1276 }
else if ((backend_filter[idy] > 0) &&
1277 (backend_filter[idy - 1] == 0)) {
1278 fmin_pb[pbIdx] =
f_backend[idx] + backend_f_grid[idy - 1] - delta;
1280 if ((backend_filter[idy] == 0) && (backend_filter[idy - 1] > 0)) {
1281 fmax_pb[pbIdx] =
f_backend[idx] + backend_f_grid[idy] + delta;
1283 <<
"fmin_pb " << fmin_pb[pbIdx] <<
" "
1285 <<
"fmax_pb " << fmax_pb[pbIdx] <<
" "
1286 <<
"diff " << fmax_pb[pbIdx] - fmin_pb[pbIdx] <<
"\n";
1293 fmin_pb[pbIdx] =
f_backend[idx] + backend_f_grid[0] - delta;
1295 backend_f_grid[backend_f_grid.
nelem() - 1] +
1298 <<
"fmin_pb " << fmin_pb[pbIdx] <<
" "
1299 <<
"f_backend" <<
f_backend[pbIdx] <<
" "
1300 <<
"fmax_pb " << fmax_pb[pbIdx] <<
"\n";
1324 out2 <<
" resize numPb " << numPB <<
"\n";
1325 for (
Index idx = 0; idx < numPB; ++idx) {
1326 fmin[idx] = fmin_pb[isorted[idx]];
1327 fmax[idx] = fmax_pb[isorted[idx]];
1336 for (
Index i = 0; i < fmin.
nelem() - 1; ++i) {
1337 bool continue_checking =
true;
1341 while (continue_checking && i < fmin.
nelem() - 1) {
1349 out2 <<
" New channel characteristics:\n"
1350 <<
" min max (all in Hz):\n";
1352 out2 <<
" " << fmin[i] <<
" " << fmax[i] <<
"\n";
1370 assert(h.
nelem() == ng);
1371 assert(f.
nelem() == nf);
1378 Numeric xfmax = x_f_in[nf - 1];
1382 Index xg_reversed = 0;
1385 x_g = x_g_in[
Range(ng - 1, ng, -1)];
1391 assert(x_g[0] <= xfmin);
1392 assert(x_g[ng - 1] >= xfmax);
1395 const Numeric df = xfmax - xfmin;
1398 for (
Index i = 0; i < nf; i++) {
1399 x_f[i] = (x_f_in[i] - xfmin) / df;
1401 for (
Index i = 0; i < ng; i++) {
1402 x_g[i] = (x_g[i] - xfmin) / df;
1414 for (
Index it = 0; it < nf; it++) {
1415 l_x.push_back(x_f[it]);
1417 for (
Index it = 0; it < ng; it++) {
1418 if (x_g[it] > xfmin && x_g[it] < xfmax) {
1419 l_x.push_back(x_g[it]);
1425 Vector x_ref(l_x.size());
1427 for (list<Numeric>::iterator li = l_x.begin(); li != l_x.end(); li++) {
1439 for (
Index i = 0; i < x_ref.
nelem() - 1; i++) {
1442 while (x_g[i_g + 1] <= x_ref[i]) {
1445 while (x_f[i_f + 1] <= x_ref[i]) {
1451 if (x_ref[i] >= xfmin && x_ref[i] < xfmax) {
1453 dx = (x_f[i_f + 1] - x_f[i_f]) * (x_g[i_g + 1] - x_g[i_g]);
1456 a0 = (f[i_f] - f[i_f + 1]) / 3.0;
1457 b0 = (-f[i_f] * (x_g[i_g + 1] + x_f[i_f + 1]) +
1458 f[i_f + 1] * (x_g[i_g + 1] + x_f[i_f])) /
1460 c0 = x_g[i_g + 1] * (f[i_f] * x_f[i_f + 1] - f[i_f + 1] * x_f[i_f]);
1463 b1 = (f[i_f] * (x_g[i_g] + x_f[i_f + 1]) -
1464 f[i_f + 1] * (x_g[i_g] + x_f[i_f])) /
1466 c1 = x_g[i_g] * (-f[i_f] * x_f[i_f + 1] + f[i_f + 1] * x_f[i_f]);
1468 x1 = x_ref[i + 1] - x_ref[i];
1473 x2 =
x1 * (2 * x_ref[i] +
x1);
1474 x3 =
x1 * (3 * x_ref[i] * (x_ref[i] +
x1) +
x1 *
x1);
1478 h[i_g] += df * (a0 *
x3 +
b0 *
x2 + c0 *
x1) /
dx;
1492 if (
min(f) >= 0 &&
min(h) < -1e-15)
1493 throw runtime_error(
1494 "Significant negative response value obtained, "
1495 "despite sensor reponse is strictly positive. This "
1496 "indicates numerical problems. Is there any very "
1497 "small spacing of the sensor response grid?"
1498 "Please, send a report to Patrick if you see this!");
1512 assert(h.
nelem() == ng);
1513 assert(limit1 <= limit2);
1517 Index xg_reversed = 0;
1520 x_g = x_g_in[
Range(ng - 1, ng, -1)];
1526 assert(x_g[0] <= limit1);
1527 assert(x_g[ng - 1] >= limit2);
1531 if (limit1 == limit2) {
1536 else if (limit1 == x_g[0] && limit2 == x_g[ng - 1]) {
1537 h[0] = (x_g[1] - x_g[0]) / 2.0;
1538 for (
Index i = 1; i < ng - 1; i++) {
1539 h[i] = (x_g[i + 1] - x_g[i - 1]) / 2.0;
1541 h[ng - 1] = (x_g[ng - 1] - x_g[ng - 2]) / 2.0;
1549 for (
Index i = 0; i < ng; i++) {
1550 bool inside =
false;
1553 if (limit1 < x_g[1]) {
1556 x2 =
min(limit2, x_g[1]);
1558 }
else if (i == ng - 1) {
1559 if (limit2 > x_g[ng - 2]) {
1561 x1 =
max(limit1, x_g[ng - 2]);
1565 if ((limit1 < x_g[i + 1] && limit2 > x_g[i - 1]) ||
1566 (limit2 > x_g[i - 1] && limit1 < x_g[i + 1])) {
1568 x1 =
max(limit1, x_g[i - 1]);
1569 x2 =
min(limit2, x_g[i + 1]);
1579 const Numeric r = 1.0 / (x_g[i] - x_g[i - 1]);
1580 const Numeric y1 = r * (
x1 - x_g[i - 1]);
1583 h[i] = 0.5 *
dx * (y1 + y2);
1590 const Numeric r = 1.0 / (x_g[i + 1] - x_g[i]);
1591 const Numeric y2 = r * (x_g[i + 1] -
x2);
1594 h[i] += 0.5 *
dx * (y1 + y2);
1616 assert(x_g[0] <= x_f[0]);
1618 assert(
x1 >= x_f[0]);
1619 assert(
x2 >= x_f[0]);
1631 interp(f1, itw1, f, gp1f);
1640 interp(f2, itw2, f, gp2f);
1644 h[gp1g[0].idx] += f1 * gp1g[0].fd[1];
1645 h[gp1g[0].idx + 1] += f1 * gp1g[0].fd[0];
1646 h[gp2g[0].idx] += f2 * gp2g[0].fd[1];
1647 h[gp2g[0].idx + 1] += f2 * gp2g[0].fd[0];