modulated.h
1//-*-C++-*-
2/***************************************************************************
3 *
4 * Copyright (C) 2016 - 2021 by Willem van Straten
5 * Licensed under the Academic Free License version 2.1
6 *
7 ***************************************************************************/
8
9// epsic/src/modulated.h
10
11#ifndef __epsic_modulated_h
12#define __epsic_modulated_h
13
14#include "mode.h"
15
16#include <vector>
17
18#define _DEBUG 0
19#if _DEBUG
20#include <iostream>
21#endif
22
23namespace epsic
24{
25
26 /***************************************************************************
27 *
28 * an amplitude modulated mode of electromagnetic radiation
29 *
30 ***************************************************************************/
31
32 class modulated_mode : public field_transformer
33 {
34 #if _DEBUG
35 mutable double tot, totsq;
36 uint64_t count;
37 #endif
38
39 public:
40
41 modulated_mode (mode* s) : field_transformer(s)
42 {
43 #if -DEBUG
44 tot=0; totsq=0; count=0;
45 #endif
46 }
47
48 // return a random scalar modulation factor
49 virtual double modulation () = 0;
50
51 // return the mean of the scalar modulation factor
52 virtual double get_mod_mean () const = 0;
53
54 // return the variance of the scalar modulation factor
55 virtual double get_mod_variance () const = 0;
56
57 Spinor<double> transform (const Spinor<double>& field)
58 {
59 double mod = modulation();
60 #if _DEBUG
61 tot+=mod;
62 totsq+=mod*mod;
63 count+=1;
64 #endif
65 return sqrt(mod) * field;
66 }
67
68 Matrix<4,4,double> get_covariance () const
69 {
70 double mean = get_mod_mean();
71 double var = get_mod_variance();
72
73 #if _DEBUG
74 cerr << "modulated_mode::get_covariance expected mean=" << mean
75 << " var=" << var << endl;
76 tot /= count;
77 totsq /= count;
78 totsq -= tot*tot;
79 cerr << " measured mean=" << tot << " var=" << totsq << endl;
80 #endif
81
82 Matrix<4,4,double> C = source->get_covariance();
83 C *= (mean*mean + var);
84 Matrix<4,4,double> o = outer (source->get_mean(), source->get_mean());
85 o *= var;
86 return C + o;
87 }
88
89 Stokes<double> get_mean () const
90 {
91 return get_mod_mean () * source->get_mean();
92 }
93
94 };
95
96 class lognormal_mode : public modulated_mode
97 {
98 // standard deviation of the logarithm of the random variate
99 double log_sigma;
100
101 public:
102
103 // initialize based on the modulation index beta
104 lognormal_mode (mode* s, double beta) : modulated_mode (s) { set_beta (beta); }
105
106 void set_beta (double beta)
107 {
108 log_sigma = sqrt( log( beta*beta + 1.0 ) );
109 }
110
111 double get_beta () const
112 {
113 return sqrt( get_mod_variance() );
114 }
115
117 double get_log_sigma () const
118 {
119 return log_sigma;
120 }
121
122 // return a random scalar modulation factor
123 double modulation ()
124 {
125 return exp ( log_sigma * (get_normal()->evaluate() - 0.5*log_sigma) ) ;
126 }
127
128 double get_mod_mean () const { return 1.0; }
129
130 double get_mod_variance () const { return exp(log_sigma*log_sigma) - 1.0; }
131
132 };
133
134
135 class boxcar_modulated_mode : public modulated_mode
136 {
137 std::vector< double > instances;
138 unsigned smooth;
139 unsigned current;
140
141 void setup()
142 {
143 current = 0;
144 instances.resize (smooth);
145 for (unsigned i=1; i<smooth; i++)
146 instances[i] = mod->modulation();
147 }
148
149 modulated_mode* mod;
150
151 public:
152
153 boxcar_modulated_mode (modulated_mode* s, unsigned n)
154 : modulated_mode(s->get_source()) { smooth = n; mod = s; }
155
156 double modulation ()
157 {
158 if (instances.size() < smooth)
159 setup ();
160
161 instances[current] = mod->modulation();
162 current = (current + 1) % smooth;
163
164 double result = 0.0;
165 for (unsigned i=0; i<smooth; i++)
166 result += instances[i];
167
168 result /= smooth;
169
170 return result;
171 }
172
173 double get_mod_variance () const
174 {
175 return mod->get_mod_variance() / smooth;
176 }
177
178 double get_mod_mean () const
179 {
180 return mod->get_mod_mean ();
181 }
182
183 Matrix<4,4, double> get_crosscovariance (unsigned ilag) const
184 {
185 if (ilag >= smooth)
186 return 0;
187
188 Matrix<4,4, double> result = outer(source->get_mean(), source->get_mean());
189 result *= double (smooth - ilag) / smooth * get_mod_variance();
190 return result;
191 }
192
193 };
194
195
196 class square_modulated_mode : public modulated_mode
197 {
198 unsigned width;
199 unsigned current;
200 double value;
201
202 modulated_mode* mod;
203
204 std::vector<double> cross_correlation;
205
206 public:
207
208 square_modulated_mode (modulated_mode*,
209 unsigned width,
210 unsigned sample_size);
211
212 void compute_cross_correlation (unsigned sample_size);
213
214 double modulation ()
215 {
216 if (current == width)
217 {
218 value = mod->modulation();
219 current = 0;
220 }
221
222 current ++;
223 return value;
224 }
225
226 double get_mod_variance () const
227 {
228 return mod->get_mod_variance();
229 }
230
231 double get_mod_mean () const
232 {
233 return mod->get_mod_mean ();
234 }
235
237 Matrix<4,4, double> get_crosscovariance (unsigned ilag) const
238 {
239 if (ilag >= width)
240 return 0;
241
242 Matrix<4,4, double> result = outer(source->get_mean(), source->get_mean());
243 result *= cross_correlation[ilag] * get_mod_variance();
244
245 return result;
246 }
247 };
248
249} // namespace epsic
250
251#endif // ! defined __epsic_modulated_h

Generated using doxygen 1.14.0