<commit_before>from rezgui.qt import QtCore, QtGui
import threading

class StreamableTextEdit(QtGui.QTextEdit):
    """A QTextEdit that also acts like a write-only file object.

    The object is threadsafe - write() etc can be called from any thread.
    """
    written = QtCore.Signal()

    def __init__(self, parent=None):
        super(StreamableTextEdit, self).__init__(parent)
        self.setReadOnly(True)
        self.buffer = []
        self.lock = threading.Lock()

        self.written.connect(self._consume)

    # -- file-like methods

    def isatty(self):
        return False

    def write(self, txt):
        try:
            self.lock.acquire()
            self.buffer.append(str(txt))
        finally:
            self.lock.release()
        self.written.emit()

    def _consume(self):
        try:
            self.lock.acquire()
            buffer_ = self.buffer
            self.buffer = []
        finally:
            self.lock.release()
        for txt in buffer_:
            self._write(txt)

    def _write(self, txt):
        self.moveCursor(QtGui.QTextCursor.End)
        self.insertPlainText(txt)
        self.moveCursor(QtGui.QTextCursor.End)
<commit_msg>-fixed a bug in the GUI causing heavy use of streamable text widget to block up the main thread<commit_after>from rezgui.qt import QtCore, QtGui
import threading

class StreamableTextEdit(QtGui.QTextEdit):
    """A QTextEdit that also acts like a write-only file object.

    The object is threadsafe - write() etc can be called from any thread.
    """
    written = QtCore.Signal()

    def __init__(self, parent=None):
        super(StreamableTextEdit, self).__init__(parent)
        self.setReadOnly(True)
        self.buffer = []
        self.lock = threading.Lock()

        self.written.connect(self._consume)

    # -- file-like methods

    def isatty(self):
        return False

    def write(self, txt):
        emit = False
        try:
            self.lock.acquire()
            emit = not bool(self.buffer)
            self.buffer.append(str(txt))
        finally:
            self.lock.release()
        if emit:
            self.written.emit()

    def _consume(self):
        try:
            self.lock.acquire()
            buffer_ = self.buffer
            self.buffer = []
        finally:
            self.lock.release()

        if buffer_:
            txt = ''.join(buffer_)
            self._write(txt)

    def _write(self, txt):
        self.moveCursor(QtGui.QTextCursor.End)
        self.insertPlainText(txt)
        self.moveCursor(QtGui.QTextCursor.End)
<|endoftext|>


<commit_before>from autobahn.asyncio.wamp import ApplicationSession
from autobahn.wamp.types import SubscribeOptions, RegisterOptions
import asyncio

class QuestionComponent(ApplicationSession):
    """
    An application component providing procedures with different kinds
    of arguments.
    """
    def __init__(self, *kwargs):
        super().__init__(*kwargs)

        self.pendingQuestion = False
        self.last_input = ""

    def get_channel_from_details(self,details):
        arr = details.topic.split(".")
        indexOfMessage = arr.index("channel")
        return arr[indexOfMessage+1]

    def convert_to_intent(self, sentence):

        if sentence == "Wo ist Klasse xyz?":

            return {
                    "eventName": "SEARCH_FOR_CLASS",
                    "className": "xyz"
                    }

    async def wait_for_next_input(self):
        while(self.pendingQuestion):
            await asyncio.sleep(200)
        return self.last_input

    def ask_string(self, details, sentence):
        self.pendingQuestion = True
        channel_id = self.get_channel_from_details(details)
        yield self.publish(u'sofia.channel.{0}.messages.OUTGOING_MESSAGE'.format(channel_id), {"text": sentence})
        user_input = yield self.wait_for_next_input()
        print(user_input)
        return user_input

    def onIncommingMessage(self,message, details):
        self.last_message = message
        self.pendingQuestion = False
        print("{0}".format(message))
        channel_id = self.get_channel_from_details(details)
        message_text = message["text"].strip()

        project_setup = [
            "project setup"
            "setup"
            "setup project"
            "setup git"
            "setup repository"
            "repository setup"
            "git setup"
            "channel setup"
            "setup channel"
        ]
        if any(message_text in s for s in project_setup):
            #self.publish("sofia.channel.{0}.messages.RequestProjectConfig".format(channel_id), {"msh": "test"})
            self.publish(u'sofia.channel.{0}.messages.RequestProjectConfig'.format(channel_id), {
                "text": u'asdasd force will be with you always',
                "channel": channel_id})
            print("project setup send")

        else:
            self.publish(u'sofia.channel.{0}.messages.OutgoingSentence'.format(channel_id), {
                "text": u'The force will be with you always',
                "channel": channel_id})

    async def onJoin(self, details):

        await self.subscribe(self.onIncommingMessage,"sofia.channel..messages.IncomingSentence",options=SubscribeOptions(match='wildcard',details_arg='details'))
        await self.register(self.ask_string, u'sofia.channel..rpc.QuestionService.askString',options=RegisterOptions(match='wildcard', details_arg='details'))
        print("Registered methods; ready for actions. Give me some... ")
<commit_msg>- changed uri format - add more functions for rpc calls<commit_after>from autobahn.asyncio.wamp import ApplicationSession
from autobahn.wamp.types import SubscribeOptions, RegisterOptions, CallDetails
import asyncio

class QuestionComponent(ApplicationSession):
    """
    An application component providing procedures with different kinds
    of arguments.
    """
    def __init__(self, *kwargs):
        super().__init__(*kwargs)

        self.pendingQuestion = False
        self.last_input = ""

    def get_channel_from_details(self,details):
        if type(details) == CallDetails:
            arr = details.procedure.split(".")
        else:
            arr = details.topic.split(".")
        indexOfMessage = arr.index("channel")
        return arr[indexOfMessage+1]

    def convert_to_intent(self, sentence):

        if sentence == "Wo ist Klasse xyz?":

            return {
                    "eventName": "SEARCH_FOR_CLASS",
                    "className": "xyz"
                    }

    def send_text(self,text,channel_id):
        print("Send text {0}".format(text))
        self.publish(u'sofia.channel.{0}.messages.OutgoingSentence'.format(channel_id), {
            "text": text,
            "channel": channel_id})

    def ask_string(self, msg, details):
        print("Ask for string")
        self.pendingQuestion = True
        channel_id = self.get_channel_from_details(details)
        self.send_text(msg['question'], channel_id)
        while (self.pendingQuestion):
            yield from asyncio.sleep(1)
        user_input = self.last_message
        print("Got response... {0}".format(user_input))
        return user_input['text']

    def onIncommingMessage(self,message, details):

        self.last_message = message
        print(self.pendingQuestion)
        if(self.pendingQuestion):
            self.pendingQuestion = False
            print("Pending question skip all other")
            return
        print("{0}".format(message))
        channel_id = self.get_channel_from_details(details)
        message_text = message["text"].strip()

        project_setup = [
            "project setup"
            "setup"
            "setup project"
            "setup git"
            "setup repository"
            "repository setup"
            "git setup"
            "channel setup"
            "setup channel"
        ]
        if any(message_text in s for s in project_setup):
            #self.publish("sofia.channel.{0}.messages.RequestProjectConfig".format(channel_id), {"msh": "test"})
            self.publish(u'sofia.channel.{0}.messages.RequestProjectConfig'.format(channel_id), {
                "text": u'asdasd force will be with you always',
                "channel": channel_id})
            print("project setup send")

        else:
            self.publish(u'sofia.channel.{0}.messages.OutgoingSentence'.format(channel_id), {
                "text": u'The force will be with you always',
                "channel": channel_id})

    async def onJoin(self, details):

        await self.subscribe(self.onIncommingMessage,"sofia.channel..messages.IncomingSentence",options=SubscribeOptions(match='wildcard',details_arg='details'))
        await self.register(self.ask_string, u'sofia.channel..rpc.service-question.askString',options=RegisterOptions(match='wildcard', details_arg='details'))
        print("Registered methods; ready for actions. Give me some... ")
<|endoftext|>


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

"""

ZUGBRUECKE
Calling routines in Windows DLLs from Python scripts running on unixlike systems
https://github.com/pleiszenburg/zugbruecke

	src/zugbruecke/core/data/mem_contents.py: (Un-) packing of memory

	Required to run on platform / side: [UNIX, WINE]

	Copyright (C) 2017-2018 Sebastian M. Ernst <ernst@pleiszenburg.de>

<LICENSE_BLOCK>
The contents of this file are subject to the GNU Lesser General Public License
Version 2.1 ("LGPL" or "License"). You may not use this file except in
compliance with the License. You may obtain a copy of the License at
https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
https://github.com/pleiszenburg/zugbruecke/blob/master/LICENSE

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
specific language governing rights and limitations under the License.
</LICENSE_BLOCK>

"""

# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# IMPORT
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

import ctypes
from pprint import pformat as pf
#import traceback

from ..const import GROUP_VOID
from ..memory import (
	generate_pointer_from_bytes,
	overwrite_pointer_with_bytes,
	serialize_pointer_into_bytes
	)

WCHAR_BYTES = ctypes.sizeof(ctypes.c_wchar)

# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# CLASS: Memory content packing and unpacking
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

