<commit_before>from setuptools import setup, Extension
import distutils.command.build as _build
import distutils.command.build_ext as _build_ext
import os
import sys
import subprocess
import multiprocessing
import shutil

from contextlib import contextmanager
from os import path

@contextmanager
def symlink_keyvi():
    if not path.exists('keyvi'):
        os.symlink('../keyvi', 'keyvi')
        yield
        os.unlink('keyvi')
    else:
        yield

with symlink_keyvi():
    # workaround for autwrap bug (includes incompatible boost)
    autowrap_data_dir = "autowrap_includes"

    dictionary_sources = path.abspath('keyvi')
    tpie_build_dir = path.join(dictionary_sources, '3rdparty/tpie/build')
    tpie_install_prefix = 'install'
    tpie_include_dir = path.join(tpie_build_dir, tpie_install_prefix, 'include')
    tpie_lib_dir = path.join(tpie_build_dir, tpie_install_prefix, 'lib')

    additional_compile_flags = []

    linklibraries_static_or_dynamic = [
        "boost_program_options",
        "boost_iostreams",
        "boost_filesystem",
        "boost_system",
        "boost_regex",
        "boost_thread",
        "snappy"
    ]

    linklibraries = [
        "tpie",
        "z"
    ]

    mac_os_static_libs_dir = 'mac_os_static_libs'

    extra_link_arguments = []
    link_library_dirs = [tpie_lib_dir]

    if sys.platform == 'darwin':
        additional_compile_flags.append("-DOS_MACOSX")
        additional_compile_flags.append('-mmacosx-version-min=10.9')
        linklibraries_static_or_dynamic.remove('boost_thread')
        linklibraries_static_or_dynamic.append('boost_thread-mt')
        link_library_dirs.append(mac_os_static_libs_dir)
        extra_link_arguments.append('-L{}'.format(mac_os_static_libs_dir))

    #########################
    # Custom 'build' command
    #########################

    custom_user_options = [('mode=',
                            None,
                            "build mode."),
                           ('staticlinkboost',
                            None,
                            "special mode to statically link boost."),
                           ]

    class custom_opts:

        parent = None

        def initialize_options(self):
            self.parent.initialize_options(self)
            self.mode = 'release'
            self.staticlinkboost = False

        def run(self):
            global additional_compile_flags
            global linklibraries
            global linklibraries_static_or_dynamic
            global extra_link_arguments
            global ext_modules
            print "Building in {} mode".format(self.mode)

            if self.mode == 'debug':
                additional_compile_flags.append("-O0")
                additional_compile_flags.append("-ggdb3")
                additional_compile_flags.append("-fstack-protector")
            else:
                additional_compile_flags.append("-O3")

            if self.mode == 'coverage':
                additional_compile_flags.append("--coverage")
                linklibraries.append("gcov")

            # check linking
            if self.staticlinkboost:
                # set static
                extra_link_arguments = ['-Wl,-Bstatic']
                for lib in linklibraries_static_or_dynamic:
                    extra_link_arguments.append("-l{}".format(lib))
                # reset to dynamic
                extra_link_arguments.append('-Wl,-Bdynamic')
                extra_link_arguments.append('-static-libstdc++')
                extra_link_arguments.append('-static-libgcc')
                # workaround: link librt explicitly
                linklibraries.append("rt")
            else:
                # no static linking, add the libs to dynamic linker
                linklibraries += linklibraries_static_or_dynamic

            # patch the compile flags
            for ext_m in ext_modules:
                flags = getattr(ext_m, 'extra_compile_args') + additional_compile_flags
                setattr(ext_m, 'extra_compile_args', flags)
                setattr(ext_m, 'libraries', linklibraries)
                args = getattr(ext_m, 'extra_link_args') + extra_link_arguments
                setattr(ext_m, 'extra_link_args', args)

            self.parent.run(self)

    class build(custom_opts, _build.build):
        parent = _build.build
        user_options = _build.build.user_options + custom_user_options

    class build_ext(_build_ext.build_ext):
        def run(self):
            if sys.platform == 'darwin':
                if not os.path.exists(mac_os_static_libs_dir):
                    os.makedirs(mac_os_static_libs_dir)

                for lib in linklibraries_static_or_dynamic:
                    lib_file_name = 'lib{}.a'.format(lib)
                    src_file = path.join('/usr/local/lib', lib_file_name)
                    dst_file = path.join(mac_os_static_libs_dir, lib_file_name)
                    shutil.copyfile(src_file, dst_file)

            if not path.exists(path.join(tpie_lib_dir, 'libtpie.a')):
                try:
                    cpu_count = multiprocessing.cpu_count()
                except:
                    cpu_count = 1

                CMAKE_CXX_FLAGS='-fPIC -std=c++11'
                if sys.platform == 'darwin':
                    CMAKE_CXX_FLAGS += ' -mmacosx-version-min=10.9'

                tpie_build_cmd = 'mkdir -p {}'.format(tpie_build_dir)
                tpie_build_cmd += ' && cd {}'.format(tpie_build_dir)
                tpie_build_cmd += ' && cmake -D CMAKE_BUILD_TYPE:STRING=Release ' \
                                  ' -D TPIE_PARALLEL_SORT=1 -D COMPILE_TEST=OFF -D CMAKE_CXX_FLAGS="{CXX_FLAGS}"' \
                                  ' -D CMAKE_INSTALL_PREFIX={INSTALL_PREFIX} ..'.format(
                                        CXX_FLAGS=CMAKE_CXX_FLAGS, INSTALL_PREFIX=tpie_install_prefix)
                tpie_build_cmd += ' && make -j {}'.format(cpu_count)
                tpie_build_cmd += ' && make install'

                subprocess.call(tpie_build_cmd, shell=True)

            os.environ['ARCHFLAGS'] = '-arch x86_64'
            _build_ext.build_ext.run(self)

    ext_modules = [Extension('pykeyvi',
                             include_dirs=[autowrap_data_dir,
                                           tpie_include_dir,
                                           path.join(dictionary_sources, 'src/cpp'),
                                           path.join(dictionary_sources, '3rdparty/rapidjson/include'),
                                           path.join(dictionary_sources, '3rdparty/msgpack-c/include'),
                                           path.join(dictionary_sources, '3rdparty/utf8'),
                                           path.join(dictionary_sources, '3rdparty/misc'),
                                           path.join(dictionary_sources, '3rdparty/xchange/src')],
                             language='c++',
                             sources=['src/pykeyvi.cpp'],
                             extra_compile_args=['-std=c++11', '-msse4.2'] + additional_compile_flags,
                             extra_link_args=extra_link_arguments,
                             library_dirs=link_library_dirs,
                             libraries=linklibraries)]

    PACKAGE_NAME = 'pykeyvi'

    install_requires = [
        'msgpack-python',
    ]

    setup(
        name=PACKAGE_NAME,
        version='0.1.30',
        description='Python bindings for keyvi',
        author='Hendrik Muhs',
        author_email='hendrik.muhs@gmail.com',
        license="ASL 2.0",
        cmdclass={'build_ext': build_ext, 'build': build },
        scripts=['bin/keyvi'],
        packages=['keyvicli'],
        ext_modules=ext_modules,
        zip_safe=False,
        url='https://github.com/cliqz/keyvi',
        download_url='https://github.com/cliqz/keyvi/tarball/v0.1.30',
        keywords=['FST'],
        classifiers=[],
        install_requires=install_requires,
    )
<commit_msg>bump version to 0.1.31<commit_after>from setuptools import setup, Extension
import distutils.command.build as _build
import distutils.command.build_ext as _build_ext
import os
import sys
import subprocess
import multiprocessing
import shutil

from contextlib import contextmanager
from os import path

@contextmanager
def symlink_keyvi():
    if not path.exists('keyvi'):
        os.symlink('../keyvi', 'keyvi')
        yield
        os.unlink('keyvi')
    else:
        yield

