<commit_before>#!/usr/bin/env python
from __future__ import print_function

__version__ = '0.1.1'

import argparse
import os
import platform
import shutil
import stat
import subprocess
import sys

from collections import OrderedDict
from datetime import datetime
from pathlib import Path

# Populated in __main__
STAGES = {}

class StageError(Exception):
    pass

class Tee(object):
    """Contect manager that duplicates stdout and stderr to a file
    """
    # http://stackoverflow.com/a/616686/1773758
    def __init__(self, path):
        self.file = path.open('w', encoding='utf8')
        self.stdout, sys.stdout = sys.stdout, self
        self.stderr, sys.stderr = sys.stderr, self

    def __enter__(self):
        pass

    def __exit__(self, type, value, traceback):
        sys.stdout, sys.stderr = self.stdout, self.stderr
        self.file.close()

    def write(self, data):
        # Flush to ensure that data are written to disk
        self.file.write(data)
        self.file.flush()
        self.stdout.write(data)
        self.stdout.flush()

class Stage(object):
    """A stage in a pipeline
    """

    def __init__(self, stage):
        if stage not in STAGES:
            raise StageError('Stage [{0}] not recognised'.format(stage))
        else:
            self.stage = stage
            p = Path(STAGES[stage][-1])
            self.output_dir = p.parent / p.stem

    def _prime(self):
        "Creates self.output_dir. An error is raised if it already exists"
        if self.output_dir.is_dir():
            msg = ('Output directory [{0}] already exists. Has this stage '
                   'already been run?')
            raise StageError(msg.format(self.output_dir))
        else:
            self.output_dir.mkdir()
            return Tee(self.output_dir / 'log.txt')

    def _time_string(self):
        return datetime.now().strftime('%Y-%m-%dT%H:%M:%S%Z')

    def _finished(self):
        "Makes output files read only"
        for p in (p for p in self.output_dir.rglob('*') if p.is_file()):
            mode = stat.S_IMODE(p.stat().st_mode)
            p.chmod(mode & ~(stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH))

    def _cmd(self, args):
        "Runs args and waits for it to finish, printing stdout"
        s = subprocess.Popen(args, stdout=subprocess.PIPE,
                             stderr=subprocess.STDOUT)
        while True:
            line = s.stdout.readline()
            exitcode = s.poll()
            line = line[:-1]
            if not line and exitcode is not None:
                break
            elif line:
                print(line.decode())

        if exitcode:
            sys.exit(exitcode)

    def run(self):
        "Runs this stage"
        with self._prime():
            print('Stage [{0}] started at [{1}]'.format(self.stage,
                                                        self._time_string()))
            print('Running somerset [{0}] in Python [{1}] on [{2}] [{3}]'.format(
                        __version__, sys.version, platform.node(), platform.platform()))
            args = STAGES[self.stage]
            if args[0].lower().endswith(('java', 'java.exe')):
                # Sigh...
                self._cmd( [args[0], '-version'] )
            else:
                self._cmd( [args[0], '--version'] )
            self._cmd(args)
            print('Stage [{0}] finished at [{1}]'.format(self.stage,
                                                         self._time_string()))

        self._finished()

def run_all():
    "Runs all stages"
    if not STAGES:
        raise StageError('No stages defined')
    else:
        print('Running all stages')
        for s in STAGES.keys():
            Stage(s).run()
        print('All stages completed')

def remove_all_output():
    "Removed all stage output directories"
    if not STAGES:
        raise StageError('No stages defined')
    else:
        print('Removing all output directories')
        for s in STAGES.keys():
            output_dir = Stage(s).output_dir
            if output_dir.is_dir():
                print('Removing [{0}]'.format(output_dir))
                shutil.rmtree(str(output_dir))
        print('All output directories removed')

def main():
    try:
        import stages
    except ImportError as e:
        print('Unable to import stages.py: {0}'.format(e))
    else:
        global STAGES
        STAGES = OrderedDict((stage, args) for stage, *args in stages.STAGES)

    parser = argparse.ArgumentParser(description='Simple scientific pipelines')
    parser.add_argument("stage", help='The stages to run', nargs='*')
    parser.add_argument('-v', '--version', action='version',
                        version='%(prog)s ' + __version__)
    #group = parser.add_mutually_exclusive_group(required=True)
    parser.add_argument("-l", '--list-stages', action='store_true',
                        help='List all stages')
    parser.add_argument('-r', '--remove-all-output', action='store_true',
                        help='Remove all stage output directories')
    args = parser.parse_args()

    if args.list_stages:
        for key, command_line in STAGES.items():
            print(key, command_line)
        print('all')
    elif args.remove_all_output:
        res = input('Are you sure you want to remove all output directories (y/N)?')
        if 'y'==res.lower():
            remove_all_output()
        else:
            print('No action taken')
    elif 1 == len(args.stage) and 'all'==args.stage[0].lower():
        run_all()
    elif args.stage:
        for stage in args.stage:
            Stage(stage).run()
    else:
        parser.print_help()

if __name__=='__main__':
    main()
<commit_msg>Added -R<commit_after>#!/usr/bin/env python
from __future__ import print_function

__version__ = '0.1.3'

import argparse
import os
import platform
import shutil
import stat
import subprocess
import sys

from collections import OrderedDict
from datetime import datetime
from pathlib import Path

# Populated in __main__
STAGES = {}

class StageError(Exception):
    pass

class Tee(object):
    """Contect manager that duplicates stdout and stderr to a file
    """
    # http://stackoverflow.com/a/616686/1773758
    def __init__(self, path):
        self.file = path.open('w', encoding='utf8')
        self.stdout, sys.stdout = sys.stdout, self
        self.stderr, sys.stderr = sys.stderr, self

    def __enter__(self):
        pass

    def __exit__(self, type, value, traceback):
        sys.stdout, sys.stderr = self.stdout, self.stderr
        self.file.close()

    def write(self, data):
        # Flush to ensure that data are written to disk
        self.file.write(data)
        self.file.flush()
        self.stdout.write(data)
        self.stdout.flush()

class Stage(object):
    """A stage in a pipeline
    """

    def __init__(self, stage):
        if stage not in STAGES:
            raise StageError('Stage [{0}] not recognised'.format(stage))
        else:
            self.stage = stage
            p = Path(STAGES[stage][-1])
            self.output_dir = p.parent / p.stem

    def _prime(self):
        "Creates self.output_dir. An error is raised if it already exists"
        if self.output_dir.is_dir():
            msg = ('Output directory [{0}] already exists. Has this stage '
                   'already been run?')
            raise StageError(msg.format(self.output_dir))
        else:
            self.output_dir.mkdir()
            return Tee(self.output_dir / 'log.txt')

    def _time_string(self):
        return datetime.now().strftime('%Y-%m-%dT%H:%M:%S%Z')

    def _finished(self):
        "Makes output files read only"
        for p in (p for p in self.output_dir.rglob('*') if p.is_file()):
            mode = stat.S_IMODE(p.stat().st_mode)
            p.chmod(mode & ~(stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH))

    def _cmd(self, args):
        "Runs args and waits for it to finish, printing stdout"
        s = subprocess.Popen(args, stdout=subprocess.PIPE,
                             stderr=subprocess.STDOUT)
        while True:
            line = s.stdout.readline()
            exitcode = s.poll()
            line = line[:-1]
            if not line and exitcode is not None:
                break
            elif line:
                print(line.decode())

        if exitcode:
            sys.exit(exitcode)

    def run(self):
        "Runs this stage"
        with self._prime():
            print('Stage [{0}] started at [{1}]'.format(self.stage,
                                                        self._time_string()))
            print('Running somerset [{0}] in Python [{1}] on [{2}] [{3}]'.format(
                        __version__, sys.version, platform.node(), platform.platform()))
            args = STAGES[self.stage]
            if args[0].lower().endswith(('java', 'java.exe')):
                # Sigh...
                self._cmd( [args[0], '-version'] )
            else:
                self._cmd( [args[0], '--version'] )
            self._cmd(args)
            print('Stage [{0}] finished at [{1}]'.format(self.stage,
                                                         self._time_string()))

        self._finished()

def run_all():
    "Runs all stages"
    if not STAGES:
        raise StageError('No stages defined')
    else:
        print('Running all stages')
        for s in STAGES.keys():
            Stage(s).run()
        print('All stages completed')

def remove_all_output():
    "Removed all stage output directories"
    if not STAGES:
        raise StageError('No stages defined')
    else:
        print('Removing all output directories')
        for s in STAGES.keys():
            output_dir = Stage(s).output_dir
            if output_dir.is_dir():
                print('Removing [{0}]'.format(output_dir))
                shutil.rmtree(str(output_dir))
        print('All output directories removed')

def main():
    try:
        import stages
    except ImportError as e:
        print('Unable to import stages.py: {0}'.format(e))
    else:
        global STAGES
        STAGES = OrderedDict((stage, args) for stage, *args in stages.STAGES)

    parser = argparse.ArgumentParser(description='Simple scientific pipelines')
    parser.add_argument("stage", help='The stages to run', nargs='*')
    parser.add_argument('-v', '--version', action='version',
                        version='%(prog)s ' + __version__)
    parser.add_argument("-l", '--list-stages', action='store_true',
                        help='List all stages')

    group_r = parser.add_mutually_exclusive_group()
    group_r.add_argument('-r', '--remove-all-output', action='store_true',
                        help='Remove all stage output directories')
    group_r.add_argument('-R', '--REMOVE-ALL-OUTPUT', action='store_true',
                        help='Same as -r but does not prompt before removing')
    args = parser.parse_args()

    if args.list_stages:
        for key, command_line in STAGES.items():
            print(key, command_line)
        print('all')
    elif args.remove_all_output or args.REMOVE_ALL_OUTPUT:
        if args.remove_all_output:
            res = input('Are you sure you want to remove all output directories '
                        '(y/N)?')
        if args.REMOVE_ALL_OUTPUT or 'y'==res.lower():
            remove_all_output()
        else:
            print('No action taken')
    elif 1 == len(args.stage) and 'all'==args.stage[0].lower():
        run_all()
    elif args.stage:
        for stage in args.stage:
            Stage(stage).run()
    else:
        parser.print_help()

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


<commit_before>"""sosource.py Second order source term calculation module.
Author: Ian Huston
$Id: sosource.py,v 1.42 2009/02/16 17:56:38 ith Exp $

Provides the method getsourceandintegrate which uses an instance of a first
order class from cosmomodels to calculate the source term required for second
order models.

"""

from __future__ import division # Get rid of integer division problems, i.e. 1/2=0
import tables
import numpy as N
from scipy import integrate
import helpers
import logging
import time
import os

#This is the results directory which will be used if no filenames are specified
RESULTSDIR = "/misc/scratch/ith/numerics/results/"

#Start logging
source_logger = logging.getLogger(__name__)

