<commit_before>"""
These classes hold methods to apply general filters to any data type.
By inherritting these classes into the wrapped VTK data structures, a user
can easily apply common filters in an intuitive manner.

Example:

    >>> import vtki
    >>> from vtki import examples
    >>> dataset = examples.load_uniform()
    >>> dataset.set_active_scalar('Spatial Point Data') # Array the filters will use

    >>> # Threshold
    >>> thresh = dataset.threshold([100, 500])
    >>> thresh.plot(scalars='Spatial Point Data')

    >>> # Slice
    >>> slc = dataset.slice()
    >>> slc.plot(scalars='Spatial Point Data')

    >>> # Clip
    >>> clp = dataset.clip(invert=True)
    >>> clp.plot(scalars='Spatial Point Data')

    >>> # Contour
    >>> iso = dataset.contour()
    >>> iso.plot(scalars='Spatial Point Data')

"""
import collections
import numpy as np
import vtk

from vtki.utilities import get_scalar, wrap

NORMALS = {
    'x': [1, 0, 0],
    'y': [0, 1, 0],
    'z': [0, 0, 1],
    '-x': [-1, 0, 0],
    '-y': [0, -1, 0],
    '-z': [0, 0, -1],
}

def _get_output(algorithm, iport=0, iconnection=0, oport=0):
    """A helper to get the algorithm's output and copy input's vtki meta info"""
    ido = algorithm.GetInputDataObject(iport, iconnection)
    data = wrap(algorithm.GetOutputDataObject(oport))
    data.copy_meta_from(ido)
    return data

def _generate_plane(normal, origin):
    """ Returns a vtk.vtkPlane """
    plane = vtk.vtkPlane()
    plane.SetNormal(normal[0], normal[1], normal[2])
    plane.SetOrigin(origin[0], origin[1], origin[2])
    return plane

class DataSetFilters(object):
    """A set of common filters that can be applied to any vtkDataSet"""

    def clip(dataset, normal='x', origin=None, invert=True):
        """
        Clip a dataset by a plane by specifying the origin and normal. If no
        parameters are given the clip will occur in the center of that dataset

        Parameters
        ----------

        dataset : vtk.vtkDataSet object
            Input dataset.

        normal : tuple(float) or str
            Length 3 tuple for the normal vector direction. Can also be specified
            as a string conventional direction such as ``'x'`` for ``(1,0,0)``
            or ``'-x'`` for ``(-1,0,0), etc.

        origin : tuple(float)
            The center (x,y,z) coordinate of the plane on which the clip occurs

        invert : bool
            Flag on whether to flip/invert the clip

        """
        if isinstance(normal, str):
            normal = NORMALS[normal.lower()]
        # find center of data if origin not specified
        if origin is None:
            origin = dataset.center
        # create the plane for clipping
        plane = _generate_plane(normal, origin)
        # run the clip
        alg = vtk.vtkClipDataSet()
        alg.SetInputDataObject(dataset) # Use the grid as the data we desire to cut
        alg.SetClipFunction(plane) # the the cutter to use the plane we made
        alg.SetInsideOut(invert) # invert the clip if needed
        alg.Update() # Perfrom the Cut
        return _get_output(alg)

    def slice(dataset, normal='x', origin=None):
        """Slice a dataset by a plane at the specified origin and normal vector
        orientation. If no origin is specified, the center of the input dataset will
        be used.

        Parameters
        ----------

        dataset : vtk.vtkDataSet object
            Input dataset.

        normal : tuple(float) or str
            Length 3 tuple for the normal vector direction. Can also be specified
            as a string conventional direction such as ``'x'`` for ``(1,0,0)``
            or ``'-x'`` for ``(-1,0,0), etc.

        origin : tuple(float)
            The center (x,y,z) coordinate of the plane on which the slice occurs

        """
        if isinstance(normal, str):
            normal = NORMALS[normal.lower()]
        # find center of data if origin not specified
        if origin is None:
            origin = dataset.center
        # create the plane for clipping
        plane = _generate_plane(normal, origin)
        # create slice
        alg = vtk.vtkCutter() # Construct the cutter object
        alg.SetInputDataObject(dataset) # Use the grid as the data we desire to cut
        alg.SetCutFunction(plane) # the the cutter to use the plane we made
        alg.Update() # Perfrom the Cut
        return _get_output(alg)

    def threshold(dataset, value=None, scalars=None, invert=False, continuous=False,
                  preference='cell'):
        """
        This filter will apply a ``vtkThreshold`` filter to the input dataset and
        return the resulting object. This extracts cells where scalar value in each
        cell satisfies threshold criterion.  If scalars is None, the inputs
        active_scalar is used.

        Parameters
        ----------
        dataset : vtk.vtkDataSet object
            Input dataset.

        value : float or iterable, optional
            Single value or (min, max) to be used for the data threshold.  If
            iterable, then length must be 2. If no value is specified, the
            non-NaN data range will be used to remove any NaN values.

        scalars : str, optional
            Name of scalars to threshold on. Defaults to currently active scalars.

        invert : bool, optional
            If value is a single value, when invert is True cells are kept when
            their values are below parameter "value".  When invert is False
            cells are kept when their value is above the threshold "value".

        continuous : bool, optional
            When True, the continuous interval [minimum cell scalar,
            maxmimum cell scalar] will be used to intersect the threshold bound,
            rather than the set of discrete scalar values from the vertices.

        preference : str, optional
            When scalars is specified, this is the perfered scalar type to search
            for in the dataset.  Must be either 'point' or 'cell'.

        """
        alg = vtk.vtkThreshold()
        alg.SetInputDataObject(dataset)
        # set the scalaras to threshold on
        if scalars is None:
            field, scalars = dataset.active_scalar_info
        else:
            _, field = get_scalar(dataset, scalars, preference=preference, info=True)
        alg.SetInputArrayToProcess(0, 0, 0, field, scalars) # args: (idx, port, connection, field, name)
        # set thresholding parameters
        alg.SetUseContinuousCellRange(continuous)
        # use valid range if no value given
        if value is None:
            value = dataset.get_data_range(scalars)
        # check if value is iterable (if so threshold by min max range like ParaView)
        if isinstance(value, collections.Iterable):
            if len(value) != 2:
                raise RuntimeError('Value range must be length one for a float value or two for min/max; not ({}).'.format(value))
            alg.ThresholdBetween(value[0], value[1])
            # NOTE: Invert for ThresholdBetween is coming in vtk=>8.2.x
            #alg.SetInvert(invert)
        else:
            # just a single value
            if invert:
                alg.ThresholdByLower(value)
            else:
                alg.ThresholdByUpper(value)
        # Run the threshold
        alg.Update()
        return _get_output(alg)

    def outline(dataset, gen_faces=False):
        """Produces an outline of the full extent for the input dataset"""
        alg = vtk.vtkOutlineFilter()
        alg.SetInputDataObject(dataset)
        alg.SetGenerateFaces(gen_faces)
        alg.Update()
        return wrap(alg.GetOutputDataObject(0))

class PointSetFilters(object):
    """Filters that can be applied to point set data objects"""

    def contour(dataset, isosurfaces=10, scalars=None, compute_normals=False,
                compute_gradients=False, compute_scalars=True, preference='point'):
        """Contours an input dataset by an array. ``isosurfaces`` can be an integer
        specifying the number of isosurfaces in the data range or an iterable set of
        values for explicitly setting the isosurfaces.

        Parameters
        ----------
        dataset : vtk.vtkDataSet object
            Input dataset.

        isosurfaces : int or iterable
            Number of isosurfaces to compute across valid data range or an
            iterable of float values to explicitly use as the isosurfaces.

        scalars : str, optional
            Name of scalars to threshold on. Defaults to currently active scalars.

        compute_normals : bool, optional

        compute_gradients : bool, optional
            Desc

        compute_scalars : bool, optional
            Preserves the scalar values that are being contoured

        preference : str, optional
            When scalars is specified, this is the perfered scalar type to search
            for in the dataset.  Must be either 'point' or 'cell'.

        """
        alg = vtk.vtkContourFilter() #vtkMarchingCubes
        alg.SetInputDataObject(dataset)
        alg.SetComputeNormals(compute_normals)
        alg.SetComputeGradients(compute_gradients)
        alg.SetComputeScalars(compute_scalars)
        # set the array to contour on
        #dataset.set_active_scalar(scalars, preference=preference)
        if scalars is None:
            field, scalars = dataset.active_scalar_info
        else:
            _, field = get_scalar(dataset, scalars, preference=preference, info=True)
        # NOTE: only point data is allowed
        if field != 0:
            raise RuntimeError('Can only contour by Point data at this time.')
        alg.SetInputArrayToProcess(0, 0, 0, field, scalars) # args: (idx, port, connection, field, name)
        # set the isosurfaces
        if isinstance(isosurfaces, int):
            # generate values
            alg.GenerateValues(isosurfaces, dataset.get_data_range(scalars))
        elif isinstance(isosurfaces, collections.Iterable):
            alg.SetNumberOfContours(len(isosurfaces))
            for i, val in enumerate(isosurfaces):
                alg.SetValue(i, val)
        else:
            raise RuntimeError('isosurfaces not understood.')
        alg.Update()
        return _get_output(alg)
<commit_msg>Allow contouring by cell scalars<commit_after>"""
These classes hold methods to apply general filters to any data type.
By inherritting these classes into the wrapped VTK data structures, a user
can easily apply common filters in an intuitive manner.

Example:

    >>> import vtki
    >>> from vtki import examples
    >>> dataset = examples.load_uniform()
    >>> dataset.set_active_scalar('Spatial Point Data') # Array the filters will use

    >>> # Threshold
    >>> thresh = dataset.threshold([100, 500])
    >>> thresh.plot(scalars='Spatial Point Data')

    >>> # Slice
    >>> slc = dataset.slice()
    >>> slc.plot(scalars='Spatial Point Data')

    >>> # Clip
    >>> clp = dataset.clip(invert=True)
    >>> clp.plot(scalars='Spatial Point Data')

    >>> # Contour
    >>> iso = dataset.contour()
    >>> iso.plot(scalars='Spatial Point Data')

"""
import collections
import numpy as np
import vtk

from vtki.utilities import get_scalar, wrap

NORMALS = {
    'x': [1, 0, 0],
    'y': [0, 1, 0],
    'z': [0, 0, 1],
    '-x': [-1, 0, 0],
    '-y': [0, -1, 0],
    '-z': [0, 0, -1],
}

def _get_output(algorithm, iport=0, iconnection=0, oport=0):
    """A helper to get the algorithm's output and copy input's vtki meta info"""
    ido = algorithm.GetInputDataObject(iport, iconnection)
    data = wrap(algorithm.GetOutputDataObject(oport))
    data.copy_meta_from(ido)
    return data

def _generate_plane(normal, origin):
    """ Returns a vtk.vtkPlane """
    plane = vtk.vtkPlane()
    plane.SetNormal(normal[0], normal[1], normal[2])
    plane.SetOrigin(origin[0], origin[1], origin[2])
    return plane

