<commit_before># -*- coding: utf-8 -*-
"""

Edited by Christian Münker, 2013
"""
from __future__ import print_function, division, unicode_literals
import sys, os

from PyQt4 import QtGui
from PyQt4.QtGui import QSizePolicy
from PyQt4.QtCore import QSize

#import matplotlib as plt
#from matplotlib.figure import Figure

import numpy as np
import scipy.signal as sig
# import filterbroker from one level above if this file is run as __main__
# for test purposes
if __name__ == "__main__":
    __cwd__ = os.path.dirname(os.path.abspath(__file__))
    sys.path.append(__cwd__ + '/..')

import filterbroker as fb

from plot_utils import MplWidget#, MyMplToolbar, MplCanvas

"""
QMainWindow is a class that understands GUI elements like a toolbar, statusbar,
central widget, docking areas. QWidget is just a raw widget.
When you want to have a main window for you project, use QMainWindow.

If you want to create a dialog box (modal dialog), use QWidget, or,
more preferably, QDialog
"""

class PlotHf(QtGui.QMainWindow):

    def __init__(self, parent = None, DEBUG = False): # default parent = None -> top Window
        super(PlotHf, self).__init__(parent) # initialize QWidget base class
#        QtGui.QMainWindow.__init__(self) # alternative syntax

        self.DEBUG = DEBUG

        self.lblLog = QtGui.QLabel("Log. y-scale")
        self.btnLog = QtGui.QCheckBox()
        self.btnLog.setChecked(True)
        self.lblInset = QtGui.QLabel("Show Inset")
        self.btnInset = QtGui.QCheckBox()
        self.lblSpecs = QtGui.QLabel("Show Specs")
        self.btnSpecs = QtGui.QCheckBox()
        self.lblPhase = QtGui.QLabel("Show Phase")
        self.btnPhase = QtGui.QCheckBox()
        self.btnSpecs.setChecked(False)

        self.hbox = QtGui.QHBoxLayout()
        self.hbox.addStretch(10)
        self.hbox.addWidget(self.lblLog)
        self.hbox.addWidget(self.btnLog)
        self.hbox.addStretch(1)
        self.hbox.addWidget(self.lblInset)
        self.hbox.addWidget(self.btnInset)
        self.hbox.addStretch(1)
        self.hbox.addWidget(self.lblSpecs)
        self.hbox.addWidget(self.btnSpecs)
        self.hbox.addStretch(1)
        self.hbox.addWidget(self.lblPhase)
        self.hbox.addWidget(self.btnPhase)
        self.hbox.addStretch(10)

        self.mplwidget = MplWidget()
#        self.mplwidget.setParent(self)

        self.mplwidget.vbox.addLayout(self.hbox)
#        self.mplwidget.vbox1.addWidget(self.mplwidget)

        self.mplwidget.setFocus()
        # make this the central widget, taking all available space:
        self.setCentralWidget(self.mplwidget)

#        self.setLayout(self.hbox)

        self.draw() # calculate and draw |H(f)|

#        #=============================================
#        # Signals & Slots
#        #=============================================
        self.btnLog.clicked.connect(lambda:self.draw())
        self.btnInset.clicked.connect(lambda:self.draw())
        self.btnSpecs.clicked.connect(lambda:self.draw())
        self.btnPhase.clicked.connect(lambda:self.draw())

    def plotSpecLimits(self, specAxes, specLog):
        """
        Plot the specifications limits
        """
#        fc = (0.8,0.8,0.8) # color for shaded areas
        fill_params = {"color":"none","hatch":"/", "edgecolor":"k", "lw":0.0}
        ax = specAxes
        ymax = ax.get_ylim()[1]
        F_max = self.f_S/2
        if specLog:
            if fb.gD['selFilter']['ft'] == "FIR":
                A_pb_max = self.A_pb # 20*log10(1+del_DB)
            else: # IIR log
                A_pb_max = 0
            A_pb_min = -self.A_pb
            A_pb_minx = A_pb_min - 10# 20*log10(1-del_DB)
            A_sb = -self.A_sb
            A_sbx = A_sb - 10
        else:
            if fb.gD['selFilter']['ft'] == 'FIR':
                A_pb_max = 10**(self.A_pb/20)# 1 + del_DB
            else:
                A_pb_max = 1
            A_pb_min = 10**(-self.A_pb/20) #1 - del_DB
            A_pb_minx = A_pb_min / 2
            A_sb = 10**(-self.A_sb/20)
            A_sbx = A_sb / 5

        F_pb = self.F_pb
        F_sb = fb.gD['selFilter']['F_sb'] / self.f_S
        F_sb2 = fb.gD['selFilter']['F_sb2'] / self.f_S
        F_pb2 = fb.gD['selFilter']['F_pb2'] / self.f_S

        if fb.gD['selFilter']['rt'] == 'LP':
            # upper limits:
            ax.plot([0, F_sb, F_sb, F_max],
                    [A_pb_max, A_pb_max, A_sb, A_sb], 'b--')
            ax.fill_between([0, F_sb, F_sb, F_max], ymax,
                    [A_pb_max, A_pb_max, A_sb, A_sb], **fill_params)
            # lower limits:
            ax.plot([0, F_pb, F_pb],[A_pb_min, A_pb_min, A_pb_minx], 'b--')
            ax.fill_between([0, F_pb, F_pb], A_pb_minx,
                            [A_pb_min, A_pb_min, A_pb_minx], **fill_params)

        if fb.gD['selFilter']['rt'] == 'HP':
            # upper limits:
            ax.plot([0, F_sb, F_sb, F_max],
                    [A_sb, A_sb, A_pb_max, A_pb_max], 'b--')
            ax.fill_between([0, F_sb, F_sb, F_max], 10,
                    [A_sb, A_sb, A_pb_max, A_pb_max], **fill_params)
            # lower limits:
            ax.plot([F_pb, F_pb, F_max],[A_pb_minx, A_pb_min, A_pb_min], 'b--')
            ax.fill_between([F_pb, F_pb, F_max], A_pb_minx,
                            [A_pb_minx, A_pb_min, A_pb_min], **fill_params)

        if fb.gD['selFilter']['rt'] == 'BS':
            # lower limits left:
            ax.plot([0, F_pb, F_pb],[A_pb_min, A_pb_min, A_pb_minx], 'b--')
            ax.fill_between([0, F_pb, F_pb], A_pb_minx,
                            [A_pb_min, A_pb_min, A_pb_minx], **fill_params)

            # upper limits:
            ax.plot([0, F_sb, F_sb, F_sb2, F_sb2, F_max],
                    [A_pb_max, A_pb_max, A_sb, A_sb, A_pb_max, A_pb_max], 'b--')
            ax.fill_between([0, F_sb, F_sb, F_sb2, F_sb2, F_max], 10,
                    [A_pb_max, A_pb_max, A_sb, A_sb, A_pb_max, A_pb_max],
                        **fill_params)

            # lower limits right:
            ax.plot([F_pb2, F_pb2, F_max],[A_pb_minx, A_pb_min, A_pb_min],'b--')
            ax.fill_between([F_pb2, F_pb2, F_max], A_pb_minx,
                            [A_pb_minx, A_pb_min, A_pb_min], **fill_params)

        if fb.gD['selFilter']['rt'] == "BP":
            # upper limits:
            ax.plot([0,    F_sb,  F_sb,      F_sb2,      F_sb2,  F_max],
                    [A_sb, A_sb, A_pb_max, A_pb_max, A_sb, A_sb], 'b--')
            ax.fill_between([0, F_sb, F_sb, F_sb2, F_sb2, F_max], 10,
                    [A_sb, A_sb, A_pb_max, A_pb_max, A_sb, A_sb],**fill_params)
            # lower limits:
            ax.plot([F_pb, F_pb, F_pb2, F_pb2],
                    [A_pb_minx, A_pb_min, A_pb_min, A_pb_minx], 'b--' )
            ax.fill_between([F_pb, F_pb, F_pb2, F_pb2], A_pb_minx,
                    [A_pb_minx, A_pb_min, A_pb_min, A_pb_minx], **fill_params)

    def draw(self):
        """
        Re-calculate |H(f)| and draw the figure
        """
        self.log = self.btnLog.isChecked()
        self.specs = self.btnSpecs.isChecked()
        self.inset = self.btnInset.isChecked()
        self.phase = self.btnPhase.isChecked()

#        self.coeffs = fb.gD['coeffs']# coeffs
        self.bb = fb.gD['coeffs'][0]
        self.aa = fb.gD['coeffs'][1]

        self.f_S = fb.gD['selFilter']['fS']
        self.f_S = 1
        self.F_pb = fb.gD['selFilter']['F_pb'] / self.f_S
        self.F_sb = fb.gD['selFilter']['F_sb'] / self.f_S

        self.A_pb = fb.gD['selFilter']['A_pb']
        self.A_sb = fb.gD['selFilter']['A_sb']

        if self.DEBUG:
            print("--- plotHf.draw() --- ")
            print("b, a = ", self.bb, self.aa)

        # calculate |H(W)| for W = 0 ... pi:
        [W,H] = sig.freqz(self.bb, self.aa, worN = fb.gD['N_FFT'])
        F = W / (2 * np.pi)

        # clear the axes and (re)draw the plot
        #
        fig = self.mplwidget.fig
        ax = self.mplwidget.ax# fig.add_axes([.1,.1,.8,.8])#  ax = fig.add_axes([.1,.1,.8,.8])
#        ax2= self.mplwidget.ax2
        ax.clear()

        #================ Main Plotting Routine =========================

        if self.log:
            ax.plot(F,20*np.log10(abs(H)), lw = fb.gD['rc']['lw'])

            ax.set_ylabel(r'$|H(\mathrm{e}^{\mathrm{j} \Omega})|$'+ ' in dB ' +
                        r'$\rightarrow$')

        else: #  'lin'
            ax.plot(F,abs(H), lw = fb.gD['rc']['lw'])

            ax.set_ylabel(r'$|H(\mathrm{e}^{\mathrm{j} \Omega})| \;$'+
                        r'$\rightarrow $')

        if self.specs: self.plotSpecLimits(specAxes = ax, specLog = self.log)

        if self.log:
            ax.axis([0, 0.5, -self.A_sb -10, self.A_pb +1] )
        else:
            ax.axis([0, 0.5, 10**((-self.A_sb-10)/20), 10**((self.A_pb+1)/20)])
        if self.phase:
            ax.plot(F,np.angle(H), lw = fb.gD['rc']['lw'])
            pass

        ax.set_title(r'Magnitude Frequency Response')
        ax.set_xlabel(r'$F\; \rightarrow $')

        # ---------- Inset Plot -------------------------------------------
        if self.inset:
            ax_i = fig.add_axes([0.65, 0.61, .3, .3]);  # x,y,dx,dy