with symlink_keyvi():
    # workaround for autwrap bug (includes incompatible boost)
    autowrap_data_dir = "autowrap_includes"

    dictionary_sources = path.abspath('keyvi')
    tpie_build_dir = path.join(dictionary_sources, '3rdparty/tpie/build')
    tpie_install_prefix = 'install'
    tpie_include_dir = path.join(tpie_build_dir, tpie_install_prefix, 'include')
    tpie_lib_dir = path.join(tpie_build_dir, tpie_install_prefix, 'lib')

    additional_compile_flags = []

    linklibraries_static_or_dynamic = [
        "boost_program_options",
        "boost_iostreams",
        "boost_filesystem",
        "boost_system",
        "boost_regex",
        "boost_thread",
        "snappy"
    ]

    linklibraries = [
        "tpie",
        "z"
    ]

    mac_os_static_libs_dir = 'mac_os_static_libs'

    extra_link_arguments = []
    link_library_dirs = [tpie_lib_dir]

    if sys.platform == 'darwin':
        additional_compile_flags.append("-DOS_MACOSX")
        additional_compile_flags.append('-mmacosx-version-min=10.9')
        linklibraries_static_or_dynamic.remove('boost_thread')
        linklibraries_static_or_dynamic.append('boost_thread-mt')
        link_library_dirs.append(mac_os_static_libs_dir)
        extra_link_arguments.append('-L{}'.format(mac_os_static_libs_dir))

    #########################
    # Custom 'build' command
    #########################

    custom_user_options = [('mode=',
                            None,
                            "build mode."),
                           ('staticlinkboost',
                            None,
                            "special mode to statically link boost."),
                           ]

    class custom_opts:

        parent = None

        def initialize_options(self):
            self.parent.initialize_options(self)
            self.mode = 'release'
            self.staticlinkboost = False

        def run(self):
            global additional_compile_flags
            global linklibraries
            global linklibraries_static_or_dynamic
            global extra_link_arguments
            global ext_modules
            print "Building in {} mode".format(self.mode)

            if self.mode == 'debug':
                additional_compile_flags.append("-O0")
                additional_compile_flags.append("-ggdb3")
                additional_compile_flags.append("-fstack-protector")
            else:
                additional_compile_flags.append("-O3")

            if self.mode == 'coverage':
                additional_compile_flags.append("--coverage")
                linklibraries.append("gcov")

            # check linking
            if self.staticlinkboost:
                # set static
                extra_link_arguments = ['-Wl,-Bstatic']
                for lib in linklibraries_static_or_dynamic:
                    extra_link_arguments.append("-l{}".format(lib))
                # reset to dynamic
                extra_link_arguments.append('-Wl,-Bdynamic')
                extra_link_arguments.append('-static-libstdc++')
                extra_link_arguments.append('-static-libgcc')
                # workaround: link librt explicitly
                linklibraries.append("rt")
            else:
                # no static linking, add the libs to dynamic linker
                linklibraries += linklibraries_static_or_dynamic

            # patch the compile flags
            for ext_m in ext_modules:
                flags = getattr(ext_m, 'extra_compile_args') + additional_compile_flags
                setattr(ext_m, 'extra_compile_args', flags)
                setattr(ext_m, 'libraries', linklibraries)
                args = getattr(ext_m, 'extra_link_args') + extra_link_arguments
                setattr(ext_m, 'extra_link_args', args)

            self.parent.run(self)

    class build(custom_opts, _build.build):
        parent = _build.build
        user_options = _build.build.user_options + custom_user_options

    class build_ext(_build_ext.build_ext):
        def run(self):
            if sys.platform == 'darwin':
                if not os.path.exists(mac_os_static_libs_dir):
                    os.makedirs(mac_os_static_libs_dir)

                for lib in linklibraries_static_or_dynamic:
                    lib_file_name = 'lib{}.a'.format(lib)
                    src_file = path.join('/usr/local/lib', lib_file_name)
                    dst_file = path.join(mac_os_static_libs_dir, lib_file_name)
                    shutil.copyfile(src_file, dst_file)

            if not path.exists(path.join(tpie_lib_dir, 'libtpie.a')):
                try:
                    cpu_count = multiprocessing.cpu_count()
                except:
                    cpu_count = 1

                CMAKE_CXX_FLAGS='-fPIC -std=c++11'
                if sys.platform == 'darwin':
                    CMAKE_CXX_FLAGS += ' -mmacosx-version-min=10.9'

                tpie_build_cmd = 'mkdir -p {}'.format(tpie_build_dir)
                tpie_build_cmd += ' && cd {}'.format(tpie_build_dir)
                tpie_build_cmd += ' && cmake -D CMAKE_BUILD_TYPE:STRING=Release ' \
                                  ' -D TPIE_PARALLEL_SORT=1 -D COMPILE_TEST=OFF -D CMAKE_CXX_FLAGS="{CXX_FLAGS}"' \
                                  ' -D CMAKE_INSTALL_PREFIX={INSTALL_PREFIX} ..'.format(
                                        CXX_FLAGS=CMAKE_CXX_FLAGS, INSTALL_PREFIX=tpie_install_prefix)
                tpie_build_cmd += ' && make -j {}'.format(cpu_count)
                tpie_build_cmd += ' && make install'

                subprocess.call(tpie_build_cmd, shell=True)

            os.environ['ARCHFLAGS'] = '-arch x86_64'
            _build_ext.build_ext.run(self)

    ext_modules = [Extension('pykeyvi',
                             include_dirs=[autowrap_data_dir,
                                           tpie_include_dir,
                                           path.join(dictionary_sources, 'src/cpp'),
                                           path.join(dictionary_sources, '3rdparty/rapidjson/include'),
                                           path.join(dictionary_sources, '3rdparty/msgpack-c/include'),
                                           path.join(dictionary_sources, '3rdparty/utf8'),
                                           path.join(dictionary_sources, '3rdparty/misc'),
                                           path.join(dictionary_sources, '3rdparty/xchange/src')],
                             language='c++',
                             sources=['src/pykeyvi.cpp'],
                             extra_compile_args=['-std=c++11', '-msse4.2'] + additional_compile_flags,
                             extra_link_args=extra_link_arguments,
                             library_dirs=link_library_dirs,
                             libraries=linklibraries)]

    PACKAGE_NAME = 'pykeyvi'

    install_requires = [
        'msgpack-python',
    ]

    setup(
        name=PACKAGE_NAME,
        version='0.1.31',
        description='Python bindings for keyvi',
        author='Hendrik Muhs',
        author_email='hendrik.muhs@gmail.com',
        license="ASL 2.0",
        cmdclass={'build_ext': build_ext, 'build': build },
        scripts=['bin/keyvi'],
        packages=['keyvicli'],
        ext_modules=ext_modules,
        zip_safe=False,
        url='https://github.com/cliqz/keyvi',
        download_url='https://github.com/cliqz/keyvi/tarball/v0.1.31',
        keywords=['FST'],
        classifiers=[],
        install_requires=install_requires,
    )
<|endoftext|>


<commit_before>import numpy as np
from netCDF4 import Dataset as dset, MFDataset as mfdset
from functools import partial

class GridNdarray(np.ndarray):
    """A class to hold a grid-located variable."""
    def __new__(cls,input_array,loc):
        obj = input_array.view(cls)
        obj.loc = loc
        return obj

    def __array_finalize__(self, obj):
        if obj is None: return
        self.loc = getattr(obj, 'loc', None)

    def __array_wrap__(self, out_arr, context=None):
        return np.ndarray.__array_wrap__(self, out_arr, context)

class GridVariable():

    """A class to hold a variable."""
    def __init__(self,var,domain,loc,*fhl,**kwargs):
        for fh in fhl:
            try:
                self._v = fh.variables[var]
            except KeyError:
                print('Trying next file.')
            else:
                self.var = var
                self.dom = domain
                self.loc = loc
                self.plot_loc = kwargs.get('plot_loc',self.loc)[0]
                self._plot_slice = self.dom.slices[self.plot_loc].copy()
                self.implement_syntactic_sugar_for_plot_slice()
                self.Time = fh.variables['Time'][:]
                self.dom.dt = np.diff(self.Time[:2])*3600
                average_DT = fh.variables['average_DT'][:]
                average_DT = average_DT[:,np.newaxis,np.newaxis,np.newaxis]
                self.average_DT = average_DT
                break

    def __add__(self,other):
        if self.values.loc == other.values.loc:
            new_variable = GridVariable(self.var,self.dom,self.values.loc)
            new_variable.values = self.values + other.values
            return new_variable
        else:
            raise ValueError('The two variables are not co-located.')

    def __sub__(self,other):
        if self.values.loc == other.values.loc:
            new_variable = GridVariable(self.var,self.dom,self.values.loc)
            new_variable.values = self.values - other.values
            return new_variable
        else:
            raise ValueError('The two variables are not co-located.')

    def __neg__(self):
        self.values *= -1
        return self

    @property
    def plot_slice(self):
        return self._plot_slice

    @plot_slice.setter
    def plot_slice(self,operation_string):
        axis,limit,operation = list(operation_string)

        axes = ['t','l','y','x']
        limits = ['s','e']
        operations = { 'm': -1,
                       'p': +1 }
        self._plot_slice[axes.index(axis)][limits.index(limit)] += operations[operation]

    def plot_slice_modifier(self,string):
        self.plot_slice = string
        return self

    def implement_syntactic_sugar_for_plot_slice(self):
        axes = ['t','l','y','x']
        limits = ['s','e']
        operations = ['m','p']
        for axis in axes:
            for limit in limits:
                for op in operations:
                    string = axis+limit+op
                    setattr(self,string,partial(self.plot_slice_modifier,string))

    @staticmethod
    def extend_halos(array,axis,boundary_index,**kwargs):
        method = kwargs.get('method')
        if method == 'vorticity':
            slip = kwargs.get('slip',False)
            slip_multiplyer = 1 if slip else -1
            array_extendor = slip_multiplyer*array.take([boundary_index],axis=axis)
            if boundary_index == 0:
                array1 = array_extendor
                array2 = array
            else:
                array1 = array
                array2 = array_extendor
            array = np.append(array1,array2,axis=axis)
        if method == 'mirror':
            array_extendor = array.take([boundary_index],axis=axis)
            if boundary_index == 0:
                array1 = array_extendor
                array2 = array
            else:
                array1 = array
                array2 = array_extendor
            array = np.append(array1,array2,axis=axis)
        if method == 'zeros':
            array_extendor = np.zeros(array.take([boundary_index],axis=axis).shape)
            if boundary_index == 0:
                array1 = array_extendor
                array2 = array
            else:
                array1 = array
                array2 = array_extendor
            array = np.append(array1,array2,axis=axis)
        return array

    def read_array(self,extend_kwargs={},**kwargs):
        self._slice = self._slice_array_to_slice(self._plot_slice)
        out_array = self._v[self._slice]
        if np.ma.isMaskedArray(out_array):
            filled = kwargs.get('filled',np.nan)
            out_array = out_array.filled(filled)

        if self._plot_slice[2,0] < 0:
            out_array = self.extend_halos(out_array,axis=2,
                                          boundary_index=0,**extend_kwargs)
        if self._plot_slice[2,1] > self.dom.total_ylen:
            out_array = self.extend_halos(out_array,axis=2,
                                          boundary_index=-1,**extend_kwargs)
        if self._plot_slice[3,0] < 0:
            out_array = self.extend_halos(out_array,axis=3,
                                          boundary_index=0,**extend_kwargs)
        if self._plot_slice[3,1] > self.dom.total_xlen:
            out_array = self.extend_halos(out_array,axis=3,
                                          boundary_index=-1,**extend_kwargs)
        tmean = kwargs.get('tmean',True)
        if tmean:
            dt = self.average_DT
            out_array = np.apply_over_axes(np.sum,out_array*dt,0)/np.sum(dt)
        out_array = GridNdarray(out_array,self.loc)
        self.values = out_array
        return self

    def _modify_slice(self,axis,ns,ne):
        out_slice = self._plot_slice[axis,0] + ns
        out_slice = out_slice[axis,1] + ne
        return out_slice

    @staticmethod
    def _slice_array_to_slice(slice_array):
        """Creates a slice object from a slice array"""
        Slice = np.s_[ slice_array[0,0]:slice_array[0,1]:slice_array[0,2],
                       slice_array[1,0]:slice_array[1,1]:slice_array[1,2],
                       slice_array[2,0]:slice_array[2,1]:slice_array[2,2],
                       slice_array[3,0]:slice_array[3,1]:slice_array[3,2] ]
        return Slice

    def o1diff(self,axis):
        possible_hlocs = dict(u = ['u','u','q','h'],
                              v = ['v','v','h','q'],
                              h = ['h','h','v','u'],
                              q = ['q','q','u','v'])
        possible_vlocs = dict(l = ['l','i','l','l'],
                              i = ['i','l','i','i'])

        out_array = np.diff(self.values,n=1,axis=axis)
        out_array.loc = (  possible_hlocs[self.values.loc[0]][axis]
                           + possible_vlocs[self.values.loc[1]][axis] )
        self.values = out_array
        return self

    def ddx(self,axis):
        possible_divisors = dict(u = [self.dom.dt, self.dom.db,
                                      self.dom.dyBu, self.dom.dxT],
                                 v = [self.dom.dt, self.dom.db,
                                      self.dom.dyT,  self.dom.dxBu],
                                 h = [self.dom.dt, self.dom.db,
                                      self.dom.dyCv, self.dom.dxCu],
                                 q = [self.dom.dt, self.dom.db,
                                      self.dom.dyCu, self.dom.dxCv])
        if axis == 1:
            divisor = possible_divisors[self.values.loc[0]][axis]
        else:
            divisor = possible_divisors[self.values.loc[0]][axis][self._slice[2:]]
        ddx = self.o1diff(axis).values/divisor
        self.values = ddx
        return self

    def move_to(self,new_loc):
        possible_hlocs = dict(u = ['q','h'],
                              v = ['h','q'],
                              h = ['v','u'],
                              q = ['u','v'])
        loc = self.values.loc
        if new_loc[0] in possible_hlocs[loc[0]]:
            axis = possible_hlocs[loc[0]].index(new_loc[0])+2
        elif new_loc[1] is not loc[1]:
            axis = 1
        out_array = 0.5*(  np.take(self.values,range(self.values.shape[axis]-1),axis=axis)
                         + np.take(self.values,range(1,self.values.shape[axis]),axis=axis)  )
        out_array.loc = new_loc
        self.values = out_array
        return self