class DataSetFilters(object):
    """A set of common filters that can be applied to any vtkDataSet"""

    def clip(dataset, normal='x', origin=None, invert=True):
        """
        Clip a dataset by a plane by specifying the origin and normal. If no
        parameters are given the clip will occur in the center of that dataset

        Parameters
        ----------

        dataset : vtk.vtkDataSet object
            Input dataset.

        normal : tuple(float) or str
            Length 3 tuple for the normal vector direction. Can also be specified
            as a string conventional direction such as ``'x'`` for ``(1,0,0)``
            or ``'-x'`` for ``(-1,0,0), etc.

        origin : tuple(float)
            The center (x,y,z) coordinate of the plane on which the clip occurs

        invert : bool
            Flag on whether to flip/invert the clip

        """
        if isinstance(normal, str):
            normal = NORMALS[normal.lower()]
        # find center of data if origin not specified
        if origin is None:
            origin = dataset.center
        # create the plane for clipping
        plane = _generate_plane(normal, origin)
        # run the clip
        alg = vtk.vtkClipDataSet()
        alg.SetInputDataObject(dataset) # Use the grid as the data we desire to cut
        alg.SetClipFunction(plane) # the the cutter to use the plane we made
        alg.SetInsideOut(invert) # invert the clip if needed
        alg.Update() # Perfrom the Cut
        return _get_output(alg)

    def slice(dataset, normal='x', origin=None):
        """Slice a dataset by a plane at the specified origin and normal vector
        orientation. If no origin is specified, the center of the input dataset will
        be used.

        Parameters
        ----------

        dataset : vtk.vtkDataSet object
            Input dataset.

        normal : tuple(float) or str
            Length 3 tuple for the normal vector direction. Can also be specified
            as a string conventional direction such as ``'x'`` for ``(1,0,0)``
            or ``'-x'`` for ``(-1,0,0), etc.

        origin : tuple(float)
            The center (x,y,z) coordinate of the plane on which the slice occurs

        """
        if isinstance(normal, str):
            normal = NORMALS[normal.lower()]
        # find center of data if origin not specified
        if origin is None:
            origin = dataset.center
        # create the plane for clipping
        plane = _generate_plane(normal, origin)
        # create slice
        alg = vtk.vtkCutter() # Construct the cutter object
        alg.SetInputDataObject(dataset) # Use the grid as the data we desire to cut
        alg.SetCutFunction(plane) # the the cutter to use the plane we made
        alg.Update() # Perfrom the Cut
        return _get_output(alg)

    def threshold(dataset, value=None, scalars=None, invert=False, continuous=False,
                  preference='cell'):
        """
        This filter will apply a ``vtkThreshold`` filter to the input dataset and
        return the resulting object. This extracts cells where scalar value in each
        cell satisfies threshold criterion.  If scalars is None, the inputs
        active_scalar is used.

        Parameters
        ----------
        dataset : vtk.vtkDataSet object
            Input dataset.

        value : float or iterable, optional
            Single value or (min, max) to be used for the data threshold.  If
            iterable, then length must be 2. If no value is specified, the
            non-NaN data range will be used to remove any NaN values.

        scalars : str, optional
            Name of scalars to threshold on. Defaults to currently active scalars.

        invert : bool, optional
            If value is a single value, when invert is True cells are kept when
            their values are below parameter "value".  When invert is False
            cells are kept when their value is above the threshold "value".

        continuous : bool, optional
            When True, the continuous interval [minimum cell scalar,
            maxmimum cell scalar] will be used to intersect the threshold bound,
            rather than the set of discrete scalar values from the vertices.

        preference : str, optional
            When scalars is specified, this is the perfered scalar type to search
            for in the dataset.  Must be either 'point' or 'cell'.

        """
        alg = vtk.vtkThreshold()
        alg.SetInputDataObject(dataset)
        # set the scalaras to threshold on
        if scalars is None:
            field, scalars = dataset.active_scalar_info
        else:
            _, field = get_scalar(dataset, scalars, preference=preference, info=True)
        alg.SetInputArrayToProcess(0, 0, 0, field, scalars) # args: (idx, port, connection, field, name)
        # set thresholding parameters
        alg.SetUseContinuousCellRange(continuous)
        # use valid range if no value given
        if value is None:
            value = dataset.get_data_range(scalars)
        # check if value is iterable (if so threshold by min max range like ParaView)
        if isinstance(value, collections.Iterable):
            if len(value) != 2:
                raise RuntimeError('Value range must be length one for a float value or two for min/max; not ({}).'.format(value))
            alg.ThresholdBetween(value[0], value[1])
            # NOTE: Invert for ThresholdBetween is coming in vtk=>8.2.x
            #alg.SetInvert(invert)
        else:
            # just a single value
            if invert:
                alg.ThresholdByLower(value)
            else:
                alg.ThresholdByUpper(value)
        # Run the threshold
        alg.Update()
        return _get_output(alg)

    def outline(dataset, gen_faces=False):
        """Produces an outline of the full extent for the input dataset"""
        alg = vtk.vtkOutlineFilter()
        alg.SetInputDataObject(dataset)
        alg.SetGenerateFaces(gen_faces)
        alg.Update()
        return wrap(alg.GetOutputDataObject(0))

class PointSetFilters(object):
    """Filters that can be applied to point set data objects"""

    def contour(dataset, isosurfaces=10, scalars=None, compute_normals=False,
                compute_gradients=False, compute_scalars=True, preference='point'):
        """Contours an input dataset by an array. ``isosurfaces`` can be an integer
        specifying the number of isosurfaces in the data range or an iterable set of
        values for explicitly setting the isosurfaces.

        Parameters
        ----------
        dataset : vtk.vtkDataSet object
            Input dataset.

        isosurfaces : int or iterable
            Number of isosurfaces to compute across valid data range or an
            iterable of float values to explicitly use as the isosurfaces.

        scalars : str, optional
            Name of scalars to threshold on. Defaults to currently active scalars.

        compute_normals : bool, optional

        compute_gradients : bool, optional
            Desc

        compute_scalars : bool, optional
            Preserves the scalar values that are being contoured

        preference : str, optional
            When scalars is specified, this is the perfered scalar type to search
            for in the dataset.  Must be either 'point' or 'cell'.

        """
        alg = vtk.vtkContourFilter() #vtkMarchingCubes
        alg.SetInputDataObject(dataset)
        alg.SetComputeNormals(compute_normals)
        alg.SetComputeGradients(compute_gradients)
        alg.SetComputeScalars(compute_scalars)
        # set the array to contour on
        #dataset.set_active_scalar(scalars, preference=preference)
        if scalars is None:
            field, scalars = dataset.active_scalar_info
        else:
            _, field = get_scalar(dataset, scalars, preference=preference, info=True)
        # NOTE: only point data is allowed? well cells works but seems buggy?
        # if field != 0:
        #     raise RuntimeError('Can only contour by Point data at this time.')
        alg.SetInputArrayToProcess(0, 0, 0, field, scalars) # args: (idx, port, connection, field, name)
        # set the isosurfaces
        if isinstance(isosurfaces, int):
            # generate values
            alg.GenerateValues(isosurfaces, dataset.get_data_range(scalars))
        elif isinstance(isosurfaces, collections.Iterable):
            alg.SetNumberOfContours(len(isosurfaces))
            for i, val in enumerate(isosurfaces):
                alg.SetValue(i, val)
        else:
            raise RuntimeError('isosurfaces not understood.')
        alg.Update()
        return _get_output(alg)
<|endoftext|>


<commit_before>#!/usr/bin/env python
###################################################################################
#
# Copyright (c)     2010-2016   Motsai
#
# The MIT License (MIT)
#
# 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.
#
###################################################################################

import logging
import time
import unittest

import neblinaUtilities
from neblina import *
from neblinaBLE import NeblinaBLE, NeblinaDelegate
from neblinaError import *
from neblinaResponsePacket import NebResponsePacket
from neblinaUtilities import NebUtilities
from test import neblinaTestUtilities

###################################################################################

def getSuite(deviceAddress):
    BLEIntegrationTest.deviceAddress = deviceAddress
    return unittest.TestLoader().loadTestsFromTestCase(BLEIntegrationTest)

###################################################################################

