From 2f5b7ae8f7d98e30a7db668dc1569b69f92b7df4 Mon Sep 17 00:00:00 2001 From: rowanc1 Date: Thu, 16 Jan 2014 10:06:00 -0800 Subject: [PATCH] Moving functions around into the new framework. Added requiresProblem annotation. --- SimPEG/forward/Data.py | 81 +++++++++++++++++++++++++++++++++++-- SimPEG/forward/Problem.py | 13 ------ SimPEG/inverse/Inversion.py | 13 ------ SimPEG/utils/__init__.py | 8 ++-- 4 files changed, 81 insertions(+), 34 deletions(-) diff --git a/SimPEG/forward/Data.py b/SimPEG/forward/Data.py index 86123003..bc18e2a5 100644 --- a/SimPEG/forward/Data.py +++ b/SimPEG/forward/Data.py @@ -1,6 +1,37 @@ from SimPEG import utils +def requiresProblem(f): + """ + Use this to wrap a funciton:: + + @requiresProblem + def dpred(self): + pass + + This wrapper will ensure that a problem has been bound to the data. + If a problem is not bound an Exception will be raised, and an nice error message printed. + """ + extra = """ + This function requires that a problem be bound to the data. + If a problem has not been bound, an Exception will be raised. + To bind a problem to the Data object:: + + data.setProblem(myProblem) + """ + from functools import wraps + @wraps(f) + def requiresProblemWrapper(self,*args,**kwargs): + if getattr(self, 'prob', None) is None: + raise Exception(extra) + return f(self,*args,**kwargs) + + doc = requiresProblemWrapper.__doc__ + requiresProblemWrapper.__doc__ = ('' if doc is None else doc) + extra + + return requiresProblemWrapper + + class SimPEGData(object): """Data holds the observed data, and the standard deviations.""" @@ -10,11 +41,55 @@ class SimPEGData(object): dobs = None #: Observed data dtrue = None #: True data, if data is synthetic mtrue = None #: True model, if data is synthetic + prob = None #: The geophysical problem that explains this data - def __init__(self, prob, **kwargs): + + def __init__(self, **kwargs): utils.setKwargs(self, **kwargs) - self.prob = prob def isSynthetic(self): "Check if the data is synthetic." - return self.mtrue is not None + return (self.mtrue is not None) + + def setProblem(self, prob): + self.prob = prob + + @property + def Wd(self): + """ + Standard deviation weighting matrix. + + By default, this is based on the norm of the data plus a noise floor. + + """ + if getattr(self,'_Wd',None) is None: + eps = np.linalg.norm(utils.mkvc(self.dobs),2)*1e-5 + self._Wd = 1/(abs(self.dobs)*self.std+eps) + return self._Wd + @Wd.setter + def Wd(self, value): + self._Wd = value + + @requiresProblem + def dpred(self, m, u=None): + pass + + def residual(self, m, u=None): + pass + + def residualWeighted(self, m, u=None): + pass + + def projectField(self, m, u=None): + """ + Projection matrix. + + .. math:: + d_\\text{pred} = Pu(m) + """ + return self.P*u + + +if __name__ == '__main__': + d = SimPEGData() + d.dpred() diff --git a/SimPEG/forward/Problem.py b/SimPEG/forward/Problem.py index adc825cc..2b2af6d1 100644 --- a/SimPEG/forward/Problem.py +++ b/SimPEG/forward/Problem.py @@ -55,19 +55,6 @@ class Problem(object): def RHS(self, value): self._RHS = value - @property - def P(self): - """ - Projection matrix. - - .. math:: - d_\\text{pred} = Pu(m) - """ - return self._P - @P.setter - def P(self, value): - self._P = value - @utils.count def dpred(self, m, u=None): """ diff --git a/SimPEG/inverse/Inversion.py b/SimPEG/inverse/Inversion.py index 926f719a..44b3e57b 100644 --- a/SimPEG/inverse/Inversion.py +++ b/SimPEG/inverse/Inversion.py @@ -42,19 +42,6 @@ class BaseInversion(object): opt.bfgsH0 = SimPEG.Solver(reg.modelObj2Deriv()) - @property - def Wd(self): - """ - Standard deviation weighting matrix. - """ - if getattr(self,'_Wd',None) is None: - eps = np.linalg.norm(utils.mkvc(self.data.dobs),2)*1e-5 - self._Wd = 1/(abs(self.data.dobs)*self.data.std+eps) - return self._Wd - @Wd.setter - def Wd(self, value): - self._Wd = value - @property def phi_d_target(self): """ diff --git a/SimPEG/utils/__init__.py b/SimPEG/utils/__init__.py index d20c2cec..ab67b25d 100644 --- a/SimPEG/utils/__init__.py +++ b/SimPEG/utils/__init__.py @@ -98,7 +98,7 @@ def callHooks(match, mainFirst=False): def doEndIteration(self): pass - This will call everything named _doEndIteration* at the beginning of the function call. + This will call everything named _doEndIteration* at the beginning of the function call. By default the master method (doEndIteration) is run after all of the sub methods (_doEndIteration*). This can be reversed by adding the mainFirst=True kwarg. """ @@ -131,10 +131,8 @@ def callHooks(match, mainFirst=False): Where the * can be any string. If present, _%s* will be called at the start of the default %s call. You may also completely overwrite this function. """ % (match, match, match, match) - try: - wrapper.__doc__ += extra - except Exception, e: - pass + doc = wrapper.__doc__ + wrapper.__doc__ = ('' if doc is None else doc) + extra return wrapper return callHooksWrap