def slowrollsrcterm(k, q, a, potentials, bgvars, fovars, s2shape):
    """Return unintegrated slow roll source term.

    The source term before integration is calculated here using the slow roll
    approximation. This function follows the revised version of Eq (5.8) in
    Malik 06 (astro-ph/0610864v5).

    Parameters
    ----------
    k: array_like
       Array of mode numbers being calculated.

    q: array_like
       Array of mode numbers which will be integrated over.
       (Should be the same as k, might remove later.)

    a: float
       Scale factor at the current timestep, `a = ainit*exp(n)`

    potentials: tuple
                Tuple of potential values in the form `(U, dU, dU2, dU3)`

    bgvars: tuple
            Tuple of background field values in the form `(phi, phidot, H)`

    fovars: tuple
            Tuple of first order field values in the form `(dphi1, dphi1dot, dp1diff, dp1dotdiff)`

    s2shape: tuple
             Shape of the results array to return

    Returns
    -------
    s2: array_like
        Array containing the unintegrated source terms for all k and q modes.

    References
    ----------
    Malik, K. 2006, JCAP03(2007)004, astro-ph/0610864v5
    """
    #Unpack variables
    phi, phidot, H = bgvars
    U, dU, dU2, dU3 = potentials
    dphi1, dphi1dot, dp1diff, dp1dotdiff = fovars
    #Initialize result variable for k modes
    s2 = N.empty(s2shape)

    #Calculate unintegrated source term
    #First major term:
    s2 = ((1/H**2) * (dU3 + 3*phidot*dU2) * q**2*dp1diff*dphi1)
    #Second major term:
    s2 += ((-1.5*q**2) * phidot * dp1dotdiff * dphi1dot)
    #Third major term:
    s2 += (1/((a*H)**2) * (2.5*q**4 + 2*(k*q)**2) * phidot * dp1diff * dphi1)
    #Multiply by prefactor
    s2 = s2 * (1/(2*N.pi**2))

    return s2

def calculatesource(m, nix, integrand_elements, srcfunc=slowrollsrcterm):
    """Return the integrated source term at this timestep.

    Given the first order model and the timestep calculate the
    integrated source term at this time step.

    Parameters
    ----------
    m: Cosmomodels.TwoStageModel
       First order model to be used.

    nix: int
         Index of current timestep in m.tresult

    integrand_elements: tuple
         Contains integrand arrays in order
         integrand_elements = (k, q, theta, klessq)

    srcfunc: function, optional
             Funtion which contains expression for source integrand
             Default is slowrollsrcterm in this module.

    Returns
    -------
    s: array_like
       Integrated source term calculated using srcfunc.
    """
    #Unpack important arrays
    k, q, theta, klessq = integrand_elements

    #Copy of yresult
    myr = m.yresult[nix].copy()
    #Fill nans with initial conditions
    if N.any(m.tresult[nix] < m.fotstart):
        #Get first order ICs:
        nanfiller = m.getfoystart(m.tresult[nix].copy(), N.array([nix]))
        source_logger.debug("Left getfoystart. Filling nans...")
        #switch nans for ICs in m.yresult
        are_nan = N.isnan(myr)
        myr[are_nan] = nanfiller[are_nan]
        source_logger.debug("NaNs filled. Setting dynamical variables...")

    #Get first order results
    dphi1 = myr[3,:] + myr[4,:]*1j
    dphi1dot = myr[5,:] + myr[6,:]*1j
    #Setup interpolation
    dp1func = interpolate.interp1d(m.k, dphi1)
    dp1dotfunc = interpolate.interp1d(m.k, dphi1dot)

    source_logger.debug("Variables set. Getting potentials for this timestep...")
    potentials = list(m.potentials(myr))
    #Get potentials in right shape
    for pix, p in enumerate(potentials):
        if N.shape(p) != N.shape(potentials[0]):
            potentials[pix] = p*N.ones_like(potentials[0])
    source_logger.debug("Potentials obtained. Setting a and making results array...")
    #Single time step
    a = m.ainit*N.exp(m.tresult[nix])

    #save results for each q
    source_logger.debug("Calculating source term integrand for this tstep...")
    #Get unintegrated source term
    s2 = srcfunc(bgvars, a, potentials, integrand_elements, dp1func, dp1dotfunc)

    #Get integration function
    source_logger.debug("Integrating source term...")
    intfunc, intfnargs = helpers.getintfunc(m.k)
    #Do integration
    s2int=intfunc(s2, **intfnargs) #Do theta and q integrations
    return s2int

def getsourceandintegrate(m, savefile=None, srcfunc=slowrollsrcterm, ntheta=129):
    """Calculate and save integrated source term.

    Using first order results in the specified model, the source term for second order perturbations
    is obtained from the given source function. The convolution integral is performed and the results
    are saved in a file with the specified filename.

    Parameters
    ----------
    m: compatible cosmomodels model instance
       The model class should contain first order results as in `cosmomodels.FOCanonicalTwoStage`

    savefile: String, optional
              Filename where results should be saved.

    srcfunc: function, optional
             Function which returns unintegrated source term. Defaults to slowrollsrcterm in this module.
             Function signature is `srcfunc(k, q, a, potentials, bgvars, fovars, s2shape)`.

    Returns
    -------
    savefile: String
              Filename where results have been saved.
    """
    #Initialize variables for all timesteps
    halfk = m.k[:len(m.k)/2] #Need N=len(m.k)/2 for case when q=-k
    k = halfk[...,newaxis,newaxis]
    q = halfk[newaxis,...,newaxis]
    theta = N.linspace(0, N.pi, ntheta)[newaxis,newaxis,...]
    #Main array of k^i - q^i values
    klessq=sqrt(k**2+q**2-2*k*q*cos(theta2))
    #Pack together in tuple
    integrand_elements = (k, q, theta, klessq)
    #Get atom shape for savefile
    atomshape = (0, len(halfk))
    #Main try block for file IO
    try:
        sf, sarr = opensourcefile(atomshape, savefile, sourcetype="term")
        try:
            # Begin calculation
            source_logger.debug("Entering main time loop...")
            #Main loop over each time step
            for nix in xrange(len(m.tresult)):
                if nix%1000 == 0:
                    source_logger.info("Starting n=%f, nix=%d sequence...", m.tresult[nix], nix)
                #Only run calculation if one of the modes has started.
                if any(m.tresult[nix+2] >= m.fotstart):
                    src = calculatesource(m, nix, integrand_elements, srcfunc)
                else:
                    src = N.nan*N.ones_like(m.k)
                sarr.append(src[N.newaxis,:])
                source_logger.debug("Results for this timestep saved.")
        finally:
            #source = N.array(source)
            sf.close()
    except IOError:
        raise
    return savefile

def opensourcefile(atomshape, filename=None, sourcetype=None):
    """Open the source term hdf5 file with filename."""
    #Set up file for results
    if not filename or not os.path.isdir(os.path.dirname(filename)):
        date = time.strftime("%Y%m%d%H%M%S")
        filename = RESULTSDIR + "src" + date + ".hf5"
        source_logger.info("Saving source results in file " + filename)
    if not sourcetype:
        raise TypeError("Need to specify filename and type of source data to store [int(egrand)|(full)term]!")
    if sourcetype in ["int", "term"]:
        sarrname = "source" + sourcetype
        source_logger.debug("Source array type: " + sarrname)
    else:
        raise TypeError("Incorrect source type specified!")
    #Add compression to files and specify good chunkshape
    filters = tables.Filters(complevel=1, complib="zlib")
    #cshape = (10,10,10) #good mix of t, k, q values
    try:
        source_logger.debug("Trying to open source file " + filename)
        rf = tables.openFile(filename, "a", "Source term result")
        if not "results" in rf.root:
            source_logger.debug("Creating group 'results' in source file.")
            rf.createGroup(rf.root, "results", "Results")
        if not sarrname in rf.root.results:
            source_logger.debug("Creating array '" + sarrname + "' in source file.")
            sarr = rf.createEArray(rf.root.results, sarrname, tables.ComplexAtom(itemsize=16), atomshape, filters=filters)
        else:
            source_logger.debug("Source file and node exist. Testing source node shape...")
            sarr = rf.getNode(rf.root.results, sarrname)
            if sarr.shape[1:] != atomshape[1:]:
                raise ValueError("Source node on file is not correct shape!")
    except IOError:
        raise
    return rf, sarr
<commit_msg>Change signature of slowrollsrcterm.<commit_after>"""sosource.py Second order source term calculation module.
Author: Ian Huston
$Id: sosource.py,v 1.43 2009/02/16 18:00:32 ith Exp $

Provides the method getsourceandintegrate which uses an instance of a first
order class from cosmomodels to calculate the source term required for second
order models.

"""

from __future__ import division # Get rid of integer division problems, i.e. 1/2=0
import tables
import numpy as N
from scipy import integrate
import helpers
import logging
import time
import os

#This is the results directory which will be used if no filenames are specified
RESULTSDIR = "/misc/scratch/ith/numerics/results/"

#Start logging
source_logger = logging.getLogger(__name__)

def slowrollsrcterm(bgvars, a, potentials, integrand_elements, dp1func, dp1dotfunc):
    """Return unintegrated slow roll source term.

    The source term before integration is calculated here using the slow roll
    approximation. This function follows the revised version of Eq (5.8) in
    Malik 06 (astro-ph/0610864v5).

    Parameters
    ----------
    bgvars: tuple
            Tuple of background field values in the form `(phi, phidot, H)`

    a: float
       Scale factor at the current timestep, `a = ainit*exp(n)`

    potentials: tuple
                Tuple of potential values in the form `(U, dU, dU2, dU3)`

    integrand_elements: tuple
         Contains integrand arrays in order (k, q, theta, klessq)

    dp1func: function object
             Interpolation function for \delta\phi_1

    dp1dotfunc: function object
             Interpolation function for \dot{\delta\phi_1}

    Returns
    -------
    src_integrand: array_like
        Array containing the unintegrated source terms for all k and q modes.

    References
    ----------
    Malik, K. 2006, JCAP03(2007)004, astro-ph/0610864v5
    """
    #Unpack variables
    phi, phidot, H = bgvars
    U, dU, dU2, dU3 = potentials
    dphi1, dphi1dot, dp1diff, dp1dotdiff = fovars
    #Initialize result variable for k modes
    s2 = N.empty(s2shape)

    #Calculate unintegrated source term
    #First major term:
    s2 = ((1/H**2) * (dU3 + 3*phidot*dU2) * q**2*dp1diff*dphi1)
    #Second major term:
    s2 += ((-1.5*q**2) * phidot * dp1dotdiff * dphi1dot)
    #Third major term:
    s2 += (1/((a*H)**2) * (2.5*q**4 + 2*(k*q)**2) * phidot * dp1diff * dphi1)
    #Multiply by prefactor
    s2 = s2 * (1/(2*N.pi**2))

    return src_integrand