class BLEIntegrationTest(unittest.TestCase):
    setupHasAlreadyRun = False
    deviceAddress = None

    def setUp(self):
        if not self.deviceAddress:
            logging.warn("No Device Address specified. Skipping.")
            raise unittest.SkipTest1

        # Give it a break between each test
        time.sleep(2)

        self.ble = NeblinaBLE()
        self.ble.open(self.deviceAddress)
        if not self.ble.isOpened():
            self.fail("Unable to connect to BLE device.")

    def tearDown(self):
        self.ble.stopEverything()
        self.ble.close(self.deviceAddress)

    def testMotionEngine(self):
        testInputVectorPacketList = neblinaTestUtilities.csvVectorsToList('motEngineInputs.csv')
        testOutputVectorPacketList = neblinaTestUtilities.csvVectorsToList('motEngineOutputs.csv')
        self.ble.debugUnitTestEnable(True)
        for idx, packetBytes in enumerate(testInputVectorPacketList):
            # logging.debug('Sending {0} to stream'.format(binascii.hexlify(packetBytes)))
            packet = self.ble.debugUnitTestSendBytes(packetBytes)
            self.assertEqual(testOutputVectorPacketList[idx], packet.stringEncode())
            print("Sent %d testVectors out of %d\r" % (idx + 1, len(testInputVectorPacketList)), end="", flush=True)
        print("\r")
        self.ble.debugUnitTestEnable(False)

    def testMotionStreamEuler(self):
        self.ble.motionSetDownsample(40)
        self.ble.motionStream(Commands.Motion.EulerAngle, 100)

    def testMotionStreamIMU(self):
        self.ble.motionStream(Commands.Motion.IMU, 100)

    def testMotionStreamMAG(self):
        self.ble.motionStream(Commands.Motion.MAG, 100)

    def testMotionStreamQuaternion(self):
        self.ble.motionStream(Commands.Motion.Quaternion, 100)

    def testVersion(self):
        versions = self.ble.debugFWVersions()
        logging.info(versions)
        self.assertEqual(versions.apiRelease, 1)
        for i in range(0, 2):
            self.assertNotEqual(versions.bleFWVersion[i], 255)
            self.assertNotEqual(versions.mcuFWVersion[i], 255)

    def testMEMSComm(self):
        logging.debug('Checking communication with the LSM9DS1 chip by getting the temperature...')
        temp = self.ble.getTemperature()
        logging.info("Board Temperature: {0} degrees (Celsius)".format(temp))

    def testBattery(self):
        batteryLevel = self.ble.getBatteryLevel()
        logging.info("Board Battery: {0}\%".format(batteryLevel))

    def testLEDs(self):
        for i in range(0, 10):
            self.ble.setLEDs(([0, 1], [1, 0]))
            self.ble.setLEDs(([0, 0], [1, 1]))
        for i in range(0, 10):
            self.ble.setLEDs(([0, 1], [1, 1]))
            self.ble.setLEDs(([0, 0], [1, 0]))

    def testEEPROM(self):
        # Verify EEPROM Read/Write limit
        with self.assertRaises(AssertionError):
            self.ble.EEPROMRead(-1)
            self.ble.EEPROMRead(256)
            self.ble.EEPROMWrite(-1, "0xFF")
            self.ble.EEPROMWrite(256, "0xFF")

        # Test Write/Read. Make sure to store current bytes for each page and rewrite it after test.
        num = 256
        storeBytes = []
        # Store EEPROM state
        for i in range(0, num):
            dataBytes = self.ble.EEPROMRead(i)
            storeBytes.append(dataBytes)
            logging.debug("EEPROMRead store {0}: {1}".format(i, dataBytes))
        # Test write/read
        for i in range(0, num):
            dataBytes = bytes([i, i, i, i, i, i, i, i])
            logging.debug("EEPROMWrite {0} : {1}".format(i, dataBytes))
            self.ble.EEPROMWrite(i, dataBytes)
        for i in range(0, num):
            dataBytes = self.ble.EEPROMRead(i)
            logging.debug("EEPROMRead {0} : {1}".format(i, dataBytes))
            for j in range(0, 8):
                self.assertEqual(dataBytes[j], i)
        for i in range(0, num):
            logging.debug("EEPROMWrite store {0} : {1}".format(i, storeBytes[i]))
            self.ble.EEPROMWrite(i, storeBytes[i])
        for i in range(0, num):
            dataBytes = self.ble.EEPROMRead(i)
            logging.debug("EEPROMRead store {0} : {1}".format(i, dataBytes))
            self.assertTrue(dataBytes == storeBytes[i])

    def testMotionDownsample(self):
        numPacket = 2
        for i in range(1, 51):
            factor = i * 20
            logging.info("Downsample factor : {0}".format(factor))
            self.ble.motionSetDownsample(factor)
            start = time.time()
            self.ble.motionStream(Commands.Motion.EulerAngle, numPacket)
            end = time.time()
            duration = end - start
            logging.info("Downsample factor {0} took {1} seconds".format(factor, duration))
            desiredDuration = 1/(1000/factor)*numPacket
            #self.assertAlmostEqual(duration, desiredDuration, delta=0.02)

        with self.assertRaises(AssertionError):
            self.ble.motionSetDownsample(1)
            self.ble.motionSetDownsample(1001)
        self.ble.motionSetDownsample(20)  # Reset to default

    def testMotionAccRange(self):
        with self.assertRaises(AssertionError):
            self.ble.motionSetAccFullScale(-1)
            self.ble.motionSetAccFullScale(17)
        self.ble.motionSetAccFullScale(2)
        self.ble.motionSetAccFullScale(4)
        self.ble.motionSetAccFullScale(8)
        self.ble.motionSetAccFullScale(16)
        self.ble.motionSetAccFullScale(8)   # Reset to default

    def testMotionState(self):
        self.ble.motionStopStreams()
        motionState = self.ble.motionGetStates()
        self.assertFalse(motionState.distance)
        self.assertFalse(motionState.force)
        self.assertFalse(motionState.euler)
        self.assertFalse(motionState.quaternion)
        self.assertFalse(motionState.imuData)
        self.assertFalse(motionState.motion)
        self.assertFalse(motionState.steps)
        self.assertFalse(motionState.magData)
        self.assertFalse(motionState.sitStand)
        self.assertFalse(motionState.sitStand)

    def testFlashErase(self):
        self.ble.flashErase()
        num = self.ble.flashGetSessions()
        self.assertEqual(num, 0)

    def testFlashRecord(self):
        with self.assertRaises(AssertionError):
            self.ble.flashRecord(1, Commands.Motion.Quaternion)

    def testStreamExtreme(self):
        self.ble.flashErase()

        streamToUse = 10

        self.ble.motionStopAllStreams()
        self.ble.motionSetDownsample(40)
        self.streamIfRequired(1,  Commands.Motion.IMU, streamToUse)
        self.streamIfRequired(2,  Commands.Motion.MAG, streamToUse)
        self.streamIfRequired(3,  Commands.Motion.Quaternion, streamToUse)
        self.streamIfRequired(4,  Commands.Motion.EulerAngle, streamToUse)
        self.streamIfRequired(5,  Commands.Motion.ExtForce, streamToUse)
        self.streamIfRequired(6,  Commands.Motion.Pedometer, streamToUse)
        self.streamIfRequired(7,  Commands.Motion.SittingStanding, streamToUse)
        self.streamIfRequired(8,  Commands.Motion.FingerGesture, streamToUse)
        self.streamIfRequired(9,  Commands.Motion.RotationInfo, streamToUse)
        self.streamIfRequired(10, Commands.Motion.MotionState, streamToUse)
        self.ble.flashRecordStart()

        count = 0
        while count < 100:
            self.ble.receivePacket()
            count = count + 1

        self.ble.flashRecordStop()
        self.ble.motionStopAllStreams()

        num = self.ble.flashGetSessions()
        self.assertEqual(num, 1)

        packet = self.ble.flashGetSessionInfo(0)
        self.assertGreater(packet.sessionLength, 0)

    def streamIfRequired(self, id, streamingType, streamToUse):
        (lambda: None, lambda: self.ble.motionStartStream(streamingType))[streamToUse >= id]()
<commit_msg>Removed testMotionEngine.<commit_after>#!/usr/bin/env python
###################################################################################
#
# Copyright (c)     2010-2016   Motsai
#
# The MIT License (MIT)
#
# 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.
#
###################################################################################

import logging
import time
import unittest

import neblinaUtilities
from neblina import *
from neblinaBLE import NeblinaBLE, NeblinaDelegate
from neblinaError import *
from neblinaResponsePacket import NebResponsePacket
from neblinaUtilities import NebUtilities
from test import neblinaTestUtilities

###################################################################################

def getSuite(deviceAddress):
    BLEIntegrationTest.deviceAddress = deviceAddress
    return unittest.TestLoader().loadTestsFromTestCase(BLEIntegrationTest)

###################################################################################

class BLEIntegrationTest(unittest.TestCase):
    setupHasAlreadyRun = False
    deviceAddress = None

    def setUp(self):
        if not self.deviceAddress:
            logging.warn("No Device Address specified. Skipping.")
            raise unittest.SkipTest

        # Give it a break between each test
        time.sleep(2)

        self.ble = NeblinaBLE()
        self.ble.open(self.deviceAddress)
        if not self.ble.isOpened():
            self.fail("Unable to connect to BLE device.")

    def tearDown(self):
        self.ble.stopEverything()
        self.ble.close(self.deviceAddress)

    # def testMotionEngine(self):
    #     testInputVectorPacketList = neblinaTestUtilities.csvVectorsToList('motEngineInputs.csv')
    #     testOutputVectorPacketList = neblinaTestUtilities.csvVectorsToList('motEngineOutputs.csv')
    #     self.ble.debugUnitTestEnable(True)
    #     for idx, packetBytes in enumerate(testInputVectorPacketList):
    #         # logging.debug('Sending {0} to stream'.format(binascii.hexlify(packetBytes)))
    #         packet = self.ble.debugUnitTestSendBytes(packetBytes)
    #         self.assertEqual(testOutputVectorPacketList[idx], packet.stringEncode())
    #         print("Sent %d testVectors out of %d\r" % (idx + 1, len(testInputVectorPacketList)), end="", flush=True)
    #     print("\r")
    #     self.ble.debugUnitTestEnable(False)

    def testMotionStreamEuler(self):
        self.ble.motionSetDownsample(40)
        self.ble.motionStream(Commands.Motion.EulerAngle, 100)

    def testMotionStreamIMU(self):
        self.ble.motionStream(Commands.Motion.IMU, 100)

    def testMotionStreamMAG(self):
        self.ble.motionStream(Commands.Motion.MAG, 100)

    def testMotionStreamQuaternion(self):
        self.ble.motionStream(Commands.Motion.Quaternion, 100)

    def testVersion(self):
        versions = self.ble.debugFWVersions()
        logging.info(versions)
        self.assertEqual(versions.apiRelease, 1)
        for i in range(0, 2):
            self.assertNotEqual(versions.bleFWVersion[i], 255)
            self.assertNotEqual(versions.mcuFWVersion[i], 255)

    def testMEMSComm(self):
        logging.debug('Checking communication with the LSM9DS1 chip by getting the temperature...')
        temp = self.ble.getTemperature()
        logging.info("Board Temperature: {0} degrees (Celsius)".format(temp))

    def testBattery(self):
        batteryLevel = self.ble.getBatteryLevel()
        logging.info("Board Battery: {0}\%".format(batteryLevel))

    def testLEDs(self):
        for i in range(0, 10):
            self.ble.setLEDs(([0, 1], [1, 0]))
            self.ble.setLEDs(([0, 0], [1, 1]))
        for i in range(0, 10):
            self.ble.setLEDs(([0, 1], [1, 1]))
            self.ble.setLEDs(([0, 0], [1, 0]))

    def testEEPROM(self):
        # Verify EEPROM Read/Write limit
        with self.assertRaises(AssertionError):
            self.ble.EEPROMRead(-1)
            self.ble.EEPROMRead(256)
            self.ble.EEPROMWrite(-1, "0xFF")
            self.ble.EEPROMWrite(256, "0xFF")

        # Test Write/Read. Make sure to store current bytes for each page and rewrite it after test.
        num = 256
        storeBytes = []
        # Store EEPROM state
        for i in range(0, num):
            dataBytes = self.ble.EEPROMRead(i)
            storeBytes.append(dataBytes)
            logging.debug("EEPROMRead store {0}: {1}".format(i, dataBytes))
        # Test write/read
        for i in range(0, num):
            dataBytes = bytes([i, i, i, i, i, i, i, i])
            logging.debug("EEPROMWrite {0} : {1}".format(i, dataBytes))
            self.ble.EEPROMWrite(i, dataBytes)
        for i in range(0, num):
            dataBytes = self.ble.EEPROMRead(i)
            logging.debug("EEPROMRead {0} : {1}".format(i, dataBytes))
            for j in range(0, 8):
                self.assertEqual(dataBytes[j], i)
        for i in range(0, num):
            logging.debug("EEPROMWrite store {0} : {1}".format(i, storeBytes[i]))
            self.ble.EEPROMWrite(i, storeBytes[i])
        for i in range(0, num):
            dataBytes = self.ble.EEPROMRead(i)
            logging.debug("EEPROMRead store {0} : {1}".format(i, dataBytes))
            self.assertTrue(dataBytes == storeBytes[i])

    def testMotionDownsample(self):
        numPacket = 2
        for i in range(1, 51):
            factor = i * 20
            logging.info("Downsample factor : {0}".format(factor))
            self.ble.motionSetDownsample(factor)
            start = time.time()
            self.ble.motionStream(Commands.Motion.EulerAngle, numPacket)
            end = time.time()
            duration = end - start
            logging.info("Downsample factor {0} took {1} seconds".format(factor, duration))
            desiredDuration = 1/(1000/factor)*numPacket
            #self.assertAlmostEqual(duration, desiredDuration, delta=0.02)

        with self.assertRaises(AssertionError):
            self.ble.motionSetDownsample(1)
            self.ble.motionSetDownsample(1001)
        self.ble.motionSetDownsample(20)  # Reset to default

    def testMotionAccRange(self):
        with self.assertRaises(AssertionError):
            self.ble.motionSetAccFullScale(-1)
            self.ble.motionSetAccFullScale(17)
        self.ble.motionSetAccFullScale(2)
        self.ble.motionSetAccFullScale(4)
        self.ble.motionSetAccFullScale(8)
        self.ble.motionSetAccFullScale(16)
        self.ble.motionSetAccFullScale(8)   # Reset to default

    def testMotionState(self):
        self.ble.motionStopStreams()
        motionState = self.ble.motionGetStates()
        self.assertFalse(motionState.distance)
        self.assertFalse(motionState.force)
        self.assertFalse(motionState.euler)
        self.assertFalse(motionState.quaternion)
        self.assertFalse(motionState.imuData)
        self.assertFalse(motionState.motion)
        self.assertFalse(motionState.steps)
        self.assertFalse(motionState.magData)
        self.assertFalse(motionState.sitStand)
        self.assertFalse(motionState.sitStand)

    def testFlashErase(self):
        self.ble.flashErase()
        num = self.ble.flashGetSessions()
        self.assertEqual(num, 0)

    def testFlashRecord(self):
        with self.assertRaises(AssertionError):
            self.ble.flashRecord(1, Commands.Motion.Quaternion)

    def testStreamExtreme(self):
        self.ble.flashErase()

        streamToUse = 10

        self.ble.motionStopAllStreams()
        self.ble.motionSetDownsample(40)
        self.streamIfRequired(1,  Commands.Motion.IMU, streamToUse)
        self.streamIfRequired(2,  Commands.Motion.MAG, streamToUse)
        self.streamIfRequired(3,  Commands.Motion.Quaternion, streamToUse)
        self.streamIfRequired(4,  Commands.Motion.EulerAngle, streamToUse)
        self.streamIfRequired(5,  Commands.Motion.ExtForce, streamToUse)
        self.streamIfRequired(6,  Commands.Motion.Pedometer, streamToUse)
        self.streamIfRequired(7,  Commands.Motion.SittingStanding, streamToUse)
        self.streamIfRequired(8,  Commands.Motion.FingerGesture, streamToUse)
        self.streamIfRequired(9,  Commands.Motion.RotationInfo, streamToUse)
        self.streamIfRequired(10, Commands.Motion.MotionState, streamToUse)
        self.ble.flashRecordStart()

        count = 0
        while count < 100:
            self.ble.receivePacket()
            count = count + 1

        self.ble.flashRecordStop()
        self.ble.motionStopAllStreams()

        num = self.ble.flashGetSessions()
        self.assertEqual(num, 1)

        packet = self.ble.flashGetSessionInfo(0)
        self.assertGreater(packet.sessionLength, 0)

    def streamIfRequired(self, id, streamingType, streamToUse):
        (lambda: None, lambda: self.ble.motionStartStream(streamingType))[streamToUse >= id]()