#            ax1 = zoomed_inset_axes(ax, 6, loc=1) # zoom = 6
            ax_i.clear() # clear old plot and specs
            if self.specs: self.plotSpecs(specAxes = ax_i, specLog = self.log)
            if self.log:
                ax_i.plot(F,20*np.log10(abs(H)), lw = fb.gD['rc']['lw'])
            else:
                ax_i.plot(F,abs(H), lw = fb.gD['rc']['lw'])
#            ax1.set_xlim(0, self.F_pb)
#            ax1.set_ylim(-self.A_pb, self.A_pb)

        else:
            try:
#                for ax in fig.axes:
#                    fig.delaxes(ax)
                fig.delaxes(ax_i)
            except UnboundLocalError:
                pass

        self.mplwidget.redraw()

#------------------------------------------------------------------------------

def main():
    app = QtGui.QApplication(sys.argv)
    form = PlotHf()
    form.show()
    app.exec_()

if __name__ == "__main__":
    main()
<commit_msg>Renamed fS -> f_S Signed-off-by: chipmuenk <mail@chipmuenk.de><commit_after># -*- coding: utf-8 -*-
"""

Edited by Christian Münker, 2013
"""
from __future__ import print_function, division, unicode_literals
import sys, os

from PyQt4 import QtGui
from PyQt4.QtGui import QSizePolicy
from PyQt4.QtCore import QSize

#import matplotlib as plt
#from matplotlib.figure import Figure

import numpy as np
import scipy.signal as sig
# import filterbroker from one level above if this file is run as __main__
# for test purposes
if __name__ == "__main__":
    __cwd__ = os.path.dirname(os.path.abspath(__file__))
    sys.path.append(__cwd__ + '/..')

import filterbroker as fb

from plot_utils import MplWidget#, MyMplToolbar, MplCanvas

"""
QMainWindow is a class that understands GUI elements like a toolbar, statusbar,
central widget, docking areas. QWidget is just a raw widget.
When you want to have a main window for you project, use QMainWindow.

If you want to create a dialog box (modal dialog), use QWidget, or,
more preferably, QDialog
"""

class PlotHf(QtGui.QMainWindow):

    def __init__(self, parent = None, DEBUG = False): # default parent = None -> top Window
        super(PlotHf, self).__init__(parent) # initialize QWidget base class
#        QtGui.QMainWindow.__init__(self) # alternative syntax

        self.DEBUG = DEBUG

        self.lblLog = QtGui.QLabel("Log. y-scale")
        self.btnLog = QtGui.QCheckBox()
        self.btnLog.setChecked(True)
        self.lblInset = QtGui.QLabel("Show Inset")
        self.btnInset = QtGui.QCheckBox()
        self.lblSpecs = QtGui.QLabel("Show Specs")
        self.btnSpecs = QtGui.QCheckBox()
        self.lblPhase = QtGui.QLabel("Show Phase")
        self.btnPhase = QtGui.QCheckBox()
        self.btnSpecs.setChecked(False)

        self.hbox = QtGui.QHBoxLayout()
        self.hbox.addStretch(10)
        self.hbox.addWidget(self.lblLog)
        self.hbox.addWidget(self.btnLog)
        self.hbox.addStretch(1)
        self.hbox.addWidget(self.lblInset)
        self.hbox.addWidget(self.btnInset)
        self.hbox.addStretch(1)
        self.hbox.addWidget(self.lblSpecs)
        self.hbox.addWidget(self.btnSpecs)
        self.hbox.addStretch(1)
        self.hbox.addWidget(self.lblPhase)
        self.hbox.addWidget(self.btnPhase)
        self.hbox.addStretch(10)

        self.mplwidget = MplWidget()
#        self.mplwidget.setParent(self)

        self.mplwidget.vbox.addLayout(self.hbox)
#        self.mplwidget.vbox1.addWidget(self.mplwidget)

        self.mplwidget.setFocus()
        # make this the central widget, taking all available space:
        self.setCentralWidget(self.mplwidget)

#        self.setLayout(self.hbox)

        self.draw() # calculate and draw |H(f)|

#        #=============================================
#        # Signals & Slots
#        #=============================================
        self.btnLog.clicked.connect(lambda:self.draw())
        self.btnInset.clicked.connect(lambda:self.draw())
        self.btnSpecs.clicked.connect(lambda:self.draw())
        self.btnPhase.clicked.connect(lambda:self.draw())

    def plotSpecLimits(self, specAxes, specLog):
        """
        Plot the specifications limits
        """
#        fc = (0.8,0.8,0.8) # color for shaded areas
        fill_params = {"color":"none","hatch":"/", "edgecolor":"k", "lw":0.0}
        ax = specAxes
        ymax = ax.get_ylim()[1]
        F_max = self.f_S/2
        if specLog:
            if fb.gD['selFilter']['ft'] == "FIR":
                A_pb_max = self.A_pb # 20*log10(1+del_DB)
            else: # IIR log
                A_pb_max = 0
            A_pb_min = -self.A_pb
            A_pb_minx = A_pb_min - 10# 20*log10(1-del_DB)
            A_sb = -self.A_sb
            A_sbx = A_sb - 10
        else:
            if fb.gD['selFilter']['ft'] == 'FIR':
                A_pb_max = 10**(self.A_pb/20)# 1 + del_DB
            else:
                A_pb_max = 1
            A_pb_min = 10**(-self.A_pb/20) #1 - del_DB
            A_pb_minx = A_pb_min / 2
            A_sb = 10**(-self.A_sb/20)
            A_sbx = A_sb / 5

        F_pb = self.F_pb
        F_sb = fb.gD['selFilter']['F_sb'] / self.f_S
        F_sb2 = fb.gD['selFilter']['F_sb2'] / self.f_S
        F_pb2 = fb.gD['selFilter']['F_pb2'] / self.f_S

        if fb.gD['selFilter']['rt'] == 'LP':
            # upper limits:
            ax.plot([0, F_sb, F_sb, F_max],
                    [A_pb_max, A_pb_max, A_sb, A_sb], 'b--')
            ax.fill_between([0, F_sb, F_sb, F_max], ymax,
                    [A_pb_max, A_pb_max, A_sb, A_sb], **fill_params)
            # lower limits:
            ax.plot([0, F_pb, F_pb],[A_pb_min, A_pb_min, A_pb_minx], 'b--')
            ax.fill_between([0, F_pb, F_pb], A_pb_minx,
                            [A_pb_min, A_pb_min, A_pb_minx], **fill_params)

        if fb.gD['selFilter']['rt'] == 'HP':
            # upper limits:
            ax.plot([0, F_sb, F_sb, F_max],
                    [A_sb, A_sb, A_pb_max, A_pb_max], 'b--')
            ax.fill_between([0, F_sb, F_sb, F_max], 10,
                    [A_sb, A_sb, A_pb_max, A_pb_max], **fill_params)
            # lower limits:
            ax.plot([F_pb, F_pb, F_max],[A_pb_minx, A_pb_min, A_pb_min], 'b--')
            ax.fill_between([F_pb, F_pb, F_max], A_pb_minx,
                            [A_pb_minx, A_pb_min, A_pb_min], **fill_params)

        if fb.gD['selFilter']['rt'] == 'BS':
            # lower limits left:
            ax.plot([0, F_pb, F_pb],[A_pb_min, A_pb_min, A_pb_minx], 'b--')
            ax.fill_between([0, F_pb, F_pb], A_pb_minx,
                            [A_pb_min, A_pb_min, A_pb_minx], **fill_params)

            # upper limits:
            ax.plot([0, F_sb, F_sb, F_sb2, F_sb2, F_max],
                    [A_pb_max, A_pb_max, A_sb, A_sb, A_pb_max, A_pb_max], 'b--')
            ax.fill_between([0, F_sb, F_sb, F_sb2, F_sb2, F_max], 10,
                    [A_pb_max, A_pb_max, A_sb, A_sb, A_pb_max, A_pb_max],
                        **fill_params)

            # lower limits right:
            ax.plot([F_pb2, F_pb2, F_max],[A_pb_minx, A_pb_min, A_pb_min],'b--')
            ax.fill_between([F_pb2, F_pb2, F_max], A_pb_minx,
                            [A_pb_minx, A_pb_min, A_pb_min], **fill_params)

        if fb.gD['selFilter']['rt'] == "BP":
            # upper limits:
            ax.plot([0,    F_sb,  F_sb,      F_sb2,      F_sb2,  F_max],
                    [A_sb, A_sb, A_pb_max, A_pb_max, A_sb, A_sb], 'b--')
            ax.fill_between([0, F_sb, F_sb, F_sb2, F_sb2, F_max], 10,
                    [A_sb, A_sb, A_pb_max, A_pb_max, A_sb, A_sb],**fill_params)
            # lower limits:
            ax.plot([F_pb, F_pb, F_pb2, F_pb2],
                    [A_pb_minx, A_pb_min, A_pb_min, A_pb_minx], 'b--' )
            ax.fill_between([F_pb, F_pb, F_pb2, F_pb2], A_pb_minx,
                    [A_pb_minx, A_pb_min, A_pb_min, A_pb_minx], **fill_params)

    def draw(self):
        """
        Re-calculate |H(f)| and draw the figure
        """
        self.log = self.btnLog.isChecked()
        self.specs = self.btnSpecs.isChecked()
        self.inset = self.btnInset.isChecked()
        self.phase = self.btnPhase.isChecked()

#        self.coeffs = fb.gD['coeffs']# coeffs
        self.bb = fb.gD['coeffs'][0]
        self.aa = fb.gD['coeffs'][1]

        self.f_S = fb.gD['selFilter']['f_S']
        self.f_S = 1
        self.F_pb = fb.gD['selFilter']['F_pb'] / self.f_S
        self.F_sb = fb.gD['selFilter']['F_sb'] / self.f_S

        self.A_pb = fb.gD['selFilter']['A_pb']
        self.A_sb = fb.gD['selFilter']['A_sb']

        if self.DEBUG:
            print("--- plotHf.draw() --- ")
            print("b, a = ", self.bb, self.aa)

        # calculate |H(W)| for W = 0 ... pi:
        [W,H] = sig.freqz(self.bb, self.aa, worN = fb.gD['N_FFT'])
        F = W / (2 * np.pi)

        # clear the axes and (re)draw the plot
        #
        fig = self.mplwidget.fig
        ax = self.mplwidget.ax# fig.add_axes([.1,.1,.8,.8])#  ax = fig.add_axes([.1,.1,.8,.8])