<commit_msg>Introduced mul and div dunders.<commit_after>import numpy as np
from netCDF4 import Dataset as dset, MFDataset as mfdset
from functools import partial

class GridNdarray(np.ndarray):
    """A class to hold a grid-located variable."""
    def __new__(cls,input_array,loc):
        obj = input_array.view(cls)
        obj.loc = loc
        return obj

    def __array_finalize__(self, obj):
        if obj is None: return
        self.loc = getattr(obj, 'loc', None)

    def __array_wrap__(self, out_arr, context=None):
        return np.ndarray.__array_wrap__(self, out_arr, context)

class GridVariable():

    """A class to hold a variable."""
    def __init__(self,var,domain,loc,*fhl,**kwargs):
        for fh in fhl:
            try:
                self._v = fh.variables[var]
            except KeyError:
                print('Trying next file.')
            else:
                self.var = var
                self.dom = domain
                self.loc = loc
                self.plot_loc = kwargs.get('plot_loc',self.loc)[0]
                self._plot_slice = self.dom.slices[self.plot_loc].copy()
                self.implement_syntactic_sugar_for_plot_slice()
                self.Time = fh.variables['Time'][:]
                self.dom.dt = np.diff(self.Time[:2])*3600
                average_DT = fh.variables['average_DT'][:]
                average_DT = average_DT[:,np.newaxis,np.newaxis,np.newaxis]
                self.average_DT = average_DT
                break

    def __add__(self,other):
        if self.values.loc == other.values.loc:
            new_variable = GridVariable(self.var,self.dom,self.values.loc)
            new_variable.values = self.values + other.values
            return new_variable
        else:
            raise ValueError('The two variables are not co-located.')

    def __sub__(self,other):
        if self.values.loc == other.values.loc:
            new_variable = GridVariable(self.var,self.dom,self.values.loc)
            new_variable.values = self.values - other.values
            return new_variable
        else:
            raise ValueError('The two variables are not co-located.')

    def __mul__(self,other):
        if self.values.loc == other.values.loc:
            new_variable = GridVariable(self.var,self.dom,self.values.loc)
            new_variable.values = self.values * other.values
            return new_variable
        else:
            raise ValueError('The two variables are not co-located.')

    def __div__(self,other):
        if self.values.loc == other.values.loc:
            new_variable = GridVariable(self.var,self.dom,self.values.loc)
            new_variable.values = self.values / other.values
            return new_variable
        else:
            raise ValueError('The two variables are not co-located.')

    def __neg__(self):
        self.values *= -1
        return self

    @property
    def plot_slice(self):
        return self._plot_slice

    @plot_slice.setter
    def plot_slice(self,operation_string):
        axis,limit,operation = list(operation_string)

        axes = ['t','l','y','x']
        limits = ['s','e']
        operations = { 'm': -1,
                       'p': +1 }
        self._plot_slice[axes.index(axis)][limits.index(limit)] += operations[operation]

    def plot_slice_modifier(self,string):
        self.plot_slice = string
        return self

    def implement_syntactic_sugar_for_plot_slice(self):
        axes = ['t','l','y','x']
        limits = ['s','e']
        operations = ['m','p']
        for axis in axes:
            for limit in limits:
                for op in operations:
                    string = axis+limit+op
                    setattr(self,string,partial(self.plot_slice_modifier,string))

    @staticmethod
    def extend_halos(array,axis,boundary_index,**kwargs):
        method = kwargs.get('method')
        if method == 'vorticity':
            slip = kwargs.get('slip',False)
            slip_multiplyer = 1 if slip else -1
            array_extendor = slip_multiplyer*array.take([boundary_index],axis=axis)
        elif method == 'mirror':
            array_extendor = array.take([boundary_index],axis=axis)
        elif method == 'zeros':
            array_extendor = np.zeros(array.take([boundary_index],axis=axis).shape)

        if boundary_index == 0:
            array1 = array_extendor
            array2 = array
        else:
            array1 = array
            array2 = array_extendor
        array = np.append(array1,array2,axis=axis)
        return array

    def read_array(self,extend_kwargs={},**kwargs):
        self._slice = self._slice_array_to_slice(self._plot_slice)
        out_array = self._v[self._slice]
        if np.ma.isMaskedArray(out_array):
            filled = kwargs.get('filled',np.nan)
            out_array = out_array.filled(filled)

#        for axis in range(2,4):
#            for boundary_index in range(2):
#                if self._plot_slice[axis,boundary_index] < 0:
#                    out_array = self.extend_halos(out_array,axis=axis,
#                                                  boundary_index=boundary_index,
#                                                  **extend_kwargs)

        if self._plot_slice[2,0] < 0:
            out_array = self.extend_halos(out_array,axis=2,
                                          boundary_index=0,**extend_kwargs)
        if self._plot_slice[2,1] > self.dom.total_ylen:
            out_array = self.extend_halos(out_array,axis=2,
                                          boundary_index=-1,**extend_kwargs)
        if self._plot_slice[3,0] < 0:
            out_array = self.extend_halos(out_array,axis=3,
                                          boundary_index=0,**extend_kwargs)
        if self._plot_slice[3,1] > self.dom.total_xlen:
            out_array = self.extend_halos(out_array,axis=3,
                                          boundary_index=-1,**extend_kwargs)
        tmean = kwargs.get('tmean',True)
        if tmean:
            dt = self.average_DT
            out_array = np.apply_over_axes(np.sum,out_array*dt,0)/np.sum(dt)
        out_array = GridNdarray(out_array,self.loc)
        self.values = out_array
        return self

    def _modify_slice(self,axis,ns,ne):
        out_slice = self._plot_slice[axis,0] + ns
        out_slice = out_slice[axis,1] + ne
        return out_slice

    @staticmethod
    def _slice_array_to_slice(slice_array):
        """Creates a slice object from a slice array"""
        Slice = np.s_[ slice_array[0,0]:slice_array[0,1]:slice_array[0,2],
                       slice_array[1,0]:slice_array[1,1]:slice_array[1,2],
                       slice_array[2,0]:slice_array[2,1]:slice_array[2,2],
                       slice_array[3,0]:slice_array[3,1]:slice_array[3,2] ]
        return Slice

    def o1diff(self,axis):
        possible_hlocs = dict(u = ['u','u','q','h'],
                              v = ['v','v','h','q'],
                              h = ['h','h','v','u'],
                              q = ['q','q','u','v'])
        possible_vlocs = dict(l = ['l','i','l','l'],
                              i = ['i','l','i','i'])

        out_array = np.diff(self.values,n=1,axis=axis)
        out_array.loc = (  possible_hlocs[self.values.loc[0]][axis]
                           + possible_vlocs[self.values.loc[1]][axis] )
        self.values = out_array
        return self

    def ddx(self,axis):
        possible_divisors = dict(u = [self.dom.dt, self.dom.db,
                                      self.dom.dyBu, self.dom.dxT],
                                 v = [self.dom.dt, self.dom.db,
                                      self.dom.dyT,  self.dom.dxBu],
                                 h = [self.dom.dt, self.dom.db,
                                      self.dom.dyCv, self.dom.dxCu],
                                 q = [self.dom.dt, self.dom.db,
                                      self.dom.dyCu, self.dom.dxCv])
        if axis == 1:
            divisor = possible_divisors[self.values.loc[0]][axis]
        else:
            divisor = possible_divisors[self.values.loc[0]][axis][self._slice[2:]]
        ddx = self.o1diff(axis).values/divisor
        self.values = ddx
        return self

    def move_to(self,new_loc):
        possible_hlocs = dict(u = ['q','h'],
                              v = ['h','q'],
                              h = ['v','u'],
                              q = ['u','v'])
        loc = self.values.loc
        if new_loc[0] in possible_hlocs[loc[0]]:
            axis = possible_hlocs[loc[0]].index(new_loc[0])+2
        elif new_loc[1] is not loc[1]:
            axis = 1
        out_array = 0.5*(  np.take(self.values,range(self.values.shape[axis]-1),axis=axis)
                         + np.take(self.values,range(1,self.values.shape[axis]),axis=axis)  )
        out_array.loc = new_loc
        self.values = out_array
        return self