<|endoftext|>


<commit_before>import sys

class Stdout(object):
    TAG_CODE = 'code'
    def __init__(self, area):
        # I am selecting from the beginning to the start of a line
        # below to the insert cursor so i add a line
        # to the end of the line below to the cursor then
        # the code_mark will be after the sel mark.
        # this was a pain in the ass to notice.
        self.area = area
        self.area.mark_set('code_mark', 'insert')

    def write(self, data):
        index0 = self.area.index('code_mark')
        self.area.insert('code_mark', data)
        self.area.tag_add(self.TAG_CODE, index0, 'code_mark')

        self.area.see('insert')

    def __eq__(self, other):
        return self.area == other

class Transmitter(object):
    def __init__(self, default):
        self.base    = [default]
        self.default = default

    def restore(self):
        del self.base[:]
        self.base.append(self.default)

    def append(self, fd):
        self.base.append(fd)

    def remove(self, fd):
        self.base.remove(fd)

    def write(self, data):
        for ind in self.base:
            ind.write(data)

def echo(data):
    """

    """

    sys.stdout.write(data)

<commit_msg>Adding docs.<commit_after>"""
This module implements the scheme of output target for vy. Plugins that demand writting to
sys.stdout would write to sys.stdout and have the content dispatched to a sequence of
objects that have a write method.
"""

import sys

class Stdout(object):
    """
    This class is used to wrap an AreaVi widget to be used as stdout channel.
    """

    TAG_CODE = 'code'
    def __init__(self, area):
        # I am selecting from the beginning to the start of a line
        # below to the insert cursor so i add a line
        # to the end of the line below to the cursor then
        # the code_mark will be after the sel mark.
        # this was a pain in the ass to notice.
        self.area = area
        self.area.mark_set('code_mark', 'insert')

    def write(self, data):
        """
        This method is called to write data to the AreaVi widget.
        """

        index0 = self.area.index('code_mark')
        self.area.insert('code_mark', data)
        self.area.tag_add(self.TAG_CODE, index0, 'code_mark')
        self.area.see('insert')

    def __eq__(self, other):
        return self.area == other

class Transmitter(object):
    """
    This class would replace sys.stdout. It is used to dispatch
    data that is written to sys.stdout, the data is dispatched to its
    child objects that have a write method.
    """

    def __init__(self, default):
        self.base    = [default]
        self.default = default

    def restore(self):
        """
        It clears all children and restores the default
        child.
        """

        del self.base[:]
        self.base.append(self.default)

    def append(self, fd):
        """
        It appends a new child.
        """

        self.base.append(fd)

    def remove(self, fd):
        """
        It removes a given child.
        """

        self.base.remove(fd)

    def write(self, data):
        """
        This method is used to dispatch data to the
        children.
        """

        for ind in self.base:
            ind.write(data)

def echo(data):
    """
    It writes data to sys.stdout.
    """

    sys.stdout.write(data)

<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = 'maxim'

import os
import tensorflow as tf

from nn_ops import ACTIVATIONS, COST_FUNCTIONS, dropout, batch_normalization

from model import Model
from util import *

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
CPU_ONLY = False

class NeuralNetworkModel(Model):
  def __init__(self, **params):
    Model.__init__(self, **params)

    self._batch_size = params.get('batch_size', 1024)
    self._epochs = params.get('epochs', 80)
    self._layers = params.get('layers', [])
    self._learning_rate = params.get('learning_rate', 0.001)
    self._init_sigma = params.get('init_sigma', 0.001)
    self._lambda = params.get('lambda', 0.005)
    self._cost_func = COST_FUNCTIONS[params.get('cost_func', 'l2')]

    self._graph = None
    self._session = None
    self._compile()

  def _compile(self):
    with tf.Graph().as_default() as self._graph:
      x = tf.placeholder(tf.float32, shape=[None, self._features], name='x')
      y = tf.placeholder(tf.float32, shape=[None], name='y')
      mode = tf.placeholder(tf.string, name='mode')

      init = lambda shape: tf.random_normal(shape=shape) * self._init_sigma

      layer = x
      dimension = self._features
      reg = 0
      for idx, layer_params in enumerate(self._layers):
        with tf.variable_scope('l_%d' % idx):
          size = layer_params.get('size', 50)
          W = tf.Variable(init([dimension, size]), name='W%d' % idx)
          b = tf.Variable(init([size]), name='b%d' % idx)
          layer = tf.matmul(layer, W) + b

          batchnorm = layer_params.get('batchnorm', False)
          if batchnorm:
            batch_normalization(layer, tf.equal(mode, 'train'))

          activation_func = ACTIVATIONS[layer_params.get('activation_func', 'relu')]
          layer = activation_func(layer)

          dropout_prob = layer_params.get('dropout', 0.5)
          layer = dropout(layer, tf.equal(mode, 'train'), keep_prob=dropout_prob)

          reg += self._lambda * tf.nn.l2_loss(W)
          dimension = size

      with tf.variable_scope('l_out'):
        W_out = tf.Variable(init([dimension, 1]), name='W')
        b_out = tf.Variable(init([1]), name='b')
        output_layer = tf.matmul(layer, W_out) + b_out
        reg += self._lambda * tf.nn.l2_loss(W_out)

      cost = self._cost_func(output_layer, y) + reg
      optimizer = tf.train.AdamOptimizer(self._learning_rate).minimize(cost)

      init = tf.global_variables_initializer()

    self._x = x
    self._y = y
    self._mode = mode
    self._output_layer = output_layer
    self._cost = cost
    self._optimizer = optimizer
    self._init = init

  def session(self):
    assert self._graph is not None
    config = tf.ConfigProto(device_count={'GPU': 0}) if CPU_ONLY else tf.ConfigProto()
    config.gpu_options.allow_growth = True  # https://github.com/vijayvee/Recursive-neural-networks-TensorFlow/issues/1
    self._session = tf.Session(graph=self._graph, config=config)
    return self._session

  def fit(self, train):
    assert self._session is not None
    debug('Start training')
    self._session.run(self._init)
    while train.epochs_completed < self._epochs:
      batch_x, batch_y = train.next_batch(self._batch_size)
      _, cost_ = self._session.run([self._optimizer, self._cost],
                                   feed_dict={self._x: batch_x, self._y: batch_y, self._mode: 'train'})
      if train.just_completed and train.epochs_completed % 10 == 0:
        info('Epoch: %2d cost=%.6f' % (train.epochs_completed, cost_))
    debug('Training completed')

  def predict(self, test_x):
    return self._session.run(self._output_layer, feed_dict={self._x: test_x, self._mode: 'test'}).reshape((-1,))

  def save(self, dest_dir):
    path = os.path.join(dest_dir, 'session.data')
    saver = tf.train.Saver()
    saver.save(self._session, path)

  def restore(self, source_dir):
    path = os.path.join(source_dir, 'session.data')
    saver = tf.train.Saver()
    saver.restore(self._session, path)
<commit_msg>fix clashing variables<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = 'maxim'

import os
import tensorflow as tf

from nn_ops import ACTIVATIONS, COST_FUNCTIONS, dropout, batch_normalization

from model import Model
from util import *

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
CPU_ONLY = False

