76 const Index& n_za_grid,
81 if (dx_si > xwidth_si)
82 throw runtime_error(
"It is demanded that dx_si <= xwidth_si.");
87 antenna_dlos(0, 0) = 0.0;
99 cumtrapz[
i] = cumtrapz[
i - 1] + r.
data(0, 0,
i - 1, 0) + r.
data(0, 0,
i, 0);
104 nlinspace(csp, cumtrapz[0], cumtrapz[nr - 1], n_za_grid);
107 mblock_dlos_grid.
resize(n_za_grid, 1);
112 interp(mblock_dlos_grid(
joker, 0), itw, r_za_grid, gp);
123 const Index& atmosphere_dim,
133 if (sensor_pos.
ncols() != atmosphere_dim)
135 "The number of columns of sensor_pos must be " 136 "equal to the atmospheric dimensionality.");
137 if (atmosphere_dim <= 2 && sensor_los.
ncols() != 1)
138 throw runtime_error(
"For 1D and 2D, sensor_los shall have one column.");
139 if (atmosphere_dim == 3 && sensor_los.
ncols() != 2)
140 throw runtime_error(
"For 3D, sensor_los shall have two columns.");
141 if (sensor_los.
nrows() != nmblock) {
143 os <<
"The number of rows of sensor_pos and sensor_los must be " 144 <<
"identical, but sensor_pos has " << nmblock <<
" rows,\n" 145 <<
"while sensor_los has " << sensor_los.
nrows() <<
" rows.";
146 throw runtime_error(os.
str());
148 if (antenna_dim == 2 && atmosphere_dim < 3) {
149 throw runtime_error(
"If *antenna_dim* is 2, *atmosphere_dim* must be 3.");
151 if (antenna_dlos.
empty())
throw runtime_error(
"*antenna_dlos* is empty.");
152 if (antenna_dlos.
ncols() < 1 || antenna_dlos.
ncols() > 2)
153 throw runtime_error(
"*antenna_dlos* must have one or 2 columns.");
154 if (atmosphere_dim < 3 && antenna_dlos.
ncols() == 2)
156 "*antenna_dlos* can only have two columns for 3D atmosphers.");
159 const Matrix pos_copy = sensor_pos;
160 const Matrix los_copy = sensor_los;
162 sensor_pos.
resize(nmblock * nant, pos_copy.
ncols());
163 sensor_los.
resize(nmblock * nant, los_copy.
ncols());
165 for (
Index ib = 0; ib < nmblock; ib++) {
166 for (
Index ia = 0; ia < nant; ia++) {
167 const Index i = ib * nant + ia;
172 sensor_los(i, 0) += antenna_dlos(ia, 0);
173 if (antenna_dlos.
ncols() == 2) sensor_los(i, 1) += antenna_dlos(ia, 1);
178 AntennaOff(antenna_dim, mblock_dlos_grid, verbosity);
180 antenna_dlos.
resize(1, 1);
192 out2 <<
" Sets the antenna dimensionality to 1.\n";
195 out2 <<
" Sets *mblock_dlos_grid* to have one row with value 0.\n";
196 mblock_dlos_grid.
resize(1, 1);
197 mblock_dlos_grid = 0;
209 if (dx_si > xwidth_si)
210 throw runtime_error(
"It is demanded that dx_si <= xwidth_si.");
238 for (
Index z = 0; z <
n; z++) {
239 for (
Index b = 0; b <
n; b++) {
241 a * exp(-0.5 *
pow(
sqrt(x[z] * x[z] + x[b] * x[b]) / si, 2.0));
263 if (dx_si > xwidth_si)
264 throw runtime_error(
"It is demanded that dx_si <= xwidth_si.");
271 x, y, 0, fwhm, (fstop / fstart) * xwidth_si, dx_si);
299 for (
Index z = 0; z <
n; z++) {
300 for (
Index b = 0; b <
n; b++) {
302 a * exp(-0.5 *
pow(
sqrt(x[z] * x[z] + x[b] * x[b]) / si, 2.0));
312 for (
Index i = 0;
i < nf - 1;
i++) {
327 r[0].set_name(
"Backend channel response function");
331 r[0].set_grid_name(0,
"Frequency");
332 x[1] = resolution / 2.0;
337 r[0].data[0] = 1 / resolution;
338 r[0].data[1] = r[0].data[0];
352 os <<
"*xwidth_si* and *dx_si* must have one element or the same number of\n";
353 os <<
"elements as *fwhm*.";
354 throw std::runtime_error(os.str());
361 Numeric this_xwidth_si = xwidth_si[0];
363 for (
Index i = 0;
i < nchannels;
i++) {
364 if (xwidth_si.
nelem() > 1) this_xwidth_si = xwidth_si[
i];
366 if (dx_si.
nelem() > 1) this_dx_si = dx_si[
i];
370 r[
i].set_name(
"Backend channel response function");
372 r[
i].set_grid_name(0,
"Frequency");
377 for (
Index j = 0; j <
n; j++) r[i].
data[j] = y[j];
400 for (
Index s = 0; s < f_backend[
i].
nelem(); ++s) ++n_chan;
407 os <<
"There must be at least one channel.\n" 408 <<
"(The vector *lo* must have at least one element.)";
409 throw runtime_error(os.
str());
414 (backend_channel_response.
nelem() != lo.
nelem())) {
416 os <<
"Variables *lo_multi*, *f_backend_multi* and *backend_channel_response_multi*\n" 417 <<
"must have same number of elements (number of LOs).";
418 throw runtime_error(os.
str());
423 if (f_backend[
i].
nelem() != backend_channel_response[
i].
nelem()) {
425 os <<
"Variables *f_backend_multi* and *backend_channel_response_multi*\n" 426 <<
"must have same number of bands for each LO.";
427 throw runtime_error(os.
str());
436 Vector f_backend_flat(2 * n_chan);
447 const Numeric this_f_backend = f_backend[
i][s];
450 f_backend_flat[j] = this_f_backend;
451 backend_channel_response_flat[j] = this_grid;
455 Numeric offset = this_f_backend - lo[
i];
457 f_backend_flat[j] = f_image;
458 backend_channel_response_flat[j] = this_grid;
464 Vector fmin(2 * n_chan), fmax(2 * n_chan);
476 backend_channel_response_flat,
484 for (
Index i = 0;
i < fmin.nelem(); ++
i) {
489 const Numeric npf = ceil(bw / spacing);
499 out3 <<
" Band range " << i <<
": " << grid <<
"\n";
502 f_grid_array.reserve(f_grid_array.
nelem() + npi);
503 for (
Index s = 0; s < npi; ++s) f_grid_array.push_back(grid[s]);
507 f_grid = f_grid_array;
509 out2 <<
" Total number of frequencies in f_grid: " << f_grid.
nelem() <<
"\n";
523 const Vector& verbosityVect,
527 Index numFpoints = 0;
529 for (
Index idx = 0; idx < backend_channel_response_multi.
nelem(); ++idx) {
530 for (
Index idy = 0; idy < backend_channel_response_multi[idx].
nelem();
532 numFpoints += backend_channel_response_multi[idx][idy].get_grid_size(0);
536 Index numChan = backend_channel_response_multi.
nelem();
543 os <<
"There must be at least one channel.\n" 544 <<
"(The vector *lo* must have at least one element.)";
545 throw runtime_error(os.
str());
553 Vector f_backend_flat(numChan);
558 Vector FminVerbosityVect(numFpoints);
559 Vector FmaxVerbosityVect(numFpoints);
560 Vector VerbosityValVect(numFpoints);
561 Index VerbVectIdx = 0;
564 for (
Index ii = 0; ii < f_backend_multi[
i].
nelem(); ++ii) {
565 const GriddedField1& this_grid = backend_channel_response_multi[
i][ii];
566 const Numeric this_f_backend = f_backend_multi[
i][ii];
568 f_backend_flat[
i] = this_f_backend;
569 backend_channel_response_nonflat[
i] = this_grid;
571 idy < backend_channel_response_multi[
i][ii].get_grid_size(0);
573 if ((backend_channel_response_multi[
i][ii].
data[idy - 1] == 0) &&
574 (backend_channel_response_multi[
i][ii].data[idy] > 0)) {
575 FminVerbosityVect[VerbVectIdx] =
576 f_backend_multi[
i][ii] +
577 backend_channel_response_multi[
i][ii].get_numeric_grid(0)[idy];
578 VerbosityValVect[VerbVectIdx] = verbosityVect[
i];
580 if ((backend_channel_response_multi[
i][ii].
data[idy - 1] > 0) &&
581 (backend_channel_response_multi[
i][ii].
data[idy] == 0)) {
582 FmaxVerbosityVect[VerbVectIdx] =
583 f_backend_multi[
i][ii] +
584 backend_channel_response_multi[
i][ii].get_numeric_grid(0)[idy];
605 backend_channel_response_nonflat,
616 Numeric npf = ceil(bw / spacing);
620 if (verbosityVect.
nelem() > 0) {
622 for (
Index ii = 0; ii < VerbVectIdx; ++ii) {
623 if ((FminVerbosityVect[ii] >= fmin[
i]) &&
624 (FmaxVerbosityVect[ii] <= fmax[
i])) {
628 if (VerbosityValVect[ii] < VerbosityValVect[verbIdx]) {
634 if (spacing > VerbosityValVect[verbIdx]) {
636 bw / VerbosityValVect[verbIdx]);
638 npf = ceil(bw / spacing);
652 out3 <<
" Band range " << i <<
": " << grid <<
"\n";
655 f_grid_array.reserve(f_grid_array.
nelem() + npi);
656 for (
Index s = 0; s < npi; ++s) f_grid_array.push_back(grid[s]);
660 f_grid = f_grid_array;
662 out2 <<
" Total number of frequencies in f_grid: " << f_grid.
nelem() <<
"\n";
682 os <<
"Expected positive spacing. Found spacing to be: " << spacing <<
"\n";
683 throw runtime_error(os.
str());
695 fmin, fmax, f_backend, backend_channel_response, delta, verbosity);
704 for (
Index i = 0;
i < fmin.nelem(); ++
i) {
709 const Numeric npf = ceil(bw / spacing);
719 out3 <<
" Band range " << i <<
": " << grid <<
"\n";
722 f_grid_array.reserve(f_grid_array.
nelem() + npi);
723 for (
Index s = 0; s < npi; ++s) f_grid_array.push_back(grid[s]);
727 f_grid = f_grid_array;
729 out2 <<
" Total number of frequencies in f_grid: " << f_grid.
nelem() <<
"\n";
744 const Vector& freq_spacing,
746 const Numeric& freq_merge_threshold,
755 if (freq_spacing.
nelem() != 1 && freq_spacing.
nelem() != nchannels)
756 throw std::runtime_error(
757 "Length of *freq_spacing* vector must be either 1 or correspond\n" 758 "to the number of rows in *met_mm_backend*.");
760 if (freq_number.
nelem() != 1 && freq_number.
nelem() != nchannels)
761 throw std::runtime_error(
762 "Length of *freq_number* array must be either 1 or correspond\n" 763 "to the number of rows in *met_mm_backend*.");
765 if (freq_merge_threshold <= 0)
766 throw std::runtime_error(
"The *freq_merge_threshold* must be > 0.\n");
768 if (freq_merge_threshold > 100.)
769 throw std::runtime_error(
770 "The *freq_merge_threshold* is only meant to merge frequencies\n" 771 "that are basically identical and only differ slightly due to\n" 772 "numerical inaccuracies. Setting it to >100Hz is not reasonable.");
778 f_backend.
resize(nchannels);
780 for (
Index ch = 0; ch < nchannels; ch++) {
781 const Numeric lo = mm_back(ch, 0);
782 const Numeric offset1 = mm_back(ch, 1);
783 const Numeric offset2 = mm_back(ch, 2);
784 const Numeric bandwidth = mm_back(ch, 3);
786 const Index this_fnumber =
787 (freq_number.
nelem() == 1) ? freq_number[0] : freq_number[ch];
789 (freq_spacing.
nelem() == 1) ? freq_spacing[0] : freq_spacing[ch];
791 if (this_spacing <= 0)
792 throw std::runtime_error(
"*freq_spacing must be > 0.");
794 if (this_fnumber == 0) {
796 os <<
"*freq_number* must be -1 or greater zero:" 797 <<
"freq_number[" << ch <<
"] = " << this_fnumber;
798 std::runtime_error(os.
str());
803 1 + ((
Index)(offset1 > 0)) + (2 * (
Index)(offset2 > 0));
806 Index nfperband = this_fnumber;
808 if (this_fnumber == -1 ||
809 bandwidth / (
Numeric)this_fnumber > this_spacing) {
810 nfperband = (
Index)ceil(bandwidth / this_spacing);
814 nf_per_channel[ch] = npassb * nfperband;
821 for (
Index b = 0; b < npassb; b++) {
825 fc += (-1 + 2 * (
Numeric)b) * offset1;
826 }
else if (npassb == 4) {
832 if (b == 0 || b == 2) {
840 for (
Index f_index = 0; f_index < nfperband; f_index++) {
841 const Numeric fnew = fc - bandwidth / 2 + (0.5 + (
Numeric)f_index) * df;
845 for (
size_t f_try = 0; f_try < f_grid_unsorted.size(); f_try++) {
846 if (
abs(fnew - f_grid_unsorted[f_try]) < freq_merge_threshold) {
848 index_in_unsorted.push_back(f_try);
853 f_grid_unsorted.push_back(fnew);
854 index_in_unsorted.push_back(f_grid_unsorted.size() - 1);
861 const size_t nf = f_grid_unsorted.size();
866 sorted_indices.resize(nf);
867 for (
size_t i = 0;
i < nf;
i++) {
868 sorted_indices[
i] =
i;
872 std::sort(sorted_indices.begin(),
873 sorted_indices.end(),
877 for (
size_t i = 0;
i < nf;
i++) {
878 move2index[sorted_indices[
i]] =
i;
884 for (
size_t f_index = 0; f_index < nf; f_index++) {
885 f_grid[move2index[f_index]] = f_grid_unsorted[f_index];
889 channel2fgrid_indexes.resize(nchannels);
890 channel2fgrid_weights.resize(nchannels);
892 for (
Index ch = 0; ch < nchannels; ch++) {
893 channel2fgrid_indexes[ch].resize(nf_per_channel[ch]);
894 channel2fgrid_weights[ch].resize(nf_per_channel[ch]);
896 for (
Index j = 0; j < nf_per_channel[ch]; j++) {
897 channel2fgrid_indexes[ch][j] = move2index[index_in_unsorted[
i]];
898 channel2fgrid_weights[ch][j] = 1 / (
Numeric)nf_per_channel[ch];
916 w = spacing * ceil(width / spacing);
918 w = spacing * (0.5 + floor(width / spacing));
924 Matrix dlos_try(l * l, 2, 0);
926 const Numeric c = width * width;
931 for (
Index j = 0; j < l; j++) {
932 if (a + x[j] * x[j] <= c) {
933 dlos_try(n_in, 0) = x[
i];
934 dlos_try(n_in, 1) = x[j];
940 mblock_dlos_grid = dlos_try(
Range(0, n_in),
joker);
956 w = spacing * ceil(za_width / spacing);
958 w = spacing * (0.5 + floor(za_width / spacing));
965 w = spacing * ceil(aa_width / spacing);
967 w = spacing * (0.5 + floor(aa_width / spacing));
974 mblock_dlos_grid.
resize(nza * naa, 2);
978 for (
Index a = 0; a < naa; a++) {
979 for (
Index z = 0; z < nza; z++) {
980 mblock_dlos_grid(n, 0) = za[z];
981 mblock_dlos_grid(n, 1) = aa[a];
991 Vector& sensor_response_f,
993 Matrix& sensor_response_dlos,
994 Matrix& sensor_response_dlos_grid,
995 const Vector& sensor_response_f_grid,
997 const Index& atmosphere_dim,
998 const Index& antenna_dim,
999 const Matrix& antenna_dlos,
1001 const Index& sensor_norm,
1012 const Index nf = sensor_response_f_grid.
nelem();
1013 const Index npol = sensor_response_pol_grid.
nelem();
1014 const Index nlos = sensor_response_dlos_grid.
nrows();
1015 const Index nin = nf * npol * nlos;
1019 bool error_found =
false;
1022 if (sensor_response_f.
nelem() != nin) {
1023 os <<
"Inconsistency in size between *sensor_response_f* and the sensor\n" 1024 <<
"grid variables (sensor_response_f_grid etc.).\n";
1027 if (sensor_response.
nrows() != nin) {
1028 os <<
"The sensor block response matrix *sensor_response* does not have\n" 1029 <<
"right size compared to the sensor grid variables\n" 1030 <<
"(sensor_response_f_grid etc.).\n";
1035 if (antenna_dim == 2 && atmosphere_dim < 3) {
1036 os <<
"If *antenna_dim* is 2, *atmosphere_dim* must be 3.\n";
1041 if (antenna_dlos.
empty())
throw runtime_error(
"*antenna_dlos* is empty.");
1042 if (antenna_dlos.
ncols() < 1 || antenna_dlos.
ncols() > 2)
1043 throw runtime_error(
"*antenna_dlos* must have one or 2 columns.");
1044 if (atmosphere_dim < 3 && antenna_dlos.
ncols() == 2)
1045 throw runtime_error(
1046 "*antenna_dlos* can only have two columns for 3D atmosphers.");
1052 const Index lpolgrid =
1055 if (lpolgrid != 1 && lpolgrid != npol) {
1056 os <<
"The number of polarisation in *antenna_response* must be 1 or be\n" 1057 <<
"equal to the number of polarisations used (determined by\n" 1058 <<
"*stokes_dim* or *instrument_pol*).\n";
1072 f_dlow =
min(sensor_response_f_grid) - aresponse_f_grid[0];
1073 f_dhigh =
last(aresponse_f_grid) -
max(sensor_response_f_grid);
1075 if (aresponse_f_grid.
nelem() > 1) {
1077 os <<
"The frequency grid of *antenna_response is too narrow. It must\n" 1078 <<
"cover all considered frequencies (*f_grid*), if the length\n" 1079 <<
"is > 1. The grid needs to be expanded with " << -f_dlow
1081 <<
"the lower end.\n";
1085 os <<
"The frequency grid of *antenna_response is too narrow. It must\n" 1086 <<
"cover all considered frequencies (*f_grid*), if the length\n" 1087 <<
"is > 1. The grid needs to be expanded with " << -f_dhigh
1089 <<
"the upper end.\n";
1101 if (aresponse_za_grid.
nelem() < 2) {
1102 os <<
"The zenith angle grid of *antenna_response* must have >= 2 values.\n";
1111 if (antenna_dim == 1) {
1112 if (aresponse_aa_grid.
nelem() != 1) {
1113 os <<
"The azimuthal dimension of *antenna_response* must be 1 if\n" 1114 <<
"*antenna_dim* equals 1.\n";
1120 if (aresponse_za_grid.
nelem() < 2) {
1121 os <<
"The zenith angle grid of *antenna_response* must have >= 2\n" 1128 if (antenna_dim == 1) {
1131 os <<
"For 1D antennas, the zenith angles in *sensor_response_dlos_grid*\n" 1132 <<
"must be sorted, either in increasing or decreasing order.\n" 1133 <<
"The original problem is probably found in *mblock_dlos_grid*.\n";
1142 za_dlow = antenna_dlos(0, 0) + aresponse_za_grid[0] -
1143 min(sensor_response_dlos_grid(
joker, 0));
1144 za_dhigh =
max(sensor_response_dlos_grid(
joker, 0)) -
1148 os <<
"The WSV zenith angle part of *sensor_response_dlos_grid* is too narrow.\n" 1149 <<
"It should be expanded with " << -za_dlow
1150 <<
" deg in the lower end.\n" 1151 <<
"This change should be probably applied to *mblock_dlos_grid*.\n";
1155 os <<
"The WSV zenith angle part of *sensor_response_dlos_grid* is too narrow.\n" 1156 <<
"It should be expanded with " << -za_dhigh
1157 <<
" deg in the upper end.\n" 1158 <<
"This change should be probably applied to *mblock_dlos_grid*.\n";
1169 if (error_found)
throw runtime_error(os.
str());
1178 if (antenna_dim == 1)
1181 antenna_dlos(
joker, 0),
1183 sensor_response_dlos_grid(
joker, 0),
1184 sensor_response_f_grid,
1189 if (option_2d ==
"interp_response" ) {
1194 sensor_response_dlos_grid,
1195 sensor_response_f_grid,
1198 else if (option_2d ==
"gridded_dlos" ) {
1203 sensor_response_dlos_grid,
1204 sensor_response_f_grid,
1209 throw runtime_error(
"Unrecognised choice for *option_2d*." );
1216 Sparse htmp = sensor_response;
1218 mult(sensor_response, hantenna, htmp);
1221 out3 <<
" Size of *sensor_response*: " << sensor_response.
nrows() <<
"x" 1222 << sensor_response.
ncols() <<
"\n";
1225 sensor_response_dlos_grid = antenna_dlos;
1229 sensor_response_pol,
1230 sensor_response_dlos,
1231 sensor_response_f_grid,
1232 sensor_response_pol_grid,
1233 sensor_response_dlos_grid);
1241 Vector& sensor_response_f,
1243 Matrix& sensor_response_dlos,
1244 Vector& sensor_response_f_grid,
1246 const Matrix& sensor_response_dlos_grid,
1249 const Index& sensor_norm,
1254 const Index nf = sensor_response_f_grid.
nelem();
1255 const Index npol = sensor_response_pol_grid.
nelem();
1256 const Index nlos = sensor_response_dlos_grid.
nrows();
1257 const Index nin = nf * npol * nlos;
1261 bool error_found =
false;
1264 if (sensor_response_f.
nelem() != nin) {
1265 os <<
"Inconsistency in size between *sensor_response_f* and the sensor\n" 1266 <<
"grid variables (sensor_response_f_grid etc.).\n";
1269 if (sensor_response.
nrows() != nin) {
1270 os <<
"The sensor block response matrix *sensor_response* does not have\n" 1271 <<
"right size compared to the sensor grid variables\n" 1272 <<
"(sensor_response_f_grid etc.).\n";
1277 if (
min(f_backend) <
min(sensor_response_f_grid)) {
1278 os <<
"At least one value in *f_backend* (" <<
min(f_backend)
1279 <<
") below range\ncovered by *sensor_response_f_grid* (" 1280 <<
min(sensor_response_f_grid) <<
").\n";
1283 if (
max(f_backend) >
max(sensor_response_f_grid)) {
1284 os <<
"At least one value in *f_backend* (" <<
max(f_backend)
1285 <<
") above range\ncovered by *sensor_response_f_grid* (" 1286 <<
max(sensor_response_f_grid) <<
").\n";
1292 const Index nrp = backend_channel_response.
nelem();
1294 if (nrp != 1 && nrp != f_backend.
nelem()) {
1295 os <<
"The WSV *backend_channel_response* must have 1 or n elements,\n" 1296 <<
"where n is the length of *f_backend*.\n";
1302 if (error_found)
throw runtime_error(os.
str());
1307 Index freq_full = nrp > 1;
1309 const Index irp =
i * freq_full;
1313 if (bchr_f_grid.
nelem() != backend_channel_response[irp].data.
nelem()) {
1314 os <<
"Mismatch in size of grid and data in element " <<
i 1315 <<
"\nof *sideband_response*.\n";
1320 os <<
"The frequency grid of element " << irp
1321 <<
" in *backend_channel_response*\nis not strictly increasing.\n";
1328 Numeric f1 = f_backend[
i] + bchr_f_grid[0] -
min(sensor_response_f_grid);
1330 (
max(sensor_response_f_grid) - f_backend[
i]) -
last(bchr_f_grid);
1332 f_dlow =
min(f_dlow, f1);
1333 f_dhigh =
min(f_dhigh, f2);
1337 os <<
"The WSV *sensor_response_f_grid* is too narrow. It should be\n" 1338 <<
"expanded with " << -f_dlow <<
" Hz in the lower end. This change\n" 1339 <<
"should be applied to either *f_grid* or the sensor part in\n" 1340 <<
"front of *sensor_responseBackend*.\n";
1344 os <<
"The WSV *sensor_response_f_grid* is too narrow. It should be\n" 1345 <<
"expanded with " << -f_dhigh <<
" Hz in the higher end. This change\n" 1346 <<
"should be applied to either *f_grid* or the sensor part in\n" 1347 <<
"front of *sensor_responseBackend*.\n";
1353 if (error_found)
throw runtime_error(os.
str());
1361 backend_channel_response,
1362 sensor_response_f_grid,
1370 Sparse htmp = sensor_response;
1371 sensor_response.
resize(hbackend.nrows(), htmp.
ncols());
1372 mult(sensor_response, hbackend, htmp);
1375 out3 <<
" Size of *sensor_response*: " << sensor_response.
nrows() <<
"x" 1376 << sensor_response.
ncols() <<
"\n";
1379 sensor_response_f_grid = f_backend;
1383 sensor_response_pol,
1384 sensor_response_dlos,
1385 sensor_response_f_grid,
1386 sensor_response_pol_grid,
1387 sensor_response_dlos_grid);
1395 Vector& sensor_response_f,
1397 Matrix& sensor_response_dlos,
1398 Vector& sensor_response_f_grid,
1400 const Matrix& sensor_response_dlos_grid,
1403 const Index& sensor_norm,
1409 Sparse H1 = sensor_response, H2 = sensor_response;
1412 Vector f_backend_shifted;
1413 Vector fdummy = sensor_response_f, fdummy_grid = sensor_response_f_grid;
1416 f_backend_shifted = f_backend;
1417 f_backend_shifted += df1;
1421 sensor_response_pol,
1422 sensor_response_dlos,
1424 sensor_response_pol_grid,
1425 sensor_response_dlos_grid,
1427 backend_channel_response,
1431 f_backend_shifted = f_backend;
1432 f_backend_shifted += df2;
1436 sensor_response_pol,
1437 sensor_response_dlos,
1438 sensor_response_f_grid,
1439 sensor_response_pol_grid,
1440 sensor_response_dlos_grid,
1442 backend_channel_response,
1447 sub(sensor_response, H2, H1);
1450 sensor_response_f_grid = f_backend;
1454 sensor_response_pol,
1455 sensor_response_dlos,
1456 sensor_response_f_grid,
1457 sensor_response_pol_grid,
1458 sensor_response_dlos_grid);
1465 Vector& sensor_response_f,
1467 Matrix& sensor_response_dlos,
1468 Matrix& sensor_response_dlos_grid,
1469 const Vector& sensor_response_f_grid,
1476 if (sensor_response_dlos_grid.
nrows() != 2)
1477 throw runtime_error(
1478 "This method requires that the number of observation directions is 2.");
1480 if (sensor_response_pol_grid.
nelem() != 1)
1481 throw runtime_error(
1482 "This method handles (so far) only single polarisation cases.");
1487 Sparse Hbswitch(n, 2 * n);
1502 Sparse Htmp = sensor_response;
1504 mult(sensor_response, Hbswitch, Htmp);
1507 out3 <<
" Size of *sensor_response*: " << sensor_response.
nrows() <<
"x" 1508 << sensor_response.
ncols() <<
"\n";
1511 const Vector zaaa = sensor_response_dlos_grid(1,
joker);
1512 sensor_response_dlos_grid.
resize(1, zaaa.
nelem());
1513 sensor_response_dlos_grid(0,
joker) = zaaa;
1517 sensor_response_pol,
1518 sensor_response_dlos,
1519 sensor_response_f_grid,
1520 sensor_response_pol_grid,
1521 sensor_response_dlos_grid);
1529 Vector& sensor_response_f,
1531 Matrix& sensor_response_dlos,
1532 Vector& sensor_response_f_grid,
1534 const Matrix& sensor_response_dlos_grid,
1538 if (sensor_response_dlos_grid.
nrows() != 1)
1539 throw runtime_error(
1540 "This method requires that the number of observation directions is 1.");
1542 if (sensor_response_pol_grid.
nelem() != 1)
1543 throw runtime_error(
1544 "This method handles (so far) only single polarisation cases.");
1547 const Index n2 = n / 2;
1549 if (sensor_response.
nrows() !=
n)
1550 throw runtime_error(
1551 "Assumptions of method are not fulfilled, " 1552 "considering number of rows in *sensor_response* " 1553 "and length of *sensor_response_f_grid*.");
1556 throw runtime_error(
1557 "There is an odd number of total frequencies, " 1558 "which is not consistent with the assumptions of " 1577 Sparse Htmp = sensor_response;
1579 mult(sensor_response, Hbswitch, Htmp);
1582 out3 <<
" Size of *sensor_response*: " << sensor_response.
nrows() <<
"x" 1583 << sensor_response.
ncols() <<
"\n";
1586 const Vector f = sensor_response_f_grid;
1587 sensor_response_f_grid.
resize(n2);
1588 sensor_response_f_grid = f[
Range(n2, n2)];
1592 sensor_response_pol,
1593 sensor_response_dlos,
1594 sensor_response_f_grid,
1595 sensor_response_pol_grid,
1596 sensor_response_dlos_grid);
1603 Vector& sensor_response_f,
1604 Vector& sensor_response_f_grid,
1607 const String& sideband_mode,
1612 if (
max(sensor_response_f_grid) > f_lim)
1613 throw runtime_error(
"The frequencies seem to already be given in RF.");
1616 if (sideband_mode ==
"lower") {
1617 sensor_response_f *= -1;
1618 sensor_response_f_grid *= -1;
1619 sensor_response_f += lo;
1620 sensor_response_f_grid += lo;
1624 else if (sideband_mode ==
"upper") {
1625 sensor_response_f += lo;
1626 sensor_response_f_grid += lo;
1631 throw runtime_error(
1632 "Only allowed options for *sideband _mode* are \"lower\" and \"upper\".");
1640 Vector& sensor_response_f,
1642 Matrix& sensor_response_dlos,
1643 Vector& sensor_response_f_grid,
1645 const Matrix& sensor_response_dlos_grid,
1646 const Index& polyorder,
1652 const Index nf = sensor_response_f_grid.
nelem();
1653 const Index npol = sensor_response_pol_grid.
nelem();
1654 const Index nlos = sensor_response_dlos_grid.
nrows();
1655 const Index nin = nf * npol * nlos;
1659 bool error_found =
false;
1662 if (sensor_response_f.
nelem() != nin) {
1663 os <<
"Inconsistency in size between *sensor_response_f* and the sensor\n" 1664 <<
"grid variables (sensor_response_f_grid etc.).\n";
1667 if (sensor_response.
nrows() != nin) {
1668 os <<
"The sensor block response matrix *sensor_response* does not have\n" 1669 <<
"right size compared to the sensor grid variables\n" 1670 <<
"(sensor_response_f_grid etc.).\n";
1675 if (polyorder < 2 || polyorder > 7) {
1676 os <<
"Accepted range for *polyorder* is [3,7].\n";
1680 os <<
"The argument *nfill* must be > 1.\n";
1686 if (error_found)
throw runtime_error(os.
str());
1690 const Index n1 = nfill + 1;
1691 const Index n2 = nfill + 2;
1692 const Index nnew = (nf - 1) * n1 + 1;
1696 for (
Index i = 0;
i < nf - 1;
i++) {
1698 nlinspace(fp, sensor_response_f_grid[
i], sensor_response_f_grid[i + 1], n2);
1699 fnew[
Range(i * n1, n2)] = fp;
1705 Matrix itw(nnew, polyorder + 1);
1707 gridpos_poly(gp, sensor_response_f_grid, fnew, polyorder);
1712 Sparse hpoly(nnew * npol * nlos, nin);
1716 for (
Index ilos = 0; ilos < nlos; ilos++) {
1717 for (
Index iv = 0; iv < nnew; iv++) {
1718 for (
Index ip = 0; ip < npol; ip++) {
1719 const Index col0 = ilos * nf * npol;
1722 if (
abs(w) > 1e-5) {
1723 hrow[col0 + gp[iv].idx[
i] * npol + ip] =
w;
1728 hrow[col0 + gp[iv].idx[
i] * npol + ip] = 0;
1738 Sparse htmp = sensor_response;
1740 mult(sensor_response, hpoly, htmp);
1743 out3 <<
" Size of *sensor_response*: " << sensor_response.
nrows() <<
"x" 1744 << sensor_response.
ncols() <<
"\n";
1747 sensor_response_f_grid = fnew;
1751 sensor_response_pol,
1752 sensor_response_dlos,
1753 sensor_response_f_grid,
1754 sensor_response_pol_grid,
1755 sensor_response_dlos_grid);
1762 Vector& sensor_response_f,
1764 Matrix& sensor_response_dlos,
1765 Vector& sensor_response_f_grid,
1767 Matrix& sensor_response_dlos_grid,
1769 const Matrix& mblock_dlos_grid,
1770 const Index& antenna_dim,
1771 const Index& atmosphere_dim,
1772 const Index& stokes_dim,
1773 const Index& sensor_norm,
1786 if (mblock_dlos_grid.
empty())
1787 throw runtime_error(
"*mblock_dlos_grid* is empty.");
1788 if (mblock_dlos_grid.
ncols() > 2)
1789 throw runtime_error(
1790 "The maximum number of columns in *mblock_dlos_grid* is two.");
1791 if (atmosphere_dim < 3) {
1792 if (mblock_dlos_grid.
ncols() != 1)
1793 throw runtime_error(
1794 "For 1D and 2D *mblock_dlos_grid* must have exactly one column.");
1795 if (antenna_dim == 2)
1796 throw runtime_error(
1797 "2D antennas (antenna_dim=2) can only be " 1798 "used with 3D atmospheres.");
1802 sensor_response_f_grid = f_grid;
1803 sensor_response_dlos_grid = mblock_dlos_grid;
1805 sensor_response_pol_grid.resize(stokes_dim);
1807 for (
Index is = 0; is < stokes_dim; is++) {
1808 sensor_response_pol_grid[is] = is + 1;
1813 sensor_response_pol,
1814 sensor_response_dlos,
1815 sensor_response_f_grid,
1816 sensor_response_pol_grid,
1817 sensor_response_dlos_grid);
1823 out2 <<
" Initialising *sensor_reponse* as a identity matrix.\n";
1824 out3 <<
" Size of *sensor_response*: " << n <<
"x" << n <<
"\n";
1826 sensor_response.
resize(n, n);
1834 Vector& sensor_response_f,
1836 Matrix& sensor_response_dlos,
1837 Vector& sensor_response_f_grid,
1839 Matrix& sensor_response_dlos_grid,
1840 Matrix& mblock_dlos_grid,
1841 const Index& stokes_dim,
1846 AntennaOff(antenna_dim, mblock_dlos_grid, verbosity);
1851 const Index sensor_norm = 1, atmosphere_dim = 1;
1855 sensor_response_pol,
1856 sensor_response_dlos,
1857 sensor_response_f_grid,
1858 sensor_response_pol_grid,
1859 sensor_response_dlos_grid,
1873 Vector& sensor_response_f,
1875 Matrix& sensor_response_dlos,
1876 Vector& sensor_response_f_grid,
1878 const Matrix& sensor_response_dlos_grid,
1881 const Index& sensor_norm,
1886 const Index nf = sensor_response_f_grid.
nelem();
1887 const Index npol = sensor_response_pol_grid.
nelem();
1888 const Index nlos = sensor_response_dlos_grid.
nrows();
1889 const Index nin = nf * npol * nlos;
1897 bool error_found =
false;
1900 if (sensor_response_f.
nelem() != nin) {
1901 os <<
"Inconsistency in size between *sensor_response_f* and the sensor\n" 1902 <<
"grid variables (sensor_response_f_grid etc.).\n";
1905 if (sensor_response.
nrows() != nin) {
1906 os <<
"The sensor block response matrix *sensor_response* does not have\n" 1907 <<
"right size compared to the sensor grid variables\n" 1908 <<
"(sensor_response_f_grid etc.).\n";
1913 if (lo <= sensor_response_f_grid[0] || lo >=
last(sensor_response_f_grid)) {
1914 os <<
"The given local oscillator frequency is outside the sensor\n" 1915 <<
"frequency grid. It must be within the *sensor_response_f_grid*.\n";
1920 if (sbresponse_f_grid.
nelem() != sideband_response.
data.
nelem()) {
1921 os <<
"Mismatch in size of grid and data in *sideband_response*.\n";
1924 if (sbresponse_f_grid.
nelem() < 2) {
1925 os <<
"At least two data points must be specified in " 1926 <<
"*sideband_response*.\n";
1930 os <<
"The frequency grid of *sideband_response* must be strictly\n" 1934 if (fabs(
last(sbresponse_f_grid) + sbresponse_f_grid[0]) > 0) {
1935 os <<
"The end points of the *sideband_response* frequency grid must be\n" 1936 <<
"symmetrically placed around 0. That is, the grid shall cover a\n" 1937 <<
"a range that can be written as [-df,df]. \n";
1942 Numeric df_high = lo +
last(sbresponse_f_grid) -
last(sensor_response_f_grid);
1943 Numeric df_low = sensor_response_f_grid[0] - lo - sbresponse_f_grid[0];
1944 if (df_high > 0 && df_low > 0) {
1945 os <<
"The *sensor_response_f* grid must be extended by at least\n" 1946 << df_low <<
" Hz in the lower end and " << df_high <<
" Hz in the\n" 1947 <<
"upper end to cover frequency range set by *sideband_response*\n" 1948 <<
"and *lo*. Or can the frequency grid of *sideband_response* be\n" 1951 }
else if (df_high > 0) {
1952 os <<
"The *sensor_response_f* grid must be extended by at " << df_high
1953 <<
" Hz\nin the upper end to cover frequency range set by\n" 1954 <<
"*sideband_response* and *lo*. Or can the frequency grid of\n" 1955 <<
"*sideband_response* be decreased?";
1957 }
else if (df_low > 0) {
1958 os <<
"The *sensor_response_f* grid must be extended by at " << df_low
1959 <<
" Hz\nin the lower end to cover frequency range set by\n" 1960 <<
"*sideband_response* and *lo*. Or can the frequency grid of\n" 1961 <<
"*sideband_response* be decreased?";
1967 if (error_found)
throw runtime_error(os.
str());
1978 sensor_response_f_grid,
1986 Sparse htmp = sensor_response;
1987 sensor_response.
resize(hmixer.nrows(), htmp.
ncols());
1988 mult(sensor_response, hmixer, htmp);
1991 out3 <<
" Size of *sensor_response*: " << sensor_response.
nrows() <<
"x" 1992 << sensor_response.
ncols() <<
"\n";
1995 sensor_response_f_grid = f_mixer;
1999 sensor_response_pol,
2000 sensor_response_dlos,
2001 sensor_response_f_grid,
2002 sensor_response_pol_grid,
2003 sensor_response_dlos_grid);
2012 Matrix& mblock_dlos_grid,
2014 Vector& sensor_response_f,
2016 Matrix& sensor_response_dlos,
2017 Vector& sensor_response_f_grid,
2019 Matrix& sensor_response_dlos_grid,
2022 const Index& atmosphere_dim,
2023 const Index& stokes_dim,
2029 const Matrix& antenna_dlos,
2033 const Index& use_antenna,
2034 const Index& mirror_dza,
2042 throw std::runtime_error(
2043 "So far inclusion of antenna pattern is NOT supported and\n" 2044 "*met_mm_antenna* must be empty.\n");
2046 if (!(atmosphere_dim == 1 || atmosphere_dim == 3))
2047 throw std::runtime_error(
2048 "This method only supports 1D and 3D atmospheres.");
2050 if (antenna_dlos.
empty())
2051 throw std::runtime_error(
"*antenna_dlos* is empty.");
2053 if (antenna_dlos.
ncols() > 2)
2054 throw std::runtime_error(
2055 "The maximum number of columns in *antenna_dlos*" 2059 Matrix antenna_dlos_local;
2063 if (antenna_dlos.
ncols() > 1)
2064 throw std::runtime_error(
2065 "With *mirror_dza* set to true, *antenna_dlos*" 2066 "is only allowed to have a single column.");
2067 if (atmosphere_dim != 3)
2068 throw std::runtime_error(
"*mirror_dza* only makes sense in 3D.");
2073 if (antenna_dlos(
i, 0) != 0) {
2077 antenna_dlos_local.
resize(n + nnew, 1);
2078 antenna_dlos_local(
Range(0, n), 0) = antenna_dlos(
joker, 0);
2080 for (
Index i = n - 1;
i >= 0;
i--) {
2081 if (antenna_dlos(
i, 0) != 0) {
2082 antenna_dlos_local(pos, 0) = -antenna_dlos(
i, 0);
2087 antenna_dlos_local = antenna_dlos;
2095 Sparse sensor_response_single;
2096 Matrix mblock_dlos_dummy(1, 1);
2097 mblock_dlos_dummy(0, 0) = 0;
2100 sensor_response_pol,
2101 sensor_response_dlos,
2102 sensor_response_f_grid,
2103 sensor_response_pol_grid,
2104 sensor_response_dlos_grid,
2114 sensor_response_pol,
2115 sensor_response_dlos,
2116 sensor_response_f_grid,
2117 sensor_response_pol_grid,
2118 sensor_response_dlos_grid,
2120 channel2fgrid_indexes,
2121 channel2fgrid_weights,
2127 sensor_response =
Sparse(nchannels * antenna_dlos_local.
nrows(),
2128 num_f * stokes_dim * antenna_dlos_local.
nrows());
2130 sensor_response_pol_grid.resize(1);
2131 sensor_response_pol_grid[0] = 1;
2133 if (stokes_dim > 1) {
2135 if (mm_pol.
nelem() != nchannels) {
2137 os <<
"Length of *met_mm_polarisation* (" << mm_pol.
nelem()
2139 <<
"number of channels in *met_mm_backend* (" << nchannels <<
").";
2140 throw std::runtime_error(os.
str());
2144 Sparse sensor_response_tmp;
2146 for (
Index iza = 0; iza < antenna_dlos_local.
nrows(); iza++) {
2147 sensor_response_tmp =
Sparse(nchannels, sensor_response_single.
ncols());
2149 H_pol, mm_pol, antenna_dlos_local(iza, 0), stokes_dim, iy_unit);
2150 mult(sensor_response_tmp, H_pol, sensor_response_single);
2152 for (
Index c = 0; c < sensor_response_tmp.
ncols(); c++) {
2153 const Numeric v = sensor_response_tmp(
r, c);
2156 sensor_response.
rw(iza * nchannels +
r,
2157 iza * num_f * stokes_dim + c) = v;
2162 for (
Index iza = 0; iza < antenna_dlos_local.
nrows(); iza++) {
2164 for (
Index c = 0; c < sensor_response_single.
ncols(); c++) {
2165 const Numeric v = sensor_response_single(
r, c);
2168 sensor_response.
rw(iza * nchannels +
r,
2169 iza * num_f * stokes_dim + c) = v;
2178 throw std::runtime_error(
"The antenna hasn't arrived yet.");
2182 mblock_dlos_grid = antenna_dlos_local;
2185 sensor_response_dlos_grid = mblock_dlos_grid;
2189 sensor_response_pol,
2190 sensor_response_dlos,
2191 sensor_response_f_grid,
2192 sensor_response_pol_grid,
2193 sensor_response_dlos_grid);
2201 Vector& sensor_response_f,
2203 Matrix& sensor_response_dlos,
2204 Vector& sensor_response_f_grid,
2206 const Matrix& sensor_response_dlos_grid,
2214 const Index nin_f = sensor_response_f_grid.
nelem();
2216 const Index npol = sensor_response_pol_grid.
nelem();
2217 const Index nlos = sensor_response_dlos_grid.
nrows();
2218 const Index nin = nin_f * npol * nlos;
2219 const Index nout = nout_f * npol * nlos;
2223 bool error_found =
false;
2226 if (sensor_response_f.
nelem() != nin) {
2227 os <<
"Inconsistency in size between *sensor_response_f* and the sensor\n" 2228 <<
"grid variables (sensor_response_f_grid etc.).\n";
2231 if (sensor_response.
nrows() != nin) {
2232 os <<
"The sensor block response matrix *sensor_response* does not have\n" 2233 <<
"right size compared to the sensor grid variables\n" 2234 <<
"(sensor_response_f_grid etc.).\n";
2240 os <<
"*f_backend* is empty !!!\n";
2243 if (
min(f_backend) <
min(sensor_response_f_grid)) {
2244 os <<
"At least one value in *f_backend* (" <<
min(f_backend)
2245 <<
") below range\ncovered by *sensor_response_f_grid* (" 2246 <<
min(sensor_response_f_grid) <<
").\n";
2249 if (
max(f_backend) >
max(sensor_response_f_grid)) {
2250 os <<
"At least one value in *f_backend* (" <<
max(f_backend)
2251 <<
") above range\ncovered by *sensor_response_f_grid* (" 2252 <<
max(sensor_response_f_grid) <<
").\n";
2257 if (channel2fgrid_indexes.
nelem() != nout_f) {
2258 os <<
"The first size of *channel2fgrid_indexes* an length of *f_backend* " 2259 <<
"must be equal.\n";
2262 if (channel2fgrid_weights.
nelem() != channel2fgrid_indexes.
nelem()) {
2263 os <<
"Leading sizes of *channel2fgrid_indexes* and " 2264 <<
"*channel2fgrid_weights* differ.\n";
2267 for (
Index i = 0;
i < nout_f;
i++) {
2268 if (channel2fgrid_indexes[
i].
nelem() != channel2fgrid_weights[
i].
nelem()) {
2269 os <<
"Mismatch in size between *channel2fgrid_indexes* and " 2270 <<
"*channel2fgrid_weights*, found for array/vector with " 2271 <<
"index " <<
i <<
".\n";
2274 for (
Index j = 0; j < channel2fgrid_indexes[
i].
nelem(); j++) {
2275 if (channel2fgrid_indexes[
i][j] < 0 ||
2276 channel2fgrid_indexes[
i][j] >= nin_f) {
2277 os <<
"At least one value in *channel2fgrid_indexes* is either " 2278 <<
" < 0 or is too high considering length of " 2279 <<
"*sensor_response_f_grid*.\n";
2287 if (error_found)
throw runtime_error(os.
str());
2294 for (
Index ifr = 0; ifr < nout_f; ifr++) {
2297 for (
Index j = 0; j < channel2fgrid_indexes[ifr].
nelem(); j++) {
2298 w1[channel2fgrid_indexes[ifr][j]] = channel2fgrid_weights[ifr][j];
2304 for (
Index sp = 0; sp < nlos; sp++) {
2305 for (
Index pol = 0; pol < npol; pol++) {
2307 Vector weights_long(nin, 0.0);
2308 weights_long[
Range(sp * nin_f * npol + pol, nin_f, npol)] = w1;
2311 hmb.insert_row(sp * nout_f * npol + ifr * npol + pol, weights_long);
2320 Sparse htmp = sensor_response;
2321 sensor_response.
resize(hmb.nrows(), htmp.
ncols());
2322 mult(sensor_response, hmb, htmp);
2325 sensor_response_f_grid = f_backend;
2329 sensor_response_pol,
2330 sensor_response_dlos,
2331 sensor_response_f_grid,
2332 sensor_response_pol_grid,
2333 sensor_response_dlos_grid);
2341 Vector& sensor_response_f,
2343 Matrix& sensor_response_dlos,
2344 Vector& sensor_response_f_grid,
2346 const Matrix& sensor_response_dlos_grid,
2352 const Index& sensor_norm,
2355 const Index nf = sensor_response_f_grid.
nelem();
2356 const Index npol = sensor_response_pol_grid.
nelem();
2357 const Index nlos = sensor_response_dlos_grid.
nrows();
2358 const Index nin = nf * npol * nlos;
2363 bool error_found =
false;
2366 if (sensor_response_f.
nelem() != nin) {
2367 os <<
"Inconsistency in size between *sensor_response_f* and the sensor\n" 2368 <<
"grid variables (sensor_response_f_grid etc.).\n";
2371 if (sensor_response.
nrows() != nin) {
2372 os <<
"The sensor block response matrix *sensor_response* does not have\n" 2373 <<
"right size compared to the sensor grid variables\n" 2374 <<
"(sensor_response_f_grid etc.).\n";
2380 if (sideband_response_multi.
nelem() != nlo) {
2381 os <<
"Inconsistency in length between *lo_mixer* and " 2382 <<
"*sideband_response_multi*.\n";
2385 if (sideband_mode_multi.
nelem() != nlo) {
2386 os <<
"Inconsistency in length between *lo_mixer* and " 2387 <<
"*sideband_mode_multi*.\n";
2390 if (f_backend_multi.
nelem() != nlo) {
2391 os <<
"Inconsistency in length between *lo_mixer* and " 2392 <<
"*f_backend_multi*.\n";
2395 if (backend_channel_response_multi.
nelem() != nlo) {
2396 os <<
"Inconsistency in length between *lo_mixer* and " 2397 <<
"*backend_channel_response_multi*.\n";
2403 if (error_found)
throw runtime_error(os.
str());
2410 for (
Index ilo = 0; ilo < nlo; ilo++) {
2413 Sparse sr1 = sensor_response;
2414 Vector srf1 = sensor_response_f;
2416 Matrix srdlos1 = sensor_response_dlos;
2417 Vector srfgrid1 = sensor_response_f_grid;
2426 sensor_response_pol_grid,
2427 sensor_response_dlos_grid,
2429 sideband_response_multi[ilo],
2434 srf1, srfgrid1, lo_multi[ilo], sideband_mode_multi[ilo], verbosity);
2441 sensor_response_pol_grid,
2442 sensor_response_dlos_grid,
2443 f_backend_multi[ilo],
2444 backend_channel_response_multi[ilo],
2447 }
catch (
const runtime_error& e) {
2449 os2 <<
"Error when dealing with receiver/mixer chain (1-based index) " 2452 throw runtime_error(os2.
str());
2457 srfgrid.push_back(srfgrid1);
2459 cumsumf[ilo + 1] = cumsumf[ilo] + srfgrid1.
nelem();
2464 const Index nfnew = cumsumf[nlo];
2465 sensor_response_f_grid.
resize(nfnew);
2467 for (
Index ilo = 0; ilo < nlo; ilo++) {
2469 sensor_response_f_grid[cumsumf[ilo] +
i] = srfgrid[ilo][
i];
2475 const Index ncols = sr[0].ncols();
2476 const Index npolnew = sensor_response_pol_grid.
nelem();
2477 const Index nfpolnew = nfnew * npolnew;
2479 sensor_response.
resize(nlos * nfpolnew, ncols);
2481 Vector dummy(ncols, 0.0);
2483 for (
Index ilo = 0; ilo < nlo; ilo++) {
2484 const Index nfpolthis = (cumsumf[ilo + 1] - cumsumf[ilo]) * npolnew;
2486 assert(sr[ilo].nrows() == nlos * nfpolthis);
2487 assert(sr[ilo].ncols() == ncols);
2489 for (
Index ilos = 0; ilos < nlos; ilos++) {
2490 for (
Index i = 0;
i < nfpolthis;
i++) {
2492 for (
Index ic = 0; ic < ncols; ic++) {
2493 dummy[ic] = sr[ilo](ilos * nfpolthis +
i, ic);
2496 sensor_response.
insert_row(ilos * nfpolnew + cumsumf[ilo] * npolnew +
i,
2504 sensor_response_pol,
2505 sensor_response_dlos,
2506 sensor_response_f_grid,
2507 sensor_response_pol_grid,
2508 sensor_response_dlos_grid);
2515 Vector& sensor_response_f,
2517 Matrix& sensor_response_dlos,
2519 const Vector& sensor_response_f_grid,
2520 const Matrix& sensor_response_dlos_grid,
2521 const Index& stokes_dim,
2527 const Index nf = sensor_response_f_grid.
nelem();
2528 const Index npol = sensor_response_pol_grid.
nelem();
2529 const Index nlos = sensor_response_dlos_grid.
nrows();
2533 bool error_found =
false;
2535 Index nfz = nf * nlos;
2536 Index nin = nfz * npol;
2538 if (sensor_response.
nrows() != nin) {
2539 os <<
"The sensor block response matrix *sensor_response* does not have\n" 2540 <<
"right size compared to the sensor grid variables\n" 2541 <<
"(sensor_response_f_grid etc.).\n";
2546 if (sensor_response_f.
nelem() != nin) {
2547 os <<
"Inconsistency in size between *sensor_response_f* and the sensor\n" 2548 <<
"grid variables (sensor_response_f_grid etc.).\n";
2551 if (npol != stokes_dim) {
2552 os <<
"Number of input polarisation does not match *stokes_dim*.\n";
2556 os <<
"The WSV *instrument_pol* can not be empty.\n";
2561 if (error_found)
throw runtime_error(os.
str());
2564 for (
Index i = 0;
i < npol && !error_found;
i++) {
2565 if (sensor_response_pol_grid[
i] !=
i + 1) {
2566 os <<
"The input polarisations must be I, Q, U and V (up to " 2567 <<
"stokes_dim). It seems that input data are for other " 2568 <<
"polarisation components.";
2572 for (
Index i = 0;
i < nnew && !error_found;
i++) {
2573 if (instrument_pol[
i] < 1 || instrument_pol[
i] > 10) {
2574 os <<
"The elements of *instrument_pol* must be inside the range [1,10].\n";
2580 if (error_found)
throw runtime_error(os.
str());
2584 if (error_found)
throw runtime_error(os.
str());
2588 if (iy_unit ==
"PlanckBT" || iy_unit ==
"RJBT") {
2594 Sparse Hpol(nfz * nnew, nin);
2600 for (
Index in = 0; in < nnew; in++) {
2608 hrow[
Range(col, stokes_dim)], stokes_dim, instrument_pol[in], w);
2620 Sparse Htmp = sensor_response;
2622 mult(sensor_response, Hpol, Htmp);
2625 sensor_response_pol_grid = instrument_pol;
2629 sensor_response_pol,
2630 sensor_response_dlos,
2631 sensor_response_f_grid,
2632 sensor_response_pol_grid,
2633 sensor_response_dlos_grid);
2640 const Vector& sensor_response_f_grid,
2642 const Matrix& sensor_response_dlos_grid,
2643 const Index& stokes_dim,
2644 const Vector& stokes_rotation,
2650 const Index nf = sensor_response_f_grid.
nelem();
2651 const Index npol = sensor_response_pol_grid.
nelem();
2652 const Index nlos = sensor_response_dlos_grid.
nrows();
2653 const Index nin = nf * npol * nlos;
2658 bool error_found =
false;
2661 if (sensor_response.
nrows() != nin) {
2662 os <<
"The sensor block response matrix *sensor_response* does not have\n" 2663 <<
"right size compared to the sensor grid variables\n" 2664 <<
"(sensor_response_f_grid etc.).\n";
2669 if (stokes_dim < 3) {
2670 os <<
"To perform a rotation of the Stokes coordinate system,\n" 2671 <<
"*stokes_dim* must be >= 3.\n";
2674 if (stokes_rotation.
nelem() != nlos) {
2675 os <<
"Incorrect number of angles in *stokes_rotation*. The length\n" 2676 <<
"of this matrix must match *sensor_response_dlos_grid*.\n";
2679 if (npol != stokes_dim) {
2680 os <<
"Inconsistency detected. The length of *sensor_response_pol_grid*\n" 2681 <<
"must be equal to *stokes_dim*, and this is not the case.\n";
2684 for (
Index is = 0; is < npol; is++) {
2685 if (sensor_response_pol_grid[is] != is + 1) {
2686 os <<
"For this method, the values in *sensor_response_pol_grid* must\n" 2687 <<
"be 1,2...stokes_dim. This is not the case, indicating that\n" 2688 <<
"some previous sensor part has that the data no longer are\n" 2689 <<
"Stokes vectors.\n";
2697 if (error_found)
throw runtime_error(os.
str());
2705 Vector row(H.ncols(), 0);
2708 for (
Index ilos = 0; ilos < nlos; ilos++) {
2712 for (
Index ifr = 0; ifr < nf; ifr++) {
2713 for (
Index ip = 0; ip < npol; ip++) {
2716 for (
Index is = 0; is < npol; is++) {
2717 row[irow + is] = Hrot.
ro(ip, is);
2719 H.insert_row(irow + ip, row);
2721 for (
Index is = 0; is < npol; is++) {
2734 Sparse Htmp = sensor_response;
2736 mult(sensor_response, H, Htmp);
2745 Matrix& mblock_dlos_grid,
2747 Vector& sensor_response_f,
2749 Matrix& sensor_response_dlos,
2750 Vector& sensor_response_f_grid,
2752 Matrix& sensor_response_dlos_grid,
2755 const Index& atmosphere_dim,
2756 const Index& stokes_dim,
2757 const Matrix& sensor_description_amsu,
2763 const Index m = sensor_description_amsu.
ncols();
2773 if (5 > sensor_description_amsu.
ncols()) {
2775 os <<
"Input variable sensor_description_amsu must have atleast five columns, but it has " 2776 << sensor_description_amsu.
ncols() <<
".";
2777 throw runtime_error(os.
str());
2784 sensor_description_amsu(
Range(
joker), m - 1);
2789 const Numeric minRatioVerbosityVsFdiff =
2794 for (
Index idx = 0; idx <
n; ++idx) {
2795 if ((verbosityVectIn[idx] == 0) || (verbosityVectIn[idx] > width[idx])) {
2796 verbosityVect[idx] = ((
Numeric)width[idx]) / 3;
2798 verbosityVect[idx] = verbosityVectIn[idx];
2808 for (
Index j = 0; j < (m - 2); ++j) {
2810 if (offset(
i, j) > 0) {
2815 numPB[
i] = 1 << (int)numPB[
i];
2816 if (numPB[
i] == 1) {
2819 numPBpseudo[
i] = numPB[
i];
2822 totNumPb += (int)numPB[
i];
2826 os <<
"This function does currently not support more than 4 passbands per channel" 2828 throw runtime_error(os.
str());
2838 Vector& f = f_backend_multi[
i];
2840 f[0] = lo_multi[
i] + 0.0 * width[
i];
2843 const Index numVal = 4;
2844 backend_channel_response_multi[
i].resize(1);
2846 b_resp.
set_name(
"Backend channel response function");
2847 b_resp.
resize(numVal * numPBpseudo[
i]);
2848 Vector f_range(numVal * numPBpseudo[i]);
2854 for (
Index pbOffsetIdx = 0; pbOffsetIdx < numPBpseudo[
i];
2856 slope = width[
i] / 100;
2857 f_range[pbOffsetIdx * numVal + 0] = -0.5 * width[
i] - 0 * slope;
2858 f_range[pbOffsetIdx * numVal + 1] = -0.5 * width[
i] + 1 * slope;
2859 f_range[pbOffsetIdx * numVal + 2] = +0.5 * width[
i] - 1 * slope;
2860 f_range[pbOffsetIdx * numVal + 3] = +0.5 * width[
i] + 0 * slope;
2862 b_resp.
data[pbOffsetIdx * numVal + 0] = 0.0 / (
Numeric)numPB[i];
2864 b_resp.
data[pbOffsetIdx * numVal + 1] = 1.0 / (
Numeric)numPB[i];
2865 b_resp.
data[pbOffsetIdx * numVal + 2] = 1.0 / (
Numeric)numPB[i];
2866 b_resp.
data[pbOffsetIdx * numVal + 3] = 0.0 / (
Numeric)numPB[i];
2868 if (numPB[i] == 1) {
2869 if (pbOffsetIdx == 0) {
2870 pbOffset = -0.0 * width[
i];
2871 b_resp.
data[pbOffsetIdx * numVal + 0] = 0;
2872 b_resp.
data[pbOffsetIdx * numVal + 1] = 1.0 / 1;
2874 b_resp.
data[pbOffsetIdx * numVal + 2] = 1.0 / 1;
2875 b_resp.
data[pbOffsetIdx * numVal + 3] = 1.0 / 1;
2876 f_range[pbOffsetIdx * numVal + 0] = -0.5 * width[
i] - 2 * slope;
2877 f_range[pbOffsetIdx * numVal + 1] = -0.5 * width[
i] - 1 * slope;
2878 f_range[pbOffsetIdx * numVal + 2] = -0.5 * width[
i] + 1 * slope;
2879 f_range[pbOffsetIdx * numVal + 3] = -0.5 * width[
i] + 2 * slope;
2881 if (pbOffsetIdx == 1) {
2882 pbOffset = 0.0 * width[
i];
2883 b_resp.
data[pbOffsetIdx * numVal + 0] = 1.0 / 1;
2884 b_resp.
data[pbOffsetIdx * numVal + 1] = 1.0 / 1;
2885 b_resp.
data[pbOffsetIdx * numVal + 2] = 1.0 / 1;
2886 b_resp.
data[pbOffsetIdx * numVal + 3] = 0;
2887 f_range[pbOffsetIdx * numVal + 0] = +0.5 * width[
i] - 3 * slope;
2888 f_range[pbOffsetIdx * numVal + 1] = +0.5 * width[
i] - 2 * slope;
2889 f_range[pbOffsetIdx * numVal + 2] = +0.5 * width[
i] - 1 * slope;
2890 f_range[pbOffsetIdx * numVal + 3] = +0.5 * width[
i] + 0 * slope - 10;
2896 if (pbOffsetIdx == 0) {
2897 pbOffset = -offset(i, 0);
2899 if (pbOffsetIdx == 1) {
2900 pbOffset = offset(i, 0);
2903 if (numPB[i] == 4) {
2904 if (pbOffsetIdx == 0) {
2905 pbOffset = -offset(i, 0) - offset(i, 1);
2907 if (pbOffsetIdx == 1) {
2908 pbOffset = -offset(i, 0) + offset(i, 1);
2910 if (pbOffsetIdx == 2) {
2911 pbOffset = offset(i, 0) - offset(i, 1);
2913 if (pbOffsetIdx == 3) {
2914 pbOffset = offset(i, 0) + offset(i, 1);
2917 for (
Index iii = 0; iii < numVal; ++iii) {
2918 f_range[pbOffsetIdx * numVal + iii] += 1 * pbOffset;
2922 for (
Index ii = 2; ii < (f_range.
nelem() - 2); ++ii) {
2923 if (((b_resp.
data[ii - 1] == 1) && (b_resp.
data[ii] == 0) &&
2924 (b_resp.
data[ii + 1] == 0) && (b_resp.
data[ii + 2] == 1))) {
2925 if ((f_range[ii] >= f_range[ii + 1]))
2927 if ((f_range[ii + 2] - f_range[ii - 1]) >
2930 f_range[ii + 1] = f_range[ii + 2] - verbosityVectIn[
i] / 2;
2931 f_range[ii] = f_range[ii - 1] + verbosityVectIn[
i] / 2;
2933 f_range[ii - 1] = (f_range[ii] + f_range[ii + 2]) / 2 -
2934 2 * verbosityVectIn[i] / minRatioVerbosityVsFdiff;
2935 f_range[ii + 1] = (f_range[ii] + f_range[ii + 2]) / 2 +
2936 verbosityVectIn[i] / minRatioVerbosityVsFdiff;
2938 f_range[ii - 1] + verbosityVectIn[
i] / minRatioVerbosityVsFdiff;
2940 f_range[ii + 1] + verbosityVectIn[
i] / minRatioVerbosityVsFdiff;
2952 r.
set_name(
"Sideband response function");
2954 Vector f(numPBpseudo[i]);
2955 if (numPB[i] == 1) {
2957 f[0] = -.0 * width[
i];
2959 f[1] = .0 * width[
i];
2960 }
else if (numPB[i] == 2) {
2963 f[0] = -1 * offset(i, 0) - 0.5 * width[
i];
2964 f[1] = +1 * offset(i, 0) + 0.5 * width[
i];
2965 }
else if (numPB[i] == 4) {
2970 f[0] = -offset(i, 0) - offset(i, 1) - 0.5 * width[
i];
2972 f[1] = -offset(i, 0) + offset(i, 1) - 0.5 * width[
i];
2974 f[2] = +offset(i, 0) - offset(i, 1) + 0.5 * width[
i];
2976 f[3] = +offset(i, 0) + offset(i, 1) + 0.5 * width[
i];
2989 backend_channel_response_multi,
2995 AntennaOff(antenna_dim, mblock_dlos_grid, verbosity);
3001 sensor_response_pol,
3002 sensor_response_dlos,
3003 sensor_response_f_grid,
3004 sensor_response_pol_grid,
3005 sensor_response_dlos_grid,
3015 Index numLO = lo_multi.nelem();
3021 const Index nlos = sensor_response_dlos_grid.
nrows();
3024 for (
Index idxLO = 0; idxLO < numLO; idxLO++) {
3025 Sparse sr1 = sensor_response;
3026 Vector srf1 = sensor_response_f;
3028 Matrix srdlos1 = sensor_response_dlos;
3029 Vector srfgrid1 = sensor_response_f_grid;
3038 sensor_response_pol_grid,
3039 sensor_response_dlos_grid,
3040 f_backend_multi[idxLO],
3041 backend_channel_response_multi[idxLO],
3047 srfgrid.push_back(srfgrid1);
3049 cumsumf[idxLO + 1] = cumsumf[idxLO] + srfgrid1.
nelem();
3054 const Index nfnew = cumsumf[numLO];
3055 sensor_response_f_grid.
resize(nfnew);
3057 for (
Index ilo = 0; ilo < numLO; ilo++) {
3059 sensor_response_f_grid[cumsumf[ilo] +
i] = srfgrid[ilo][
i];
3063 const Index ncols = sr[0].ncols();
3064 const Index npolnew = sensor_response_pol_grid.
nelem();
3065 const Index nfpolnew = nfnew * npolnew;
3067 sensor_response.
resize(nlos * nfpolnew, ncols);
3069 Vector dummy(ncols, 0.0);
3071 for (
Index ilo = 0; ilo < numLO; ilo++) {
3072 const Index nfpolthis = (cumsumf[ilo + 1] - cumsumf[ilo]) * npolnew;
3074 assert(sr[ilo].nrows() == nlos * nfpolthis);
3075 assert(sr[ilo].ncols() == ncols);
3077 for (
Index ilos = 0; ilos < nlos; ilos++) {
3078 for (
Index i = 0;
i < nfpolthis;
i++) {
3080 for (
Index ic = 0; ic < ncols; ic++) {
3081 dummy[ic] = sr[ilo](ilos * nfpolthis +
i, ic);
3084 sensor_response.
insert_row(ilos * nfpolnew + cumsumf[ilo] * npolnew +
i,
3091 sensor_response_pol,
3092 sensor_response_dlos,
3093 sensor_response_f_grid,
3094 sensor_response_pol_grid,
3095 sensor_response_dlos_grid);
3104 Matrix& mblock_dlos_grid,
3106 Vector& sensor_response_f,
3108 Matrix& sensor_response_dlos,
3109 Vector& sensor_response_f_grid,
3111 Matrix& sensor_response_dlos_grid,
3114 const Index& atmosphere_dim,
3115 const Index& stokes_dim,
3116 const Matrix& sensor_description_amsu,
3121 if (3 != sensor_description_amsu.
ncols()) {
3123 os <<
"Input variable sensor_description_amsu must have three columns, but it has " 3124 << sensor_description_amsu.
ncols() <<
".";
3125 throw runtime_error(os.
str());
3141 Vector& f = f_backend_multi[
i];
3143 f[0] = lo_multi[
i] + offset[
i];
3149 backend_channel_response_multi[
i].resize(1);
3151 r.
set_name(
"Backend channel response function");
3156 f[0] = -0.5 * width[
i];
3157 f[1] = +0.5 * width[
i];
3170 r.
set_name(
"Sideband response function");
3175 f[0] = -(offset[
i] + 0.5 * width[
i]);
3176 f[1] = +(offset[
i] + 0.5 * width[
i]);
3197 backend_channel_response_multi,
3201 AntennaOff(antenna_dim, mblock_dlos_grid, verbosity);
3205 sensor_response_pol,
3206 sensor_response_dlos,
3207 sensor_response_f_grid,
3208 sensor_response_pol_grid,
3209 sensor_response_dlos_grid,
3220 sensor_response_pol,
3221 sensor_response_dlos,
3222 sensor_response_f_grid,
3223 sensor_response_pol_grid,
3224 sensor_response_dlos_grid,
3226 sideband_response_multi,
3227 sideband_mode_multi,
3229 backend_channel_response_multi,
3253 if ((wmrf_weights.
nrows() != f_backend.
nelem()) ||
3255 os <<
"The WSV *wmrf_weights* must have same number of rows as\n" 3256 <<
"*f_backend*, and same number of columns as *f_grid*.\n" 3257 <<
"wmrf_weights.nrows() = " << wmrf_weights.
nrows() <<
"\n" 3258 <<
"f_backend.nelem() = " << f_backend.
nelem() <<
"\n" 3259 <<
"wmrf_weights.ncols() = " << wmrf_weights.
ncols() <<
"\n" 3260 <<
"f_grid.nelem() = " << f_grid.
nelem();
3261 throw runtime_error(os.
str());
3269 if (
min(wmrf_channels) < 0) {
3270 os <<
"Min(wmrf_channels) must be >= 0, but it is " <<
min(wmrf_channels)
3273 if (
max(wmrf_channels) >= f_backend.
nelem()) {
3274 os <<
"Max(wmrf_channels) must be less than the total number of channels.\n" 3275 <<
"(We use zero-based indexing!)\n" 3276 <<
"The actual value you have is " <<
max(wmrf_channels) <<
".";
3279 if (wmrf_channels.
nelem() == f_backend.
nelem()) {
3281 out2 <<
" Retaining all channels.\n";
3283 out2 <<
" Reducing number of channels from " << f_backend.
nelem() <<
" to " 3284 << wmrf_channels.
nelem() <<
".\n";
3290 Select(f_backend, f_backend, wmrf_channels, verbosity);
3295 Select(wmrf_weights, wmrf_weights, wmrf_channels, verbosity);
3306 selection.reserve(f_grid.
nelem());
3310 assert(wmrf_weights.
nrows() == f_backend.
nelem());
3311 assert(wmrf_weights.
ncols() == f_grid.
nelem());
3312 for (
Index fi = 0; fi < wmrf_weights.
ncols(); ++fi) {
3314 for (i = 0; i < wmrf_weights.
nrows(); ++
i) {
3315 if (wmrf_weights(i, fi) != 0) {
3316 selection.push_back(fi);
3320 if (i == wmrf_weights.
nrows()) {
3321 out3 <<
" The frequency with index " << fi
3322 <<
" is not used by any channel.\n";
3328 out2 <<
" No unnecessary frequencies, leaving f_grid untouched.\n";
3329 }
else if (selection.
nelem() == 0) {
3330 throw runtime_error(
"No frequencies found for any selected channels.\n");
3332 out2 <<
" Reducing number of frequency grid points from " << f_grid.
nelem()
3333 <<
" to " << selection.
nelem() <<
".\n";
3337 Select(f_grid, f_grid, selection, verbosity);
3344 Select(wt, wt, selection, verbosity);
3345 wmrf_weights.
resize(wt.ncols(), wt.nrows());
3354 Vector& sensor_response_f,
3356 Matrix& sensor_response_dlos,
3357 Vector& sensor_response_f_grid,
3360 const Matrix& sensor_response_dlos_grid,
3361 const Sparse& wmrf_weights,
3367 const Index nf = sensor_response_f_grid.
nelem();
3368 const Index npol = sensor_response_pol_grid.
nelem();
3369 const Index nlos = sensor_response_dlos_grid.
nrows();
3370 const Index nin = nf * npol * nlos;
3374 bool error_found =
false;
3377 if (sensor_response_f.
nelem() != nin) {
3378 os <<
"Inconsistency in size between *sensor_response_f* and the sensor\n" 3379 <<
"grid variables (sensor_response_f_grid etc.).\n";
3382 if (sensor_response.
nrows() != nin) {
3383 os <<
"The sensor block response matrix *sensor_response* does not have\n" 3384 <<
"right size compared to the sensor grid variables\n" 3385 <<
"(sensor_response_f_grid etc.).\n";
3390 os <<
"One of f_grid, pol_grid, dlos_grid are empty. Sizes are: (" << nf
3391 <<
", " << npol <<
", " << nlos <<
")" 3400 if (nrw != f_backend.
nelem()) {
3401 os <<
"The WSV *wmrf_weights* must have as many rows\n" 3402 <<
"as *f_backend* has elements.\n" 3403 <<
"wmrf_weights.nrows() = " << nrw <<
"\n" 3404 <<
"f_backend.nelem() = " << f_backend.
nelem() <<
"\n";
3412 if (ncw != sensor_response_f_grid.
nelem()) {
3413 os <<
"The WSV *wmrf_weights* must have as many columns\n" 3414 <<
"as *sensor_response_f_grid* has elements.\n" 3415 <<
"wmrf_weights.ncols() = " << ncw <<
"\n" 3416 <<
"sensor_response_f_grid.nelem() = " << sensor_response_f_grid.
nelem()
3423 if (error_found)
throw runtime_error(os.
str());
3430 Sparse htmp = sensor_response;
3431 sensor_response.
resize(wmrf_weights.
nrows(), htmp.ncols());
3432 mult(sensor_response, wmrf_weights, htmp);
3435 out3 <<
" Size of *sensor_response*: " << sensor_response.
nrows() <<
"x" 3436 << sensor_response.
ncols() <<
"\n";
3439 sensor_response_f_grid = f_backend;
3443 sensor_response_pol,
3444 sensor_response_dlos,
3445 sensor_response_f_grid,
3446 sensor_response_pol_grid,
3447 sensor_response_dlos_grid);
3456 const Index& stokes_dim,
3461 const Index sensor_norm = 1, atmosphere_dim = 1;
3466 Vector sensor_response_f, sensor_response_f_grid;
3467 Matrix mblock_dlos_grid, sensor_response_dlos_grid, sensor_response_dlos;
3468 ArrayOfIndex sensor_response_pol, sensor_response_pol_grid;
3471 AntennaOff(antenna_dim, mblock_dlos_grid, verbosity);
3475 sensor_response_pol,
3476 sensor_response_dlos,
3477 sensor_response_f_grid,
3478 sensor_response_pol_grid,
3479 sensor_response_dlos_grid,
3490 linspace(f_backend, f_grid[0] + df / 2,
last(f_grid), df);
3499 sensor_response_pol,
3500 sensor_response_dlos,
3501 sensor_response_f_grid,
3502 sensor_response_pol_grid,
3503 sensor_response_dlos_grid,
3515 Vector iyb(nf * stokes_dim);
3517 for (
Index is = 0; is < stokes_dim; is++) {
3518 iyb[
Range(is, nf, stokes_dim)] = iy(
joker, is);
3523 y_f = sensor_response_f;
3525 mult(y, sensor_response, iyb);
3539 const Index& stokes_dim,
3540 const Index& jacobian_do,
3541 const Matrix& sensor_pos,
3542 const Matrix& sensor_pol,
3548 const Index n2 = nm * nc;
3551 if (y.
empty())
throw runtime_error(
"Input *y* is empty. Use *yCalc*");
3552 if (y_f.
nelem() != n1)
3553 throw runtime_error(
"Lengths of input *y* and *y_f* are inconsistent.");
3554 if (y_pol.
nelem() != n1)
3555 throw runtime_error(
"Lengths of input *y* and *y_pol* are inconsistent.");
3556 if (y_pos.
nrows() != n1)
3557 throw runtime_error(
"Sizes of input *y* and *y_pos* are inconsistent.");
3558 if (y_los.
nrows() != n1)
3559 throw runtime_error(
"Sizes of input *y* and *y_los* are inconsistent.");
3560 if (y_geo.
nrows() != n1)
3561 throw runtime_error(
"Sizes of input *y* and *y_geo* are inconsistent.");
3563 if (jacobian.
nrows() != n1)
3564 throw runtime_error(
"Sizes of *y* and *jacobian* are inconsistent.");
3569 throw runtime_error(
3570 "*stokes_dim* must be >= 3 to correctly apply a " 3571 "polarisation rotation.");
3572 if (n1 < stokes_dim)
3573 throw runtime_error(
"Length of input *y* smaller than *stokes_dim*.");
3574 for (
Index i = 0;
i < stokes_dim;
i++) {
3575 if (y_pol[
i] !=
i + 1)
3576 throw runtime_error(
3577 "*y* must hold Stokes element values. Data in " 3578 "*y_pol* indicates that this is not the case.");
3582 if (sensor_pos.
nrows() != nm)
3583 throw runtime_error(
3584 "Different number of rows in *sensor_pos* and *sensor_pol*.");
3585 if (n2 * stokes_dim != n1)
3586 throw runtime_error(
3587 "Number of columns in *sensor_pol* not consistent with " 3588 "length of *y* and value of *stokes_dim*.");
3591 const Vector y1 = y, y_f1 = y_f;
3592 const Matrix y_pos1 = y_pos, y_los1 = y_los, y_geo1 = y_geo;
3597 jacobian1 = jacobian;
3605 y_los.
resize(n2, y_los1.ncols());
3606 y_geo.
resize(n2, y_geo1.ncols());
3607 for (
Index a = 0; a < y_aux.
nelem(); a++) y_aux[a].resize(n2);
3613 for (
Index c = 0; c < nc; c++) {
3614 const Index iout =
r * nc + c;
3615 const Index iin = iout * stokes_dim;
3621 y[iout] = y1[iin] + wq * y1[iin + 1] + wu * y1[iin + 2];
3626 jacobian(iout,
q) = jacobian1(iin,
q) + wq * jacobian1(iin + 1,
q) +
3627 wu * jacobian1(iin + 2,
q);
3631 y_pol[iout] = (
Index)sensor_pol(
r, c);
3634 y_f[iout] = y_f1[iin];
3638 for (
Index a = 0; a < y_aux.
nelem(); a++) y_aux[a][iout] = y_aux1[a][iin];
INDEX Index
The type to use for all integer numbers and indices.
void antenna2d_interp_response(Sparse &H, const Index &antenna_dim, ConstMatrixView antenna_dlos, const GriddedField4 &antenna_response, ConstMatrixView mblock_dlos, ConstVectorView f_grid, const Index n_pol)
antenna2d_interp_response
void sensor_responseAntenna(Sparse &sensor_response, Vector &sensor_response_f, ArrayOfIndex &sensor_response_pol, Matrix &sensor_response_dlos, Matrix &sensor_response_dlos_grid, const Vector &sensor_response_f_grid, const ArrayOfIndex &sensor_response_pol_grid, const Index &atmosphere_dim, const Index &antenna_dim, const Matrix &antenna_dlos, const GriddedField4 &antenna_response, const Index &sensor_norm, const String &option_2d, const Verbosity &verbosity)
WORKSPACE METHOD: sensor_responseAntenna.
void gaussian_response(Vector &y, const Vector &x, const Numeric &x0, const Numeric &fwhm)
gaussian_response
void gaussian_response_autogrid(Vector &x, Vector &y, const Numeric &x0, const Numeric &fwhm, const Numeric &xwidth_si, const Numeric &dx_si)
gaussian_response_autogrid
void sensor_responseBackendFrequencySwitching(Sparse &sensor_response, Vector &sensor_response_f, ArrayOfIndex &sensor_response_pol, Matrix &sensor_response_dlos, Vector &sensor_response_f_grid, const ArrayOfIndex &sensor_response_pol_grid, const Matrix &sensor_response_dlos_grid, const Vector &f_backend, const ArrayOfGriddedField1 &backend_channel_response, const Index &sensor_norm, const Numeric &df1, const Numeric &df2, const Verbosity &verbosity)
WORKSPACE METHOD: sensor_responseBackendFrequencySwitching.
void spectrometer_matrix(Sparse &H, ConstVectorView ch_f, const ArrayOfGriddedField1 &ch_response, ConstVectorView sensor_f, const Index &n_pol, const Index &n_sp, const Index &do_norm)
spectrometer_matrix
void checksize_strict() const final
Strict consistency check.
Index nelem() const
Number of elements.
void resize(const GriddedField1 &gf)
Make this GriddedField1 the same size as the given one.
bool empty() const
Returns true if variable size is zero.
void mueller_rotation(Sparse &H, const Index &stokes_dim, const Numeric &rotangle)
mueller_rotation
void f_gridFromSensorAMSUgeneric(Vector &f_grid, const ArrayOfVector &f_backend_multi, const ArrayOfArrayOfGriddedField1 &backend_channel_response_multi, const Numeric &spacing, const Vector &verbosityVect, const Verbosity &verbosity)
WORKSPACE METHOD: f_gridFromSensorAMSUgeneric.
void mblock_dlos_gridUniformRectangular(Matrix &mblock_dlos_grid, const Numeric &spacing, const Numeric &za_width, const Numeric &aa_width, const Index ¢re, const Verbosity &)
WORKSPACE METHOD: mblock_dlos_gridUniformRectangular.
Declarations having to do with the four output streams.
const Index GFIELD4_ZA_GRID
void sensor_responseBackend(Sparse &sensor_response, Vector &sensor_response_f, ArrayOfIndex &sensor_response_pol, Matrix &sensor_response_dlos, Vector &sensor_response_f_grid, const ArrayOfIndex &sensor_response_pol_grid, const Matrix &sensor_response_dlos_grid, const Vector &f_backend, const ArrayOfGriddedField1 &backend_channel_response, const Index &sensor_norm, const Verbosity &verbosity)
WORKSPACE METHOD: sensor_responseBackend.
void antenna2d_gridded_dlos(Sparse &H, const Index &antenna_dim, ConstMatrixView antenna_dlos, const GriddedField4 &antenna_response, ConstMatrixView mblock_dlos, ConstVectorView f_grid, const Index n_pol)
antenna2d_interp_gridded_dlos
void sensor_responseWMRF(Sparse &sensor_response, Vector &sensor_response_f, ArrayOfIndex &sensor_response_pol, Matrix &sensor_response_dlos, Vector &sensor_response_f_grid, const ArrayOfIndex &sensor_response_pol_grid, const Matrix &sensor_response_dlos_grid, const Sparse &wmrf_weights, const Vector &f_backend, const Verbosity &verbosity)
WORKSPACE METHOD: sensor_responseWMRF.
void f_gridFromSensorHIRS(Vector &f_grid, const Vector &f_backend, const ArrayOfGriddedField1 &backend_channel_response, const Numeric &spacing, const Verbosity &verbosity)
WORKSPACE METHOD: f_gridFromSensorHIRS.
void sensor_responseStokesRotation(Sparse &sensor_response, const Vector &sensor_response_f_grid, const ArrayOfIndex &sensor_response_pol_grid, const Matrix &sensor_response_dlos_grid, const Index &stokes_dim, const Vector &stokes_rotation, const Verbosity &)
WORKSPACE METHOD: sensor_responseStokesRotation.
Numeric interp(ConstVectorView itw, ConstVectorView a, const GridPos &tc)
Red 1D Interpolate.
const ArrayOfString & get_string_grid(Index i) const
Get a string grid.
bool is_increasing(ConstVectorView x)
Checks if a vector is sorted and strictly increasing.
const Index GFIELD1_F_GRID
Numeric last(ConstVectorView x)
last
bool is_multiple(const Index &x, const Index &y)
Checks if an integer is a multiple of another integer.
bool empty() const
Returns true if variable size is zero.
Index ncols() const
Returns the number of columns.
Numeric & rw(Index r, Index c)
Read and write index operator.
invlib::Vector< ArtsVector > Vector
invlib wrapper type for ARTS vectors.
cmplx FADDEEVA() w(cmplx z, double relerr)
This file contains basic functions to handle XML data files.
void WMRFSelectChannels(Vector &f_grid, Sparse &wmrf_weights, Vector &f_backend, const ArrayOfIndex &wmrf_channels, const Verbosity &verbosity)
WORKSPACE METHOD: WMRFSelectChannels.
void backend_channel_responseGaussian(ArrayOfGriddedField1 &r, const Vector &fwhm, const Vector &xwidth_si, const Vector &dx_si, const Verbosity &)
WORKSPACE METHOD: backend_channel_responseGaussian.
const Index GFIELD4_F_GRID
G0 G2 FVC Y DV Numeric Numeric Numeric Zeeman LowerQuantumNumbers void * data
void antenna1d_matrix(Sparse &H, const Index &antenna_dim, ConstVectorView antenna_dza, const GriddedField4 &antenna_response, ConstVectorView za_grid, ConstVectorView f_grid, const Index n_pol, const Index do_norm)
antenna1d_matrix
Index nelem() const
Returns the number of elements.
void sensorOff(Sparse &sensor_response, Vector &sensor_response_f, ArrayOfIndex &sensor_response_pol, Matrix &sensor_response_dlos, Vector &sensor_response_f_grid, ArrayOfIndex &sensor_response_pol_grid, Matrix &sensor_response_dlos_grid, Matrix &mblock_dlos_grid, const Index &stokes_dim, const Vector &f_grid, const Verbosity &verbosity)
WORKSPACE METHOD: sensorOff.
Contains sorting routines.
void sensor_responseIF2RF(Vector &sensor_response_f, Vector &sensor_response_f_grid, const Numeric &lo, const String &sideband_mode, const Verbosity &)
WORKSPACE METHOD: sensor_responseIF2RF.
Sensor modelling functions.
Index ncols() const
Returns the number of columns.
void sensor_responseSimpleAMSU(Vector &f_grid, Index &antenna_dim, Matrix &mblock_dlos_grid, Sparse &sensor_response, Vector &sensor_response_f, ArrayOfIndex &sensor_response_pol, Matrix &sensor_response_dlos, Vector &sensor_response_f_grid, ArrayOfIndex &sensor_response_pol_grid, Matrix &sensor_response_dlos_grid, Index &sensor_norm, const Index &atmosphere_dim, const Index &stokes_dim, const Matrix &sensor_description_amsu, const Numeric &spacing, const Verbosity &verbosity)
WORKSPACE METHOD: sensor_responseSimpleAMSU.
The global header file for ARTS.
_CS_string_type str() const
void AntennaConstantGaussian1D(Index &antenna_dim, Matrix &mblock_dlos_grid, GriddedField4 &r, Matrix &antenna_dlos, const Index &n_za_grid, const Numeric &fwhm, const Numeric &xwidth_si, const Numeric &dx_si, const Verbosity &verbosity)
WORKSPACE METHOD: AntennaConstantGaussian1D.
void yApplySensorPol(Vector &y, Vector &y_f, ArrayOfIndex &y_pol, Matrix &y_pos, Matrix &y_los, ArrayOfVector &y_aux, Matrix &y_geo, Matrix &jacobian, const Index &stokes_dim, const Index &jacobian_do, const Matrix &sensor_pos, const Matrix &sensor_pol, const Verbosity &)
WORKSPACE METHOD: yApplySensorPol.
void mblock_dlos_gridUniformCircular(Matrix &mblock_dlos_grid, const Numeric &spacing, const Numeric &width, const Index ¢re, const Verbosity &)
WORKSPACE METHOD: mblock_dlos_gridUniformCircular.
void set_grid(Index i, const Vector &g)
Set a numeric grid.
void nlinspace(Vector &x, const Numeric start, const Numeric stop, const Index n)
nlinspace
void ySimpleSpectrometer(Vector &y, Vector &y_f, const Matrix &iy, const Index &stokes_dim, const Vector &f_grid, const Numeric &df, const Verbosity &verbosity)
WORKSPACE METHOD: ySimpleSpectrometer.
Index nrows() const
Returns the number of rows.
const Numeric SPEED_OF_LIGHT
void AntennaMultiBeamsToPencilBeams(Matrix &sensor_pos, Matrix &sensor_los, Matrix &antenna_dlos, Index &antenna_dim, Matrix &mblock_dlos_grid, const Index &atmosphere_dim, const Verbosity &verbosity)
WORKSPACE METHOD: AntennaMultiBeamsToPencilBeams.
void sensor_responseFillFgrid(Sparse &sensor_response, Vector &sensor_response_f, ArrayOfIndex &sensor_response_pol, Matrix &sensor_response_dlos, Vector &sensor_response_f_grid, const ArrayOfIndex &sensor_response_pol_grid, const Matrix &sensor_response_dlos_grid, const Index &polyorder, const Index &nfill, const Verbosity &verbosity)
WORKSPACE METHOD: sensor_responseFillFgrid.
void sensor_responseMixer(Sparse &sensor_response, Vector &sensor_response_f, ArrayOfIndex &sensor_response_pol, Matrix &sensor_response_dlos, Vector &sensor_response_f_grid, const ArrayOfIndex &sensor_response_pol_grid, const Matrix &sensor_response_dlos_grid, const Numeric &lo, const GriddedField1 &sideband_response, const Index &sensor_norm, const Verbosity &verbosity)
WORKSPACE METHOD: sensor_responseMixer.
void gridpos(ArrayOfGridPos &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Numeric &extpolfac)
Set up a grid position Array.
const Vector & get_numeric_grid(Index i) const
Get a numeric grid.
void sensor_responsePolarisation(Sparse &sensor_response, Vector &sensor_response_f, ArrayOfIndex &sensor_response_pol, Matrix &sensor_response_dlos, ArrayOfIndex &sensor_response_pol_grid, const Vector &sensor_response_f_grid, const Matrix &sensor_response_dlos_grid, const Index &stokes_dim, const String &iy_unit, const ArrayOfIndex &instrument_pol, const Verbosity &)
WORKSPACE METHOD: sensor_responsePolarisation.
void met_mm_polarisation_hmatrix(Sparse &H, const ArrayOfString &mm_pol, const Numeric dza, const Index stokes_dim, const String &iy_unit)
Calculate polarisation H-matrix.
NUMERIC Numeric
The type to use for all floating point numbers.
void sensor_aux_vectors(Vector &sensor_response_f, ArrayOfIndex &sensor_response_pol, Matrix &sensor_response_dlos, ConstVectorView sensor_response_f_grid, const ArrayOfIndex &sensor_response_pol_grid, ConstMatrixView sensor_response_dlos_grid)
sensor_aux_vectors
void VectorNLogSpace(Vector &x, const Index &n, const Numeric &start, const Numeric &stop, const Verbosity &verbosity)
WORKSPACE METHOD: VectorNLogSpace.
void f_gridFromSensorAMSU(Vector &f_grid, const Vector &lo, const ArrayOfVector &f_backend, const ArrayOfArrayOfGriddedField1 &backend_channel_response, const Numeric &spacing, const Verbosity &verbosity)
WORKSPACE METHOD: f_gridFromSensorAMSU.
Helper comparison class to sort an array or vector based on an ArrayOfNumeric.
void gridpos_poly(ArrayOfGridPosPoly &gp, ConstVectorView old_grid, ConstVectorView new_grid, const Index order, const Numeric &extpolfac)
The maximum difference from 1 that we allow for a sum check.
void mixer_matrix(Sparse &H, Vector &f_mixer, const Numeric &lo, const GriddedField1 &filter, ConstVectorView f_grid, const Index &n_pol, const Index &n_sp, const Index &do_norm)
mixer_matrix
Header file for special_interp.cc.
Propagation path structure and functions.
Numeric pow(const Rational base, Numeric exp)
Power of.
void mult(ComplexVectorView y, const ConstComplexMatrixView &M, const ConstComplexVectorView &x)
Matrix-Vector Multiplication.
basic_ostringstream< char, string_char_traits< char >, alloc > ostringstream
This can be used to make arrays out of anything.
void sensor_responseMetMM(Index &antenna_dim, Matrix &mblock_dlos_grid, Sparse &sensor_response, Vector &sensor_response_f, ArrayOfIndex &sensor_response_pol, Matrix &sensor_response_dlos, Vector &sensor_response_f_grid, ArrayOfIndex &sensor_response_pol_grid, Matrix &sensor_response_dlos_grid, Index &sensor_norm, const Index &atmosphere_dim, const Index &stokes_dim, const Vector &f_grid, const Vector &f_backend, const ArrayOfArrayOfIndex &channel2fgrid_indexes, const ArrayOfVector &channel2fgrid_weights, const String &iy_unit, const Matrix &antenna_dlos, const ArrayOfString &mm_pol, const Vector &mm_ant, const Index &use_antenna, const Index &mirror_dza, const Verbosity &verbosity)
WORKSPACE METHOD: sensor_responseMetMM.
Header file for interpolation_poly.cc.
void sensor_responseMixerBackendPrecalcWeights(Sparse &sensor_response, Vector &sensor_response_f, ArrayOfIndex &sensor_response_pol, Matrix &sensor_response_dlos, Vector &sensor_response_f_grid, const ArrayOfIndex &sensor_response_pol_grid, const Matrix &sensor_response_dlos_grid, const Vector &f_backend, const ArrayOfArrayOfIndex &channel2fgrid_indexes, const ArrayOfVector &channel2fgrid_weights, const Verbosity &verbosity)
WORKSPACE METHOD: sensor_responseMixerBackendPrecalcWeights.
ConstComplexMatrixView transpose(ConstComplexMatrixView m)
Const version of transpose.
void f_gridMetMM(Vector &f_grid, Vector &f_backend, ArrayOfArrayOfIndex &channel2fgrid_indexes, ArrayOfVector &channel2fgrid_weights, const Matrix &mm_back, const Vector &freq_spacing, const ArrayOfIndex &freq_number, const Numeric &freq_merge_threshold, const Verbosity &)
WORKSPACE METHOD: f_gridMetMM.
void AntennaOff(Index &antenna_dim, Matrix &mblock_dlos_grid, const Verbosity &verbosity)
WORKSPACE METHOD: AntennaOff.
void resize(Index n)
Resize function.
void sensor_responseGenericAMSU(Vector &f_grid, Index &antenna_dim, Matrix &mblock_dlos_grid, Sparse &sensor_response, Vector &sensor_response_f, ArrayOfIndex &sensor_response_pol, Matrix &sensor_response_dlos, Vector &sensor_response_f_grid, ArrayOfIndex &sensor_response_pol_grid, Matrix &sensor_response_dlos_grid, Index &sensor_norm, const Index &atmosphere_dim, const Index &stokes_dim, const Matrix &sensor_description_amsu, const Numeric &spacing, const Verbosity &verbosity)
WORKSPACE METHOD: sensor_responseGenericAMSU.
Numeric ro(Index r, Index c) const
Read only index operator.
void sensor_responseInit(Sparse &sensor_response, Vector &sensor_response_f, ArrayOfIndex &sensor_response_pol, Matrix &sensor_response_dlos, Vector &sensor_response_f_grid, ArrayOfIndex &sensor_response_pol_grid, Matrix &sensor_response_dlos_grid, const Vector &f_grid, const Matrix &mblock_dlos_grid, const Index &antenna_dim, const Index &atmosphere_dim, const Index &stokes_dim, const Index &sensor_norm, const Verbosity &verbosity)
WORKSPACE METHOD: sensor_responseInit.
void sensor_responseMultiMixerBackend(Sparse &sensor_response, Vector &sensor_response_f, ArrayOfIndex &sensor_response_pol, Matrix &sensor_response_dlos, Vector &sensor_response_f_grid, const ArrayOfIndex &sensor_response_pol_grid, const Matrix &sensor_response_dlos_grid, const Vector &lo_multi, const ArrayOfGriddedField1 &sideband_response_multi, const ArrayOfString &sideband_mode_multi, const ArrayOfVector &f_backend_multi, const ArrayOfArrayOfGriddedField1 &backend_channel_response_multi, const Index &sensor_norm, const Verbosity &verbosity)
WORKSPACE METHOD: sensor_responseMultiMixerBackend.
A constant view of a Vector.
void set_name(const String &s)
Set name of this gridded field.
void antenna_responseVaryingGaussian(GriddedField4 &r, const Numeric &leff, const Numeric &xwidth_si, const Numeric &dx_si, const Index &nf, const Numeric &fstart, const Numeric &fstop, const Index &do_2d, const Verbosity &verbosity)
WORKSPACE METHOD: antenna_responseVaryingGaussian.
Index nelem(const Lines &l)
Number of lines.
const Index GFIELD4_FIELD_NAMES
void sub(Sparse &A, const Sparse &B, const Sparse &C)
Sparse - Sparse subtraction.
A constant view of a Matrix.
void antenna_responseGaussian(GriddedField4 &r, const Numeric &fwhm, const Numeric &xwidth_si, const Numeric &dx_si, const Index &do_2d, const Verbosity &)
WORKSPACE METHOD: antenna_responseGaussian.
void set_grid_name(Index i, const String &s)
Set grid name.
void stokes2pol(VectorView w, const Index &stokes_dim, const Index &ipol_1based, const Numeric nv)
stokes2pol
void resize(Index r, Index c)
Resize function.
bool is_decreasing(ConstVectorView x)
Checks if a vector is sorted in reversed order and is strictly decreasing.
void id_mat(MatrixView I)
Identity Matrix.
void backend_channel_responseFlat(ArrayOfGriddedField1 &r, const Numeric &resolution, const Verbosity &)
WORKSPACE METHOD: backend_channel_responseFlat.
void sensor_responseFrequencySwitching(Sparse &sensor_response, Vector &sensor_response_f, ArrayOfIndex &sensor_response_pol, Matrix &sensor_response_dlos, Vector &sensor_response_f_grid, const ArrayOfIndex &sensor_response_pol_grid, const Matrix &sensor_response_dlos_grid, const Verbosity &verbosity)
WORKSPACE METHOD: sensor_responseFrequencySwitching.
void sensor_responseBeamSwitching(Sparse &sensor_response, Vector &sensor_response_f, ArrayOfIndex &sensor_response_pol, Matrix &sensor_response_dlos, Matrix &sensor_response_dlos_grid, const Vector &sensor_response_f_grid, const ArrayOfIndex &sensor_response_pol_grid, const Numeric &w1, const Numeric &w2, const Verbosity &verbosity)
WORKSPACE METHOD: sensor_responseBeamSwitching.
void interpweights(VectorView itw, const GridPos &tc)
Red 1D interpolation weights.
void insert_row(Index r, Vector v)
Insert row function.
std::vector< T > linspace(T s, T e, typename std::vector< T >::size_type count) noexcept
Index nrows() const
Returns the number of rows.
void resize(Index b, Index p, Index r, Index c)
Resize function.
Numeric sqrt(const Rational r)
Square root.
void resize(Index r, Index c)
Resize function.
void Select(Array< T > &needles, const Array< T > &haystack, const ArrayOfIndex &needleind, const Verbosity &)
void find_effective_channel_boundaries(Vector &fmin, Vector &fmax, const Vector &f_backend, const ArrayOfGriddedField1 &backend_channel_response, const Numeric &delta, const Verbosity &verbosity)
Calculate channel boundaries from instrument response functions.
const Index GFIELD4_AA_GRID