#        ax2= self.mplwidget.ax2
        ax.clear()

        #================ Main Plotting Routine =========================

        if self.log:
            ax.plot(F,20*np.log10(abs(H)), lw = fb.gD['rc']['lw'])

            ax.set_ylabel(r'$|H(\mathrm{e}^{\mathrm{j} \Omega})|$'+ ' in dB ' +
                        r'$\rightarrow$')

        else: #  'lin'
            ax.plot(F,abs(H), lw = fb.gD['rc']['lw'])

            ax.set_ylabel(r'$|H(\mathrm{e}^{\mathrm{j} \Omega})| \;$'+
                        r'$\rightarrow $')

        if self.specs: self.plotSpecLimits(specAxes = ax, specLog = self.log)

        if self.log:
            ax.axis([0, 0.5, -self.A_sb -10, self.A_pb +1] )
        else:
            ax.axis([0, 0.5, 10**((-self.A_sb-10)/20), 10**((self.A_pb+1)/20)])
        if self.phase:
            ax.plot(F,np.angle(H), lw = fb.gD['rc']['lw'])
            pass

        ax.set_title(r'Magnitude Frequency Response')
        ax.set_xlabel(r'$F\; \rightarrow $')

        # ---------- Inset Plot -------------------------------------------
        if self.inset:
            ax_i = fig.add_axes([0.65, 0.61, .3, .3]);  # x,y,dx,dy
#            ax1 = zoomed_inset_axes(ax, 6, loc=1) # zoom = 6
            ax_i.clear() # clear old plot and specs
            if self.specs: self.plotSpecs(specAxes = ax_i, specLog = self.log)
            if self.log:
                ax_i.plot(F,20*np.log10(abs(H)), lw = fb.gD['rc']['lw'])
            else:
                ax_i.plot(F,abs(H), lw = fb.gD['rc']['lw'])
#            ax1.set_xlim(0, self.F_pb)
#            ax1.set_ylim(-self.A_pb, self.A_pb)

        else:
            try:
#                for ax in fig.axes:
#                    fig.delaxes(ax)
                fig.delaxes(ax_i)
            except UnboundLocalError:
                pass

        self.mplwidget.redraw()

#------------------------------------------------------------------------------

def main():
    app = QtGui.QApplication(sys.argv)
    form = PlotHf()
    form.show()
    app.exec_()

if __name__ == "__main__":
    main()
<|endoftext|>


<commit_before>from __future__ import print_function, absolute_import, division
from numpy import *
from .variables import *

class SolvingStrategy:

    def __init__(self, model_part, scheme, builder_and_solver):
        self.model_part = model_part
        self.scheme = scheme
        self.builder_and_solver = builder_and_solver
        self.A = zeros((0, 0))
        self.b = zeros((0))
        self.dx = zeros((0))

    def Initialize(self):
        # find list of dofs
        self.builder_and_solver.SetupDofSet()

        # allocate memory for the system
        self.A, self.x, self.b = self.builder_and_solver.SetupSystem(
            self.A, self.dx, self.b)

    def Solve(self):
        # eventually do prediction
        self.scheme.Predict()

        # do build and solve
        self.A, self.dx, self.b = self.builder_and_solver.BuildAndSolve(
            self.A, self.x, self.b)

        # call scheme to do update
        self.scheme.Update(self.builder_and_solver.dofset, self.dx)

    def SpyMatrix(self):
        try:
            import matplotlib.pylab as pl
            pl.spy(self.A)
            pl.show()
        except:
            raise Exception(
                "error in function Spy. Probably matplotlib not installed")
<commit_msg>minor correction<commit_after>from __future__ import print_function, absolute_import, division
from numpy import *
from .variables import *

class SolvingStrategy:

    def __init__(self, model_part, scheme, builder_and_solver):
        self.model_part = model_part
        self.scheme = scheme
        self.builder_and_solver = builder_and_solver
        self.A = zeros((0, 0))
        self.b = zeros((0))
        self.dx = zeros((0))

    def Initialize(self):
        # find list of dofs
        self.builder_and_solver.SetupDofSet()

        # allocate memory for the system
        self.A, self.dx, self.b = self.builder_and_solver.SetupSystem(
            self.A, self.dx, self.b)

    def Solve(self):
        # eventually do prediction
        self.scheme.Predict()

        # do build and solve
        self.A, self.dx, self.b = self.builder_and_solver.BuildAndSolve(
            self.A, self.dx, self.b)

        # call scheme to do update
        self.scheme.Update(self.builder_and_solver.dofset, self.dx)

    def ComputeReactionsVector(self):
        self.A, self.dx, self.b = self.builder_and_solver.Build(
            self.A, self.dx, self.b)
        return self.b

    def SpyMatrix(self):
        try:
            import matplotlib.pylab as pl
            pl.spy(self.A)
            pl.show()
        except:
            raise Exception(
                "error in function Spy. Probably matplotlib not installed")
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
from py_privatekonomi.utilities import helper
from py_privatekonomi.utilities.common import as_obj, is_string
from py_privatekonomi.utilities.proxy import HookProxy
from py_privatekonomi.core import loader
from py_privatekonomi.core.error import (MissingAppFunctionError, FormatterError, ParserError)
import py_privatekonomi.core.db

class AppProxy(HookProxy):
    def __init__(self, objname, obj):
        super(AppProxy, self).__init__(objname, obj)
        self.__called = []

    def _pre( self, name, *args, **kwargs ):
        self.__called.append(name)

    def _post(self, name, *args, **kwargs ):
        pass

    def _pre_run(self, *args, **kwargs ):
        if super(AppProxy, self).getObj().isBuilt() and len(self.__called) > 0:
            if len(self.__called) == 1 and self.__called[0] == 'run':
                return
            raise Exception("Following methods called without building first: %s" % (repr(self.__called)))

    def _post_run(self, *args, **kwargs):
        self.__called = []

    def _post_build(self, *args, **kwargs):
        self.__called = []

    def __repr__(self):
        return super(AppProxy, self).getObj().__repr__()

class App(object):
    def __init__(self):
        self.__formatter = None
        self.__parser = None
        self.__sources = []
        self.__persist = False
        self.__config =  {}
        self.__db = {}
        self.__output = None
        self.__auto_discover = False
        self.__discover_from = None
        self.app = None

    def setFormatter(self, formatter_name):
        self.__formatter = formatter_name

    def setParser(self, parser_name):
        self.__parser = parser_name

    def addSource(self, source_name):
        self.__sources.append(source_name)

    def addSources(self, source_names):
        self.__sources.extend(source_names)

    def clearSources(self):
        self.__sources = []

    def persistWith(self, database_settings):
        self.__persist = True
        self.__db = database_settings

    def setOutput(self, output):
        """ Setting the output will avoid calling execute, but
        may still trigger a call to persist.
        If output is set, the building process will not consider
        formatter, parser, or source(s) """
        self.__output = output

    def autodiscover(self, discover_from):
        """ This will attempt to guess the formatter
            and parser given a list of parsers and formatters of format:
            discover_from = [
                {
                    'formatter' : 'swedbank',
                    'parser' : 'swedbank'
                }, { ... }
            ]
        """
        if self.__formatter is not None:
            raise Exception("Unable to autodiscover; Formatter is already set to: %s" % (self.__formatter))
        if self.__parser is not None:
            raise Exception("Unable to autodiscover; Parser is already set to: %s" % (self.__parser))
        self.__auto_discover = True
        self.__discover_from = discover_from

    def config(self, conf):
        self.__config.update(conf)

    def isBuilt(self):
        return self.app is not None

    def __set_parser(self, core):
        self.app['parser'] = None
        if self.__parser is not None:
            self.app['parser'] = self.__load_parser(self.__parser, core)

    def __set_formatter(self, core):
        self.app['formatter'] = None
        if self.__formatter is not None:
            self.app['formatter'] = self.__load_formatter(self.__formatter, core)

    def __load_formatter(self, formatter_name, core):
        return loader.load_formatter(formatter_name, core['factories']['formatters']['account_formatter_factory'])

    def __load_parser(self, parser_name, core):
        return loader.load_parser(parser_name, core['factories']['parsers']['account_parser_factory'])

    def __autodiscover(self, core):
        self.app['formatter'] = None
        self.app['parser'] = None
        for discover in self.__discover_from:
            formatter = self.__load_formatter(discover['formatter'], core)
            if formatter is not None:
                parser = self.__load_parser(discover['parser'], core)
                if parser is not None:
                    self.app['formatter'] = formatter
                    self.app['parser'] = parser
                    return True
        return False

    def build(self):
        self.app = {}
        core = loader.load_core()
        self.app['core'] = core
        if len(self.__db) > 0:
            self.__config['database'] = self.__db
        if self.__output is None and self.__auto_discover is False:
            if self.__formatter is None:
                raise Exception("Formatter has not been specified, please call setFormatter, setOutput, or autodiscover")
            if self.__parser is None:
                raise Exception("Parser has not been specified, please call setParser, setOutput, or autodiscover")
            if len(self.__sources) == 0:
                raise Exception("Sources have not been specified, please call addSource, setOutput, or autodiscover")
            self.__set_parser(self.app['core'])
            self.__set_formatter(self.app['core'])
        elif self.__auto_discover is True:
            found = self.__autodiscover(self.app['core'])
            if not found:
                raise Exception("Unable to find parser/formatter from %s" % (repr(self.__discover_from)))

        return self

    def run(self):
        def __execute():
            if self.__auto_discover is True:
                found = False
                for discover in self.__discover_from:
                    try:
                        parser = self.__load_parser(discover['parser'], self.app['core'])
                        formatter = self.__load_formatter(discover['formatter'],  self.app['core'])
                        if parser is None or formatter is None:
                            continue
                        output = self.execute(
                            sources=self.__sources,
                            parser=parser,
                            formatter=formatter,
                            configs=as_obj(self.__config))
                        self.app['parser'] = discover['parser']
                        self.app['formatter'] = discover['formatter']
                        found = True
                        break
                    except FormatterError as e:
                        continue
                    except ParserError as e:
                        continue
                if found is False:
                    raise Exception("Unable to parse/format using parsers and formatters from %s" % (repr(self.__discover_from)))
            else:
                output = self.execute(self.__sources, self.app['parser'], self.app['formatter'], as_obj(self.__config))
            return output

        if self.app is None:
            raise Exception("Build app using app.build() before running.")
        ret = {}
        if self.__output is not None:
            ret['execute'] = self.__output
            ret['formatter'] = 'unknown'
            ret['parser'] = 'unknown'
        else:
            if 'execute' not in dir(self):
                raise MissingAppFunctionError(capture_data={
                    'fun_name' : 'execute',
                    'app' : self.app
                })
            ret['execute'] = __execute()
            if not is_string(self.app['formatter']):
                ret['formatter'] = self.app['formatter'].getName()
            if not is_string(self.app['parser']):
                ret['parser'] = self.app['parser'].getName()
        if self.__persist is True:
            if 'persist' not in dir(self):
                raise MissingAppFunctionError(capture_data={
                    'fun_name' : 'persist',
                    'app' : self.app
                })
            try:
                py_privatekonomi.core.db.DB().connect(self.__config['database'])
            except AttributeError as e:
                raise Exception("Unable to connect to database: inaccurate database settings.", e)
            ret['persist'] = self.persist(ret['execute'], as_obj(self.__config))
        return ret

    def __repr__(self):
        return "App %s" % (repr(self.__config))
