ReFRACtor
retrieval.py
Go to the documentation of this file.
1 import re
2 from collections import OrderedDict
3 
4 import numpy as np
5 
6 from .base import Creator
7 from .. import param
8 
9 from refractor import framework as rf
10 
12 
13  retrieval_components = param.Dict()
14  state_vector = param.InstanceOf(rf.StateVector)
15  initial_guess = param.Array(dims=1)
16 
17  def __init__(self, *vargs, **kwargs):
18  super().__init__(*vargs, **kwargs)
19 
20  def create(self, **kwargs):
21 
22  # The order these are accessed matters, store values into common for subsequent steps
23  retrieval_components = self.common_store["retrieval_components"] = self.retrieval_components()
24  state_vector = self.common_store["state_vector"] = self.state_vector()
25  initial_guess = self.common_store["initial_guess"] = self.initial_guess()
26 
27  return {
28  'retrieval_components': retrieval_components,
29  'state_vector': state_vector,
30  'initial_guess': initial_guess,
31  }
32 
34 
35  a_priori = param.Array(dims=1)
36  covariance = param.Array(dims=2)
37  solver = param.Choice(param.InstanceOf(rf.NLLSSolver), param.InstanceOf(rf.ConnorSolver))
38 
39  def __init__(self, *vargs, **kwargs):
40  super().__init__(*vargs, **kwargs)
41 
42  def create(self, **kwargs):
43  retrieval_objects = super().create(**kwargs)
44 
45  # The order these are accessed matters, store values into common for subsequent steps
46  a_priori = self.common_store["a_priori"] = self.a_priori()
47  covariance = self.common_store["covariance"] = self.covariance()
48  solver = self.common_store["solver"] = self.solver()
49 
50  retrieval_objects.update({
51  'a_priori': a_priori,
52  'covariance': covariance,
53  'solver': solver,
54  })
55 
56  return retrieval_objects
57 
59 
60  exclude = param.Iterable(default=None, required=False)
61  include = param.Iterable(default=None, required=False)
62  order = param.Iterable(default=[], required=False)
63 
64  def __init__(self, *vargs, **kwargs):
65  super().__init__(*vargs, **kwargs)
66 
67  self.register_to_receive(rf.SubStateVectorObserver)
68 
69  self.retrieval_components = OrderedDict()
70 
71  def receive(self, rec_obj):
72 
73  if hasattr(rec_obj, "sub_state_identifier") and rec_obj.coefficient.value.shape[0] > 0:
74  ss_iden = rec_obj.sub_state_identifier
75  self.retrieval_components[ss_iden] = rec_obj
76 
77  def is_included(self, iden):
78 
79  include_list = self.include()
80 
81  if include_list is None:
82  return True
83  else:
84  for incl_re in include_list:
85  if re.search(incl_re, iden):
86  return True
87  return False
88 
89  def is_excluded(self, iden):
90 
91  exclude_list = self.exclude()
92 
93  if exclude_list is None:
94  return False
95  else:
96  for excl_re in exclude_list:
97  if re.search(excl_re, iden):
98  return True
99  return False
100 
101  def create(self, **kwargs):
102 
103  filtered_components = []
104  for iden, obj in self.retrieval_components.items():
105  if self.is_included(iden) and not self.is_excluded(iden):
106  filtered_components.append( (iden, obj) )
107 
108  # Sort by the items listed in the order parameter
109  # falling back to the order of items originally recieved
110  order = self.order()
111  def sort_key(comp_tuple):
112  found_order = None
113  for idx, ord_item in enumerate(order):
114  if re.search(ord_item, comp_tuple[0]):
115  found_order = idx
116  break
117 
118  if found_order is not None:
119  return found_order
120  else:
121  # Add length of order array so items without a specific order
122  # come after any that match the specific ordering
123  dflt_order = len(order) + filtered_components.index(comp_tuple)
124  return dflt_order
125 
126  return OrderedDict(sorted(filtered_components, key=sort_key))
127 
129 
130  retrieval_components = param.Dict()
131 
132  def __init__(self, *vargs, **kwargs):
133  super().__init__(*vargs, **kwargs)
134 
135  self.register_to_receive(rf.StateVectorObserver)
136 
137  self.sv_observers = []
138 
139  def receive(self, rec_obj):
140 
141  if not hasattr(rec_obj, "sub_state_identifier") and rec_obj not in self.sv_observers:
142  self.sv_observers.append(rec_obj)
143 
144  def create(self, **kwargs):
145  sv = rf.StateVector()
146 
147  # Register retrieval components first as state vector observers
148  for observer in self.retrieval_components().values():
149  sv.add_observer(observer)
150 
151  # Add remaining non retrieval components as observers
152  for observer in self.sv_observers:
153  sv.add_observer(observer)
154 
155  return sv
156 
158 
159  retrieval_components = param.Dict()
160  state_vector = param.InstanceOf(rf.StateVector)
161 
162  def create(self, **kwargs):
163 
164  sv = self.state_vector()
165 
166  # Gather initial guess from retrieval components
167  ig_values = []
168  for ret_component in self.retrieval_components().values():
169  used_indexes = np.nonzero(ret_component.used_flag_value)
170  ig_values.append(ret_component.coefficient.value[used_indexes])
171 
172  if len(ig_values) == 0:
173  raise param.ParamError("InitialGuessFromSV: No initial guess values available as identified by the retrieval components")
174 
175  ig = np.concatenate(ig_values)
176 
177  if ig.shape[0] != sv.observer_claimed_size:
178  raise ValueError("The initial guess vector size %d does not match expected state vector size %d" % (ig.shape[0], sv.observer_claimed_size))
179 
180  return ig
181 
183 
184  initial_guess = param.Array(dims=1)
185 
186  def create(self, **kwargs):
187 
188  return self.initial_guess()
189 
191 
192  retrieval_components = param.Dict()
193  values = param.Dict()
194 
195  def create(self, **kwargs):
196 
197  cov_inputs = self.values()
198 
199  # Gather covariance arrays and do input checking
200  covariances = []
201  total_len = 0
202  for rc_name, rc_obj in self.retrieval_components().items():
203  if rc_name not in cov_inputs:
204  raise param.ParamError("CovarianceByComponent: covariance values argument is missing data for this retrieval component: %s" % rc_name)
205 
206  rc_cov = cov_inputs[rc_name]
207 
208  if not hasattr(rc_cov, "shape"):
209  raise param.ParamError("CovarianceByComponent: value for retrieval component covariance must be a numpy array: %s" % rc_name)
210 
211  if len(rc_cov.shape) != 2:
212  raise param.ParamError("CovarianceByComponent: shape of array for retrieval component covariance must be 2: %s" % rc_name)
213 
214  if rc_cov.shape[0] != rc_cov.shape[1]:
215  raise param.ParamError("CovarianceByComponent: array for retrieval component must be a square matrix: %s" % rc_name)
216 
217  flag = rc_obj.used_flag_value
218 
219  if flag.shape[0] != rc_cov.shape[0]:
220  raise param.ParamError("CovarianceByComponent: covariance shape %s and and flag shape are mismatched: %s" % (flag.shape, rc_cov.shape, rc_name))
221 
222  used_indexes = np.nonzero(flag)
223  used_cov = rc_cov[np.ix_(used_indexes[0], used_indexes[0])]
224 
225  total_len += used_cov.shape[0]
226  covariances.append(used_cov)
227 
228  # Concatenate covariances along the diagonal
229  total_covariance = np.zeros((total_len, total_len), dtype=float)
230 
231  offset = 0
232  for idx, cov in enumerate(covariances):
233  total_covariance[offset:offset+cov.shape[0], offset:offset+cov.shape[1]] = cov
234  offset += cov.shape[0]
235 
236  return total_covariance
237 
239 
240  l1b = param.InstanceOf(rf.Level1b)
241  instrument = param.InstanceOf(rf.Instrument)
242  forward_model = param.InstanceOf(rf.ForwardModel)
243 
244  state_vector = param.InstanceOf(rf.StateVector)
245 
246  initial_guess = param.Array(dims=1)
247  a_priori = param.Array(dims=1)
248  covariance = param.Array(dims=2)
249 
250  max_iteration = param.Scalar(int)
251  max_divergence = param.Scalar(int)
252  max_chisq = param.Scalar(float)
253  threshold = param.Scalar(float)
254  gamma_initial = param.Scalar(float)
255 
256  def create(self, **kwargs):
257  sv = self.state_vector()
258  fm = self.forward_model()
259 
260  observation = rf.ObservationLevel1b(self.l1b(), self.instrument(), fm.spectral_grid)
261 
262  cost_func = rf.ConnorCostFunction(sv, fm, observation)
263  conv = rf.ConnorConvergence(fm,
264  self.threshold(),
265  self.max_iteration(),
266  self.max_divergence(),
267  self.max_chisq())
268 
269  # Create wrapper function to make the ConnorSolver interface match that of IterativeSolver
270  # for at least the solve routine
271  def create_solve_wrapper(conn_solver, conn_creator):
272  orig_solve_func = conn_solver.solve
273 
274  def solve_wrapper(**vargs):
275  "Automatically pass initial guess, apriori and covariance to solve routine if no arguments supplied"
276 
277  if len(vargs) == 3:
278  return orig_solve_func()
279  elif len(vargs) == 0:
280  return orig_solve_func(conn_creator.initial_guess(), conn_creator.a_priori(), conn_creator.covariance())
281  else:
282  raise Exception("Wrong number of arguments to ConnorSolver::solve. Expected 0 or 3 arguments.")
283 
284  return solve_wrapper
285 
286  solver = rf.ConnorSolver(cost_func, conv, self.gamma_initial())
287  solver.solve = create_solve_wrapper(solver, self)
288 
289  iter_log = rf.ConnorIterationLog(sv)
290  solver.add_observer(iter_log)
291 
292  return solver
293 
295 
296  l1b = param.InstanceOf(rf.Level1b)
297  instrument = param.InstanceOf(rf.Instrument)
298  forward_model = param.InstanceOf(rf.ForwardModel)
299 
300  state_vector = param.InstanceOf(rf.StateVector)
301 
302  initial_guess = param.Array(dims=1)
303  a_priori = param.Array(dims=1)
304  covariance = param.Array(dims=2)
305 
306  max_cost_function_calls = param.Scalar(int)
307 
308  def init_state_vector(self):
309 
310  self.state_vector().update_state(self.a_priori(), self.covariance())
311 
312  def opt_problem(self):
313  fm = self.forward_model()
314 
315  observation = rf.ObservationLevel1b(self.l1b(), self.instrument(), fm.spectral_grid)
316 
317  stat_method = rf.MaxAPosterioriStandard(fm, observation, self.state_vector(), self.a_priori(), self.covariance())
318 
319  opt_problem = rf.NLLSMaxAPosteriori(stat_method)
320 
321  # Initialize solver intitial guess
322  opt_problem.parameters = self.initial_guess()
323 
324  return opt_problem
325 
326  def attach_logging(self, solver):
327  iter_log = rf.SolverIterationLog(self.state_vector())
328  solver.add_observer(iter_log)
329 
331 
332  dx_tol_abs = param.Scalar(float)
333  dx_tol_rel = param.Scalar(float)
334  g_tol_abs = param.Scalar(float)
335 
336  def create(self, **kwargs):
337 
338  solver = rf.NLLSSolverGSLLMSDER(self.opt_problem(),
339  self.max_cost_function_calls(), self.dx_tol_abs(), self.dx_tol_rel(), self.g_tol_abs(),
340  True)
341 
342  self.init_state_vector()
343  self.attach_logging(solver)
344 
345  return solver
346 
348 
349  threshold = param.Scalar(float)
350  max_iteration = param.Scalar(int)
351  max_divergence = param.Scalar(int)
352  max_chisq = param.Scalar(float)
353  gamma_initial = param.Scalar(float)
354 
355  def create(self, **kwargs):
356 
357  conv = rf.ConnorConvergence(self.forward_model(), self.threshold(), self.max_iteration(), self.max_divergence(), self.max_chisq())
358 
359  solver = rf.ConnorSolverMAP(self.opt_problem(), conv,
360  self.max_cost_function_calls(), True,
361  self.gamma_initial())
362 
363  self.init_state_vector()
364  self.attach_logging(solver)
365 
366  return solver
367 
368 
370 
371  max_iteration = param.Scalar(int)
372 
373  dx_tol_abs = param.Scalar(float, default=1e-6)
374  dx_tol_rel = param.Scalar(float, default=1e-6)
375  g_tol_abs = param.Scalar(float, default=1e-6)
376  g_tol_rel = param.Scalar(float, default=1e-6)
377 
378  min_W = param.Scalar(float, required=False)
379  tr_rad_tol = param.Scalar(float, required=False)
380  tr_rad = param.Scalar(float, required=False)
381  cr_ratio_tol = param.Scalar(float, required=False)
382 
383  def create(self, **kwargs):
384 
385  # Class comes with defaults, only overwrite the defaults if the config has a value supplied
386  opts = rf.NLLSSolverLMOptions()
387 
388  if self.min_W() is not None:
389  opts.min_W = self.min_W()
390 
391  if self.tr_rad_tol() is not None:
392  opts.tr_rad_tol = self.tr_rad_tol()
393 
394  if self.tr_rad() is not None:
395  opts.tr_rad = self.tr_rad()
396 
397  if self.cr_ratio_tol() is not None:
398  opts.cr_ratio_tol = self.cr_ratio_tol()
399 
400  solver = rf.NLLSSolverLM(self.opt_problem(), self.max_iteration(), opts, self.dx_tol_abs(), self.dx_tol_rel(), self.g_tol_abs(), self.g_tol_rel())
401 
402  self.init_state_vector()
403  self.attach_logging(solver)
404 
405  return solver
def register_to_receive(self, RfType)
Definition: base.py:122

Copyright © 2017, California Institute of Technology.
ALL RIGHTS RESERVED.
U.S. Government Sponsorship acknowledged.
Generated Fri Aug 24 2018 15:44:10