<|endoftext|>


<commit_before>'''
======================================================================================================
Copyright (c) 2013, Makarov Yurii

               All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
======================================================================================================
'''

class NginxConfig:
    def __init__(self, offset_char=' '):
        self.i = 0 #char iterator for parsing
        self.length = 0
        self.config = ''
        self.data = []
        self.off_char = offset_char

    def __getitem__(self, index):
        return self.data[index]

    def __setitem__(self, index, value):
        self.data[index] = value

    def __delitem__(self, index):
        del self.data[index]

    def get_value(self, data):
        if isinstance(data, tuple):
            return data[1]
        elif isinstance(data, dict):
            return data['value']
        else:
            return data

    def get_name(self, data):
        if isinstance(data, tuple):
            return data[0]
        elif isinstance(data, dict):
            return data['name']
        else:
            return data

    def get(self, item_arr, data=[], param=None):
        if data == []:
            data = self.data
        if type(item_arr) in [str, tuple]:
            item = item_arr
        elif isinstance(item_arr, list):
            if len(item_arr) == 1:
                item = item_arr[0]
            else:
                element = item_arr.pop(0)

                if isinstance(element, tuple):#cannot be a string
                    if len(element) == 1:
                        element = (element[0], '')
                    for i, data_elem in enumerate(data):
                        if isinstance(data_elem, dict):
                            if (data_elem['name'], data_elem['param']) == element:
                                return self.get(item_arr, self.get_value(data[i]))

        if isinstance(item, str):
            for i, elem in enumerate(data):
                if isinstance(elem, tuple):
                    if elem[0] == item:
                        return data[i]
        elif isinstance(item, tuple):
            if len(item) == 1:
                item = (item[0], '')
            for i, elem in enumerate(data):
                if isinstance(elem, dict):
                    if (elem['name'], elem['param']) == item:
                        return data[i]

    def append(self, item, root=[], position=None):
        if root == []:
            root = self.data
        elif root is None:
            raise AttributeError('Root element is None')
        if position:
            root.insert(position, item)
        else:
            root.append(item)

    def remove(self, item_arr, data=[]):
        if data == []:
            data = self.data
        if type(item_arr) in [str, tuple]:
            item = item_arr
        elif isinstance(item_arr, list):
            if len(item_arr) == 1:
                item = item_arr[0]
            else:
                elem = item_arr.pop(0)
                if isinstance(elem, str):#strange code
                    self.remove(item_arr, self.get_value(elem, data))
                elif isinstance(elem, tuple):
                    if len(elem) == 2:
                        param = elem[1]
                    else:
                        param = ''
                    self.remove(item_arr, self.get_value(elem[0], data, param=param))
                    return

        if isinstance(item, str):
            for i,elem in enumerate(data):
                if isinstance(elem, tuple):
                    if elem[0] == item:
                        del data[i]
                        return
        elif isinstance(item, tuple):
            for i,elem in enumerate(data):
                if isinstance(elem, dict):
                    if (elem['name'], elem['param']) == item:
                        del data[i]
                        return
        else:
            raise AttributeError("Unknown item type '%s' in item_arr" % item.__class__.__name__)

    def load(self, config):
        self.config = config
        self.length = len(config) - 1
        self.i = 0
        self.data = self.parse_block()

    def parse_block(self):
        data = []
        param_name = None
        param_value = None
        buf = ''
        while self.i < self.length:
            if self.config[self.i] == '\n': #multiline value
                if buf and param_name:
                    if param_value is None:
                        param_value = []
                    param_value.append(buf.strip())
                    buf = ''
            elif self.config[self.i] == ' ':
                if not param_name and len(buf.strip()) > 0:
                    param_name = buf.strip()
                    buf = ''
                else:
                    buf += self.config[self.i]
            elif self.config[self.i] == ';':
                if isinstance(param_value, list):
                    param_value.append(buf.strip())
                else:
                    param_value = buf.strip()
                data.append((param_name, param_value))
                param_name = None
                param_value = None
                buf = ''
            elif self.config[self.i] == '{':
                self.i += 1
                block = self.parse_block()
                data.append({'name':param_name, 'param':buf.strip(), 'value':block})
                param_name = None
                param_value = None
                buf = ''
            elif self.config[self.i] == '}':
                self.i += 1
                return data
            elif self.config[self.i] == '#': #skip comments
                while self.i < self.length and self.config[self.i] != '\n':
                    self.i += 1
            else:
                buf += self.config[self.i]
            self.i += 1
        return data

    def gen_block(self, blocks, offset):
        subrez = '' # ready to return string
        block_name = None
        block_param = ''
        for i, block in enumerate(blocks):
            if isinstance(block, tuple):
                if isinstance(block[1], str):
                    subrez += self.off_char * offset + '%s %s;\n' % (block[0], block[1])
                else: #multiline
                    subrez += self.off_char * offset + '%s %s;\n' % (block[0],
                        self.gen_block(block[1], offset + len(block[0]) + 1))

            elif isinstance(block, dict):
                block_value = self.gen_block(block['value'], offset + 4)
                if block['param']:
                    param = block['param'] + ' '
                else:
                    param = ''
                if subrez != '':
                    subrez += '\n'
                subrez += '%(offset)s%(name)s %(param)s{\n%(data)s%(offset)s}\n' % {
                    'offset':self.off_char * offset, 'name':block['name'], 'data':block_value,
                    'param':param}

            elif isinstance(block, str): #multiline params
                if i == 0:
                    subrez += '%s\n' % block
                else:
                    subrez += '%s%s\n' % (self.off_char * offset, block)

        if block_name:
            return '%(offset)s%(name)s %(param)s{\n%(data)s%(offset)s}\n' % {
                'offset':self.off_char * offset, 'name':block_name, 'data':subrez,
                'param':block_param}
        else:
            return subrez

    def gen_config(self, offset_char=' '):
        self.off_char = offset_char
        return self.gen_block(self.data, 0)
<commit_msg>Fixed remove procedure<commit_after>'''
======================================================================================================
Copyright (c) 2013, Makarov Yurii

               All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
======================================================================================================
'''