class NeuralNetworkModel(Model):
  def __init__(self, **params):
    Model.__init__(self, **params)

    self._batch_size = params.get('batch_size', 1024)
    self._epochs = params.get('epochs', 80)
    self._layers = params.get('layers', [])
    self._learning_rate = params.get('learning_rate', 0.001)
    self._init_sigma = params.get('init_sigma', 0.001)
    self._lambda = params.get('lambda', 0.005)
    self._cost_func = COST_FUNCTIONS[params.get('cost_func', 'l2')]

    self._graph = None
    self._session = None
    self._compile()

  def _compile(self):
    with tf.Graph().as_default() as self._graph:
      x = tf.placeholder(tf.float32, shape=[None, self._features], name='x')
      y = tf.placeholder(tf.float32, shape=[None], name='y')
      mode = tf.placeholder(tf.string, name='mode')

      rand_init = lambda shape: tf.random_normal(shape=shape, stddev=self._init_sigma)

      layer = x
      dimension = self._features
      reg = 0
      for idx, layer_params in enumerate(self._layers):
        with tf.variable_scope('l_%d' % idx):
          size = layer_params.get('size', 50)
          W = tf.Variable(rand_init([dimension, size]), name='W%d' % idx)
          b = tf.Variable(rand_init([size]), name='b%d' % idx)
          layer = tf.matmul(layer, W) + b

          batchnorm = layer_params.get('batchnorm', False)
          if batchnorm:
            batch_normalization(layer, tf.equal(mode, 'train'))

          activation_func = ACTIVATIONS[layer_params.get('activation_func', 'relu')]
          layer = activation_func(layer)

          dropout_prob = layer_params.get('dropout', 0.5)
          layer = dropout(layer, tf.equal(mode, 'train'), keep_prob=dropout_prob)

          reg += self._lambda * tf.nn.l2_loss(W)
          dimension = size

      with tf.variable_scope('l_out'):
        W_out = tf.Variable(rand_init([dimension, 1]), name='W')
        b_out = tf.Variable(rand_init([1]), name='b')
        output_layer = tf.matmul(layer, W_out) + b_out
        reg += self._lambda * tf.nn.l2_loss(W_out)

      cost = self._cost_func(output_layer, y) + reg
      optimizer = tf.train.AdamOptimizer(self._learning_rate).minimize(cost)

      init = tf.global_variables_initializer()

    self._x = x
    self._y = y
    self._mode = mode
    self._output_layer = output_layer
    self._cost = cost
    self._optimizer = optimizer
    self._init = init

  def session(self):
    assert self._graph is not None
    config = tf.ConfigProto(device_count={'GPU': 0}) if CPU_ONLY else tf.ConfigProto()
    config.gpu_options.allow_growth = True  # https://github.com/vijayvee/Recursive-neural-networks-TensorFlow/issues/1
    self._session = tf.Session(graph=self._graph, config=config)
    return self._session

  def fit(self, train):
    assert self._session is not None
    debug('Start training')
    self._session.run(self._init)
    while train.epochs_completed < self._epochs:
      batch_x, batch_y = train.next_batch(self._batch_size)
      _, cost_ = self._session.run([self._optimizer, self._cost],
                                   feed_dict={self._x: batch_x, self._y: batch_y, self._mode: 'train'})
      if train.just_completed and train.epochs_completed % 10 == 0:
        info('Epoch: %2d cost=%.6f' % (train.epochs_completed, cost_))
    debug('Training completed')

  def predict(self, test_x):
    return self._session.run(self._output_layer, feed_dict={self._x: test_x, self._mode: 'test'}).reshape((-1,))

  def save(self, dest_dir):
    path = os.path.join(dest_dir, 'session.data')
    saver = tf.train.Saver()
    saver.save(self._session, path)

  def restore(self, source_dir):
    path = os.path.join(source_dir, 'session.data')
    saver = tf.train.Saver()
    saver.restore(self._session, path)
<|endoftext|>


<commit_before>from __future__ import unicode_literals

from django.contrib import admin

from waffle.models import Flag, Sample, Switch

def enable_for_all(ma, request, qs):
    # Iterate over all objects to cause cache invalidation.
    for f in qs.all():
        f.everyone = True
        f.save()
enable_for_all.short_description = 'Enable selected flags for everyone.'

def disable_for_all(ma, request, qs):
    # Iterate over all objects to cause cache invalidation.
    for f in qs.all():
        f.everyone = False
        f.save()
disable_for_all.short_description = 'Disable selected flags for everyone.'

def delete_flags(ma, request, qs):
    # Iterate over all objects to cause cache invalidation.
    for f in qs.all():
        f.delete()
delete_flags.short_description = 'Delete the selected flags.'

class FlagAdmin(admin.ModelAdmin):
    actions = [enable_for_all, disable_for_all, delete_flags]
    date_hierarchy = 'created'
    list_display = ('name', 'note', 'everyone', 'percent', 'superusers',
                    'staff', 'authenticated', 'languages')
    list_filter = ('everyone', 'superusers', 'staff', 'authenticated')
    raw_id_fields = ('users', 'groups')
    ordering = ('-id',)

    def get_actions(self, request):
        actions = super(FlagAdmin, self).get_actions(request)
        if 'delete_selected' in actions:
            del actions['delete_selected']
        return actions

def enable_switches(ma, request, qs):
    for switch in qs:
        switch.active = True
        switch.save()
enable_switches.short_description = 'Enable the selected switches.'

def disable_switches(ma, request, qs):
    for switch in qs:
        switch.active = False
        switch.save()
disable_switches.short_description = 'Disable the selected switches.'

class SwitchAdmin(admin.ModelAdmin):
    actions = [enable_switches, disable_switches]
    date_hierarchy = 'created'
    list_display = ('name', 'active', 'note', 'created', 'modified')
    list_filter = ('active',)
    ordering = ('-id',)

class SampleAdmin(admin.ModelAdmin):
    date_hierarchy = 'created'
    list_display = ('name', 'percent', 'note', 'created', 'modified')
    ordering = ('-id',)

admin.site.register(Flag, FlagAdmin)
admin.site.register(Sample, SampleAdmin)
admin.site.register(Switch, SwitchAdmin)
<commit_msg>Use custom delete actions everywhere<commit_after>from __future__ import unicode_literals

from django.contrib import admin

from waffle.models import Flag, Sample, Switch

class BaseAdmin(admin.ModelAdmin):
    def get_actions(self, request):
        actions = super(BaseAdmin, self).get_actions(request)
        if 'delete_selected' in actions:
            del actions['delete_selected']
        return actions

def enable_for_all(ma, request, qs):
    # Iterate over all objects to cause cache invalidation.
    for f in qs.all():
        f.everyone = True
        f.save()
enable_for_all.short_description = 'Enable selected flags for everyone.'

def disable_for_all(ma, request, qs):
    # Iterate over all objects to cause cache invalidation.
    for f in qs.all():
        f.everyone = False
        f.save()
disable_for_all.short_description = 'Disable selected flags for everyone.'

def delete_individually(ma, request, qs):
    # Iterate over all objects to cause cache invalidation.
    for f in qs.all():
        f.delete()
delete_individually.short_description = 'Delete selected.'

class FlagAdmin(BaseAdmin):
    actions = [enable_for_all, disable_for_all, delete_individually]
    list_display = ('name', 'note', 'everyone', 'percent', 'superusers',
                    'staff', 'authenticated', 'languages')
    list_filter = ('everyone', 'superusers', 'staff', 'authenticated')
    raw_id_fields = ('users', 'groups')
    ordering = ('-id',)

def enable_switches(ma, request, qs):
    for switch in qs:
        switch.active = True
        switch.save()
enable_switches.short_description = 'Enable the selected switches.'

def disable_switches(ma, request, qs):
    for switch in qs:
        switch.active = False
        switch.save()
disable_switches.short_description = 'Disable the selected switches.'

class SwitchAdmin(BaseAdmin):
    actions = [enable_switches, disable_switches, delete_individually]
    list_display = ('name', 'active', 'note', 'created', 'modified')
    list_filter = ('active',)
    ordering = ('-id',)

class SampleAdmin(BaseAdmin):
    actions = [delete_individually]
    list_display = ('name', 'percent', 'note', 'created', 'modified')
    ordering = ('-id',)

admin.site.register(Flag, FlagAdmin)
admin.site.register(Sample, SampleAdmin)
admin.site.register(Switch, SwitchAdmin)
<|endoftext|>


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

from openerp.osv import fields, osv
from openerp.tools.translate import _

from datetime import datetime

class account_move_reversal(osv.Model):

    _inherit = 'account.move'

    def button_reverse_move(self, cr, uid, ids, context=None):
        moves = self.browse(cr, uid, ids, context=context)
        context['active_ids'] = [move.id for move in moves]
        return {
            'name': 'Create Move Reversals',
            'type': 'ir.actions.act_window',
            'res_model': 'account.move.reversal.create',
            'view_type': 'form',
            'view_mode': 'form',
            'target': 'new',
            'context': context
        }

    def reverse_move(
        self, cr, uid, move_id, journal_id, period_id, context=None
    ):
        """ Create the reverse of 'move'.
        We only switch debit/credit,
        add '-canceled' after the name and reference,
        and change the date_maturity to today
        """

        move_obj = self.pool['account.move']

        move = move_obj.browse(cr, uid, move_id, context=context)

        # TODO translate in English
        cred_acc = move.journal_id.default_credit_account_id
        deb_acc = move.journal_id.default_debit_account_id
        # We verify that one account is defined
        # and that
        if not (
            (cred_acc or deb_acc) and
            ((cred_acc and cred_acc.reconcile) or
             (deb_acc and deb_acc.reconcile))
        ):
            raise osv.except_osv(
                _(u"Error"),
                _(u"Reconciliation is forbidden on the selected journal,"
                  u" please contact your administrator.")
            )

        # Specific changes for move

        vals = {
            'name': '/' if move.name == '/' else _('%s-canceled') % move.name,
            'ref': '' if not move.ref else _('%s-canceled') % move.ref,
            'period_id': period_id,
            'journal_id': journal_id,
            'partner_id': move.partner_id.id,
            'narration': move.narration,
            'company_id': move.company_id.id,
        }

        # Dynamically copy fields of move lines.

        move_line_fields = self.pool['account.move.line'].fields_get(
            cr, uid, context=context
        )

        vals['line_id'] = []

        # This tricky part just copy the fields from aml depending on the types
        # of the field. The types are mapped in the below enumeration

        fnct_types = {
            'many2one': lambda val: val.id,
            'one2many': lambda vals: [(6, 0, [v.id for v in vals])],
            'many2many': lambda vals: [(6, 0, [v.id for v in vals])],
            'default': lambda val: val,
        }
        for aml in move.line_id:
            new_line = {}
            for key in move_line_fields:
                # Call a function that will format the value depending on type
                new_line[key] = fnct_types.get(
                    move_line_fields[key]['type'],
                    fnct_types['default']
                )(getattr(aml, key))

            # Some specific changes
            new_line['name'] = aml.name + _('-canceled')
            new_line['debit'] = aml.credit
            new_line['credit'] = aml.debit
            new_line['amount_currency'] = -aml.amount_currency

            vals['line_id'].append((0, 0, new_line))

        reversed_move_id = self.create(cr, uid, vals, context=context)
        return reversed_move_id