class memory_contents_class():

	def apply_memsync_to_argtypes_definition(self, memsync_d_list, argtypes_d):

		# Iterate over memory segments, which must be kept in sync
		for memsync_d in memsync_d_list:

			# Get type of pointer argument
			arg_type = self.__get_argument_type_by_memsync_path__(memsync_d['p'], argtypes_d)

			# HACK make memory sync pointers type agnostic
			arg_type['g'] = GROUP_VOID
			arg_type['t'] = None # no type string

	def client_pack_memory_list(self, args_tuple, memsync_d_list):

		# Pack data for every pointer, append data to package
		return [self.__pack_memory_item__(args_tuple, memsync_d) for memsync_d in memsync_d_list]

	def client_unpack_memory_list(self, args_list, mem_package_list, memsync_d_list):

		# Iterate over memory package dicts
		for memory_d, memsync_d in zip(mem_package_list, memsync_d_list):

			# If pointer was passed as a Null pointer
			if memory_d['_a'] is None:

				# Unpack one memory section / item
				self.__unpack_memory_item__(args_list, memory_d, memsync_d)

			# If pointer pointed to data
			else:

				# Swap local and remote memory addresses
				self.__swap_memory_addresses__(memory_d)

				# Adjust Unicode wchar length
				if memsync_d['w']:
					self.__adjust_wchar_length__(memory_d)

				# Overwrite the local pointers with new data
				overwrite_pointer_with_bytes(
					ctypes.c_void_p(memory_d['a']),
					memory_d['d']
					)

	def server_pack_memory_list(self, args_list, mem_package_list, memsync_d_list):

		# Iterate through pointers and serialize them
		for memory_d, memsync_d in zip(mem_package_list, memsync_d_list):

			# If pointer was passed as a Null pointer
			if memory_d['a'] is None:

				memory_d.update(self.__pack_memory_item__(args_list, memsync_d))

			# If pointer pointed to data
			else:

				# Overwrite old data in package with new data from memory
				memory_d['d'] = serialize_pointer_into_bytes(
					ctypes.c_void_p(memory_d['a']), memory_d['l']
					)

	def server_unpack_memory_list(self, args_tuple, arg_memory_list, memsync_d_list):

		# Iterate over memory segments, which must be kept in sync
		for memory_d, memsync_d in zip(arg_memory_list, memsync_d_list):

			# Unpack one memory section / item
			self.__unpack_memory_item__(args_tuple, memory_d, memsync_d)

	def __adjust_wchar_length__(self, memory_d):

		old_len = memory_d['w']
		new_len = WCHAR_BYTES

		if old_len == new_len:
			return

		tmp = bytearray(memory_d['l'] * new_len // old_len)

		for index in range(old_len if new_len > old_len else new_len):
			tmp[index::new_len] = memory_d['d'][index::old_len]

		memory_d['d'] = bytes(tmp)
		memory_d['l'] = len(memory_d['d'])
		memory_d['w'] = WCHAR_BYTES

	def __get_argument_by_memsync_path__(self, args_tuple, memsync_path):

		# Reference args_tuple as initial value
		element = args_tuple

		# Step through path
		for path_element in memsync_path:

			# Go deeper ...
			if isinstance(path_element, int):
				if path_element < 0: # Pointer to pointer for memory allocation by DLL
					element = self.__item_pointer_strip__(element)
				else: # Dive into argument tuple
					element = element[path_element]
			else: # Dive into struct
				element = getattr(self.__item_pointer_strip__(element), path_element)

		return element

	def __get_argument_type_by_memsync_path__(self, memsync_path, argtypes_d):

		# Reference processed argument types - start with depth 0
		arg_type = argtypes_d[memsync_path[0]]

		# Step through path to argument type ...
		for path_element in memsync_path[1:]:
			# Continue on special flags HACK
			if isinstance(path_element, int):
				if path_element < 0:
					continue
			# Go deeper ...
			arg_type = {field['n']: field for field in arg_type['_fields_']}[path_element]

		return arg_type

	def __get_number_of_elements__(self, args_tuple, memsync_d):

		# There is no function defining the length?
		if '_f' not in memsync_d.keys():

			# Search for length
			length = self.__get_argument_by_memsync_path__(args_tuple, memsync_d['l'])

			# Length might come from ctypes or a Python datatype
			return getattr(length, 'value', length)

		# Make sure length can be computed from a tuple of arguments
		assert isinstance(memsync_d['l'], tuple)

		# Compute length from arguments and return
		return memsync_d['_f'](*(
			self.__get_argument_by_memsync_path__(args_tuple, item) for item in memsync_d['l']
			))

	def __pack_memory_item__(self, args_tuple, memsync_d):

		# Search for pointer
		pointer = self.__get_argument_by_memsync_path__(args_tuple, memsync_d['p'])

		# Compute actual length
		length = self.__get_number_of_elements__(args_tuple, memsync_d) * memsync_d['s']

		# Convert argument into ctypes datatype TODO more checks needed!
		if '_c' in memsync_d.keys():
			pointer = ctypes.pointer(memsync_d['_c'].from_param(pointer))

		return {
			'd': serialize_pointer_into_bytes(pointer, length), # serialized data
			'l': length, # length of serialized data
			'a': ctypes.cast(pointer, ctypes.c_void_p).value, # local pointer address as integer
			'_a': None, # remote pointer has not been initialized
			'w': WCHAR_BYTES if memsync_d['w'] else None # local length of Unicode wchar if required
			}

	def __swap_memory_addresses__(self, memory_d):

		memory_d.update({
			'a': memory_d.get('_a', None),
			'_a': memory_d.get('a', None)
			})

	def __unpack_memory_item__(self, args_tuple, memory_d, memsync_d):

		# Swap local and remote memory addresses
		self.__swap_memory_addresses__(memory_d)

		# Is this a null pointer?
		if memory_d['_a'] is None:

			# Make sure this is a pointer to a pointer
			assert memsync_d['p'][-1] == -1

			# Search for pointer in passed arguments
			pointer_arg = self.__get_argument_by_memsync_path__(args_tuple, memsync_d['p'][:-2])

			# Generate empty pointer
			pointer_data = ctypes.pointer(ctypes.c_void_p())

			# If we're in the top level arguments or an array ...
			if isinstance(memsync_d['p'][-2], int):
				# Handle deepest instance (exchange element in list/tuple) HACK
				pointer_arg[memsync_d['p'][-2]] = pointer_data
			# If we're at a field of a struct
			else:
				# Handle deepest instance
				setattr(pointer_arg.contents, memsync_d['p'][-1], pointer_data)

			# Exit here
			return

		# Search for pointer in passed arguments
		pointer_arg = self.__get_argument_by_memsync_path__(args_tuple, memsync_d['p'][:-1])

		# Adjust Unicode wchar length
		if memsync_d['w']:
			self.__adjust_wchar_length__(memory_d)

		# Generate pointer to passed data
		pointer_data = generate_pointer_from_bytes(memory_d['d'])

		# HACK Is this a pointer?
		if hasattr(pointer_arg, 'contents'):
			# Is the pointer pointing to another pointer?
			if hasattr(pointer_arg.contents, 'value'):
				# Is the pointer empty?
				if pointer_arg.contents.value is None:
					# Overwrite the pointer's value
					pointer_arg.contents.value = pointer_data.value
					# Get out of here HACK
					return

		# If we're in the top level arguments or an array ...
		if isinstance(memsync_d['p'][-1], int):
			# Handle deepest instance (exchange element in list/tuple) HACK
			pointer_arg[memsync_d['p'][-1]] = pointer_data
		# If we're at a field of a struct
		else:
			# Handle deepest instance
			setattr(pointer_arg.contents, memsync_d['p'][-1], pointer_data)

		# Store the server's memory address
		memory_d['a'] = pointer_data.value
<commit_msg>isolated null pointer unpacking<commit_after># -*- coding: utf-8 -*-

"""

ZUGBRUECKE
Calling routines in Windows DLLs from Python scripts running on unixlike systems
https://github.com/pleiszenburg/zugbruecke

	src/zugbruecke/core/data/mem_contents.py: (Un-) packing of memory

	Required to run on platform / side: [UNIX, WINE]

	Copyright (C) 2017-2018 Sebastian M. Ernst <ernst@pleiszenburg.de>

<LICENSE_BLOCK>
The contents of this file are subject to the GNU Lesser General Public License
Version 2.1 ("LGPL" or "License"). You may not use this file except in
compliance with the License. You may obtain a copy of the License at
https://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
https://github.com/pleiszenburg/zugbruecke/blob/master/LICENSE

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
specific language governing rights and limitations under the License.
</LICENSE_BLOCK>

"""

# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# IMPORT
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

import ctypes
from pprint import pformat as pf
#import traceback

from ..const import GROUP_VOID
from ..memory import (
	generate_pointer_from_bytes,
	overwrite_pointer_with_bytes,
	serialize_pointer_into_bytes
	)

WCHAR_BYTES = ctypes.sizeof(ctypes.c_wchar)

# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# CLASS: Memory content packing and unpacking
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

class memory_contents_class():

	def apply_memsync_to_argtypes_definition(self, memsync_d_list, argtypes_d):

		# Iterate over memory segments, which must be kept in sync
		for memsync_d in memsync_d_list:

			# Get type of pointer argument
			arg_type = self.__get_argument_type_by_memsync_path__(memsync_d['p'], argtypes_d)

			# HACK make memory sync pointers type agnostic
			arg_type['g'] = GROUP_VOID
			arg_type['t'] = None # no type string

	def client_pack_memory_list(self, args_tuple, memsync_d_list):

		# Pack data for every pointer, append data to package
		return [self.__pack_memory_item__(args_tuple, memsync_d) for memsync_d in memsync_d_list]

	def client_unpack_memory_list(self, args_list, mem_package_list, memsync_d_list):

		# Iterate over memory package dicts
		for memory_d, memsync_d in zip(mem_package_list, memsync_d_list):

			# If pointer was passed as a Null pointer
			if memory_d['_a'] is None:

				# Unpack one memory section / item
				self.__unpack_memory_item_data__(args_list, memory_d, memsync_d)

			# If pointer pointed to data
			else:

				# Swap local and remote memory addresses
				self.__swap_memory_addresses__(memory_d)

				# Adjust Unicode wchar length
				if memsync_d['w']:
					self.__adjust_wchar_length__(memory_d)

				# Overwrite the local pointers with new data
				overwrite_pointer_with_bytes(
					ctypes.c_void_p(memory_d['a']),
					memory_d['d']
					)

	def server_pack_memory_list(self, args_list, mem_package_list, memsync_d_list):

		# Iterate through pointers and serialize them
		for memory_d, memsync_d in zip(mem_package_list, memsync_d_list):

			# If pointer was passed as a Null pointer
			if memory_d['a'] is None:

				memory_d.update(self.__pack_memory_item__(args_list, memsync_d))

			# If pointer pointed to data
			else:

				# Overwrite old data in package with new data from memory
				memory_d['d'] = serialize_pointer_into_bytes(
					ctypes.c_void_p(memory_d['a']), memory_d['l']
					)

	def server_unpack_memory_list(self, args_tuple, arg_memory_list, memsync_d_list):

		# Iterate over memory segments, which must be kept in sync
		for memory_d, memsync_d in zip(arg_memory_list, memsync_d_list):

			# Is this a null pointer?
			if memory_d['a'] is None:

				# Insert new NULL pointer
				self.__unpack_memory_item_null__(args_tuple, memory_d, memsync_d)

			else:

				# Unpack one memory section / item
				self.__unpack_memory_item_data__(args_tuple, memory_d, memsync_d)

	def __adjust_wchar_length__(self, memory_d):

		old_len = memory_d['w']
		new_len = WCHAR_BYTES

		if old_len == new_len:
			return

		tmp = bytearray(memory_d['l'] * new_len // old_len)

		for index in range(old_len if new_len > old_len else new_len):
			tmp[index::new_len] = memory_d['d'][index::old_len]

		memory_d['d'] = bytes(tmp)
		memory_d['l'] = len(memory_d['d'])
		memory_d['w'] = WCHAR_BYTES

	def __get_argument_by_memsync_path__(self, args_tuple, memsync_path):

		# Reference args_tuple as initial value
		element = args_tuple

		# Step through path
		for path_element in memsync_path:

			# Go deeper ...
			if isinstance(path_element, int):
				if path_element < 0: # Pointer to pointer for memory allocation by DLL
					element = self.__item_pointer_strip__(element)
				else: # Dive into argument tuple
					element = element[path_element]
			else: # Dive into struct
				element = getattr(self.__item_pointer_strip__(element), path_element)

		return element

	def __get_argument_type_by_memsync_path__(self, memsync_path, argtypes_d):

		# Reference processed argument types - start with depth 0
		arg_type = argtypes_d[memsync_path[0]]

		# Step through path to argument type ...
		for path_element in memsync_path[1:]:
			# Continue on special flags HACK
			if isinstance(path_element, int):
				if path_element < 0:
					continue
			# Go deeper ...
			arg_type = {field['n']: field for field in arg_type['_fields_']}[path_element]

		return arg_type

	def __get_number_of_elements__(self, args_tuple, memsync_d):

		# There is no function defining the length?
		if '_f' not in memsync_d.keys():

			# Search for length
			length = self.__get_argument_by_memsync_path__(args_tuple, memsync_d['l'])

			# Length might come from ctypes or a Python datatype
			return getattr(length, 'value', length)

		# Make sure length can be computed from a tuple of arguments
		assert isinstance(memsync_d['l'], tuple)

		# Compute length from arguments and return
		return memsync_d['_f'](*(
			self.__get_argument_by_memsync_path__(args_tuple, item) for item in memsync_d['l']
			))

	def __pack_memory_item__(self, args_tuple, memsync_d):

		# Search for pointer
		pointer = self.__get_argument_by_memsync_path__(args_tuple, memsync_d['p'])

		# Compute actual length
		length = self.__get_number_of_elements__(args_tuple, memsync_d) * memsync_d['s']

		# Convert argument into ctypes datatype TODO more checks needed!
		if '_c' in memsync_d.keys():
			pointer = ctypes.pointer(memsync_d['_c'].from_param(pointer))

		return {
			'd': serialize_pointer_into_bytes(pointer, length), # serialized data, '' if NULL pointer
			'l': length, # length of serialized data
			'a': ctypes.cast(pointer, ctypes.c_void_p).value, # local pointer address as integer
			'_a': None, # remote pointer has not been initialized
			'w': WCHAR_BYTES if memsync_d['w'] else None # local length of Unicode wchar if required
			}

	def __swap_memory_addresses__(self, memory_d):

		memory_d.update({
			'a': memory_d.get('_a', None),
			'_a': memory_d.get('a', None)
			})

	def __unpack_memory_item_data__(self, args_tuple, memory_d, memsync_d):

		# Swap local and remote memory addresses
		self.__swap_memory_addresses__(memory_d)

		# Search for pointer in passed arguments
		pointer_arg = self.__get_argument_by_memsync_path__(args_tuple, memsync_d['p'][:-1])

		# Adjust Unicode wchar length
		if memsync_d['w']:
			self.__adjust_wchar_length__(memory_d)

		# Generate pointer to passed data
		pointer = generate_pointer_from_bytes(memory_d['d'])

		# HACK Is this a pointer?
		if hasattr(pointer_arg, 'contents'):
			# Is the pointer pointing to another pointer?
			if hasattr(pointer_arg.contents, 'value'):
				# Is the pointer empty?
				if pointer_arg.contents.value is None:
					# Overwrite the pointer's value
					pointer_arg.contents.value = pointer.value
					# Get out of here HACK
					return

		# If we're in the top level arguments or an array ...
		if isinstance(memsync_d['p'][-1], int):
			# Handle deepest instance (exchange element in list/tuple) HACK
			pointer_arg[memsync_d['p'][-1]] = pointer
		# If we're at a field of a struct
		else:
			# Handle deepest instance
			setattr(pointer_arg.contents, memsync_d['p'][-1], pointer)

		# Store the server's memory address
		memory_d['a'] = pointer.value

	def __unpack_memory_item_null__(self, args_tuple, memory_d, memsync_d):

		# Swap local and remote memory addresses
		self.__swap_memory_addresses__(memory_d)

		# Make sure this is a pointer to a pointer
		assert memsync_d['p'][-1] == -1

		# Search for pointer in passed arguments
		pointer_arg = self.__get_argument_by_memsync_path__(args_tuple, memsync_d['p'][:-2])

		# Generate empty pointer
		pointer = ctypes.pointer(ctypes.c_void_p())

		# If we're in the top level arguments or an array ...
		if isinstance(memsync_d['p'][-2], int):
			# Handle deepest instance (exchange element in list/tuple) HACK
			pointer_arg[memsync_d['p'][-2]] = pointer
		# If we're at a field of a struct
		else:
			# Handle deepest instance
			setattr(pointer_arg.contents, memsync_d['p'][-1], pointer)
<|endoftext|>


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

# Copyright 2016,  Digital Reasoning
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""
Loads a stack-specific pillar file. stack_pillar_file must be set in the grains
or this module will not be available to pillar.
"""

from __future__ import absolute_import

import logging
import os

import yaml
from stackdio.core.utils import recursive_update

# Set up logging
logger = logging.getLogger(__name__)

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'stackdio.server.settings.production')

def django_setup():
    """
    Our version of django.setup() that doesn't configure logging
    """
    from django.apps import apps
    from django.conf import settings

    apps.populate(settings.INSTALLED_APPS)

# setup django (without logging)
django_setup()

# These must be imported AFTER django is set up
from stackdio.api.cloud.models import CloudAccount  # NOQA
from stackdio.api.stacks.models import Stack  # NOQA
from stackdio.api.environments.models import Environment  # NOQA

def __virtual__():
    return True

def ext_pillar(minion_id, pillar, *args, **kwargs):
    """
    Basically, we need to provide additional pillar data to our states
    but only the pillar data defined for a stack. The user should have
    the ability to do this from the UI and the pillar file used will
    be located in the grains.
    """

    new_pillar = {}

    # First try the environment
    if 'env' in __grains__:
        try:
            environment = Environment.objects.get(name=__grains__['env'])
            recursive_update(new_pillar, environment.get_full_pillar())
        except Environment.DoesNotExist:
            logger.info('Environment {} not found'.format(__grains__['env']))

    # Then the cloud account
    if 'cloud_account' in __grains__:
        try:
            account = CloudAccount.objects.get(slug=__grains__['cloud_account'])
            recursive_update(new_pillar, account.get_full_pillar())
        except CloudAccount.DoesNotExist:
            logger.info('Cloud account {} not found'.format(__grains__['cloud_account']))

    # Then the stack (so that stack properties override the cloud account ones)
    if 'stack_id' in __grains__ and isinstance(__grains__['stack_id'], int):
        try:
            stack = Stack.objects.get(id=__grains__['stack_id'])
            recursive_update(new_pillar, stack.get_full_pillar())
        except Stack.DoesNotExist:
            logger.info('Stack {} not found'.format(__grains__['stack_id']))

    # This is the old way, try it too for compatibility purposes.
    # Make it last so it has the highest precedence.
    if 'stack_pillar_file' in __grains__:
        # load the stack_pillar_file, rendered as yaml, and add it into the return dict
        try:
            with open(__grains__['stack_pillar_file'], 'r') as f:
                loaded_pillar = yaml.safe_load(f)
                recursive_update(new_pillar, loaded_pillar)
        except Exception as e:
            logger.exception(e)
            logger.critical('Unable to load/render stack_pillar_file. Is the YAML '
                            'properly formatted?')

    return new_pillar
<commit_msg>Fixed pillar ext<commit_after># -*- coding: utf-8 -*-

# Copyright 2016,  Digital Reasoning
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""
Loads a stack-specific pillar file. stack_pillar_file must be set in the grains
or this module will not be available to pillar.
"""

from __future__ import absolute_import

import logging
import os

import yaml
from stackdio.core.utils import recursive_update

# Set up logging
logger = logging.getLogger(__name__)

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'stackdio.server.settings.production')

def django_setup():
    """
    Our version of django.setup() that doesn't configure logging
    """
    from django.apps import apps
    from django.conf import settings

    apps.populate(settings.INSTALLED_APPS)

# setup django (without logging)
django_setup()

# These must be imported AFTER django is set up
from stackdio.api.cloud.models import CloudAccount  # NOQA
from stackdio.api.stacks.models import Stack  # NOQA
from stackdio.api.environments.models import Environment  # NOQA

def __virtual__():
    return True

def ext_pillar(minion_id, pillar, *args, **kwargs):
    """
    Basically, we need to provide additional pillar data to our states
    but only the pillar data defined for a stack. The user should have
    the ability to do this from the UI and the pillar file used will
    be located in the grains.
    """

    new_pillar = {}

    # First try the environment
    if 'env' in __grains__:
        _, _, env_name = __grains__['env'].partition('.')
        try:
            environment = Environment.objects.get(name=env_name)
            recursive_update(new_pillar, environment.get_full_pillar())
        except Environment.DoesNotExist:
            logger.info('Environment {} not found'.format(__grains__['env']))

    # Then the cloud account
    if 'cloud_account' in __grains__:
        try:
            account = CloudAccount.objects.get(slug=__grains__['cloud_account'])
            recursive_update(new_pillar, account.get_full_pillar())
        except CloudAccount.DoesNotExist:
            logger.info('Cloud account {} not found'.format(__grains__['cloud_account']))

    # Then the stack (so that stack properties override the cloud account ones)
    if 'stack_id' in __grains__ and isinstance(__grains__['stack_id'], int):
        try:
            stack = Stack.objects.get(id=__grains__['stack_id'])
            recursive_update(new_pillar, stack.get_full_pillar())
        except Stack.DoesNotExist:
            logger.info('Stack {} not found'.format(__grains__['stack_id']))

    # This is the old way, try it too for compatibility purposes.
    # Make it last so it has the highest precedence.
    if 'stack_pillar_file' in __grains__:
        # load the stack_pillar_file, rendered as yaml, and add it into the return dict
        try:
            with open(__grains__['stack_pillar_file'], 'r') as f:
                loaded_pillar = yaml.safe_load(f)
                recursive_update(new_pillar, loaded_pillar)
        except Exception as e:
            logger.exception(e)
            logger.critical('Unable to load/render stack_pillar_file. Is the YAML '
                            'properly formatted?')

    return new_pillar
<|endoftext|>


<commit_before>"""
This file is part of the Avast project.
Copyright 2016 Megan Bedell (Chicago) and David W. Hogg (NYU).
"""
import glob
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator, FormatStrFormatter
from scipy.optimize import leastsq, fmin_bfgs, fmin_cg
from scipy.linalg import svd
from scipy.io.idl import readsav
c = 2.99792458e8   # m/s
xi_scale = 1.e7
scale_scale = 1.e-4

def unpack_pars(pars, n_ms, n_epoch):
    # unpack parameters
    ams = pars[0:n_ms]
    scales = pars[n_ms:n_ms+n_epoch] / scale_scale
    xis = pars[n_ms+n_epoch:] / xi_scale
    return ams, scales, xis

def xi_to_v(xi):
    # translate ln(wavelength) Doppler shift to a velocity in m/s
    r = np.exp(2.*xi) # r = (c+v)/(c-v)
    return c * (r - 1.)/(r + 1.)

def g(xs, xms, del_x):
    # returns values of triangle components centered on xms at location xs
    # xs & xms must be broadcastable
    return np.maximum(1. - np.abs(xs - xms)/del_x, 0.)

def dg_dx(xs, xms, del_x):
    # return the derivatives of `g()`
    signs = np.sign(xms - xs)
    signs[np.abs(xms - xs) > del_x] = 0.
    return signs/del_x

def f(xs, xms, del_x, ams):
    # returns values of triangle-based model f(x) at xs
    # xs : ln(wavelength) at point(s) of interest
    # xms : ln(wavelength) grid, shape (M)
    # del_x : ln(wavelength) spacing of xms
    # ams : function coefficients, shape (M)
    return np.sum(ams[None,:] * g(xs[:,None], xms[None,:], del_x), axis=1)

def resid_function(pars, xs, ys, yerrs, xms, del_x):
    """
    function to minimize

    ## bugs:
    - needs proper comment header.
    - array indexing is very brittle.
    """
    n_epoch = len(xs)
    n_ms = len(xms)
    n_x = len(xs[0])  # assumes all xs are the same length
    ams, scales, xis = unpack_pars(pars, n_ms, n_epoch)
    resid = np.zeros((n_epoch*n_x + n_ms + n_epoch))
    for j in range(n_epoch):
        xprimes = xs[j] + xis[j]
        calc = scales[j] * f(xprimes, xms, del_x, ams)
        resid[j*n_x:(j+1)*n_x] = (ys[j] - calc) / yerrs[j]
    resid[-n_epoch-n_ms:-n_epoch] = (ams - 1.)/1.0  # append penalty terms of a MAGIC NUMBER
    resid[-n_epoch:] = (xis - 0.)/3.e-6  # MAGIC NUMBER (1 km/s-ish)
    return resid.flatten()

def deriv_matrix(pars, xs, ys, yerrs, xms, del_x):
    """
    derivatives of resid_function() wrt pars

    ## bugs:
    - penalty terms are arbitrary & should be linked to resid_function
    """
    n_epoch = len(xs)
    n_ms = len(xms)
    n_x = len(xs[0])  # assumes all xs are the same length
    ams, scales, xis = unpack_pars(pars, n_ms, n_epoch)
    deriv_matrix = np.zeros((n_epoch*n_x + n_ms + n_epoch, len(pars)))
    for j in range(n_epoch):
        xprimes = xs[j] + xis[j]
        dy_dams = scales[j] * g(xprimes[:,None], xms[None,:], del_x)
        deriv_matrix[j*n_x:(j+1)*n_x,:n_ms] = - dy_dams / (yerrs[j])[:,None]
        dy_dsj = f(xprimes, xms, del_x, ams)
        deriv_matrix[j*n_x:(j+1)*n_x,n_ms+j] = - dy_dsj / yerrs[j] / scale_scale
        dy_dxij = scales[j] * np.sum(ams[None,:] * dg_dx(xprimes[:,None],
            xms[None,:], del_x), axis=1)
        deriv_matrix[j*n_x:(j+1)*n_x,-n_epoch+j] = - dy_dxij / yerrs[j] / xi_scale
    deriv_matrix[-n_epoch-n_ms:-n_epoch,:n_ms] = np.eye(n_ms)/1.0  # append penalty terms of a MAGIC NUMBER
    deriv_matrix[-n_epoch:,-n_epoch:] = np.eye(n_epoch)/3.e-6 / xi_scale  # MAGIC NUMBER (1 km/s-ish)
    return deriv_matrix

def objective(pars, xs, ys, yerrs, xms, del_x):
   # scalar objective function
   resid = resid_function(pars, xs, ys, yerrs, xms, del_x)
   return np.dot(resid, resid)

def obj_deriv(pars, xs, ys, yerrs, xms, del_x):
    # derivative of objective function
    resid = resid_function(pars, xs, ys, yerrs, xms, del_x)
    matrix = deriv_matrix(pars, xs, ys, yerrs, xms, del_x)
    return 2.0 * np.dot(resid, matrix)

def min_v(pars, i, xs, ys, yerrs, xms, del_x):
    # do a simple minimization of just one xi parameter
    # i : epoch # to minimize, 0-2
    tmp_pars = np.copy(pars)
    obj = []  # objective function
    xi0 = []
    for xi in np.linspace(xis[i]-1.,xis[i]+1.,100):
        tmp_pars[-n_epoch+i] = xi
        resids = resid_function(tmp_pars, xs, ys, yerrs, xms, del_x)
        obj = np.append(obj, np.dot(resids,resids))
        xi0 = np.append(xi0,xi)
    plt.clf()
    plt.plot(xi_to_v(xi0),obj)
    plt.axvline(xi_to_v(xis[i]))
    plt.xlabel('v (m/s)')
    plt.ylabel('objective function')
    plt.savefig('objectivefn_v{0}.png'.format(i))
    xi_min = xi0[np.argmin(obj)]
    tmp_pars[-n_epoch+i] = xi_min
    return tmp_pars

def save_plot(xs, obs, calc, resid, x_plot, calc_plot, save_name, i):
    xs = np.e**xs
    x_plot = np.e**x_plot
    fig = plt.figure()

    ax1 = fig.add_subplot(2,1,1)
    ax1.step(xs,obs, color='black', label='Observed')
    ax1.plot(x_plot,calc_plot, color='red', label='Calculated')
    ax1.set_ylabel('Flux')
    #ax1.legend()
    ax1.set_title('Epoch {0}'.format(i))
    ax1.set_xticklabels( () )
    ax2 = fig.add_subplot(2,1,2)
    ax2.step(xs,obs - calc, color='black')
    ax2.step(xs,resid, color='red')
    ax2.set_ylabel('(O-C)')
    ax2.ticklabel_format(useOffset=False)
    ax2.set_xlabel(r'Wavelength ($\AA$)')
    majorLocator = MultipleLocator(1)
    minorLocator = MultipleLocator(0.1)
    ax1.xaxis.set_minor_locator(minorLocator)
    ax1.xaxis.set_major_locator(majorLocator)
    ax2.xaxis.set_minor_locator(minorLocator)
    ax2.xaxis.set_major_locator(majorLocator)
    majorLocator = MultipleLocator(5000)
    ax1.yaxis.set_major_locator(majorLocator)
    majorLocator = MultipleLocator(200)
    ax2.yaxis.set_major_locator(majorLocator)
    ax2.set_ylim([-500,500])
    fig.subplots_adjust(hspace=0.05)
    ax1.set_xlim([x_plot.min(),x_plot.max()])
    ax2.set_xlim([x_plot.min(),x_plot.max()])

    plt.savefig(save_name)

if __name__ == "__main__":
    data_dir = '../data/halpha_quiet/'

    print "Reading files..."
    filelist = glob.glob(data_dir+'*.txt')
    nfile = len(filelist)
    xs = None
    for e,fn in enumerate(filelist):
        w, s = np.loadtxt(fn, unpack=True)
        if xs is None:
            nwave = len(w)
            xs, ys = np.zeros([nfile,nwave]), np.zeros([nfile,nwave])
        assert len(w) == nwave
        xs[e] = np.log(w)
        ys[e] = s

    print "Got data!"
    yerrs = np.sqrt(ys)  # assumes Poisson noise and a gain of 1.0
    del_x = 1.3e-5/2.0
    xms = np.arange(np.min(xs) - 0.5 * del_x, np.max(xs) + 0.99 * del_x, del_x)

    # initial fit to ams & scales:
    fa = (xs, ys, yerrs, xms, del_x)
    n_epoch = len(xs)
    n_ms = len(xms)
    ams0 = np.ones(n_ms)
    scales0 = [np.median(s) * scale_scale for s in ys]
    xis0 = np.zeros(n_epoch) * xi_scale
    #xis0 = np.random.normal(size=n_epoch)/1.e7 # ~10 m/s level
    pars0 = np.append(ams0, np.append(scales0, xis0))
    ftol = 1.49012e-08  # default is 1.49012e-08

    '''''
    soln = leastsq(resid_function, pars0, args=fa, ftol=ftol, full_output=True)
    pars_nodf = soln[0]
    ams, scales, xis = unpack_pars(pars_nodf, n_ms, n_epoch)
    for e in range(n_epoch):
        xprimes = xs[e] + xis[e]
        calc = f(xprimes, xms, del_x, ams) * scales[e]
        x_plot = np.linspace(xprimes[0],xprimes[-1],num=5000)
        calc_plot = f(x_plot, xms, del_x, ams * scales[e])
        save_plot(xprimes, ys[e], calc, x_plot, calc_plot, 'fig/epoch'+str(e)+'_nodf.pdf')
    '''

    #soln = leastsq(resid_function, pars0, args=fa, Dfun=deriv_matrix,
    #        col_deriv=False, ftol=ftol, full_output=True)

    print "Optimizing...."

    gtol = 1.e-9
    soln = fmin_bfgs(objective, pars0, args=fa, fprime=obj_deriv, full_output=True, gtol=gtol)
    print "Solution achieved!"

    # look at the fit:
    pars = soln[0]
    #pars = soln
    ams, scales, xis = unpack_pars(pars, n_ms, n_epoch)
    #resids = resid_function(pars, xs, ys, xms, del_x)
    print "Initial optimization of all parameters:"
    #print "Objective function value: {0}".format(np.dot(resids,resids))
    #print "nfev: {0}".format(soln[2]['nfev'])
    #print "mesg: {0}".format(soln[3])
    #print "ier: {0}".format(soln[4])
    vs = xi_to_v(xis)
    print "Velocities:", vs

    calcs = np.zeros((n_epoch, len(xs[e])))
    for e in range(n_epoch):
        xprimes = xs[e] + xis[e]
        calc = f(xprimes, xms, del_x, ams * scales[e])
        x_plot = np.linspace(xprimes[0],xprimes[-1],num=5000)
        calc_plot = f(x_plot+xis[e], xms, del_x, ams * scales[e])
        resid = resid_function(pars, xs, ys, yerrs, xms, del_x)
        n_x = len(xs[e])
        resid = resid[e*n_x:(e+1)*n_x] * yerrs[e]
        #save_plot(xs[e], ys[e], calc, resid, x_plot, calc_plot, 'fig/epoch'+str(e)+'.pdf', e)
        calcs[e] = calc

    scaled_resids = (ys - calcs) / scales[:,None]
    u, s, v = svd(scaled_resids, full_matrices=False)
    u.shape, s.shape, v.shape

    data_dir = "/Users/mbedell/Documents/Research/HARPSTwins/Results/"
    pipeline = readsav(data_dir+'HIP54287_result.dat')
    plt.scatter(pipeline.rv, u[:,0])

if False:
    # plotting objective function with various parameters:
    tmp_pars = np.copy(pars)
    obj = []  # objective function
    a20 = []
    for a in np.linspace(ams[20]-100.,ams[20]+100.,100):
        tmp_pars[20] = a
        resids = resid_function(tmp_pars, xs, ys, yerrs, xms, del_x)
        obj = np.append(obj, np.dot(resids,resids))
        a20 = np.append(a20,a)
    plt.clf()
    plt.plot(a20,obj)
    plt.axvline(ams[20], linestyle='solid')
    plt.xlabel(r'a$_{20}$')
    plt.ylabel('objective function')
    plt.savefig('objectivefn_a20.png')
    plt.clf()

    tmp_pars = np.copy(pars)
    obj = []  # objective function
    scale0 = []
    for s in np.linspace(scales[0]*0.95,scales[0]*1.05,100):
        tmp_pars[n_ms] = s
        resids = resid_function(tmp_pars, xs, ys, yerrs, xms, del_x)
        obj = np.append(obj, np.dot(resids,resids))
        scale0 = np.append(scale0,s)
    plt.clf()
    plt.plot(scale0,obj)
    plt.axvline(scales[0], linestyle='solid')
    plt.xlabel(r'scale$_{0}$')
    plt.ylabel('objective function')
    plt.savefig('objectivefn_scale0.png')
    plt.clf()

    tmp_pars = np.copy(pars)
    obj = []  # objective function
    xi0 = []
    for xi in np.linspace(xis[0]*0.95,xis[0]*1.05,100):
        tmp_pars[n_ms+n_epoch] = xi
        resids = resid_function(tmp_pars, xs, ys, yerrs, xms, del_x)
        obj = np.append(obj, np.dot(resids,resids))
        xi0 = np.append(xi0,xi)
    plt.clf()
    plt.plot(xi0,obj)
    plt.axvline(xis[0], linestyle='solid')
    plt.xlabel(r'$\xi_{0}$')
    plt.ylabel('objective function')
    plt.savefig('objectivefn_xi0.png')
    plt.clf()

    '''''
    # optimize one epoch at a time:
    for i in range(n_epoch):
        pars = min_v(pars, i, xs, ys, xms, del_x)
        resids = resid_function(pars, xs, ys, xms, del_x)
        ams, scales, xis = unpack_pars(pars, n_ms, n_epoch)
        print "Optimization of velocity at epoch {0}:".format(i)
        print "Objective function value: {0}".format(np.dot(resids,resids))
        #vs = xi_to_v(xis)
        #print "Velocities:", vs
    '''
<commit_msg>cleaned up function names etc<commit_after>"""
This file is part of the Avast project.
Copyright 2016 Megan Bedell (Chicago) and David W. Hogg (NYU).
"""
import glob
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator, FormatStrFormatter
from scipy.optimize import leastsq, fmin_bfgs, fmin_cg
from scipy.linalg import svd
from scipy.io.idl import readsav
c = 2.99792458e8   # m/s
xi_scale = 1.e7
scale_scale = 1.e-4
am_penalty = 1.0
xi_penalty = 3.e-6  # MAGIC NUMBER (1 km/s-ish)

def unpack_pars(pars, n_ms, n_epoch):
    # unpack parameters
    ams = pars[0:n_ms]
    scales = pars[n_ms:n_ms+n_epoch] / scale_scale
    xis = pars[n_ms+n_epoch:] / xi_scale
    return ams, scales, xis

def xi_to_v(xi):
    # translate ln(wavelength) Doppler shift to a velocity in m/s
    r = np.exp(2.*xi) # r = (c+v)/(c-v)
    return c * (r - 1.)/(r + 1.)

def g(xs, xms, del_x):
    # returns values of triangle components centered on xms at location xs
    # xs & xms must be broadcastable
    return np.maximum(1. - np.abs(xs - xms)/del_x, 0.)

def dg_dx(xs, xms, del_x):
    # return the derivatives of `g()`
    signs = np.sign(xms - xs)
    signs[np.abs(xms - xs) > del_x] = 0.
    return signs/del_x

def f(xs, xms, del_x, ams):
    # returns values of triangle-based model f(x) at xs
    # xs : ln(wavelength) at point(s) of interest
    # xms : ln(wavelength) grid, shape (M)
    # del_x : ln(wavelength) spacing of xms
    # ams : function coefficients, shape (M)
    return np.sum(ams[None,:] * g(xs[:,None], xms[None,:], del_x), axis=1)

def resid_function(pars, xs, ys, yerrs, xms, del_x):
    """
    function to minimize

    ## bugs:
    - needs proper comment header.
    - array indexing is very brittle.
    - penalty terms are arbitrary.
    """
    n_epoch = len(xs)
    n_ms = len(xms)
    n_x = len(xs[0])  # assumes all xs are the same length
    ams, scales, xis = unpack_pars(pars, n_ms, n_epoch)
    resid = np.zeros((n_epoch*n_x + n_ms + n_epoch))
    for j in range(n_epoch):
        xprimes = xs[j] + xis[j]
        calc = scales[j] * f(xprimes, xms, del_x, ams)
        resid[j*n_x:(j+1)*n_x] = (ys[j] - calc) / yerrs[j]
    resid[-n_epoch-n_ms:-n_epoch] = (ams - 1.) / am_penalty
    resid[-n_epoch:] = (xis - 0.) / xi_penalty
    return resid.flatten()

def resid_deriv(pars, xs, ys, yerrs, xms, del_x):
    """
    derivatives of resid_function() wrt pars
    """
    n_epoch = len(xs)
    n_ms = len(xms)
    n_x = len(xs[0])  # assumes all xs are the same length
    ams, scales, xis = unpack_pars(pars, n_ms, n_epoch)
    resid_deriv = np.zeros((n_epoch*n_x + n_ms + n_epoch, len(pars)))
    for j in range(n_epoch):
        xprimes = xs[j] + xis[j]
        dy_dams = scales[j] * g(xprimes[:,None], xms[None,:], del_x)
        resid_deriv[j*n_x:(j+1)*n_x,:n_ms] = - dy_dams / (yerrs[j])[:,None]
        dy_dsj = f(xprimes, xms, del_x, ams)
        resid_deriv[j*n_x:(j+1)*n_x,n_ms+j] = - dy_dsj / yerrs[j] / scale_scale
        dy_dxij = scales[j] * np.sum(ams[None,:] * dg_dx(xprimes[:,None],
            xms[None,:], del_x), axis=1)
        resid_deriv[j*n_x:(j+1)*n_x,-n_epoch+j] = - dy_dxij / yerrs[j] / xi_scale
    resid_deriv[-n_epoch-n_ms:-n_epoch,:n_ms] = np.eye(n_ms) / am_penalty
    resid_deriv[-n_epoch:,-n_epoch:] = np.eye(n_epoch) / xi_penalty / xi_scale
    return resid_deriv

def obj_function(pars, xs, ys, yerrs, xms, del_x):
   # scalar objective function
   resid = resid_function(pars, xs, ys, yerrs, xms, del_x)
   return np.dot(resid, resid)

def obj_deriv(pars, xs, ys, yerrs, xms, del_x):
    # derivative of objective function
    resid = resid_function(pars, xs, ys, yerrs, xms, del_x)
    matrix = resid_deriv(pars, xs, ys, yerrs, xms, del_x)
    return 2.0 * np.dot(resid, matrix)

def min_v(pars, i, xs, ys, yerrs, xms, del_x):
    # do a simple minimization of just one xi parameter
    # i : epoch # to minimize, 0-2
    tmp_pars = np.copy(pars)
    obj = []  # objective function
    xi0 = []
    for xi in np.linspace(xis[i]-1.,xis[i]+1.,100):
        tmp_pars[-n_epoch+i] = xi
        resids = resid_function(tmp_pars, xs, ys, yerrs, xms, del_x)
        obj = np.append(obj, np.dot(resids,resids))
        xi0 = np.append(xi0,xi)
    plt.clf()
    plt.plot(xi_to_v(xi0),obj)
    plt.axvline(xi_to_v(xis[i]))
    plt.xlabel('v (m/s)')
    plt.ylabel('objective function')
    plt.savefig('objectivefn_v{0}.png'.format(i))
    xi_min = xi0[np.argmin(obj)]
    tmp_pars[-n_epoch+i] = xi_min
    return tmp_pars

def save_plot(xs, obs, calc, resid, x_plot, calc_plot, save_name, i):
    xs = np.e**xs
    x_plot = np.e**x_plot
    fig = plt.figure()

    ax1 = fig.add_subplot(2,1,1)
    ax1.step(xs,obs, color='black', label='Observed')
    ax1.plot(x_plot,calc_plot, color='red', label='Calculated')
    ax1.set_ylabel('Flux')
    #ax1.legend()
    ax1.set_title('Epoch {0}'.format(i))
    ax1.set_xticklabels( () )
    ax2 = fig.add_subplot(2,1,2)
    ax2.step(xs,obs - calc, color='black')
    ax2.step(xs,resid, color='red')
    ax2.set_ylabel('(O-C)')
    ax2.ticklabel_format(useOffset=False)
    ax2.set_xlabel(r'Wavelength ($\AA$)')
    majorLocator = MultipleLocator(1)
    minorLocator = MultipleLocator(0.1)
    ax1.xaxis.set_minor_locator(minorLocator)
    ax1.xaxis.set_major_locator(majorLocator)
    ax2.xaxis.set_minor_locator(minorLocator)
    ax2.xaxis.set_major_locator(majorLocator)
    majorLocator = MultipleLocator(5000)
    ax1.yaxis.set_major_locator(majorLocator)
    majorLocator = MultipleLocator(200)
    ax2.yaxis.set_major_locator(majorLocator)
    ax2.set_ylim([-500,500])
    fig.subplots_adjust(hspace=0.05)
    ax1.set_xlim([x_plot.min(),x_plot.max()])
    ax2.set_xlim([x_plot.min(),x_plot.max()])

    plt.savefig(save_name)

if __name__ == "__main__":
    data_dir = '../data/halpha_quiet/'

    print "Reading files..."
    filelist = glob.glob(data_dir+'*.txt')
    nfile = len(filelist)
    xs = None
    for e,fn in enumerate(filelist):
        w, s = np.loadtxt(fn, unpack=True)
        if xs is None:
            nwave = len(w)
            xs, ys = np.zeros([nfile,nwave]), np.zeros([nfile,nwave])
        assert len(w) == nwave
        xs[e] = np.log(w)
        ys[e] = s

    print "Got data!"
    yerrs = np.sqrt(ys)  # assumes Poisson noise and a gain of 1.0
    del_x = 1.3e-5/2.0
    xms = np.arange(np.min(xs) - 0.5 * del_x, np.max(xs) + 0.99 * del_x, del_x)

    # initial fit to ams & scales:
    fa = (xs, ys, yerrs, xms, del_x)
    n_epoch = len(xs)
    n_ms = len(xms)
    ams0 = np.ones(n_ms)
    scales0 = [np.median(s) * scale_scale for s in ys]
    xis0 = np.zeros(n_epoch) * xi_scale
    #xis0 = np.random.normal(size=n_epoch)/1.e7 # ~10 m/s level
    pars0 = np.append(ams0, np.append(scales0, xis0))

    print "Optimizing...."

    gtol = 1.e-9
    soln = fmin_bfgs(obj_function, pars0, args=fa, fprime=obj_deriv, full_output=True, gtol=gtol)
    print "Solution achieved!"

    # look at the fit:
    pars = soln[0]
    ams, scales, xis = unpack_pars(pars, n_ms, n_epoch)
    vs = xi_to_v(xis)
    print "Velocities:", vs

    calcs = np.zeros((n_epoch, len(xs[e])))
    for e in range(n_epoch):
        xprimes = xs[e] + xis[e]
        calc = f(xprimes, xms, del_x, ams * scales[e])
        x_plot = np.linspace(xprimes[0],xprimes[-1],num=5000)
        calc_plot = f(x_plot+xis[e], xms, del_x, ams * scales[e])
        resid = resid_function(pars, xs, ys, yerrs, xms, del_x)
        n_x = len(xs[e])
        resid = resid[e*n_x:(e+1)*n_x] * yerrs[e]
        #save_plot(xs[e], ys[e], calc, resid, x_plot, calc_plot, 'fig/epoch'+str(e)+'.pdf', e)
        calcs[e] = calc

    scaled_resids = (ys - calcs) / scales[:,None]
    u, s, v = svd(scaled_resids, full_matrices=False)
    u.shape, s.shape, v.shape

    data_dir = "/Users/mbedell/Documents/Research/HARPSTwins/Results/"
    pipeline = readsav(data_dir+'HIP54287_result.dat')
    plt.scatter(pipeline.rv, u[:,0])

if False:
    # plotting objective function with various parameters:
    tmp_pars = np.copy(pars)
    obj = []  # objective function
    a20 = []
    for a in np.linspace(ams[20]-100.,ams[20]+100.,100):
        tmp_pars[20] = a
        resids = resid_function(tmp_pars, xs, ys, yerrs, xms, del_x)
        obj = np.append(obj, np.dot(resids,resids))
        a20 = np.append(a20,a)
    plt.clf()
    plt.plot(a20,obj)
    plt.axvline(ams[20], linestyle='solid')
    plt.xlabel(r'a$_{20}$')
    plt.ylabel('objective function')
    plt.savefig('objectivefn_a20.png')
    plt.clf()

    tmp_pars = np.copy(pars)
    obj = []  # objective function
    scale0 = []
    for s in np.linspace(scales[0]*0.95,scales[0]*1.05,100):
        tmp_pars[n_ms] = s
        resids = resid_function(tmp_pars, xs, ys, yerrs, xms, del_x)
        obj = np.append(obj, np.dot(resids,resids))
        scale0 = np.append(scale0,s)
    plt.clf()
    plt.plot(scale0,obj)
    plt.axvline(scales[0], linestyle='solid')
    plt.xlabel(r'scale$_{0}$')
    plt.ylabel('objective function')
    plt.savefig('objectivefn_scale0.png')
    plt.clf()

    tmp_pars = np.copy(pars)
    obj = []  # objective function
    xi0 = []
    for xi in np.linspace(xis[0]*0.95,xis[0]*1.05,100):
        tmp_pars[n_ms+n_epoch] = xi
        resids = resid_function(tmp_pars, xs, ys, yerrs, xms, del_x)
        obj = np.append(obj, np.dot(resids,resids))
        xi0 = np.append(xi0,xi)
    plt.clf()
    plt.plot(xi0,obj)
    plt.axvline(xis[0], linestyle='solid')
    plt.xlabel(r'$\xi_{0}$')
    plt.ylabel('objective function')
    plt.savefig('objectivefn_xi0.png')
    plt.clf()

    '''''
    # optimize one epoch at a time:
    for i in range(n_epoch):
        pars = min_v(pars, i, xs, ys, xms, del_x)
        resids = resid_function(pars, xs, ys, xms, del_x)
        ams, scales, xis = unpack_pars(pars, n_ms, n_epoch)
        print "Optimization of velocity at epoch {0}:".format(i)
        print "Objective function value: {0}".format(np.dot(resids,resids))
        #vs = xi_to_v(xis)
        #print "Velocities:", vs
    '''
<|endoftext|>


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

import argparse
from . import compiler

def main():
    parser = argparse.ArgumentParser(description='CodeKit Language Compiler.')
    parser.add_argument('src', nargs=1, metavar='SOURCE')
    parser.add_argument('dest', nargs=1, metavar='DEST')
    parser.add_argument('--framework-paths', '-f', action='append',
                        metavar='DIR')
    namespace = parser.parse_args()
    compiler_ = compiler.Compiler(framework_paths=namespace.framework_paths)
    compiler_.generate_to_file(namespace.dest[0], namespace.src[0])

if __name__ == '__main__':  # pragma:nocover
    main()
<commit_msg>Refactor command-line option handling.<commit_after># -*- coding: utf-8 -*-

import argparse
from . import compiler

def main():
    parser = argparse.ArgumentParser(description='CodeKit Language Compiler.')
    parser.add_argument('src', nargs=1, metavar='SOURCE')
    parser.add_argument('dest', nargs=1, metavar='DEST')
    parser.add_argument('--framework-paths', '-f', action='append',
                        metavar='DIR')
    namespace = parser.parse_args()
    options = vars(namespace)
    src = options.pop('src')[0]
    dest = options.pop('dest')[0]
    compiler_ = compiler.Compiler(**options)
    compiler_.generate_to_file(dest, src)

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


<commit_before>import os
import argparse

from elasticgit.storage import StorageManager

from pyramid.paster import bootstrap
from pyramid.request import Request

from unicore.distribute.utils import get_repositories
from unicore.webhooks.events import WebhookEvent

class PollRepositories(object):

    # This gets set at run time or is overriden for tests
    notify = None

    def run(self, repo_dir, ini_file, base_url):
        request = Request.blank('/', base_url=base_url)
        env = bootstrap(ini_file, request=request)
        self.notify = env['registry'].notify
        for repo in get_repositories(repo_dir):
            self.pull_repo(env, repo)

        # http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/narr/commandline.html#cleanup # noqa
        env['closer']()

    def pull_repo(self, env, repo):
        sm = StorageManager(repo)
        remote = repo.remotes[0]
        head = repo.heads[0]
        original_commit = head.commit
        sm.pull(branch_name=head.name,
                remote_name=remote.name)
        last_commit = repo.heads[0].commit
        if original_commit.hexsha != last_commit.hexsha:
            name = os.path.basename(repo.working_dir)
            request = env['request']
            self.notify(
                WebhookEvent(
                    owner=None,
                    event_type='repo.push',
                    payload={
                        'repo': name,
                        'url': request.route_url(
                            'repositoryresource', name=name)
                    }))

def get_parser():  # pragma: no cover
    parser = argparse.ArgumentParser(
        description="unicore.distribute command line tools.")
    subparser = parser.add_subparsers(help='Commands')
    command = subparser.add_parser(
        'poll-repositories', help='poll repositories')
    command.add_argument(
        '-d', '--repo-dir',
        dest='repo_dir',
        help='The directory with repositories.',
        default='./repos')
    command.add_argument(
        '-i', '--ini-file',
        dest='ini_file',
        help='The project\'s ini file.',
        default='development.ini')
    command.add_argument(
        '-u', '--base-url',
        dest='base_url',
        help='This server\'s public URL (for webhooks)',
        default='http://localhost/')
    command.set_defaults(dispatcher=PollRepositories)

    return parser

def run(parser):  # pragma: no cover
    args = parser.parse_args()
    data = vars(args)
    dispatcher_class = data.pop('dispatcher')
    dispatcher = dispatcher_class()
    dispatcher.run(**data)

def main():  # pragma: no cover
    parser = get_parser()
    run(parser)
<commit_msg>using active_branch rather than heads[0] (thanks @rizziepit)<commit_after>import os
import argparse

from elasticgit.storage import StorageManager

from pyramid.paster import bootstrap
from pyramid.request import Request

from unicore.distribute.utils import get_repositories
from unicore.webhooks.events import WebhookEvent

class PollRepositories(object):

    # This gets set at run time or is overriden for tests
    notify = None

    def run(self, repo_dir, ini_file, base_url):
        request = Request.blank('/', base_url=base_url)
        env = bootstrap(ini_file, request=request)
        self.notify = env['registry'].notify
        for repo in get_repositories(repo_dir):
            self.pull_repo(env, repo)

        # http://docs.pylonsproject.org/projects/pyramid/en/1.3-branch/narr/commandline.html#cleanup # noqa
        env['closer']()

    def pull_repo(self, env, repo):
        sm = StorageManager(repo)
        remote = repo.remotes[0]
        branch = repo.active_branch
        original_commit = branch.commit
        sm.pull(branch_name=branch.name,
                remote_name=remote.name)
        last_commit = branch.commit
        if original_commit.hexsha != last_commit.hexsha:
            name = os.path.basename(repo.working_dir)
            request = env['request']
            self.notify(
                WebhookEvent(
                    owner=None,
                    event_type='repo.push',
                    payload={
                        'repo': name,
                        'url': request.route_url(
                            'repositoryresource', name=name)
                    }))

def get_parser():  # pragma: no cover
    parser = argparse.ArgumentParser(
        description="unicore.distribute command line tools.")
    subparser = parser.add_subparsers(help='Commands')
    command = subparser.add_parser(
        'poll-repositories', help='poll repositories')
    command.add_argument(
        '-d', '--repo-dir',
        dest='repo_dir',
        help='The directory with repositories.',
        default='./repos')
    command.add_argument(
        '-i', '--ini-file',
        dest='ini_file',
        help='The project\'s ini file.',
        default='development.ini')
    command.add_argument(
        '-u', '--base-url',
        dest='base_url',
        help='This server\'s public URL (for webhooks)',
        default='http://localhost/')
    command.set_defaults(dispatcher=PollRepositories)

    return parser

def run(parser):  # pragma: no cover
    args = parser.parse_args()
    data = vars(args)
    dispatcher_class = data.pop('dispatcher')
    dispatcher = dispatcher_class()
    dispatcher.run(**data)

def main():  # pragma: no cover
    parser = get_parser()
    run(parser)
<|endoftext|>


<commit_before># BEGIN LOTTERY_BLOWER

import random

from tombola import Tombola

class LotteryBlower(Tombola):

    def __init__(self, iterable):
        self._balls = list(iterable)  # <1>

    def load(self, iterable):
        self._balls.extend(iterable)

    def pick(self):
        try:
            position = random.randrange(len(self._balls))  # <2>
        except ValueError:
            raise LookupError('pick from empty BingoCage')
        return self._balls.pop(position)  # <3>

    def loaded(self):  # <4>
        return bool(self._balls)

    def inspect(self):  # <5>
        return tuple(sorted(self._balls))

# END LOTTERY_BLOWER
<commit_msg>correct LookupError<commit_after># BEGIN LOTTERY_BLOWER

import random

from tombola import Tombola

class LotteryBlower(Tombola):

    def __init__(self, iterable):
        self._balls = list(iterable)  # <1>

    def load(self, iterable):
        self._balls.extend(iterable)

    def pick(self):
        try:
            position = random.randrange(len(self._balls))  # <2>
        except ValueError:
            raise LookupError('pick from empty LotteryBlower')
        return self._balls.pop(position)  # <3>

    def loaded(self):  # <4>
        return bool(self._balls)

    def inspect(self):  # <5>
        return tuple(sorted(self._balls))

# END LOTTERY_BLOWER
<|endoftext|>


<commit_before>#!/usr/bin/python
# -*- coding: utf-8 -*-

BUILD = 12644
TESTS = {}

TESTS[11723] = {
	 1010: "Curse the target with idiocy, reducing Intellect and Spirit by 6 every 3 seconds until each is reduced by a total of 90.  Only one Curse per Warlock can be active on any one target.",
	 2687: "Generates 20 rage at the cost of health, and then generates an additional 10 rage over 10 sec.",
	 8024: "Imbue the Shaman's weapon with fire, increasing total spell damage by 7. Each hit causes 4.2 to 13.0 additional Fire damage, based on the speed of the weapon.  Slower weapons cause more fire damage per swing.  Lasts 30 minutes.",
	10390: "Causes an explosion of arcane magic around the caster, causing 0 damage to all targets within 0 yards.",
	11213: "Gives you a 2% chance of entering a Clearcasting state after any damage spell hits a target.  The Clearcasting state reduces the mana cost of your next damage spell by 100%.",
	14253: "Attempts to cure 1 poison effect on the target, and 1 more poison effect every 2 seconds for 8 sec.",
	16190: "Summons a Mana Tide Totem with 10% of the caster's health at the feet of the caster for 12 sec that restores 6% of total mana every 3 seconds to group members within 30 yards.",
	21228: "Increases the duration of your Arcane Missiles by 1 sec.",
	23025: "Reduces the cooldown of your Blink spell by 2 sec.",
	29907: "Hits an enemy with an anti-mana bolt that consumes up to 255 to 295 mana. For each point of mana consumed by the bolt, the target takes 1.0 damage.",
	29977: "When activated, this spell causes each of your Fire damage spell hits to increase your critical strike chance with Fire damage spells by 10%.  This effect lasts until you have caused 3 critical strikes with Fire spells.",
	31687: "Summon a Water Elemental to fight for the caster for 45 sec.",
	33127: "Gives the Paladin a chance to deal additional Holy damage equal to 36% of normal weapon damage.  Only one Seal can be active on the Paladin at any one time.  Lasts 30 sec.\r\n\r\nUnleashing this Seal's energy will judge an enemy, instantly causing $s1 Holy damage, $s1 if the target is stunned or incapacitated.",
	36459: "Summon a Water Elemental to fight for the caster for until cancelled.",
	36950: "Causes up to 5 nearby enemies to flee for 6 sec.",
	37360: "Imbue your weapon with power, increasing attack power against undead and demons by 150.  Lasts 5 min.  Cannot be used on items level 138 and higher.",
	39758: "Soothes the target, reducing the range at which it will attack you by 1000 yards.  Only affects Humanoid targets level 200 or lower.  Lasts 1 hour.",
	39794: "Brings a dead player back to life with 1 health and 0 mana.  Cannot be cast when in combat.",
	47471: "Attempt to finish off a wounded foe, causing [1456+AP*0.2] damage and converting each extra point of rage into 38 additional damage (up to a maximum cost of 30 rage).  Only usable on enemies that have less than 20% health.",
	48677: "Throw burning oil at your pursuers slowing them down and inflicting 21336 to 42664 Fire damage over 8 sec.",
	49628: "Your auto attacks have a 30% chance to cause a Blood-Caked Strike, which hits for 25% weapon damage plus 12.5% for each of your diseases on the target.",
	53717: "Cause a corpse to explode for 60 Nature damage modified by attack power to all enemies within 20 yards.  Will use a nearby corpse if none is targeted.  Does not affect mechanical or elemental corpses.",
	57861: "Lets loose a roar, Increaseing damage taken by 20% for $.",
	58425: "Your finishing moves have a 20% chance per combo point to restore 25 energy.",
	58644: "Reduces the cost of your Frost Strike by -5864.",
	58645: "Restores 18480 health and 12840 mana over 30 sec.  Must remain seated while eating.",
	61905: "Summons a Magma Totem with 5000 health at the feet of the caster for -1 sec that causes 371 Fire damage to creatures within 8 yards every 2 seconds.",
	64936: "Shield Block also grants you $s1% reduction to magical damage taken.",
	66188: "A deadly attack that deals 150% offhand weapon damage plus a bonus and heals the Death Knight for 5.0% of <his/her> maximum health for each of <his/her> diseases on the target.",
	69561: "Restores 19200 mana over 30 sec.  Must remain seated while drinking.  If you spend at least 10 seconds drinking you will become \"well fed\" and gain 40 critical strike rating for 1 hour. Standard alcohol.",
	71180: "Reduces the cast time of your next Frostbolt or Frostfire Bolt by $/1000S1 sec.  Lasts 10 sec.",
	72930: "Chills a random target, reducing movement speed by 50% and dealing significant Frost damage after 14 sec.",
	75878: "Deals 75000 to 85000 Fire damage to enemies within 0 yards and spawns a Living Inferno.",
}

_ = TESTS[12266] = TESTS[11723].copy()
del _[1010], _[37360], _[47471], _[57861], _[75878]
_[14253] = "Attempts to cure 1 poison effect on the target, and $s1 more poison effect every 2 seconds for 8 sec."
_[15349] = "Increases your critical healing effect chance by 2% for each harmful damage-over-time effect on your target up to 2 effects or -20% increased critical healing effect chance."
_[16190] = "Summons a Mana Tide Totem with 10% of the caster's health at the feet of the caster for 12 sec that restores 6% of total mana every 3 seconds to group members within 10 yards." # scaling
_[61905] = "Summons a Magma Totem with 5000 health at the feet of the caster for -1 sec that causes $s1 Fire damage to creatures within $a1 yards every $t1 seconds."
_[78273] = "Imbue the Shaman's weapon with fire, increasing total spell damage by 7. Each hit causes $/78275m1 to 1 additional Fire damage. Lasts 30 minutes."

_ = TESTS[12644] = TESTS[12266].copy()
del _[29977], _[31687], _[58425]
_[11213] = "Gives you a 3% chance of entering a Clearcasting state after any damage spell hits a target.  The Clearcasting state reduces the mana cost of your next damage spell by 100%."
_[33127] = "Gives the Paladin a chance to deal additional Holy damage equal to 15% of normal weapon damage.  Only one Seal can be active on the Paladin at any one time.  Lasts 30 sec.\r\n\r\nUnleashing this Seal's energy will judge an enemy, instantly causing $s1 Holy damage, $s1 if the target is stunned or incapacitated."
_[86479] = "Select a talent specialization in order to activate the bonus from mastery rating. Consult your talent overview pane for additional information."

def main():
	from pywow.wdbc.environment import Environment
	from pywow.spellstrings import SpellString, WDBCProxy

	f = Environment(BUILD)["Spell.dbc"]

	fail, success = 0, 0
	for id, expected in sorted(TESTS[BUILD].items()):
		print "Testing %i..." % (id),
		if id not in f:
			print "PASS"
			continue

		spell = f[id]
		description = SpellString(spell.description_enus).format(spell, proxy=WDBCProxy)

		if description != expected:
			print "FAIL"
			print "Returned:", repr(description)
			print "Expected:", repr(expected)
			print "Original:", repr(spell.description_enus)
			fail += 1
		else:
			print "OK"
			success += 1

	print "%i/%i tests passed, %i failure" % (success, fail+success, fail)

if __name__ == "__main__":
	main()
<commit_msg>spellstrings/tests: Fix a typo in a test<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-

BUILD = 12644
TESTS = {}

TESTS[11723] = {
	 1010: "Curse the target with idiocy, reducing Intellect and Spirit by 6 every 3 seconds until each is reduced by a total of 90.  Only one Curse per Warlock can be active on any one target.",
	 2687: "Generates 20 rage at the cost of health, and then generates an additional 10 rage over 10 sec.",
	 8024: "Imbue the Shaman's weapon with fire, increasing total spell damage by 7. Each hit causes 4.2 to 13.0 additional Fire damage, based on the speed of the weapon.  Slower weapons cause more fire damage per swing.  Lasts 30 minutes.",
	10390: "Causes an explosion of arcane magic around the caster, causing 0 damage to all targets within 0 yards.",
	11213: "Gives you a 2% chance of entering a Clearcasting state after any damage spell hits a target.  The Clearcasting state reduces the mana cost of your next damage spell by 100%.",
	14253: "Attempts to cure 1 poison effect on the target, and 1 more poison effect every 2 seconds for 8 sec.",
	16190: "Summons a Mana Tide Totem with 10% of the caster's health at the feet of the caster for 12 sec that restores 6% of total mana every 3 seconds to group members within 30 yards.",
	21228: "Increases the duration of your Arcane Missiles by 1 sec.",
	23025: "Reduces the cooldown of your Blink spell by 2 sec.",
	29907: "Hits an enemy with an anti-mana bolt that consumes up to 255 to 295 mana. For each point of mana consumed by the bolt, the target takes 1.0 damage.",
	29977: "When activated, this spell causes each of your Fire damage spell hits to increase your critical strike chance with Fire damage spells by 10%.  This effect lasts until you have caused 3 critical strikes with Fire spells.",
	31687: "Summon a Water Elemental to fight for the caster for 45 sec.",
	33127: "Gives the Paladin a chance to deal additional Holy damage equal to 36% of normal weapon damage.  Only one Seal can be active on the Paladin at any one time.  Lasts 30 sec.\r\n\r\nUnleashing this Seal's energy will judge an enemy, instantly causing $s1 Holy damage, $s1 if the target is stunned or incapacitated.",
	36459: "Summon a Water Elemental to fight for the caster for until cancelled.",
	36950: "Causes up to 5 nearby enemies to flee for 6 sec.",
	37360: "Imbue your weapon with power, increasing attack power against undead and demons by 150.  Lasts 5 min.  Cannot be used on items level 138 and higher.",
	39758: "Soothes the target, reducing the range at which it will attack you by 1000 yards.  Only affects Humanoid targets level 200 or lower.  Lasts 1 hour.",
	39794: "Brings a dead player back to life with 1 health and 0 mana.  Cannot be cast when in combat.",
	47471: "Attempt to finish off a wounded foe, causing [1456+AP*0.2] damage and converting each extra point of rage into 38 additional damage (up to a maximum cost of 30 rage).  Only usable on enemies that have less than 20% health.",
	48677: "Throw burning oil at your pursuers slowing them down and inflicting 21336 to 42664 Fire damage over 8 sec.",
	49628: "Your auto attacks have a 30% chance to cause a Blood-Caked Strike, which hits for 25% weapon damage plus 12.5% for each of your diseases on the target.",
	53717: "Cause a corpse to explode for 60 Nature damage modified by attack power to all enemies within 20 yards.  Will use a nearby corpse if none is targeted.  Does not affect mechanical or elemental corpses.",
	57861: "Lets loose a roar, Increaseing damage taken by 20% for $.",
	58425: "Your finishing moves have a 20% chance per combo point to restore 25 energy.",
	58644: "Reduces the cost of your Frost Strike by -5864.",
	58645: "Restores 18480 health and 12840 mana over 30 sec.  Must remain seated while eating.",
	61905: "Summons a Magma Totem with 5000 health at the feet of the caster for -1 sec that causes 371 Fire damage to creatures within 8 yards every 2 seconds.",
	64936: "Shield Block also grants you $s1% reduction to magical damage taken.",
	66188: "A deadly attack that deals 150% offhand weapon damage plus a bonus and heals the Death Knight for 5.0% of <his/her> maximum health for each of <his/her> diseases on the target.",
	69561: "Restores 19200 mana over 30 sec.  Must remain seated while drinking.  If you spend at least 10 seconds drinking you will become \"well fed\" and gain 40 critical strike rating for 1 hour. Standard alcohol.",
	71180: "Reduces the cast time of your next Frostbolt or Frostfire Bolt by $/1000S1 sec.  Lasts 10 sec.",
	72930: "Chills a random target, reducing movement speed by 50% and dealing significant Frost damage after 14 sec.",
	75878: "Deals 75000 to 85000 Fire damage to enemies within 0 yards and spawns a Living Inferno.",
}

_ = TESTS[12266] = TESTS[11723].copy()
del _[1010], _[37360], _[47471], _[57861], _[75878]
_[14253] = "Attempts to cure 1 poison effect on the target, and $s1 more poison effect every 2 seconds for 8 sec."
_[15349] = "Increases your critical healing effect chance by 2% for each harmful damage-over-time effect on your target up to 2 effects or -20% increased critical healing effect chance."
_[16190] = "Summons a Mana Tide Totem with 10% of the caster's health at the feet of the caster for 12 sec that restores 6% of total mana every 3 seconds to group members within 10 yards." # scaling
_[61905] = "Summons a Magma Totem with 5000 health at the feet of the caster for -1 sec that causes $s1 Fire damage to creatures within $a1 yards every $t1 seconds."
_[78273] = "Imbue the Shaman's weapon with fire, increasing total spell damage by 7. Each hit causes $/78275m1 to 1 additional Fire damage. Lasts 30 minutes."

_ = TESTS[12644] = TESTS[12266].copy()
del _[29977], _[31687], _[58425]
_[11213] = "Gives you a 3% chance of entering a Clearcasting state after any damage spell hits a target.  The Clearcasting state reduces the mana cost of your next damage spell by 100%."
_[33127] = "Gives the Paladin a chance to deal additional Holy damage equal to 15% of normal weapon damage.  Only one Seal can be active on the Paladin at any one time.  Lasts 30 sec.\r\n\r\nUnleashing this Seal's energy will judge an enemy, instantly causing $s1 Holy damage, $s1 if the target is stunned or incapacitated."
_[86479] = "Select a talent specialization in order to activate the bonus from mastery rating.  Consult your talent overview pane for additional information."

def main():
	from pywow.wdbc.environment import Environment
	from pywow.spellstrings import SpellString, WDBCProxy

	f = Environment(BUILD)["Spell.dbc"]

	fail, success = 0, 0
	for id, expected in sorted(TESTS[BUILD].items()):
		print "Testing %i..." % (id),
		if id not in f:
			print "PASS"
			continue

		spell = f[id]
		description = SpellString(spell.description_enus).format(spell, proxy=WDBCProxy)

		if description != expected:
			print "FAIL"
			print "Returned:", repr(description)
			print "Expected:", repr(expected)
			print "Original:", repr(spell.description_enus)
			fail += 1
		else:
			print "OK"
			success += 1

	print "%i/%i tests passed, %i failure" % (success, fail+success, fail)

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


<commit_before>import argparse
import sys

from gevent.event import Event

from spinoff.actor import Actor, Node
from spinoff.actor.exceptions import Unhandled
from spinoff.util.logging import err

_EMPTY = object()

class Wrapper(Actor):
    def __init__(self, actor_factory, spawn_at, keep_running, initial_messages, stop_event):
        self.actor_factory = actor_factory
        self.spawn_at = spawn_at
        self.keep_running = keep_running
        self.initial_messages = initial_messages
        self.stop_event = stop_event

    def _do_spawn(self):
        self.actor = self.watch(self.node.spawn(self.actor_factory, name=self.spawn_at))

    def pre_start(self):
        self._do_spawn()
        for msg in self.initial_messages:
            self.actor << msg

    def receive(self, message):
        if message == ('terminated', self.actor):
            _, actor = message
            if self.keep_running:
                self.send_later(1.0, '-spawn')
            else:
                self.stop()
        elif message == '-spawn':
            self._do_spawn()
        else:
            raise Unhandled

    def post_stop(self):
        self.stop_event.set()

    def __repr__(self):
        return '#wrapper#'

def spin(actor_cls, name=None, init_params={}, node_id=None, initial_messages=[], keep_running=False, enable_relay=False, wrapper_cls=Wrapper):
    node = Node(nid=node_id, enable_remoting=True if node_id else False, enable_relay=enable_relay)
    stop_event = Event()
    node.spawn(wrapper_cls.using(
        actor_cls.using(**init_params),
        spawn_at=name, keep_running=keep_running,
        initial_messages=initial_messages,
        stop_event=stop_event
    ), name='-runner')
    try:
        stop_event.wait()
    except KeyboardInterrupt:
        pass

def console():
    class _ImportFailed(Exception):
        pass

    class _InitError(Exception):
        pass

    argparser = argparse.ArgumentParser(
        description="Runs the specified actor",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    )
    argparser.add_argument('actor', metavar='ACTOR',
                           help="The actor to run")
    argparser.add_argument('-init', '--init-params', metavar='INIT', default={},
                           help="Parameters to pass to the actor")
    argparser.add_argument('-msg', '--initial-message', metavar='MSG', nargs='*', default=[],
                           help="Messages to send to the actor. Specify multiple times to send multiple messages. These must be valid Python expressions")
    argparser.add_argument('-keep', '--keep-running', action='store_true',
                           help="Whether to respawn the actor when it terminates")
    argparser.add_argument('-name', '--name', metavar='NAME',
                           help="What to name the actor")
    argparser.add_argument('-nid', '--node-id', metavar='NODEID',
                           help="What to name the actor")
    argparser.add_argument('-relay', '--enable-relay', metavar='RELAY',
                           help="What to name the actor")

    args = argparser.parse_args()

    try:
        try:
            if '.' not in args.actor:
                raise _ImportFailed
                sys.exit(1)
            else:
                mod_name, cls_name = args.actor.rsplit('.', 1)
                try:
                    mod = __import__(mod_name, fromlist=[cls_name])
                except ImportError:
                    raise _ImportFailed
                try:
                    actor_cls = getattr(mod, cls_name)
                except AttributeError:
                    raise _ImportFailed
        except _ImportFailed:
            raise _InitError("Failed to import %s" % (args.actor,))

        eval_str = 'dict(%s)' % (args.init_params,)
        try:
            init_params = eval(eval_str)
        except Exception:
            raise _InitError("Failed to parse value: -init/--init-params")

        initial_messages = []
        for msg_raw in args.initial_message:
            try:
                msg = eval(msg_raw)
            except Exception:
                quote = '\'' if '"' in msg_raw else '"'
                raise _InitError("Failde to parse value: -msg %s%s%s" % (quote, msg_raw, quote))
            else:
                initial_messages.append(msg)
    except _InitError as exc:
        err(exc.args[0])
        sys.exit(exc.args[1] if len(exc.args) > 1 else 1)

    spin(actor_cls, name=args.name, init_params=init_params, node_id=args.node_id,
         initial_messages=initial_messages, keep_running=args.keep_running, enable_relay=args.enable_relay)
<commit_msg>Let ImportErrors pass thru in spin()<commit_after>import argparse
import sys

from gevent.event import Event

from spinoff.actor import Actor, Node
from spinoff.actor.exceptions import Unhandled
from spinoff.util.logging import err

_EMPTY = object()

class Wrapper(Actor):
    def __init__(self, actor_factory, spawn_at, keep_running, initial_messages, stop_event):
        self.actor_factory = actor_factory
        self.spawn_at = spawn_at
        self.keep_running = keep_running
        self.initial_messages = initial_messages
        self.stop_event = stop_event

    def _do_spawn(self):
        self.actor = self.watch(self.node.spawn(self.actor_factory, name=self.spawn_at))

    def pre_start(self):
        self._do_spawn()
        for msg in self.initial_messages:
            self.actor << msg

    def receive(self, message):
        if message == ('terminated', self.actor):
            _, actor = message
            if self.keep_running:
                self.send_later(1.0, '-spawn')
            else:
                self.stop()
        elif message == '-spawn':
            self._do_spawn()
        else:
            raise Unhandled

    def post_stop(self):
        self.stop_event.set()

    def __repr__(self):
        return '#wrapper#'

def spin(actor_cls, name=None, init_params={}, node_id=None, initial_messages=[], keep_running=False, enable_relay=False, wrapper_cls=Wrapper):
    node = Node(nid=node_id, enable_remoting=True if node_id else False, enable_relay=enable_relay)
    stop_event = Event()
    node.spawn(wrapper_cls.using(
        actor_cls.using(**init_params),
        spawn_at=name, keep_running=keep_running,
        initial_messages=initial_messages,
        stop_event=stop_event
    ), name='-runner')
    try:
        stop_event.wait()
    except KeyboardInterrupt:
        pass

def console():
    class _ImportFailed(Exception):
        pass

    class _InitError(Exception):
        pass

    argparser = argparse.ArgumentParser(
        description="Runs the specified actor",
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    )
    argparser.add_argument('actor', metavar='ACTOR',
                           help="The actor to run")
    argparser.add_argument('-init', '--init-params', metavar='INIT', default={},
                           help="Parameters to pass to the actor")
    argparser.add_argument('-msg', '--initial-message', metavar='MSG', nargs='*', default=[],
                           help="Messages to send to the actor. Specify multiple times to send multiple messages. These must be valid Python expressions")
    argparser.add_argument('-keep', '--keep-running', action='store_true',
                           help="Whether to respawn the actor when it terminates")
    argparser.add_argument('-name', '--name', metavar='NAME',
                           help="What to name the actor")
    argparser.add_argument('-nid', '--node-id', metavar='NODEID',
                           help="What to name the actor")
    argparser.add_argument('-relay', '--enable-relay', metavar='RELAY',
                           help="What to name the actor")

    args = argparser.parse_args()

    try:
        if '.' not in args.actor:
            raise _InitError("Failed to import %s" % (args.actor,))
            sys.exit(1)
        else:
            mod_name, cls_name = args.actor.rsplit('.', 1)
            mod = __import__(mod_name, fromlist=[cls_name])
            actor_cls = getattr(mod, cls_name)

        eval_str = 'dict(%s)' % (args.init_params,)
        try:
            init_params = eval(eval_str)
        except Exception:
            raise _InitError("Failed to parse value: -init/--init-params")

        initial_messages = []
        for msg_raw in args.initial_message:
            try:
                msg = eval(msg_raw)
            except Exception:
                quote = '\'' if '"' in msg_raw else '"'
                raise _InitError("Failde to parse value: -msg %s%s%s" % (quote, msg_raw, quote))
            else:
                initial_messages.append(msg)
    except _InitError as exc:
        err(exc.args[0])
        sys.exit(exc.args[1] if len(exc.args) > 1 else 1)

    spin(actor_cls, name=args.name, init_params=init_params, node_id=args.node_id,
         initial_messages=initial_messages, keep_running=args.keep_running, enable_relay=args.enable_relay)
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
import datetime
import click
import logging
from .helpers import render_bot_statistic, render_bot_tradelog, render_bot_title

log = logging.getLogger(__name__)

BUY = 1
SELL = -1
WAIT = 0
QUIT = -99
signal_map = {
    BUY: "BUY",
    WAIT: "WAIT",
    SELL: "SELL",
    QUIT: "QUIT"
}
# Signals for strategies.

class Signal(object):

    def __init__(self, signal, date):
        self.value = signal
        self.date = date

class Strategy(object):

    """Docstring for Strategy. """

    def __str__(self):
        return "{}".format(self.__class__)

    def __init__(self):
        self._signal_history = []
        """Store last emitted signals"""
        self._bot = None

    def set_bot(self, bot):
        self._bot = bot

    def details(self, market, resolution):
        """Will return details on the reasong why the signal was emited."""
        raise NotImplementedError

    def signal(self, market, resolution, start, end):
        """Will return either a BUY, SELL or WAIT signal for the given
        market"""
        raise NotImplementedError

class InteractivStrategyWrapper(object):

    def __init__(self, strategie):
        self._strategie = strategie
        self._bot = None

    def set_bot(self, bot):
        self._bot = bot

    def __str__(self):
        return "Interavtiv: {}".format(self._strategie)

    def signal(self, market, resolution, start, end):
        """Will return either a BUY, SELL or WAIT signal for the given
        market"""

        # Get current chart
        click.echo(render_bot_title(self._bot, market, resolution))
        signal = self._strategie.signal(market, resolution, start, end)

        click.echo('Signal: {} {}'.format(signal.date, signal_map[signal.value]))
        click.echo('')
        options = []
        if self._bot.btc:
            options.append("b) Buy")
        if self._bot.amount:
            options.append("s) Sell")
        options.append("l) Tradelog")
        options.append("p) Performance of bot")
        options.append("q) Quit")
        options.append("")
        options.append("Press any key to continue")

        click.echo(u'\n'.join(options))
        c = click.getchar()
        if c == 'b' and self._bot.btc:
            # btc = click.prompt('BTC', default=self._bot.btc)
            if click.confirm('Buy for {} btc?'.format(self._bot.btc)):
                return Signal(BUY, datetime.datetime.utcnow())
        if c == 's' and self._bot.amount:
            # amount = click.prompt('Amount', default=self._bot.amount)
            if click.confirm('Sell {}?'.format(self._bot.amount)):
                return Signal(SELL, datetime.datetime.utcnow())
        if c == 'l':
            click.echo(render_bot_tradelog(self._bot.trades))
        if c == 'p':
            click.echo(render_bot_statistic(self._bot.stat()))
            # click.echo(self._strategie.details(market, resolution))
        if c == 'q':
            return Signal(QUIT, datetime.datetime.utcnow())
        else:
            return Signal(WAIT, datetime.datetime.utcnow())
<commit_msg>Added details command again to CLI<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
import datetime
import click
import logging
from .helpers import render_bot_statistic, render_bot_tradelog, render_bot_title

log = logging.getLogger(__name__)

BUY = 1
SELL = -1
WAIT = 0
QUIT = -99
signal_map = {
    BUY: "BUY",
    WAIT: "WAIT",
    SELL: "SELL",
    QUIT: "QUIT"
}
# Signals for strategies.

class Signal(object):

    def __init__(self, signal, date):
        self.value = signal
        self.date = date

class Strategy(object):

    """Docstring for Strategy. """

    def __str__(self):
        return "{}".format(self.__class__)

    def __init__(self):
        self._signal_history = []
        """Store last emitted signals"""
        self._bot = None

    def set_bot(self, bot):
        self._bot = bot

    def details(self, market, resolution):
        """Will return details on the reasong why the signal was emited."""
        raise NotImplementedError

    def signal(self, market, resolution, start, end):
        """Will return either a BUY, SELL or WAIT signal for the given
        market"""
        raise NotImplementedError

class InteractivStrategyWrapper(object):

    def __init__(self, strategie):
        self._strategie = strategie
        self._bot = None

    def set_bot(self, bot):
        self._bot = bot

    def __str__(self):
        return "Interavtiv: {}".format(self._strategie)

    def signal(self, market, resolution, start, end):
        """Will return either a BUY, SELL or WAIT signal for the given
        market"""

        # Get current chart
        click.echo(render_bot_title(self._bot, market, resolution))
        signal = self._strategie.signal(market, resolution, start, end)

        click.echo('Signal: {} {}'.format(signal.date, signal_map[signal.value]))
        click.echo('')
        options = []
        if self._bot.btc:
            options.append("b) Buy")
        if self._bot.amount:
            options.append("s) Sell")
        options.append("l) Tradelog")
        options.append("p) Performance of bot")
        options.append("d) Show details on signal")
        options.append("q) Quit")
        options.append("")
        options.append("Press any key to continue")

        click.echo(u'\n'.join(options))
        c = click.getchar()
        if c == 'b' and self._bot.btc:
            # btc = click.prompt('BTC', default=self._bot.btc)
            if click.confirm('Buy for {} btc?'.format(self._bot.btc)):
                return Signal(BUY, datetime.datetime.utcnow())
        if c == 's' and self._bot.amount:
            # amount = click.prompt('Amount', default=self._bot.amount)
            if click.confirm('Sell {}?'.format(self._bot.amount)):
                return Signal(SELL, datetime.datetime.utcnow())
        if c == 'l':
            click.echo(render_bot_tradelog(self._bot.trades))
        if c == 'p':
            click.echo(render_bot_statistic(self._bot.stat()))
        if c == 'd':
            click.echo(self._strategie.details(market, resolution))
        if c == 'q':
            return Signal(QUIT, datetime.datetime.utcnow())
        else:
            return Signal(WAIT, datetime.datetime.utcnow())
<|endoftext|>


<commit_before>from .spi_rack import SPI_rack
from .chip_mode import MAX5702_MODE, MAX5702_SPEED, MCP320x_MODE

class M2j_module(object):

    def __init__(self, spi_rack, module):
        # Set module number for Chip Select
        self.module = module
        # Give the spi_rack object to use
        self.spi_rack = spi_rack

        # Set DAC reference to 2.5V internal
        s_data = bytearray([0b01110001,0,0])
        self.spi_rack.write_data(self.module, 0, MAX5702_MODE, MAX5702_SPEED, s_data)

    def get_level(self):
        s_data = bytearray([0, 0])
        r_data = self.spi_rack.read_data(self.module, 1, MCP320x_MODE, MAX5702_SPEED, s_data)
        return (r_data[0]&0x0F)<<8 | r_data[1]

    def set_gain(self, level):
        s_data = bytearray([0b10000010, (level&0xFF0)>>4, (level&0x0F)<<4])
        self.spi_rack.write_data(self.module, 0, MAX5702_MODE, MAX5702_SPEED, s_data)

    def clear_rf_clip(self):
        # SPI address 5 for writing
        # Resets clipped bit
        self.spi_rack.write_data(self.module, 5, 0, 6, bytearray([0xF7]))
        self.spi_rack.write_data(self.module, 5, 0, 6, bytearray([0xFF]))

    def rf_clipped(self):
        # SPI adress 6 for reading
        # Return True if clipped, False if not clipped
        inputs = self.spi_rack.read_data(2, 6, 0, bytearray([0x00]))
        inputs = int.from_bytes(inputs, byteorder='big')
        inputs = (inputs>>3)&0x01
        return bool(inputs)
<commit_msg>M2j remote select<commit_after>from .spi_rack import SPI_rack
from .chip_mode import MAX5702_MODE, MAX5702_SPEED, MCP320x_MODE, BICPINS_SPEED

class M2j_module(object):
    """M2j module interface class

    This class does the low level interfacing with the M2j amplifier module. It
    requires a SPI Rack object and module number at initializationself.

    Allows the user to get the RF level before the last amplifier and see if
    the amplifiers are clipping. The user can also set the amplification of the
    module by changing a variable attenuator inside the unit.

    Attributes:
        module: the module number set by the user (must coincide with hardware)
        remote: true if remote control is enabled
    """

    def __init__(self, spi_rack, module, remote=False):
        """Inits M2j module class

        The M2j module needs an SPI_rack class for communication. Resets the dual
        DAC output at startup.

        Args:
            spi_rack: SPI_rack class object via which the communication runs
            module: module number set on the hardware
            remote: enable/disable remote control
        Example:
            M2j = M2j_module(SPI_Rack_1, 5)
        """
        # Set module number for Chip Select
        self.module = module
        # Give the spi_rack object to use
        self.spi_rack = spi_rack

        # Set remote control
        self.enable_remote(remote)

        # Set BIC outputs SPI6 MOSI connected to -CLR Dual DAC      # HvdD
        self.spi_rack.write_data(self.module, 5, 0, 6, bytearray([0xFF]))

        # Set DAC reference to 2.5V internal
        s_data = bytearray([0b01110001, 0, 0])
        self.spi_rack.write_data(self.module, 0, MAX5702_MODE, MAX5702_SPEED, s_data)

    def get_level(self):
        s_data = bytearray([0, 0])
        r_data = self.spi_rack.read_data(self.module, 1, MCP320x_MODE, MAX5702_SPEED, s_data)
        return (r_data[0]&0x0F)<<8 | r_data[1]

    def set_gain(self, level):
        s_data = bytearray([0b10000010, (level&0xFF0)>>4, (level&0x0F)<<4])
        self.spi_rack.write_data(self.module, 0, MAX5702_MODE, MAX5702_SPEED, s_data)

    def enable_remote(self, enable):
        """Enables remote control of module

        Set to 1/True to enable remote control and 0/False to disable. If enabled
        the setting on the front of the module is ignored and all control happens
        remotely.

        Args:
            enable (bool/int: 0-1): enables/disables remote control
        """
        self.remote = enable
        #Keep the clear rf clip high (active low)
        self.spi_rack.write_data(self.module, 5, 0, BICPINS_SPEED, bytearray([self.remote<<5 | 16]))

    def clear_rf_clip(self):
        """Clears rf clip bit

        Resets the rf clip bit.
        """
        # SPI address 5 for writing
        # Resets clipped bit
        self.spi_rack.write_data(self.module, 5, 0, BICPINS_SPEED, bytearray([self.remote<<4]))
        self.spi_rack.write_data(self.module, 5, 0, BICPINS_SPEED, bytearray([self.remote<<4 | 8]))

    def rf_clipped(self):
        """Return if the RF clipped

        If the RF clipped since the last RF bit reset, returns True. Else returns False.

        Returns:
            True/False depending if the RF clipped (bool)
        """

        data = self.spi_rack.read_data(self.module, 6, 0, BICPINS_SPEED, bytearray([0]))
        return bool(data[0]&0x08)
<|endoftext|>