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

import wave, struct, random, math
import os, sys

from utility import *
from scales  import *

# same included wave functions
# a function of frequency and tick
#   each function accepts the frequency and tick,
#   and returns a value from -1 to 1

sine     = lambda f, t: math.sin(2 * math.pi * t * f / 44100.0)
square   = lambda f, t: 0.6 * ((t % (44100 / f) >= ((44100 / f)/2)) * 2 - 1)
sawtooth = lambda f, t: (t % (44100 / f)) / (44100 / f) * 2 - 1
def triangle(f, t):
    v = 2 * (t % (44100 / f)) / (44100 / f)
    if t % (44100 / f) >= (44100 / (2 * f)):
        v = 2 * 1 - v
    v = 2 * v - 1
    return v

class Melopy:
    def __init__(self, title='sound', volume=20, tempo=120, octave=4):
        self.title = title.lower()
        self.rate = 44100
        self.volume = volume
        self.data = []

        self.tempo = tempo
        self.octave = octave
        self.wave_type = sine

    def add_wave(self, frequency, length, location='END'):
        if location == 'END':
            location = len(self.data)
        elif location < 0:
            location = 0
        elif location * 44100 > len(self.data):
            location = len(self.data) / 44100.0

        # location is a time, so let's adjust
        location = int(location * 44100)

        for n in range(0, int(44100 * length)):
            val = self.wave_type(frequency, n)
            val *= self.volume / 100.0 * 32767

            if location + n >= len(self.data):
                self.data.append(val)
            else:
                current_val = self.data[location + n]
                if current_val + val > 32767:
                    val = 32767
                elif current_val + val < -32768:
                    val = -32768
                else:
                    val += current_val

                self.data[location + n] = val

    def add_note(self, note, length, location='END'):
        """Add a note, or if a list, add a chord."""
        if not isinstance(note, list):
            note = [note]

        if location == 'END':
            location = len(self.data) / 44100.0

        for item in note:
            if item[-1] not in '0123456789':
                item += str(self.octave)

            self.add_wave(note_to_frequency(item, self.octave), length, location)

    def add_melody(self, melody, length):
        for note in melody:
            if note[-1] not in '0123456789':
                note += self.octave
            self.add_wave(note_to_frequency(note), length)

    def add_whole_note(self, note, location='END'):
        """Add a whole note"""
        self.add_fractional_note(note, 1.0, location)

    def add_half_note(self, note, location='END'):
        """Add a half note"""
        self.add_fractional_note(note, 1.0 / 2, location)

    def add_quarter_note(self, note, location='END'):
        """Add a quarter note"""
        self.add_fractional_note(note, 1.0 / 4, location)

    def add_eighth_note(self, note, location='END'):
        """Add a eigth note"""
        self.add_fractional_note(note, 1.0 / 8, location)

    def add_sixteenth_note(self, note, location='END'):
        """Add a sixteenth note"""
        self.add_fractional_note(note, 1.0 / 16, location)

    def add_fractional_note(self, note, fraction, location='END'):
        """Add a fractional note (smaller then 1/16 notes)"""
        self.add_note(note, 60.0 / self.tempo * (fraction * 4), location)

    def add_rest(self, length):
        for i in range(int(self.rate * length)):
            self.data.append(0)

    def add_whole_rest(self):
        self.add_fractional_rest(1.0)

    def add_half_rest(self):
        self.add_fractional_rest(1.0 / 2)

    def add_quarter_rest(self):
        self.add_fractional_rest(1.0 / 4)

    def add_eighth_rest(self):
        self.add_fractional_rest(1.0 / 8)

    def add_sixteenth_rest(self):
        self.add_fractional_rest(1.0 / 16)

    def add_fractional_rest(self, fraction):
        self.add_rest(60.0 / self.tempo * (fraction * 4))

    def parse(self, string, location='END'):
        tracks = string.split('&&&')

        # special case for multiple tracks
        if len(tracks) > 1:
            t = len(self.data) / 44100.0
            for track in tracks:
                self.parse(track, t)
            return

        cf = 0.25                    # start with a quarter note, change accordingly
        in_comment = False

        for i, char in enumerate(string):        # divide melody into fragments
            # / this is a comment /
            if char == '/':
                in_comment = not in_comment

            if in_comment:
                continue
            elif char in 'ABCDEFG':
                if (i+1 < len(string)) and (string[i+1] in '#b'):
                    # check if the next item in the array is
                    #    a sharp or flat, make sure we include it
                    char += string[i+1]

                self.add_fractional_note(char, cf, location)
                if location != 'END':
                    location += (60.0 / self.tempo * (cf * 4))
            elif char in map(str, range(0, 20)):
                self.octave = int(char)
            elif char == '+' or char == '^':
                self.octave += 1
            elif char == 'V' or char == 'v' or char == '-':
                self.octave -= 1
            elif char == '(' or char == ']':
                cf /= 2
            elif char == ')' or char == '[':
                cf *= 2
            elif char == '_':
                self.add_fractional_rest(cf)
                if location != 'END':
                    location += (60.0 / self.tempo * (cf * 4))

    def parsefile(self, filename, location='END'):
        fr = open(filename, 'r')
        s = fr.read()
        fr.close()

        self.parse(s, location)

    def render(self):
        """Render a playable song out to a .wav file"""
        melopy_writer = wave.open(self.title + '.wav', 'w')
        melopy_writer.setparams((2, 2, 44100, 0, 'NONE', 'not compressed'))
        p = -1
        data_frames = []

        for i in range(len(self.data)):
            q = 100 * i / len(self.data)
            if p != q:
                sys.stdout.write("\r[%s] %d%%" % (('='*int((float(i)/len(self.data)*50))+'>').ljust(50), 100 * i / len(self.data)))
                sys.stdout.flush()
                p = q
            packed_val = struct.pack('h', int(self.data[i]))
            data_frames.append(packed_val)
            data_frames.append(packed_val)

        melopy_writer.writeframes(''.join(data_frames))

        sys.stdout.write("\r[%s] 100%%" % ('='*50))
        sys.stdout.flush()
        sys.stdout.write("\nDone\n")
        melopy_writer.close()

# Licensed under The MIT License (MIT)
# See LICENSE file for more
<commit_msg>Added individual volume options<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

import wave, struct, random, math
import os, sys

from utility import *
from scales  import *

# same included wave functions
# a function of frequency and tick
#   each function accepts the frequency and tick,
#   and returns a value from -1 to 1

sine     = lambda f, t: math.sin(2 * math.pi * t * f / 44100.0)
square   = lambda f, t: 0.6 * ((t % (44100 / f) >= ((44100 / f)/2)) * 2 - 1)
sawtooth = lambda f, t: (t % (44100 / f)) / (44100 / f) * 2 - 1
def triangle(f, t):
    v = 2 * (t % (44100 / f)) / (44100 / f)
    if t % (44100 / f) >= (44100 / (2 * f)):
        v = 2 * 1 - v
    v = 2 * v - 1
    return v