<commit_msg>Remove a check that should be upstream<commit_after># -*- coding: utf-8 -*-

from openerp.osv import fields, osv
from openerp.tools.translate import _

from datetime import datetime

class account_move_reversal(osv.Model):

    _inherit = 'account.move'

    def button_reverse_move(self, cr, uid, ids, context=None):
        moves = self.browse(cr, uid, ids, context=context)
        context['active_ids'] = [move.id for move in moves]
        return {
            'name': 'Create Move Reversals',
            'type': 'ir.actions.act_window',
            'res_model': 'account.move.reversal.create',
            'view_type': 'form',
            'view_mode': 'form',
            'target': 'new',
            'context': context
        }

    def reverse_move(
        self, cr, uid, move_id, journal_id, period_id, context=None
    ):
        """ Create the reverse of 'move'.
        We only switch debit/credit,
        add '-canceled' after the name and reference,
        and change the date_maturity to today
        """

        move_obj = self.pool['account.move']

        move = move_obj.browse(cr, uid, move_id, context=context)

        # Specific changes for move

        vals = {
            'name': '/' if move.name == '/' else _('%s-canceled') % move.name,
            'ref': '' if not move.ref else _('%s-canceled') % move.ref,
            'period_id': period_id,
            'journal_id': journal_id,
            'partner_id': move.partner_id.id,
            'narration': move.narration,
            'company_id': move.company_id.id,
        }

        # Dynamically copy fields of move lines.

        move_line_fields = self.pool['account.move.line'].fields_get(
            cr, uid, context=context
        )

        vals['line_id'] = []

        # This tricky part just copy the fields from aml depending on the types
        # of the field. The types are mapped in the below enumeration

        fnct_types = {
            'many2one': lambda val: val.id,
            'one2many': lambda vals: [(6, 0, [v.id for v in vals])],
            'many2many': lambda vals: [(6, 0, [v.id for v in vals])],
            'default': lambda val: val,
        }
        for aml in move.line_id:
            new_line = {}
            for key in move_line_fields:
                # Call a function that will format the value depending on type
                new_line[key] = fnct_types.get(
                    move_line_fields[key]['type'],
                    fnct_types['default']
                )(getattr(aml, key))

            # Some specific changes
            new_line['name'] = aml.name + _('-canceled')
            new_line['debit'] = aml.credit
            new_line['credit'] = aml.debit
            new_line['amount_currency'] = -aml.amount_currency

            vals['line_id'].append((0, 0, new_line))

        reversed_move_id = self.create(cr, uid, vals, context=context)
        return reversed_move_id
<|endoftext|>


<commit_before># coding: utf-8
import os
import sqlite3
from contextlib import closing

from hypothesis import given, note, settings, example
from hypothesis._strategies import data, integers
from hypothesis.strategies import lists, sampled_from, composite, choices, text

from siebenapp.enumeration import Enumeration
from siebenapp.goaltree import Goals, Edge
from siebenapp.system import run_migrations, save_updates

settings.register_profile('ci', settings(max_examples=2000))
settings.register_profile('dev', settings(max_examples=200))
settings.load_profile(os.getenv('HYPOTHESIS_PROFILE', 'dev'))

USER_ACTIONS = {
    'add': lambda g, x: g.add('a'),
    'delete': lambda g, x: g.delete(),
    'hold_select': lambda g, x: g.hold_select(),
    'insert': lambda g, x: g.insert('i'),
    'rename': lambda g, x: g.rename('r'),
    'select': lambda g, x: g.select(x),
    'toggle_close': lambda g, x: g.toggle_close(),
    'toggle_link': lambda g, x: g.toggle_link(),
    'toggle_child': lambda g, x: g.toggle_link(edge_type=Edge.PARENT),
}

@composite
def user_actions(draw, skip=None, **lists_kwargs):
    if skip is None:
        skip = []
    possible_actions = sorted(k for k in USER_ACTIONS if k not in skip)
    return draw(lists(sampled_from(possible_actions), **lists_kwargs))

def build_from(actions, selections, show_notes=True):
    def _select_one_from(keys):
        if isinstance(selections, list):
            return selections.pop(0)
        return selections.draw(integers(min_value=1, max_value=max(keys)))

    g = Goals('Root')
    try:
        for name in actions:
            int_val = 0
            if name == 'select':
                int_val = _select_one_from(g.q().keys())
            USER_ACTIONS[name](g, int_val)
    finally:
        if show_notes:
            note(actions)
    return g

@given(user_actions(), data())
@example(actions=['add', 'add', 'select', 'toggle_close', 'select', 'hold_select', 'select', 'toggle_link'],
         selections=[2, 2, 3])
@example(actions=['add', 'select', 'add', 'add', 'select', 'hold_select', 'select', 'insert', 'select', 'delete'],
         selections=[2, 4, 3, 2])
@example(actions=['add', 'select', 'insert', 'toggle_link', 'toggle_close', 'select', 'toggle_close', 'select', 'toggle_close'],
         selections=[2, 3, 2])
@example(actions=['add', 'select', 'hold_select', 'add', 'select', 'insert', 'toggle_link', 'select', 'delete'],
         selections=[2, 3, 2])
def test_goaltree_must_be_valid_after_build(actions, selections):
    g = build_from(actions, selections, show_notes=False)
    assert g.verify()

@given(user_actions(), data())
def test_there_is_always_at_least_one_goal(actions, selections):
    g = build_from(actions, selections)
    assert g.q()

@given(user_actions(), data())
def test_there_is_always_one_selected_goal(actions, selections):
    g = build_from(actions, selections)
    assert len([1 for k, v in g.q(keys='select').items() if v['select'] == 'select']) == 1

@given(user_actions(min_size=15, skip=['rename']),
       user_actions(min_size=1, skip=['select']),
       data(), choices())
def test_any_goal_may_be_selected(all_actions, non_select_actions, selections, choice):
    g = build_from(all_actions + non_select_actions, selections)
    rnd_goal = choice(list(g.q().keys()))
    g.select(rnd_goal)
    assert g.q(keys='select')[rnd_goal]['select'] == 'select'

@given(user_actions(skip=['rename']), data(), choices())
def test_any_goal_may_be_selected_through_enumeration(actions, selections, choice):
    g = build_from(actions, selections)
    e = Enumeration(g)
    e.next_view()
    e.next_view()
    rnd_goal = choice(list(e.q().keys()))
    for i in str(rnd_goal):
        e.select(int(i))
    assert e.q(keys='select')[rnd_goal]['select'] == 'select'

@given(user_actions(), data())
def test_no_modify_action_sequence_could_break_goaltree_correctness(actions, selections):
    g = build_from(actions, selections)
    assert g.verify()

def build_goals(conn):
    with closing(conn.cursor()) as cur:
        goals = [row for row in cur.execute('select * from goals')]
        edges = [row for row in cur.execute('select parent, child, reltype from edges')]
        selection = [row for row in cur.execute('select * from settings')]
        note(goals)
        note(edges)
        note(selection)
        return Goals.build(goals, edges, selection)

@given(user_actions(), data())
def test_full_export_and_streaming_export_must_be_the_same(actions, selections):
    g = build_from(actions, selections)
    with closing(sqlite3.connect(':memory:')) as conn:
        run_migrations(conn)
        note(g.events)
        save_updates(g, conn)
        assert not g.events
        ng = build_goals(conn)
        assert g.q('name,open,edge,select') == ng.q('name,open,edge,select')

@given(text())
def test_all_goal_names_must_be_saved_correctly(name):
    g = Goals('renamed')
    g.rename(name)
    with closing(sqlite3.connect(':memory:')) as conn:
        note(g.events)
        run_migrations(conn)
        save_updates(g, conn)
        ng = build_goals(conn)
        assert g.q('name,open,edge,select') == ng.q('name,open,edge,select')

def test_all_keys_in_enumeration_must_be_of_the_same_length():
    g = Goals('Root')
    for i in range(2999):
        g.add(str(i))
    e = Enumeration(g)
    mapping = e.q()
    assert len(mapping) == len(g.q())
    assert set(len(str(k)) for k in mapping) == {4}
<commit_msg>Wrap collections into str() before passing into note<commit_after># coding: utf-8
import os
import sqlite3
from contextlib import closing

from hypothesis import given, note, settings, example
from hypothesis._strategies import data, integers
from hypothesis.strategies import lists, sampled_from, composite, choices, text

from siebenapp.enumeration import Enumeration
from siebenapp.goaltree import Goals, Edge
from siebenapp.system import run_migrations, save_updates

settings.register_profile('ci', settings(max_examples=2000))
settings.register_profile('dev', settings(max_examples=200))
settings.load_profile(os.getenv('HYPOTHESIS_PROFILE', 'dev'))

USER_ACTIONS = {
    'add': lambda g, x: g.add('a'),
    'delete': lambda g, x: g.delete(),
    'hold_select': lambda g, x: g.hold_select(),
    'insert': lambda g, x: g.insert('i'),
    'rename': lambda g, x: g.rename('r'),
    'select': lambda g, x: g.select(x),
    'toggle_close': lambda g, x: g.toggle_close(),
    'toggle_link': lambda g, x: g.toggle_link(),
    'toggle_child': lambda g, x: g.toggle_link(edge_type=Edge.PARENT),
}

@composite
def user_actions(draw, skip=None, **lists_kwargs):
    if skip is None:
        skip = []
    possible_actions = sorted(k for k in USER_ACTIONS if k not in skip)
    return draw(lists(sampled_from(possible_actions), **lists_kwargs))

def build_from(actions, selections, show_notes=True):
    def _select_one_from(keys):
        if isinstance(selections, list):
            return selections.pop(0)
        return selections.draw(integers(min_value=1, max_value=max(keys)))

    g = Goals('Root')
    try:
        for name in actions:
            int_val = 0
            if name == 'select':
                int_val = _select_one_from(g.q().keys())
            USER_ACTIONS[name](g, int_val)
    finally:
        if show_notes:
            note(actions)
    return g

@given(user_actions(), data())
@example(actions=['add', 'add', 'select', 'toggle_close', 'select', 'hold_select', 'select', 'toggle_link'],
         selections=[2, 2, 3])
@example(actions=['add', 'select', 'add', 'add', 'select', 'hold_select', 'select', 'insert', 'select', 'delete'],
         selections=[2, 4, 3, 2])
@example(actions=['add', 'select', 'insert', 'toggle_link', 'toggle_close', 'select', 'toggle_close', 'select', 'toggle_close'],
         selections=[2, 3, 2])
@example(actions=['add', 'select', 'hold_select', 'add', 'select', 'insert', 'toggle_link', 'select', 'delete'],
         selections=[2, 3, 2])
def test_goaltree_must_be_valid_after_build(actions, selections):
    g = build_from(actions, selections, show_notes=False)
    assert g.verify()

