diff --git a/SimPEG/DataMisfit.py b/SimPEG/DataMisfit.py index 870b5880..417b94e1 100644 --- a/SimPEG/DataMisfit.py +++ b/SimPEG/DataMisfit.py @@ -85,6 +85,20 @@ class BaseDataMisfit(object): """ raise NotImplementedError('This method should be overwritten.') + def target(self, forward): + """target(forward) + + Target for data misfit. By default this is the number of data, + which satisfies the Discrepancy Principle. + + :param Problem,Survey forward: forward simulation + :rtype: float + :return: data misfit target + + """ + prob, survey = self.splitForward(forward) + return survey.nD + class l2_DataMisfit(object): """ diff --git a/SimPEG/Inversion.py b/SimPEG/Inversion.py index b380b3df..cd571afe 100644 --- a/SimPEG/Inversion.py +++ b/SimPEG/Inversion.py @@ -5,7 +5,10 @@ import Directives class BaseInversion(object): - """BaseInversion(invProb, opt, **kwargs) + """ + + Inversion Class. + """ __metaclass__ = Utils.SimPEGMetaClass diff --git a/SimPEG/Maps.py b/SimPEG/Maps.py index 882af375..9b032889 100644 --- a/SimPEG/Maps.py +++ b/SimPEG/Maps.py @@ -1,6 +1,42 @@ import Utils, numpy as np, scipy.sparse as sp from Tests import checkDerivative +class Model(np.ndarray): + + def __new__(cls, input_array, mapping=None): + # Input array is an already formed ndarray instance + # We first cast to be our class type + obj = np.asarray(input_array).view(cls) + # add the new attribute to the created instance + obj.mapping = mapping + # Finally, we must return the newly created object: + return obj + + def __array_finalize__(self, obj): + # see InfoArray.__array_finalize__ for comments + if obj is None: return + self.mapping = getattr(obj, 'mapping', None) + + @property + def mapping(self): + return self._mapping + @mapping.setter + def mapping(self, value): + self._mapping = value + + @property + def transform(self): + if getattr(self, '_transform', None) is None: + self._transform = self.mapping.transform(self.view(np.ndarray)) + return self._transform + + @property + def transformDeriv(self): + if getattr(self, '_transformDeriv', None) is None: + self._transformDeriv = self.mapping.transformDeriv(self.view(np.ndarray)) + return self._transformDeriv + + class IdentityMap(object): """ SimPEG Map @@ -76,7 +112,7 @@ class IdentityMap(object): return ComboMap(self.mesh, [self] + val.maps) elif isinstance(val, IdentityMap): return ComboMap(self.mesh, [self, val]) - elif type(val) is np.ndarray: + elif isinstance(val, np.ndarray): return self.transform(val) class NonLinearMap(object): @@ -381,7 +417,7 @@ class ComboMap(IdentityMap): return ComboMap(self.mesh, self.maps + val.maps) elif isinstance(val, IdentityMap): return ComboMap(self.mesh, self.maps + [val]) - elif type(val) is np.ndarray: + elif isinstance(val, np.ndarray): return self.transform(val) class ComplexMap(IdentityMap): diff --git a/SimPEG/Mesh/BaseMesh.py b/SimPEG/Mesh/BaseMesh.py index 9083e59d..78fe4140 100644 --- a/SimPEG/Mesh/BaseMesh.py +++ b/SimPEG/Mesh/BaseMesh.py @@ -238,7 +238,7 @@ class BaseMesh(object): :rtype: numpy.array with shape (nF, ) :return: projected face vector """ - assert type(fV) == np.ndarray, 'fV must be an ndarray' + assert isinstance(fV, np.ndarray), 'fV must be an ndarray' assert len(fV.shape) == 2 and fV.shape[0] == self.nF and fV.shape[1] == self.dim, 'fV must be an ndarray of shape (nF x dim)' return np.sum(fV*self.normals, 1) @@ -250,7 +250,7 @@ class BaseMesh(object): :rtype: numpy.array with shape (nE, ) :return: projected edge vector """ - assert type(eV) == np.ndarray, 'eV must be an ndarray' + assert isinstance(eV, np.ndarray), 'eV must be an ndarray' assert len(eV.shape) == 2 and eV.shape[0] == self.nE and eV.shape[1] == self.dim, 'eV must be an ndarray of shape (nE x dim)' return np.sum(eV*self.tangents, 1) @@ -511,7 +511,7 @@ class BaseRectangularMesh(BaseMesh): eX, eY, eZ = r(edgeVector, 'E', 'E', 'V') # Separates each component of the edgeVector into 3 vectors """ - assert (type(x) == list or type(x) == np.ndarray), "x must be either a list or a ndarray" + assert (type(x) == list or isinstance(x, np.ndarray)), "x must be either a list or a ndarray" assert xType in ['CC', 'N', 'F', 'Fx', 'Fy', 'Fz', 'E', 'Ex', 'Ey', 'Ez'], "xType must be either 'CC', 'N', 'F', 'Fx', 'Fy', 'Fz', 'E', 'Ex', 'Ey', or 'Ez'" assert outType in ['CC', 'N', 'F', 'Fx', 'Fy', 'Fz', 'E', 'Ex', 'Ey', 'Ez'], "outType must be either 'CC', 'N', 'F', Fx', 'Fy', 'Fz', 'E', 'Ex', 'Ey', or 'Ez'" assert format in ['M', 'V'], "format must be either 'M' or 'V'" @@ -519,7 +519,7 @@ class BaseRectangularMesh(BaseMesh): assert xType in outType, 'You cannot change type of components.' if type(x) == list: for i, xi in enumerate(x): - assert type(x) == np.ndarray, "x[%i] must be a numpy array" % i + assert isinstance(x, np.ndarray), "x[%i] must be a numpy array" % i assert xi.size == x[0].size, "Number of elements in list must not change." x_array = np.ones((x.size, len(x))) @@ -528,7 +528,7 @@ class BaseRectangularMesh(BaseMesh): x_array[:, i] = Utils.mkvc(xi) x = x_array - assert type(x) == np.ndarray, "x must be a numpy array" + assert isinstance(x, np.ndarray), "x must be a numpy array" x = x[:] # make a copy. xTypeIsFExyz = len(xType) > 1 and xType[0] in ['F', 'E'] and xType[1] in ['x', 'y', 'z'] diff --git a/SimPEG/Mesh/LogicallyRectMesh.py b/SimPEG/Mesh/LogicallyRectMesh.py index 41dd2641..b2dc6f55 100644 --- a/SimPEG/Mesh/LogicallyRectMesh.py +++ b/SimPEG/Mesh/LogicallyRectMesh.py @@ -34,7 +34,7 @@ class LogicallyRectMesh(BaseRectangularMesh, DiffOperators, InnerProducts): assert len(nodes) > 1, "len(node) must be greater than 1" for i, nodes_i in enumerate(nodes): - assert type(nodes_i) == np.ndarray, ("nodes[%i] is not a numpy array." % i) + assert isinstance(nodes_i, np.ndarray), ("nodes[%i] is not a numpy array." % i) assert nodes_i.shape == nodes[0].shape, ("nodes[%i] is not the same shape as nodes[0]" % i) assert len(nodes[0].shape) == len(nodes), "Dimension mismatch" diff --git a/SimPEG/Mesh/TensorMesh.py b/SimPEG/Mesh/TensorMesh.py index 41e670d5..ba5bd258 100644 --- a/SimPEG/Mesh/TensorMesh.py +++ b/SimPEG/Mesh/TensorMesh.py @@ -22,7 +22,7 @@ class BaseTensorMesh(BaseRectangularMesh): h_i = self._unitDimensions[i] * np.ones(int(h_i))/int(h_i) elif type(h_i) is list: h_i = Utils.meshTensor(h_i) - assert type(h_i) == np.ndarray, ("h[%i] is not a numpy array." % i) + assert isinstance(h_i, np.ndarray), ("h[%i] is not a numpy array." % i) assert len(h_i.shape) == 1, ("h[%i] must be a 1D numpy array." % i) h[i] = h_i[:] # make a copy. diff --git a/SimPEG/Mesh/TreeMesh.py b/SimPEG/Mesh/TreeMesh.py index 0ddd337b..dca39595 100644 --- a/SimPEG/Mesh/TreeMesh.py +++ b/SimPEG/Mesh/TreeMesh.py @@ -686,7 +686,7 @@ class TreeMesh(InnerProducts, BaseMesh): if type(h_i) in [int, long, float]: # This gives you something over the unit cube. h_i = np.ones(int(h_i))/int(h_i) - assert type(h_i) == np.ndarray, ("h[%i] is not a numpy array." % i) + assert isinstance(h_i, np.ndarray), ("h[%i] is not a numpy array." % i) assert len(h_i.shape) == 1, ("h[%i] must be a 1D numpy array." % i) h[i] = h_i[:] # make a copy. self.h = h diff --git a/SimPEG/Problem.py b/SimPEG/Problem.py index 671dc60e..7e69fcba 100644 --- a/SimPEG/Problem.py +++ b/SimPEG/Problem.py @@ -138,7 +138,7 @@ class BaseTimeProblem(BaseProblem): @timeSteps.setter def timeSteps(self, value): - if type(value) is np.ndarray: + if isinstance(value, np.ndarray): self._timeSteps = value del self.timeMesh return diff --git a/SimPEG/Survey.py b/SimPEG/Survey.py index 5d0da5c4..e33b7611 100644 --- a/SimPEG/Survey.py +++ b/SimPEG/Survey.py @@ -184,7 +184,7 @@ class Data(object): def __setitem__(self, key, value): tx, rx = self._ensureCorrectKey(key) assert rx is not None, 'set data using [Tx, Rx]' - assert type(value) == np.ndarray, 'value must by ndarray' + assert isinstance(value, np.ndarray), 'value must by ndarray' assert value.size == rx.nD, "value must have the same number of data as the transmitter." self._dataDict[tx][rx] = Utils.mkvc(value) @@ -347,7 +347,7 @@ class Fields(object): return self._getField(name, ind) def _setField(self, field, val, name, ind): - if type(val) is np.ndarray and (field.shape[1] == 1 or val.ndim == 1): + if isinstance(val, np.ndarray) and (field.shape[1] == 1 or val.ndim == 1): val = Utils.mkvc(val,2) field[:,ind] = val @@ -618,23 +618,3 @@ class BaseSurvey(object): noise = std*abs(self.dtrue)*np.random.randn(*self.dtrue.shape) self.dobs = self.dtrue+noise self.std = self.dobs*0 + std - - - #TODO: Move this to the survey class? - # @property - # def phi_d_target(self): - # """ - # target for phi_d - - # By default this is the number of data. - - # Note that we do not set the target if it is None, but we return the default value. - # """ - # if getattr(self, '_phi_d_target', None) is None: - # return self.data.dobs.size # - # return self._phi_d_target - - # @phi_d_target.setter - # def phi_d_target(self, value): - # self._phi_d_target = value - diff --git a/SimPEG/Utils/codeutils.py b/SimPEG/Utils/codeutils.py index c1d898a6..982289e4 100644 --- a/SimPEG/Utils/codeutils.py +++ b/SimPEG/Utils/codeutils.py @@ -140,14 +140,14 @@ def isScalar(f): scalarTypes = [float, int, long, np.float_, np.int_] if type(f) in scalarTypes: return True - elif type(f) == np.ndarray and f.size == 1 and type(f[0]) in scalarTypes: + elif isinstance(f, np.ndarray) and f.size == 1 and type(f[0]) in scalarTypes: return True return False def asArray_N_x_Dim(pts, dim): if type(pts) == list: pts = np.array(pts) - assert type(pts) == np.ndarray, "pts must be a numpy array" + assert isinstance(pts, np.ndarray), "pts must be a numpy array" if dim > 1: pts = np.atleast_2d(pts) diff --git a/SimPEG/Utils/lrmutils.py b/SimPEG/Utils/lrmutils.py index b641ef7f..f49d292f 100644 --- a/SimPEG/Utils/lrmutils.py +++ b/SimPEG/Utils/lrmutils.py @@ -75,7 +75,7 @@ def indexCube(nodes, gridSize, n=None): """ assert type(nodes) == str, "Nodes must be a str variable: e.g. 'ABCD'" - assert type(gridSize) == np.ndarray, "Number of nodes must be an ndarray" + assert isinstance(gridSize, np.ndarray), "Number of nodes must be an ndarray" nodes = nodes.upper() # Make sure that we choose from the possible nodes. possibleNodes = 'ABCD' if gridSize.size == 2 else 'ABCDEFGH' diff --git a/SimPEG/Utils/matutils.py b/SimPEG/Utils/matutils.py index 2e72f557..a93e6f07 100644 --- a/SimPEG/Utils/matutils.py +++ b/SimPEG/Utils/matutils.py @@ -26,7 +26,7 @@ def mkvc(x, numDims=1): if hasattr(x, 'tovec'): x = x.tovec() - assert type(x) == np.ndarray, "Vector must be a numpy array" + assert isinstance(x, np.ndarray), "Vector must be a numpy array" if numDims == 1: return x.flatten(order='F') @@ -119,7 +119,7 @@ def ndgrid(*args, **kwargs): xin = args # Each vector needs to be a numpy array - assert np.all([type(x) == np.ndarray for x in xin]), "All vectors must be numpy arrays." + assert np.all([isinstance(x, np.ndarray) for x in xin]), "All vectors must be numpy arrays." if len(xin) == 1: return xin[0] diff --git a/docs/api_Inverse.rst b/docs/api_Inverse.rst index ab711f81..bd4d8704 100644 --- a/docs/api_Inverse.rst +++ b/docs/api_Inverse.rst @@ -2,7 +2,7 @@ Regularization -============== +************** .. automodule:: SimPEG.Regularization :show-inheritance: @@ -10,16 +10,8 @@ Regularization :undoc-members: -Objective Function -================== - -.. automodule:: SimPEG.ObjFunction - :members: - :undoc-members: - - Optimize -======== +******** .. automodule:: SimPEG.Optimization :show-inheritance: @@ -27,8 +19,16 @@ Optimize :members: :undoc-members: +Directives +********** + +.. automodule:: SimPEG.Directives + :show-inheritance: + :members: + :undoc-members: + Inversion -========= +********* .. automodule:: SimPEG.Inversion :show-inheritance: diff --git a/docs/api_Parameters.rst b/docs/api_Parameters.rst deleted file mode 100644 index 1a333b88..00000000 --- a/docs/api_Parameters.rst +++ /dev/null @@ -1,11 +0,0 @@ -.. _api_Parameters: - - -Parameters -========== - -.. automodule:: SimPEG.Parameters - :show-inheritance: - :members: - :undoc-members: - :inherited-members: diff --git a/docs/index.rst b/docs/index.rst index 7b5f91e1..22709033 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -41,7 +41,6 @@ Forward Problems api_Problem api_Survey - api_Maps Inversion ********* @@ -51,7 +50,6 @@ Inversion api_DataMisfit api_Inverse - api_Parameters Utility Codes ************* @@ -60,6 +58,7 @@ Utility Codes :maxdepth: 2 api_Solver + api_Maps api_Utils