<commit_before>"""
Django settings for Project Moore.

This file contains the shared settings. See development.py
and production.py for environment specific settings.

For more information on this file, see
https://docs.djangoproject.com/en/1.10/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.10/ref/settings/
"""

from __future__ import absolute_import, unicode_literals

from django.conf.global_settings import LOGIN_URL
from django.utils.translation import ugettext_lazy as _

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os

PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
BASE_DIR = os.path.dirname(PROJECT_DIR)

# Application definition

INSTALLED_APPS = [
    'website',  # include for templatetags
    'home',
    'involvement',
    'members',
    'search',

    'wagtail.wagtailforms',
    'wagtail.wagtailredirects',
    'wagtail.wagtailembeds',
    'wagtail.wagtailsites',
    'wagtail.wagtailusers',
    'wagtail.wagtailsnippets',
    'wagtail.wagtaildocs',
    'wagtail.wagtailimages',
    'wagtail.wagtailsearch',
    'wagtail.wagtailadmin',
    'wagtail.wagtailcore',
    'wagtail.contrib.settings',
    'wagtail.contrib.modeladmin',
    "wagtail.contrib.wagtailroutablepage",
    "wagtail.contrib.wagtailstyleguide",

    'modelcluster',
    'taggit',
    'compressor',
    'rules.apps.AutodiscoverRulesConfig',

    'django.contrib.admin',  # Used for wagtail admin filters
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.middleware.locale.LocaleMiddleware',

    'wagtail.wagtailcore.middleware.SiteMiddleware',
    'wagtail.wagtailredirects.middleware.RedirectMiddleware',
]

ROOT_URLCONF = 'website.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            os.path.join(PROJECT_DIR, 'templates'),
        ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'website.wsgi.application'

# Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/

LANGUAGE_CODE = 'en'

TIME_ZONE = 'Europe/Stockholm'

USE_I18N = True

USE_L10N = True

USE_TZ = True

LANGUAGES = [
    ('en', _('English')),
    ('sv', _('Swedish'))
]

LOCALE_PATHS = ['locale']

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/

STATICFILES_FINDERS = [
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    # Compressor
    'compressor.finders.CompressorFinder',
]

STATICFILES_DIRS = [
    os.path.join(PROJECT_DIR, 'static'),
]

STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

# Compressor
# https://django-compressor.readthedocs.io/en/latest/settings/

COMPRESS_PRECOMPILERS = (
    ('text/x-scss', 'django_libsass.SassCompiler'),
)

COMPRESS_CSS_FILTERS = ['compressor.filters.css_default.CssAbsoluteFilter',
                        'compressor.filters.cssmin.rCSSMinFilter']

# Authentication settings

AUTH_USER_MODEL = 'members.Member'

AUTHENTICATION_BACKENDS = (
    'rules.permissions.ObjectPermissionBackend',
    'django.contrib.auth.backends.ModelBackend',
)

# Password validation
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation'
                '.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation'
                '.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation'
                '.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation'
                '.NumericPasswordValidator',
    },
]

# Password hashers
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators

PASSWORD_HASHERS = [
    'django.contrib.auth.hashers.Argon2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
    'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
    'django.contrib.auth.hashers.BCryptPasswordHasher',
]

# Wagtail settings

WAGTAIL_SITE_NAME = "Uppsala teknolog- och naturvetarkår"
WAGTAIL_FRONTEND_LOGIN_URL = LOGIN_URL

# Base URL to use when referring to full URLs within the Wagtail admin
# backend - e.g. in notification emails. Don't include '/admin' or a
# trailing slash
BASE_URL = 'http://utn.se'

WAGTAIL_USER_EDIT_FORM = 'members.forms.CustomUserEditForm'
WAGTAIL_USER_CREATION_FORM = 'members.forms.CustomUserCreationForm'
WAGTAIL_USER_CUSTOM_FIELDS = ['birthday', 'person_number_ext', 'phone_number',
                              'registration_year', 'study']
<commit_msg>:bug: Remove the wagtailstyleguide from website This must have been added by mistake<commit_after>"""
Django settings for Project Moore.

This file contains the shared settings. See development.py
and production.py for environment specific settings.

For more information on this file, see
https://docs.djangoproject.com/en/1.10/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.10/ref/settings/
"""

from __future__ import absolute_import, unicode_literals

from django.conf.global_settings import LOGIN_URL
from django.utils.translation import ugettext_lazy as _

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os

PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
BASE_DIR = os.path.dirname(PROJECT_DIR)

# Application definition

INSTALLED_APPS = [
    'website',  # include for templatetags
    'home',
    'involvement',
    'members',
    'search',

    'wagtail.wagtailforms',
    'wagtail.wagtailredirects',
    'wagtail.wagtailembeds',
    'wagtail.wagtailsites',
    'wagtail.wagtailusers',
    'wagtail.wagtailsnippets',
    'wagtail.wagtaildocs',
    'wagtail.wagtailimages',
    'wagtail.wagtailsearch',
    'wagtail.wagtailadmin',
    'wagtail.wagtailcore',
    'wagtail.contrib.settings',
    'wagtail.contrib.modeladmin',
    "wagtail.contrib.wagtailroutablepage",

    'modelcluster',
    'taggit',
    'compressor',
    'rules.apps.AutodiscoverRulesConfig',

    'django.contrib.admin',  # Used for wagtail admin filters
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.middleware.locale.LocaleMiddleware',

    'wagtail.wagtailcore.middleware.SiteMiddleware',
    'wagtail.wagtailredirects.middleware.RedirectMiddleware',
]

ROOT_URLCONF = 'website.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            os.path.join(PROJECT_DIR, 'templates'),
        ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'website.wsgi.application'

# Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/

LANGUAGE_CODE = 'en'

TIME_ZONE = 'Europe/Stockholm'

USE_I18N = True

USE_L10N = True

USE_TZ = True

LANGUAGES = [
    ('en', _('English')),
    ('sv', _('Swedish'))
]

LOCALE_PATHS = ['locale']

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/

STATICFILES_FINDERS = [
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    # Compressor
    'compressor.finders.CompressorFinder',
]

STATICFILES_DIRS = [
    os.path.join(PROJECT_DIR, 'static'),
]

STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

# Compressor
# https://django-compressor.readthedocs.io/en/latest/settings/

COMPRESS_PRECOMPILERS = (
    ('text/x-scss', 'django_libsass.SassCompiler'),
)

COMPRESS_CSS_FILTERS = ['compressor.filters.css_default.CssAbsoluteFilter',
                        'compressor.filters.cssmin.rCSSMinFilter']

# Authentication settings

AUTH_USER_MODEL = 'members.Member'

AUTHENTICATION_BACKENDS = (
    'rules.permissions.ObjectPermissionBackend',
    'django.contrib.auth.backends.ModelBackend',
)

# Password validation
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation'
                '.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation'
                '.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation'
                '.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation'
                '.NumericPasswordValidator',
    },
]

# Password hashers
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators

PASSWORD_HASHERS = [
    'django.contrib.auth.hashers.Argon2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
    'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
    'django.contrib.auth.hashers.BCryptPasswordHasher',
]

# Wagtail settings

WAGTAIL_SITE_NAME = "Uppsala teknolog- och naturvetarkår"
WAGTAIL_FRONTEND_LOGIN_URL = LOGIN_URL

# Base URL to use when referring to full URLs within the Wagtail admin
# backend - e.g. in notification emails. Don't include '/admin' or a
# trailing slash
BASE_URL = 'http://utn.se'

WAGTAIL_USER_EDIT_FORM = 'members.forms.CustomUserEditForm'
WAGTAIL_USER_CREATION_FORM = 'members.forms.CustomUserCreationForm'
WAGTAIL_USER_CUSTOM_FIELDS = ['birthday', 'person_number_ext', 'phone_number',
                              'registration_year', 'study']
<|endoftext|>


<commit_before>import logging
from copy import deepcopy

import virtool.api.utils

async def default_writer(connection, message):
    return await connection.send(message)

class Connection:

    def __init__(self, ws, session):
        self._ws = ws
        self.ping = self._ws.ping
        self.user_id = session.user_id
        self.groups = session.groups
        self.permissions = session.permissions

    async def send(self, message):
        await self._ws.send_json(message, dumps=virtool.api.utils.dumps)

    async def close(self):
        await self._ws.close()