class NginxConfig:
    def __init__(self, offset_char=' '):
        self.i = 0 #char iterator for parsing
        self.length = 0
        self.config = ''
        self.data = []
        self.off_char = offset_char

    def __getitem__(self, index):
        return self.data[index]

    def __setitem__(self, index, value):
        self.data[index] = value

    def __delitem__(self, index):
        del self.data[index]

    def get_value(self, data):
        if isinstance(data, tuple):
            return data[1]
        elif isinstance(data, dict):
            return data['value']
        else:
            return data

    def get_name(self, data):
        if isinstance(data, tuple):
            return data[0]
        elif isinstance(data, dict):
            return data['name']
        else:
            return data

    def get(self, item_arr, data=[], param=None):
        if data == []:
            data = self.data
        if type(item_arr) in [str, tuple]:
            item = item_arr
        elif isinstance(item_arr, list):
            if len(item_arr) == 1:
                item = item_arr[0]
            else:
                element = item_arr.pop(0)

                if isinstance(element, tuple):#cannot be a string
                    if len(element) == 1:
                        element = (element[0], '')
                    for i, data_elem in enumerate(data):
                        if isinstance(data_elem, dict):
                            if (data_elem['name'], data_elem['param']) == element:
                                return self.get(item_arr, self.get_value(data[i]))

        if isinstance(item, str):
            for i, elem in enumerate(data):
                if isinstance(elem, tuple):
                    if elem[0] == item:
                        return data[i]
        elif isinstance(item, tuple):
            if len(item) == 1:
                item = (item[0], '')
            for i, elem in enumerate(data):
                if isinstance(elem, dict):
                    if (elem['name'], elem['param']) == item:
                        return data[i]

    def append(self, item, root=[], position=None):
        if root == []:
            root = self.data
        elif root is None:
            raise AttributeError('Root element is None')
        if position:
            root.insert(position, item)
        else:
            root.append(item)

    def remove(self, item_arr, data=[]):
        if data == []:
            data = self.data
        if type(item_arr) in [str, tuple]:
            item = item_arr
        elif isinstance(item_arr, list):
            if len(item_arr) == 1:
                item = item_arr[0]
            else:
                elem = item_arr.pop(0)
                if type(elem) in [tuple,str]:
                    self.remove(item_arr, self.get_value(self.get(elem, data)))
                    return

        if isinstance(item, str):
            for i,elem in enumerate(data):
                if isinstance(elem, tuple):
                    if elem[0] == item:
                        del data[i]
                        return
        elif isinstance(item, tuple):
            for i,elem in enumerate(data):
                if isinstance(elem, dict):
                    if (elem['name'], elem['param']) == item:
                        del data[i]
                        return
        else:
            raise AttributeError("Unknown item type '%s' in item_arr" % item.__class__.__name__)
        raise KeyError('Unable to remove')

    def load(self, config):
        self.config = config
        self.length = len(config) - 1
        self.i = 0
        self.data = self.parse_block()

    def parse_block(self):
        data = []
        param_name = None
        param_value = None
        buf = ''
        while self.i < self.length:
            if self.config[self.i] == '\n': #multiline value
                if buf and param_name:
                    if param_value is None:
                        param_value = []
                    param_value.append(buf.strip())
                    buf = ''
            elif self.config[self.i] == ' ':
                if not param_name and len(buf.strip()) > 0:
                    param_name = buf.strip()
                    buf = ''
                else:
                    buf += self.config[self.i]
            elif self.config[self.i] == ';':
                if isinstance(param_value, list):
                    param_value.append(buf.strip())
                else:
                    param_value = buf.strip()
                data.append((param_name, param_value))
                param_name = None
                param_value = None
                buf = ''
            elif self.config[self.i] == '{':
                self.i += 1
                block = self.parse_block()
                data.append({'name':param_name, 'param':buf.strip(), 'value':block})
                param_name = None
                param_value = None
                buf = ''
            elif self.config[self.i] == '}':
                self.i += 1
                return data
            elif self.config[self.i] == '#': #skip comments
                while self.i < self.length and self.config[self.i] != '\n':
                    self.i += 1
            else:
                buf += self.config[self.i]
            self.i += 1
        return data

    def gen_block(self, blocks, offset):
        subrez = '' # ready to return string
        block_name = None
        block_param = ''
        for i, block in enumerate(blocks):
            if isinstance(block, tuple):
                if isinstance(block[1], str):
                    subrez += self.off_char * offset + '%s %s;\n' % (block[0], block[1])
                else: #multiline
                    subrez += self.off_char * offset + '%s %s;\n' % (block[0],
                        self.gen_block(block[1], offset + len(block[0]) + 1))

            elif isinstance(block, dict):
                block_value = self.gen_block(block['value'], offset + 4)
                if block['param']:
                    param = block['param'] + ' '
                else:
                    param = ''
                if subrez != '':
                    subrez += '\n'
                subrez += '%(offset)s%(name)s %(param)s{\n%(data)s%(offset)s}\n' % {
                    'offset':self.off_char * offset, 'name':block['name'], 'data':block_value,
                    'param':param}

            elif isinstance(block, str): #multiline params
                if i == 0:
                    subrez += '%s\n' % block
                else:
                    subrez += '%s%s\n' % (self.off_char * offset, block)

        if block_name:
            return '%(offset)s%(name)s %(param)s{\n%(data)s%(offset)s}\n' % {
                'offset':self.off_char * offset, 'name':block_name, 'data':subrez,
                'param':block_param}
        else:
            return subrez

    def gen_config(self, offset_char=' '):
        self.off_char = offset_char
        return self.gen_block(self.data, 0)
<|endoftext|>


<commit_before>'''
======================================================================================================
Copyright (c) 2013, Makarov Yurii

               All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
======================================================================================================
'''

class NginxConfig:
    def __init__(self, offset_char=' '):
        self.i = 0 #char iterator for parsing
        self.length = 0
        self.config = ''
        self.data = []
        self.off_char = offset_char

    def __getitem__(self, index):
        return self.data[index]

    def __setitem__(self, index, value):
        self.data[index] = value

    def __delitem__(self, index):
        del self.data[index]

    def get(self, item, data=[], param=None):
        if data == []:
            data = self.data
        for d in data:
            if isinstance(d, tuple) and d[0] == item:
                return d
            elif isinstance(d, dict):
                if (d['name'] == item) and (param is None or param == d['param']):
                    return d
        return None

    def get_value(self, item, data=[], param=None):
        rez = self.get(item, data, param)
        if isinstance(rez, tuple):
            return rez[1]
        elif isinstance(rez, dict):
            return rez['value']
        else:
            return rez

    def append(self, item, root=[], position=None):
        if root == []:
            root = self.data
        elif root is None:
            raise AttributeError('Root element is None')
        if position:
            root.insert(position, item)
        else:
            root.append(item)

    def remove(self, item_arr, data=[]):
        if data == []:
            data = self.data
        if type(item_arr) in [str, tuple]:
            item = item_arr
        elif isinstance(item_arr, list):
            if len(item_arr) == 1:
                item = item_arr[0]
            else:
                elem = item_arr.pop(0)
                if isinstance(elem, str):
                    self.remove(item_arr, self.get_value(elem, data))
                elif isinstance(elem, tuple):
                    self.remove(item_arr, self.get_value(elem[0], data, param=elem[1]))
                    return

        if isinstance(item, str):
            for i,elem in enumerate(data):
                if isinstance(elem, tuple):
                    if elem[0] == item:
                        del data[i]
                        return
        elif isinstance(item, tuple):
            for i,elem in enumerate(data):
                if isinstance(elem, dict):
                    if (elem['name'], elem['param']) == item:
                        del data[i]
                        return
        else:
            raise AttributeError("Unknown item type '%s' in item_arr" % item.__class__.__name__)

    def load(self, config):
        self.config = config
        self.length = len(config) - 1
        self.i = 0
        self.data = self.parse_block()

    def parse_block(self, name=''):
        data = []
        param_name = None
        param_value = None
        buf = ''
        while self.i < self.length:
            if self.config[self.i] == '\n': #multiline value
                if buf and param_name:
                    if param_value is None:
                        param_value = []
                    param_value.append(buf.strip())
                    buf = ''
            elif self.config[self.i] == ' ':
                if not param_name and len(buf.strip()) > 0:
                    param_name = buf.strip()
                    buf = ''
                else:
                    buf += self.config[self.i]
            elif self.config[self.i] == ';':
                if isinstance(param_value, list):
                    param_value.append(buf.strip())
                else:
                    param_value = buf.strip()
                data.append((param_name, param_value))
                param_name = None
                param_value = None
                buf = ''
            elif self.config[self.i] == '{':
                self.i += 1
                block = self.parse_block(name+':'+param_name)
                data.append({'name':param_name, 'param':buf.strip(), 'value':block})
                param_name = None
                param_value = None
                buf = ''
            elif self.config[self.i] == '}':
                self.i += 1
                return data
            elif self.config[self.i] == '#': #skip comments
                while self.i < self.length and self.config[self.i] != '\n':
                    self.i += 1
            else:
                buf += self.config[self.i]
            self.i += 1
        return data

    def gen_block(self, blocks, offset):
        subrez = '' # ready to return string
        block_name = None
        block_param = ''
        for i, block in enumerate(blocks):
            if isinstance(block, tuple):
                if isinstance(block[1], str):
                    subrez += self.off_char * offset + '%s %s;\n' % (block[0], block[1])
                else: #multiline
                    subrez += self.off_char * offset + '%s %s;\n' % (block[0],
                        self.gen_block(block[1], offset + len(block[0]) + 1))

            elif isinstance(block, dict):
                block_value = self.gen_block(block['value'], offset + 4)
                if block['param']:
                    param = block['param'] + ' '
                else:
                    param = ''
                if subrez != '':
                    subrez += '\n'
                subrez += '%(offset)s%(name)s %(param)s{\n%(data)s%(offset)s}\n' % {
                    'offset':self.off_char * offset, 'name':block['name'], 'data':block_value,
                    'param':param}

            elif isinstance(block, str): #multiline params
                if i == 0:
                    subrez += '%s\n' % block
                else:
                    subrez += '%s%s\n' % (self.off_char * offset, block)

        if block_name:
            return '%(offset)s%(name)s %(param)s{\n%(data)s%(offset)s}\n' % {
                'offset':self.off_char * offset, 'name':block_name, 'data':subrez,
                'param':block_param}
        else:
            return subrez

    def gen_config(self, offset_char=' '):
        self.off_char = offset_char
        return self.gen_block(self.data, 0)
<commit_msg>Some changes in remove interface<commit_after>'''
======================================================================================================
Copyright (c) 2013, Makarov Yurii

               All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
======================================================================================================
'''