class Melopy:
    def __init__(self, title='sound', volume=20, tempo=120, octave=4):
        self.title = title.lower()
        self.rate = 44100
        self.volume = volume
        self.data = []

        self.tempo = tempo
        self.octave = octave
        self.wave_type = sine

    def add_wave(self, frequency, length, location='END', level=None):
        if location == 'END':
            location = len(self.data)
        elif location < 0:
            location = 0
        elif location * 44100 > len(self.data):
            location = len(self.data) / 44100.0

        # location is a time, so let's adjust
        location = int(location * 44100)

        if level == None:
            level = self.volume
        elif level > 100:
            level = 100
        elif level < 0:
            level = 0

        for n in range(0, int(44100 * length)):
            val = self.wave_type(frequency, n)
            val *= level / 100.0 * 32767

            if location + n >= len(self.data):
                self.data.append(val)
            else:
                current_val = self.data[location + n]
                if current_val + val > 32767:
                    val = 32767
                elif current_val + val < -32768:
                    val = -32768
                else:
                    val += current_val

                self.data[location + n] = val

    def add_note(self, note, length, location='END', volume=None):
        """Add a note, or if a list, add a chord."""
        if not isinstance(note, list):
            note = [note]

        if location == 'END':
            location = len(self.data) / 44100.0

        if not isinstance(volume, list):
            volume = [volume]
        if volume[0] == None:
            volume = [float(self.volume)/len(note)] * len(note)
            #By default, when adding a chord, set equal level for each
            #component note, such that the sum volume is self.volume
        else:
            volume = volume + [volume[-1]]*(len(note) - len(volume))
            #Otherwise, pad volume by repeating the final level so that we have
            #enough level values for each note

        for item, level in zip(note, volume):
            if item[-1] not in '0123456789':
                item += str(self.octave)

            self.add_wave(note_to_frequency(item, self.octave), length, location, level)

    def add_melody(self, melody, length):
        for note in melody:
            if note[-1] not in '0123456789':
                note += self.octave
            self.add_wave(note_to_frequency(note), length)

    def add_whole_note(self, note, location='END', volume=None):
        """Add a whole note"""
        self.add_fractional_note(note, 1.0, location, volume)

    def add_half_note(self, note, location='END', volume=None):
        """Add a half note"""
        self.add_fractional_note(note, 1.0 / 2, location, volume)

    def add_quarter_note(self, note, location='END', volume=None):
        """Add a quarter note"""
        self.add_fractional_note(note, 1.0 / 4, location, volume)

    def add_eighth_note(self, note, location='END', volume=None):
        """Add a eigth note"""
        self.add_fractional_note(note, 1.0 / 8, location, volume)

    def add_sixteenth_note(self, note, location='END', volume=None):
        """Add a sixteenth note"""
        self.add_fractional_note(note, 1.0 / 16, location, volume)

    def add_fractional_note(self, note, fraction, location='END', volume=None):
        """Add a fractional note (smaller then 1/16 notes)"""
        self.add_note(note, 60.0 / self.tempo * (fraction * 4), location, volume)

    def add_rest(self, length):
        for i in range(int(self.rate * length)):
            self.data.append(0)

    def add_whole_rest(self):
        self.add_fractional_rest(1.0)

    def add_half_rest(self):
        self.add_fractional_rest(1.0 / 2)

    def add_quarter_rest(self):
        self.add_fractional_rest(1.0 / 4)

    def add_eighth_rest(self):
        self.add_fractional_rest(1.0 / 8)

    def add_sixteenth_rest(self):
        self.add_fractional_rest(1.0 / 16)

    def add_fractional_rest(self, fraction):
        self.add_rest(60.0 / self.tempo * (fraction * 4))

    def parse(self, string, location='END'):
        tracks = string.split('&&&')

        # special case for multiple tracks
        if len(tracks) > 1:
            t = len(self.data) / 44100.0
            for track in tracks:
                self.parse(track, t)
            return

        cf = 0.25                    # start with a quarter note, change accordingly
        in_comment = False

        for i, char in enumerate(string):        # divide melody into fragments
            # / this is a comment /
            if char == '/':
                in_comment = not in_comment

            if in_comment:
                continue
            elif char in 'ABCDEFG':
                if (i+1 < len(string)) and (string[i+1] in '#b'):
                    # check if the next item in the array is
                    #    a sharp or flat, make sure we include it
                    char += string[i+1]

                self.add_fractional_note(char, cf, location)
                if location != 'END':
                    location += (60.0 / self.tempo * (cf * 4))
            elif char in map(str, range(0, 20)):
                self.octave = int(char)
            elif char == '+' or char == '^':
                self.octave += 1
            elif char == 'V' or char == 'v' or char == '-':
                self.octave -= 1
            elif char == '(' or char == ']':
                cf /= 2
            elif char == ')' or char == '[':
                cf *= 2
            elif char == '_':
                self.add_fractional_rest(cf)
                if location != 'END':
                    location += (60.0 / self.tempo * (cf * 4))

    def parsefile(self, filename, location='END'):
        fr = open(filename, 'r')
        s = fr.read()
        fr.close()

        self.parse(s, location)

    def render(self):
        """Render a playable song out to a .wav file"""
        melopy_writer = wave.open(self.title + '.wav', 'w')
        melopy_writer.setparams((2, 2, 44100, 0, 'NONE', 'not compressed'))
        p = -1
        data_frames = []

        for i in range(len(self.data)):
            q = 100 * i / len(self.data)
            if p != q:
                sys.stdout.write("\r[%s] %d%%" % (('='*int((float(i)/len(self.data)*50))+'>').ljust(50), 100 * i / len(self.data)))
                sys.stdout.flush()
                p = q
            packed_val = struct.pack('h', int(self.data[i]))
            data_frames.append(packed_val)
            data_frames.append(packed_val)

        melopy_writer.writeframes(''.join(data_frames))

        sys.stdout.write("\r[%s] 100%%" % ('='*50))
        sys.stdout.flush()
        sys.stdout.write("\nDone\n")
        melopy_writer.close()

    def play(self):
        """Opens the song in the os default program"""
        os.startfile(self.title + '.wav')

# Licensed under The MIT License (MIT)
# See LICENSE file for more
<|endoftext|>


<commit_before>import declarative

__all__ = ['NoDefault', 'Invalid', 'Validator', 'Identity',
           'FancyValidator', 'is_validator']

class NoDefault:
    pass

def is_validator(obj):
    return (isinstance(obj, Validator) or
            (isinstance(obj, type) and
             issubclass(obj, Validator)))

class Invalid(Exception):

    """
    This is raised in response to invalid input.  It has several
    public attributes:

    msg:
        The message, *without* values substituted.  For instance, if
        you want HTML quoting of values, you can apply that.
    substituteArgs:
        The arguments (a dictionary) to go with `msg`.
    str(self):
        The message describing the error, with values substituted.
    value:
        The offending (invalid) value.
    state:
        The state that went with this validator.  This is an
        application-specific object.
    error_list:
        If this was a compound validator that takes a repeating value,
        and sub-validator(s) had errors, then this is a list of those
        exceptions.  The list will be the same length as the number of
        values -- valid values will have None instead of an exception.
    error_dict:
        Like `error_list`, but for dictionary compound validators.
    """

    def __init__(self, msg,
                 value, state, error_list=None, error_dict=None):
        Exception.__init__(self, msg)
        self.msg = msg
        self.value = value
        self.state = state
        self.error_list = error_list
        self.error_dict = error_dict

    def __str__(self):
        val = self.msg
        #if self.value:
        #    val += " (value: %s)" % repr(self.value)
        return val

    def unpack_errors(self):
        """
        Returns the error as a simple data structure -- lists,
        dictionaries, and strings.
        """
        if self.error_list:
            assert not self.error_dict
            result = []
            for item in self.error_list:
                if not item:
                    result.append(item)
                else:
                    result.append(item.unpack_errors())
            return result
        elif self.error_dict:
            result = {}
            for name, item in self.error_dict.items():
                if isinstance(item, (str, unicode)):
                    result[name] = item
                else:
                    result[name] = item.unpack_errors()
            return result
        else:
            return self.msg

############################################################
## Base Classes
############################################################

class Validator(declarative.Declarative):

    """
    The base class of most validators.  See `IValidator` for more, and
    `FancyValidator` for the more common (and more featureful) class.
    """

    _messages = {}
    if_missing = NoDefault
    repeating = False
    compound = False

    __singletonmethods__ = ('to_python', 'from_python')

    def __classinit__(cls, new_attrs):
        if new_attrs.has_key('messages'):
            cls._messages = cls._messages.copy()
            cls._messages.update(cls.messages)
            del cls.messages

    def __init__(self, *args, **kw):
        if kw.has_key('messages'):
            self._messages = self._messages.copy()
            self._messages.update(kw['messages'])
            del kw['messages']
        declarative.Declarative.__init__(self, *args, **kw)

    def to_python(self, value, state=None):
        return value

    def from_python(self, value, state=None):
        return value

    def message(self, msgName, state, **kw):
        try:
            return self._messages[msgName] % kw
        except KeyError:
            raise KeyError(
                "Key not found for %r=%r %% %r (from: %s)"
                % (msgName, self._messages.get(msgName), kw,
                   ', '.join(self._messages.keys())))

class _Identity(Validator):
    def __repr__(self):
        return 'validators.Identity'
Identity = _Identity()