class Dispatcher:

    def __init__(self, loop):
        self.loop = loop

        #: A dict of all active connections.
        self.connections = list()

        logging.debug("Initialized dispatcher")

    def add_connection(self, connection):
        """
        Add a connection to the dispatcher.

        """
        self.connections.append(connection)
        logging.debug("Added connection to dispatcher: {}".format(connection.user_id))

    def remove_connection(self, connection):
        """
        Remove a connection from the dispatcher. Make sure it is closed first.

        :param connection: the connection to remove
        :type connection: :class:`.SocketHandler`

        """
        try:
            self.connections.remove(connection)
            logging.debug("Removed connection from dispatcher: {}".format(connection.user_id))
        except ValueError:
            pass

    async def dispatch(self, interface, operation, data, connections=None, conn_filter=None, conn_modifier=None,
                       writer=default_writer):
        """
        Dispatch a ``message`` with a conserved format to a selection of active ``connections``.

        :param interface: the name of the interface the client should perform the operation on
        :type interface: str

        :param operation: a word used to tell the client what to do in response to the message
        :type operation: str

        :param data: the data the client will use
        :type data: dict

        :param connections: the connection(s) (:class:`.SocketHandler` objects) to dispatch the message to.
        :type connections: list

        :param conn_filter: filters the connections to which messages are written.
        :type conn_filter: callable

        :param conn_modifier: modifies the connection objects to which messages are written.
        :type conn_modifier: callable

        :param writer: modifies the written message based on the connection.
        :type writer: callable

        """
        message = {
            "operation": operation,
            "interface": interface,
            "data": data
        }

        # If the connections parameter was not set, dispatch the message to all authorized connections. Authorized
        # connections have assigned ``user_id`` properties.
        connections = connections or [conn for conn in self.connections if conn.user_id]

        if conn_filter:
            if not callable(conn_filter):
                raise TypeError("conn_filter must be callable")

            connections = [conn for conn in connections if conn_filter(conn)]

        if conn_modifier:
            if not callable(conn_modifier):
                raise TypeError("conn_modifier must be callable")

            for connection in connections:
                conn_modifier(connection)

        if writer and not callable(writer):
            raise TypeError("writer must be callable")

        connections_to_remove = list()

        for connection in connections:
            try:
                await writer(connection, deepcopy(message))
            except RuntimeError as err:
                if "RuntimeError: unable to perform operation on <TCPTransport" in str(err):
                    connections_to_remove.append(connection)

        for connection in connections_to_remove:
            self.remove_connection(connection)

        logging.debug("Dispatched {}.{}".format(interface, operation))

    async def close(self):
        for connection in self.connections:
            await connection.close()

        logging.debug("Closed dispatcher")
<commit_msg>Log message when dispatcher close is started<commit_after>import logging
from copy import deepcopy

import virtool.api.utils

async def default_writer(connection, message):
    return await connection.send(message)

class Connection:

    def __init__(self, ws, session):
        self._ws = ws
        self.ping = self._ws.ping
        self.user_id = session.user_id
        self.groups = session.groups
        self.permissions = session.permissions

    async def send(self, message):
        await self._ws.send_json(message, dumps=virtool.api.utils.dumps)

    async def close(self):
        await self._ws.close()

class Dispatcher:

    def __init__(self, loop):
        self.loop = loop

        #: A dict of all active connections.
        self.connections = list()

        logging.debug("Initialized dispatcher")

    def add_connection(self, connection):
        """
        Add a connection to the dispatcher.

        """
        self.connections.append(connection)
        logging.debug("Added connection to dispatcher: {}".format(connection.user_id))

    def remove_connection(self, connection):
        """
        Remove a connection from the dispatcher. Make sure it is closed first.

        :param connection: the connection to remove
        :type connection: :class:`.SocketHandler`

        """
        try:
            self.connections.remove(connection)
            logging.debug("Removed connection from dispatcher: {}".format(connection.user_id))
        except ValueError:
            pass

    async def dispatch(self, interface, operation, data, connections=None, conn_filter=None, conn_modifier=None,
                       writer=default_writer):
        """
        Dispatch a ``message`` with a conserved format to a selection of active ``connections``.

        :param interface: the name of the interface the client should perform the operation on
        :type interface: str

        :param operation: a word used to tell the client what to do in response to the message
        :type operation: str

        :param data: the data the client will use
        :type data: dict

        :param connections: the connection(s) (:class:`.SocketHandler` objects) to dispatch the message to.
        :type connections: list

        :param conn_filter: filters the connections to which messages are written.
        :type conn_filter: callable

        :param conn_modifier: modifies the connection objects to which messages are written.
        :type conn_modifier: callable

        :param writer: modifies the written message based on the connection.
        :type writer: callable

        """
        message = {
            "operation": operation,
            "interface": interface,
            "data": data
        }

        # If the connections parameter was not set, dispatch the message to all authorized connections. Authorized
        # connections have assigned ``user_id`` properties.
        connections = connections or [conn for conn in self.connections if conn.user_id]

        if conn_filter:
            if not callable(conn_filter):
                raise TypeError("conn_filter must be callable")

            connections = [conn for conn in connections if conn_filter(conn)]

        if conn_modifier:
            if not callable(conn_modifier):
                raise TypeError("conn_modifier must be callable")

            for connection in connections:
                conn_modifier(connection)

        if writer and not callable(writer):
            raise TypeError("writer must be callable")

        connections_to_remove = list()

        for connection in connections:
            try:
                await writer(connection, deepcopy(message))
            except RuntimeError as err:
                if "RuntimeError: unable to perform operation on <TCPTransport" in str(err):
                    connections_to_remove.append(connection)

        for connection in connections_to_remove:
            self.remove_connection(connection)

        logging.debug("Dispatched {}.{}".format(interface, operation))

    async def close(self):
        logging.debug("Closing dispatcher")

        for connection in self.connections:
            await connection.close()

        logging.debug("Closed dispatcher")
<|endoftext|>


<commit_before>def module_exists(module_name):
    try:
        __import__(module_name)
    except ImportError:
        return False
    else:
        return True

if module_exists('browser') and module_exists('javascript'):

    from browser import window, document
    from javascript import JSObject, JSConstructor
    major = window.__BRYTHON__.implementation[0]
    minor = window.__BRYTHON__.implementation[1]
    if major == 3 and minor >= 3 or major > 3:
        GFX = window.PIXI
        GFX_Rectangle = GFX.Rectangle.new
        GFX_Texture = GFX.Texture.new
        GFX_Texture_fromImage = GFX.Texture.fromImage.new
        GFX_Sprite = GFX.Sprite.new
        GFX_Graphics = GFX.Graphics.new()
        GFX_Text = GFX.Text.new
        SND = window.buzz
        SND_Sound = SND.sound.new
    else:
        GFX = JSObject(window.PIXI)
        GFX_Rectangle = JSConstructor(GFX.Rectangle)
        GFX_Texture = JSConstructor(GFX.Texture)
        GFX_Texture_fromImage = JSConstructor(GFX.Texture.fromImage)
        GFX_Sprite = JSConstructor(GFX.Sprite)
        GFX_Graphics = JSConstructor(GFX.Graphics)()
        GFX_Text = JSConstructor(GFX.Text)
        SND = JSObject(window.buzz)
        SND_Sound = JSConstructor(SND.sound)
    GFX_DetectRenderer = GFX.autoDetectRenderer

    class GFX_Window(object):

        def __init__(self, width, height, onclose):
            self._w = window.open("", "")
            self._stage = JSConstructor(GFX.Container)()
            self.width = width if width != 0 else int(window.innerWidth * 0.9)
            self.height = height if height != 0 else int(window.innerHeight * 0.9)
            self._renderer = GFX.autoDetectRenderer(self.width, self.height, {'transparent':True, 'antialias':True})
            self._w.document.body.appendChild(self._renderer.view)
            self._w.onunload = onclose

        def bind(self, evtspec, callback):
            self._w.document.body.bind(evtspec, callback)

        def add(self, obj):
            self._stage.addChild(obj)

        def remove(self, obj):
            self._stage.removeChild(obj)

        def animate(self, stepcallback):
            self._renderer.render(self._stage)
            self._w.requestAnimationFrame(stepcallback)

        def destroy(self):
            SND.all().stop()
            self._stage.destroy()

elif module_exists('pygame'):

    try:
        from ggame.pygamedeps import *
    except:
        from pygamedeps import *

else:
    try:
        from ggame.headlessdeps import *
    except:
        from headlessdeps import *

<commit_msg>Updated from Brython Server: 7/8/2017 4:50:30 PM<commit_after>def module_exists(module_name):
    try:
        __import__(module_name)
    except ImportError:
        return False
    else:
        return True

if module_exists('browser') and module_exists('javascript'):

    from browser import window, document
    from javascript import JSObject, JSConstructor
    major = window.__BRYTHON__.implementation[0]
    minor = window.__BRYTHON__.implementation[1]
    if major == 3 and minor >= 3 or major > 3:
        GFX = window.PIXI
        GFX_Rectangle = GFX.Rectangle.new
        GFX_Texture = GFX.Texture.new
        GFX_Texture_fromImage = GFX.Texture.fromImage.new
        GFX_Sprite = GFX.Sprite.new
        GFX_Graphics = GFX.Graphics.new()
        GFX_Text = GFX.Text.new
        GFX_NewStage = GFX.Container
        SND = window.buzz
        SND_Sound = SND.sound.new
    else:
        GFX = JSObject(window.PIXI)
        GFX_Rectangle = JSConstructor(GFX.Rectangle)
        GFX_Texture = JSConstructor(GFX.Texture)
        GFX_Texture_fromImage = JSConstructor(GFX.Texture.fromImage)
        GFX_Sprite = JSConstructor(GFX.Sprite)
        GFX_Graphics = JSConstructor(GFX.Graphics)()
        GFX_Text = JSConstructor(GFX.Text)
        GFX_NewStage = JSConstructor(GFX.Container)
        SND = JSObject(window.buzz)
        SND_Sound = JSConstructor(SND.sound)
    GFX_DetectRenderer = GFX.autoDetectRenderer

    class GFX_Window(object):

        def __init__(self, width, height, onclose):
            self._w = window.open("", "")
            self._stage = GFX.NewStage()
            self.width = width if width != 0 else int(window.innerWidth * 0.9)
            self.height = height if height != 0 else int(window.innerHeight * 0.9)
            self._renderer = GFX.autoDetectRenderer(self.width, self.height, {'transparent':True, 'antialias':True})
            self._w.document.body.appendChild(self._renderer.view)
            self._w.onunload = onclose

        def bind(self, evtspec, callback):
            self._w.document.body.bind(evtspec, callback)

        def add(self, obj):
            self._stage.addChild(obj)

        def remove(self, obj):
            self._stage.removeChild(obj)

        def animate(self, stepcallback):
            self._renderer.render(self._stage)
            self._w.requestAnimationFrame(stepcallback)

        def destroy(self):
            SND.all().stop()
            self._stage.destroy()