class NginxConfig:
    def __init__(self, offset_char=' '):
        self.i = 0 #char iterator for parsing
        self.length = 0
        self.config = ''
        self.data = []
        self.off_char = offset_char

    def __getitem__(self, index):
        return self.data[index]

    def __setitem__(self, index, value):
        self.data[index] = value

    def __delitem__(self, index):
        del self.data[index]

    def get(self, item, data=[], param=None):
        if data == []:
            data = self.data
        for d in data:
            if isinstance(d, tuple) and d[0] == item:
                return d
            elif isinstance(d, dict):
                if (d['name'] == item) and (param is None or param == d['param']):
                    return d
        return None

    def get_value(self, item, data=[], param=None):
        rez = self.get(item, data, param)
        if isinstance(rez, tuple):
            return rez[1]
        elif isinstance(rez, dict):
            return rez['value']
        else:
            return rez

    def append(self, item, root=[], position=None):
        if root == []:
            root = self.data
        elif root is None:
            raise AttributeError('Root element is None')
        if position:
            root.insert(position, item)
        else:
            root.append(item)

    def remove(self, item_arr, data=[]):
        if data == []:
            data = self.data
        if type(item_arr) in [str, tuple]:
            item = item_arr
        elif isinstance(item_arr, list):
            if len(item_arr) == 1:
                item = item_arr[0]
            else:
                elem = item_arr.pop(0)
                if isinstance(elem, str):
                    self.remove(item_arr, self.get_value(elem, data))
                elif isinstance(elem, tuple):
                    if len(elem) == 2:
                        param = elem[1]
                    else:
                        param = ''
                    self.remove(item_arr, self.get_value(elem[0], data, param=param))
                    return

        if isinstance(item, str):
            for i,elem in enumerate(data):
                if isinstance(elem, tuple):
                    if elem[0] == item:
                        del data[i]
                        return
        elif isinstance(item, tuple):
            for i,elem in enumerate(data):
                if isinstance(elem, dict):
                    if (elem['name'], elem['param']) == item:
                        del data[i]
                        return
        else:
            raise AttributeError("Unknown item type '%s' in item_arr" % item.__class__.__name__)

    def load(self, config):
        self.config = config
        self.length = len(config) - 1
        self.i = 0
        self.data = self.parse_block()

    def parse_block(self, name=''):
        data = []
        param_name = None
        param_value = None
        buf = ''
        while self.i < self.length:
            if self.config[self.i] == '\n': #multiline value
                if buf and param_name:
                    if param_value is None:
                        param_value = []
                    param_value.append(buf.strip())
                    buf = ''
            elif self.config[self.i] == ' ':
                if not param_name and len(buf.strip()) > 0:
                    param_name = buf.strip()
                    buf = ''
                else:
                    buf += self.config[self.i]
            elif self.config[self.i] == ';':
                if isinstance(param_value, list):
                    param_value.append(buf.strip())
                else:
                    param_value = buf.strip()
                data.append((param_name, param_value))
                param_name = None
                param_value = None
                buf = ''
            elif self.config[self.i] == '{':
                self.i += 1
                block = self.parse_block(name+':'+param_name)
                data.append({'name':param_name, 'param':buf.strip(), 'value':block})
                param_name = None
                param_value = None
                buf = ''
            elif self.config[self.i] == '}':
                self.i += 1
                return data
            elif self.config[self.i] == '#': #skip comments
                while self.i < self.length and self.config[self.i] != '\n':
                    self.i += 1
            else:
                buf += self.config[self.i]
            self.i += 1
        return data

    def gen_block(self, blocks, offset):
        subrez = '' # ready to return string
        block_name = None
        block_param = ''
        for i, block in enumerate(blocks):
            if isinstance(block, tuple):
                if isinstance(block[1], str):
                    subrez += self.off_char * offset + '%s %s;\n' % (block[0], block[1])
                else: #multiline
                    subrez += self.off_char * offset + '%s %s;\n' % (block[0],
                        self.gen_block(block[1], offset + len(block[0]) + 1))

            elif isinstance(block, dict):
                block_value = self.gen_block(block['value'], offset + 4)
                if block['param']:
                    param = block['param'] + ' '
                else:
                    param = ''
                if subrez != '':
                    subrez += '\n'
                subrez += '%(offset)s%(name)s %(param)s{\n%(data)s%(offset)s}\n' % {
                    'offset':self.off_char * offset, 'name':block['name'], 'data':block_value,
                    'param':param}

            elif isinstance(block, str): #multiline params
                if i == 0:
                    subrez += '%s\n' % block
                else:
                    subrez += '%s%s\n' % (self.off_char * offset, block)

        if block_name:
            return '%(offset)s%(name)s %(param)s{\n%(data)s%(offset)s}\n' % {
                'offset':self.off_char * offset, 'name':block_name, 'data':subrez,
                'param':block_param}
        else:
            return subrez

    def gen_config(self, offset_char=' '):
        self.off_char = offset_char
        return self.gen_block(self.data, 0)
<|endoftext|>


<commit_before>"""
The threading module.  This module implements various locking diagnostics.
To use the locking diagnostics use the WatchLock or WatchRLock for the locks
that should be monitored for deadlocks.
"""
from __future__ import absolute_import, with_statement
import threading
from thread import allocate_lock as _allocate_lock
from threading import *
from threading import _active, _DummyThread

__all__ = threading.__all__ + ['WatchLock', 'WatchRLock']

class _Watcher(object):
  def __init__(self):
    self.__lock = _allocate_lock()
    self.__locks = {}
    self.__waiting = {}
    watcher = threading.Thread(target=self._watcher)
    watcher.daemon = True
    watcher.start()

  def wait(self, lock):
    from traceback import extract_stack
    with self.__lock:
      self.__waiting[current_thread()] = (lock, extract_stack())

  def got(self):
    # Assert checked by wait(lock)
    with self.__lock:
      me = current_thread()
      lock, bt = self.__waiting[me]
      self.__waiting[me] = None
      self.__locks[lock] = (me, bt)

  def acquired(self, lock):
    from traceback import extract_stack
    with self.__lock:
      self.__locks[lock] = (current_thread(), extract_stack())

  def release(self, lock, release):
    assert lock.locked()
    with self.__lock:
      release()
      self.__locks.pop(lock)

  def info(self, stack=None):
    from traceback import format_list
    if not stack:
      all_acq = True
      stack = [(i[1][0], i[0]) for i in self.__waiting.iteritems() if i[1]]
      msg = " --- Waiting threads ---\n"
    else:
      all_acq = False
      msg = " --- Cyclic deadlock ---\n"
    for lock, thr in stack:
      msg += 'Thread "%s" waiting for lock "%s"\n' % (thr.name, str(lock))
      msg += '\tLock "%s" held by thread "%s"\n' % (str(lock), self.__locks[lock][0].name)

    msg += "\n\n --- Waiting threads traceback ---\n"
    for lock, thr in stack:
      msg += '\nThread "%s" (waiting for lock "%s"):\n' % (thr.name, str(lock))
      msg += ''.join(format_list(self.__waiting[thr][1]))

    if all_acq:
      stack = [(i[0], i[1][0]) for i in self.__locks.iteritems()]
    msg += "\n\n --- Acquired locks traceback ---\n"
    for i in stack:
      lock = i[0]
      msg += '\nLock "%s" (held by thread "%s"):\n' % (str(lock), self.__locks[lock][0].name)
      msg += ''.join(format_list(self.__locks[lock][1]))
    return msg

  def _watcher(self):
    from time import sleep
    from sys import stderr
    while True:
      sleep(5)
      #stderr.write(self.info())
      with self.__lock:
        for lock, thr in [(i[1][0], i[0]) for i in self.__waiting.iteritems() if i[1]]:
          stack = [(lock, thr)]
          threads = [thr]
          while True:
            if self.__locks.has_key(lock):
              thr = self.__locks[lock][0]
              if self.__waiting.has_key(thr) and self.__waiting[thr]:
                lock = self.__waiting[thr][0]
                if thr == threads[0]:
                  self._report_cyclic(stack)
                elif thr not in threads:
                  stack.append((lock, thr))
                  threads.append(thr)
                  continue
            # If no next link
            break

  def _report_cyclic(self, stack):
    from os import getpid, kill
    from logging import getLogger
    from signal import SIGKILL
    from sys import stderr
    from time import sleep

    from .exit import terminate

    stderr.write("Cyclic deadlock detected, terminating program\n")
    getLogger("pypkg.threading").critical(self.info(stack))

    terminate()
    sleep(5)
    kill(getpid(), SIGKILL)

_watcher = _Watcher()

class WatchLock(object):
  __lock_count = 0
  __intr_lock  = _allocate_lock()

  def __init__(self, name=None, enum=False):
    self.__lock = _allocate_lock()
    if name and not enum:
      self.__name = name
    else:
      with WatchLock.__intr_lock:
        self.__name = "%s-%i" % (name and name or "WatchLock", WatchLock.__lock_count)
        WatchLock.__lock_count += 1

  def __repr__(self):
    return "<%s>" % (self.__class__.__name__)

  def __str__(self):
    return self.__name

  def acquire(self, blocking=True):
    if not blocking:
      status = self.__lock.acquire(False)
      if status:
        _watcher.acquired(self)
      return status
    else:
      _watcher.wait(self)
      self.__lock.acquire()
      _watcher.got()
      return True

  __enter__ = acquire

  def release(self):
    _watcher.release(self, self.__lock.release)

  def __exit__(self, t, v, bt):
    self.release()

  def locked(self):
    return self.__lock.locked()

class WatchRLock(threading._RLock):
  __lock_count = 0
  __intr_lock  = _allocate_lock()

  def __init__(self, name=None, enum=False):
    threading._RLock.__init__(self)
     if name and not enum:
      self.__name = name
    else:
      with WatchLock.__intr_lock:
        self.__name = "%s-%i" % (name and name or "WatchRLock", WatchLock.__lock_count)
        WatchLock.__lock_count += 1
    self._RLock__block = WatchLock(self.__name)

  def __str__(self):
    return self.__name

Lock = WatchLock
RLock = WatchRLock
<commit_msg> - Allow lock.acquire to not be watched<commit_after>"""
The threading module.  This module implements various locking diagnostics.
To use the locking diagnostics use the WatchLock or WatchRLock for the locks
that should be monitored for deadlocks.
"""
from __future__ import absolute_import, with_statement
import threading
from thread import allocate_lock as _allocate_lock
from threading import *
from threading import _active, _DummyThread

__all__ = threading.__all__ + ['WatchLock', 'WatchRLock']