class FancyValidator(Validator):

    """
    FancyValidator is the (abstract) superclass for various validators
    and converters.  A subclass can validate, convert, or do both.
    There is no formal distinction made here.

    Validators have two important external methods:
    * .to_python(value, state):
      Attempts to convert the value.  If there is a problem, or the
      value is not valid, an Invalid exception is raised.  The
      argument for this exception is the (potentially HTML-formatted)
      error message to give the user.
    * .from_python(value, state):
      Reverses to_python.

    There are five important methods for subclasses to override,
    however none of these *have* to be overridden, only the ones that
    are appropriate for the validator:
    * __init__():
      if the `declarative.Declarative` model doesn't work for this.
    * .validate_python(value, state):
      This should raise an error if necessary.  The value is a Python
      object, either the result of to_python, or the input to
      from_python.
    * .validate_other(value, state):
      Validates the source, before to_python, or after from_python.
      It's more common to use `.validate_python()` however.
    * ._to_python(value, state):
      This returns the converted value, or raises an Invalid
      exception if there is an error.  The argument to this exception
      should be the error message.
    * ._from_python(value, state):
      Should undo .to_python() in some reasonable way, returning
      a string.

    Validators should have no internal state besides the
    values given at instantiation.  They should be reusable and
    reentrant.

    All subclasses can take the arguments/instance variables:

    * if_empty:
      If set, then this value will be returned if the input evaluates
      to false (empty list, empty string, None, etc), but not the 0 or
      False objects.  This only applies to ``.to_python()``.

    * not_empty:
      If true, then if an empty value is given raise an error.
      (Both with ``.to_python()`` and also ``.from_python()``
      if ``.validate_python`` is true).

    * if_invalid:
      If set, then when this validator would raise Invalid during
      ``.to_python()``, instead return this value.

    * if_invalid_python:

      If set, when the Python value (converted with
      ``.from_python()``) is invalid, this value will be returned.

    * validate_python:
      If False (default True), then ``.validate_python()`` and
      ``.validate_other()`` will not be called when
      ``.from_python()`` is used.
    """

    if_invalid = NoDefault
    if_invalid_python = NoDefault
    if_empty = NoDefault
    not_empty = False
    validate_python = True

    messages = {
        'empty': "Please enter a value",
        'badType': "The input must be a string (not a %(type)s: %(value)r)",
        'noneType': "The input must be a string (not None)",
        }

    def to_python(self, value, state=None):
        try:
            if not value and value != 0:
                # False/0 are not "empty"
                if self.if_empty is not NoDefault:
                    return self.if_empty
                if self.not_empty:
                    raise Invalid(self.message('empty', state), value, state)
            vo = self.validate_other
            if vo:
                vo(value, state)
            tp = self._to_python
            if tp:
                value = tp(value, state)
            vp = self.validate_python
            if vp:
                vp(value, state)
            return value
        except Invalid:
            if self.if_invalid is NoDefault:
                raise
            else:
                return self.if_invalid

    def from_python(self, value, state=None):
        try:
            if self.validate_python:
                if (not value and value != 0
                    and self.not_empty):
                    raise Invalid(self.message('empty', state),
                                  value, state)
                vp = self.validate_python
                if vp:
                    vp(value, state)
                fp = self._from_python
                if fp:
                    value = fp(value, state)
                vo = self.validate_other
                if vo:
                    vo(value, state)
                return value
            else:
                fp = self._from_python
                if fp:
                    value = self._from_python(value, state)
                return value
        except Invalid:
            if self.if_invalid_python is NoDefault:
                raise
            else:
                return self.if_invalid_python

    validate_python = None
    validate_other = None
    _to_python = None
    _from_python = None

<commit_msg>Whitespace<commit_after>import declarative

__all__ = ['NoDefault', 'Invalid', 'Validator', 'Identity',
           'FancyValidator', 'is_validator']

class NoDefault:
    pass

def is_validator(obj):
    return (isinstance(obj, Validator) or
            (isinstance(obj, type) and
             issubclass(obj, Validator)))

class Invalid(Exception):

    """
    This is raised in response to invalid input.  It has several
    public attributes:

    msg:
        The message, *without* values substituted.  For instance, if
        you want HTML quoting of values, you can apply that.
    substituteArgs:
        The arguments (a dictionary) to go with `msg`.
    str(self):
        The message describing the error, with values substituted.
    value:
        The offending (invalid) value.
    state:
        The state that went with this validator.  This is an
        application-specific object.
    error_list:
        If this was a compound validator that takes a repeating value,
        and sub-validator(s) had errors, then this is a list of those
        exceptions.  The list will be the same length as the number of
        values -- valid values will have None instead of an exception.
    error_dict:
        Like `error_list`, but for dictionary compound validators.
    """

    def __init__(self, msg,
                 value, state, error_list=None, error_dict=None):
        Exception.__init__(self, msg)
        self.msg = msg
        self.value = value
        self.state = state
        self.error_list = error_list
        self.error_dict = error_dict

    def __str__(self):
        val = self.msg
        #if self.value:
        #    val += " (value: %s)" % repr(self.value)
        return val

    def unpack_errors(self):
        """
        Returns the error as a simple data structure -- lists,
        dictionaries, and strings.
        """
        if self.error_list:
            assert not self.error_dict
            result = []
            for item in self.error_list:
                if not item:
                    result.append(item)
                else:
                    result.append(item.unpack_errors())
            return result
        elif self.error_dict:
            result = {}
            for name, item in self.error_dict.items():
                if isinstance(item, (str, unicode)):
                    result[name] = item
                else:
                    result[name] = item.unpack_errors()
            return result
        else:
            return self.msg

############################################################
## Base Classes
############################################################

class Validator(declarative.Declarative):

    """
    The base class of most validators.  See `IValidator` for more, and
    `FancyValidator` for the more common (and more featureful) class.
    """

    _messages = {}
    if_missing = NoDefault
    repeating = False
    compound = False

    __singletonmethods__ = ('to_python', 'from_python')

    def __classinit__(cls, new_attrs):
        if new_attrs.has_key('messages'):
            cls._messages = cls._messages.copy()
            cls._messages.update(cls.messages)
            del cls.messages

    def __init__(self, *args, **kw):
        if kw.has_key('messages'):
            self._messages = self._messages.copy()
            self._messages.update(kw['messages'])
            del kw['messages']
        declarative.Declarative.__init__(self, *args, **kw)

    def to_python(self, value, state=None):
        return value

    def from_python(self, value, state=None):
        return value

    def message(self, msgName, state, **kw):
        try:
            return self._messages[msgName] % kw
        except KeyError:
            raise KeyError(
                "Key not found for %r=%r %% %r (from: %s)"
                % (msgName, self._messages.get(msgName), kw,
                   ', '.join(self._messages.keys())))

class _Identity(Validator):
    def __repr__(self):
        return 'validators.Identity'
Identity = _Identity()