<commit_msg>minor fix<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
from py_privatekonomi.utilities import helper
from py_privatekonomi.utilities.common import as_obj, is_string
from py_privatekonomi.utilities.proxy import HookProxy
from py_privatekonomi.core import loader
from py_privatekonomi.core.error import (MissingAppFunctionError, FormatterError, ParserError)
import py_privatekonomi.core.db

class AppProxy(HookProxy):
    def __init__(self, objname, obj):
        super(AppProxy, self).__init__(objname, obj)
        self.__called = []

    def _pre( self, name, *args, **kwargs ):
        self.__called.append(name)

    def _post(self, name, *args, **kwargs ):
        pass

    def _pre_run(self, *args, **kwargs ):
        if super(AppProxy, self).getObj().isBuilt() and len(self.__called) > 0:
            if len(self.__called) == 1 and self.__called[0] == 'run':
                return
            raise Exception("Following methods called without building first: %s" % (repr(self.__called)))

    def _post_run(self, *args, **kwargs):
        self.__called = []

    def _post_build(self, *args, **kwargs):
        self.__called = []

    def __repr__(self):
        return super(AppProxy, self).getObj().__repr__()

class App(object):
    def __init__(self):
        self.__formatter = None
        self.__parser = None
        self.__sources = []
        self.__persist = False
        self.__config =  {}
        self.__db = {}
        self.__output = None
        self.__auto_discover = False
        self.__discover_from = None
        self.app = None

    def setFormatter(self, formatter_name):
        self.__formatter = formatter_name

    def setParser(self, parser_name):
        self.__parser = parser_name

    def addSource(self, source_name):
        self.__sources.append(source_name)

    def addSources(self, source_names):
        self.__sources.extend(source_names)

    def clearSources(self):
        self.__sources = []

    def persistWith(self, database_settings):
        self.__persist = True
        self.__db = database_settings

    def setOutput(self, output):
        """ Setting the output will avoid calling execute, but
        may still trigger a call to persist.
        If output is set, the building process will not consider
        formatter, parser, or source(s) """
        self.__output = output

    def autodiscover(self, discover_from):
        """ This will attempt to guess the formatter
            and parser given a list of parsers and formatters of format:
            discover_from = [
                {
                    'formatter' : 'swedbank',
                    'parser' : 'swedbank'
                }, { ... }
            ]
        """
        if self.__formatter is not None:
            raise Exception("Unable to autodiscover; Formatter is already set to: %s" % (self.__formatter))
        if self.__parser is not None:
            raise Exception("Unable to autodiscover; Parser is already set to: %s" % (self.__parser))
        self.__auto_discover = True
        self.__discover_from = discover_from

    def config(self, conf):
        self.__config.update(conf)

    def isBuilt(self):
        return self.app is not None

    def __set_parser(self, core):
        self.app['parser'] = None
        if self.__parser is not None:
            self.app['parser'] = self.__load_parser(self.__parser, core)

    def __set_formatter(self, core):
        self.app['formatter'] = None
        if self.__formatter is not None:
            self.app['formatter'] = self.__load_formatter(self.__formatter, core)

    def __load_formatter(self, formatter_name, core):
        return loader.load_formatter(formatter_name, core['factories']['formatters']['account_formatter_factory'])

    def __load_parser(self, parser_name, core):
        return loader.load_parser(parser_name, core['factories']['parsers']['account_parser_factory'])

    def __autodiscover(self, core):
        self.app['formatter'] = None
        self.app['parser'] = None
        for discover in self.__discover_from:
            formatter = self.__load_formatter(discover['formatter'], core)
            if formatter is not None:
                parser = self.__load_parser(discover['parser'], core)
                if parser is not None:
                    self.app['formatter'] = formatter
                    self.app['parser'] = parser
                    return True
        return False

    def build(self):
        self.app = {}
        core = loader.load_core()
        self.app['core'] = core
        if len(self.__db) > 0:
            self.__config['database'] = self.__db
        if self.__output is None and self.__auto_discover is False:
            if self.__formatter is None:
                raise Exception("Formatter has not been specified, please call setFormatter, setOutput, or autodiscover")
            if self.__parser is None:
                raise Exception("Parser has not been specified, please call setParser, setOutput, or autodiscover")
            if len(self.__sources) == 0:
                raise Exception("Sources have not been specified, please call addSource, setOutput, or autodiscover")
            self.__set_parser(self.app['core'])
            self.__set_formatter(self.app['core'])
        elif self.__auto_discover is True:
            found = self.__autodiscover(self.app['core'])
            if not found:
                raise Exception("Unable to find parser/formatter from %s" % (repr(self.__discover_from)))

        return self

    def run(self):
        def __execute():
            if self.__auto_discover is True:
                found = False
                for discover in self.__discover_from:
                    try:
                        parser = self.__load_parser(discover['parser'], self.app['core'])
                        formatter = self.__load_formatter(discover['formatter'],  self.app['core'])
                        if parser is None or formatter is None:
                            continue
                        output = self.execute(
                            sources=self.__sources,
                            parser=parser,
                            formatter=formatter,
                            configs=as_obj(self.__config))
                        self.app['parser'] = discover['parser']
                        self.app['formatter'] = discover['formatter']
                        found = True
                        break
                    except FormatterError as e:
                        continue
                    except ParserError as e:
                        continue
                if found is False:
                    raise Exception("Unable to parse/format using parsers and formatters from %s" % (repr(self.__discover_from)))
            else:
                output = self.execute(self.__sources, self.app['parser'], self.app['formatter'], as_obj(self.__config))
            return output

        if self.app is None:
            raise Exception("Build app using app.build() before running.")
        ret = {}
        if self.__output is not None:
            ret['execute'] = self.__output
            ret['formatter'] = 'unknown'
            ret['parser'] = 'unknown'
        else:
            if 'execute' not in dir(self):
                raise MissingAppFunctionError(capture_data={
                    'fun_name' : 'execute',
                    'app' : self.app
                })
            ret['execute'] = __execute()
            if not is_string(self.app['formatter']):
                ret['formatter'] = self.app['formatter'].getName()
            else:
                ret['formatter'] = self.app['formatter']
            if not is_string(self.app['parser']):
                ret['parser'] = self.app['parser'].getName()
            else:
                ret['parser'] = self.app['parser']
        if self.__persist is True:
            if 'persist' not in dir(self):
                raise MissingAppFunctionError(capture_data={
                    'fun_name' : 'persist',
                    'app' : self.app
                })
            try:
                py_privatekonomi.core.db.DB().connect(self.__config['database'])
            except AttributeError as e:
                raise Exception("Unable to connect to database: inaccurate database settings.", e)
            ret['persist'] = self.persist(ret['execute'], as_obj(self.__config))
        return ret

    def __repr__(self):
        return "App %s" % (repr(self.__config))
<|endoftext|>


<commit_before>"""Maccor txt data"""

import pandas as pd

from cellpy import prms
from cellpy import exceptions
from cellpy.parameters.internal_settings import (
    HeaderDict,
    base_columns_float,
    base_columns_int,
    headers_normal,
)
from cellpy.readers.instruments.base import TxtLoader

DEBUG_MODE = prms.Reader.diagnostics  # not used

SUPPORTED_MODELS = {
    "ZERO": "maccor_txt_zero",
    "ONE": "maccor_txt_one",
    "TWO": "maccor_txt_two",
    "THREE": "maccor_txt_three",
    "FOUR": "maccor_txt_four",
    "WMG_SIMBA": "maccor_txt_three",
    "KIT_SIMBA": "maccor_txt_four",
    "KIT_COMMA_SIMBA": "maccor_txt_two",
    "UBHAM_SIMBA": "maccor_txt_three",
}

MUST_HAVE_RAW_COLUMNS = [
    headers_normal.test_time_txt,
    headers_normal.step_time_txt,
    headers_normal.current_txt,
    headers_normal.voltage_txt,
    headers_normal.step_index_txt,
    headers_normal.cycle_index_txt,
    headers_normal.charge_capacity_txt,
    headers_normal.discharge_capacity_txt,
]

class MaccorTxtLoader(TxtLoader):
    """Class for loading data from Maccor txt files."""

    default_model = prms.Instruments.Maccor["default_model"]  # Required
    supported_models = SUPPORTED_MODELS  # Required

    @staticmethod
    def get_headers_aux(raw):
        """Defines the so-called auxiliary table column headings"""

        headers = HeaderDict()
        for col in raw.columns:
            if col.startswith("Aux_"):
                ncol = col.replace("/", "_")
                ncol = "".join(ncol.split("(")[0])
                headers[col] = ncol.lower()

        return headers

    def validate(self, data):
        """A simple check that all the needed columns has been successfully loaded and that they get the correct type"""
        missing_must_have_columns = []

        # validating the float-type raw data
        for col in base_columns_float:
            if col in data.raw.columns:
                data.raw[col] = pd.to_numeric(data.raw[col], errors="coerce")
            else:
                if col in MUST_HAVE_RAW_COLUMNS:
                    missing_must_have_columns.append(col)

        # validating the integer-type raw data
        for col in base_columns_int:
            if col in data.raw.columns:
                data.raw[col] = pd.to_numeric(
                    data.raw[col], errors="coerce", downcast="integer"
                )
            else:
                if col in MUST_HAVE_RAW_COLUMNS:
                    missing_must_have_columns.append(col)

        if missing_must_have_columns:
            raise exceptions.IOError(
                f"Missing needed columns: {missing_must_have_columns}\nAborting!"
            )
        return data

def check_retrieve_file(n=1):
    import pathlib

    pd.options.display.max_columns = 100
    # prms.Reader.sep = "\t"
    data_root = pathlib.Path(r"C:\scripting\cellpy_dev_resources")
    data_dir = data_root / r"2021_leafs_data\Charge-Discharge\Maccor series 4000"
    if n == 2:
        name = data_dir / "KIT-Full-cell-PW-HC-CT-cell016.txt"
    else:
        name = data_dir / "01_UBham_M50_Validation_0deg_01.txt"
    print(name)
    print(f"Exists? {name.is_file()}")
    if name.is_file():
        return name
    else:
        raise IOError(f"could not locate the file {name}")