class _Watcher(object):
  def __init__(self):
    self.__lock = _allocate_lock()
    self.__locks = {}
    self.__waiting = {}
    watcher = threading.Thread(target=self._watcher)
    watcher.daemon = True
    watcher.start()

  def wait(self, lock):
    from traceback import extract_stack
    with self.__lock:
      self.__waiting[current_thread()] = (lock, extract_stack())

  def got(self):
    # Assert checked by wait(lock)
    with self.__lock:
      me = current_thread()
      lock, bt = self.__waiting[me]
      self.__waiting[me] = None
      self.__locks[lock] = (me, bt)

  def acquired(self, lock):
    from traceback import extract_stack
    with self.__lock:
      self.__locks[lock] = (current_thread(), extract_stack())

  def release(self, lock, release):
    assert lock.locked()
    with self.__lock:
      release()
      self.__locks.pop(lock)

  def info(self, stack=None):
    from traceback import format_list
    if not stack:
      all_acq = True
      stack = [(i[1][0], i[0]) for i in self.__waiting.iteritems() if i[1]]
      msg = " --- Waiting threads ---\n"
    else:
      all_acq = False
      msg = " --- Cyclic deadlock ---\n"
    for lock, thr in stack:
      msg += 'Thread "%s" waiting for lock "%s"\n' % (thr.name, str(lock))
      msg += '\tLock "%s" held by thread "%s"\n' % (str(lock), self.__locks[lock][0].name)

    msg += "\n\n --- Waiting threads traceback ---\n"
    for lock, thr in stack:
      msg += '\nThread "%s" (waiting for lock "%s"):\n' % (thr.name, str(lock))
      msg += ''.join(format_list(self.__waiting[thr][1]))

    if all_acq:
      stack = [(i[0], i[1][0]) for i in self.__locks.iteritems()]
    msg += "\n\n --- Acquired locks traceback ---\n"
    for i in stack:
      lock = i[0]
      msg += '\nLock "%s" (held by thread "%s"):\n' % (str(lock), self.__locks[lock][0].name)
      msg += ''.join(format_list(self.__locks[lock][1]))
    return msg

  def _watcher(self):
    from time import sleep
    from sys import stderr
    while True:
      sleep(5)
      #stderr.write(self.info())
      with self.__lock:
        for lock, thr in [(i[1][0], i[0]) for i in self.__waiting.iteritems() if i[1]]:
          stack = [(lock, thr)]
          threads = [thr]
          while True:
            if self.__locks.has_key(lock):
              thr = self.__locks[lock][0]
              if self.__waiting.has_key(thr) and self.__waiting[thr]:
                lock = self.__waiting[thr][0]
                if thr == threads[0]:
                  self._report_cyclic(stack)
                elif thr not in threads:
                  stack.append((lock, thr))
                  threads.append(thr)
                  continue
            # If no next link
            break

  def _report_cyclic(self, stack):
    from os import getpid, kill
    from logging import getLogger
    from signal import SIGKILL
    from sys import stderr
    from time import sleep

    from .exit import terminate

    stderr.write("Cyclic deadlock detected, terminating program\n")
    getLogger("pypkg.threading").critical(self.info(stack))

    terminate()
    sleep(5)
    kill(getpid(), SIGKILL)

_watcher = _Watcher()

class WatchLock(object):
  __lock_count = 0
  __intr_lock  = _allocate_lock()

  def __init__(self, name=None, enum=False):
    self.__lock = _allocate_lock()
    if name and not enum:
      self.__name = name
    else:
      with WatchLock.__intr_lock:
        self.__name = "%s-%i" % (name and name or "WatchLock", WatchLock.__lock_count)
        WatchLock.__lock_count += 1

  def __repr__(self):
    return "<%s>" % (self.__class__.__name__)

  def __str__(self):
    return self.__name

  def acquire(self, blocking=True, watch=True):
    if not blocking or not watch:
      status = self.__lock.acquire(blocking)
      if status:
        _watcher.acquired(self)
      return status
    else:
      _watcher.wait(self)
      self.__lock.acquire()
      _watcher.got()
      return True

  __enter__ = acquire

  def release(self):
    _watcher.release(self, self.__lock.release)

  def __exit__(self, t, v, bt):
    self.release()

  def locked(self):
    return self.__lock.locked()

class WatchRLock(threading._RLock):
  __lock_count = 0
  __intr_lock  = _allocate_lock()

  def __init__(self, name=None, enum=False):
    threading._RLock.__init__(self)
     if name and not enum:
      self.__name = name
    else:
      with WatchLock.__intr_lock:
        self.__name = "%s-%i" % (name and name or "WatchRLock", WatchLock.__lock_count)
        WatchLock.__lock_count += 1
    self._RLock__block = WatchLock(self.__name)

  def __str__(self):
    return self.__name

Lock = WatchLock
RLock = WatchRLock
<|endoftext|>


<commit_before>from .decorator import task  # noqa

__title__ = 'pyqs'
__version__ = '0.0.22'
<commit_msg>Version 0.1.0.<commit_after>from .decorator import task  # noqa

__title__ = 'pyqs'
__version__ = '0.1.0'
<|endoftext|>


<commit_before>import sys
import zmq
import json
import time
import threading

from copy import deepcopy
from datetime import datetime
from collections import defaultdict

from .io import io_from_host
from .modules import name2mod
from .metrics import Publisher

def run_from_unittest():
    return 'unittest' in sys.modules

class Robot(object):
    _heartbeat_timeout = 5  # in sec.

    def __init__(self, host, verbose=True, *args, **kwargs):
        self._io = io_from_host(host=host,
                                *args, **kwargs)

        self._verbose = verbose

        self._log('Connected to "{}".'.format(host))

        # We force a first poll to setup our model.
        self._setup()
        self._log('Robot setup.')

        self._last_update = time.time()
        self._running = True

        # Setup both poll/push synchronization loops.
        self._poll_bg = threading.Thread(target=self._poll_and_up)
        self._poll_bg.daemon = True
        self._poll_bg.start()

        if not run_from_unittest():
            self._metrics_pub = Publisher(robot=self)
            self._metrics_pub.start()

            c = zmq.Context()
            s = c.socket(zmq.PUB)
            s.connect('tcp://127.0.0.1:33000')
            self._s = s

    @property
    def state(self):
        return {
            'gate': self.name,
            'timestamp': datetime.now(),
            'types': ','.join([mod.type for mod in self.modules]),
            'modules': ','.join([mod.alias for mod in self.modules])
        }

    @property
    def name(self):
        return self._name

    @property
    def alive(self):
        dt = time.time() - self._last_update
        return self._running and dt < self._heartbeat_timeout

    def close(self):
        self._running = False
        self._poll_bg.join()

    def _setup(self):
        self._log('Sending detection signal.')
        self._send({'detection': {}})

        self._log('Waiting for first state...')
        state = self._poll_once()

        gate = next(g for g in state['modules']
                    if g['type'] == 'gate')
        self._name = gate['alias']

        modules = [mod for mod in state['modules']
                   if mod['type'] in name2mod.keys()]

        self._old_cmd = defaultdict(lambda: defaultdict(int))
        self._cmd = defaultdict(lambda: defaultdict(int))

        self.modules = [
            name2mod[mod['type']](id=mod['id'],
                                  alias=mod['alias'],
                                  robot=self)
            for mod in modules
        ]
        # We push our current state to make sure that
        # both our model and the hardware are synced.
        self._push_once()

        for mod in self.modules:
            setattr(self, mod.alias, mod)

    # Poll state from hardware.
    def _poll_once(self):
        return self._io.read()

    def _poll_and_up(self):
        while self._running:
            state = self._poll_once()
            self._update(state)
            self._push_once()

            self._broadcast(state)

    # Update our model with the new state.
    def _update(self, new_state):
        mod_need_update = [mod for mod in new_state['modules']
                           if hasattr(self, mod['alias']) and
                           set(mod.keys()) != {'type', 'id', 'alias'}]

        for mod in mod_need_update:
            getattr(self, mod['alias'])._update(mod)

        self._last_update = time.time()

    # Push update from our model to the hardware
    def _push_once(self):
        diff = defaultdict(dict)

        for mod, values in self._cmd.items():
            for key, val in values.items():
                if self._old_cmd[mod][key] != val:
                    diff[mod][key] = val

        if diff:
            self._send({
                'modules': diff
            })
            self._old_cmd = deepcopy(self._cmd)

    def _send(self, msg):
        self._io.send(msg)

    def _broadcast(self, state):
        if not hasattr(self, '_s'):
            return

        for mod in state['modules']:
            if ((mod['type'] in ('servo', 'dynamixel')) and
               (hasattr(self, mod['alias']))):
                servo = getattr(self, mod['alias'])
                mod['value'] = servo.position

        msg = '{} {}'.format(self.name, json.dumps(state))
        self._s.send_string(msg)

    def _log(self, msg):
        if self._verbose:
            print(msg)
<commit_msg>Store last state in the robot (mostly for debug purpose).<commit_after>import sys
import zmq
import json
import time
import threading

from copy import deepcopy
from datetime import datetime
from collections import defaultdict

from .io import io_from_host
from .modules import name2mod
from .metrics import Publisher

def run_from_unittest():
    return 'unittest' in sys.modules