@given(user_actions(), data())
def test_there_is_always_at_least_one_goal(actions, selections):
    g = build_from(actions, selections)
    assert g.q()

@given(user_actions(), data())
def test_there_is_always_one_selected_goal(actions, selections):
    g = build_from(actions, selections)
    assert len([1 for k, v in g.q(keys='select').items() if v['select'] == 'select']) == 1

@given(user_actions(min_size=15, skip=['rename']),
       user_actions(min_size=1, skip=['select']),
       data(), choices())
def test_any_goal_may_be_selected(all_actions, non_select_actions, selections, choice):
    g = build_from(all_actions + non_select_actions, selections)
    rnd_goal = choice(list(g.q().keys()))
    g.select(rnd_goal)
    assert g.q(keys='select')[rnd_goal]['select'] == 'select'

@given(user_actions(skip=['rename']), data(), choices())
def test_any_goal_may_be_selected_through_enumeration(actions, selections, choice):
    g = build_from(actions, selections)
    e = Enumeration(g)
    e.next_view()
    e.next_view()
    rnd_goal = choice(list(e.q().keys()))
    for i in str(rnd_goal):
        e.select(int(i))
    assert e.q(keys='select')[rnd_goal]['select'] == 'select'

@given(user_actions(), data())
def test_no_modify_action_sequence_could_break_goaltree_correctness(actions, selections):
    g = build_from(actions, selections)
    assert g.verify()

def build_goals(conn):
    with closing(conn.cursor()) as cur:
        goals = [row for row in cur.execute('select * from goals')]
        edges = [row for row in cur.execute('select parent, child, reltype from edges')]
        selection = [row for row in cur.execute('select * from settings')]
        note(str(goals))
        note(str(edges))
        note(str(selection))
        return Goals.build(goals, edges, selection)

@given(user_actions(), data())
def test_full_export_and_streaming_export_must_be_the_same(actions, selections):
    g = build_from(actions, selections)
    with closing(sqlite3.connect(':memory:')) as conn:
        run_migrations(conn)
        note(str(g.events))
        save_updates(g, conn)
        assert not g.events
        ng = build_goals(conn)
        assert g.q('name,open,edge,select') == ng.q('name,open,edge,select')

@given(text())
def test_all_goal_names_must_be_saved_correctly(name):
    g = Goals('renamed')
    g.rename(name)
    with closing(sqlite3.connect(':memory:')) as conn:
        note(str(g.events))
        run_migrations(conn)
        save_updates(g, conn)
        ng = build_goals(conn)
        assert g.q('name,open,edge,select') == ng.q('name,open,edge,select')

def test_all_keys_in_enumeration_must_be_of_the_same_length():
    g = Goals('Root')
    for i in range(2999):
        g.add(str(i))
    e = Enumeration(g)
    mapping = e.q()
    assert len(mapping) == len(g.q())
    assert set(len(str(k)) for k in mapping) == {4}
<|endoftext|>


<commit_before># Copyright (C) 2016 SignalFx, Inc. All rights reserved.

from . import errors, messages

class Computation(object):
    """A live handle to a running SignalFlow computation."""

    STATE_UNKNOWN = 0
    STATE_STREAM_STARTED = 1
    STATE_COMPUTATION_STARTED = 2
    STATE_DATA_RECEIVED = 3
    STATE_COMPLETED = 4
    STATE_ABORTED = 5

    def __init__(self, exec_fn):
        self._id = None
        self._exec_fn = exec_fn

        self._stream = None
        self._state = Computation.STATE_UNKNOWN
        self._resolution = None

        self._metadata = {}
        self._last_logical_ts = None

        self._expected_batches = 0
        self._batch_count_detected = False
        self._current_batch_message = None
        self._current_batch_count = 0

        # Kick it off.
        self._stream = self._execute()

    def _execute(self):
        return self._exec_fn(self._last_logical_ts)

    @property
    def id(self):
        return self._id

    @property
    def resolution(self):
        return self._resolution

    @property
    def state(self):
        return self._state

    @property
    def last_logical_ts(self):
        return self._last_logical_ts

    def close(self):
        """Manually close this computation and detach from its stream.

        This computation object cannot be restarted, used or streamed for after
        this method is called."""
        if self._stream:
            self._stream.close()
            self._stream = None

    def get_known_tsids(self):
        return sorted(self._metadata.keys())

    def get_metadata(self, tsid):
        """Return the full metadata object for the given timeseries (by its
        ID), if available."""
        return self._metadata.get(tsid)

    def stream(self):
        """Iterate over the messages from the computation's output.

        Control and metadata messages are intercepted and interpreted to
        enhance this Computation's object knowledge of the computation's
        context. Data and event messages are yielded back to the caller as a
        generator.
        """

        iterator = iter(self._stream)
        while self._state < Computation.STATE_COMPLETED:
            try:
                message = next(iterator)
            except StopIteration:
                if self._state < Computation.STATE_COMPLETED:
                    self._stream = self._execute()
                    iterator = iter(self._stream)
                    continue

            if isinstance(message, messages.StreamStartMessage):
                self._state = Computation.STATE_STREAM_STARTED
                continue

            if isinstance(message, messages.JobStartMessage):
                self._state = Computation.STATE_COMPUTATION_STARTED
                self._id = message.handle
                yield message
                continue

            if isinstance(message, messages.JobProgressMessage):
                yield message
                continue

            if isinstance(message, messages.ChannelAbortMessage):
                self._state = Computation.STATE_ABORTED
                raise errors.ComputationAborted(message.abort_info)

            if isinstance(message, messages.EndOfChannelMessage):
                self._state = Computation.STATE_COMPLETED
                continue

            # Intercept metadata messages to accumulate received metadata...
            if isinstance(message, messages.MetadataMessage):
                self._metadata[message.tsid] = message.properties
                yield message
                continue

            # ...as well as expired-tsid messages to clean it up.
            if isinstance(message, messages.ExpiredTsIdMessage):
                if message.tsid in self._metadata:
                    del self._metadata[message.tsid]
                yield message
                continue

            if isinstance(message, messages.InfoMessage):
                self._process_info_message(message.message)
                self._batch_count_detected = True
                if self._current_batch_message:
                    yield self._get_batch_to_yield()
                continue

            # Accumulate data messages and release them when we have received
            # all batches for the same logical timestamp.
            if isinstance(message, messages.DataMessage):
                self._state = Computation.STATE_DATA_RECEIVED

                if not self._batch_count_detected:
                    self._expected_batches += 1

                if not self._current_batch_message:
                    self._current_batch_message = message
                    self._current_batch_count = 1
                elif ((message.logical_timestamp_ms ==
                       self._current_batch_message.logical_timestamp_ms) and
                      (self._current_batch_count < self._expected_batches)):
                    self._current_batch_message.add_data(message.data)
                    self._current_batch_count += 1
                else:
                    self._batch_count_detected = True

                if self._current_batch_count == self._expected_batches:
                    yield self._get_batch_to_yield()
                continue

            if isinstance(message, messages.EventMessage):
                yield message
                continue

            if isinstance(message, messages.ErrorMessage):
                raise errors.ComputationFailed(message.errors)

        # Yield last batch, even if potentially incomplete.
        if self._current_batch_message:
            yield self._get_batch_to_yield()

    def _process_info_message(self, message):
        """Process an information message received from the computation."""
        # Extract the output resolution from the appropriate message, if
        # it's present.
        if message['messageCode'] == 'JOB_RUNNING_RESOLUTION':
            self._resolution = message['contents']['resolutionMs']

    def _get_batch_to_yield(self):
        if not self._current_batch_message:
            return None
        to_yield = self._current_batch_message
        self._current_batch_message = None
        self._current_batch_count = 0
        self._last_logical_ts = to_yield.logical_timestamp_ms
        return to_yield
<commit_msg>Fix yielding of first computation data batch<commit_after># Copyright (C) 2016 SignalFx, Inc. All rights reserved.

from . import errors, messages

class Computation(object):
    """A live handle to a running SignalFlow computation."""

    STATE_UNKNOWN = 0
    STATE_STREAM_STARTED = 1
    STATE_COMPUTATION_STARTED = 2
    STATE_DATA_RECEIVED = 3
    STATE_COMPLETED = 4
    STATE_ABORTED = 5

    def __init__(self, exec_fn):
        self._id = None
        self._exec_fn = exec_fn

        self._stream = None
        self._state = Computation.STATE_UNKNOWN
        self._resolution = None

        self._metadata = {}
        self._last_logical_ts = None

        self._expected_batches = 0
        self._batch_count_detected = False
        self._current_batch_message = None
        self._current_batch_count = 0

        # Kick it off.
        self._stream = self._execute()

    def _execute(self):
        return self._exec_fn(self._last_logical_ts)

    @property
    def id(self):
        return self._id

    @property
    def resolution(self):
        return self._resolution

    @property
    def state(self):
        return self._state

    @property
    def last_logical_ts(self):
        return self._last_logical_ts

    def close(self):
        """Manually close this computation and detach from its stream.

        This computation object cannot be restarted, used or streamed for after
        this method is called."""
        if self._stream:
            self._stream.close()
            self._stream = None

    def get_known_tsids(self):
        return sorted(self._metadata.keys())

    def get_metadata(self, tsid):
        """Return the full metadata object for the given timeseries (by its
        ID), if available."""
        return self._metadata.get(tsid)

    def stream(self):
        """Iterate over the messages from the computation's output.

        Control and metadata messages are intercepted and interpreted to
        enhance this Computation's object knowledge of the computation's
        context. Data and event messages are yielded back to the caller as a
        generator.
        """

        iterator = iter(self._stream)
        while self._state < Computation.STATE_COMPLETED:
            try:
                message = next(iterator)
            except StopIteration:
                if self._state < Computation.STATE_COMPLETED:
                    self._stream = self._execute()
                    iterator = iter(self._stream)
                    continue

            if isinstance(message, messages.StreamStartMessage):
                self._state = Computation.STATE_STREAM_STARTED
                continue

            if isinstance(message, messages.JobStartMessage):
                self._state = Computation.STATE_COMPUTATION_STARTED
                self._id = message.handle
                yield message
                continue

            if isinstance(message, messages.JobProgressMessage):
                yield message
                continue

            if isinstance(message, messages.ChannelAbortMessage):
                self._state = Computation.STATE_ABORTED
                raise errors.ComputationAborted(message.abort_info)

            if isinstance(message, messages.EndOfChannelMessage):
                self._state = Computation.STATE_COMPLETED
                continue

            # Intercept metadata messages to accumulate received metadata...
            if isinstance(message, messages.MetadataMessage):
                self._metadata[message.tsid] = message.properties
                yield message
                continue

            # ...as well as expired-tsid messages to clean it up.
            if isinstance(message, messages.ExpiredTsIdMessage):
                if message.tsid in self._metadata:
                    del self._metadata[message.tsid]
                yield message
                continue

            if isinstance(message, messages.InfoMessage):
                self._process_info_message(message.message)
                self._batch_count_detected = True
                if self._current_batch_message:
                    yield self._get_batch_to_yield()
                continue

            # Accumulate data messages and release them when we have received
            # all batches for the same logical timestamp.
            if isinstance(message, messages.DataMessage):
                self._state = Computation.STATE_DATA_RECEIVED

                if not self._batch_count_detected:
                    self._expected_batches += 1

                if not self._current_batch_message:
                    self._current_batch_message = message
                    self._current_batch_count = 1
                elif (message.logical_timestamp_ms ==
                        self._current_batch_message.logical_timestamp_ms):
                    self._current_batch_message.add_data(message.data)
                    self._current_batch_count += 1
                else:
                    self._batch_count_detected = True

                if (self._batch_count_detected and
                        self._current_batch_count == self._expected_batches):
                    yield self._get_batch_to_yield()
                continue

            if isinstance(message, messages.EventMessage):
                yield message
                continue

            if isinstance(message, messages.ErrorMessage):
                raise errors.ComputationFailed(message.errors)

        # Yield last batch, even if potentially incomplete.
        if self._current_batch_message:
            yield self._get_batch_to_yield()

    def _process_info_message(self, message):
        """Process an information message received from the computation."""
        # Extract the output resolution from the appropriate message, if
        # it's present.
        if message['messageCode'] == 'JOB_RUNNING_RESOLUTION':
            self._resolution = message['contents']['resolutionMs']

    def _get_batch_to_yield(self):
        to_yield = self._current_batch_message
        self._current_batch_message = None
        self._current_batch_count = 0
        self._last_logical_ts = to_yield.logical_timestamp_ms
        return to_yield