def check_dev_loader(name=None, model=None):
    if name is None:
        name = check_retrieve_file()

    pd.options.display.max_columns = 100
    # prms.Reader.sep = "\t"

    sep = "\t"
    loader1 = MaccorTxtLoader(sep=sep, model=model)
    loader2 = MaccorTxtLoader(model="one")
    loader3 = MaccorTxtLoader(model="zero")
    loader4 = MaccorTxtLoader(model="zero")
    dd = loader1.loader(name)
    dd = loader2.loader(name)
    dd = loader3.loader(name)
    dd = loader4.loader(name)
    raw = dd[0].raw
    print(len(raw))

def check_dev_loader2(name=None, model=None, sep=None, number=2):
    if name is None:
        name = check_retrieve_file(number)

    pd.options.display.max_columns = 100

    if sep is not None and sep != "none":
        loader3 = MaccorTxtLoader(sep=sep, model=model)
    elif sep == "none":
        loader3 = MaccorTxtLoader(sep=None, model=model)
    else:
        loader3 = MaccorTxtLoader(model=model)

    dd = loader3.loader(name)

    raw = dd[0].raw
    print(len(raw))
    print(raw)

def check_loader(name=None, number=1, model="one"):
    import matplotlib.pyplot as plt

    if name is None:
        name = check_retrieve_file(number)
    print(name)
    pd.options.display.max_columns = 100
    # prms.Reader.sep = "\t"

    loader = MaccorTxtLoader(sep="\t", model=model)
    dd = loader.loader(name)
    raw = dd[0].raw
    raw.plot(x="data_point", y="current", title="current vs data-point")
    raw.plot(
        x="data_point",
        y=["charge_capacity", "discharge_capacity"],
        title="capacity vs data-point",
    )
    raw.plot(
        x="test_time",
        y=["charge_capacity", "discharge_capacity"],
        title="capacity vs test-time",
    )
    raw.plot(
        x="step_time",
        y=["charge_capacity", "discharge_capacity"],
        title="capacity vs step-time",
    )
    print(raw.head())
    plt.show()

def check_loader_from_outside():
    # NOT EDITED YET!!!
    import pathlib

    import matplotlib.pyplot as plt

    from cellpy import cellreader

    pd.options.display.max_columns = 100
    datadir = pathlib.Path(
        r"C:\scripts\cellpy_dev_resources\2021_leafs_data\Charge-Discharge\Maccor series 4000"
    )
    name = datadir / "01_UBham_M50_Validation_0deg_01.txt"
    out = pathlib.Path(r"C:\scripts\notebooks\Div")
    print(f"Exists? {name.is_file()}")

    c = cellreader.CellpyData()
    c.set_instrument("maccor_txt", sep="\t")

    c.from_raw(name)
    c.set_mass(1000)

    c.make_step_table()
    c.make_summary()

    raw = c.cell.raw
    steps = c.cell.steps
    summary = c.cell.summary
    raw.to_csv(r"C:\scripts\notebooks\Div\trash\raw.csv", sep=";")
    steps.to_csv(r"C:\scripts\notebooks\Div\trash\steps.csv", sep=";")
    summary.to_csv(r"C:\scripts\notebooks\Div\trash\summary.csv", sep=";")

    fig_1, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(6, 10))
    raw.plot(x="test_time", y="voltage", ax=ax1)
    raw.plot(x="test_time", y=["charge_capacity", "discharge_capacity"], ax=ax3)
    raw.plot(x="test_time", y="current", ax=ax2)

    n = c.get_number_of_cycles()
    print(f"number of cycles: {n}")

    cycle = c.get_cap(1, method="forth-and-forth")
    print(cycle.head())

    fig_2, (ax4, ax5, ax6) = plt.subplots(1, 3)
    cycle.plot(x="capacity", y="voltage", ax=ax4)
    s = c.get_step_numbers()
    t = c.sget_timestamp(1, s[1])
    v = c.sget_voltage(1, s[1])
    steps = c.sget_step_numbers(1, s[1])

    print("step numbers:")
    print(s)
    print("sget step numbers:")
    print(steps)
    print("\ntesttime:")
    print(t)
    print("\nvoltage")
    print(v)

    ax5.plot(t, v, label="voltage")
    ax6.plot(t, steps, label="steps")

    fig_3, (ax7, ax8) = plt.subplots(2, sharex=True)
    raw.plot(x="test_time", y="voltage", ax=ax7)
    raw.plot(x="test_time", y="step_index", ax=ax8)

    plt.legend()
    plt.show()

    outfile = out / "test_out"
    c.save(outfile)

def check_loader_from_outside_with_get():
    import pathlib

    import matplotlib.pyplot as plt

    import cellpy

    pd.options.display.max_columns = 100
    datadir = pathlib.Path(
        r"C:\scripting\cellpy_dev_resources\2021_leafs_data\Charge-Discharge\Maccor series 4000"
    )
    name = datadir / "01_UBham_M50_Validation_0deg_01.txt"
    out = pathlib.Path(r"C:\scripting\trash")
    print(f"File exists? {name.is_file()}")
    if not name.is_file():
        print(f"could not find {name} ")
        return

    c = cellpy.get(filename=name, instrument="maccor_txt", model="one", mass=1.0)
    print("loaded")
    raw = c.cell.raw
    steps = c.cell.steps
    summary = c.cell.summary

    raw.to_csv(r"C:\scripting\trash\raw.csv", sep=";")
    steps.to_csv(r"C:\scripting\trash\steps.csv", sep=";")
    summary.to_csv(r"C:\scripting\trash\summary.csv", sep=";")

    fig_1, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(6, 10))
    raw.plot(x="test_time", y="voltage", ax=ax1, title="voltage")
    raw.plot(
        x="test_time", y=["charge_capacity", "discharge_capacity"], ax=ax3, title="caps"
    )
    raw.plot(x="test_time", y="current", ax=ax2, title="current")

    n = c.get_number_of_cycles()
    print(f"number of cycles: {n}")

    cycle = c.get_cap(1, method="forth-and-forth")

    fig_2, (ax4, ax5, ax6) = plt.subplots(1, 3)
    # cycle.plot(x="capacity", y="voltage", ax=ax4)
    s = c.get_step_numbers()
    t = c.sget_timestamp(1, s[1])
    v = c.sget_voltage(1, s[1])
    steps = c.sget_step_numbers(1, s[1])

    print("step numbers:")
    print(s)
    print("sget step numbers:")
    print(steps)
    print("\ntesttime:")
    print(t)
    print("\nvoltage")
    print(v)

    ax5.plot(t, v, label="voltage")
    ax6.plot(t, steps, label="steps")

    fig_3, (ax7, ax8) = plt.subplots(2, sharex=True)
    raw.plot(x="test_time", y="voltage", ax=ax7, title="voltage")
    raw.plot(x="test_time", y="step_index", ax=ax8, title="step index")

    plt.legend()
    plt.show()

    outfile = out / "test_out"
    c.save(outfile)

def check_loader_from_outside_with_get2():
    import pathlib

    import matplotlib.pyplot as plt

    import cellpy
    from cellpy.parameters.internal_settings import headers_normal

    keep = [
        headers_normal.data_point_txt,
        headers_normal.test_time_txt,
        headers_normal.step_time_txt,
        headers_normal.step_index_txt,
        headers_normal.cycle_index_txt,
        headers_normal.current_txt,
        headers_normal.voltage_txt,
        headers_normal.ref_voltage_txt,
        headers_normal.charge_capacity_txt,
        headers_normal.discharge_capacity_txt,
        headers_normal.internal_resistance_txt,
        # "ir_pct_change"
    ]

    # zero: auto
    # one:
    # two: KIT
    # three | WMB_SIMBA: WMG new
    INSTRUMENT = "maccor_txt"
    # MODEL = "WMG_SIMBA"
    # MODEL = "two"
    # MODEL = None
    MODEL = "KIT_SIMBA"
    # FILENAME = "1044-CT-MaccorExport.txt"  # WMG_SIMBA
    # FILENAME = "01_UBham_M50_Validation_0deg_01.txt"  # WMG_SIMBA and NONE
    # FILENAME = "KIT-Full-cell-PW-HC-CT-cell002.txt"
    # FILENAME = "KIT-Full-cell-PW-HC-CT-cell016.txt"
    # FILENAME = "KIT-Full-cell-PW-HC-CT-cell013.txt"  # Two
    # FILENAME = "KIT-Full-cell-PW-HC-CT-cell009.txt"  # FAILS in convert_date_time_to_datetime!
    FILENAME = "maccor_002_full.txt"
    DATADIR = r"C:\scripting\processing_cellpy\notebooks\test\new\data"

    pd.options.display.max_columns = 100
    datadir = pathlib.Path(DATADIR)
    name = datadir / FILENAME
    out = pathlib.Path(r"C:\scripting\trash")
    print(f"File exists? {name.is_file()}")
    if not name.is_file():
        print(f"could not find {name} ")
        return

    c = cellpy.get(
        filename=name, instrument=INSTRUMENT, model=MODEL, mass=1.0, auto_summary=False
    )
    print(f"loaded the file - now lets see what we got")
    raw = c.cell.raw
    raw.to_clipboard()
    print(raw.head())
    c.make_step_table()

    steps = c.cell.steps
    summary = c.cell.summary

    raw.to_csv(out / "raw.csv", sep=";")
    steps.to_csv(out / "steps.csv", sep=";")
    summary.to_csv(out / "summary.csv", sep=";")

    fig_1, (ax1, ax2, ax3, ax4) = plt.subplots(
        4,
        1,
        figsize=(6, 10),
        constrained_layout=True,
        sharex=True,
    )
    raw.plot(x="test_time", y="voltage", ax=ax1, xlabel="")
    raw.plot(x="test_time", y="current", ax=ax2, xlabel="")
    raw.plot(
        x="test_time", y=["charge_capacity", "discharge_capacity"], ax=ax3, xlabel=""
    )
    raw.plot(x="test_time", y="cycle_index", ax=ax4)
    fig_1.suptitle(f"{name.name}", fontsize=16)

    n = c.get_number_of_cycles()
    print(f"Number of cycles: {n}")

    plt.legend()
    plt.show()

    outfile = out / "test_out"
    c.save(outfile)

if __name__ == "__main__":
    # check_dev_loader2(model="two")
    # check_loader(number=2, model="two")
    check_loader_from_outside_with_get2()
<commit_msg>test some other files<commit_after>"""Maccor txt data"""

import pandas as pd

from cellpy import prms
from cellpy import exceptions
from cellpy.parameters.internal_settings import (
    HeaderDict,
    base_columns_float,
    base_columns_int,
    headers_normal,
)
from cellpy.readers.instruments.base import TxtLoader

