Source code for pygimli.frameworks.timelapse
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
import pygimli as pg
from .modelling import MeshModelling
[docs]
class MultiFrameModelling(MeshModelling):
    """Full frame (multiple fop parallel) forward modelling."""
[docs]
    def __init__(self, modellingOperator, scalef=1.0, **ini):
        """Init class and jacobian matrix."""
        super().__init__()
        self.ini = ini
        self.modellingOperator = modellingOperator
        self.jac = pg.matrix.BlockMatrix()
        self.scalef = scalef
        self.fops = []
        self.nf = 0
        self.nm = 0 
[docs]
    def setData(self, data, modellingOperator=None, **ini):
        """Distribute the data containers amongst the fops."""
        modellingOperator = modellingOperator or self.modellingOperator
        ini = self.ini or ini
        self.fops = []
        for datai in data:
            fopi = modellingOperator(**ini)
            fopi.setData(datai)
            # fopi.setData(pg.Vector(datai))
            self.fops.append(fopi) 
[docs]
    def setMeshPost(self, mesh):
        """Set mesh to all forward operators."""
        for fop in self.fops:
            fop.setMesh(mesh, ignoreRegionManager=True)
        self.prepareJacobian() 
[docs]
    def setDefaultBackground(self):
        """Set the default background behaviour."""
        regionIds = self.regionManager().regionIdxs()
        pg.info("Found {} regions.".format(len(regionIds)))
        if len(regionIds) > 1:
            bk = pg.sort(regionIds)[0]
            pg.info("Region with smallest marker ({0}) "
                    "set to background".format(bk))
            self.setRegionProperties(bk, background=True) 
    @property
    def parameterCount(self):
        """Return number of parameters."""
        pc = self.regionManager().parameterCount()
        if pc == 0:
            pc = self.fops[0].parameterCount
        return pc * len(self.fops)
[docs]
    def prepareJacobian(self):
        """Build up Jacobian block matrix (once the sizes are known)."""
        self.jac.clear()
        self.nm = self.regionManager().parameterCount()
        if self.nm == 0:
            self.nm = self.fops[0].parameterCount
        self.nf = len(self.fops)
        print(self.nm, "model cells")
        nd = 0
        for i, fop in enumerate(self.fops):
            self.jac.addMatrix(fop.jacobian(), nd, i*self.nm)
            nd += fop.data.size()
        self.jac.recalcMatrixSize()
        self.setJacobian(self.jac) 
[docs]
    def createConstraints(self, C=None):
        """Create constraint matrix (special type for this)."""
        if C is not None:
            self.C1 = C
        elif isinstance(super().createConstraints(), pg.SparseMapMatrix):
            self.C1 = pg.SparseMapMatrix(self.constraintsRef())
            # make a copy because it will be overwritten
        else:
            self.C1 = self.constraints()
        self.C = pg.matrix.FrameConstraintMatrix(self.C1,
                                                 len(self.fops),
                                                 self.scalef)
        self.setConstraints(self.C)
        # cw = self.regionManager().constraintWeights()
        # self.regionManager().setConstraintsWeights(np.tile(cw, self.nf))
        # switch off automagic inside core.inversion which checks for
        # local modeltransform of the regionManager
        self.regionManager().setLocalTransFlag(False) 
[docs]
    def response(self, model):
        """Forward response."""
        mod = np.reshape(model, [len(self.fops), -1])
        return np.concatenate([fop.response(mo) for fop, mo in
                               zip(self.fops, mod)]) 
[docs]
    def createJacobian(self, model):
        """Create Jacobian matrix."""
        mod = np.reshape(model, [len(self.fops), -1])
        for i, fop in enumerate(self.fops):
            fop.createJacobian(mod[i]) 
[docs]
    def createDefaultStartModel(self):  # , dataVals):
        """Create standard starting model."""
        return pg.Vector(self.nm*self.nf, 10.0)  # look up in fop 
[docs]
    def createStartModel(self, dataVals):
        """Create a starting model from mean data values."""
        # return np.concatenate([f.createStartModel() for f in self.fops])
        self.nm = self.regionManager().parameterCount()
        return pg.Vector(self.nm*len(self.fops), np.median(dataVals))