class FancyValidator(Validator):

    """
    FancyValidator is the (abstract) superclass for various validators
    and converters.  A subclass can validate, convert, or do both.
    There is no formal distinction made here.

    Validators have two important external methods:
    * .to_python(value, state):
      Attempts to convert the value.  If there is a problem, or the
      value is not valid, an Invalid exception is raised.  The
      argument for this exception is the (potentially HTML-formatted)
      error message to give the user.
    * .from_python(value, state):
      Reverses to_python.

    There are five important methods for subclasses to override,
    however none of these *have* to be overridden, only the ones that
    are appropriate for the validator:
    * __init__():
      if the `declarative.Declarative` model doesn't work for this.
    * .validate_python(value, state):
      This should raise an error if necessary.  The value is a Python
      object, either the result of to_python, or the input to
      from_python.
    * .validate_other(value, state):
      Validates the source, before to_python, or after from_python.
      It's more common to use `.validate_python()` however.
    * ._to_python(value, state):
      This returns the converted value, or raises an Invalid
      exception if there is an error.  The argument to this exception
      should be the error message.
    * ._from_python(value, state):
      Should undo .to_python() in some reasonable way, returning
      a string.

    Validators should have no internal state besides the
    values given at instantiation.  They should be reusable and
    reentrant.

    All subclasses can take the arguments/instance variables:

    * if_empty:
      If set, then this value will be returned if the input evaluates
      to false (empty list, empty string, None, etc), but not the 0 or
      False objects.  This only applies to ``.to_python()``.

    * not_empty:
      If true, then if an empty value is given raise an error.
      (Both with ``.to_python()`` and also ``.from_python()``
      if ``.validate_python`` is true).

    * if_invalid:
      If set, then when this validator would raise Invalid during
      ``.to_python()``, instead return this value.

    * if_invalid_python:
      If set, when the Python value (converted with
      ``.from_python()``) is invalid, this value will be returned.

    * validate_python:
      If False (default True), then ``.validate_python()`` and
      ``.validate_other()`` will not be called when
      ``.from_python()`` is used.
    """

    if_invalid = NoDefault
    if_invalid_python = NoDefault
    if_empty = NoDefault
    not_empty = False
    validate_python = True

    messages = {
        'empty': "Please enter a value",
        'badType': "The input must be a string (not a %(type)s: %(value)r)",
        'noneType': "The input must be a string (not None)",
        }

    def to_python(self, value, state=None):
        try:
            if not value and value != 0:
                # False/0 are not "empty"
                if self.if_empty is not NoDefault:
                    return self.if_empty
                if self.not_empty:
                    raise Invalid(self.message('empty', state), value, state)
            vo = self.validate_other
            if vo:
                vo(value, state)
            tp = self._to_python
            if tp:
                value = tp(value, state)
            vp = self.validate_python
            if vp:
                vp(value, state)
            return value
        except Invalid:
            if self.if_invalid is NoDefault:
                raise
            else:
                return self.if_invalid

    def from_python(self, value, state=None):
        try:
            if self.validate_python:
                if (not value and value != 0
                    and self.not_empty):
                    raise Invalid(self.message('empty', state),
                                  value, state)
                vp = self.validate_python
                if vp:
                    vp(value, state)
                fp = self._from_python
                if fp:
                    value = fp(value, state)
                vo = self.validate_other
                if vo:
                    vo(value, state)
                return value
            else:
                fp = self._from_python
                if fp:
                    value = self._from_python(value, state)
                return value
        except Invalid:
            if self.if_invalid_python is NoDefault:
                raise
            else:
                return self.if_invalid_python

    validate_python = None
    validate_other = None
    _to_python = None
    _from_python = None

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# Create your views here.

from django.conf import settings
from django.contrib.auth import logout
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse_lazy
from django.shortcuts import redirect, render
from django.template.loader import render_to_string

# from core.context_processors import categories_context, subdomains_context
from core.mixins import CategoryMixin, SubdomainContextMixin, MultipleFormsView
# from core.models import Subdomain
from core.views import (RyndaCreateView, RyndaDetailView, RyndaFormView,
                        RyndaListView)
# from feed.models import FeedItem
from geozones.forms import LocationForm
from geozones.models import Region, Location
from message.forms import RequestForm
from message.models import Message, MessageIndexFilter, MessageSideFilter

MAX_PANE_MESSAGES = 5

def generate_message_pane(pane_label, context_messages, link_to_continue=None):
    """ Генерация виджета панели сообщений на главной странице """
    has_more = len(context_messages) > MAX_PANE_MESSAGES
    context = {
        "messages": context_messages[:MAX_PANE_MESSAGES],
        "has_more": has_more,
        "helper_title": pane_label,
        "link_to_continue": link_to_continue,
    }
    return render_to_string("widgets/message_pane.html", context)

def list(request, slug='all'):
    """ Главная страница """
    last_requests = generate_message_pane(
        "Просьбы о помощи",
        Message.objects.active().type_is(
            Message.REQUEST).values(
                'id', 'title', 'date_add')[:MAX_PANE_MESSAGES + 1],
        "/message/pomogite")
    last_offers = generate_message_pane(
        "Предложения помощи",
        Message.objects.active().type_is(
            Message.OFFER).values(
                'id', 'title', 'date_add')[:MAX_PANE_MESSAGES + 1],
        "/message/pomogu")
    last_completed = generate_message_pane(
        "Помощь оказана",
        Message.objects.type_is(
            Message.REQUEST).closed().values(
                'id', 'title', 'date_add')[:MAX_PANE_MESSAGES + 1],
        "/message/pomogli")
    return render(
        request,
        'index.html',
        {
            'regions': Region.objects.filter(id__gt=0),
            #'categories': cat_tree,
            'filter': MessageIndexFilter(
                request.GET, Message.objects.active().list().all()),
            'requests': last_requests,
            'offers': last_offers,
            'completed': last_completed,
            # 'info': last_info,
            # 'news': last_feeds,
        },)
        # context_instance=RequestContext(
            # request,
            # processors=[subdomains_context, categories_context]))

def logout_view(request):
    logout(request)
    return redirect('/')

class CreateRequest(CategoryMixin, RyndaFormView):
    template_name = "request_form.html"
    model = Message
    form_class = RequestForm
    success_url = reverse_lazy('message_list')

    def get_initial(self):
        initial = {}
        if self.request.user.is_authenticated():
            initial['contact_first_name'] = self.request.user.first_name
            initial['contact_last_name'] = self.request.user.last_name
            initial['contact_mail'] = self.request.user.email
            initial['contact_phone'] = self.request.user.profile.phones
        return initial

    def form_valid(self, form):
        instance = form.save(commit=False)
        if self.request.user.is_authenticated():
            instance.user = self.request.user
        else:
            instance.user = User.objects.get(pk=settings.ANONYMOUS_USER_ID)
        data = {
            'name': self.request.POST['address'],
            'coordinates': self.request.POST['coordinates'], }
        loc_form = LocationForm(data=data)
        location = loc_form.save()
        # location.save()
        instance.linked_location = location
        instance.save()
        return redirect(self.success_url)

class CreateRequestM(MultipleFormsView):
    template_name = "request_form_simple.html"
    model = Message
    form_classes = {
        'message': RequestForm,
        'location': LocationForm,
    }
    success_url = reverse_lazy('message_list')

    def get_initial(self):
        initial = {}
        if self.request.user.is_authenticated():
            initial['contact_first_name'] = self.request.user.first_name
            initial['contact_last_name'] = self.request.user.last_name
            initial['contact_mail'] = self.request.user.email
            initial['contact_phone'] = self.request.user.profile.phones
        return initial

    def forms_valid(self, forms):
        location = forms['location'].save(commit=False)
        location.region_id = 64
        location.save()
        message = forms['message'].save(commit=False)
        message.linked_location = location
        if self.request.user.is_authenticated():
            message.user = self.request.user
        else:
            message.user = User.objects.get(pk=settings.ANONYMOUS_USER_ID)
        message.save()
        return super(CreateRequestM, self).forms_valid(forms)

class CreateOffer(CategoryMixin, RyndaCreateView):
    template_name = "offer_form.html"
    model = Message
    form_class = RequestForm

    def form_valid(self, form):
        instance = form.save(commit=False)
        if self.request.user.is_authenticated():
            instance.user = self.request.user
        else:
            instance.user = User.objects.get(pk=settings.ANONYMOUS_USER_ID)
        data = {
            'name': self.request.POST['address'],
            'coordinates': self.request.POST['coordinates'], }
        loc_form = LocationForm(data=data)
        location = loc_form.save()
        # location.save()
        instance.linked_location = location
        instance.save()
        return redirect(self.success_url)

class MessageView(RyndaDetailView):
    model = Message
    template_name = "message_details.html"
    context_object_name = "message"

    def get_context_data(self, **kwargs):
        context = super(RyndaDetailView, self).get_context_data(**kwargs)
        if self.allow_external():
            external = {'VK_APP_ID':  settings.VK_APP_ID, }
            context['external'] = external
        return context

class MessageList(RyndaListView):
    queryset = Message.objects.active().select_related().all().prefetch_related('category')
    paginate_by = 10
    template_name = 'all_messages.html'
    context_object_name = 'messages'
    paginator_url = '/message/page/'
    list_title_short = 'Список сообщений'

    def get_context_data(self, **kwargs):
        context = super(MessageList, self).get_context_data(**kwargs)
        context['filter'] = MessageSideFilter(self.request.GET, self.queryset)
        count = self.queryset.count()
        context['count'] = count
        return context

    def get_queryset(self):
        return MessageSideFilter(self.request.GET, self.queryset)
<commit_msg>Оптимизация message/views.py<commit_after># -*- coding: utf-8 -*-

from django.conf import settings
from django.contrib.auth import logout
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse_lazy
from django.shortcuts import redirect, render
from django.template.loader import render_to_string