elif module_exists('pygame'):

    try:
        from ggame.pygamedeps import *
    except:
        from pygamedeps import *

else:
    try:
        from ggame.headlessdeps import *
    except:
        from headlessdeps import *

<|endoftext|>


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

from wechatpy.client.api.base import BaseWeChatAPI

class WeChatMenu(BaseWeChatAPI):
    """
    自定义菜单

    https://work.weixin.qq.com/api/doc#90000/90135/90230
    """

    def create(self, agent_id, menu_data):
        """
        创建菜单

        https://work.weixin.qq.com/api/doc#90000/90135/90231

        :param agent_id: 应用id
        """
        return self._post("menu/create", params={"agentid": agent_id}, data=menu_data)

    def get(self, agent_id):
        """
        获取菜单

        https://work.weixin.qq.com/api/doc#90000/90135/90232

        :param agent_id: 应用id
        """
        return self._get("menu/get", params={"agentid": agent_id})

    def delete(self, agent_id):
        """
        删除菜单

        https://work.weixin.qq.com/api/doc#90000/90135/90233

        :param agent_id: 应用id
        """
        return self._get("menu/delete", params={"agentid": agent_id})

    def update(self, agent_id, menu_data):
        self.delete(agent_id)
        return self.create(agent_id, menu_data)
<commit_msg>更新 WeChatMenu (#723)<commit_after># -*- coding: utf-8 -*-

from wechatpy.client.api.base import BaseWeChatAPI

class WeChatMenu(BaseWeChatAPI):
    """
    自定义菜单
    """

    def create(self, agent_id: int, menu_data: dict) -> dict:
        """
        创建菜单

        详情请参考：
        https://developer.work.weixin.qq.com/document/path/90231

        :param agent_id: 应用id
        """
        return self._post("menu/create", params={"agentid": agent_id}, data=menu_data)

    def get(self, agent_id: int) -> dict:
        """
        获取菜单

        详情请参考：
        https://developer.work.weixin.qq.com/document/path/90232

        :param agent_id: 应用id
        """
        return self._get("menu/get", params={"agentid": agent_id})

    def delete(self, agent_id: int) -> dict:
        """
        删除菜单

        详情请参考：
        https://developer.work.weixin.qq.com/document/path/90233

        :param agent_id: 应用id
        """
        return self._get("menu/delete", params={"agentid": agent_id})

    def update(self, agent_id: int, menu_data: dict) -> dict:
        self.delete(agent_id)
        return self.create(agent_id, menu_data)
<|endoftext|>


<commit_before>#!/usr/bin/env python3

import os, sys, subprocess, datetime

def full_print(kernel=True, fqdn=True, uptime=True, date=True, ipaddr=True, iproute=True):
    print('Kernel: {0}-{1}'.format(*get_kernel()))
    print('Hostname: {0}.{1}.{2}'.format(*get_fqdn()))
    print('Uptime: {days} Days, {hours} Hours, {mins} Minutes'.format(**get_uptime()))

def get_kernel():
    kernel =  subprocess.check_output(['uname', '-r']).decode('utf-8').strip('\n')
    kernel = kernel.split('-')
    return kernel

def get_fqdn():
    fqdn = subprocess.check_output(['hostname', '-f']).decode('utf-8').strip('\n')
    fqdn = fqdn.split('.')
    return fqdn

def get_uptime():
    uptime = subprocess.check_output(['uptime', '-p']).decode('utf-8').strip('\n')
    uptime = uptime.replace(',', '')
    uptime = uptime.split()
    return {'days':int(uptime[1]), 'hours':int(uptime[3]), 'mins':int(uptime[5])}

def get_date():
    dt = str(datetime.datetime.now()).split()
    dt[1] = dt[1].split('.')[0]
    return dt

def get_ip_addr():
    addr = subprocess.check_output(['ip', 'addr']).decode('utf-8').strip('\n')
    addr = addr.split('\n')
    addrs = {}
    for line in addr:
        if line[0].isdigit():
            iface = line.split()[1].strip(':')
            addrs[iface] = {'ipv6':[], 'ipv4':[]}
        if 'inet6' in line:
            address = line.split()[1].split('/')
            addrs[iface]['ipv6'].append(address)
        elif 'inet' in line:
            address = line.split()[1].split('/')
            addrs[iface]['ipv4'].append(address)
    return addrs

def get_ip_route():
    route = subprocess.check_output(['ip', 'route']).decode('utf-8').strip('\n')
    route = route.split('\n')
    routes = {}
    for line in route:
        info = line.split()
        name = info[0]
        routes[name] = {}
        for i in range(1,len(info)):
            if info[i] == 'dev':
                routes[name]['dev'] = info[i+1]
            elif info[i] == 'via':
                routes[name]['via'] = info[i+1]
            elif info[i] == 'src':
                routes[name]['src'] = info[i+1]
    return routes

if __name__ == '__main__':
    #print(get_kernel())
    #print(get_fqdn())
    #print(get_uptime())
    #print(get_date())
    #print(get_ip_addr())
    #print(get_ip_route())
    full_print()
<commit_msg>privateish functions<commit_after>#!/usr/bin/env python3

import os, sys, subprocess, datetime

def full_print(kernel=True, fqdn=True, uptime=True, date=True, ipaddr=True, iproute=True):
    print('Kernel: {0}-{1}'.format(*_get_kernel()))
    print('Hostname: {0}.{1}.{2}'.format(*_get_fqdn()))
    print('Uptime: {days} Days, {hours} Hours, {mins} Minutes'.format(**_get_uptime()))
    print('Date: {0} {1}'.format(*_get_date()))

def _get_kernel():
    kernel =  subprocess.check_output(['uname', '-r']).decode('utf-8').strip('\n')
    kernel = kernel.split('-')
    return kernel

def _get_fqdn():
    fqdn = subprocess.check_output(['hostname', '-f']).decode('utf-8').strip('\n')
    fqdn = fqdn.split('.')
    return fqdn

def _get_uptime():
    uptime = subprocess.check_output(['uptime', '-p']).decode('utf-8').strip('\n')
    uptime = uptime.replace(',', '')
    uptime = uptime.split()
    return {'days':int(uptime[1]), 'hours':int(uptime[3]), 'mins':int(uptime[5])}

def _get_date():
    dt = str(datetime.datetime.now()).split()
    dt[1] = dt[1].split('.')[0]
    return dt

def _get_ip_addr():
    addr = subprocess.check_output(['ip', 'addr']).decode('utf-8').strip('\n')
    addr = addr.split('\n')
    addrs = {}
    for line in addr:
        if line[0].isdigit():
            iface = line.split()[1].strip(':')
            addrs[iface] = {'ipv6':[], 'ipv4':[]}
        if 'inet6' in line:
            address = line.split()[1].split('/')
            addrs[iface]['ipv6'].append(address)
        elif 'inet' in line:
            address = line.split()[1].split('/')
            addrs[iface]['ipv4'].append(address)
    return addrs

def _get_ip_route():
    route = subprocess.check_output(['ip', 'route']).decode('utf-8').strip('\n')
    route = route.split('\n')
    routes = {}
    for line in route:
        info = line.split()
        name = info[0]
        routes[name] = {}
        for i in range(1,len(info)):
            if info[i] == 'dev':
                routes[name]['dev'] = info[i+1]
            elif info[i] == 'via':
                routes[name]['via'] = info[i+1]
            elif info[i] == 'src':
                routes[name]['src'] = info[i+1]
    return routes

if __name__ == '__main__':
    #print(_get_kernel())
    #print(_get_fqdn())
    #print(_get_uptime())
    #print(_get_date())
    #print(_get_ip_addr())
    #print(_get_ip_route())
    full_print()
<|endoftext|>


<commit_before>
from IPython.display import Javascript, display

__has_initialized__ = False

def init():
    # FIXME
    # Loads the JS extensions. This is still a bit of a
    # hack: calls to gmaps methods cannot occur in the
    # same cell as the import statement.
    #
    # Potential alternatives would be to re-factor the
    # init statement into a line magic.
    global __has_initialized__
    if not __has_initialized__:
        display(Javascript("""
            IPython.load_extensions('gmaps_js/gmaps_views')
            """))
        __has_initialized__ = True

<commit_msg>Adapted loader to work with ipython 4<commit_after>
from IPython.display import Javascript, display
from ipywidgets import widget

__has_initialized__ = False

def init():
    # FIXME
    # Loads the JS extensions. This is still a bit of a
    # hack: calls to gmaps methods cannot occur in the
    # same cell as the import statement.
    #
    # Potential alternatives would be to re-factor the
    # init statement into a line magic.
    global __has_initialized__
    if not __has_initialized__:
        display(Javascript("""
            require(['base/js/utils'],
            function(utils) {
                utils.load_extensions('gmaps_js/gmaps_views');
            });
            """))
        __has_initialized__ = True

<|endoftext|>


<commit_before>import sys
import random
from pytz import timezone
import datetime
from datetime import datetime
import pytz
from libs import post_text
import spotipy
import os
from spotipy.oauth2 import SpotifyClientCredentials

username = os.environ.get("USERNAME")
client_id = os.environ.get("SPOTIPY_CLIENT_ID")
client_secret = os.environ.get("SPOTIPY_CLIENT_SECRET")
playlist_id = os.environ.get("SPOTIPY_PLAYLIST_ID")
client_credentials_manager = SpotifyClientCredentials()
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)