DEBUG_MODE = prms.Reader.diagnostics  # not used

SUPPORTED_MODELS = {
    "ZERO": "maccor_txt_zero",
    "ONE": "maccor_txt_one",
    "TWO": "maccor_txt_two",
    "THREE": "maccor_txt_three",
    "FOUR": "maccor_txt_four",
    "WMG_SIMBA": "maccor_txt_three",
    "KIT_SIMBA": "maccor_txt_four",
    "KIT_COMMA_SIMBA": "maccor_txt_two",
    "UBHAM_SIMBA": "maccor_txt_three",
}

MUST_HAVE_RAW_COLUMNS = [
    headers_normal.test_time_txt,
    headers_normal.step_time_txt,
    headers_normal.current_txt,
    headers_normal.voltage_txt,
    headers_normal.step_index_txt,
    headers_normal.cycle_index_txt,
    headers_normal.charge_capacity_txt,
    headers_normal.discharge_capacity_txt,
]

class MaccorTxtLoader(TxtLoader):
    """Class for loading data from Maccor txt files."""

    default_model = prms.Instruments.Maccor["default_model"]  # Required
    supported_models = SUPPORTED_MODELS  # Required

    @staticmethod
    def get_headers_aux(raw):
        """Defines the so-called auxiliary table column headings"""

        headers = HeaderDict()
        for col in raw.columns:
            if col.startswith("Aux_"):
                ncol = col.replace("/", "_")
                ncol = "".join(ncol.split("(")[0])
                headers[col] = ncol.lower()

        return headers

    def validate(self, data):
        """A simple check that all the needed columns has been successfully loaded and that they get the correct type"""
        missing_must_have_columns = []

        # validating the float-type raw data
        for col in base_columns_float:
            if col in data.raw.columns:
                data.raw[col] = pd.to_numeric(data.raw[col], errors="coerce")
            else:
                if col in MUST_HAVE_RAW_COLUMNS:
                    missing_must_have_columns.append(col)

        # validating the integer-type raw data
        for col in base_columns_int:
            if col in data.raw.columns:
                data.raw[col] = pd.to_numeric(
                    data.raw[col], errors="coerce", downcast="integer"
                )
            else:
                if col in MUST_HAVE_RAW_COLUMNS:
                    missing_must_have_columns.append(col)

        if missing_must_have_columns:
            raise exceptions.IOError(
                f"Missing needed columns: {missing_must_have_columns}\nAborting!"
            )
        return data

def check_retrieve_file(n=1):
    import pathlib

    pd.options.display.max_columns = 100
    # prms.Reader.sep = "\t"
    data_root = pathlib.Path(r"C:\scripting\cellpy_dev_resources")
    data_dir = data_root / r"2021_leafs_data\Charge-Discharge\Maccor series 4000"
    if n == 2:
        name = data_dir / "KIT-Full-cell-PW-HC-CT-cell016.txt"
    else:
        name = data_dir / "01_UBham_M50_Validation_0deg_01.txt"
    print(name)
    print(f"Exists? {name.is_file()}")
    if name.is_file():
        return name
    else:
        raise IOError(f"could not locate the file {name}")

def check_dev_loader(name=None, model=None):
    if name is None:
        name = check_retrieve_file()

    pd.options.display.max_columns = 100
    # prms.Reader.sep = "\t"

    sep = "\t"
    loader1 = MaccorTxtLoader(sep=sep, model=model)
    loader2 = MaccorTxtLoader(model="one")
    loader3 = MaccorTxtLoader(model="zero")
    loader4 = MaccorTxtLoader(model="zero")
    dd = loader1.loader(name)
    dd = loader2.loader(name)
    dd = loader3.loader(name)
    dd = loader4.loader(name)
    raw = dd[0].raw
    print(len(raw))

def check_dev_loader2(name=None, model=None, sep=None, number=2):
    if name is None:
        name = check_retrieve_file(number)

    pd.options.display.max_columns = 100

    if sep is not None and sep != "none":
        loader3 = MaccorTxtLoader(sep=sep, model=model)
    elif sep == "none":
        loader3 = MaccorTxtLoader(sep=None, model=model)
    else:
        loader3 = MaccorTxtLoader(model=model)

    dd = loader3.loader(name)

    raw = dd[0].raw
    print(len(raw))
    print(raw)

def check_loader(name=None, number=1, model="one"):
    import matplotlib.pyplot as plt

    if name is None:
        name = check_retrieve_file(number)
    print(name)
    pd.options.display.max_columns = 100
    # prms.Reader.sep = "\t"

    loader = MaccorTxtLoader(sep="\t", model=model)
    dd = loader.loader(name)
    raw = dd[0].raw
    raw.plot(x="data_point", y="current", title="current vs data-point")
    raw.plot(
        x="data_point",
        y=["charge_capacity", "discharge_capacity"],
        title="capacity vs data-point",
    )
    raw.plot(
        x="test_time",
        y=["charge_capacity", "discharge_capacity"],
        title="capacity vs test-time",
    )
    raw.plot(
        x="step_time",
        y=["charge_capacity", "discharge_capacity"],
        title="capacity vs step-time",
    )
    print(raw.head())
    plt.show()

def check_loader_from_outside():
    # NOT EDITED YET!!!
    import pathlib

    import matplotlib.pyplot as plt

    from cellpy import cellreader

    pd.options.display.max_columns = 100
    datadir = pathlib.Path(
        r"C:\scripts\cellpy_dev_resources\2021_leafs_data\Charge-Discharge\Maccor series 4000"
    )
    name = datadir / "01_UBham_M50_Validation_0deg_01.txt"
    out = pathlib.Path(r"C:\scripts\notebooks\Div")
    print(f"Exists? {name.is_file()}")

    c = cellreader.CellpyData()
    c.set_instrument("maccor_txt", sep="\t")

    c.from_raw(name)
    c.set_mass(1000)

    c.make_step_table()
    c.make_summary()

    raw = c.cell.raw
    steps = c.cell.steps
    summary = c.cell.summary
    raw.to_csv(r"C:\scripts\notebooks\Div\trash\raw.csv", sep=";")
    steps.to_csv(r"C:\scripts\notebooks\Div\trash\steps.csv", sep=";")
    summary.to_csv(r"C:\scripts\notebooks\Div\trash\summary.csv", sep=";")

    fig_1, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(6, 10))
    raw.plot(x="test_time", y="voltage", ax=ax1)
    raw.plot(x="test_time", y=["charge_capacity", "discharge_capacity"], ax=ax3)
    raw.plot(x="test_time", y="current", ax=ax2)

    n = c.get_number_of_cycles()
    print(f"number of cycles: {n}")

    cycle = c.get_cap(1, method="forth-and-forth")
    print(cycle.head())

    fig_2, (ax4, ax5, ax6) = plt.subplots(1, 3)
    cycle.plot(x="capacity", y="voltage", ax=ax4)
    s = c.get_step_numbers()
    t = c.sget_timestamp(1, s[1])
    v = c.sget_voltage(1, s[1])
    steps = c.sget_step_numbers(1, s[1])

    print("step numbers:")
    print(s)
    print("sget step numbers:")
    print(steps)
    print("\ntesttime:")
    print(t)
    print("\nvoltage")
    print(v)

    ax5.plot(t, v, label="voltage")
    ax6.plot(t, steps, label="steps")

    fig_3, (ax7, ax8) = plt.subplots(2, sharex=True)
    raw.plot(x="test_time", y="voltage", ax=ax7)
    raw.plot(x="test_time", y="step_index", ax=ax8)

    plt.legend()
    plt.show()

    outfile = out / "test_out"
    c.save(outfile)

def check_loader_from_outside_with_get():
    import pathlib

    import matplotlib.pyplot as plt

    import cellpy

    pd.options.display.max_columns = 100
    datadir = pathlib.Path(
        r"C:\scripting\cellpy_dev_resources\2021_leafs_data\Charge-Discharge\Maccor series 4000"
    )
    name = datadir / "01_UBham_M50_Validation_0deg_01.txt"
    out = pathlib.Path(r"C:\scripting\trash")
    print(f"File exists? {name.is_file()}")
    if not name.is_file():
        print(f"could not find {name} ")
        return

    c = cellpy.get(filename=name, instrument="maccor_txt", model="one", mass=1.0)
    print("loaded")
    raw = c.cell.raw
    steps = c.cell.steps
    summary = c.cell.summary

    raw.to_csv(r"C:\scripting\trash\raw.csv", sep=";")
    steps.to_csv(r"C:\scripting\trash\steps.csv", sep=";")
    summary.to_csv(r"C:\scripting\trash\summary.csv", sep=";")

    fig_1, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(6, 10))
    raw.plot(x="test_time", y="voltage", ax=ax1, title="voltage")
    raw.plot(
        x="test_time", y=["charge_capacity", "discharge_capacity"], ax=ax3, title="caps"
    )
    raw.plot(x="test_time", y="current", ax=ax2, title="current")

    n = c.get_number_of_cycles()
    print(f"number of cycles: {n}")

    cycle = c.get_cap(1, method="forth-and-forth")

    fig_2, (ax4, ax5, ax6) = plt.subplots(1, 3)
    # cycle.plot(x="capacity", y="voltage", ax=ax4)
    s = c.get_step_numbers()
    t = c.sget_timestamp(1, s[1])
    v = c.sget_voltage(1, s[1])
    steps = c.sget_step_numbers(1, s[1])

    print("step numbers:")
    print(s)
    print("sget step numbers:")
    print(steps)
    print("\ntesttime:")
    print(t)
    print("\nvoltage")
    print(v)

    ax5.plot(t, v, label="voltage")
    ax6.plot(t, steps, label="steps")

    fig_3, (ax7, ax8) = plt.subplots(2, sharex=True)
    raw.plot(x="test_time", y="voltage", ax=ax7, title="voltage")
    raw.plot(x="test_time", y="step_index", ax=ax8, title="step index")

    plt.legend()
    plt.show()

    outfile = out / "test_out"
    c.save(outfile)