def calculatesource(m, nix, integrand_elements, srcfunc=slowrollsrcterm):
    """Return the integrated source term at this timestep.

    Given the first order model and the timestep calculate the
    integrated source term at this time step.

    Parameters
    ----------
    m: Cosmomodels.TwoStageModel
       First order model to be used.

    nix: int
         Index of current timestep in m.tresult

    integrand_elements: tuple
         Contains integrand arrays in order
         integrand_elements = (k, q, theta, klessq)

    srcfunc: function, optional
             Funtion which contains expression for source integrand
             Default is slowrollsrcterm in this module.

    Returns
    -------
    s: array_like
       Integrated source term calculated using srcfunc.
    """
    #Unpack important arrays
    k, q, theta, klessq = integrand_elements

    #Copy of yresult
    myr = m.yresult[nix].copy()
    #Fill nans with initial conditions
    if N.any(m.tresult[nix] < m.fotstart):
        #Get first order ICs:
        nanfiller = m.getfoystart(m.tresult[nix].copy(), N.array([nix]))
        source_logger.debug("Left getfoystart. Filling nans...")
        #switch nans for ICs in m.yresult
        are_nan = N.isnan(myr)
        myr[are_nan] = nanfiller[are_nan]
        source_logger.debug("NaNs filled. Setting dynamical variables...")

    #Get first order results
    bgvars = myr[0:3,:]
    dphi1 = myr[3,:] + myr[4,:]*1j
    dphi1dot = myr[5,:] + myr[6,:]*1j
    #Setup interpolation
    dp1func = interpolate.interp1d(m.k, dphi1)
    dp1dotfunc = interpolate.interp1d(m.k, dphi1dot)

    source_logger.debug("Variables set. Getting potentials for this timestep...")
    potentials = list(m.potentials(myr))
    #Get potentials in right shape
    for pix, p in enumerate(potentials):
        if N.shape(p) != N.shape(potentials[0]):
            potentials[pix] = p*N.ones_like(potentials[0])
    source_logger.debug("Potentials obtained. Setting a and making results array...")
    #Single time step
    a = m.ainit*N.exp(m.tresult[nix])

    #save results for each q
    source_logger.debug("Calculating source term integrand for this tstep...")
    #Get unintegrated source term
    s2 = srcfunc(bgvars, a, potentials, integrand_elements, dp1func, dp1dotfunc)

    #Get integration function
    source_logger.debug("Integrating source term...")
    intfunc, intfnargs = helpers.getintfunc(m.k)
    #Do integration
    s2int=intfunc(s2, **intfnargs) #Do theta and q integrations
    return s2int

def getsourceandintegrate(m, savefile=None, srcfunc=slowrollsrcterm, ntheta=129):
    """Calculate and save integrated source term.

    Using first order results in the specified model, the source term for second order perturbations
    is obtained from the given source function. The convolution integral is performed and the results
    are saved in a file with the specified filename.

    Parameters
    ----------
    m: compatible cosmomodels model instance
       The model class should contain first order results as in `cosmomodels.FOCanonicalTwoStage`

    savefile: String, optional
              Filename where results should be saved.

    srcfunc: function, optional
             Function which returns unintegrated source term. Defaults to slowrollsrcterm in this module.
             Function signature is `srcfunc(k, q, a, potentials, bgvars, fovars, s2shape)`.

    Returns
    -------
    savefile: String
              Filename where results have been saved.
    """
    #Initialize variables for all timesteps
    halfk = m.k[:len(m.k)/2] #Need N=len(m.k)/2 for case when q=-k
    k = halfk[...,newaxis,newaxis]
    q = halfk[newaxis,...,newaxis]
    theta = N.linspace(0, N.pi, ntheta)[newaxis,newaxis,...]
    #Main array of k^i - q^i values
    klessq=sqrt(k**2+q**2-2*k*q*cos(theta2))
    #Pack together in tuple
    integrand_elements = (k, q, theta, klessq)
    #Get atom shape for savefile
    atomshape = (0, len(halfk))
    #Main try block for file IO
    try:
        sf, sarr = opensourcefile(atomshape, savefile, sourcetype="term")
        try:
            # Begin calculation
            source_logger.debug("Entering main time loop...")
            #Main loop over each time step
            for nix in xrange(len(m.tresult)):
                if nix%1000 == 0:
                    source_logger.info("Starting n=%f, nix=%d sequence...", m.tresult[nix], nix)
                #Only run calculation if one of the modes has started.
                if any(m.tresult[nix+2] >= m.fotstart):
                    src = calculatesource(m, nix, integrand_elements, srcfunc)
                else:
                    src = N.nan*N.ones_like(m.k)
                sarr.append(src[N.newaxis,:])
                source_logger.debug("Results for this timestep saved.")
        finally:
            #source = N.array(source)
            sf.close()
    except IOError:
        raise
    return savefile

def opensourcefile(atomshape, filename=None, sourcetype=None):
    """Open the source term hdf5 file with filename."""
    #Set up file for results
    if not filename or not os.path.isdir(os.path.dirname(filename)):
        date = time.strftime("%Y%m%d%H%M%S")
        filename = RESULTSDIR + "src" + date + ".hf5"
        source_logger.info("Saving source results in file " + filename)
    if not sourcetype:
        raise TypeError("Need to specify filename and type of source data to store [int(egrand)|(full)term]!")
    if sourcetype in ["int", "term"]:
        sarrname = "source" + sourcetype
        source_logger.debug("Source array type: " + sarrname)
    else:
        raise TypeError("Incorrect source type specified!")
    #Add compression to files and specify good chunkshape
    filters = tables.Filters(complevel=1, complib="zlib")
    #cshape = (10,10,10) #good mix of t, k, q values
    try:
        source_logger.debug("Trying to open source file " + filename)
        rf = tables.openFile(filename, "a", "Source term result")
        if not "results" in rf.root:
            source_logger.debug("Creating group 'results' in source file.")
            rf.createGroup(rf.root, "results", "Results")
        if not sarrname in rf.root.results:
            source_logger.debug("Creating array '" + sarrname + "' in source file.")
            sarr = rf.createEArray(rf.root.results, sarrname, tables.ComplexAtom(itemsize=16), atomshape, filters=filters)
        else:
            source_logger.debug("Source file and node exist. Testing source node shape...")
            sarr = rf.getNode(rf.root.results, sarrname)
            if sarr.shape[1:] != atomshape[1:]:
                raise ValueError("Source node on file is not correct shape!")
    except IOError:
        raise
    return rf, sarr
<|endoftext|>


<commit_before>from ggame import App, Sprite, ImageAsset, Frame
import math

class Stars(Sprite):

    asset = ImageAsset("starfield.jpg")
    width = 512
    height = 512

    def __init__(self, position):
        super().__init__(Stars.asset, position)

class Sun(Sprite):

    asset = ImageAsset("sun.png")
    width = 80
    height = 76

    def __init__(self, position):
        super().__init__(Sun.asset, position)
        self.mass = 30*1000
        self.fxcenter = 0.5
        self.fycenter = 0.5

class Vector(object):

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def mag(self):
        return math.sqrt(self.x*self.x + self.y*self.y)

    def unit(self):
        r = self.mag()
        if r == 0:
            return Vector(0,0)
        else:
            return Vector(self.x/r, self.y/r)

class GravitySprite(Sprite):

    G = 1.0
    T = 3.0

    def __init__(self, asset, position, velocity, sun):
        super().__init__(asset, position)
        self.vx = velocity[0]
        self.vy = velocity[1]
        self.sun = sun
        self.fxcenter = 0.5
        self.fycenter = 0.5
        self.rrate = 0.0
        self.thrust = 0.0

    def step(self):
        dt = 0.033
        R = Vector(self.sun.x-self.x, self.sun.y-self.y)
        Ur = R.unit()
        ag = GravitySprite.G*self.sun.mass/R.mag()**2
        Ag = Vector(Ur.x*ag, Ur.y*ag)
        vx = self.vx
        vy = self.vy
        self.vx += (Ag.x + self.thrust*GravitySprite.T*math.sin(self.rotation))* dt
        self.vy += (Ag.y - self.thrust*GravitySprite.T*math.cos(self.rotation))* dt
        self.x += self.vx + 0.5*Ag.x*dt*dt
        self.y += self.vy + 0.5*Ag.y*dt*dt

class Ship(GravitySprite):

    R = 2.0
    bullets = 4

    def __init__(self, asset, app, position, velocity, sun):
        super().__init__(asset, position, velocity, sun)
        self.app = app
        bullets = []
        for i in range(Ship.bullets):
            bullets.append(Bullet(app, sun))

    def registerKeys(self, keys):
        commands = ["left", "right", "forward", "fire"]
        self.keymap = dict(zip(keys, commands))
        [self.app.listenKeyEvent("keydown", k, self.controldown) for k in keys]
        [self.app.listenKeyEvent("keyup", k, self.controlup) for k in keys]

    def shootvector(self):
        vel = 2
        xv = vel*math.sin(self.rotation)
        yv = vel*(-math.cos(self.rotation))
        return xv + self.xv, yv + self.yv

    def controldown(self, event):
        command = self.keymap[event.key]
        if command == "left":
            self.rrate = -0.01*Ship.R
        elif command == "right":
            self.rrate = Ship.R*0.01
        elif command == "forward":
            self.thrust = 0.1
        elif command == "fire":
            for bullet in bullets:
                if bullet.time == 0:
                    bullet.shoot(self.position, self.shootvector(), 15)

    def controlup(self, event):
        command = self.keymap[event.key]
        if command in ["left", "right"]:
            self.rrate = 0.0
        elif command == "forward":
            self.thrust = 0.0

    def step(self):
        super().step()
        self.rotation += self.rrate

class Bullet(GravitySprite):

    asset = ImageAsset("blast.png", Frame(0,0,8,8), 8)

    def __init__(self, app, sun):
        super().__init__(Bullet.asset, (0,0), (0,0), sun)
        self.visible = False
        self.time = 0

    def shoot(self, position, velocity, time):
        self.position = position
        self.vx = velocity[0]
        self.vy = velocity[1]
        self.time = time*30
        self.visible = True

    def step(self):
        if self.time > 0:
            self.time -= 1
            super().step()
        elif self.visible:
            self.visible = False

class Ship1(Ship):

    asset = ImageAsset("four_spaceship_by_albertov.png",
        Frame(227,0,292-227,92), 1)

    def __init__(self, app, position, velocity, sun):
        super().__init__(Ship1.asset, app, position, velocity, sun)
        self.registerKeys(["left arrow", "right arrow", "up arrow", "enter"])

class Ship2(Ship):

    asset = ImageAsset("four_spaceship_by_albertov.png",
        Frame(0,0,86,92), 1)

    def __init__(self, app, position, velocity, sun):
        super().__init__(Ship2.asset, app, position, velocity, sun)
        self.registerKeys(["a", "d", "w", "space"])