from core.mixins import CategoryMixin, MultipleFormsView
from core.views import (RyndaCreateView, RyndaDetailView, RyndaFormView,
                        RyndaListView)
from geozones.forms import LocationForm
from geozones.models import Region
from message.forms import RequestForm, OfferForm
from message.models import Message, MessageIndexFilter, MessageSideFilter

MAX_PANE_MESSAGES = 5

def generate_message_pane(pane_label, context_messages, link_to_continue=None):
    """ Генерация виджета панели сообщений на главной странице """
    has_more = len(context_messages) > MAX_PANE_MESSAGES
    context = {
        "messages": context_messages[:MAX_PANE_MESSAGES],
        "has_more": has_more,
        "helper_title": pane_label,
        "link_to_continue": link_to_continue,
    }
    return render_to_string("widgets/message_pane.html", context)

def list(request, slug='all'):
    """ Главная страница """
    last_requests = generate_message_pane(
        "Просьбы о помощи",
        Message.objects.active().type_is(
            Message.REQUEST).values(
                'id', 'title', 'date_add')[:MAX_PANE_MESSAGES + 1],
        "/message/pomogite")
    last_offers = generate_message_pane(
        "Предложения помощи",
        Message.objects.active().type_is(
            Message.OFFER).values(
                'id', 'title', 'date_add')[:MAX_PANE_MESSAGES + 1],
        "/message/pomogu")
    last_completed = generate_message_pane(
        "Помощь оказана",
        Message.objects.type_is(
            Message.REQUEST).closed().values(
                'id', 'title', 'date_add')[:MAX_PANE_MESSAGES + 1],
        "/message/pomogli")
    return render(
        request,
        'index.html',
        {
            'regions': Region.objects.filter(id__gt=0),
            #'categories': cat_tree,
            'filter': MessageIndexFilter(
                request.GET, Message.objects.active().list().all()),
            'requests': last_requests,
            'offers': last_offers,
            'completed': last_completed,
            # 'info': last_info,
            # 'news': last_feeds,
        },)
        # context_instance=RequestContext(
            # request,
            # processors=[subdomains_context, categories_context]))

def logout_view(request):
    logout(request)
    return redirect('/')

class SaveGeoDataMixin():
    """ Сохранение сообщения и геоточки """
    def form_valid(self, form):
        instance = form.save(commit=False)
        if self.request.user.is_authenticated():
            instance.user = self.request.user
        else:
            instance.user = User.objects.get(pk=settings.ANONYMOUS_USER_ID)
        data = {
            'name': self.request.POST['address'],
            'coordinates': self.request.POST['coordinates'], }
        loc_form = LocationForm(data=data)
        location = loc_form.save()
        # location.save()
        instance.linked_location = location
        instance.save()
        return redirect(self.success_url)

class CreateRequest(CategoryMixin, RyndaFormView):
    template_name = "request_form.html"
    model = Message
    form_class = RequestForm
    success_url = reverse_lazy('message_list')

    def get_initial(self):
        initial = {}
        if self.request.user.is_authenticated():
            initial['contact_first_name'] = self.request.user.first_name
            initial['contact_last_name'] = self.request.user.last_name
            initial['contact_mail'] = self.request.user.email
            initial['contact_phone'] = self.request.user.profile.phones
        return initial

class CreateRequestM(MultipleFormsView):
    template_name = "request_form_simple.html"
    model = Message
    form_classes = {
        'message': RequestForm,
        'location': LocationForm,
    }
    success_url = reverse_lazy('message_list')

    def get_initial(self):
        initial = {}
        if self.request.user.is_authenticated():
            initial['contact_first_name'] = self.request.user.first_name
            initial['contact_last_name'] = self.request.user.last_name
            initial['contact_mail'] = self.request.user.email
            initial['contact_phone'] = self.request.user.profile.phones
        return initial

    def forms_valid(self, forms):
        location = forms['location'].save(commit=False)
        location.region_id = 64
        location.save()
        message = forms['message'].save(commit=False)
        message.linked_location = location
        if self.request.user.is_authenticated():
            message.user = self.request.user
        else:
            message.user = User.objects.get(pk=settings.ANONYMOUS_USER_ID)
        message.save()
        return super(CreateRequestM, self).forms_valid(forms)

class CreateOffer(CategoryMixin, RyndaCreateView):
    template_name = "offer_form.html"
    model = Message
    form_class = OfferForm

    def form_valid(self, form):
        instance = form.save(commit=False)
        if self.request.user.is_authenticated():
            instance.user = self.request.user
        else:
            instance.user = User.objects.get(pk=settings.ANONYMOUS_USER_ID)
        data = {
            'name': self.request.POST['address'],
            'coordinates': self.request.POST['coordinates'], }
        loc_form = LocationForm(data=data)
        location = loc_form.save()
        # location.save()
        instance.linked_location = location
        instance.save()
        return redirect(self.success_url)

class MessageView(RyndaDetailView):
    model = Message
    template_name = "message_details.html"
    context_object_name = "message"

    def get_context_data(self, **kwargs):
        context = super(RyndaDetailView, self).get_context_data(**kwargs)
        if self.allow_external():
            external = {'VK_APP_ID':  settings.VK_APP_ID, }
            context['external'] = external
        return context

class MessageList(RyndaListView):
    queryset = Message.objects.active().select_related().all().prefetch_related('category')
    paginate_by = 10
    template_name = 'all_messages.html'
    context_object_name = 'messages'
    paginator_url = '/message/page/'
    list_title_short = 'Список сообщений'

    def get_context_data(self, **kwargs):
        context = super(MessageList, self).get_context_data(**kwargs)
        context['filter'] = MessageSideFilter(self.request.GET, self.queryset)
        count = self.queryset.count()
        context['count'] = count
        return context

    def get_queryset(self):
        return MessageSideFilter(self.request.GET, self.queryset)
<|endoftext|>


<commit_before>from scitbx import matrix
import sys
import math

# read in XPARM.XDS - get the real-space cell vectors, distance, rotation
# axis and so on...

def read_xparm(xparm_file):
    '''Parse the XPARM file to a dictionary.'''

    records = open(xparm_file, 'r').readlines()

    data = map(float, open(xparm_file, 'r').read().split())

    if not len(data) == 42:
        raise RuntimeError, 'error parsing %s' % xparm_file

    starting_frame = int(data[0])
    phi_start = data[1]
    phi_width = data[2]
    axis = data[3:6]

    wavelength = data[6]
    beam = data[7:10]

    nx = int(data[10])
    ny = int(data[11])
    px = data[12]
    py = data[13]

    distance = data[14]
    ox = data[15]
    oy = data[16]

    x = data[17:20]
    y = data[20:23]
    normal = data[23:26]

    spacegroup = int(data[26])
    cell = data[27:33]

    a = data[33:36]
    b = data[36:39]
    c = data[39:42]

    results = {
        'starting_frame':starting_frame,
        'phi_start':phi_start,
        'phi_width':phi_width,
        'axis':axis,
        'wavelength':wavelength,
        'beam':beam,
        'nx':nx,
        'ny':ny,
        'px':px,
        'py':py,
        'distance':distance,
        'ox':ox,
        'oy':oy,
        'x':x,
        'y':y,
        'normal':normal,
        'spacegroup':spacegroup,
        'cell':cell,
        'a':a,
        'b':b,
        'c':c
        }

    return results

def keep():

    print '%6d%12.6f%12.6f%12.6f%12.6f%12.6f' % (starting_frame, phi_start,
                                                 phi_width,
                                                 axis[0], axis[1], axis[2])
    print '%15.6f%15.6f%15.6f%15.6f' % (wavelength, beam[0], beam[1], beam[2])
    print '%10d%10d%10.5f%10.5f' % (nx, ny, px, py)
    print '%15.6f%15.6f%15.6f' % (distance, ox, oy)
    print '%15.6f%15.6f%15.6f' % tuple(x)
    print '%15.6f%15.6f%15.6f' % tuple(y)
    print '%15.6f%15.6f%15.6f' % tuple(normal)
    print '%10d%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f' % \
          (spacegroup, cell[0], cell[1], cell[2], cell[3], cell[4], cell[5])
    print '%15.6f%15.6f%15.6f' % tuple(a)
    print '%15.6f%15.6f%15.6f' % tuple(b)
    print '%15.6f%15.6f%15.6f' % tuple(c)