def check_loader_from_outside_with_get2():
    import pathlib

    import matplotlib.pyplot as plt

    import cellpy
    from cellpy.parameters.internal_settings import headers_normal

    keep = [
        headers_normal.data_point_txt,
        headers_normal.test_time_txt,
        headers_normal.step_time_txt,
        headers_normal.step_index_txt,
        headers_normal.cycle_index_txt,
        headers_normal.current_txt,
        headers_normal.voltage_txt,
        headers_normal.ref_voltage_txt,
        headers_normal.charge_capacity_txt,
        headers_normal.discharge_capacity_txt,
        headers_normal.internal_resistance_txt,
        # "ir_pct_change"
    ]

    # zero: auto
    # one:
    # two: KIT
    # three | WMB_SIMBA: WMG new
    INSTRUMENT = "maccor_txt"
    MODEL = "WMG_SIMBA"
    # MODEL = "two"
    # MODEL = None
    # MODEL = "KIT_SIMBA"
    # FILENAME = "1044-CT-MaccorExport.txt"  # WMG_SIMBA
    # FILENAME = "01_UBham_M50_Validation_0deg_01.txt"  # WMG_SIMBA and NONE
    # FILENAME = "KIT-Full-cell-PW-HC-CT-cell002.txt"
    # FILENAME = "KIT-Full-cell-PW-HC-CT-cell016.txt"
    # FILENAME = "KIT-Full-cell-PW-HC-CT-cell013.txt"  # Two
    # FILENAME = "KIT-Full-cell-PW-HC-CT-cell009.txt"  # FAILS in convert_date_time_to_datetime!
    FILENAME = "SIM-A7-1047-ET - 079.txt"
    DATADIR = r"C:\scripting\processing_cellpy\notebooks\test\new\data"

    pd.options.display.max_columns = 100
    datadir = pathlib.Path(DATADIR)
    name = datadir / FILENAME
    out = pathlib.Path(r"C:\scripting\trash")
    print(f"File exists? {name.is_file()}")
    if not name.is_file():
        print(f"could not find {name} ")
        return

    c = cellpy.get(
        filename=name, instrument=INSTRUMENT, model=MODEL, mass=1.0, auto_summary=False
    )
    print(f"loaded the file - now lets see what we got")
    raw = c.cell.raw
    raw.to_clipboard()
    print(raw.head())
    c.make_step_table()

    steps = c.cell.steps
    summary = c.cell.summary

    raw.to_csv(out / "raw.csv", sep=";")
    steps.to_csv(out / "steps.csv", sep=";")
    summary.to_csv(out / "summary.csv", sep=";")

    fig_1, (ax1, ax2, ax3, ax4) = plt.subplots(
        4,
        1,
        figsize=(6, 10),
        constrained_layout=True,
        sharex=True,
    )
    raw.plot(x="test_time", y="voltage", ax=ax1, xlabel="")
    raw.plot(x="test_time", y="current", ax=ax2, xlabel="")
    raw.plot(
        x="test_time", y=["charge_capacity", "discharge_capacity"], ax=ax3, xlabel=""
    )
    raw.plot(x="test_time", y="cycle_index", ax=ax4)
    fig_1.suptitle(f"{name.name}", fontsize=16)

    n = c.get_number_of_cycles()
    print(f"Number of cycles: {n}")

    plt.legend()
    plt.show()

    outfile = out / "test_out"
    c.save(outfile)

if __name__ == "__main__":
    # check_dev_loader2(model="two")
    # check_loader(number=2, model="two")
    check_loader_from_outside_with_get2()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
Created on Fri Apr  8 08:32:48 2016

@author: RCGlade
"""

from landlab import Component
import numpy as np
from landlab import INACTIVE_LINK

class DepthDependentDiffuser(Component):

    """
    This component implements a depth and slope dependent linear diffusion rule
    in the style of Johnstone and Hilley (2014).

    This component will ignore soil thickness located at non-core nodes.

    Parameters
    ----------
    grid: ModelGrid
        Landlab ModelGrid object
    linear_diffusivity: float
        Hillslope diffusivity, m**2/yr
        Equivalent to the soil creep efficiency
        times the soil transport decay depth.
    soil_transport_decay_depth: float
        characteristic transport soil depth, m

    Examples
    --------
    >>> import numpy as np
    >>> from landlab import RasterModelGrid
    >>> from landlab.components import ExponentialWeatherer
    >>> from landlab.components import DepthDependentDiffuser
    >>> mg = RasterModelGrid((5, 5))
    >>> soilTh = mg.add_zeros('node', 'soil__depth')
    >>> z = mg.add_zeros('node', 'topographic__elevation')
    >>> BRz = mg.add_zeros('node', 'bedrock__elevation')
    >>> expweath = ExponentialWeatherer(mg)
    >>> DDdiff = DepthDependentDiffuser(mg)
    >>> expweath.calc_soil_prod_rate()
    >>> np.allclose(mg.at_node['soil_production__rate'][mg.core_nodes], 1.)
    True
    >>> DDdiff.soilflux(2.)
    >>> np.allclose(mg.at_node['topographic__elevation'][mg.core_nodes], 0.)
    True
    >>> np.allclose(mg.at_node['bedrock__elevation'][mg.core_nodes], -2.)
    True
    >>> np.allclose(mg.at_node['soil__depth'][mg.core_nodes], 2.)
    True

    Now with a slope:
    >>> mg = RasterModelGrid((3, 5))
    >>> soilTh = mg.add_zeros('node', 'soil__depth')
    >>> z = mg.add_zeros('node', 'topographic__elevation')
    >>> BRz = mg.add_zeros('node', 'bedrock__elevation')
    >>> z += mg.node_x.copy()
    >>> BRz += mg.node_x/2.
    >>> soilTh[:] = z - BRz
    >>> expweath = ExponentialWeatherer(mg)
    >>> DDdiff = DepthDependentDiffuser(mg)
    >>> expweath.calc_soil_prod_rate()
    >>> np.allclose(
    ...     mg.at_node['soil_production__rate'][mg.core_nodes],
    ...     np.array([ 0.60653066,  0.36787944,  0.22313016]))
    True
    >>> DDdiff.soilflux(2.)
    >>> np.allclose(
    ...     mg.at_node['topographic__elevation'][mg.core_nodes],
    ...     np.array([ 1.47730244,  2.28949856,  3.17558975]))
    True
    >>> np.allclose(mg.at_node['bedrock__elevation'][mg.core_nodes],
    ...     np.array([-0.71306132,  0.26424112,  1.05373968]))
    True
    >>> np.allclose(mg.at_node['soil__depth'], z - BRz)
    True
    """

    _name = 'DepthDependentDiffuser'

    _input_var_names = (
        'topographic__elevation',
        'soil__depth',
        'soil_production__rate',
    )

    _output_var_names = (
        'soil__flux',
        'topographic__slope',
        'topographic__elevation',
        'bedrock__elevation',
        'soil__depth',
    )

    _var_units = {
        'topographic__elevation' : 'm',
        'topographic__slope' : 'm/m',
        'soil__depth' : 'm',
        'soil__flux' : 'm^2/yr',
        'soil_production__rate' : 'm/yr',
        'bedrock__elevation' : 'm',
    }

    _var_mapping = {
        'topographic__elevation' : 'node',
        'topographic__slope' : 'link',
        'soil__depth' : 'node',
        'soil__flux' : 'link',
        'soil_production__rate' : 'node',
        'bedrock__elevation' :'node',
    }

    _var_doc = {
        'topographic__elevation':
                'elevation of the ground surface',
        'topographic__slope':
                'gradient of the ground surface',
        'soil__depth':
                'depth of soil/weather bedrock',
        'soil__flux':
                'flux of soil in direction of link',
        'soil_production__rate':
                'rate of soil production at nodes',
        'bedrock__elevation':
                'elevation of the bedrock surface',
    }
    def __init__(self,grid, linear_diffusivity=1.0,
                 soil_transport_decay_depth=1.0):
        """Initialize the DepthDependentDiffuser."""

        # Store grid and parameters
        self._grid = grid
        self.K = linear_diffusivity
        self.soil_transport_decay_depth = soil_transport_decay_depth

        # create fields
        # elevation
        if 'topographic__elevation' in self.grid.at_node:
            self.elev = self.grid.at_node['topographic__elevation']
        else:
            self.elev = self.grid.add_zeros('node', 'topographic__elevation')

        # slope
        if 'topographic__slope' in self.grid.at_link:
            self.slope = self.grid.at_link['topographic__slope']
        else:
            self.slope = self.grid.add_zeros('link', 'topographic__slope')

        # soil depth
        if 'soil__depth' in self.grid.at_node:
            self.depth = self.grid.at_node['soil__depth']
        else:
            self.depth = self.grid.add_zeros('node', 'soil__depth')

        # soil flux
        if 'soil__flux' in self.grid.at_link:
            self.flux = self.grid.at_link['soil__flux']
        else:
            self.flux=self.grid.add_zeros('link', 'soil__flux')

        # weathering rate
        if 'soil_production__rate' in self.grid.at_node:
            self.soil_prod_rate = self.grid.at_node['soil_production__rate']
        else:
            self.soil_prod_rate = self.grid.add_zeros('node',
                                                      'soil_production__rate')

        # bedrock elevation
        if 'bedrock__elevation' in self.grid.at_node:
            self.bedrock = self.grid.at_node['bedrock__elevation']
        else:
            self.bedrock = self.grid.add_zeros('node', 'bedrock__elevation')

    def soilflux(self, dt):
        """Calculate soil flux for a time period 'dt'.

        Parameters
        ----------

        dt: float (time)
            The imposed timestep.
        """

        #update soil thickness
        self.grid.at_node['soil__depth'][:] = (
            self.grid.at_node['topographic__elevation']
            - self.grid.at_node['bedrock__elevation'])

        #Calculate soil depth at links.
        H_link = self.grid.map_value_at_max_node_to_link(
            'topographic__elevation','soil__depth')

        #Calculate gradients
        slope = self.grid.calc_grad_at_link(self.elev)
        slope[self.grid.status_at_link == INACTIVE_LINK] = 0.

        #Calculate flux
        self.flux[:] = (-self.K
                        * slope
                        * (1.0 - np.exp(-H_link
                                        / self.soil_transport_decay_depth)))

        #Calculate flux divergence
        dqdx = self.grid.calc_flux_div_at_node(self.flux)

        #Calculate change in soil depth
        dhdt = self.soil_prod_rate - dqdx

        #Calculate soil depth at nodes
        self.depth[self.grid.core_nodes] += dhdt[self.grid.core_nodes] * dt

        #prevent negative soil thickness
        self.depth[self.depth < 0.0] = 0.0

        #Calculate bedrock elevation
        self.bedrock[self.grid.core_nodes] -= (
            self.soil_prod_rate[self.grid.core_nodes] * dt)

        #Update topography
        self.elev[self.grid.core_nodes] = (self.depth[self.grid.core_nodes]
                                         + self.bedrock[self.grid.core_nodes])

    def run_one_step(self, dt):
        """

        Parameters
        ----------
        dt: float (time)
            The imposed timestep.
        """

        self.soilflux(dt)<commit_msg>A missing carriage return = bad docs, now fixed<commit_after># -*- coding: utf-8 -*-
"""
Created on Fri Apr  8 08:32:48 2016