def post_rand_song():
    results = sp.user_playlist(username, playlist_id, 'tracks,next')
    tracks = results['tracks']
    all_tracks = tracks['items']
    while tracks['next']:
        tracks = sp.next(tracks)
        all_tracks += tracks['items']

    random_track = random.choice(all_tracks)
    post_text(u'\U0001F3B5\U0001F4C5: ' + random_track['track']['name'] + ' - ' + random_track['track']['artists'][0]['name'] , sys.argv[1])
"""' ' + random_track['track']['external_urls']['spotify']"""
<commit_msg>Moar Tests<commit_after>import sys
import random
from pytz import timezone
import datetime
from datetime import datetime
import pytz
from libs import post_text
import spotipy
import os
from spotipy.oauth2 import SpotifyClientCredentials

username = os.environ.get("USERNAME")
client_id = os.environ.get("SPOTIPY_CLIENT_ID")
client_secret = os.environ.get("SPOTIPY_CLIENT_SECRET")
playlist_id = os.environ.get("SPOTIPY_PLAYLIST_ID")
client_credentials_manager = SpotifyClientCredentials()
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)

def post_rand_song():
    results = sp.user_playlist(username, playlist_id, 'tracks,next')
    tracks = results['tracks']
    all_tracks = tracks['items']
    while tracks['next']:
        tracks = sp.next(tracks)
        all_tracks += tracks['items']

    random_track = random.choice(all_tracks)
    post_text("test", sys.arg[1])
    """post_text(u'\U0001F3B5\U0001F4C5: ' + random_track['track']['name'] + ' - ' + random_track['track']['artists'][0]['name']
    + ' ' + random_track['track']['external_urls']['spotify'], sys.argv[1])"""
<|endoftext|>


<commit_before>from django.contrib import admin

from .models import Candidate, Election, CandidateBallot, Proposition, PropositionBallot

admin.site.register(Election)
admin.site.register(Candidate)
admin.site.register(CandidateBallot)
admin.site.register(Proposition)
admin.site.register(PropositionBallot)<commit_msg>remove ballots<commit_after>from django.contrib import admin

from .models import Candidate, Election, CandidateBallot, Proposition, PropositionBallot

admin.site.register(Election)
admin.site.register(Candidate)
# admin.site.register(CandidateBallot)
admin.site.register(Proposition)
# admin.site.register(PropositionBallot)<|endoftext|>


<commit_before>import base64
import json
import re
import tornado.gen as gen
import os
import subprocess

from collections import namedtuple
from notebook.base.handlers import APIHandler, app_log

from jupyterlab_gitsync.version import VERSION

class SyncHandler(APIHandler):

  """
  Implements all synchronization operations
  * uses git-sync-changes bash script
  """

  @gen.coroutine
  def post(self, *args, **kwargs):
    recv = self.get_json_body()
    path = recv['path'] if recv['path'] else '.'
    ex_path = recv['ex_path'] if recv['ex_path'] else None
    options = recv['options'] if recv['options'] else []

    try:
      return_code = subprocess.call([ex_path]+options, cwd=path)
      if return_code == 0:
        self.finish({'success': True})
      else:
        self.finish({'conflict': True})
    except Exception as e:
      self.finish({'error': str(e)})

class SetupHandler(APIHandler):

  """
  Sets up environment for extension to run
  * verify that working path is a git repo
  * returns executable path for sync
  """

  def inside_git_repo(self, path):
    return_code = subprocess.call(['git', 'rev-parse'], cwd=path)
    return return_code == 0

  def add_sync_command(self):
    cwd = os.getcwd()
    ex_path = 'jupyterlab_gitsync/jupyterlab_gitsync/git-sync-changes/git-sync-changes'
    return os.path.join(cwd, ex_path)

  @gen.coroutine
  def post(self, *args, **kwargs):
    recv = self.get_json_body()
    path = recv['path'] if recv['path'] else '.'

    try:
      if self.inside_git_repo(path):
        ex_path = self.add_sync_command()
        self.finish({'ex_path': ex_path})
      else:
        self.finish({'error': 'Given path is not a git repository.'})
    except Exception as e:
      self.finish({'error': str(e)})

<commit_msg>change helper function name<commit_after>import base64
import json
import re
import tornado.gen as gen
import os
import subprocess

from collections import namedtuple
from notebook.base.handlers import APIHandler, app_log

from jupyterlab_gitsync.version import VERSION

class SyncHandler(APIHandler):

  """
  Implements all synchronization operations
  * uses git-sync-changes bash script
  """

  @gen.coroutine
  def post(self, *args, **kwargs):
    recv = self.get_json_body()
    path = recv['path'] if recv['path'] else '.'
    ex_path = recv['ex_path'] if recv['ex_path'] else None
    options = recv['options'] if recv['options'] else []

    try:
      return_code = subprocess.call([ex_path]+options, cwd=path)
      if return_code == 0:
        self.finish({'success': True})
      else:
        self.finish({'conflict': True})
    except Exception as e:
      self.finish({'error': str(e)})

class SetupHandler(APIHandler):

  """
  Sets up environment for extension to run
  * verify that working path is a git repo
  * returns executable path for sync
  """

  def inside_git_repo(self, path):
    return_code = subprocess.call(['git', 'rev-parse'], cwd=path)
    return return_code == 0

  def get_sync_path(self):
    cwd = os.getcwd()
    ex_path = 'jupyterlab_gitsync/jupyterlab_gitsync/git-sync-changes/git-sync-changes'
    return os.path.join(cwd, ex_path)

  @gen.coroutine
  def post(self, *args, **kwargs):
    recv = self.get_json_body()
    path = recv['path'] if recv['path'] else '.'

    try:
      if self.inside_git_repo(path):
        ex_path = self.get_sync_path()
        self.finish({'ex_path': ex_path})
      else:
        self.finish({'error': 'Given path is not a git repository.'})
    except Exception as e:
      self.finish({'error': str(e)})

<|endoftext|>


<commit_before>from telegram.ext import MessageHandler

from oracles.color import ColorOracle
from oracles.element import ElementOracle
from oracles.number import NumberOracle
from oracles.place import PlaceOracle
from oracles.question import QuestionOracle

class OracleMessageHandler(MessageHandler):
    def __init__(self):
        super().__init__(None, self.callback)

    @classmethod
    def callback(cls, bot, update):
        update.message.text = cls.sanitize_message(update.message.text, bot.username)
        message = update.message.text
        if message.endswith("?"):
            if message.startswith("dove "):
                return PlaceOracle.from_env(bot, update).handle()
            return QuestionOracle(bot, update).handle()
        elif update.message.new_chat_members:
            return cls.greetings(bot, update)
        elif any(x in message for x in ["scegl", "trov", "estra"]):
            return cls.choice(bot, update)
        elif any(x in message for x in [", ", " o ", " oppure "]):
            return ElementOracle(bot, update).handle()

    @staticmethod
    def choice(bot, update):
        message = update.message.text
        if "numer" in message:
            NumberOracle(bot, update).handle()
        elif "color" in message:
            ColorOracle(bot, update).handle()
        elif any(x in message for x in [",", " o ", " oppure "]):
            ElementOracle(bot, update).handle()

    @staticmethod
    def greetings(bot, update):
        if bot.username in update.message.new_chat_participant.username:
            message = "Salve" + (" a tutti" if update.message.chat.type == "group" else "") + "! Posso essere d'aiuto?"
            bot.send_message(update.message.chat_id, text=message)

    @staticmethod
    def sanitize_message(text, bot_username):
        sanitized_message = text.lower()
        sanitized_message.replace(f'@{bot_username}')
        return sanitized_message
<commit_msg>Improved sanitize message<commit_after>from telegram.ext import MessageHandler

from oracles.color import ColorOracle
from oracles.element import ElementOracle
from oracles.number import NumberOracle
from oracles.place import PlaceOracle
from oracles.question import QuestionOracle

class OracleMessageHandler(MessageHandler):
    def __init__(self):
        super().__init__(None, self.callback)

    @classmethod
    def callback(cls, bot, update):
        update.message.text = cls.sanitize_message(update.message.text, bot.username)
        message = update.message.text
        if message.endswith("?"):
            if message.startswith("dove "):
                return PlaceOracle.from_env(bot, update).handle()
            return QuestionOracle(bot, update).handle()
        elif update.message.new_chat_members:
            return cls.greetings(bot, update)
        elif any(x in message for x in ["scegl", "trov", "estra"]):
            return cls.choice(bot, update)
        elif any(x in message for x in [", ", " o ", " oppure "]):
            return ElementOracle(bot, update).handle()

    @staticmethod
    def choice(bot, update):
        message = update.message.text
        if "numer" in message:
            NumberOracle(bot, update).handle()
        elif "color" in message:
            ColorOracle(bot, update).handle()
        elif any(x in message for x in [",", " o ", " oppure "]):
            ElementOracle(bot, update).handle()

    @staticmethod
    def greetings(bot, update):
        if bot.username in update.message.new_chat_participant.username:
            message = "Salve" + (" a tutti" if update.message.chat.type == "group" else "") + "! Posso essere d'aiuto?"
            bot.send_message(update.message.chat_id, text=message)

    @staticmethod
    def sanitize_message(text, bot_username):
        return text.lower().replace(f'@{bot_username}', '').strip()
<|endoftext|>


<commit_before>import re

