1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 """Module for performing Monte Carlo simulations for error analysis."""
25
26
27 from numpy import diag, ndarray, sqrt
28 from random import gauss
29
30
31 from lib import statistics
32 from lib.errors import RelaxError
33 from pipe_control.pipes import check_pipe
34 from specific_analyses.api import return_api
35
36
38 """Estimate model parameter errors via the covariance matrix technique.
39
40 Note that the covariance matrix error estimate is always of lower quality than Monte Carlo simulations.
41
42
43 @param epsrel: Any columns of R which satisfy |R_{kk}| <= epsrel |R_{11}| are considered linearly-dependent and are excluded from the covariance matrix, where the corresponding rows and columns of the covariance matrix are set to zero.
44 @type epsrel: float
45 @keyword verbosity: The amount of information to print. The higher the value, the greater the verbosity.
46 @type verbosity: int
47 """
48
49
50 check_pipe()
51
52
53 api = return_api()
54
55
56 for model_info in api.model_loop():
57
58 jacobian, weights = api.covariance_matrix(model_info=model_info, verbosity=verbosity)
59
60
61 pcov = statistics.multifit_covar(J=jacobian, weights=weights)
62
63
64 sd = sqrt(diag(pcov))
65
66
67 index = 0
68 for name in api.get_param_names(model_info):
69
70 api.set_error(index, sd[index], model_info=model_info)
71
72
73 index = index + 1
74
75
77 """Function for creating simulation data.
78
79 @keyword method: The type of Monte Carlo simulation to perform.
80 @type method: str
81 @keyword distribution: Which gauss distribution to draw errors from. Can be: 'measured', 'red_chi2', 'fixed'.
82 @type distribution: str
83 @keyword fixed_error: If distribution is set to 'fixed', use this value as the standard deviation for the gauss distribution.
84 @type fixed_error: float
85 """
86
87
88 check_pipe()
89
90
91 if not hasattr(cdp, 'sim_state'):
92 raise RelaxError("Monte Carlo simulations have not been set up.")
93
94
95 valid_methods = ['back_calc', 'direct']
96 if method not in valid_methods:
97 raise RelaxError("The simulation creation method " + repr(method) + " is not valid.")
98
99
100 valid_distributions = ['measured', 'red_chi2', 'fixed']
101 if distribution not in valid_distributions:
102 raise RelaxError("The simulation error distribution method " + repr(distribution) + " is not valid. Try one of the following: " + repr(valid_distributions))
103
104
105 if fixed_error != None and distribution != 'fixed':
106 raise RelaxError("The argument 'fixed_error' is set to a value, but the argument 'distribution' is not set to 'fixed'.")
107
108
109 if distribution == 'fixed' and fixed_error == None:
110 raise RelaxError("The argument 'distribution' is set to 'fixed', but you have not provided a value to the argument 'fixed_error'.")
111
112
113 api = return_api()
114
115
116 for data_index in api.base_data_loop():
117
118 if method == 'back_calc':
119 data = api.create_mc_data(data_index)
120
121
122 else:
123 data = api.return_data(data_index)
124
125
126 if data == None:
127 continue
128
129
130 if distribution == 'red_chi2':
131 error_red_chi2 = api.return_error_red_chi2(data_index)
132
133
134 error = api.return_error(data_index)
135
136
137 if isinstance(data, list) or isinstance(data, ndarray):
138
139 random = []
140 for j in range(cdp.sim_number):
141
142 random.append([])
143 for k in range(len(data)):
144
145 if data[k] == None or error[k] == None:
146 random[j].append(None)
147 continue
148
149
150 if distribution == 'fixed':
151 random[j].append(gauss(data[k], float(fixed_error)))
152
153 else:
154 random[j].append(gauss(data[k], error[k]))
155
156
157 if isinstance(data, dict):
158
159 random = []
160 for j in range(cdp.sim_number):
161
162 random.append({})
163 for id in data:
164
165 if data[id] == None or error[id] == None:
166 random[j][id] = None
167 continue
168
169
170 if distribution == 'red_chi2':
171
172 g_error = gauss(0.0, error_red_chi2[id])
173
174
175 new_point = data[id] + g_error * error[id]
176
177
178 elif distribution == 'fixed':
179
180 new_point = gauss(data[id], float(fixed_error))
181
182
183 else:
184
185 new_point = gauss(data[id], error[id])
186
187
188 random[j][id] = new_point
189
190
191 api.sim_pack_data(data_index, random)
192
193
195 r"""Function for calculating errors from the Monte Carlo simulations.
196
197 The standard deviation formula used to calculate the errors is the square root of the
198 bias-corrected variance, given by the formula::
199
200 __________________________
201 / 1
202 sd = / ----- * sum({Xi - Xav}^2)
203 \/ n - 1
204
205 where
206 - n is the total number of simulations.
207 - Xi is the parameter value for simulation i.
208 - Xav is the mean parameter value for all simulations.
209 """
210
211
212 check_pipe()
213
214
215 if not hasattr(cdp, 'sim_state'):
216 raise RelaxError("Monte Carlo simulations have not been set up.")
217
218
219 api = return_api()
220
221
222 for model_info in api.model_loop():
223
224 select_sim = api.sim_return_selected(model_info=model_info)
225
226
227 index = 0
228 while True:
229
230 param_array = api.sim_return_param(index, model_info=model_info)
231
232
233 if param_array == None:
234 break
235
236
237 if isinstance(param_array[0], dict):
238
239 sd = {}
240
241
242 for key in param_array[0]:
243
244 data = []
245 for i in range(len(param_array)):
246 data.append(param_array[i][key])
247
248
249 sd[key] = statistics.std(values=data, skip=select_sim)
250
251
252 elif isinstance(param_array[0], list):
253
254 sd = []
255
256
257 for j in range(len(param_array[0])):
258
259 data = []
260 for i in range(len(param_array)):
261 data.append(param_array[i][j])
262
263
264 sd.append(statistics.std(values=data, skip=select_sim))
265
266
267 elif param_array[0] != None:
268 sd = statistics.std(values=param_array, skip=select_sim)
269
270
271 else:
272 sd = None
273
274
275 api.set_error(index, sd, model_info=model_info)
276
277
278 index = index + 1
279
280
281 cdp.sim_state = False
282
283
285 """Set the initial simulation parameter values."""
286
287
288 check_pipe()
289
290
291 if not hasattr(cdp, 'sim_state'):
292 raise RelaxError("Monte Carlo simulations have not been set up.")
293
294
295 api = return_api()
296
297
298 api.sim_init_values()
299
300
302 """Turn simulations off."""
303
304
305 check_pipe()
306
307
308 if not hasattr(cdp, 'sim_state'):
309 raise RelaxError("Monte Carlo simulations have not been set up.")
310
311
312 cdp.sim_state = False
313
314
316 """Turn simulations on."""
317
318
319 check_pipe()
320
321
322 if not hasattr(cdp, 'sim_state'):
323 raise RelaxError("Monte Carlo simulations have not been set up.")
324
325
326 cdp.sim_state = True
327
328
330 """Set the select flag of all simulations of all models to one.
331
332 @keyword number: The number of Monte Carlo simulations to set up.
333 @type number: int
334 @keyword all_select_sim: The selection status of the Monte Carlo simulations. The first
335 dimension of this matrix corresponds to the simulation and the
336 second corresponds to the models.
337 @type all_select_sim: list of lists of bool
338 """
339
340
341 api = return_api()
342
343
344 if all_select_sim == None:
345 select_sim = [True]*number
346
347
348 i = 0
349 for model_info in api.model_loop():
350
351 if api.skip_function(model_info=model_info):
352 continue
353
354
355 if all_select_sim != None:
356 select_sim = all_select_sim[i]
357
358
359 api.set_selected_sim(select_sim, model_info=model_info)
360
361
362 i += 1
363
364
366 """Store the Monte Carlo simulation number.
367
368 @keyword number: The number of Monte Carlo simulations to set up.
369 @type number: int
370 @keyword all_select_sim: The selection status of the Monte Carlo simulations. The first dimension of this matrix corresponds to the simulation and the second corresponds to the instance.
371 @type all_select_sim: list of lists of bool
372 """
373
374
375 check_pipe()
376
377
378 if number < 3:
379 raise RelaxError("A minimum of 3 Monte Carlo simulations is required.")
380
381
382 cdp.sim_number = number
383 cdp.sim_state = True
384
385
386 monte_carlo_select_all_sims(number=number, all_select_sim=all_select_sim)
387