if __name__ == '__main__':
    results = read_xparm('XPARM.XDS')

    A = results['a']
    B = results['b']
    C = results['c']

    cell = results['cell']
    wavelength = results['wavelength']
    distance = results['distance']
    beam = results['beam']

    nx = results['nx']
    ny = results['ny']
    px = results['px']
    py = results['py']
    ox = results['ox']
    oy = results['oy']

    normal = results['normal']

    m = matrix.sqr(A + B + C)

    mi = m.inverse()

    A = matrix.col(A)
    B = matrix.col(B)
    C = matrix.col(C)

    axis = matrix.col(results['axis'])

    a = math.sqrt(A.dot())
    b = math.sqrt(B.dot())
    c = math.sqrt(C.dot())

    dtor = 180.0 / math.pi

    alpha = dtor * B.angle(C)
    beta = dtor * C.angle(A)
    gamma = dtor * A.angle(B)

    print '%8.3f%8.3f%8.3f%8.3f%8.3f%8.3f' % tuple(cell)
    print '%8.3f%8.3f%8.3f%8.3f%8.3f%8.3f' % (a, b, c, alpha, beta, gamma)

    phi_start = results['phi_start']
    phi_width = results['phi_width']
    start = results['starting_frame'] - 1

    # compute where the direct beam strikes the detector - this gives the
    # primary origin for the calculation of the reciprocal space
    # vectors - at this stage need the offset in pixels not mm

    N = matrix.col(normal)
    D = distance * N
    S = matrix.col(beam)

    Sd = (wavelength * distance / (wavelength * S.dot(N))) * S
    d = math.sqrt(Sd.dot())

    off = Sd - D

    bx = ox + off.elems[0] / px
    by = oy + off.elems[1] / py

    count = 0

    for record in open('SPOT.XDS', 'r').readlines():
        l = record.split()

        if not l:
            continue

        X, Y, i = map(float, l[:3])
        h, k, l = map(int, l[-3:])

        if h == 0 and k == 0 and l == 0:
            continue

        count += 1

        if count > 10:
            break

        phi = (i - start) * phi_width + phi_start

        X = px * (X - bx)
        Y = py * (Y - by)

        # first convert detector position to reciprocal space position

        scale = wavelength * math.sqrt(X * X + Y * Y + d * d)

        x = X / scale
        y = Y / scale
        z = d / scale

        Sp = matrix.col([x, y, z]) - S

        hkl = m * Sp.rotate(axis, - 1 * phi / dtor).elems

        print '%4d %4d %4d => %8.4f %8.4f %8.4f' % \
              (h, k, l, hkl[0], hkl[1], hkl[2])

<commit_msg>Have the calculations working right now, I think - correctly using a vector description rather than the approximation Rossmann & Co used in DPS.<commit_after>from scitbx import matrix
import sys
import math

# read in XPARM.XDS - get the real-space cell vectors, distance, rotation
# axis and so on...

def read_xparm(xparm_file):
    '''Parse the XPARM file to a dictionary.'''

    records = open(xparm_file, 'r').readlines()

    data = map(float, open(xparm_file, 'r').read().split())

    if not len(data) == 42:
        raise RuntimeError, 'error parsing %s' % xparm_file

    starting_frame = int(data[0])
    phi_start = data[1]
    phi_width = data[2]
    axis = data[3:6]

    wavelength = data[6]
    beam = data[7:10]

    nx = int(data[10])
    ny = int(data[11])
    px = data[12]
    py = data[13]

    distance = data[14]
    ox = data[15]
    oy = data[16]

    x = data[17:20]
    y = data[20:23]
    normal = data[23:26]

    spacegroup = int(data[26])
    cell = data[27:33]

    a = data[33:36]
    b = data[36:39]
    c = data[39:42]

    results = {
        'starting_frame':starting_frame,
        'phi_start':phi_start,
        'phi_width':phi_width,
        'axis':axis,
        'wavelength':wavelength,
        'beam':beam,
        'nx':nx,
        'ny':ny,
        'px':px,
        'py':py,
        'distance':distance,
        'ox':ox,
        'oy':oy,
        'x':x,
        'y':y,
        'normal':normal,
        'spacegroup':spacegroup,
        'cell':cell,
        'a':a,
        'b':b,
        'c':c
        }

    return results

def keep():

    print '%6d%12.6f%12.6f%12.6f%12.6f%12.6f' % (starting_frame, phi_start,
                                                 phi_width,
                                                 axis[0], axis[1], axis[2])
    print '%15.6f%15.6f%15.6f%15.6f' % (wavelength, beam[0], beam[1], beam[2])
    print '%10d%10d%10.5f%10.5f' % (nx, ny, px, py)
    print '%15.6f%15.6f%15.6f' % (distance, ox, oy)
    print '%15.6f%15.6f%15.6f' % tuple(x)
    print '%15.6f%15.6f%15.6f' % tuple(y)
    print '%15.6f%15.6f%15.6f' % tuple(normal)
    print '%10d%10.3f%10.3f%10.3f%10.3f%10.3f%10.3f' % \
          (spacegroup, cell[0], cell[1], cell[2], cell[3], cell[4], cell[5])
    print '%15.6f%15.6f%15.6f' % tuple(a)
    print '%15.6f%15.6f%15.6f' % tuple(b)
    print '%15.6f%15.6f%15.6f' % tuple(c)

if __name__ == '__main__':
    results = read_xparm('XPARM.XDS')

    A = results['a']
    B = results['b']
    C = results['c']

    cell = results['cell']
    wavelength = results['wavelength']
    distance = results['distance']
    beam = results['beam']

    nx = results['nx']
    ny = results['ny']
    px = results['px']
    py = results['py']
    ox = results['ox']
    oy = results['oy']

    normal = results['normal']

    m = matrix.sqr(A + B + C)

    mi = m.inverse()

    A = matrix.col(A)
    B = matrix.col(B)
    C = matrix.col(C)

    axis = matrix.col(results['axis'])

    a = math.sqrt(A.dot())
    b = math.sqrt(B.dot())
    c = math.sqrt(C.dot())

    dtor = 180.0 / math.pi

    alpha = dtor * B.angle(C)
    beta = dtor * C.angle(A)
    gamma = dtor * A.angle(B)

    print '%8.3f%8.3f%8.3f%8.3f%8.3f%8.3f' % tuple(cell)
    print '%8.3f%8.3f%8.3f%8.3f%8.3f%8.3f' % (a, b, c, alpha, beta, gamma)

    phi_start = results['phi_start']
    phi_width = results['phi_width']
    start = results['starting_frame'] - 1

    # compute where the direct beam strikes the detector - this gives the
    # primary origin for the calculation of the reciprocal space
    # vectors - at this stage need the offset in pixels not mm

    N = matrix.col(normal)
    D = distance * N
    S = matrix.col(beam)

    Sd = (wavelength * distance / (wavelength * S.dot(N))) * S
    d = math.sqrt(Sd.dot())

    off = Sd - D

    bx = ox + off.elems[0] / px
    by = oy + off.elems[1] / py

    for record in open('SPOT.XDS', 'r').readlines():
        l = record.split()

        if not l:
            continue

        X, Y, i = map(float, l[:3])
        h, k, l = map(int, l[-3:])

        phi = (i - start) * phi_width + phi_start

        X = px * (X - bx)
        Y = py * (Y - by)

        # first convert detector position to reciprocal space position

        P = matrix.col([X, Y, 0]) + Sd

        scale = wavelength * math.sqrt(P.dot())

        x = P.elems[0] / scale
        y = P.elems[1] / scale
        z = P.elems[2] / scale

        Sp = matrix.col([x, y, z]) - S

        hkl = m * Sp.rotate(axis, - 1 * phi / dtor).elems

        print '%4d %4d %4d => %8.4f %8.4f %8.4f' % \
              (h, k, l, hkl[0], hkl[1], hkl[2])

<|endoftext|>


<commit_before>#!/usr/bin/python
# -*- coding: utf-8 -*-
import os.path

from PIL import Image

from get_latest_json import *
from init_blinkt import *
from init_unicorn import *

# read the config file
config = get_config()

THREADING_TIMER = config['THREADING_TIMER']

folder_path = '/home/pi/WeatherPi/Modules/Animations/'

version_path = config['UNICORN_VERSION'] + '/'

