Line data Source code
1 : /**
2 : Bojan Nikolic <bn204@mrao.cam.ac.uk>, <bojan@bnikolic.co.uk>
3 : Initial version February 2008
4 : Maintained by ESO since 2013.
5 :
6 : This file is part of LibAIR and is licensed under GNU Public
7 : License Version 2
8 :
9 : \file radiometermeasure.hpp
10 : Renamed radiometermeasure.h 2023
11 :
12 : Model the radiometer measurement process
13 : */
14 :
15 : #ifndef _LIBAIR_RADIOMETERMEASURE_HPP__
16 : #define _LIBAIR_RADIOMETERMEASURE_HPP__
17 :
18 : #include <vector>
19 : #include <stdexcept>
20 : #include <string>
21 : #include <memory>
22 :
23 : namespace LibAIR2 {
24 :
25 : /**
26 : General exception class for errors in the radiometer subsystem.
27 : */
28 : class RadiometerError :
29 : public std::runtime_error
30 : {
31 : public:
32 :
33 0 : RadiometerError(const std::string & s):
34 0 : std::runtime_error(s)
35 0 : {}
36 :
37 : };
38 :
39 :
40 :
41 : /** \brief Base class for radiometers
42 : */
43 : class Radiometer {
44 :
45 : /** The frequency grid over which measurements are expected.
46 : */
47 : std::vector<double> FGrid;
48 :
49 : /** \brief Coefficients used to compute the output of the
50 : radiomter from sky brigthnesses
51 :
52 : Multiple vectors of coefficients allow multiple channels
53 :
54 : */
55 : std::vector< std::vector<double> > coeffs_v;
56 :
57 : public:
58 :
59 : // ---------- Construction / Destruction --------------
60 :
61 : /** \brief Constructs a single channel radiometer
62 : */
63 : Radiometer( const std::vector<double> & FGrid,
64 : const std::vector<double> & coeffs);
65 :
66 : /** \brief Construct a multi channel radiometer
67 : */
68 : Radiometer( const std::vector<double> & FGrid,
69 : const std::vector< std::vector<double> > & coeffs_v);
70 :
71 : // ---------- Public interface --------------------------
72 :
73 : /**
74 : \brief
75 : Return the frequency grid required by this radiometer
76 : */
77 0 : const std::vector<double> & getFGrid(void) const
78 : {
79 0 : return FGrid;
80 : }
81 :
82 0 : const std::vector<double> & getCoeffs(size_t ch) const
83 : {
84 0 : return coeffs_v[ch];
85 : }
86 :
87 : /** \brief Returns the number of channels
88 :
89 : */
90 0 : size_t nchannels(void) const
91 : {
92 0 : return coeffs_v.size();
93 : }
94 :
95 :
96 :
97 : /** \brief Return the meausrement from a vector of sky Tbs
98 : evaluated on grid as returned by getFGrid.
99 :
100 : \param ch is zero-indexed
101 : */
102 0 : double eval( const std::vector<double> & skyTb,
103 : size_t ch) const
104 : {
105 0 : const std::vector<double> & coeffs = coeffs_v[ch];
106 :
107 0 : double res = 0;
108 0 : for (size_t i = 0 ; i < FGrid.size() ; ++i )
109 0 : res += coeffs[i] * skyTb[i];
110 0 : return res;
111 :
112 : }
113 :
114 0 : double eval( const std::vector<double> & skyTb) const
115 : {
116 0 : if ( nchannels() > 1 )
117 : {
118 0 : std::string err("More than one channel but asking for single result");
119 0 : throw RadiometerError(err);
120 0 : }
121 :
122 0 : return eval( skyTb, 0);
123 : }
124 :
125 : };
126 :
127 : /**
128 : \brief Model of a simple double-sideband radiometer.
129 :
130 : At the moment this is single-channel only
131 :
132 : */
133 : class DSBRadio
134 : {
135 :
136 : std::unique_ptr<Radiometer> r;
137 :
138 : public:
139 :
140 : // ---------- Public data ------------ --------------
141 :
142 : /// The central frequency
143 : const double f_0;
144 :
145 : /// The frequency of the middle of the IF band
146 : const double f_if;
147 :
148 : // ---------- Construction / Destruction --------------
149 :
150 : /** The basic constructor
151 :
152 : */
153 : DSBRadio( double f_0,
154 : double f_if);
155 :
156 : /** Use the supplied radiometer -- for derived classes
157 : */
158 : DSBRadio( double f_0,
159 : double f_if,
160 : Radiometer * rr);
161 :
162 : // ---------- Public interface --------------------------
163 :
164 : /** \brief Return a const reference to the actual radiometer
165 : */
166 : const Radiometer & getRadiometer(void) const;
167 :
168 : double eval( const std::vector<double> & skyTb) const;
169 :
170 : const std::vector<double> & getFGrid(void) const
171 : {
172 : return r->getFGrid();
173 : }
174 :
175 : };
176 :
177 :
178 : /** \brief Incoroporate the effect of bandiwdth of radiometer filters.
179 :
180 : This version calculates the average of the signal over the band
181 : using rectangular integration of the signal over 30 points --
182 : not very efficient.
183 :
184 : */
185 : class DSBBWRadio:
186 : public DSBRadio
187 : {
188 :
189 : public:
190 :
191 : /// The fitlter bandwidth
192 : const double f_bw;
193 :
194 : // ---------- Construction / Destruction --------------
195 :
196 : DSBBWRadio( double f_0,
197 : double f_if,
198 : double f_bw);
199 :
200 : // ---------- Public interface --------------------------
201 :
202 : static Radiometer * MkRadio( double f_0,
203 : double f_if,
204 : double f_bw);
205 : };
206 :
207 : /**
208 : Generate finite bandwidth radiometers with Gaussian quadrature
209 : integration.
210 : */
211 : class DSBBW_QuadRadio:
212 : public DSBRadio
213 : {
214 :
215 : public:
216 :
217 : // ---------- Construction / Destruction --------------
218 :
219 : DSBBW_QuadRadio( double f_0,
220 : double f_if,
221 : double f_bw);
222 :
223 : // ---------- Public interface --------------------------
224 :
225 : static Radiometer * MkRadio( double f_0,
226 : double f_if,
227 : double f_bw);
228 : };
229 :
230 :
231 :
232 : /** \brief Exception type representing for errors due to unknown
233 : radiometer channel.
234 :
235 : */
236 : struct InvalidWVRChannel
237 : {
238 : int chlow, chhigh, ch;
239 :
240 : InvalidWVRChannel(int chlow,
241 : int chhigh,
242 : int ch);
243 : };
244 :
245 : /** \brief Returns WVR perfectly to spec for ALMA
246 :
247 : \param ch the WVR channel (1 to 4 inclusive).
248 :
249 : */
250 : DSBRadio * MkALMARadiometer(int ch,
251 : double cf_off=0.0,
252 : double bw_off=0.0) noexcept(false);
253 :
254 : /** \brief Returns WVR Dicke prototype
255 :
256 : \param ch the WVR channel (1 to 4 inclusive).
257 :
258 : */
259 : DSBRadio * MkALMADickeProto(int ch) noexcept(false);
260 :
261 :
262 : /**
263 : \brief Create the four channel production ALMA WVR
264 :
265 : */
266 : Radiometer * MkFullALMAWVR(void);
267 :
268 : /**
269 : \brief Create the ALMA radiometer but offset the centre
270 : frequencies by foffset (in GHz)
271 : */
272 : Radiometer * MkALMAWVR_offset(double cf,
273 : double bw);
274 :
275 : /**
276 : \brief Measured properties of ALMA Production radiometers
277 : */
278 : struct ALMAWVRCharacter {
279 : /// Measured centre frequencies of each of the filters
280 : double cf1, cf2, cf3, cf4;
281 : /// Measured bandwidths of each fo the filters
282 : double bw1, bw2, bw3, bw4;
283 :
284 : /// By default set to the nominal character
285 : ALMAWVRCharacter(void);
286 : };
287 :
288 : /** \brief Create ALMA radiometer with measured characteristics
289 : */
290 : Radiometer *MkALMAWVR(const ALMAWVRCharacter &c);
291 :
292 : /**
293 : \brief Create the four channel dicke Prototype WVR
294 :
295 : */
296 : Radiometer * MkFullDickeProtoWVR(void);
297 :
298 : /**
299 : \brief Create a single sideband radiometer
300 :
301 : The filter is approximated by five-point Gaussian quadrature
302 :
303 : \param f_c Centre frequency of the filter
304 :
305 : \param f_bw Filter bandwidth
306 : */
307 : Radiometer * MkSSBRadio(double f_c,
308 : double f_bw);
309 :
310 :
311 : /**
312 : \brief Make a model of the IRAM 22 GHz WVRs
313 :
314 : The channel centres and bandwidths are typical values for units
315 : at the PdB
316 : */
317 : Radiometer * MkIRAM22(void);
318 :
319 : }
320 :
321 : #endif
322 :
|