class Spacewar(App):

    def __init__(self, width, height):
        super().__init__(width, height)
        for x in range(self.width//Stars.width + 1):
            for y in range(self.height//Stars.height + 1):
                Stars((x*Stars.width, y*Stars.height))
        self.sun = Sun((self.width/2, self.height/2))
        self.ship1 = Ship1(self, (self.width/2+100,self.height/2), (0,-4), self.sun)
        self.ship2 = Ship2(self, (self.width/2-100,self.height/2), (0,4), self.sun)

    def step(self):
        #for ship in self.getSpritesbyClass(Ship1
        self.ship1.step()
        self.ship2.step()

app = Spacewar(0,0)
app.run()

<commit_msg>Updated from Brython Server: 8/7/2015 5:40:54 PM<commit_after>from ggame import App, Sprite, ImageAsset, Frame
import math

class Stars(Sprite):

    asset = ImageAsset("starfield.jpg")
    width = 512
    height = 512

    def __init__(self, position):
        super().__init__(Stars.asset, position)

class Sun(Sprite):

    asset = ImageAsset("sun.png")
    width = 80
    height = 76

    def __init__(self, position):
        super().__init__(Sun.asset, position)
        self.mass = 30*1000
        self.fxcenter = 0.5
        self.fycenter = 0.5

class Vector(object):

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def mag(self):
        return math.sqrt(self.x*self.x + self.y*self.y)

    def unit(self):
        r = self.mag()
        if r == 0:
            return Vector(0,0)
        else:
            return Vector(self.x/r, self.y/r)

class GravitySprite(Sprite):

    G = 1.0
    T = 3.0

    def __init__(self, asset, position, velocity, sun):
        super().__init__(asset, position)
        self.vx = velocity[0]
        self.vy = velocity[1]
        self.sun = sun
        self.fxcenter = 0.5
        self.fycenter = 0.5
        self.rrate = 0.0
        self.thrust = 0.0

    def step(self):
        dt = 0.033
        R = Vector(self.sun.x-self.x, self.sun.y-self.y)
        Ur = R.unit()
        ag = GravitySprite.G*self.sun.mass/R.mag()**2
        Ag = Vector(Ur.x*ag, Ur.y*ag)
        vx = self.vx
        vy = self.vy
        self.vx += (Ag.x + self.thrust*GravitySprite.T*math.sin(self.rotation))* dt
        self.vy += (Ag.y - self.thrust*GravitySprite.T*math.cos(self.rotation))* dt
        self.x += self.vx + 0.5*Ag.x*dt*dt
        self.y += self.vy + 0.5*Ag.y*dt*dt

class Ship(GravitySprite):

    R = 2.0
    bullets = 4

    def __init__(self, asset, app, position, velocity, sun):
        super().__init__(asset, position, velocity, sun)
        self.app = app
        bullets = []
        for i in range(Ship.bullets):
            bullets.append(Bullet(app, sun))

    def registerKeys(self, keys):
        commands = ["left", "right", "forward", "fire"]
        self.keymap = dict(zip(keys, commands))
        [self.app.listenKeyEvent("keydown", k, self.controldown) for k in keys]
        [self.app.listenKeyEvent("keyup", k, self.controlup) for k in keys]

    def shootvector(self):
        vel = 2
        xv = vel*math.sin(self.rotation)
        yv = vel*(-math.cos(self.rotation))
        return xv + self.xv, yv + self.yv

    def controldown(self, event):
        command = self.keymap[event.key]
        if command == "left":
            self.rrate = -0.01*Ship.R
        elif command == "right":
            self.rrate = Ship.R*0.01
        elif command == "forward":
            self.thrust = 0.1
        elif command == "fire":
            for bullet in bullets:
                if bullet.time == 0:
                    print("shooting")
                    bullet.shoot(self.position, self.shootvector(), 15)
                    break

    def controlup(self, event):
        command = self.keymap[event.key]
        if command in ["left", "right"]:
            self.rrate = 0.0
        elif command == "forward":
            self.thrust = 0.0

    def step(self):
        super().step()
        self.rotation += self.rrate

class Bullet(GravitySprite):

    asset = ImageAsset("blast.png", Frame(0,0,8,8), 8)

    def __init__(self, app, sun):
        super().__init__(Bullet.asset, (0,0), (0,0), sun)
        self.visible = False
        self.time = 0

    def shoot(self, position, velocity, time):
        self.position = position
        self.vx = velocity[0]
        self.vy = velocity[1]
        self.time = time*30
        self.visible = True

    def step(self):
        if self.time > 0:
            self.time -= 1
            super().step()
        elif self.visible:
            self.visible = False

class Ship1(Ship):

    asset = ImageAsset("four_spaceship_by_albertov.png",
        Frame(227,0,292-227,92), 1)

    def __init__(self, app, position, velocity, sun):
        super().__init__(Ship1.asset, app, position, velocity, sun)
        self.registerKeys(["left arrow", "right arrow", "up arrow", "enter"])

class Ship2(Ship):

    asset = ImageAsset("four_spaceship_by_albertov.png",
        Frame(0,0,86,92), 1)

    def __init__(self, app, position, velocity, sun):
        super().__init__(Ship2.asset, app, position, velocity, sun)
        self.registerKeys(["a", "d", "w", "space"])

class Spacewar(App):

    def __init__(self, width, height):
        super().__init__(width, height)
        for x in range(self.width//Stars.width + 1):
            for y in range(self.height//Stars.height + 1):
                Stars((x*Stars.width, y*Stars.height))
        self.sun = Sun((self.width/2, self.height/2))
        self.ship1 = Ship1(self, (self.width/2+100,self.height/2), (0,-4), self.sun)
        self.ship2 = Ship2(self, (self.width/2-100,self.height/2), (0,4), self.sun)

    def step(self):
        #for ship in self.getSpritesbyClass(Ship1
        self.ship1.step()
        self.ship2.step()

app = Spacewar(0,0)
app.run()

<|endoftext|>


<commit_before># run from root sources directory: python Scripts/cppcheck/cppcheck.py
import os

ignoredContent = [
#	"It is safe to deallocate a NULL pointer", # ignore, fine for us
	"Exception thrown in destructor.", # ignore, fine for us
#	"::initialise' can be const.", # ignore, because some are not const and we keep all non-const for similarity
#	"::shutdown' can be const.", # ignore, because some are not const and we keep all non-const for similarity
#	"hides typedef with same name", # false positive
	"(style) The function '", # ignore "Function is never used"
	"MyGUI_UString", # ignore warnings from UString, because it wasn't written by the MyGUI developers
	"pugixml", # ignore warnings from pugixml, because it wasn't written by the MyGUI developers
	"sigslot", # ignore warnings from sigslot, because it wasn't written by the MyGUI developers
#	") Include file: ", # ignore "(debug) Include file: "name" can not be found."
#	"Technically the member function 'input::", # useless, because with other input system this function could be non-const
#	"Cppcheck cannot find all the include files",
	"is assigned in constructor body. Consider performing initialization in initialization list.", # ignore, fine for us
	"(performance) Prefer prefix ++/-- operators for non-primitive types", # ignore, fine for us - leave this optimisation to compiler
	"MyGUI_DelegateImplement.h:195]: (warning) 'operator=' should check for assignment to self to avoid problems with dynamic memory.", # false positive
	"(error) Reference to temporary returned." # only false positives (revert later)
]

def isIgnoredWarning(warning):
	for ignore in ignoredContent:
		if warning.find(ignore) != -1:
			return True
	return False

def parseOutput():
	file = open("temp.cppcheck", 'r')

	line = file.readline()
	while line != "":
		line = line[0:len(line)-1]
		if (not isIgnoredWarning(line)):
			print line
		line = file.readline()
	file.close ()

def checkFolderSources(folder, flags) :
	os.system("cppcheck --enable=all -I Scripts/cppcheck -I MyGUIEngine/include -D MYGUI_COMPILER=2 " + flags + " " + folder + " 2>temp.cppcheck")
	parseOutput()

checkFolderSources('MyGUIEngine', '')

checkFolderSources('Demos', '-I Common -I Common/Base/Ogre -I Common/Input/OIS -I Platforms/Ogre/OgrePlatform/include -I Plugins/Plugin_BerkeliumWidget')
checkFolderSources('Tools', '-I Common -I Common/Base/Ogre -I Common/Input/OIS -I Platforms/Ogre/OgrePlatform/include -I Tools/EditorFramework')
checkFolderSources('UnitTests/UnitTest_*', '-I Common -I Common/Base/Ogre -I Common/Input/OIS -I Platforms/Ogre/OgrePlatform/include')
checkFolderSources('Common', '-I Common')
checkFolderSources('Platforms/OpenGL/OpenGLPlatform/src', '-I Platforms/OpenGL/OpenGLPlatform/include -I Common')
checkFolderSources('Platforms/Ogre/OgrePlatform/src', '-I Platforms/Ogre/OgrePlatform/include')
checkFolderSources('Platforms/DirectX/DirectXPlatform/src', '-I Platforms/DirectX/DirectXPlatform/include -I Common')
checkFolderSources('Platforms/DirectX11/DirectX11Platform/src', '-I Platforms/DirectX11/DirectX11Platform/include -I Common')
checkFolderSources('Plugins', '')
checkFolderSources('Wrappers/MyGUI_Export', ' -I Common')

<commit_msg>update cppcheck script<commit_after># run from root sources directory: python Scripts/cppcheck/cppcheck.py
import os

ignoredContent = [
#	"It is safe to deallocate a NULL pointer", # ignore, fine for us
	"Exception thrown in destructor.", # ignore, fine for us
#	"::initialise' can be const.", # ignore, because some are not const and we keep all non-const for similarity
#	"::shutdown' can be const.", # ignore, because some are not const and we keep all non-const for similarity
	"(style) The function '", # ignore "Function is never used"
	"MyGUI_UString", # ignore warnings from UString, because it wasn't written by the MyGUI developers
	"pugixml", # ignore warnings from pugixml, because it wasn't written by the MyGUI developers
	"sigslot", # ignore warnings from sigslot, because it wasn't written by the MyGUI developers
#	") Include file: ", # ignore "(debug) Include file: "name" can not be found."
#	"Technically the member function 'input::", # useless, because with other input system this function could be non-const
#	"Cppcheck cannot find all the include files",
	"is assigned in constructor body. Consider performing initialization in initialization list.", # ignore, fine for us
	"(performance) Prefer prefix ++/-- operators for non-primitive types", # ignore, fine for us - leave this optimisation to compiler
	"MyGUI_DelegateImplement.h:195]: (warning) 'operator=' should check for assignment to self to avoid problems with dynamic memory.", # false positive
#	"(error) Reference to temporary returned." # only false positives (revert later)
	"does not have a copy constructor which is recommended since the class contains a pointer to allocated memory." # ignore, not important
]

def isIgnoredWarning(warning):
	for ignore in ignoredContent:
		if warning.find(ignore) != -1:
			return True
	return False

def parseOutput():
	file = open("temp.cppcheck", 'r')

	line = file.readline()
	while line != "":
		line = line[0:len(line)-1]
		if (not isIgnoredWarning(line)):
			print line
		line = file.readline()
	file.close ()

def checkFolderSources(folder, flags) :
	os.system("cppcheck --enable=all -I Scripts/cppcheck -I MyGUIEngine/include -D MYGUI_COMPILER=2 " + flags + " " + folder + " 2>temp.cppcheck")
	parseOutput()

checkFolderSources('MyGUIEngine', '')

checkFolderSources('Demos', '-I Common -I Common/Base/Ogre -I Common/Input/OIS -I Platforms/Ogre/OgrePlatform/include -I Plugins/Plugin_BerkeliumWidget')
checkFolderSources('Tools', '-I Common -I Common/Base/Ogre -I Common/Input/OIS -I Platforms/Ogre/OgrePlatform/include -I Tools/EditorFramework')
checkFolderSources('UnitTests/UnitTest_*', '-I Common -I Common/Base/Ogre -I Common/Input/OIS -I Platforms/Ogre/OgrePlatform/include')
checkFolderSources('Common', '-I Common -I Common/Input/OIS')
checkFolderSources('Platforms/OpenGL/OpenGLPlatform/src', '-I Platforms/OpenGL/OpenGLPlatform/include -I Common')
checkFolderSources('Platforms/Ogre/OgrePlatform/src', '-I Platforms/Ogre/OgrePlatform/include')
checkFolderSources('Platforms/DirectX/DirectXPlatform/src', '-I Platforms/DirectX/DirectXPlatform/include -I Common')
checkFolderSources('Platforms/DirectX11/DirectX11Platform/src', '-I Platforms/DirectX11/DirectX11Platform/include -I Common')
checkFolderSources('Plugins', '')
checkFolderSources('Wrappers/MyGUI_Export', ' -I Common')

<|endoftext|>


<commit_before># to be used with h5py

import numpy as np
from scipy.sparse import coo_matrix

def to_sparse_repr(mat):
    mat = coo_matrix(mat)
    dtype = [('r', int), ('c', int), ('v', mat.dtype)]
    m = np.zeros(shape=(mat.nnz,), dtype=dtype)
    m["r"] = mat.row
    m["c"] = mat.col
    m["v"] = mat.data
    return m

def from_sparse_repr(m, shape=None):
    return coo_matrix((m["v"], (m["r"], m["c"])), shape=shape)

def save_sparse_h5(grp, name, data):
    grp[name] = to_sparse_repr(data)
    grp[name].attrs["shape"] = data.shape

def load_sparse_h5(grp, name):
    shape = grp[name].attrs["shape"]
    return from_sparse_repr(grp[name], shape=shape)
<commit_msg>sparseh5.py: return matrix in CSR format instead of COO, since it is more efficient to work with<commit_after># to be used with h5py

import numpy as np
from scipy.sparse import coo_matrix

def to_sparse_repr(mat):
    mat = coo_matrix(mat)
    dtype = [('r', int), ('c', int), ('v', mat.dtype)]
    m = np.zeros(shape=(mat.nnz,), dtype=dtype)
    m["r"] = mat.row
    m["c"] = mat.col
    m["v"] = mat.data
    return m

def from_sparse_repr(m, shape=None):
    return coo_matrix((m["v"], (m["r"], m["c"])), shape=shape).tocsr()

def save_sparse_h5(grp, name, data):
    grp[name] = to_sparse_repr(data)
    grp[name].attrs["shape"] = data.shape

def load_sparse_h5(grp, name):
    shape = grp[name].attrs["shape"]
    return from_sparse_repr(grp[name], shape=shape)
<|endoftext|>


<commit_before>"""
    Shared generic views used across the modules
"""

import reversion

from django.contrib import messages
from django.http.response import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic.base import View
from django.utils.translation import ugettext_lazy as _
from django.views.generic import DetailView
from django.views.generic.edit import UpdateView
from django.views.generic.detail import SingleObjectMixin

from django_tables2 import SingleTableView
from utils import dict_diff

class LoginMixin(object):
    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        return super(LoginMixin, self).dispatch(request, *args, **kwargs)

class MessageView(object):
    """
        Simple view for making it easier to work with Message framework.
    """

    def add_message(self, message, level=messages.INFO):
        messages.add_message(self.request, level, message)

class ActionView(View, MessageView):
    """
    View for processing actions etc.
    """
    allowed_actions = ()
    # required permission for doing any kind of action
    permission = None

    def process_action(self, action):
        """
        Override this method
        """
        raise NotImplementedError('You must implement this method')

    def get_success_url(self):
        """
        This method will be used when action is successfully performed
        """
        raise NotImplementedError('Implement this!')

    def get_fail_url(self):
        """
        This method will be used when something goes awry.
        """
        raise NotImplementedError('Why would you not implement this?!')

    def get(self, request, *args, **kwargs):
        return HttpResponseRedirect(self.get_fail_url())

    def check_permissions(self, user):
        return self.permission and user.has_perm(self.permission)

    def post(self, request, *args, **kwargs):
        if not self.check_permissions(request.user):
            self.add_message(_('Insufficient permissions.'), messages.ERROR)
        else:
            action = request.POST.get('action', None)
            if action in self.allowed_actions:
                self.process_action(action)
                return HttpResponseRedirect(self.get_success_url())
            else:
                self.add_message(_('Action {0} not allowed.').format(action),
                                 messages.ERROR)
        return HttpResponseRedirect(self.get_fail_url())

class EditView(UpdateView, MessageView):
    template_name = 'edit_form.html'

    def form_valid(self, form):
        form.save()
        self.add_message(_('Changes successfully saved.'), messages.SUCCESS)
        return HttpResponseRedirect(self.get_object().get_absolute_url())

class ObjectMixinFixed(SingleObjectMixin):
    """
    This is fixes mixin that can be used with login and form mixin
    """
    def dispatch(self, *args, **kwargs):
        self.object = self.get_object()
        return super(ObjectMixinFixed, self).dispatch(*args, **kwargs)

class HistoryView(DetailView):
    """
        Simple generic view for django reversion history
    """
    template_name = 'history.html'

    def get_context_data(self, **kwargs):
        context = super(HistoryView, self).get_context_data(**kwargs)
        versions = reversion.get_unique_for_object(self.get_object())
        diffs = []
        if len(versions) > 1:
            for i in range(len(versions) - 1):
                new = versions[i]
                old = versions[i+1]
                fields_changed = dict_diff(old.field_dict, new.field_dict)
                if fields_changed:
                    diffs.append({
                        'date': new.revision.date_created,
                        'user': new.revision.user,
                        'comment': new.revision.comment,
                        'fields_changed': fields_changed
                    })
        context['diffs'] = diffs
        context['versions'] = versions
        return context

class FilteredListView(SingleTableView):
    """
        Abstract view class for list views with filters
    """
    template_name = 'filtered_list.html'
    context_object_name = 'objects'
    table_pagination = {"per_page": 20}

    table_class = NotImplemented
    filter_class = NotImplemented

    def get_table_data(self):
        queryset = super(FilteredListView, self).get_table_data()
        return self.filter_class(self.request.GET, queryset=queryset)

    def get_context_data(self, **kwargs):
        context = super(FilteredListView, self).get_context_data(**kwargs)
        context['filter'] = self.filter_class(data=self.request.GET)
        context['filter_active'] = bool(self.request.GET)
        return context
<commit_msg>fixing voting bug<commit_after>"""
    Shared generic views used across the modules
"""

import reversion

from django.contrib import messages
from django.http.response import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.views.generic.base import View
from django.utils.translation import ugettext_lazy as _
from django.views.generic import DetailView
from django.views.generic.edit import UpdateView
from django.views.generic.detail import SingleObjectMixin

from django_tables2 import SingleTableView
from utils import dict_diff

class LoginMixin(object):
    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        return super(LoginMixin, self).dispatch(request, *args, **kwargs)

class MessageView(object):
    """
        Simple view for making it easier to work with Message framework.
    """

    def add_message(self, message, level=messages.INFO):
        messages.add_message(self.request, level, message)

class ActionView(View, MessageView):
    """
    View for processing actions etc.
    """
    allowed_actions = ()
    # required permission for doing any kind of action
    permission = None

    def process_action(self, action):
        """
        Override this method
        """
        raise NotImplementedError('You must implement this method')

    def get_success_url(self):
        """
        This method will be used when action is successfully performed
        """
        raise NotImplementedError('Implement this!')

    def get_fail_url(self):
        """
        This method will be used when something goes awry.
        """
        raise NotImplementedError('Why would you not implement this?!')

    def get(self, request, *args, **kwargs):
        return HttpResponseRedirect(self.get_fail_url())

    def check_permissions(self, user):
        return user.has_perm(self.permission) if self.permission else True

    def post(self, request, *args, **kwargs):
        if not self.check_permissions(request.user):
            self.add_message(_('Insufficient permissions.'), messages.ERROR)
        else:
            action = request.POST.get('action', None)
            if action in self.allowed_actions:
                self.process_action(action)
                return HttpResponseRedirect(self.get_success_url())
            else:
                self.add_message(_('Action {0} not allowed.').format(action),
                                 messages.ERROR)
        return HttpResponseRedirect(self.get_fail_url())

class EditView(UpdateView, MessageView):
    template_name = 'edit_form.html'

    def form_valid(self, form):
        form.save()
        self.add_message(_('Changes successfully saved.'), messages.SUCCESS)
        return HttpResponseRedirect(self.get_object().get_absolute_url())

class ObjectMixinFixed(SingleObjectMixin):
    """
    This is fixes mixin that can be used with login and form mixin
    """
    def dispatch(self, *args, **kwargs):
        self.object = self.get_object()
        return super(ObjectMixinFixed, self).dispatch(*args, **kwargs)

class HistoryView(DetailView):
    """
        Simple generic view for django reversion history
    """
    template_name = 'history.html'

    def get_context_data(self, **kwargs):
        context = super(HistoryView, self).get_context_data(**kwargs)
        versions = reversion.get_unique_for_object(self.get_object())
        diffs = []
        if len(versions) > 1:
            for i in range(len(versions) - 1):
                new = versions[i]
                old = versions[i+1]
                fields_changed = dict_diff(old.field_dict, new.field_dict)
                if fields_changed:
                    diffs.append({
                        'date': new.revision.date_created,
                        'user': new.revision.user,
                        'comment': new.revision.comment,
                        'fields_changed': fields_changed
                    })
        context['diffs'] = diffs
        context['versions'] = versions
        return context

class FilteredListView(SingleTableView):
    """
        Abstract view class for list views with filters
    """
    template_name = 'filtered_list.html'
    context_object_name = 'objects'
    table_pagination = {"per_page": 20}

    table_class = NotImplemented
    filter_class = NotImplemented

    def get_table_data(self):
        queryset = super(FilteredListView, self).get_table_data()
        return self.filter_class(self.request.GET, queryset=queryset)

    def get_context_data(self, **kwargs):
        context = super(FilteredListView, self).get_context_data(**kwargs)
        context['filter'] = self.filter_class(data=self.request.GET)
        context['filter_active'] = bool(self.request.GET)
        return context
<|endoftext|>


<commit_before>from __future__ import unicode_literals
import warnings, pandas, numpy, six, collections, string
from StringIO import StringIO
from decimal import Decimal
from mpcontribs.config import mp_level01_titles, mp_id_pattern, csv_comment_char

def flatten_dict(dd, separator='.', prefix=''):
    """http://stackoverflow.com/a/19647596"""
    return { prefix + separator + k if prefix else k : v
            for kk, vv in dd.items()
            for k, v in flatten_dict(vv, separator, kk).items()
           } if isinstance(dd, dict) else { prefix : dd }

def unflatten_dict(d):
    for k in d:
        value, keys = d.pop(k), k.split('.')
        d.rec_update(nest_dict({keys[-1]: value}, keys[:-1]))

def get_short_object_id(cid):
    length = 7
    cid_short = str(cid)[-length:]
    if cid_short == '0'*length:
        cid_short = str(cid)[:length]
    return cid_short

def make_pair(key, value, sep=':'):
    """make a key-value pair"""
    if not isinstance(value, six.string_types):
        value = unicode(value)
    return '{} '.format(sep).join([key, value])

def nest_dict(dct, keys):
    """nest dict under list of keys"""
    from mpcontribs.io.core.recdict import RecursiveDict
    nested_dict = dct
    for key in reversed(keys):
        nested_dict = RecursiveDict({key: nested_dict})
    return nested_dict

def get_composition_from_string(s):
    from pymatgen import Composition, Element
    comp = Composition(s)
    for element in comp.elements:
        Element(element)
    c = comp.get_integer_formula_and_factor()[0]
    comp = Composition(c)
    return ''.join([
        '{}{}'.format(key, int(value) if value > 1 else '')
        for key, value in comp.as_dict().items()
    ])

def normalize_root_level(title):
    """convert root-level title into conventional identifier; non-identifiers
    become part of shared (meta-)data. Returns: (is_general, title)"""
    try:
        composition = get_composition_from_string(title)
        return False, composition
    except:
        if mp_id_pattern.match(title.lower()):
            return False, title.lower()
        else:
            return True, title

def clean_value(value, unit='', convert_to_percent=False, max_dgts=3):
    dgts = max_dgts
    value = str(value) if not isinstance(value, six.string_types) else value
    try:
        value = Decimal(value)
        dgts = len(value.as_tuple().digits)
        dgts = max_dgts if dgts > max_dgts else dgts
    except:
        return value
    if convert_to_percent:
        value = Decimal(value) * Decimal('100')
        unit = '%'
    v = '{{:.{}g}}'.format(dgts).format(value)
    if unit:
        v += ' {}'.format(unit)
    return v

def strip_converter(text):
    """http://stackoverflow.com/questions/13385860"""
    try:
        text = text.strip()
        if not text:
            return numpy.nan
        try:
            val = clean_value(text, max_dgts=6)
            return str(Decimal(val))
        except:
            return text
    except AttributeError:
        return text

def read_csv(body, is_data_section=True):
    """run pandas.read_csv on (sub)section body"""
    body = body.strip()
    if not body: return None
    from mpcontribs.io.core.components import Table
    if is_data_section:
        cur_line = 1
        while 1:
            body_split = body.split('\n', cur_line)
            first_line = body_split[cur_line-1].strip()
            cur_line += 1
            if first_line and not first_line.startswith(csv_comment_char):
                break
        options = {'sep': ',', 'header': 0}
        header = map(string.strip, first_line.split(options['sep']))
        body = '\n'.join([options['sep'].join(header), body_split[1]])
        if first_line.startswith('level_'):
            options.update({'index_col': [0, 1]})
        ncols = len(header)
    else:
        options = { 'sep': ':', 'header': None, 'index_col': 0 }
        ncols = 2
    converters = dict((col, strip_converter) for col in range(ncols))
    return Table(pandas.read_csv(
        StringIO(body), comment=csv_comment_char,
        skipinitialspace=True, squeeze=True,
        converters=converters, encoding='utf8',
        **options
    ).dropna(how='all'))

def disable_ipython_scrollbar():
    from IPython.display import display, Javascript
    display(Javascript("""
        require("notebook/js/outputarea").OutputArea.prototype._should_scroll=function(){return false;};
    """))

def nested_dict_iter(nested, scope=''):
    for key, value in nested.iteritems():
        if isinstance(value, collections.Mapping):
            s = '.'.join([scope, key]) if scope else key
            for inner_key, inner_value in nested_dict_iter(value, scope=s):
                yield '.'.join([s, inner_key]), inner_value
        else:
            yield key, value
<commit_msg>allow scroll to avoid js error<commit_after>from __future__ import unicode_literals
import warnings, pandas, numpy, six, collections, string
from StringIO import StringIO
from decimal import Decimal
from mpcontribs.config import mp_level01_titles, mp_id_pattern, csv_comment_char

def flatten_dict(dd, separator='.', prefix=''):
    """http://stackoverflow.com/a/19647596"""
    return { prefix + separator + k if prefix else k : v
            for kk, vv in dd.items()
            for k, v in flatten_dict(vv, separator, kk).items()
           } if isinstance(dd, dict) else { prefix : dd }

def unflatten_dict(d):
    for k in d:
        value, keys = d.pop(k), k.split('.')
        d.rec_update(nest_dict({keys[-1]: value}, keys[:-1]))

def get_short_object_id(cid):
    length = 7
    cid_short = str(cid)[-length:]
    if cid_short == '0'*length:
        cid_short = str(cid)[:length]
    return cid_short

def make_pair(key, value, sep=':'):
    """make a key-value pair"""
    if not isinstance(value, six.string_types):
        value = unicode(value)
    return '{} '.format(sep).join([key, value])

def nest_dict(dct, keys):
    """nest dict under list of keys"""
    from mpcontribs.io.core.recdict import RecursiveDict
    nested_dict = dct
    for key in reversed(keys):
        nested_dict = RecursiveDict({key: nested_dict})
    return nested_dict

def get_composition_from_string(s):
    from pymatgen import Composition, Element
    comp = Composition(s)
    for element in comp.elements:
        Element(element)
    c = comp.get_integer_formula_and_factor()[0]
    comp = Composition(c)
    return ''.join([
        '{}{}'.format(key, int(value) if value > 1 else '')
        for key, value in comp.as_dict().items()
    ])

def normalize_root_level(title):
    """convert root-level title into conventional identifier; non-identifiers
    become part of shared (meta-)data. Returns: (is_general, title)"""
    try:
        composition = get_composition_from_string(title)
        return False, composition
    except:
        if mp_id_pattern.match(title.lower()):
            return False, title.lower()
        else:
            return True, title

def clean_value(value, unit='', convert_to_percent=False, max_dgts=3):
    dgts = max_dgts
    value = str(value) if not isinstance(value, six.string_types) else value
    try:
        value = Decimal(value)
        dgts = len(value.as_tuple().digits)
        dgts = max_dgts if dgts > max_dgts else dgts
    except:
        return value
    if convert_to_percent:
        value = Decimal(value) * Decimal('100')
        unit = '%'
    v = '{{:.{}g}}'.format(dgts).format(value)
    if unit:
        v += ' {}'.format(unit)
    return v

def strip_converter(text):
    """http://stackoverflow.com/questions/13385860"""
    try:
        text = text.strip()
        if not text:
            return numpy.nan
        try:
            val = clean_value(text, max_dgts=6)
            return str(Decimal(val))
        except:
            return text
    except AttributeError:
        return text

def read_csv(body, is_data_section=True):
    """run pandas.read_csv on (sub)section body"""
    body = body.strip()
    if not body: return None
    from mpcontribs.io.core.components import Table
    if is_data_section:
        cur_line = 1
        while 1:
            body_split = body.split('\n', cur_line)
            first_line = body_split[cur_line-1].strip()
            cur_line += 1
            if first_line and not first_line.startswith(csv_comment_char):
                break
        options = {'sep': ',', 'header': 0}
        header = map(string.strip, first_line.split(options['sep']))
        body = '\n'.join([options['sep'].join(header), body_split[1]])
        if first_line.startswith('level_'):
            options.update({'index_col': [0, 1]})
        ncols = len(header)
    else:
        options = { 'sep': ':', 'header': None, 'index_col': 0 }
        ncols = 2
    converters = dict((col, strip_converter) for col in range(ncols))
    return Table(pandas.read_csv(
        StringIO(body), comment=csv_comment_char,
        skipinitialspace=True, squeeze=True,
        converters=converters, encoding='utf8',
        **options
    ).dropna(how='all'))

def disable_ipython_scrollbar():
    pass
    #from IPython.display import display, Javascript
    #display(Javascript("""
    #    require("notebook/js/outputarea").OutputArea.prototype._should_scroll=function(){return false;};
    #"""))

def nested_dict_iter(nested, scope=''):
    for key, value in nested.iteritems():
        if isinstance(value, collections.Mapping):
            s = '.'.join([scope, key]) if scope else key
            for inner_key, inner_value in nested_dict_iter(value, scope=s):
                yield '.'.join([s, inner_key]), inner_value
        else:
            yield key, value
<|endoftext|>


<commit_before>"""
MARS compiler backend - responsible for taking program events emitted by the
driver and converting them into code.
"""
import logging

from .errors import CompilerError
from . import expressions
from . import types

LOGGER = logging.getLogger('spc.mars')

class SymbolTable:
    """
    A lookup table which binds variables in a nested way, where access goes
    from the current symbol table up to the parent.
    """
    def __init__(self, parent=None, is_global=False, is_builtin=False):
        self.parent = parent
        self.is_builtin = is_builtin
        self.is_global = is_global
        self.bindings = {}

    def find(self, key):
        """
        Finds the symbol table in which the given key is bound, or returns
        None if the symbol is not bound.
        """
        table = self
        while table is not None:
            if key in table.bindings:
                return table
            else:
                table = table.parent

        return None

    def __getitem__(self, key):
        table = self
        while table is not None:
            if key in table.bindings:
                return table.bindings[key]
            else:
                table = table.parent

        raise KeyError('Could not resolve symbol "{}"'.format(parent))

    def __setitem__(self, key, value):
        if key in self:
            raise KeyError('Cannot overwrite existing definition of "{}"'.format(key))

        self.bindings[key] = value

    def __contains__(sef, key):
        table = self
        while table is not None:
            if key in table.bindings:
                return True
            else:
                table = table.parent

        return False

BUILTIN_TYPES = SymbolTable(is_builtin=True)
BUILTIN_TYPES['string'] = types.PointerTo(types.Byte)

BUILTIN_FUNCTIONS = SymbolTable(is_builtin=True)
BUILTIN_FUNCTIONS['@print-int'] = types.FunctionDecl(types.Byte, (types.Integer,))
BUILTIN_FUNCTIONS['@print-string'] = types.FunctionDecl(types.Byte, (types.TypeName('string'),))
BUILTIN_FUNCTIONS['@read-int'] = types.FunctionDecl(types.Integer, ())
BUILTIN_FUNCTIONS['@read-string'] = types.FunctionDecl(types.Byte, (types.TypeName('string'), types.Integer))
BUILTIN_FUNCTIONS['@sbrk'] = types.FunctionDecl(types.AnyPoniter, (types.Integer,))
BUILTIN_FUNCTIONS['@exit'] = types.FunctionDecl(types.Byte, ())
<commit_msg>Add a representation of the stack<commit_after>"""
MARS compiler backend - responsible for taking program events emitted by the
driver and converting them into code.
"""
import logging

from .errors import CompilerError
from . import expressions
from . import types

LOGGER = logging.getLogger('spc.mars')

class SymbolTable:
    """
    A lookup table which binds variables in a nested way, where access goes
    from the current symbol table up to the parent.
    """
    def __init__(self, parent=None, is_global=False, is_builtin=False):
        self.parent = parent
        self.is_builtin = is_builtin
        self.is_global = is_global
        self.bindings = {}

    def find(self, key):
        """
        Finds the symbol table in which the given key is bound, or returns
        None if the symbol is not bound.
        """
        table = self
        while table is not None:
            if key in table.bindings:
                return table
            else:
                table = table.parent

        return None

    def __getitem__(self, key):
        table = self
        while table is not None:
            if key in table.bindings:
                return table.bindings[key]
            else:
                table = table.parent

        raise KeyError('Could not resolve symbol "{}"'.format(parent))

    def __setitem__(self, key, value):
        if key in self:
            raise KeyError('Cannot overwrite existing definition of "{}"'.format(key))

        self.bindings[key] = value

    def __contains__(sef, key):
        table = self
        while table is not None:
            if key in table.bindings:
                return True
            else:
                table = table.parent

        return False

# A context is a bundle of symbol tables for values, functions, and types
Context = namedtuple('Context', ['value_defns', 'type_defns', 'func_stack'])

BUILTIN_TYPES = SymbolTable(is_builtin=True)
BUILTIN_TYPES['string'] = types.PointerTo(types.Byte)

BUILTIN_FUNCTIONS = SymbolTable(is_builtin=True)
BUILTIN_FUNCTIONS['@print-int'] = types.FunctionDecl(types.Byte, (types.Integer,))
BUILTIN_FUNCTIONS['@print-string'] = types.FunctionDecl(types.Byte, (types.TypeName('string'),))
BUILTIN_FUNCTIONS['@read-int'] = types.FunctionDecl(types.Integer, ())
BUILTIN_FUNCTIONS['@read-string'] = types.FunctionDecl(types.Byte, (types.TypeName('string'), types.Integer))
BUILTIN_FUNCTIONS['@sbrk'] = types.FunctionDecl(types.AnyPoniter, (types.Integer,))
BUILTIN_FUNCTIONS['@exit'] = types.FunctionDecl(types.Byte, ())

class FunctionStack:
    """
    Tracks where variables are on the function's stack.
    """
    # The stack discipline in use here works like this:
    #
    #     +-------
    #     | arg 2
    #     +------- offset 4
    #     | arg 1
    #     +------- offset 0
    #     | $fp
    #     +------- offset -4
    #     | $ra
    #     +------- offset -8
    #     | local 1
    #     +-------
    #     | local 2
    #     +-------
    #
    # Note that this doesn't take into account the calling convention, because
    # this compiler pretty much ignores it. All arguments are passed on the stack,
    # in reverse order. Functions keep all their local vars on the stack, to keep
    # them safe during recursion, and parameters are no exception - taking them
    # in via $a0 - $a3 would require an extra copy from the arg. register to memory

    def __init__(self):
        self.local_offset = -8
        self.param_offset = 0

    def add_param(self, name, size, alignment):
        """
        Adds a new parameter to the stack.
        """
        self.param_offset = types.align_address(self.param_offset, alignment)

        self.vars[name] = self.param_offset
        self.param_offset += size

    def add_local(self, name, size, alignment):
        """
        Adds a local variable to the stack.
        """
        self.local_offset = (
            types.align_address(self.local_offset - size, alignment,
                types.Alignment.Down))

        self.vars[name] = local_offset

    def get_temp_context(self, backend):
        """
        Returns a context which can be used for putting temporary values on
        the stack. When the context exits, the space used by the temporary
        variables is cleaned up.
        """
        class TemporaryContext:
            def __init__(self, start_offset):
                self.tmp_offset = start_offset
                self.total_tmp_size = 0

            def __enter__(self):
                pass

            def __exit__(self, *exc_info):
                backend._write_instr('    addi $sp, $sp, {}', self.total_tmp_size)

            def add_temp(self, size, alignment):
                """
                Makes space for a new temporary, returning the $fp offset at
                which to write it.
                """
                old_tmp_offset = self.tmp_offset
                self.tmp_offset = (
                    types.align_address(self.tmp_offset - size, alignment,
                        types.Alignment.Down))

                size_used = old_tmp_offset - self.tmp_offset
                self.total_tmp_size += size_used
                backend._write_instr('    addi $sp, $sp, -{}', size_used)

                return self.tmp_offset

        return TemporaryContext(self.local_offset)

    def locals_size(self):
        """
        Gets the size used by all the locals.
        """
        return abs(self.local_offset) - 8

    def __getitem__(self, name):
        """
        Gets the offset to the variable on the stack, or a Register (if the
        name was bound to one of the first four parameters)
        """
        return self.vars[name]
<|endoftext|>


<commit_before>"""Contains the Tilt mode code"""

from mpf.core.mode import Mode

class Tilt(Mode):

    def __init__(self, machine, config, name, path):
        self._balls_to_collect = None
        self._last_warning = None
        self.ball_ending_tilted_queue = None
        self.tilt_event_handlers = None
        self.last_tilt_warning_switch = None
        self.tilt_config = None
        super().__init__(machine, config, name, path)

    def mode_init(self):
        self._balls_to_collect = 0
        self._last_warning = None
        self.ball_ending_tilted_queue = None
        self.tilt_event_handlers = set()
        self.last_tilt_warning_switch = 0

        self.tilt_config = self.machine.config_validator.validate_config(
            config_spec='tilt',
            source=self._get_merged_settings('tilt'),
            section_name='tilt')

    def mode_start(self, **kwargs):
        self._register_switch_handlers()

        for event in self.tilt_config['reset_warnings_events']:
            self.add_mode_event_handler(event, self.reset_warnings)

        for event in self.tilt_config['tilt_events']:
            self.add_mode_event_handler(event, self.tilt)

        for event in self.tilt_config['tilt_warning_events']:
            self.add_mode_event_handler(event, self.tilt_warning)

        for event in self.tilt_config['tilt_slam_tilt_events']:
            self.add_mode_event_handler(event, self.slam_tilt)

    def mode_stop(self, **kwargs):
        self._remove_switch_handlers()

    def _register_switch_handlers(self):
        for switch in self.machine.switches.items_tagged(
                self.tilt_config['tilt_warning_switch_tag']):
            self.machine.switch_controller.add_switch_handler(
                switch_name=switch.name,
                callback=self._tilt_warning_switch_handler)

        for switch in self.machine.switches.items_tagged(
                self.tilt_config['tilt_switch_tag']):
            self.machine.switch_controller.add_switch_handler(
                switch_name=switch.name,
                callback=self.tilt)

        for switch in self.machine.switches.items_tagged(
                self.tilt_config['slam_tilt_switch_tag']):
            self.machine.switch_controller.add_switch_handler(
                switch_name=switch.name,
                callback=self.slam_tilt)

    def _remove_switch_handlers(self):
        for switch in self.machine.switches.items_tagged(
                self.tilt_config['tilt_warning_switch_tag']):
            self.machine.switch_controller.remove_switch_handler(
                switch_name=switch.name,
                callback=self._tilt_warning_switch_handler)
        for switch in self.machine.switches.items_tagged(
                self.tilt_config['tilt_switch_tag']):
            self.machine.switch_controller.remove_switch_handler(
                switch_name=switch.name,
                callback=self.tilt)
        for switch in self.machine.switches.items_tagged(
                self.tilt_config['slam_tilt_switch_tag']):
            self.machine.switch_controller.remove_switch_handler(
                switch_name=switch.name,
                callback=self.slam_tilt)

    # ignore false positives about self.player
    # pylint: disable-msg=unsubscriptable-object
    def tilt_warning(self):
        """Processes a tilt warning. If the number of warnings is the number to
        cause a tilt, a tilt will be processed.

        """
        self.last_tilt_warning_switch = self.machine.clock.get_time()

        if not self.player:
            return

        self.log.debug("Tilt Warning")

        self._last_warning = self.machine.clock.get_time()
        self.player[self.tilt_config['tilt_warnings_player_var']] += 1

        warnings = self.player[self.tilt_config['tilt_warnings_player_var']]

        if warnings >= self.tilt_config['warnings_to_tilt']:
            self.tilt()
        else:
            self.machine.events.post(
                'tilt_warning',
                warnings=warnings,
                warnings_remaining=(self.tilt_config['warnings_to_tilt'] -
                                    warnings))
            '''event: tilt_warning
            desc: A tilt warning just happened.
            args:
            warnings: The total number of warnings so far.
            warnings_remaining: The remaining number of warnings until a tilt.
            '''
            self.machine.events.post('tilt_warning_{}'.format(warnings))
            '''event: tilt_warning_(number)
            desc: A tilt warning just happened. The number of this tilt
            warning is in the event name in the (number).'''

    def reset_warnings(self, **kwargs):
        """Resets the tilt warnings for the current player."""
        del kwargs
        try:
            self.player[self.tilt_config['tilt_warnings_player_var']] = 0
        except AttributeError:
            pass

    def tilt(self, **kwargs):
        """Causes the ball to tilt."""
        del kwargs
        if not self.machine.game:
            return

        self._balls_to_collect = 0
        for device in self.machine.ball_devices:
            if device.is_playfield():
                self._balls_to_collect += device.available_balls

        self.log.debug("Processing Tilt. Balls to collect: %s",
                       self._balls_to_collect)

        self.machine.game.tilted = True
        self.machine.events.post('tilt')
        '''event: tilt
        desc: The player has tilted.'''
        self._disable_autofires()
        self._disable_flippers()

        self.tilt_event_handlers.add(
            self.machine.events.add_handler('ball_ending',
                                            self._ball_ending_tilted))

        for device in self.machine.ball_devices:
            if 'drain' in device.tags:
                self.tilt_event_handlers.add(
                    self.machine.events.add_handler(
                        'balldevice_{}_ball_enter'.format(device.name),
                        self._tilted_ball_drain))

        self.machine.game.ball_ending()

    def _disable_flippers(self):
        for flipper in self.machine.flippers:
            flipper.disable()

    def _disable_autofires(self):
        for autofire in self.machine.autofires:
            autofire.disable()

    def _tilted_ball_drain(self, new_balls, unclaimed_balls, device, **kwargs):
        del new_balls
        del device
        del kwargs

        self._balls_to_collect -= unclaimed_balls

        self.log.debug("Tilted ball drain. Balls to collect: %s",
                       self._balls_to_collect)

        if self._balls_to_collect <= 0:
            self._tilt_done()

        return {'unclaimed_balls': 0}

    def _tilt_switch_handler(self):
        self.tilt()

    def _tilt_warning_switch_handler(self):
        if (not self._last_warning or
                (self._last_warning + (self.tilt_config['multiple_hit_window'] * 0.001) <=
                 self.machine.clock.get_time())):

            self.tilt_warning()

    def _ball_ending_tilted(self, queue):
        self.ball_ending_tilted_queue = queue
        queue.wait()

        if not self._balls_to_collect:
            self._tilt_done()

    def _tilt_done(self):
        if self.tilt_settle_ms_remaining():
            self.delay.reset(ms=self.tilt_settle_ms_remaining(),
                             callback=self._tilt_done,
                             name='tilt')

        else:
            self.machine.game.tilted = False

            self.machine.events.post('tilt_clear')
            '''event: tilt_clear
            desc: Posted after a tilt, when the settling time has passed after
            the last tilt switch hit. This is used to hold the next ball
            start until the plumb bob has settled to prevent tilt throughs.
            '''

            self.ball_ending_tilted_queue.clear()

            self.machine.events.remove_handlers_by_keys(
                self.tilt_event_handlers)
            self.tilt_event_handlers = set()

    def tilt_settle_ms_remaining(self):
        """Returns the amount of milliseconds remaining until the tilt settle
        time has cleared.

        """
        if not self.last_tilt_warning_switch:
            return 0

        delta = (self.tilt_config['settle_time'] -
                 (self.machine.clock.get_time() -
                  self.last_tilt_warning_switch) * 1000)
        if delta > 0:
            return delta
        else:
            return 0

    def slam_tilt(self):
        self.machine.events.post('slam_tilt')
        '''event: slam_tilt
        desc: A slam tilt has just occurred.'''
        if not self.machine.game:
            return

        self.machine.game.slam_tilted = True
        self.tilt()
<commit_msg>set tilted on tilt<commit_after>"""Contains the Tilt mode code."""
from mpf.core.machine import MachineController
from mpf.core.mode import Mode

class Tilt(Mode):

    """A mode which handles a tilt in a pinball machine."""

    def __init__(self, machine: MachineController, config: dict, name: str, path):
        """Create mode."""
        self._balls_to_collect = None
        self._last_warning = None
        self.ball_ending_tilted_queue = None
        self.tilt_event_handlers = None
        self.last_tilt_warning_switch = None
        self.tilt_config = None
        super().__init__(machine, config, name, path)

    def mode_init(self):
        """Initialise mode."""
        self._balls_to_collect = 0
        self._last_warning = None
        self.ball_ending_tilted_queue = None
        self.tilt_event_handlers = set()
        self.last_tilt_warning_switch = 0

        self.tilt_config = self.machine.config_validator.validate_config(
            config_spec='tilt',
            source=self._get_merged_settings('tilt'),
            section_name='tilt')

    def mode_start(self, **kwargs):
        """Start mode."""
        self._register_switch_handlers()

        for event in self.tilt_config['reset_warnings_events']:
            self.add_mode_event_handler(event, self.reset_warnings)

        for event in self.tilt_config['tilt_events']:
            self.add_mode_event_handler(event, self.tilt)

        for event in self.tilt_config['tilt_warning_events']:
            self.add_mode_event_handler(event, self.tilt_warning)

        for event in self.tilt_config['tilt_slam_tilt_events']:
            self.add_mode_event_handler(event, self.slam_tilt)

    def mode_stop(self, **kwargs):
        """Stop mode."""
        self._remove_switch_handlers()

    def _register_switch_handlers(self):
        for switch in self.machine.switches.items_tagged(
                self.tilt_config['tilt_warning_switch_tag']):
            self.machine.switch_controller.add_switch_handler(
                switch_name=switch.name,
                callback=self._tilt_warning_switch_handler)

        for switch in self.machine.switches.items_tagged(
                self.tilt_config['tilt_switch_tag']):
            self.machine.switch_controller.add_switch_handler(
                switch_name=switch.name,
                callback=self.tilt)

        for switch in self.machine.switches.items_tagged(
                self.tilt_config['slam_tilt_switch_tag']):
            self.machine.switch_controller.add_switch_handler(
                switch_name=switch.name,
                callback=self.slam_tilt)

    def _remove_switch_handlers(self):
        for switch in self.machine.switches.items_tagged(
                self.tilt_config['tilt_warning_switch_tag']):
            self.machine.switch_controller.remove_switch_handler(
                switch_name=switch.name,
                callback=self._tilt_warning_switch_handler)
        for switch in self.machine.switches.items_tagged(
                self.tilt_config['tilt_switch_tag']):
            self.machine.switch_controller.remove_switch_handler(
                switch_name=switch.name,
                callback=self.tilt)
        for switch in self.machine.switches.items_tagged(
                self.tilt_config['slam_tilt_switch_tag']):
            self.machine.switch_controller.remove_switch_handler(
                switch_name=switch.name,
                callback=self.slam_tilt)

    # ignore false positives about self.player
    # pylint: disable-msg=unsubscriptable-object
    def tilt_warning(self):
        """Process a tilt warning

         If the number of warnings is the number to
        cause a tilt, a tilt will be processed.
        """
        self.last_tilt_warning_switch = self.machine.clock.get_time()

        if not self.player:
            return

        self.log.debug("Tilt Warning")

        self._last_warning = self.machine.clock.get_time()
        self.player[self.tilt_config['tilt_warnings_player_var']] += 1

        warnings = self.player[self.tilt_config['tilt_warnings_player_var']]

        if warnings >= self.tilt_config['warnings_to_tilt']:
            self.tilt()
        else:
            self.machine.events.post(
                'tilt_warning',
                warnings=warnings,
                warnings_remaining=(self.tilt_config['warnings_to_tilt'] -
                                    warnings))
            '''event: tilt_warning
            desc: A tilt warning just happened.
            args:
            warnings: The total number of warnings so far.
            warnings_remaining: The remaining number of warnings until a tilt.
            '''
            self.machine.events.post('tilt_warning_{}'.format(warnings))
            '''event: tilt_warning_(number)
            desc: A tilt warning just happened. The number of this tilt
            warning is in the event name in the (number).'''

    def reset_warnings(self, **kwargs):
        """Reset the tilt warnings for the current player."""
        del kwargs
        try:
            self.player[self.tilt_config['tilt_warnings_player_var']] = 0
        except AttributeError:
            pass

    def tilt(self, **kwargs):
        """Cause the ball to tilt."""
        del kwargs
        if not self.machine.game:
            return

        self.machine.game.tilted = True

        self._balls_to_collect = 0
        for device in self.machine.ball_devices:
            if device.is_playfield():
                self._balls_to_collect += device.available_balls

        self.log.debug("Processing Tilt. Balls to collect: %s",
                       self._balls_to_collect)

        self.machine.game.tilted = True
        self.machine.events.post('tilt')
        '''event: tilt
        desc: The player has tilted.'''
        self._disable_autofires()
        self._disable_flippers()

        self.tilt_event_handlers.add(
            self.machine.events.add_handler('ball_ending',
                                            self._ball_ending_tilted))

        for device in self.machine.ball_devices:
            if 'drain' in device.tags:
                self.tilt_event_handlers.add(
                    self.machine.events.add_handler(
                        'balldevice_{}_ball_enter'.format(device.name),
                        self._tilted_ball_drain))

        self.machine.game.ball_ending()

    def _disable_flippers(self):
        for flipper in self.machine.flippers:
            flipper.disable()

    def _disable_autofires(self):
        for autofire in self.machine.autofires:
            autofire.disable()

    def _tilted_ball_drain(self, new_balls, unclaimed_balls, device, **kwargs):
        del new_balls
        del device
        del kwargs

        self._balls_to_collect -= unclaimed_balls

        self.log.debug("Tilted ball drain. Balls to collect: %s",
                       self._balls_to_collect)

        if self._balls_to_collect <= 0:
            self._tilt_done()

        return {'unclaimed_balls': 0}

    def _tilt_switch_handler(self):
        self.tilt()

    def _tilt_warning_switch_handler(self):
        if (not self._last_warning or
                (self._last_warning + (self.tilt_config['multiple_hit_window'] * 0.001) <=
                 self.machine.clock.get_time())):

            self.tilt_warning()

    def _ball_ending_tilted(self, queue):
        self.ball_ending_tilted_queue = queue
        queue.wait()

        if not self._balls_to_collect:
            self._tilt_done()

    def _tilt_done(self):
        if self.tilt_settle_ms_remaining():
            self.delay.reset(ms=self.tilt_settle_ms_remaining(),
                             callback=self._tilt_done,
                             name='tilt')

        else:
            self.machine.game.tilted = False

            self.machine.events.post('tilt_clear')
            '''event: tilt_clear
            desc: Posted after a tilt, when the settling time has passed after
            the last tilt switch hit. This is used to hold the next ball
            start until the plumb bob has settled to prevent tilt throughs.
            '''

            self.ball_ending_tilted_queue.clear()

            self.machine.events.remove_handlers_by_keys(
                self.tilt_event_handlers)
            self.tilt_event_handlers = set()

    def tilt_settle_ms_remaining(self):
        """Return the amount of milliseconds remaining until the tilt settle time has cleared."""
        if not self.last_tilt_warning_switch:
            return 0

        delta = (self.tilt_config['settle_time'] -
                 (self.machine.clock.get_time() -
                  self.last_tilt_warning_switch) * 1000)
        if delta > 0:
            return delta
        else:
            return 0

    def slam_tilt(self):
        """Process a slam tilt."""
        self.machine.events.post('slam_tilt')
        '''event: slam_tilt
        desc: A slam tilt has just occurred.'''
        if not self.machine.game:
            return

        self.machine.game.slam_tilted = True
        self.machine.game.tilted = True
        self.tilt()
<|endoftext|>