icon_extension = '.' + 'png'

img_file = folder_path + version_path + 'error' + icon_extension

width, height = unicorn.get_shape()

def get_icon():
    # known conditions: clear-day, clear-night, partly-cloudy-day, partly-cloudy-night, wind, cloudy, rain, snow, fog

    json_data = get_latest_json()

    icon = json_data['currently']['icon']

    log_string('Icon to show on Unicorn_HAT: {}'.format(icon))

    return icon

def get_icon_path():
    global img_file

    icon = get_icon()

    icon_path = folder_path + version_path + icon + icon_extension

    log_string('The icon path should be: {}. Checking it...'.format(icon_path))

    # check if file and path are valid

    if os.path.isfile(icon_path):

        log_string('The File: {} is valid and present!'.format(icon_path))

        log_string('Updating Unicorn with new weather condition icon: {}.'.format(icon))

        # set new icon_path

        img_file = icon_path

        blink('red')

    else:

        log_string('Error - there is no icon for this weather condition. Please check.')

        log_string('Updating Unicorn icon to error screen')

        # set new icon_path

        icon_path = folder_path + version_path + 'error' + icon_extension

        img_file = icon_path

        blink('red')

def update_unicorn():
    unicorn.clear()

    global img_file

    log_string('Start Unicorn image loop')

    while img_file:
        img = Image.open(img_file)

        draw_unicorn(img)

def draw_unicorn(image):
    for o_x in range(int(image.size[0] / width)):

        for o_y in range(int(image.size[1] / height)):

            valid = False

            for x in range(width):

                for y in range(height):
                    pixel = image.getpixel(((o_x * width) + y, (o_y * height) + x))
                    # print(pixel)
                    r, g, b = int(pixel[0]), int(pixel[1]), int(pixel[2])
                    if r or g or b:
                        valid = True
                    unicorn.set_pixel(x, y, r, g, b)

            if valid:
                unicorn.show()
                time.sleep(0.25)

def test_unicorn():
    print('Testing all images in folder {}'.format(folder_path + version_path))

    for image in os.listdir(folder_path + version_path):

        if image.endswith(icon_extension):

            print('Testing image: {}'.format(folder_path + version_path + image))

            img = Image.open(folder_path + version_path + image)

            draw_unicorn(img)

        else:

            print('Not using this file, not an image: {}'.format(file))

    unicorn.clear()
    unicorn.show()

def test_unicornhd():
    test_file = folder_path + version_path + 'clear-day.png'

    img = Image.open(test_file)

    try:
        while True:
            for o_x in range(int(img.size[0] / width)):
                for o_y in range(int(img.size[1] / height)):

                    valid = False
                    for x in range(width):
                        for y in range(height):
                            pixel = img.getpixel(((o_x * width) + y, (o_y * height) + x))
                            r, g, b = int(pixel[0]), int(pixel[1]), int(pixel[2])
                            if r or g or b:
                                valid = True
                            unicorn.set_pixel(x, y, r, g, b)
                    if valid:
                        unicorn.show()
                        time.sleep(0.5)
    except KeyboardInterrupt:
        unicorn.off()

if __name__ == '__main__':

    try:

        unicorn_init()
        test_unicorn()
        # get_icon_path()
        # update_unicorn()

    except KeyboardInterrupt:

        unicorn.clear()
        unicorn.show()
<commit_msg>- some improvements<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-
import os.path

from PIL import Image

from get_latest_json import *
from init_blinkt import *
from init_unicorn import *

# read the config file
config = get_config()

folder_path = '/home/pi/WeatherPi/Modules/Animations/'

version_path = config['UNICORN_VERSION'] + '/'

icon_extension = '.' + 'png'

img_file = folder_path + version_path + 'error' + icon_extension

width, height = unicorn.get_shape()

def get_icon():
    # known conditions: clear-day, clear-night, partly-cloudy-day, partly-cloudy-night, wind, cloudy, rain, snow, fog

    json_data = get_latest_json()

    icon = json_data['currently']['icon']

    log_string('Icon to show on Unicorn_HAT: {}'.format(icon))

    return icon

def get_icon_path():
    global img_file

    icon = get_icon()

    icon_path = folder_path + version_path + icon + icon_extension

    log_string('The icon path should be: {}. Checking it...'.format(icon_path))

    # check if file and path are valid

    if os.path.isfile(icon_path):

        log_string('The File: {} is valid and present!'.format(icon_path))

        log_string('Updating Unicorn with new weather condition icon: {}.'.format(icon))

        # set new icon_path

        img_file = icon_path

        blink('red')

    else:

        log_string('Error - there is no icon for this weather condition. Please check.')

        log_string('Updating Unicorn icon to error screen')

        # set new icon_path

        icon_path = folder_path + version_path + 'error' + icon_extension

        img_file = icon_path

        blink('red')

def update_unicorn():
    unicorn.clear()

    global img_file

    log_string('Start Unicorn image loop')

    while img_file:

        img = Image.open(img_file)

        draw_unicorn(img)

    else:

        log_string('Something went wrong while picing up the img')
        return

def draw_unicorn(image):
    # this is the original pimoroni function for drawing sprites

    for o_x in range(int(image.size[0] / width)):

        for o_y in range(int(image.size[1] / height)):

            valid = False

            for x in range(width):

                for y in range(height):
                    pixel = image.getpixel(((o_x * width) + y, (o_y * height) + x))
                    # print(pixel)
                    r, g, b = int(pixel[0]), int(pixel[1]), int(pixel[2])
                    if r or g or b:
                        valid = True
                    unicorn.set_pixel(x, y, r, g, b)

            if valid:
                unicorn.show()
                time.sleep(0.25)

def test_unicorn():
    print('Testing all images in folder {}'.format(folder_path + version_path))

    for image in os.listdir(folder_path + version_path):

        if image.endswith(icon_extension):

            print('Testing image: {}'.format(folder_path + version_path + image))

            img = Image.open(folder_path + version_path + image)

            draw_unicorn(img)

        else:

            print('Not using this file, not an image: {}'.format(file))

    unicorn.clear()
    unicorn.show()

if __name__ == '__main__':

    try:

        unicorn_init()
        test_unicorn()
        get_icon_path()
        update_unicorn()

    except KeyboardInterrupt:

        unicorn.clear()
        unicorn.show()
<|endoftext|>


<commit_before>"""All blast commands used by aTRAM."""

import os
import re
import sys
import glob
import json
import lib.log as log

# Try to get the sequence name and which end it is from the fasta header
PARSE_HEADER = re.compile(r'^ [>@] \s* ( .* ) ( [\s/._] [12] ) \s* $',
                          re.VERBOSE)

# Parse blast hits file
PARSE_RESULTS = re.compile(r'^ ( .* ) ( [\s\/_] [12] )', re.VERBOSE)

def create_db(temp_dir, fasta_file, blast_db):
    """Create a blast DB."""

    cmd = 'makeblastdb -dbtype nucl -in {} -out {}'
    cmd = cmd.format(fasta_file, blast_db)
    log.subcommand(cmd, temp_dir)

def against_sra(args, blast_db, query, hits_file, iteration):
    """Blast the query sequences against an SRA blast DB."""

    cmd = []

    if args['protein'] and iteration == 1:
        cmd.append('tblastn')
        cmd.append('-db_gencode {}'.format(args['db_gencode']))
    else:
        cmd.append('blastn')
        cmd.append('-evalue {}'.format(args['evalue']))

    cmd.append('-outfmt 15')
    cmd.append('-max_target_seqs {}'.format(args['max_target_seqs']))
    cmd.append('-out {}'.format(hits_file))
    cmd.append('-db {}'.format(blast_db))
    cmd.append('-query {}'.format(query))

    command = ' '.join(cmd)
    log.subcommand(command, args['temp_dir'])

def against_contigs(args, blast_db, query, hits_file):
    """Blast the query sequence against the contings. The blast output
    will have the scores for later processing.
    """

    cmd = []

    if args.protein:
        cmd.append('tblastn')
        cmd.append('-db_gencode {}'.format(args.db_gencode))
    else:
        cmd.append('blastn')

    cmd.append('-db {}'.format(blast_db))
    cmd.append('-query {}'.format(query))
    cmd.append('-out {}'.format(hits_file))
    cmd.append('-outfmt 15')

    command = ' '.join(cmd)
    log.subcommand(command, args.temp_dir)