class MessageParser:
	def __init__(self):
		self.MAX_MENTION_LENGTH = '15'

		self.mentions_regex = '(?<!\S)(@[A-Za-z0-9_]{1,'+self.MAX_MENTION_LENGTH+'})'
		self.topics_regex =  '(?<!\S)(#\S+)'
		self.uri_regex = '(?<!\S)(https?:\/\/\S+)'

	def _get_mentions_from_msg(self, message):
		mentions_regex = re.compile(self.mentions_regex)
		mentions = re.findall(mentions_regex, message)
		print mentions
		return mentions

	def _get_topics_from_msg(self, message):
		topics_regex = re.compile(self.topics_regex)
		topics = re.findall(topics_regex, message)
		return topics

	def _get_uris_from_msg(self, message):
		uri_regex = re.compile(self.uri_regex)
		uris = re.findall(uri_regex, message)
		return uris

	def parse_message(self, message):
		parsedMessage = {
			'msg_text': message,
			'mentions': self._get_mentions_from_msg(message),
			'topics': self._get_topics_from_msg(message),
			'uris': self._get_uris_from_msg(message)
		}
		return parsedMessage

	def batch_parse_message(self, messages):
		parsedMessages = []
		for msg in messages:
			parsed_msg = {
				'msg_text': u'msg',
				'mentions': self._get_mentions_from_msg(msg),
				'topics': self._get_topics_from_msg(msg),
				'uris': self._get_uris_from_msg(msg),
			}
			parsedMessages.append(parsed_msg)
		return parsedMessages<commit_msg>update message_parser module so tests pass<commit_after>import re

class MessageParseError(Exception):
	def __init__(self, value):
		self.value = value

	def __str__(self):
		return repr(self.value)

class MessageParser:
	def __init__(self):
		self.MAX_MENTION_LENGTH = '15'
		self.MAX_TOPIC_LENGTH = '15'
		self.MAX_URI_LENGTH = '23'

		self.mentions_regex = '(?<!\S)(@[A-Za-z0-9_]{1,'+self.MAX_MENTION_LENGTH+'})'
		self.topics_regex =  '(?<!\S)(#[A-Za-z0-9_]{1,'+self.MAX_TOPIC_LENGTH+'})'
		self.uri_regex = '(?<!\S)(https?:\/\/\S{1,'+self.MAX_URI_LENGTH+'})'

	def _get_mentions_from_msg(self, message):
		mentions_regex = re.compile(self.mentions_regex)
		mentions = re.findall(mentions_regex, message)
		return mentions

	def _get_topics_from_msg(self, message):
		topics_regex = re.compile(self.topics_regex)
		topics = re.findall(topics_regex, message)
		return topics

	def _get_uris_from_msg(self, message):
		uri_regex = re.compile(self.uri_regex)
		uris = re.findall(uri_regex, message)
		return uris

	def parse_message(self, message):
		if type(message) is str:
			parsed_message = {
				'msg_text': message,
				'mentions': self._get_mentions_from_msg(message),
				'topics': self._get_topics_from_msg(message),
				'uris': self._get_uris_from_msg(message)
			}
			return parsed_message
		else:
			raise MessageParseError('message must be of type str')

	def batch_parse_message(self, messages):
		parsed_messages = []
		if type(messages) is list:
			for msg in messages:
				parsed_msg = self.parse_message(msg)
				parsed_messages.append(parsed_msg)
			return parsed_messages
		else:
			raise MessageParseError('arg for batch_parse must be list')<|endoftext|>


<commit_before>
import numpy as np
from scipy.optimize import brentq

from .hann_dft import FilteredDFT, FilteredWaveDFT

class SolverError(Exception):
    pass

class FrequencyEquation:
    def __init__(self, wave_dft, k, coeff_ratio):
        self.wave_dft = wave_dft
        self.k = k
        self.coeff_ratio = coeff_ratio

    def __call__(self, omega):
        numer = (abs(self.wave_dft.filtered_coeff(omega, self.k)) +
                 abs(self.wave_dft.filtered_coeff(omega, self.k-1)))
        denom = (abs(self.wave_dft.filtered_coeff(omega, self.k)) +
                 abs(self.wave_dft.filtered_coeff(omega, self.k+1)))
        analytic_ratio = numer / denom

        return analytic_ratio - self.coeff_ratio

class SpectralAnalysis:
    def __init__(self, signal, p=4, dt=1.0):
        self.signal = signal
        self.p = p
        self.dt = dt

        self.data_dft = FilteredDFT(self.signal, self.dt, self.p)
        self.wave_dft = FilteredWaveDFT(self.data_dft.N, self.data_dft.T,
                                        self.p)

    def reset(self):
        self.data_dft = FilteredDFT(self.signal, self.dt, self.p)
        self.wave_dft = FilteredWaveDFT(self.data_dft.N, self.data_dft.T,
                                        self.p)

    def compute_frequency(self, return_k=False, solver_xtol=5e-16):
        k, ratio = self.select_ratio()
        equation = FrequencyEquation(self.wave_dft, k, ratio)

        limit_shift = 1e-14
        om_min = self.data_dft.freqs[k - 1] + limit_shift
        om_max = self.data_dft.freqs[k + 1] - limit_shift

        try:
            omega = brentq(equation, om_min, om_max, xtol=solver_xtol)
        except ValueError:
            if self.p > 1:
                raise SolverError
            msg = "Warning: solver failed for p={}, using fallback solver"
            print(msg.format(self.p))
            return self.fallback_solver(return_k, solver_xtol)

        if return_k:
            return omega, k
        else:
            return omega

    def fallback_solver(self, return_k=False, solver_xtol=5e-16):
        dft = self.data_dft.dft
        coeffs = np.abs(dft - (np.roll(dft, -1) + np.roll(dft, 1)) / 2)
        k = coeffs.argmax()

        limit_shift = 1e-14
        om_min = self.data_dft.freqs[k - 1] + limit_shift
        om_max = self.data_dft.freqs[k + 1] - limit_shift

        ratio = (coeffs[k] + coeffs[k - 1]) / (coeffs[k] + coeffs[k + 1])
        wave_dft = FilteredWaveDFT(self.data_dft.N, self.data_dft.T, 1)
        equation = FrequencyEquation(wave_dft, k, ratio)

        try:
            omega = brentq(equation, om_min, om_max, xtol=solver_xtol)
        except ValueError:
            raise SolverError

        if return_k:
            return omega, k
        else:
            return omega

    def extract_frequency(self, return_ampl=False):
        omega, k = self.compute_frequency(True)
        indices = np.arange(self.wave_dft.N)

        wave_dft = self.wave_dft.fourier_coeff(omega, indices)
        wave_dft_conj = np.insert(wave_dft[1:][::-1], 0,
                                  wave_dft[0]).conj()

        filtered_wave_dft = self.wave_dft.filtered_coeff(omega, indices)
        filtered_wave_dft_conj = np.insert(filtered_wave_dft[1:][::-1], 0,
                                           filtered_wave_dft[0]).conj()

        amplitude = self.data_dft.filtered_dft[k] / filtered_wave_dft[k]
        amplitude_conj = self.data_dft.filtered_dft[-k] / \
                         filtered_wave_dft_conj[-k]

        self.data_dft.dft -= amplitude * wave_dft + amplitude_conj * wave_dft_conj
        self.data_dft.filtered_dft -= (amplitude * filtered_wave_dft +
                                       amplitude_conj * filtered_wave_dft_conj)

        if return_ampl:
            return omega, amplitude, amplitude_conj
        else:
            return omega

    def select_ratio(self):
        # TODO: ignore coefficients F[-p:p+1] ? (constant mode problem)
        coeffs = np.abs(self.data_dft.filtered_dft)
        coeffs[:self.p + 1] = 0.0
        coeffs[::-1][:self.p + 1] = 0.0

        k = coeffs.argmax()
        ratio = (coeffs[k] + coeffs[k - 1]) / (coeffs[k] + coeffs[k + 1])

        return k, ratio

    def frequencies(self, n_freqs, coeff_limit=1e-10, return_ampl=False):
        for i in range(n_freqs):
            if np.abs(self.data_dft.filtered_dft).max() > coeff_limit:
                yield self.extract_frequency(return_ampl)
            else:
                break<commit_msg>minor cleanup<commit_after>
import numpy as np
from scipy.optimize import brentq

from .hann_dft import FilteredDFT, FilteredWaveDFT

class SolverError(Exception):
    pass

class FrequencyEquation:
    def __init__(self, wave_dft, k, coeff_ratio):
        self.wave_dft = wave_dft
        self.k = k
        self.coeff_ratio = coeff_ratio

    def __call__(self, omega):
        numer = (abs(self.wave_dft.filtered_coeff(omega, self.k)) +
                 abs(self.wave_dft.filtered_coeff(omega, self.k - 1)))
        denom = (abs(self.wave_dft.filtered_coeff(omega, self.k)) +
                 abs(self.wave_dft.filtered_coeff(omega, self.k + 1)))
        analytic_ratio = numer / denom

        return analytic_ratio - self.coeff_ratio