class Robot(object):
    _heartbeat_timeout = 5  # in sec.

    def __init__(self, host, verbose=True, *args, **kwargs):
        self._io = io_from_host(host=host,
                                *args, **kwargs)

        self._verbose = verbose

        self._log('Connected to "{}".'.format(host))

        # We force a first poll to setup our model.
        self._setup()
        self._log('Robot setup.')

        self._last_update = time.time()
        self._running = True

        # Setup both poll/push synchronization loops.
        self._poll_bg = threading.Thread(target=self._poll_and_up)
        self._poll_bg.daemon = True
        self._poll_bg.start()

        if not run_from_unittest():
            self._metrics_pub = Publisher(robot=self)
            self._metrics_pub.start()

            c = zmq.Context()
            s = c.socket(zmq.PUB)
            s.connect('tcp://127.0.0.1:33000')
            self._s = s

    @property
    def state(self):
        return {
            'gate': self.name,
            'timestamp': datetime.now(),
            'types': ','.join([mod.type for mod in self.modules]),
            'modules': ','.join([mod.alias for mod in self.modules])
        }

    @property
    def name(self):
        return self._name

    @property
    def alive(self):
        dt = time.time() - self._last_update
        return self._running and dt < self._heartbeat_timeout

    def close(self):
        self._running = False
        self._poll_bg.join()

    def _setup(self):
        self._log('Sending detection signal.')
        self._send({'detection': {}})

        self._log('Waiting for first state...')
        state = self._poll_once()

        gate = next(g for g in state['modules']
                    if g['type'] == 'gate')
        self._name = gate['alias']

        modules = [mod for mod in state['modules']
                   if mod['type'] in name2mod.keys()]

        self._old_cmd = defaultdict(lambda: defaultdict(int))
        self._cmd = defaultdict(lambda: defaultdict(int))

        self.modules = [
            name2mod[mod['type']](id=mod['id'],
                                  alias=mod['alias'],
                                  robot=self)
            for mod in modules
        ]
        # We push our current state to make sure that
        # both our model and the hardware are synced.
        self._push_once()

        for mod in self.modules:
            setattr(self, mod.alias, mod)

    # Poll state from hardware.
    def _poll_once(self):
        self._state = self._io.read()
        return self._state

    def _poll_and_up(self):
        while self._running:
            state = self._poll_once()
            self._update(state)
            self._push_once()

            self._broadcast(state)

    # Update our model with the new state.
    def _update(self, new_state):
        mod_need_update = [mod for mod in new_state['modules']
                           if hasattr(self, mod['alias']) and
                           set(mod.keys()) != {'type', 'id', 'alias'}]

        for mod in mod_need_update:
            getattr(self, mod['alias'])._update(mod)

        self._last_update = time.time()

    # Push update from our model to the hardware
    def _push_once(self):
        diff = defaultdict(dict)

        for mod, values in self._cmd.items():
            for key, val in values.items():
                if self._old_cmd[mod][key] != val:
                    diff[mod][key] = val

        if diff:
            self._send({
                'modules': diff
            })
            self._old_cmd = deepcopy(self._cmd)

    def _send(self, msg):
        self._io.send(msg)

    def _broadcast(self, state):
        if not hasattr(self, '_s'):
            return

        for mod in state['modules']:
            if ((mod['type'] in ('servo', 'dynamixel')) and
               (hasattr(self, mod['alias']))):
                servo = getattr(self, mod['alias'])
                mod['value'] = servo.position

        msg = '{} {}'.format(self.name, json.dumps(state))
        self._s.send_string(msg)

    def _log(self, msg):
        if self._verbose:
            print(msg)
<|endoftext|>


<commit_before>from abc import ABCMeta, abstractmethod
import numpy as np
import itertools
import sympy

class Simulator:
    """An abstract base class for numerical simulation of models.

    Parameters
    ----------
    model : pysb.Model
        Model to simulate.
    tspan : vector-like, optional
        Time values over which to simulate. The first and last values define
        the time range. Returned trajectories are sampled at every value unless
        the simulation is interrupted for some reason, e.g., due to satisfaction
        of a logical stopping criterion (see 'tout' below).
    verbose : bool, optional (default: False)
        Verbose output.

    Attributes
    ----------
    verbose: bool
        Verbosity flag passed to the constructor.
    model : pysb.Model
        Model passed to the constructor.
    tspan : vector-like
        Time values passed to the constructor.
    tout: numpy.ndarray
        Time points returned by the simulator (may be different from ``tspan``
        if simulation is interrupted for some reason).
    y : numpy.ndarray
        Species trajectories.
    yobs : numpy.ndarray with record-style data-type
        Record names follow ``model.observables`` names.
    yobs_view : numpy.ndarray
        An array view (sharing the same data buffer) on ``yobs``.
    yexpr : numpy.ndarray with record-style data-type
        Expression trajectories. Record names follow
        ``model.expressions_dynamic()`` names.
    yexpr_view : numpy.ndarray
        An array view (sharing the same data buffer) on ``yexpr``.

    Notes
    -----
    If ``tspan`` is not defined, it may be defined in the call to the
    ``run`` method.

    The dimensionality of ``tout`` depends on whether a single simulation
    or multiple simulations are run.

    The dimensionalities of ``y``, ``yobs``, ``yobs_view``, ``yexpr``, and
    ``yexpr_view`` depend on the number of simulations being run as well
    as on the type of simulation, i.e., spatial vs. non-spatial.

    """
    __metaclass__ = ABCMeta

    @abstractmethod
    def __init__(self, model, tspan=None, verbose=False):
        self.model = model
        self.tspan = tspan
        self.verbose = verbose
        self.tout= None
        self.y = None
        self.yobs = None
        self.yobs_view = None
        self.yexpr = None
        self.yexpr_view = None

    @abstractmethod
    def run(self, tspan=None, param_values=None, y0=None):
        """Run a simulation.

        Returns nothing; access the Simulator object's ``y``, ``yobs``,
        ``yobs_view``, ``yexpr``, or ``yexpr_view`` attributes to retrieve the
        results.

        Parameters
        ----------
        tspan : vector-like, optional
            Time values over which to simulate. An Exception should be raised
            if not defined either here or in the constructor.
        param_values : vector-like, optional
            Values to use for every parameter in the model. Ordering is
            determined by the order of model.parameters. If not specified,
            parameter values will be taken directly from model.parameters.
        y0 : vector-like, optional
            Values to use for the initial condition of all species. Ordering is
            determined by the order of model.species. If not specified, initial
            conditions will be taken from model.initial_conditions (with initial
            condition parameter values taken from `param_values` if specified).

        """
        pass

    @abstractmethod
    def _calc_yobs_yexpr(self, param_values=None):
        """Calculate ``yobs`` and ``yexpr`` based on values of ``y`` obtained
        in ``run``."""
        self.yobs = len(self.y) * [None]
        self.yobs_view = len(self.y) * [None]
        self.yexpr = len(self.y) * [None]
        self.yexpr_view = len(self.y) * [None]
        len_tout = len(self.tout[0])
        tmp_obs = np.ndarray(len_tout, zip(self.model.observables.keys(), itertools.repeat(float)))
        exprs = self.model.expressions_dynamic()
        obs_names = self.model.observables.keys()
        len_obs = len(self.model.observables)
        model_obs = self.model.observables
        # loop over simulations
        for n in range(len(self.y)):
            len_tout_n = len(self.tout[n])
            # observables
            if len_obs:
                self.yobs[n] = tmp_obs.copy()
            else:
                self.yobs[n] = np.ndarray((len_tout_n, 0))
            self.yobs_view[n] = self.yobs[n].view(float).reshape(len(self.yobs[n]), -1)
            for i,obs in enumerate(model_obs):
                self.yobs_view[n][:,i] = (self.y[n][:,obs.species] * obs.coefficients).sum(axis=1)
            # expressions

            if len(exprs):
                self.yexpr[n] = np.ndarray(len(self.tout[n]), zip(exprs.keys(), itertools.repeat(float)))
            else:
                self.yexpr[n] = np.ndarray((len(self.tout[n]), 0))
            self.yexpr_view[n] = self.yexpr[n].view(float).reshape(len(self.yexpr[n]), -1)
            if param_values is None:
                param_values = [p.value for p in self.model.parameters]
            p_subs = { p.name : param_values[i] for i,p in enumerate(self.model.parameters) }

            obs_dict = { name : self.yobs_view[n][:,i] for i,name in enumerate(obs_names) }
            for i,expr in enumerate(exprs):
                expr_subs = expr.expand_expr(self.model).subs(p_subs)
                func = sympy.lambdify(obs_names, expr_subs, "numpy")
                self.yexpr_view[n][:,i] = func(**obs_dict)
        self.yobs = np.array(self.yobs)
        self.yobs_view = np.array(self.yobs_view)
        self.yexpr = np.array(self.yexpr)
        self.yexpr_view = np.array(self.yexpr_view)

    @abstractmethod
    def get_yfull(self):
        """Aggregate species, observables, and expressions trajectories into
        a numpy.ndarray with record-style data-type for return to the user."""
        sp_names = ['__s%d' % i for i in range(len(self.model.species))]
        yfull_dtype = zip(sp_names, itertools.repeat(float))
        if len(self.model.observables):
            yfull_dtype += zip(self.model.observables.keys(), itertools.repeat(float))
        if len(self.model.expressions_dynamic()):
            yfull_dtype += zip(self.model.expressions_dynamic().keys(), itertools.repeat(float))
        yfull = len(self.y) * [None]
        # loop over simulations
        for n in range(len(self.y)):
            yfull[n] = np.ndarray(len(self.tout[n]), yfull_dtype)
            yfull_view = yfull[n].view(float).reshape((len(yfull[n]), -1))
            n_sp = self.y[n].shape[1]
            n_ob = self.yobs_view[n].shape[1]
            n_ex = self.yexpr_view[n].shape[1]
            yfull_view[:,:n_sp] = self.y[n]
            yfull_view[:,n_sp:n_sp+n_ob] = self.yobs_view[n]
            yfull_view[:,n_sp+n_ob:n_sp+n_ob+n_ex] = self.yexpr_view[n]
        yfull = np.array(yfull)
        return yfull
<commit_msg>Removed simulate.py for future reintroduction<commit_after><|endoftext|>