def shard_path(blast_db, shard_index):
    """Create the BLAST shard DB names."""

    file_name = '{}.{:03d}.blast'.format(blast_db, shard_index)
    return file_name

def all_shard_paths(blast_db):
    """Get all of the BLAST DB names built by the preprocessor."""

    pattern = '{}.blast_*.nhr'.format(blast_db)

    files = glob.glob(pattern)
    if not files:
        err = ('No blast shards found. Looking for "{}"\n'
               'Verify the --work-dir and --file-prefix options.').format(
                   pattern[:-4])
        sys.exit(err)

    return sorted([f[:-4] for f in files])

def output_file_name(temp_dir, shrd_path, iteration):
    """Create a file name for blast results."""

    shard_name = os.path.basename(shrd_path)
    file_name = '{}.{:02d}.results.json'.format(shard_name, iteration)

    return os.path.join(temp_dir, file_name)

def temp_db_name(temp_dir, blast_db, iteration):
    """Generate a name for the temp DB used to filter the contigs."""

    temp_name = os.path.basename(blast_db)
    file_name = '{}.{:02d}.blast'.format(temp_name, iteration)
    return os.path.join(temp_dir, file_name)

def hits(json_file):
    """Extract the blast hits from the blast json output file."""

    with open(json_file) as blast_file:
        raw = blast_file.read()
        obj = json.loads(raw)

    hits_list = []
    for raw in obj['BlastOutput2'][0]['report']['results']['search']['hits']:
        for i, desc in enumerate(raw['description']):
            hit = dict(desc)
            hit['len'] = raw['len']
            hit.update(raw['hsps'][i])
            hits_list.append(hit)

    return hits_list
<commit_msg>Fix blast DB search<commit_after>"""All blast commands used by aTRAM."""

import os
import re
import sys
import glob
import json
import lib.log as log

# Try to get the sequence name and which end it is from the fasta header
PARSE_HEADER = re.compile(r'^ [>@] \s* ( .* ) ( [\s/._] [12] ) \s* $',
                          re.VERBOSE)

# Parse blast hits file
PARSE_RESULTS = re.compile(r'^ ( .* ) ( [\s\/_] [12] )', re.VERBOSE)

def create_db(temp_dir, fasta_file, blast_db):
    """Create a blast DB."""

    cmd = 'makeblastdb -dbtype nucl -in {} -out {}'
    cmd = cmd.format(fasta_file, blast_db)
    log.subcommand(cmd, temp_dir)

def against_sra(args, blast_db, query, hits_file, iteration):
    """Blast the query sequences against an SRA blast DB."""

    cmd = []

    if args['protein'] and iteration == 1:
        cmd.append('tblastn')
        cmd.append('-db_gencode {}'.format(args['db_gencode']))
    else:
        cmd.append('blastn')
        cmd.append('-evalue {}'.format(args['evalue']))

    cmd.append('-outfmt 15')
    cmd.append('-max_target_seqs {}'.format(args['max_target_seqs']))
    cmd.append('-out {}'.format(hits_file))
    cmd.append('-db {}'.format(blast_db))
    cmd.append('-query {}'.format(query))

    command = ' '.join(cmd)
    log.subcommand(command, args['temp_dir'])

def against_contigs(args, blast_db, query, hits_file):
    """Blast the query sequence against the contings. The blast output
    will have the scores for later processing.
    """

    cmd = []

    if args.protein:
        cmd.append('tblastn')
        cmd.append('-db_gencode {}'.format(args.db_gencode))
    else:
        cmd.append('blastn')

    cmd.append('-db {}'.format(blast_db))
    cmd.append('-query {}'.format(query))
    cmd.append('-out {}'.format(hits_file))
    cmd.append('-outfmt 15')

    command = ' '.join(cmd)
    log.subcommand(command, args.temp_dir)

def shard_path(blast_db, shard_index):
    """Create the BLAST shard DB names."""

    file_name = '{}.{:03d}.blast'.format(blast_db, shard_index)
    return file_name

def all_shard_paths(blast_db):
    """Get all of the BLAST DB names built by the preprocessor."""

    pattern = '{}.*.blast.nhr'.format(blast_db)

    files = glob.glob(pattern)
    if not files:
        err = ('No blast shards found. Looking for "{}"\n'
               'Verify the --work-dir and --file-prefix options.').format(
                   pattern[:-4])
        sys.exit(err)

    return sorted([f[:-4] for f in files])

def output_file_name(temp_dir, shrd_path, iteration):
    """Create a file name for blast results."""

    shard_name = os.path.basename(shrd_path)
    file_name = '{}.{:02d}.results.json'.format(shard_name, iteration)

    return os.path.join(temp_dir, file_name)

def temp_db_name(temp_dir, blast_db, iteration):
    """Generate a name for the temp DB used to filter the contigs."""

    temp_name = os.path.basename(blast_db)
    file_name = '{}.{:02d}.blast'.format(temp_name, iteration)
    return os.path.join(temp_dir, file_name)

def hits(json_file):
    """Extract the blast hits from the blast json output file."""

    with open(json_file) as blast_file:
        raw = blast_file.read()
        obj = json.loads(raw)

    hits_list = []
    for raw in obj['BlastOutput2'][0]['report']['results']['search']['hits']:
        for i, desc in enumerate(raw['description']):
            hit = dict(desc)
            hit['len'] = raw['len']
            hit.update(raw['hsps'][i])
            hits_list.append(hit)

    return hits_list
<|endoftext|>


<commit_before>import pickle
import unittest

from coalib.bearlib.languages.Language import Language, LanguageMeta

class LanguageTest(unittest.TestCase):

    def test_class__dir__(self):
        assert set(dir(Language)) == {
            l.__name__ for l in LanguageMeta.all
        }.union(type.__dir__(Language))

    def test_pickle_ability(self):
        cpp = Language['CPP']
        cpp_str = pickle.dumps(cpp)
        cpp_unpickled = pickle.loads(cpp_str)
        self.assertEqual(str(cpp), str(cpp_unpickled))

class LanguageAttributeErrorTest(unittest.TestCase):

    def setUp(self):
        self.lang_cpp = Language['CPP']
        self.lang_unknown = Language['Unknown']

    def tearDown(self):
        pass

    def test_invalid_attribute(self):
        with self.assertRaisesRegex(AttributeError, 'not a valid attribute'):
            self.lang_cpp.not_an_attribute

    def test_attribute_list_empy(self):
        with self.assertRaisesRegex(AttributeError, 'no available attribute'):
            self.lang_unknown.not_an_attribute
<commit_msg>LanguageTest.py: Add contains test<commit_after>import pickle
import unittest

from coalib.bearlib.languages.Language import Language, LanguageMeta

class LanguageTest(unittest.TestCase):

    def test_class__dir__(self):
        assert set(dir(Language)) == {
            l.__name__ for l in LanguageMeta.all
        }.union(type.__dir__(Language))

    def test_pickle_ability(self):
        cpp = Language['CPP']
        cpp_str = pickle.dumps(cpp)
        cpp_unpickled = pickle.loads(cpp_str)
        self.assertEqual(str(cpp), str(cpp_unpickled))

    def test_contains_method(self):
        # Test alias
        self.assertTrue('py' in Language[Language.Python])
        # Test version
        self.assertTrue('python' in Language[Language.Python == 3])
        # Test string parse
        self.assertTrue('python' in Language['python 3'])
        # Test version exclusion
        self.assertFalse('py 2' in Language['py 3'])
        # More complex version exclusion test
        self.assertFalse('py 2.7, 3.4' in Language['py 3'])

class LanguageAttributeErrorTest(unittest.TestCase):

    def setUp(self):
        self.lang_cpp = Language['CPP']
        self.lang_unknown = Language['Unknown']

    def tearDown(self):
        pass

    def test_invalid_attribute(self):
        with self.assertRaisesRegex(AttributeError, 'not a valid attribute'):
            self.lang_cpp.not_an_attribute

    def test_attribute_list_empy(self):
        with self.assertRaisesRegex(AttributeError, 'no available attribute'):
            self.lang_unknown.not_an_attribute
<|endoftext|>


<commit_before><commit_msg>Draft: recompute before using radial dimension in the unit test<commit_after><|endoftext|>