class SpectralAnalysis:
    def __init__(self, signal, p=4, dt=1.0):
        self.signal = signal
        self.p = p
        self.dt = dt

        self.data_dft = FilteredDFT(self.signal, self.dt, self.p)
        self.wave_dft = FilteredWaveDFT(self.data_dft.N, self.data_dft.T,
                                        self.p)

    def reset(self):
        self.data_dft = FilteredDFT(self.signal, self.dt, self.p)
        self.wave_dft = FilteredWaveDFT(self.data_dft.N, self.data_dft.T,
                                        self.p)

    def compute_frequency(self, return_k=False, solver_xtol=5e-16):
        k, ratio = self.select_ratio()
        equation = FrequencyEquation(self.wave_dft, k, ratio)

        limit_shift = 1e-14
        om_min = self.data_dft.freqs[k - 1] + limit_shift
        om_max = self.data_dft.freqs[k + 1] - limit_shift

        try:
            omega = brentq(equation, om_min, om_max, xtol=solver_xtol)
        except ValueError:
            if self.p > 1:
                raise SolverError
            msg = "Warning: solver failed for p={}, using fallback solver"
            print(msg.format(self.p))
            return self.fallback_solver(return_k, solver_xtol)

        if return_k:
            return omega, k
        else:
            return omega

    def fallback_solver(self, return_k=False, solver_xtol=5e-16):
        dft = self.data_dft.dft
        coeffs = np.abs(dft - (np.roll(dft, -1) + np.roll(dft, 1)) / 2)
        k = coeffs.argmax()

        limit_shift = 1e-14
        om_min = self.data_dft.freqs[k - 1] + limit_shift
        om_max = self.data_dft.freqs[k + 1] - limit_shift

        ratio = (coeffs[k] + coeffs[k - 1]) / (coeffs[k] + coeffs[k + 1])
        wave_dft = FilteredWaveDFT(self.data_dft.N, self.data_dft.T, 1)
        equation = FrequencyEquation(wave_dft, k, ratio)

        try:
            omega = brentq(equation, om_min, om_max, xtol=solver_xtol)
        except ValueError:
            raise SolverError

        if return_k:
            return omega, k
        else:
            return omega

    def extract_frequency(self, return_ampl=False):
        omega, k = self.compute_frequency(True)
        indices = np.arange(self.wave_dft.N)

        wave_dft = self.wave_dft.fourier_coeff(omega, indices)
        wave_dft_conj = np.insert(wave_dft[1:][::-1], 0,
                                  wave_dft[0]).conj()

        filtered_wave_dft = self.wave_dft.filtered_coeff(omega, indices)
        filtered_wave_dft_conj = np.insert(filtered_wave_dft[1:][::-1], 0,
                                           filtered_wave_dft[0]).conj()

        amplitude = self.data_dft.filtered_dft[k] / filtered_wave_dft[k]
        amplitude_conj = (self.data_dft.filtered_dft[-k] /
                          filtered_wave_dft_conj[-k])

        self.data_dft.dft -= (amplitude * wave_dft +
                              amplitude_conj * wave_dft_conj)
        self.data_dft.filtered_dft -= (amplitude * filtered_wave_dft +
                                       amplitude_conj * filtered_wave_dft_conj)

        if return_ampl:
            return omega, amplitude, amplitude_conj
        else:
            return omega

    def select_ratio(self):
        # TODO: ignore coefficients F[-p:p+1] ? (constant mode problem)
        coeffs = np.abs(self.data_dft.filtered_dft)
        coeffs[:self.p + 1] = 0.0
        coeffs[::-1][:self.p + 1] = 0.0

        k = coeffs.argmax()
        ratio = (coeffs[k] + coeffs[k - 1]) / (coeffs[k] + coeffs[k + 1])

        return k, ratio

    def frequencies(self, n_freqs, coeff_limit=1e-10, return_ampl=False):
        for i in range(n_freqs):
            if np.abs(self.data_dft.filtered_dft).max() > coeff_limit:
                yield self.extract_frequency(return_ampl)
            else:
                break
<|endoftext|>


<commit_before>#!/usr/bin/python3.4
from flask import Flask, render_template, url_for, Markup, abort, send_file
from flask.ext.libsass import *
import pkg_resources, socket

import markdown
from markdown.extensions.headerid import HeaderIdExtension

from slimit import minify

from PIL import Image
import io

from vishwin_http import app

Sass(
	{'app': 'scss/app.scss'},
	app,
	url_path='/static/css',
	include_paths=[pkg_resources.resource_filename('vishwin_http.views', 'scss')],
	output_style='compressed'
)

@app.route('/static/js/<js>')
def render_js(js):
	try:
		fd=open(pkg_resources.resource_filename('vishwin_http.views', 'js/' + js), encoding='UTF-8')
		out=minify(fd.read(), mangle=True, mangle_toplevel=True)
		fd.close()
		return out
	except OSError:
		abort(404)

@app.route('/static/img/<width>px-<imgfile>')
def render_thumb(width, imgfile):
	try:
		img=Image.open(pkg_resources.resource_filename('vishwin_http.views', 'img/' + imgfile))
		imgIO=io.BytesIO()
		img.thumbnail((int(width), int(width)/(img.size[0]/img.size[1])))
		img.save(imgIO, img.format)
		img.close()
		imgIO.seek(0)
		return send_file(imgIO, mimetype='image/jpeg')
	except IOError:
		abort(404)

@app.route('/<page>')
def get_page(page):
	try:
		md=open(pkg_resources.resource_filename('vishwin_http.views', 'pages/' + page + '.md'), encoding='UTF-8')
		html=Markup(markdown.markdown(md.read(), output_format='html5', extensions=['markdown.extensions.attr_list', 'markdown.extensions.def_list', 'markdown.extensions.fenced_code', 'markdown.extensions.tables', 'markdown.extensions.toc', HeaderIdExtension(level=2)]))
		md.close()
		if page=='index':
			return render_template('page.html', hostname=socket.gethostname(), content=html)
		return render_template('page.html', hostname=socket.gethostname(), content=html, title=page)
	except OSError:
		abort(404)

@app.route('/')
def index():
	return get_page('index')
<commit_msg>Correct response mimetype<commit_after>#!/usr/bin/python3.4
from flask import Flask, render_template, Response, url_for, Markup, abort, send_file
from flask.ext.libsass import *
import pkg_resources, socket

import markdown
from markdown.extensions.headerid import HeaderIdExtension

from slimit import minify

from PIL import Image
import io

from vishwin_http import app

Sass(
	{'app': 'scss/app.scss'},
	app,
	url_path='/static/css',
	include_paths=[pkg_resources.resource_filename('vishwin_http.views', 'scss')],
	output_style='compressed'
)

@app.route('/static/js/<js>')
def render_js(js):
	try:
		fd=open(pkg_resources.resource_filename('vishwin_http.views', 'js/' + js), encoding='UTF-8')
		out=minify(fd.read(), mangle=True, mangle_toplevel=True)
		fd.close()
		return Response(response=out, mimetype='text/javascript')
	except OSError:
		abort(404)

@app.route('/static/img/<width>px-<imgfile>')
def render_thumb(width, imgfile):
	try:
		img=Image.open(pkg_resources.resource_filename('vishwin_http.views', 'img/' + imgfile))
		imgIO=io.BytesIO()
		img.thumbnail((int(width), int(width)/(img.size[0]/img.size[1])))
		img.save(imgIO, img.format)
		img.close()
		imgIO.seek(0)
		return send_file(imgIO, mimetype='image/jpeg')
	except IOError:
		abort(404)

@app.route('/<page>')
def get_page(page):
	try:
		md=open(pkg_resources.resource_filename('vishwin_http.views', 'pages/' + page + '.md'), encoding='UTF-8')
		html=Markup(markdown.markdown(md.read(), output_format='html5', extensions=['markdown.extensions.attr_list', 'markdown.extensions.def_list', 'markdown.extensions.fenced_code', 'markdown.extensions.tables', 'markdown.extensions.toc', HeaderIdExtension(level=2)]))
		md.close()
		if page=='index':
			return render_template('page.html', hostname=socket.gethostname(), content=html)
		return render_template('page.html', hostname=socket.gethostname(), content=html, title=page)
	except OSError:
		abort(404)

@app.route('/')
def index():
	return get_page('index')
<|endoftext|>


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

@author: moschlar
"""
import os

from tg import expose, flash, require, url, lurl, request, redirect, app_globals as g, abort, tmpl_context as c
from tg.decorators import paginate
from tg.i18n import ugettext as _, lazy_ugettext as l_
from tgext.admin.controller import AdminController

from docutils.core import publish_string
from webhelpers.html.tags import ul, link_to

from sauce import model
from sauce.lib.base import BaseController
from sauce.model import DBSession, metadata, NewsItem
from sauce.controllers.error import ErrorController
from sauce.controllers.submissions import SubmissionsController
from sauce.controllers.events import EventsController
from sauce.controllers.user import UserController
from sauce.controllers.language import LanguagesController
from sauce.lib.menu import menu_docs
from sauce.config.admin import SAUCEAdminConfig

__all__ = ['RootController']

class RootController(BaseController):
    """
    The root controller for the SAUCE application.

    All the other controllers and WSGI applications should be mounted on this
    controller. For example::

        panel = ControlPanelController()
        another_app = AnotherWSGIApplication()

    Keep in mind that WSGI applications shouldn't be mounted directly: They
    must be wrapped around with :class:`tg.controllers.WSGIAppController`.

    """
    admin = AdminController(model, DBSession, SAUCEAdminConfig)

    error = ErrorController()

    # OUR CONTROLLERS
    #assignments = AssignmentsController()
    submissions = SubmissionsController()
    events = EventsController()
    #scores = ScoresController()
    user = UserController()
    languages = LanguagesController()

    @expose('sauce.templates.index')
    def index(self):
        """Handle the front-page."""
        return dict(page='index')

    @expose('sauce.templates.about')
    def about(self):
        c.side_menu = c.doc_menu
        return dict(page='about')

    @expose('sauce.templates.page')
    def docs(self, arg=''):
        page_title = u'SAUCE Documentation'
        page_header = u''

        if arg:
            try:
                f = open(os.path.join(g.loc, 'docs', arg + '.rst'))
            except IOError:
                abort(404)
            else:
                content = publish_string(f.read(), writer_name='html',
                    settings_overrides={'output_encoding': 'unicode'})
                page_title += ' - %s' % arg.capitalize()
        else:
            content = u'
In the menu on the left, you find all kinds of documentation about SAUCE.
'

        c.side_menu = c.doc_menu

        return dict(page='docs', page_title=page_title, page_header=page_header, content=content)

    @expose('sauce.templates.contact')
    def contact(self):
        return dict(page='contact')

    @paginate('news')
    @expose('sauce.templates.news')
    def news(self, page=1):
        '''NewsItem listing page'''

        # TODO: Show non-public NewsItems to "teachers"
        news_query = NewsItem.query.filter(NewsItem.event_id == None).filter_by(public=True)

        #news = Page(news_query, page=page, items_per_page=20)

        return dict(page='news', news=news_query)

    @expose('sauce.templates.login')
    def login(self, came_from=lurl('/')):
        """Start the user login."""
        login_counter = request.environ['repoze.who.logins']
        if login_counter > 0:
            flash(_('Wrong credentials'), 'warning')
        return dict(page='login', login_counter=unicode(login_counter),
                    came_from=came_from)

    @expose()
    def post_login(self, came_from=lurl('/')):
        """
        Redirect the user to the initially requested page on successful
        authentication or redirect her back to the login page if login failed.

        """
        if not request.identity:
            login_counter = request.environ['repoze.who.logins'] + 1
            redirect('/login',
                params=dict(came_from=came_from, __logins=login_counter))
        user = request.user
        flash(_('Welcome back, %s!') % user.display_name)
        redirect(came_from)

    @expose()
    def post_logout(self, came_from=lurl('/')):
        """
        Redirect the user to the initially requested page on logout and say
        goodbye as well.

        """
        flash(_('We hope to see you soon!'))
        redirect(came_from)
<commit_msg>Fix documentation page header<commit_after># -*- coding: utf-8 -*-
"""Main Controller