<|endoftext|>


<commit_before>"""
Basic modifiers are the typical LFOs you'd find in the audio world: Sine, Saw, Square,
Triangle, Random. Their frequency can be set freely in Hz.

To unify their definition they all work on the same domain, but two different codomains
based on if the flag "positive" is set:

  let f be the function of the modifier:

  for positive = False:   f: [0, 1] -> [-1, 1]
  for positive = True:    f: [0, 1] -> [ 0, 1]
  with f(0) = 0 in both cases.

  If f yields 0, the target value is not modified at all.
  If f yields 1, the target value is modified to the full effect (which itself is a
                 function of Modifier._amplitude and the per-Target power. See the
                 definition of Modifier for that).

When a ValueTarget is being modified by a centered modifier (positive = False),
the modifier will let the modulated value oscillate around the ValueTargets
value (center position).
With positive = True it will take the ValueTarget's value as the starting point
and modulate that value in one direction only, depending on if the power is a
positive or negative value.

The Basic base class takes care of preparing the provided time value t to sync up
with the modifiers frequency. It transforms the value to always move from 0 to 1
for one cycle of the waveform.
For musically synced frequencies, calculate the frequency to set using the bpm_syn
function which receives the bpm and the number of quarter notes per cycle.
"""
from math import sin, cos, pi
from random import random

from .modifier import Modifier

def bpm_sync(bpm, quarter_notes):
    """
    Turns a BPM value and a length given in beats into a frequency usable by a modifier.

    :param bpm: Beats Per Minutes
    :param quarter_notes: Length of LFO cycle in quarter notes
    :return: frequency in Hz
    """
    return bpm / 60.0 / quarter_notes

class Basic(Modifier):
    """
    A basic modulator that just needs a frequency to operate.

    :param frequency: in Hz
    :param positive: centered mode vs positive mode (see module docstring)
    :param kwargs: See Modifier
    """

    def __init__(self, frequency=0.25, positive=False, **kwargs):
        super().__init__(**kwargs)
        self.frequency = frequency
        self.positive = positive

    def serialize(self):
        """
        Serializes Modifier attributes into a dictionary
        :return: dict to recreate the object in its current state
        """
        m = super().serialize()
        m["frequency"] = self.frequency
        m["positive"] = self.positive
        return m

    def from_dict(self, m, *args, **kwargs):
        """
        Recreates the state of the object from a dictionary generated by serialize
        :param m: the dictionary
        :param args: see parent class
        :param kwargs: see parent class
        """
        super().from_dict(m, *args, **kwargs)
        self.frequency = m["frequency"]
        self.positive = m["positive"]

    def save(self):
        d = super().save()
        d["frequency"] = self.frequency
        d["positive"] = self.positive
        return d

    def load(self, d, i):
        super().load(d, i)
        self.frequency = d["frequency"]
        self.positive = d["positive"]

    def calculate(self, t):
        # TODO: Sync to midi clock
        t *= self.frequency

        # Dampen the amplitude of "centered" waves by 0.5
        # That way, setting the power of modulation in ModView
        # the set range equates directly to the range of oscillation
        # However, it would't allow full range modulation in centered
        # mode. It feels better, but makes the centered mode less useful.
        # * (1 + int(self.positive)) / 2
        return self.wave(t)

    def wave(self, t):
        """
        Implement in such a way that:
        self.positive == True ---> [ 0, 1], wave(0) = 0
        self.positive == False --> [-1, 1], wave(0) = 0
        """
        raise NotImplementedError

class Sine(Basic):

    def wave(self, t):
        if self.positive:
            return (sin(self.period(t)) + 1) / 2
        else:
            return -cos(self.period(t))

    @staticmethod
    def period(t):
        return t * 2 * pi

class Saw(Basic):

    def wave(self, t):
        if self.positive:
            return t
        else:
            return t * 2 - 1

class Triangle(Basic):

    def wave(self, t):
        if self.positive:
            if t < 0.5:
                return 2 * t
            else:
                return 2 - 2 * t
        else:
            if t < 0.25:
                return t * 4
            elif t < 0.75:
                return 1 - 4 * (t - 0.25)
            else:
                return 4 * (t - 0.75) - 1

class Square(Basic):

    def wave(self, t):
        if self.positive:
            return int(t < 0.25 or t > 0.75)
        else:
            return int(t < 0.5) * 2 - 1

class SampledRandom(Basic):

    last_t = 0
    current_value = 0

    def wave(self, t):
        if t <= self.last_t:
            if self.positive:
                self.current_value = random()
            else:
                self.current_value = random() * 2 - 1

        self.last_t = t
        return self.current_value
<commit_msg>Adds offset to Basic modifier<commit_after>"""
Basic modifiers are the typical LFOs you'd find in the audio world: Sine, Saw, Square,
Triangle, Random. Their frequency can be set freely in Hz.

To unify their definition they all work on the same domain, but two different codomains
based on if the flag "positive" is set:

  let f be the function of the modifier:

  for positive = False:   f: [0, 1] -> [-1, 1]
  for positive = True:    f: [0, 1] -> [ 0, 1]
  with f(0) = 0 in both cases.

  If f yields 0, the target value is not modified at all.
  If f yields 1, the target value is modified to the full effect (which itself is a
                 function of Modifier._amplitude and the per-Target power. See the
                 definition of Modifier for that).

When a ValueTarget is being modified by a centered modifier (positive = False),
the modifier will let the modulated value oscillate around the ValueTargets
value (center position).
With positive = True it will take the ValueTarget's value as the starting point
and modulate that value in one direction only, depending on if the power is a
positive or negative value.

The Basic base class takes care of preparing the provided time value t to sync up
with the modifiers frequency. It transforms the value to always move from 0 to 1
for one cycle of the waveform.
For musically synced frequencies, calculate the frequency to set using the bpm_syn
function which receives the bpm and the number of quarter notes per cycle.
"""
from math import sin, cos, pi
from random import random

from .modifier import Modifier

def bpm_sync(bpm, quarter_notes):
    """
    Turns a BPM value and a length given in beats into a frequency usable by a modifier.

    :param bpm: Beats Per Minutes
    :param quarter_notes: Length of LFO cycle in quarter notes
    :return: frequency in Hz
    """
    return bpm / 60.0 / quarter_notes

class Basic(Modifier):
    """
    A basic modulator that just needs a frequency to operate.

    :param frequency: in Hz
    :param positive: centered mode vs positive mode (see module docstring)
    :param offset: time offset of the cycle
    """
    def __init__(self, frequency=0.25, positive=False, offset=0, **kwargs):
        super().__init__(**kwargs)
        self.frequency = frequency
        self.positive = positive
        self.offset = offset

    def serialize(self):
        """
        Serializes Modifier attributes into a dictionary
        :return: dict to recreate the object in its current state
        """
        m = super().serialize()
        m["frequency"] = self.frequency
        m["positive"] = self.positive
        m["offset"] = self.offset
        return m

    def from_dict(self, m, *args, **kwargs):
        """
        Recreates the state of the object from a dictionary generated by serialize
        :param m: the dictionary
        :param args: see parent class
        :param kwargs: see parent class
        """
        super().from_dict(m, *args, **kwargs)
        self.frequency = m["frequency"]
        self.positive = m["positive"]
        self.offset = m["offset"]

    def save(self):
        d = super().save()
        d["frequency"] = self.frequency
        d["positive"] = self.positive
        d["offset"] = self.offset
        return d

    def load(self, d, i):
        super().load(d, i)
        self.frequency = d["frequency"]
        self.positive = d["positive"]
        self.offset = d["offset"]

    def calculate(self, t):
        # TODO: Sync to midi clock
        t *= self.frequency

        t = (t + self.offset) % 1

        # Dampen the amplitude of "centered" waves by 0.5
        # That way, setting the power of modulation in ModView
        # the set range equates directly to the range of oscillation
        # However, it would't allow full range modulation in centered
        # mode. It feels better, but makes the centered mode less useful.
        # * (1 + int(self.positive)) / 2
        return self.wave(t)

    def wave(self, t):
        """
        Implement in such a way that:
        self.positive == True ---> [ 0, 1], wave(0) = 0
        self.positive == False --> [-1, 1], wave(0) = 0
        """
        raise NotImplementedError

class Sine(Basic):

    def wave(self, t):
        if self.positive:
            return (sin(self.period(t)) + 1) / 2
        else:
            return -cos(self.period(t))

    @staticmethod
    def period(t):
        return t * 2 * pi

class Saw(Basic):

    def wave(self, t):
        if self.positive:
            return t
        else:
            return t * 2 - 1

class Triangle(Basic):

    def wave(self, t):
        if self.positive:
            if t < 0.5:
                return 2 * t
            else:
                return 2 - 2 * t
        else:
            if t < 0.25:
                return t * 4
            elif t < 0.75:
                return 1 - 4 * (t - 0.25)
            else:
                return 4 * (t - 0.75) - 1

class Square(Basic):

    def wave(self, t):
        if self.positive:
            return int(t < 0.25 or t > 0.75)
        else:
            return int(t < 0.5) * 2 - 1

class SampledRandom(Basic):

    last_t = 0
    current_value = 0

    def wave(self, t):
        if t <= self.last_t:
            if self.positive:
                self.current_value = random()
            else:
                self.current_value = random() * 2 - 1

        self.last_t = t
        return self.current_value
<|endoftext|>