@author: RCGlade
"""

from landlab import Component
import numpy as np
from landlab import INACTIVE_LINK

class DepthDependentDiffuser(Component):

    """
    This component implements a depth and slope dependent linear diffusion rule
    in the style of Johnstone and Hilley (2014).

    This component will ignore soil thickness located at non-core nodes.

    Parameters
    ----------
    grid: ModelGrid
        Landlab ModelGrid object
    linear_diffusivity: float
        Hillslope diffusivity, m**2/yr
        Equivalent to the soil creep efficiency
        times the soil transport decay depth.
    soil_transport_decay_depth: float
        characteristic transport soil depth, m

    Examples
    --------
    >>> import numpy as np
    >>> from landlab import RasterModelGrid
    >>> from landlab.components import ExponentialWeatherer
    >>> from landlab.components import DepthDependentDiffuser
    >>> mg = RasterModelGrid((5, 5))
    >>> soilTh = mg.add_zeros('node', 'soil__depth')
    >>> z = mg.add_zeros('node', 'topographic__elevation')
    >>> BRz = mg.add_zeros('node', 'bedrock__elevation')
    >>> expweath = ExponentialWeatherer(mg)
    >>> DDdiff = DepthDependentDiffuser(mg)
    >>> expweath.calc_soil_prod_rate()
    >>> np.allclose(mg.at_node['soil_production__rate'][mg.core_nodes], 1.)
    True
    >>> DDdiff.soilflux(2.)
    >>> np.allclose(mg.at_node['topographic__elevation'][mg.core_nodes], 0.)
    True
    >>> np.allclose(mg.at_node['bedrock__elevation'][mg.core_nodes], -2.)
    True
    >>> np.allclose(mg.at_node['soil__depth'][mg.core_nodes], 2.)
    True

    Now with a slope:

    >>> mg = RasterModelGrid((3, 5))
    >>> soilTh = mg.add_zeros('node', 'soil__depth')
    >>> z = mg.add_zeros('node', 'topographic__elevation')
    >>> BRz = mg.add_zeros('node', 'bedrock__elevation')
    >>> z += mg.node_x.copy()
    >>> BRz += mg.node_x/2.
    >>> soilTh[:] = z - BRz
    >>> expweath = ExponentialWeatherer(mg)
    >>> DDdiff = DepthDependentDiffuser(mg)
    >>> expweath.calc_soil_prod_rate()
    >>> np.allclose(
    ...     mg.at_node['soil_production__rate'][mg.core_nodes],
    ...     np.array([ 0.60653066,  0.36787944,  0.22313016]))
    True
    >>> DDdiff.soilflux(2.)
    >>> np.allclose(
    ...     mg.at_node['topographic__elevation'][mg.core_nodes],
    ...     np.array([ 1.47730244,  2.28949856,  3.17558975]))
    True
    >>> np.allclose(mg.at_node['bedrock__elevation'][mg.core_nodes],
    ...     np.array([-0.71306132,  0.26424112,  1.05373968]))
    True
    >>> np.allclose(mg.at_node['soil__depth'], z - BRz)
    True
    """

    _name = 'DepthDependentDiffuser'

    _input_var_names = (
        'topographic__elevation',
        'soil__depth',
        'soil_production__rate',
    )

    _output_var_names = (
        'soil__flux',
        'topographic__slope',
        'topographic__elevation',
        'bedrock__elevation',
        'soil__depth',
    )

    _var_units = {
        'topographic__elevation' : 'm',
        'topographic__slope' : 'm/m',
        'soil__depth' : 'm',
        'soil__flux' : 'm^2/yr',
        'soil_production__rate' : 'm/yr',
        'bedrock__elevation' : 'm',
    }

    _var_mapping = {
        'topographic__elevation' : 'node',
        'topographic__slope' : 'link',
        'soil__depth' : 'node',
        'soil__flux' : 'link',
        'soil_production__rate' : 'node',
        'bedrock__elevation' :'node',
    }

    _var_doc = {
        'topographic__elevation':
                'elevation of the ground surface',
        'topographic__slope':
                'gradient of the ground surface',
        'soil__depth':
                'depth of soil/weather bedrock',
        'soil__flux':
                'flux of soil in direction of link',
        'soil_production__rate':
                'rate of soil production at nodes',
        'bedrock__elevation':
                'elevation of the bedrock surface',
    }
    def __init__(self,grid, linear_diffusivity=1.0,
                 soil_transport_decay_depth=1.0):
        """Initialize the DepthDependentDiffuser."""

        # Store grid and parameters
        self._grid = grid
        self.K = linear_diffusivity
        self.soil_transport_decay_depth = soil_transport_decay_depth

        # create fields
        # elevation
        if 'topographic__elevation' in self.grid.at_node:
            self.elev = self.grid.at_node['topographic__elevation']
        else:
            self.elev = self.grid.add_zeros('node', 'topographic__elevation')

        # slope
        if 'topographic__slope' in self.grid.at_link:
            self.slope = self.grid.at_link['topographic__slope']
        else:
            self.slope = self.grid.add_zeros('link', 'topographic__slope')

        # soil depth
        if 'soil__depth' in self.grid.at_node:
            self.depth = self.grid.at_node['soil__depth']
        else:
            self.depth = self.grid.add_zeros('node', 'soil__depth')

        # soil flux
        if 'soil__flux' in self.grid.at_link:
            self.flux = self.grid.at_link['soil__flux']
        else:
            self.flux=self.grid.add_zeros('link', 'soil__flux')

        # weathering rate
        if 'soil_production__rate' in self.grid.at_node:
            self.soil_prod_rate = self.grid.at_node['soil_production__rate']
        else:
            self.soil_prod_rate = self.grid.add_zeros('node',
                                                      'soil_production__rate')

        # bedrock elevation
        if 'bedrock__elevation' in self.grid.at_node:
            self.bedrock = self.grid.at_node['bedrock__elevation']
        else:
            self.bedrock = self.grid.add_zeros('node', 'bedrock__elevation')

    def soilflux(self, dt):
        """Calculate soil flux for a time period 'dt'.

        Parameters
        ----------

        dt: float (time)
            The imposed timestep.
        """

        #update soil thickness
        self.grid.at_node['soil__depth'][:] = (
            self.grid.at_node['topographic__elevation']
            - self.grid.at_node['bedrock__elevation'])

        #Calculate soil depth at links.
        H_link = self.grid.map_value_at_max_node_to_link(
            'topographic__elevation','soil__depth')

        #Calculate gradients
        slope = self.grid.calc_grad_at_link(self.elev)
        slope[self.grid.status_at_link == INACTIVE_LINK] = 0.

        #Calculate flux
        self.flux[:] = (-self.K
                        * slope
                        * (1.0 - np.exp(-H_link
                                        / self.soil_transport_decay_depth)))

        #Calculate flux divergence
        dqdx = self.grid.calc_flux_div_at_node(self.flux)

        #Calculate change in soil depth
        dhdt = self.soil_prod_rate - dqdx

        #Calculate soil depth at nodes
        self.depth[self.grid.core_nodes] += dhdt[self.grid.core_nodes] * dt

        #prevent negative soil thickness
        self.depth[self.depth < 0.0] = 0.0

        #Calculate bedrock elevation
        self.bedrock[self.grid.core_nodes] -= (
            self.soil_prod_rate[self.grid.core_nodes] * dt)

        #Update topography
        self.elev[self.grid.core_nodes] = (self.depth[self.grid.core_nodes]
                                         + self.bedrock[self.grid.core_nodes])

    def run_one_step(self, dt):
        """

        Parameters
        ----------
        dt: float (time)
            The imposed timestep.
        """

        self.soilflux(dt)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from __future__ import unicode_literals
try:
    from urlparse import urlparse
except ImportError:
    from urllib.parse import urlparse

from django.core import mail
from django.core.urlresolvers import reverse
from django.contrib.auth import get_user_model
import pytest

def _assert_redirect_to(_client, url):
    send_invite_url = reverse("send-invite")
    response = _client.get(send_invite_url, follow=True)
    assert response.redirect_chain
    redirect_url, status_code = response.redirect_chain[-1]
    assert status_code == 302
    parsed = urlparse(redirect_url)
    assert parsed.path == url
    assert parsed.query == "next=%s" % send_invite_url

@pytest.mark.django_db
def test_anonymous_users_are_redirected_to_login(client):
    login_url = reverse("login")
    _assert_redirect_to(client, login_url)

@pytest.mark.django_db
def test_non_privileged_users_are_redirected_to_login(auth_client):
    admin_login_url = reverse("admin:login")
    _assert_redirect_to(auth_client, admin_login_url)

@pytest.mark.django_db
def test_staff_are_allowed(admin_client):
    response = admin_client.get(reverse("send-invite"))
    assert response.status_code == 200

@pytest.mark.django_db
def test_send_email(admin_client):
    email = 'tester@test.com'
    User = get_user_model()
    assert User.objects.filter(email=email).count() == 0
    assert len(mail.outbox) == 0
    response = admin_client.post(
        reverse("send-invite"), {'registered_to': 'tester@test.com'},
        follow=True,
    )
    assert response.status_code == 200
    assert len(mail.outbox) == 1

<commit_msg>minor update test<commit_after># -*- coding: utf-8 -*-
from __future__ import unicode_literals
try:
    from urlparse import urlparse
except ImportError:
    from urllib.parse import urlparse

from django.core import mail
from django.core.urlresolvers import reverse
from django.contrib.auth import get_user_model
import pytest

def _assert_redirect_to(_client, url):
    send_invite_url = reverse("send-invite")
    response = _client.get(send_invite_url, follow=True)
    assert response.redirect_chain
    redirect_url, status_code = response.redirect_chain[-1]
    assert status_code == 302
    parsed = urlparse(redirect_url)
    assert parsed.path == url
    assert parsed.query == "next=%s" % send_invite_url

@pytest.mark.django_db
def test_anonymous_users_are_redirected_to_site_login(client):
    login_url = reverse("login")
    _assert_redirect_to(client, login_url)

@pytest.mark.django_db
def test_unprivileged_users_are_redirected_to_admin_login(auth_client):
    admin_login_url = reverse("admin:login")
    _assert_redirect_to(auth_client, admin_login_url)

@pytest.mark.django_db
def test_staff_are_allowed(admin_client):
    response = admin_client.get(reverse("send-invite"))
    assert response.status_code == 200

@pytest.mark.django_db
def test_send_invite_view(admin_client):
    email = 'tester@test.com'
    User = get_user_model()
    assert User.objects.filter(email=email).count() == 0
    N = len(mail.outbox)
    response = admin_client.post(
        reverse("send-invite"), {'registered_to': 'tester@test.com'},
        follow=True,
    )
    assert response.status_code == 200
    assert len(mail.outbox) == N+1

<|endoftext|>