@author: moschlar
"""
import os

from tg import expose, flash, require, url, lurl, request, redirect, app_globals as g, abort, tmpl_context as c
from tg.decorators import paginate
from tg.i18n import ugettext as _, lazy_ugettext as l_
from tgext.admin.controller import AdminController

from docutils.core import publish_string
from webhelpers.html.tags import ul, link_to

from sauce import model
from sauce.lib.base import BaseController
from sauce.model import DBSession, metadata, NewsItem
from sauce.controllers.error import ErrorController
from sauce.controllers.submissions import SubmissionsController
from sauce.controllers.events import EventsController
from sauce.controllers.user import UserController
from sauce.controllers.language import LanguagesController
from sauce.lib.menu import menu_docs
from sauce.config.admin import SAUCEAdminConfig

__all__ = ['RootController']

class RootController(BaseController):
    """
    The root controller for the SAUCE application.

    All the other controllers and WSGI applications should be mounted on this
    controller. For example::

        panel = ControlPanelController()
        another_app = AnotherWSGIApplication()

    Keep in mind that WSGI applications shouldn't be mounted directly: They
    must be wrapped around with :class:`tg.controllers.WSGIAppController`.

    """
    admin = AdminController(model, DBSession, SAUCEAdminConfig)

    error = ErrorController()

    # OUR CONTROLLERS
    #assignments = AssignmentsController()
    submissions = SubmissionsController()
    events = EventsController()
    #scores = ScoresController()
    user = UserController()
    languages = LanguagesController()

    @expose('sauce.templates.index')
    def index(self):
        """Handle the front-page."""
        return dict(page='index')

    @expose('sauce.templates.about')
    def about(self):
        c.side_menu = c.doc_menu
        return dict(page='about')

    @expose('sauce.templates.page')
    def docs(self, arg=''):
        page_title = u'SAUCE Documentation'
        page_header = u''

        if arg:
            try:
                f = open(os.path.join(g.loc, 'docs', arg + '.rst'))
            except IOError:
                abort(404)
            else:
                content = publish_string(f.read(), writer_name='html',
                    settings_overrides={'output_encoding': 'unicode'})
                page_title += ' - %s' % arg.capitalize()
        else:
            page_header = u'SAUCE Documentation'
            content = u'
In the menu on the left, you find all kinds of documentation about SAUCE.
'

        c.side_menu = c.doc_menu

        return dict(page='docs', page_title=page_title, page_header=page_header, content=content)

    @expose('sauce.templates.contact')
    def contact(self):
        return dict(page='contact')

    @paginate('news')
    @expose('sauce.templates.news')
    def news(self, page=1):
        '''NewsItem listing page'''

        # TODO: Show non-public NewsItems to "teachers"
        news_query = NewsItem.query.filter(NewsItem.event_id == None).filter_by(public=True)

        #news = Page(news_query, page=page, items_per_page=20)

        return dict(page='news', news=news_query)

    @expose('sauce.templates.login')
    def login(self, came_from=lurl('/')):
        """Start the user login."""
        login_counter = request.environ['repoze.who.logins']
        if login_counter > 0:
            flash(_('Wrong credentials'), 'warning')
        return dict(page='login', login_counter=unicode(login_counter),
                    came_from=came_from)

    @expose()
    def post_login(self, came_from=lurl('/')):
        """
        Redirect the user to the initially requested page on successful
        authentication or redirect her back to the login page if login failed.

        """
        if not request.identity:
            login_counter = request.environ['repoze.who.logins'] + 1
            redirect('/login',
                params=dict(came_from=came_from, __logins=login_counter))
        user = request.user
        flash(_('Welcome back, %s!') % user.display_name)
        redirect(came_from)

    @expose()
    def post_logout(self, came_from=lurl('/')):
        """
        Redirect the user to the initially requested page on logout and say
        goodbye as well.

        """
        flash(_('We hope to see you soon!'))
        redirect(came_from)
<|endoftext|>


<commit_before><commit_msg>Tighter tests at the input points<commit_after><|endoftext|>


<commit_before>import re
import sublime

# GoSublime Globals

ANN = 'a18.04.15-1'
VERSION = 'r18.04.15-1'
VERSION_PAT = re.compile(r'\d{2}[.]\d{2}[.]\d{2}-\d+', re.IGNORECASE)
DEFAULT_GO_VERSION = 'go?'
GO_VERSION_OUTPUT_PAT = re.compile(r'go\s+version\s+(\S+(?:\s+[+]\w+|\s+\([^)]+)?)', re.IGNORECASE)
GO_VERSION_NORM_PAT = re.compile(r'[^\w.+-]+', re.IGNORECASE)
PLATFORM = '%s-%s' % (sublime.platform(), sublime.arch())
MARGO_EXE_PREFIX = 'gosublime.margo_'
MARGO_EXE_SUFFIX = '.exe'
MARGO_EXE = MARGO_EXE_PREFIX+VERSION+'_'+DEFAULT_GO_VERSION+MARGO_EXE_SUFFIX
MARGO_EXE_PAT = re.compile(r'^gosublime\.margo.*\.exe$', re.IGNORECASE)

# CEV: Dev Globals

FORCE_INSTALL = False
<commit_msg>GoSubl: bump version to r18.04.15-2<commit_after>import re
import sublime

# GoSublime Globals

ANN = 'a18.04.15-1'
VERSION = 'r18.04.15-2'
VERSION_PAT = re.compile(r'\d{2}[.]\d{2}[.]\d{2}-\d+', re.IGNORECASE)
DEFAULT_GO_VERSION = 'go?'
GO_VERSION_OUTPUT_PAT = re.compile(r'go\s+version\s+(\S+(?:\s+[+]\w+|\s+\([^)]+)?)', re.IGNORECASE)
GO_VERSION_NORM_PAT = re.compile(r'[^\w.+-]+', re.IGNORECASE)
PLATFORM = '%s-%s' % (sublime.platform(), sublime.arch())
MARGO_EXE_PREFIX = 'gosublime.margo_'
MARGO_EXE_SUFFIX = '.exe'
MARGO_EXE = MARGO_EXE_PREFIX+VERSION+'_'+DEFAULT_GO_VERSION+MARGO_EXE_SUFFIX
MARGO_EXE_PAT = re.compile(r'^gosublime\.margo.*\.exe$', re.IGNORECASE)

# CEV: Dev Globals

FORCE_INSTALL = False
<|endoftext|>


<commit_before>from __future__ import division

from .mesh import MeshVisual
import numpy as np
from numpy.linalg import norm
from ..util.transforms import rotate
from ..color import ColorArray

import collections

class TubeVisual(MeshVisual):
    """Displays a tube around a piecewise-linear path.

    The tube mesh is corrected following its Frenet curvature and
    torsion such that it varies smoothly along the curve, including if
    the tube is closed.

    Parameters
    ----------
    points : ndarray
        An array of (x, y, z) points describing the path along which the
        tube will be extruded.
    radius : float | ndarray
        The radius of the tube. Use array of floats as input to set radii of
        points individually. Defaults to 1.0.
    closed : bool
        Whether the tube should be closed, joining the last point to the
        first. Defaults to False.
    color : Color | ColorArray
        The color(s) to use when drawing the tube. The same color is
        applied to each vertex of the mesh surrounding each point of
        the line. If the input is a ColorArray, the argument will be
        cycled; for instance if 'red' is passed then the entire tube
        will be red, or if ['green', 'blue'] is passed then the points
        will alternate between these colours. Defaults to 'purple'.
    tube_points : int
        The number of points in the circle-approximating polygon of the
        tube's cross section. Defaults to 8.
    shading : str | None
        Same as for the `MeshVisual` class. Defaults to 'smooth'.
    vertex_colors: ndarray | None
        Same as for the `MeshVisual` class.
    face_colors: ndarray | None
        Same as for the `MeshVisual` class.
    mode : str
        Same as for the `MeshVisual` class. Defaults to 'triangles'.

    """
    def __init__(self, points, radius=1.0,
                 closed=False,
                 color='purple',
                 tube_points=8,
                 shading='smooth',
                 vertex_colors=None,
                 face_colors=None,
                 mode='triangles'):

        points = np.array(points)

        tangents, normals, binormals = _frenet_frames(points, closed)

        segments = len(points) - 1

        # if single radius, convert to list of radii
        if not isinstance(radius, collections.Iterable):
            radius = [radius] * len(points)
        elif len(radius) != len(points):
            raise ValueError('Length of radii list must match points.')

        # get the positions of each vertex
        grid = np.zeros((len(points), tube_points, 3))
        for i in range(len(points)):
            pos = points[i]
            normal = normals[i]
            binormal = binormals[i]
            r = radius[i]

            # Add a vertex for each point on the circle
            v = np.arange(tube_points,
                          dtype=np.float) / tube_points * 2 * np.pi
            cx = -1. * r * np.cos(v)
            cy = r * np.sin(v)
            grid[i] = (pos + cx[:, np.newaxis]*normal +
                       cy[:, np.newaxis]*binormal)

        # construct the mesh
        indices = []
        for i in range(segments):
            for j in range(tube_points):
                ip = (i+1) % segments if closed else i+1
                jp = (j+1) % tube_points

                index_a = i*tube_points + j
                index_b = ip*tube_points + j
                index_c = ip*tube_points + jp
                index_d = i*tube_points + jp

                indices.append([index_a, index_b, index_d])
                indices.append([index_b, index_c, index_d])

        vertices = grid.reshape(grid.shape[0]*grid.shape[1], 3)

        color = ColorArray(color)
        if vertex_colors is None:
            point_colors = np.resize(color.rgba,
                                     (len(points), 4))
            vertex_colors = np.repeat(point_colors, tube_points, axis=0)

        indices = np.array(indices, dtype=np.uint32)

        MeshVisual.__init__(self, vertices, indices,
                            vertex_colors=vertex_colors,
                            face_colors=face_colors,
                            shading=shading,
                            mode=mode)

def _frenet_frames(points, closed):
    '''Calculates and returns the tangents, normals and binormals for
    the tube.'''
    tangents = np.zeros((len(points), 3))
    normals = np.zeros((len(points), 3))

    epsilon = 0.0001

    # Compute tangent vectors for each segment
    tangents = np.roll(points, -1, axis=0) - np.roll(points, 1, axis=0)
    if not closed:
        tangents[0] = points[1] - points[0]
        tangents[-1] = points[-1] - points[-2]
    mags = np.sqrt(np.sum(tangents * tangents, axis=1))
    tangents /= mags[:, np.newaxis]

    # Get initial normal and binormal
    t = np.abs(tangents[0])

    smallest = np.argmin(t)
    normal = np.zeros(3)
    normal[smallest] = 1.

    vec = np.cross(tangents[0], normal)

    normals[0] = np.cross(tangents[0], vec)

    # Compute normal and binormal vectors along the path
    for i in range(1, len(points)):
        normals[i] = normals[i-1]

        vec = np.cross(tangents[i-1], tangents[i])
        if norm(vec) > epsilon:
            vec /= norm(vec)
            theta = np.arccos(np.clip(tangents[i-1].dot(tangents[i]), -1, 1))
            normals[i] = rotate(-np.degrees(theta),
                                vec)[:3, :3].dot(normals[i])

    if closed:
        theta = np.arccos(np.clip(normals[0].dot(normals[-1]), -1, 1))
        theta /= len(points) - 1

        if tangents[0].dot(np.cross(normals[0], normals[-1])) > 0:
            theta *= -1.

        for i in range(1, len(points)):
            normals[i] = rotate(-np.degrees(theta*i),
                                tangents[i])[:3, :3].dot(normals[i])

    binormals = np.cross(tangents, normals)

    return tangents, normals, binormals
<commit_msg>TubeVisual: convert coordinates to float<commit_after>from __future__ import division

from .mesh import MeshVisual
import numpy as np
from numpy.linalg import norm
from ..util.transforms import rotate
from ..color import ColorArray

import collections

class TubeVisual(MeshVisual):
    """Displays a tube around a piecewise-linear path.

    The tube mesh is corrected following its Frenet curvature and
    torsion such that it varies smoothly along the curve, including if
    the tube is closed.

    Parameters
    ----------
    points : ndarray
        An array of (x, y, z) points describing the path along which the
        tube will be extruded.
    radius : float | ndarray
        The radius of the tube. Use array of floats as input to set radii of
        points individually. Defaults to 1.0.
    closed : bool
        Whether the tube should be closed, joining the last point to the
        first. Defaults to False.
    color : Color | ColorArray
        The color(s) to use when drawing the tube. The same color is
        applied to each vertex of the mesh surrounding each point of
        the line. If the input is a ColorArray, the argument will be
        cycled; for instance if 'red' is passed then the entire tube
        will be red, or if ['green', 'blue'] is passed then the points
        will alternate between these colours. Defaults to 'purple'.
    tube_points : int
        The number of points in the circle-approximating polygon of the
        tube's cross section. Defaults to 8.
    shading : str | None
        Same as for the `MeshVisual` class. Defaults to 'smooth'.
    vertex_colors: ndarray | None
        Same as for the `MeshVisual` class.
    face_colors: ndarray | None
        Same as for the `MeshVisual` class.
    mode : str
        Same as for the `MeshVisual` class. Defaults to 'triangles'.

    """
    def __init__(self, points, radius=1.0,
                 closed=False,
                 color='purple',
                 tube_points=8,
                 shading='smooth',
                 vertex_colors=None,
                 face_colors=None,
                 mode='triangles'):

        # make sure we are working with floats
        points = np.array(points).astype(float)

        tangents, normals, binormals = _frenet_frames(points, closed)

        segments = len(points) - 1

        # if single radius, convert to list of radii
        if not isinstance(radius, collections.Iterable):
            radius = [radius] * len(points)
        elif len(radius) != len(points):
            raise ValueError('Length of radii list must match points.')

        # get the positions of each vertex
        grid = np.zeros((len(points), tube_points, 3))
        for i in range(len(points)):
            pos = points[i]
            normal = normals[i]
            binormal = binormals[i]
            r = radius[i]

            # Add a vertex for each point on the circle
            v = np.arange(tube_points,
                          dtype=np.float) / tube_points * 2 * np.pi
            cx = -1. * r * np.cos(v)
            cy = r * np.sin(v)
            grid[i] = (pos + cx[:, np.newaxis]*normal +
                       cy[:, np.newaxis]*binormal)

        # construct the mesh
        indices = []
        for i in range(segments):
            for j in range(tube_points):
                ip = (i+1) % segments if closed else i+1
                jp = (j+1) % tube_points

                index_a = i*tube_points + j
                index_b = ip*tube_points + j
                index_c = ip*tube_points + jp
                index_d = i*tube_points + jp

                indices.append([index_a, index_b, index_d])
                indices.append([index_b, index_c, index_d])

        vertices = grid.reshape(grid.shape[0]*grid.shape[1], 3)

        color = ColorArray(color)
        if vertex_colors is None:
            point_colors = np.resize(color.rgba,
                                     (len(points), 4))
            vertex_colors = np.repeat(point_colors, tube_points, axis=0)

        indices = np.array(indices, dtype=np.uint32)

        MeshVisual.__init__(self, vertices, indices,
                            vertex_colors=vertex_colors,
                            face_colors=face_colors,
                            shading=shading,
                            mode=mode)

def _frenet_frames(points, closed):
    '''Calculates and returns the tangents, normals and binormals for
    the tube.'''
    tangents = np.zeros((len(points), 3))
    normals = np.zeros((len(points), 3))

    epsilon = 0.0001

    # Compute tangent vectors for each segment
    tangents = np.roll(points, -1, axis=0) - np.roll(points, 1, axis=0)
    if not closed:
        tangents[0] = points[1] - points[0]
        tangents[-1] = points[-1] - points[-2]
    mags = np.sqrt(np.sum(tangents * tangents, axis=1))
    tangents /= mags[:, np.newaxis]

    # Get initial normal and binormal
    t = np.abs(tangents[0])

    smallest = np.argmin(t)
    normal = np.zeros(3)
    normal[smallest] = 1.

    vec = np.cross(tangents[0], normal)

    normals[0] = np.cross(tangents[0], vec)

    # Compute normal and binormal vectors along the path
    for i in range(1, len(points)):
        normals[i] = normals[i-1]

        vec = np.cross(tangents[i-1], tangents[i])
        if norm(vec) > epsilon:
            vec /= norm(vec)
            theta = np.arccos(np.clip(tangents[i-1].dot(tangents[i]), -1, 1))
            normals[i] = rotate(-np.degrees(theta),
                                vec)[:3, :3].dot(normals[i])

    if closed:
        theta = np.arccos(np.clip(normals[0].dot(normals[-1]), -1, 1))
        theta /= len(points) - 1

        if tangents[0].dot(np.cross(normals[0], normals[-1])) > 0:
            theta *= -1.

        for i in range(1, len(points)):
            normals[i] = rotate(-np.degrees(theta*i),
                                tangents[i])[:3, :3].dot(normals[i])

    binormals = np.cross(tangents, normals)

    return tangents, normals, binormals
<|endoftext|>