<commit_before>import logging; logger = logging.getLogger("robots.position")

import math
import numpy
import transformations

class UnknownFrameError(RuntimeError):
    pass

FRAMES = ["map", "base_link", "eyes_link", "station", "beacon"]

POS_EPSILON = 0.1 # Min distance in meters from origin to be considered as 'in game'

class PoseManager(object):
    """ A pose is for us a dict {'x':x, 'y':y, 'z':z, 'qx':qx, 'qy':qy, 'qz':qz, 'qw':qw, 'frame':frame},
    ie a (x, y, z) cartesian pose in meter interpreted in a specific reference
    frame, and a quaternion describing the orientation of the object in radians.

    This class helps with:
     * converting from other convention to our convention,
     * converting back to other conventions.

     """

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

    @staticmethod
    def quaternion_from_euler(rx, ry, rz):
        return transformations.quaternion_from_euler(rx, ry, rz, 'sxyz')

    def normalizedict(self, pose):
        if not 'x' in pose:
            pose['x'] = 0.0
        else:
            pose['x'] = float(pose['x'])

        if not 'y' in pose:
            pose['y'] = 0.0
        else:
            pose['y'] = float(pose['y'])

        if not 'z' in pose:
            pose['z'] = 0.0
        else:
            pose['z'] = float(pose['z'])

        if not 'qx' in pose:
            pose['qx'] = 0.0
        else:
            pose['qx'] = float(pose['qx'])

        if not 'qy' in pose:
            pose['qy'] = 0.0
        else:
            pose['qy'] = float(pose['qy'])

        if not 'qz' in pose:
            pose['qz'] = 0.0
        else:
            pose['qz'] = float(pose['qz'])

        if not 'qw' in pose:
            pose['qw'] = 1.0
        else:
            pose['qw'] = float(pose['qw'])

        if not 'frame' in pose:
            pose['frame'] = 'map'
        return pose

    def normalizelist(self, pose):
        if len(pose) == 3:
            x,y,z = pose
            return self.normalizedict({'x':x, 'y':y, 'z':z})

        if len(pose) == 4 and isinstance(pose[3], basestring):
            # we assume the last arg is the frame
            x,y,z, frame = pose
            return self.normalizedict({'x':x, 'y':y, 'z':z, 'frame': frame})

        if len(pose) == 6:
            x,y,z, rx, ry, rz = pose
            qx,qy,qz,qw = self.quaternion_from_euler(rx, ry, rz)
            return self.normalizedict({'x':x, 'y':y, 'z':z, 'qx':qx, 'qy':qy, 'qz':qz, 'qw':qw})

        if len(pose) == 7:
            if isinstance(pose[6], basestring):
                # we assume the last arg is the frame
                x,y,z, rx, ry, rz, frame = pose
                qx,qy,qz,qw = self.quaternion_from_euler(rx, ry, rz)
                return self.normalizedict({'x':x, 'y':y, 'z':z, 'qx':qx, 'qy':qy, 'qz':qz, 'qw':qw, 'frame': frame})
            else:
                x,y,z, qx, qy, qz, qw = pose
                return self.normalizedict({'x':x, 'y':y, 'z':z, 'qx':qx, 'qy':qy, 'qz':qz, 'qw':qw})

        if len(pose) == 8 and isinstance(pose[7], basestring):
            # we assume the last arg is the frame
            x,y,z, qx, qy, qz, qw, frame = pose
            return self.normalizedict({'x':x, 'y':y, 'z':z, 'qx':qx, 'qy':qy, 'qz':qz, 'qw':qw, 'frame': frame})

        raise RuntimeError("Don't know what to do with pose as array %s" % str(pose))

    def normalize(self, pose):
        if isinstance(pose, list) or isinstance(pose, tuple):
            return self.normalizelist(pose)
        if isinstance(pose, dict):
            return self.normalizedict(pose)

        raise RuntimeError("normalize() takes either lists or dict as input.")

    def __getitem__(self, raw):
        """ Implements the PoseManager[] operator as an alias for PoseManager.get()
        """
        return self.get(raw)

    def get(self, raw):
        """ takes a loosly defined 'pose' as input and returns a properly formatted
        and normalized pose.

        Input may be:
         * a frame
         * an incomplete pose dictionary
         * a list or tuple (x,y,z), (x,y,z,frame) or (z,y,z,rx,ry,rz) or (x,y,z,qx,qy,qz,qw)
        """

        pose = None

        if isinstance(raw, basestring):
            pose = self.getabspose(raw)
            if pose:
                return self.normalize(pose)

            raise UnknownFrameError("Unknown object or frame '%s'" % raw)

        else:
            return self.normalize(raw)

    def myself(self):
        """
        Returns the current robot's pose, ie the pose of the ROS TF 'base_link'
        frame.
        """
        return self.getabspose("/base_link")

    def distance(self, pose1, pose2 = "base_link"):
        """ Returns the euclidian distance between two pyRobots poses.

        If the second pose is omitted, "base_link" is assumed (ie, distance
        between a pose and the robot itself).
        """
        p1 = self.get(pose1)
        p2 = self.get(pose2)

        return math.sqrt(math.pow(p2["x"] - p1["x"], 2) + \
                         math.pow(p2["y"] - p1["y"], 2) + \
                         math.pow(p2["z"] - p1["z"], 2))

    def _xyz_to_mat44(self, pos):
        return transformations.translation_matrix((pos['x'], pos['y'], pos['z']))

    def _xyzw_to_mat44(self, ori):
        return transformations.quaternion_matrix((ori['qx'], ori['qy'], ori['qz'], ori['qw']))

    def _to_mat4(self, pose):
        return numpy.dot(self._xyz_to_mat44(pose), self._xyzw_to_mat44(pose))

    def getabspose(self, frame):
        """ This depends on each robot... (does it?)
        """
        raise NotImplementedError

    def inframe(self, pose, frame):
        """ Transform a pose from one frame to another one.

        Uses transformation matrices. Could be refactored to use directly
        quaternions.
        """
        pose = self.get(pose)

        if pose['frame'] == "map":
            orig = numpy.identity(4)
        else:
            orig = self._to_mat4(self.get(pose["frame"]))

        if frame == "map":
            dest = numpy.identity(4)
        else:
            dest = numpy.linalg.inv(self._to_mat4(self.get(frame)))

        poseMatrix = self._to_mat4(pose)

        transf = numpy.dot(dest, orig)
        transformedPose = numpy.dot(transf, poseMatrix)

        qx,qy,qz,qw = transformations.quaternion_from_matrix(transformedPose)
        x,y,z = transformations.translation_from_matrix(transformedPose)

        return {"x":float(x),
                "y":float(y),
                "z":float(z),
                "qx":float(qx),
                "qy":float(qy),
                "qz":float(qz),
                "qw":float(qw),
                "frame": frame}

    def pantilt(self, pose, ref="/base_link"):
        """
        Convert a xyz target to pan and tilt angles from a given
        viewpoint.

        :param pose: the target pose
        :param ref: the reference frame (default to base_link)
        :returns: (pan, tilt) in radians, in ]-pi, pi]
        """
        pose = self.inframe(pose, ref)
        pan = self.normalize_angle(numpy.arctan2(pose['y'], pose['x']))
        tilt = self.normalize_angle(numpy.arctan2(pose['z'], pose['x']))
        return (pan,tilt)

    @staticmethod
    def normalize_angle(angle):
        """ Returns equivalent angle such as  -pi < angle <= pi
        """
        angle = angle % (2 * math.pi) # => angle > 0
        return float(angle if angle <= math.pi else (-math.pi + angle % math.pi))

    def isin(self, point,polygon):
        """
        Determines if a 2D point is inside a given 2D polygon or not.

        :param point: a (x,y) pair
        :param polygon: a list of (x,y) pairs.

        Copied from: http://www.ariel.com.au/a/python-point-int-poly.html
        """

        x,y = point
        n = len(polygon)
        inside =False

        p1x,p1y = polygon[0]
        for i in range(n+1):
            p2x,p2y = polygon[i % n]
            if y > min(p1y,p2y):
                if y <= max(p1y,p2y):
                    if x <= max(p1x,p2x):
                        if p1y != p2y:
                            xinters = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
                        if p1x == p2x or x <= xinters:
                            inside = not inside
            p1x,p1y = p2x,p2y

        return inside

<commit_msg>Minor fix/improvements to helper/position<commit_after>import logging; logger = logging.getLogger("robots.position")

import math
import numpy
import transformations

class UnknownFrameError(RuntimeError):
    pass

FRAMES = ["map", "base_link", "eyes_link", "station", "beacon"]

POS_EPSILON = 0.1 # Min distance in meters from origin to be considered as 'in game'

class PoseManager(object):
    """ A pose is for us a dict {'x':x, 'y':y, 'z':z, 'qx':qx, 'qy':qy, 'qz':qz, 'qw':qw, 'frame':frame},
    ie a (x, y, z) cartesian pose in meter interpreted in a specific reference
    frame, and a quaternion describing the orientation of the object in radians.

    This class helps with:
     * converting from other convention to our convention,
     * converting back to other conventions.

     """

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

    @staticmethod
    def quaternion_from_euler(rx, ry, rz):
        return transformations.quaternion_from_euler(rx, ry, rz, 'sxyz')

    def euler(self, pose):
        pose = self.get(pose)
        return transformations.euler_from_quaternion([pose['qx'], pose['qy'], pose['qz'], pose['qw']], 'sxyz')

    def normalizedict(self, pose):
        if not 'x' in pose:
            pose['x'] = 0.0
        else:
            pose['x'] = float(pose['x'])

        if not 'y' in pose:
            pose['y'] = 0.0
        else:
            pose['y'] = float(pose['y'])

        if not 'z' in pose:
            pose['z'] = 0.0
        else:
            pose['z'] = float(pose['z'])

        if not 'qx' in pose:
            pose['qx'] = 0.0
        else:
            pose['qx'] = float(pose['qx'])

        if not 'qy' in pose:
            pose['qy'] = 0.0
        else:
            pose['qy'] = float(pose['qy'])

        if not 'qz' in pose:
            pose['qz'] = 0.0
        else:
            pose['qz'] = float(pose['qz'])

        if not 'qw' in pose:
            pose['qw'] = 1.0
        else:
            pose['qw'] = float(pose['qw'])

        if not 'frame' in pose:
            pose['frame'] = 'map'
        return pose

    def normalizelist(self, pose):
        if len(pose) == 3:
            x,y,z = pose
            return self.normalizedict({'x':x, 'y':y, 'z':z})

        if len(pose) == 4 and isinstance(pose[3], basestring):
            # we assume the last arg is the frame
            x,y,z, frame = pose
            return self.normalizedict({'x':x, 'y':y, 'z':z, 'frame': frame})

        if len(pose) == 6:
            x,y,z, rx, ry, rz = pose
            qx,qy,qz,qw = self.quaternion_from_euler(rx, ry, rz)
            return self.normalizedict({'x':x, 'y':y, 'z':z, 'qx':qx, 'qy':qy, 'qz':qz, 'qw':qw})

        if len(pose) == 7:
            if isinstance(pose[6], basestring):
                # we assume the last arg is the frame
                x,y,z, rx, ry, rz, frame = pose
                qx,qy,qz,qw = self.quaternion_from_euler(rx, ry, rz)
                return self.normalizedict({'x':x, 'y':y, 'z':z, 'qx':qx, 'qy':qy, 'qz':qz, 'qw':qw, 'frame': frame})
            else:
                x,y,z, qx, qy, qz, qw = pose
                return self.normalizedict({'x':x, 'y':y, 'z':z, 'qx':qx, 'qy':qy, 'qz':qz, 'qw':qw})

        if len(pose) == 8 and isinstance(pose[7], basestring):
            # we assume the last arg is the frame
            x,y,z, qx, qy, qz, qw, frame = pose
            return self.normalizedict({'x':x, 'y':y, 'z':z, 'qx':qx, 'qy':qy, 'qz':qz, 'qw':qw, 'frame': frame})

        raise RuntimeError("Don't know what to do with pose as array %s" % str(pose))

    def normalize(self, pose):
        if isinstance(pose, list) or isinstance(pose, tuple):
            return self.normalizelist(pose)
        if isinstance(pose, dict):
            return self.normalizedict(pose)

        raise RuntimeError("normalize() takes either lists or dict as input.")

    def __getitem__(self, raw):
        """ Implements the PoseManager[] operator as an alias for PoseManager.get()
        """
        return self.get(raw)

    def get(self, raw):
        """ takes a loosly defined 'pose' as input and returns a properly formatted
        and normalized pose.

        Input may be:
         * a frame
         * an incomplete pose dictionary
         * a list or tuple (x,y,z), (x,y,z,frame) or (z,y,z,rx,ry,rz) or (x,y,z,qx,qy,qz,qw)
        """

        pose = None

        if isinstance(raw, basestring) or isinstance(raw, int):
            pose = self.getabspose(raw)
            if pose:
                return self.normalize(pose)

            raise UnknownFrameError("Unknown object or frame '%s'" % raw)

        else:
            return self.normalize(raw)

    def myself(self):
        """
        Returns the current robot's pose, ie the pose of the ROS TF 'base_link'
        frame.
        """
        return self.getabspose("/base_link")

    def distance(self, pose1, pose2 = "base_link"):
        """ Returns the euclidian distance between two pyRobots poses.

        If the second pose is omitted, "base_link" is assumed (ie, distance
        between a pose and the robot itself).
        """
        p1 = self.get(pose1)
        p2 = self.get(pose2)

        return math.sqrt(math.pow(p2["x"] - p1["x"], 2) + \
                         math.pow(p2["y"] - p1["y"], 2) + \
                         math.pow(p2["z"] - p1["z"], 2))

    def _xyz_to_mat44(self, pos):
        return transformations.translation_matrix((pos['x'], pos['y'], pos['z']))

    def _xyzw_to_mat44(self, ori):
        return transformations.quaternion_matrix((ori['qx'], ori['qy'], ori['qz'], ori['qw']))

    def _to_mat4(self, pose):
        return numpy.dot(self._xyz_to_mat44(pose), self._xyzw_to_mat44(pose))

    def getabspose(self, frame):
        """ This depends on each robot... (does it?)
        """
        raise NotImplementedError

    def inframe(self, pose, frame):
        """ Transform a pose from one frame to another one.

        Uses transformation matrices. Could be refactored to use directly
        quaternions.
        """
        pose = self.get(pose)

        if pose['frame'] == "map":
            orig = numpy.identity(4)
        else:
            orig = self._to_mat4(self.get(pose["frame"]))

        if frame == "map":
            dest = numpy.identity(4)
        else:
            dest = numpy.linalg.inv(self._to_mat4(self.get(frame)))

        poseMatrix = self._to_mat4(pose)

        transf = numpy.dot(dest, orig)
        transformedPose = numpy.dot(transf, poseMatrix)

        qx,qy,qz,qw = transformations.quaternion_from_matrix(transformedPose)
        x,y,z = transformations.translation_from_matrix(transformedPose)

        return {"x":float(x),
                "y":float(y),
                "z":float(z),
                "qx":float(qx),
                "qy":float(qy),
                "qz":float(qz),
                "qw":float(qw),
                "frame": frame}

    def pantilt(self, pose, ref="/base_link"):
        """
        Convert a xyz target to pan and tilt angles from a given
        viewpoint.

        :param pose: the target pose
        :param ref: the reference frame (default to base_link)
        :returns: (pan, tilt) in radians, in ]-pi, pi]
        """
        pose = self.inframe(pose, ref)
        pan = self.normalize_angle(numpy.arctan2(pose['y'], pose['x']))
        tilt = self.normalize_angle(numpy.arctan2(pose['z'], pose['x']))
        return (pan,tilt)

    @staticmethod
    def normalize_angle(angle):
        """ Returns equivalent angle such as  -pi < angle <= pi
        """
        angle = angle % (2 * math.pi) # => angle > 0
        return float(angle if angle <= math.pi else (-math.pi + angle % math.pi))

    def isin(self, point,polygon):
        """
        Determines if a 2D point is inside a given 2D polygon or not.

        :param point: a (x,y) pair
        :param polygon: a list of (x,y) pairs.

        Copied from: http://www.ariel.com.au/a/python-point-int-poly.html
        """

        x,y = point
        n = len(polygon)
        inside =False

        p1x,p1y = polygon[0]
        for i in range(n+1):
            p2x,p2y = polygon[i % n]
            if y > min(p1y,p2y):
                if y <= max(p1y,p2y):
                    if x <= max(p1x,p2x):
                        if p1y != p2y:
                            xinters = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
                        if p1x == p2x or x <= xinters:
                            inside = not inside
            p1x,p1y = p2x,p2y

        return inside

<|endoftext|>


<commit_before># coding: utf-8

from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse

class BreadcrumpablePlaceManager(models.Manager):

    def get_queryset(self):
        return super(BreadcrumpablePlaceManager,
                     self).get_queryset().select_related(
            *self.model.get_select_related_list())

class BreadcrumpablePlaceModel(models.Model):
    PARENT_MODEL = None
    PARENT_FIELD = None

    name = models.CharField(max_length=50, unique=True, verbose_name=_('name'))
    slug = models.SlugField(verbose_name=_(u'slug'))

    objects = BreadcrumpablePlaceManager()

    class Meta:
        abstract = True

    @property
    def parent(self):
        return None

    @property
    def breadcrumps(self):
        return self.parent and self.parent.breadcrumps + [self, ] or [self, ]

    @classmethod
    def get_select_related_list(cls, chain=None):
        select_related = []
        if cls.PARENT_FIELD:
            if chain:
                related = '{}__{}'.format(chain, cls.PARENT_FIELD)
            else:
                related = cls.PARENT_FIELD
            select_related.append(related)
            select_related += cls.PARENT_MODEL.get_select_related_list(related)
        return select_related

    def get_detail_view_name(self):
        DETAIL_VIEW_NAME = getattr(self, 'DETAIL_VIEW_NAME', None)
        return DETAIL_VIEW_NAME or u'{}-details'.format(
            self._meta.model_name.lower())

    def get_absolute_url(self):
        return reverse(self.get_detail_view_name(),
                       args=[o.slug for o in self.breadcrumps])

    def __unicode__(self):
        return u'{}'.format(self.name)

class Country(BreadcrumpablePlaceModel):
    '''
    A country
    '''

    DETAIL_VIEW_NAME = 'country-details'

    class Meta:
        verbose_name = _('country')
        verbose_name_plural = _('countries')
        ordering = ('name',)

class Region(BreadcrumpablePlaceModel):
    '''
    A region is a geographical region for grouping areas (and facilities within areas).
    '''

    PARENT_FIELD = 'country'
    PARENT_MODEL = Country

    country = models.ForeignKey(Country,
                                related_name='regions',
                                verbose_name=_('country'))

    class Meta:
        verbose_name = _('region')
        verbose_name_plural = _('regions')
        ordering = ('country', 'name',)

    @property
    def parent(self):
        return self.country

class Area(BreadcrumpablePlaceModel):
    '''
    An area is a subdevision of a region, such as cities, neighbourhoods, etc.
    Each area belongs to a region.
    '''

    PARENT_FIELD = 'region'
    PARENT_MODEL = Region

    region = models.ForeignKey(Region, related_name='areas',
                               verbose_name=_('region'))

    class Meta:
        verbose_name = _('area')
        verbose_name_plural = _('areas')
        ordering = ('region', 'name',)

    @property
    def parent(self):
        return self.region

class Place(BreadcrumpablePlaceModel):
    '''
    A place (german: Ort) can be a city like Jena in Thüringen - Jena
    or a 'district' like  Wilmersdorf in Berlin - Berlin.
    '''

    PARENT_FIELD = 'area'
    PARENT_MODEL = Area

    area = models.ForeignKey(Area,
                             related_name='places',
                             verbose_name=_('area'))

    class Meta:
        verbose_name = _('place')
        verbose_name_plural = _('places')
        ordering = ('area', 'name',)

    @property
    def parent(self):
        return self.area

class Workplace(models.Model):
    facility = models.ForeignKey("TBD.Facility", verbose_name=_(u''), help_text=_(u''))
    # set only location if different from facility?
    location = models.ForeignKey("scheduler.Location", null=True, verbose_name=_(u''), help_text=_(u''))
    name = models.CharField(max_length=255)
    description = models.TextField(max_length=20000, blank=True)
<commit_msg>Implement Organization - Facility - Workplace<commit_after># coding: utf-8

from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse

class BreadcrumpablePlaceManager(models.Manager):

    def get_queryset(self):
        return super(BreadcrumpablePlaceManager,
                     self).get_queryset().select_related(
            *self.model.get_select_related_list())

class BreadcrumpablePlaceModel(models.Model):
    PARENT_MODEL = None
    PARENT_FIELD = None

    name = models.CharField(max_length=50, unique=True, verbose_name=_('name'))
    slug = models.SlugField(verbose_name=_(u'slug'))

    objects = BreadcrumpablePlaceManager()

    class Meta:
        abstract = True

    @property
    def parent(self):
        return None

    @property
    def breadcrumps(self):
        return self.parent and self.parent.breadcrumps + [self, ] or [self, ]

    @classmethod
    def get_select_related_list(cls, chain=None):
        select_related = []
        if cls.PARENT_FIELD:
            if chain:
                related = '{}__{}'.format(chain, cls.PARENT_FIELD)
            else:
                related = cls.PARENT_FIELD
            select_related.append(related)
            select_related += cls.PARENT_MODEL.get_select_related_list(related)
        return select_related

    def get_detail_view_name(self):
        DETAIL_VIEW_NAME = getattr(self, 'DETAIL_VIEW_NAME', None)
        return DETAIL_VIEW_NAME or u'{}-details'.format(
            self._meta.model_name.lower())

    def get_absolute_url(self):
        return reverse(self.get_detail_view_name(),
                       args=[o.slug for o in self.breadcrumps])

    def __unicode__(self):
        return u'{}'.format(self.name)

class Country(BreadcrumpablePlaceModel):
    '''
    A country
    '''

    DETAIL_VIEW_NAME = 'country-details'

    class Meta:
        verbose_name = _('country')
        verbose_name_plural = _('countries')
        ordering = ('name',)

class Region(BreadcrumpablePlaceModel):
    '''
    A region is a geographical region for grouping areas (and facilities within areas).
    '''

    PARENT_FIELD = 'country'
    PARENT_MODEL = Country

    country = models.ForeignKey(Country,
                                related_name='regions',
                                verbose_name=_('country'))

    class Meta:
        verbose_name = _('region')
        verbose_name_plural = _('regions')
        ordering = ('country', 'name',)

    @property
    def parent(self):
        return self.country

class Area(BreadcrumpablePlaceModel):
    '''
    An area is a subdevision of a region, such as cities, neighbourhoods, etc.
    Each area belongs to a region.
    '''

    PARENT_FIELD = 'region'
    PARENT_MODEL = Region

    region = models.ForeignKey(Region, related_name='areas',
                               verbose_name=_('region'))

    class Meta:
        verbose_name = _('area')
        verbose_name_plural = _('areas')
        ordering = ('region', 'name',)

    @property
    def parent(self):
        return self.region

class Place(BreadcrumpablePlaceModel):
    '''
    A place (german: Ort) can be a city like Jena in Thüringen - Jena
    or a 'district' like  Wilmersdorf in Berlin - Berlin.
    '''

    PARENT_FIELD = 'area'
    PARENT_MODEL = Area

    area = models.ForeignKey(Area,
                             related_name='places',
                             verbose_name=_('area'))

    class Meta:
        verbose_name = _('place')
        verbose_name_plural = _('places')
        ordering = ('area', 'name',)

    @property
    def parent(self):
        return self.area

class Organization(models.Model):
    """
    An organization of people, e.g. "Wilmersdorf hilft"
    """
    name = models.CharField(max_length=255)

class Facility(models.Model):
    """
    A building complex or suchlike.
    """
    name = models.CharField(max_length=255)
    organization = models.ForeignKey("places.Organization")
    location = models.ForeignKey("scheduler.Location")

class Workplace(models.Model):
    """
    A place where work is performed. E.g. "Spendenkammer".

    TODO:
    - We discussed workplaces having their own location if they're offsite. But wouldn't
      we just create a new facility for that?
    """
    name = models.CharField(max_length=255)
    facility = models.ForeignKey("places.Facility")
    description = models.TextField(blank=True)
<|endoftext|>


<commit_before>from django.db import models

import webbrowser
from datetime import datetime
from threading import Timer
from player import helpers

class Music(models.Model):
    # Youtube ID
    video_id = models.CharField(max_length=255)
    name = models.CharField(max_length=255, editable=False)
    # Date is used for ordering musics
    date = models.DateTimeField(auto_now_add=True)
    # Duration in second
    duration = models.PositiveIntegerField(editable=False)
    # thumbnail in 190 * 120
    thumbnail = models.CharField(max_length=255, editable=False)
    count = models.PositiveIntegerField(default=0, editable=False)
    last_play = models.DateTimeField(null=True)

    @classmethod
    def add(cls, **kwargs):
        existing_music = Music.objects.filter(video_id=kwargs['video_id']).first()
        if existing_music:
            existing_music.date = datetime.now()
            existing_music.save()
            return existing_music
        else:
            music = cls(**kwargs)
            music.save()
            return music

    def __unicode__(self):
        return self.name

class Player():
    current = None
    event = None
    shuffle = False

    @classmethod
    def play(self, music):
        # clear the queue
        if Player.event:
            Player.event.cancel()

        Player.current = music
        music.count += 1
        music.last_play = datetime.now()
        music.save()

        webbrowser.open(helpers.get_youtube_link(music.video_id))

        Player.event = Timer(music.duration, Player.play_next, ())
        Player.event.start()

    @classmethod
    def play_next(self, forced=False):
        music = None
        if Player.current:
            if forced:
                music = Player.current
            else:
                music = Music.objects.filter(date__gt=Player.current.date).first()

        if music:
            Player.play(music)
        elif Player.shuffle:
            # Select random music, excluding 5% last played musics
            count = Music.objects.all().count()
            limit = count / 20
            limit_date = Music.objects.all().order_by('-date')[limit].date
            shuffled = Music.objects.filter(date__lte=limit_date).order_by('?').first()
            shuffled.date = datetime.now()
            shuffled.save()

            Player.play(shuffled)
        else:
            Player.current = None

    @classmethod
    def push(self, video_id):
        music = Music.add(video_id=video_id)

        if not Player.current:
            Player.current = music
            Player.play_next(forced=True)

    @classmethod
    def get_current_remaining_time(self):
        if not Player.current:
            return 0
        return Player.current.duration - int(((datetime.now() - Player.current.last_play)).total_seconds())

    @classmethod
    def get_remaining_time(self):
        if not Player.current:
            return 0
        nexts = Music.objects.filter(date__gt=Player.current.date)
        time_left = 0
        for music in nexts:
            time_left += music.duration
        time_left += Player.get_current_remaining_time()

        return time_left

    @classmethod
    def get_musics_remaining(self):
        if not Player.current:
            return
        nexts = Music.objects.filter(date__gt=Player.current.date)

        return nexts

    @classmethod
    def get_count_remaining(self):
        if not Player.current:
            return 0
        return Music.objects.filter(date__gte=Player.current.date).count()

from player.signals import *
<commit_msg>send int, not int,0<commit_after>from django.db import models

import webbrowser
from datetime import datetime
from threading import Timer
from player import helpers

class Music(models.Model):
    # Youtube ID
    video_id = models.CharField(max_length=255)
    name = models.CharField(max_length=255, editable=False)
    # Date is used for ordering musics
    date = models.DateTimeField(auto_now_add=True)
    # Duration in second
    duration = models.PositiveIntegerField(editable=False)
    # thumbnail in 190 * 120
    thumbnail = models.CharField(max_length=255, editable=False)
    count = models.PositiveIntegerField(default=0, editable=False)
    last_play = models.DateTimeField(null=True)

    @classmethod
    def add(cls, **kwargs):
        existing_music = Music.objects.filter(video_id=kwargs['video_id']).first()
        if existing_music:
            existing_music.date = datetime.now()
            existing_music.save()
            return existing_music
        else:
            music = cls(**kwargs)
            music.save()
            return music

    def __unicode__(self):
        return self.name

class Player():
    current = None
    event = None
    shuffle = False

    @classmethod
    def play(self, music):
        # clear the queue
        if Player.event:
            Player.event.cancel()

        Player.current = music
        music.count += 1
        music.last_play = datetime.now()
        music.save()

        webbrowser.open(helpers.get_youtube_link(music.video_id))

        Player.event = Timer(music.duration, Player.play_next, ())
        Player.event.start()

    @classmethod
    def play_next(self, forced=False):
        music = None
        if Player.current:
            if forced:
                music = Player.current
            else:
                music = Music.objects.filter(date__gt=Player.current.date).first()

        if music:
            Player.play(music)
        elif Player.shuffle:
            # Select random music, excluding 5% last played musics
            count = Music.objects.all().count()
            limit = count / 20
            limit_date = Music.objects.all().order_by('-date')[limit].date
            shuffled = Music.objects.filter(date__lte=limit_date).order_by('?').first()
            shuffled.date = datetime.now()
            shuffled.save()

            Player.play(shuffled)
        else:
            Player.current = None

    @classmethod
    def push(self, video_id):
        music = Music.add(video_id=video_id)

        if not Player.current:
            Player.current = music
            Player.play_next(forced=True)

    @classmethod
    def get_current_remaining_time(self):
        if not Player.current:
            return 0
        time = Player.current.duration - int(((datetime.now() - Player.current.last_play)).total_seconds())
        print int(time)
        return int(time)

    @classmethod
    def get_remaining_time(self):
        if not Player.current:
            return 0
        nexts = Music.objects.filter(date__gt=Player.current.date)
        time_left = 0
        for music in nexts:
            time_left += music.duration
        time_left += Player.get_current_remaining_time()
        print int(time_left)
        return int(time_left)

    @classmethod
    def get_musics_remaining(self):
        if not Player.current:
            return
        nexts = Music.objects.filter(date__gt=Player.current.date)

        return nexts

    @classmethod
    def get_count_remaining(self):
        if not Player.current:
            return 0
        return Music.objects.filter(date__gte=Player.current.date).count()

from player.signals import *
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from urllib.parse import quote_plus

from plexapi import media, utils
from plexapi.base import PlexPartialObject
from plexapi.exceptions import BadRequest, NotFound

@utils.registerPlexObject
class Photoalbum(PlexPartialObject):
    """ Represents a photoalbum (collection of photos).

        Attributes:
            TAG (str): 'Directory'
            TYPE (str): 'photo'
            addedAt (datetime): Datetime this item was added to the library.
            art (str): Photo art (/library/metadata/<ratingkey>/art/<artid>)
            composite (str): Unknown
            fields (list): List of :class:`~plexapi.media.Field`.
            guid (str): Unknown (unique ID)
            index (sting): Index number of this album.
            key (str): API URL (/library/metadata/<ratingkey>).
            librarySectionID (int): :class:`~plexapi.library.LibrarySection` ID.
            listType (str): Hardcoded as 'photo' (useful for search filters).
            ratingKey (int): Unique key identifying this item.
            summary (str): Summary of the photoalbum.
            thumb (str): URL to thumbnail image.
            title (str): Photoalbum title. (Trip to Disney World)
            type (str): Unknown
            updatedAt (datatime): Datetime this item was updated.
    """
    TAG = 'Directory'
    TYPE = 'photo'

    def _loadData(self, data):
        """ Load attribute values from Plex XML response. """
        self.listType = 'photo'
        self.addedAt = utils.toDatetime(data.attrib.get('addedAt'))
        self.art = data.attrib.get('art')
        self.composite = data.attrib.get('composite')
        self.fields = self.findItems(data, etag='Field')
        self.guid = data.attrib.get('guid')
        self.index = utils.cast(int, data.attrib.get('index'))
        self.key = data.attrib.get('key')
        self.librarySectionID = data.attrib.get('librarySectionID')
        self.ratingKey = data.attrib.get('ratingKey')
        self.summary = data.attrib.get('summary')
        self.thumb = data.attrib.get('thumb')
        self.title = data.attrib.get('title')
        self.type = data.attrib.get('type')
        self.updatedAt = utils.toDatetime(data.attrib.get('updatedAt'))

    def albums(self, **kwargs):
        """ Returns a list of :class:`~plexapi.photo.Photoalbum` objects in this album. """
        key = '/library/metadata/%s/children' % self.ratingKey
        return self.fetchItems(key, etag='Directory', **kwargs)

    def album(self, title):
        """ Returns the :class:`~plexapi.photo.Photoalbum` that matches the specified title. """
        for album in self.albums():
            if album.title.lower() == title.lower():
                return album
        raise NotFound('Unable to find album: %s' % title)

    def photos(self, **kwargs):
        """ Returns a list of :class:`~plexapi.photo.Photo` objects in this album. """
        key = '/library/metadata/%s/children' % self.ratingKey
        return self.fetchItems(key, etag='Photo', **kwargs)

    def photo(self, title):
        """ Returns the :class:`~plexapi.photo.Photo` that matches the specified title. """
        for photo in self.photos():
            if photo.title.lower() == title.lower():
                return photo
        raise NotFound('Unable to find photo: %s' % title)

@utils.registerPlexObject
class Photo(PlexPartialObject):
    """ Represents a single photo.

        Attributes:
            TAG (str): 'Photo'
            TYPE (str): 'photo'
            addedAt (datetime): Datetime this item was added to the library.
            fields (list): List of :class:`~plexapi.media.Field`.
            index (sting): Index number of this photo.
            key (str): API URL (/library/metadata/<ratingkey>).
            listType (str): Hardcoded as 'photo' (useful for search filters).
            media (TYPE): Unknown
            originallyAvailableAt (datetime): Datetime this photo was added to Plex.
            parentKey (str): Photoalbum API URL.
            parentRatingKey (int): Unique key identifying the photoalbum.
            ratingKey (int): Unique key identifying this item.
            summary (str): Summary of the photo.
            thumb (str): URL to thumbnail image.
            title (str): Photo title.
            type (str): Unknown
            updatedAt (datatime): Datetime this item was updated.
            year (int): Year this photo was taken.
    """
    TAG = 'Photo'
    TYPE = 'photo'
    METADATA_TYPE = 'photo'

    def _loadData(self, data):
        """ Load attribute values from Plex XML response. """
        self.listType = 'photo'
        self.addedAt = utils.toDatetime(data.attrib.get('addedAt'))
        self.fields = self.findItems(data, etag='Field')
        self.index = utils.cast(int, data.attrib.get('index'))
        self.key = data.attrib.get('key')
        self.originallyAvailableAt = utils.toDatetime(
            data.attrib.get('originallyAvailableAt'), '%Y-%m-%d')
        self.parentKey = data.attrib.get('parentKey')
        self.parentRatingKey = data.attrib.get('parentRatingKey')
        self.ratingKey = data.attrib.get('ratingKey')
        self.summary = data.attrib.get('summary')
        self.thumb = data.attrib.get('thumb')
        self.title = data.attrib.get('title')
        self.type = data.attrib.get('type')
        self.updatedAt = utils.toDatetime(data.attrib.get('updatedAt'))
        self.year = utils.cast(int, data.attrib.get('year'))
        self.media = self.findItems(data, media.Media)
        self.tag = self.findItems(data, media.Tag)

    def photoalbum(self):
        """ Return this photo's :class:`~plexapi.photo.Photoalbum`. """
        return self.fetchItem(self.parentKey)

    def section(self):
        """ Returns the :class:`~plexapi.library.LibrarySection` this item belongs to. """
        if hasattr(self, 'librarySectionID'):
            return self._server.library.sectionByID(self.librarySectionID)
        elif self.parentKey:
            return self._server.library.sectionByID(self.photoalbum().librarySectionID)
        else:
            raise BadRequest('Unable to get section for photo, can`t find librarySectionID')

    def iterParts(self):
        """ Iterates over the parts of this media item. """
        for item in self.media:
            for part in item.parts:
                yield part

    def sync(self, resolution, client=None, clientId=None, limit=None, title=None):
        """ Add current photo as sync item for specified device.
            See :func:`plexapi.myplex.MyPlexAccount.sync()` for possible exceptions.

            Parameters:
                resolution (str): maximum allowed resolution for synchronized photos, see PHOTO_QUALITY_* values in the
                                  module :mod:`plexapi.sync`.
                client (:class:`plexapi.myplex.MyPlexDevice`): sync destination, see
                                                               :func:`plexapi.myplex.MyPlexAccount.sync`.
                clientId (str): sync destination, see :func:`plexapi.myplex.MyPlexAccount.sync`.
                limit (int): maximum count of items to sync, unlimited if `None`.
                title (str): descriptive title for the new :class:`plexapi.sync.SyncItem`, if empty the value would be
                             generated from metadata of current photo.

            Returns:
                :class:`plexapi.sync.SyncItem`: an instance of created syncItem.
        """

        from plexapi.sync import SyncItem, Policy, MediaSettings

        myplex = self._server.myPlexAccount()
        sync_item = SyncItem(self._server, None)
        sync_item.title = title if title else self.title
        sync_item.rootTitle = self.title
        sync_item.contentType = self.listType
        sync_item.metadataType = self.METADATA_TYPE
        sync_item.machineIdentifier = self._server.machineIdentifier

        section = self.section()

        sync_item.location = 'library://%s/item/%s' % (section.uuid, quote_plus(self.key))
        sync_item.policy = Policy.create(limit)
        sync_item.mediaSettings = MediaSettings.createPhoto(resolution)

        return myplex.sync(sync_item, client=client, clientId=clientId)

    def download(self, savepath=None, keep_original_name=False, showstatus=False):
        """ Download photo files to specified directory.

            Parameters:
                savepath (str): Defaults to current working dir.
                keep_original_name (bool): True to keep the original file name otherwise
                    a friendlier is generated.
                showstatus(bool): Display a progressbar.
        """
        filepaths = []
        locations = [i for i in self.iterParts() if i]
        for location in locations:
            name = location.file
            if not keep_original_name:
                title = self.title.replace(' ', '.')
                name = '%s.%s' % (title, location.container)
            url = self._server.url('%s?download=1' % location.key)
            filepath = utils.download(url, self._server._token, filename=name, showstatus=showstatus,
                                      savepath=savepath, session=self._server._session)
            if filepath:
                filepaths.append(filepath)
        return filepaths
<commit_msg>add iterParts() and download() methods to Photoalbum class<commit_after># -*- coding: utf-8 -*-
from urllib.parse import quote_plus

from plexapi import media, utils
from plexapi.base import PlexPartialObject
from plexapi.exceptions import BadRequest, NotFound

@utils.registerPlexObject
class Photoalbum(PlexPartialObject):
    """ Represents a photoalbum (collection of photos).

        Attributes:
            TAG (str): 'Directory'
            TYPE (str): 'photo'
            addedAt (datetime): Datetime this item was added to the library.
            art (str): Photo art (/library/metadata/<ratingkey>/art/<artid>)
            composite (str): Unknown
            fields (list): List of :class:`~plexapi.media.Field`.
            guid (str): Unknown (unique ID)
            index (sting): Index number of this album.
            key (str): API URL (/library/metadata/<ratingkey>).
            librarySectionID (int): :class:`~plexapi.library.LibrarySection` ID.
            listType (str): Hardcoded as 'photo' (useful for search filters).
            ratingKey (int): Unique key identifying this item.
            summary (str): Summary of the photoalbum.
            thumb (str): URL to thumbnail image.
            title (str): Photoalbum title. (Trip to Disney World)
            type (str): Unknown
            updatedAt (datatime): Datetime this item was updated.
    """
    TAG = 'Directory'
    TYPE = 'photo'

    def _loadData(self, data):
        """ Load attribute values from Plex XML response. """
        self.listType = 'photo'
        self.addedAt = utils.toDatetime(data.attrib.get('addedAt'))
        self.art = data.attrib.get('art')
        self.composite = data.attrib.get('composite')
        self.fields = self.findItems(data, etag='Field')
        self.guid = data.attrib.get('guid')
        self.index = utils.cast(int, data.attrib.get('index'))
        self.key = data.attrib.get('key')
        self.librarySectionID = data.attrib.get('librarySectionID')
        self.ratingKey = data.attrib.get('ratingKey')
        self.summary = data.attrib.get('summary')
        self.thumb = data.attrib.get('thumb')
        self.title = data.attrib.get('title')
        self.type = data.attrib.get('type')
        self.updatedAt = utils.toDatetime(data.attrib.get('updatedAt'))

    def albums(self, **kwargs):
        """ Returns a list of :class:`~plexapi.photo.Photoalbum` objects in this album. """
        key = '/library/metadata/%s/children' % self.ratingKey
        return self.fetchItems(key, etag='Directory', **kwargs)

    def album(self, title):
        """ Returns the :class:`~plexapi.photo.Photoalbum` that matches the specified title. """
        for album in self.albums():
            if album.title.lower() == title.lower():
                return album
        raise NotFound('Unable to find album: %s' % title)

    def photos(self, **kwargs):
        """ Returns a list of :class:`~plexapi.photo.Photo` objects in this album. """
        key = '/library/metadata/%s/children' % self.ratingKey
        return self.fetchItems(key, etag='Photo', **kwargs)

    def photo(self, title):
        """ Returns the :class:`~plexapi.photo.Photo` that matches the specified title. """
        for photo in self.photos():
            if photo.title.lower() == title.lower():
                return photo
        raise NotFound('Unable to find photo: %s' % title)

    def iterParts(self):
        """ Iterates over the parts of this media item. """
        for album in self.albums():
            for photo in album.photos():
                for part in photo.iterParts():
                    yield part

    def download(self, savepath=None, keep_original_name=False, showstatus=False):
        """ Download photo files to specified directory.

            Parameters:
                savepath (str): Defaults to current working dir.
                keep_original_name (bool): True to keep the original file name otherwise
                    a friendlier is generated.
                showstatus(bool): Display a progressbar.
        """
        filepaths = []
        locations = [i for i in self.iterParts() if i]
        for location in locations:
            name = location.file
            if not keep_original_name:
                title = self.title.replace(' ', '.')
                name = '%s.%s' % (title, location.container)
            url = self._server.url('%s?download=1' % location.key)
            filepath = utils.download(url, self._server._token, filename=name, showstatus=showstatus,
                                      savepath=savepath, session=self._server._session)
            if filepath:
                filepaths.append(filepath)
        return filepaths

@utils.registerPlexObject
class Photo(PlexPartialObject):
    """ Represents a single photo.

        Attributes:
            TAG (str): 'Photo'
            TYPE (str): 'photo'
            addedAt (datetime): Datetime this item was added to the library.
            fields (list): List of :class:`~plexapi.media.Field`.
            index (sting): Index number of this photo.
            key (str): API URL (/library/metadata/<ratingkey>).
            listType (str): Hardcoded as 'photo' (useful for search filters).
            media (TYPE): Unknown
            originallyAvailableAt (datetime): Datetime this photo was added to Plex.
            parentKey (str): Photoalbum API URL.
            parentRatingKey (int): Unique key identifying the photoalbum.
            ratingKey (int): Unique key identifying this item.
            summary (str): Summary of the photo.
            thumb (str): URL to thumbnail image.
            title (str): Photo title.
            type (str): Unknown
            updatedAt (datatime): Datetime this item was updated.
            year (int): Year this photo was taken.
    """
    TAG = 'Photo'
    TYPE = 'photo'
    METADATA_TYPE = 'photo'

    def _loadData(self, data):
        """ Load attribute values from Plex XML response. """
        self.listType = 'photo'
        self.addedAt = utils.toDatetime(data.attrib.get('addedAt'))
        self.fields = self.findItems(data, etag='Field')
        self.index = utils.cast(int, data.attrib.get('index'))
        self.key = data.attrib.get('key')
        self.originallyAvailableAt = utils.toDatetime(
            data.attrib.get('originallyAvailableAt'), '%Y-%m-%d')
        self.parentKey = data.attrib.get('parentKey')
        self.parentRatingKey = data.attrib.get('parentRatingKey')
        self.ratingKey = data.attrib.get('ratingKey')
        self.summary = data.attrib.get('summary')
        self.thumb = data.attrib.get('thumb')
        self.title = data.attrib.get('title')
        self.type = data.attrib.get('type')
        self.updatedAt = utils.toDatetime(data.attrib.get('updatedAt'))
        self.year = utils.cast(int, data.attrib.get('year'))
        self.media = self.findItems(data, media.Media)
        self.tag = self.findItems(data, media.Tag)

    def photoalbum(self):
        """ Return this photo's :class:`~plexapi.photo.Photoalbum`. """
        return self.fetchItem(self.parentKey)

    def section(self):
        """ Returns the :class:`~plexapi.library.LibrarySection` this item belongs to. """
        if hasattr(self, 'librarySectionID'):
            return self._server.library.sectionByID(self.librarySectionID)
        elif self.parentKey:
            return self._server.library.sectionByID(self.photoalbum().librarySectionID)
        else:
            raise BadRequest('Unable to get section for photo, can`t find librarySectionID')

    def iterParts(self):
        """ Iterates over the parts of this media item. """
        for item in self.media:
            for part in item.parts:
                yield part

    def sync(self, resolution, client=None, clientId=None, limit=None, title=None):
        """ Add current photo as sync item for specified device.
            See :func:`plexapi.myplex.MyPlexAccount.sync()` for possible exceptions.

            Parameters:
                resolution (str): maximum allowed resolution for synchronized photos, see PHOTO_QUALITY_* values in the
                                  module :mod:`plexapi.sync`.
                client (:class:`plexapi.myplex.MyPlexDevice`): sync destination, see
                                                               :func:`plexapi.myplex.MyPlexAccount.sync`.
                clientId (str): sync destination, see :func:`plexapi.myplex.MyPlexAccount.sync`.
                limit (int): maximum count of items to sync, unlimited if `None`.
                title (str): descriptive title for the new :class:`plexapi.sync.SyncItem`, if empty the value would be
                             generated from metadata of current photo.

            Returns:
                :class:`plexapi.sync.SyncItem`: an instance of created syncItem.
        """

        from plexapi.sync import SyncItem, Policy, MediaSettings

        myplex = self._server.myPlexAccount()
        sync_item = SyncItem(self._server, None)
        sync_item.title = title if title else self.title
        sync_item.rootTitle = self.title
        sync_item.contentType = self.listType
        sync_item.metadataType = self.METADATA_TYPE
        sync_item.machineIdentifier = self._server.machineIdentifier

        section = self.section()

        sync_item.location = 'library://%s/item/%s' % (section.uuid, quote_plus(self.key))
        sync_item.policy = Policy.create(limit)
        sync_item.mediaSettings = MediaSettings.createPhoto(resolution)

        return myplex.sync(sync_item, client=client, clientId=clientId)

    def download(self, savepath=None, keep_original_name=False, showstatus=False):
        """ Download photo files to specified directory.

            Parameters:
                savepath (str): Defaults to current working dir.
                keep_original_name (bool): True to keep the original file name otherwise
                    a friendlier is generated.
                showstatus(bool): Display a progressbar.
        """
        filepaths = []
        locations = [i for i in self.iterParts() if i]
        for location in locations:
            name = location.file
            if not keep_original_name:
                title = self.title.replace(' ', '.')
                name = '%s.%s' % (title, location.container)
            url = self._server.url('%s?download=1' % location.key)
            filepath = utils.download(url, self._server._token, filename=name, showstatus=showstatus,
                                      savepath=savepath, session=self._server._session)
            if filepath:
                filepaths.append(filepath)
        return filepaths
<|endoftext|>


<commit_before>import random
import sys
import math
import threading
#import time

class Neuron():

	def __init__(self,network):
		self.network = network
		self.subscriptions = {}
		self.publications = {}
		self.potential = random.uniform(0.0, 1.0)
		self.desired_potential = None
		self.loss = None
		self.type = 0
		self.network.neurons.append(self)
		self.fire_counter = 0
		self.blame_lock = None
		self.ban_counter = 0

	def partially_subscribe(self):
		if len(self.subscriptions) == 0:
			sample_length = int(random.normalvariate(self.network.connectivity, self.network.connectivity_sqrt))
			if sample_length > len(self.network.nonmotor_neurons):
				sample_length = len(self.network.nonmotor_neurons)
			elected = random.sample(self.network.nonmotor_neurons, sample_length)
			for neuron in elected:
				if id(neuron) != id(self):
					self.subscriptions[neuron] = random.uniform(-1.0, 1.0)
					neuron.publications[self] = 0
			self.network.initiated_neurons += 1

	def calculate_potential(self):
		total = 0
		for neuron, weight in self.subscriptions.iteritems():
			total += neuron.potential * weight
		return self.activation_function(total)

	def activation_function(self,value):
		return 1 / (1 + math.exp(-value))

	def calculate_loss(self):
		try:
			return self.desired_potential - self.potential
		except:
			return None

	def fire(self):
		if self.type != 1:

			self.potential = self.calculate_potential()
			self.network.fire_counter += 1
			self.fire_counter += 1

			if self.desired_potential != None:

				if self.blame_lock:
					if (self.network.wave_counter - self.blame_lock) < (self.network.connectivity * len(self.network.nonsensory_neurons))**3:
						return True
					else:
						self.blame_lock = None

				self.loss = self.calculate_loss()
				if self.loss > 0:
					alteration_sign = 1
				elif self.loss < 0:
					alteration_sign = -1
				else:
					self.desired_potential = None
					return True

				alteration_value = (self.loss ** 4) / (len(self.subscriptions) + 1)

				for neuron, weight in self.subscriptions.iteritems():
					neuron.desired_potential = neuron.potential + (alteration_value * alteration_sign)
					self.subscriptions[neuron] = weight + (alteration_value * alteration_sign)
					#self.blame_lock = self.network.wave_counter

class Network():

	def __init__(self,size,input_dim=0,output_dim=0,connectivity=0.01,precision=2,randomly_fire=False,dynamic_output=False):
		self.precision = precision
		print "\nPrecision of the network will be " + str( 1.0 / (10**precision) )
		self.connectivity = int(size * connectivity)
		self.connectivity_sqrt = int(math.sqrt(self.connectivity))
		self.connectivity_sqrt_sqrt = int(math.sqrt(self.connectivity_sqrt))
		print "Each individual non-sensory neuron will subscribe to " + str(int(size * connectivity)) + " different neurons"

		self.neurons = []
		for i in range(size):
			Neuron(self)
		print "\n"
		print str(size) + " neurons created"

		self.sensory_neurons = []
		self.input_dim = input_dim
		self.pick_sensory_neurons(self.input_dim)

		self.motor_neurons = []
		self.output_dim = output_dim
		self.pick_motor_neurons(self.output_dim)

		self.nonsensory_neurons = [x for x in self.neurons if x not in self.sensory_neurons]
		self.nonmotor_neurons = [x for x in self.neurons if x not in self.motor_neurons]
		self.randomly_fire = randomly_fire
		self.motor_randomly_fire_rate = int(math.sqrt( len(self.nonsensory_neurons)/len(self.motor_neurons) ))

		self.reasoning_length = int(math.sqrt(self.input_dim))
		self.mini_batch = []

		self.dynamic_output = dynamic_output

		self.initiated_neurons = 0
		self.initiate_subscriptions()

		self.fire_counter = 0
		self.first_queue = {}
		self.next_queue = {}
		self.output = []
		self.wave_counter = 0
		self.batch_lock = 1

		print "\n"

		self.freezer = False
		self.thread = None
		self.visualize()
		self.ignite()

		print ""

	def initiate_subscriptions(self,only_new_ones=0):
		print ""
		for neuron in self.neurons:
			if neuron.type == 1:
				continue
			if only_new_ones and len(neuron.subscriptions) != 0:
				continue
			neuron.partially_subscribe()
			print "Initiated: " + str(self.initiated_neurons) + " neurons\r",
			sys.stdout.flush()
		print "\n"

	def add_neurons(self,units):
		for i in range(units):
			Neuron(self)
		print "\n"
		print str(units) + " neurons added"
		self.initiate_subscriptions(1)

	def _ignite(self):
		#t0 = time.time()
		motor_fire_counter = 0
		ban_list = []
		while not self.freezer:
			if self.randomly_fire:
				neuron = random.sample(self.nonsensory_neurons,1)[0]
				if neuron.type == 2:
					if 1 != random.randint(1,self.motor_randomly_fire_rate):
						continue
					else:
						motor_fire_counter += 1
				neuron.fire()
				if motor_fire_counter >= len(self.motor_neurons):
					if self.dynamic_output:
						print "Output: " + str(self.get_output()) + "\r",
						sys.stdout.flush()
					self.output = self.get_output()
					self.wave_counter += 1
					motor_fire_counter = 0

					if (self.wave_counter - self.batch_lock) > len(self.nonmotor_neurons):
						if self.mini_batch:
							[input_arr, output_arr] = random.sample(self.mini_batch,1)[0]
							step = 0
							for neuron in self.sensory_neurons:
								neuron.potential = input_arr[step]
								step += 1
							step = 0
							for neuron in self.motor_neurons:
								neuron.desired_potential = output_arr[step]
								step += 1
							self.batch_lock = self.wave_counter
			else:
				if not self.next_queue:
					#print "Delta time: " + str(time.time() - t0)
					#t0 = time.time()
					for neuron in self.motor_neurons:
						neuron.fire()
					for neuron in ban_list:
						neuron.ban_counter = 0
					ban_list = []
					if self.dynamic_output:
						print "Output: " + str(self.get_output()) + "\r",
						sys.stdout.flush()
					self.output = self.get_output()
					self.wave_counter += 1

					if (self.wave_counter - self.batch_lock) > len(self.nonmotor_neurons):
						if self.mini_batch:
							[input_arr, output_arr] = random.sample(self.mini_batch,1)[0]
							step = 0
							for neuron in self.sensory_neurons:
								neuron.potential = input_arr[step]
								step += 1
							step = 0
							for neuron in self.motor_neurons:
								neuron.desired_potential = output_arr[step]
								step += 1
							self.batch_lock = self.wave_counter

					if not self.first_queue:
						for neuron in self.sensory_neurons:
							self.first_queue.update(neuron.publications)
					self.next_queue = self.first_queue.copy()

				current_queue = self.next_queue.copy()
				self.next_queue = {}
				for neuron in ban_list:
					if neuron.ban_counter > self.connectivity_sqrt:
						current_queue.pop(neuron, None)
				while current_queue:
					neuron = random.choice(current_queue.keys())
					current_queue.pop(neuron, None)
					if neuron.ban_counter <= self.connectivity_sqrt:
						if neuron.type == 2:
							continue
						neuron.fire()
						ban_list.append(neuron)
						neuron.ban_counter += 1
						self.next_queue.update(neuron.publications)

	def ignite(self):
		self.freezer = False
		if not self.thread:
			self.thread = threading.Thread(target=self._ignite)
			self.thread.start()
		print "Network has been ignited"

	def freeze(self):
		self.freezer = True
		self.thread = None
		print "Network is now frozen"

	def breakit(self):
		for neuron in self.neurons:
			neuron.subscriptions = {}
		print "All the subscriptions are now broken"

	def pick_sensory_neurons(self,input_dim):
		available_neurons = []
		for neuron in self.neurons:
			if neuron.type is 0:
				available_neurons.append(neuron)
		for neuron in random.sample(available_neurons,input_dim):
			neuron.type = 1
			self.sensory_neurons.append(neuron)
		print str(input_dim) + " neuron picked as sensory neuron"

	def pick_motor_neurons(self,output_dim):
		available_neurons = []
		for neuron in self.neurons:
			if neuron.type is 0:
				available_neurons.append(neuron)
		for neuron in random.sample(available_neurons,output_dim):
			neuron.type = 2
			self.motor_neurons.append(neuron)
		print str(output_dim) + " neuron picked as motor neuron"

	def load(self,input_arr,output_arr=None):
		if len(self.sensory_neurons) != len(input_arr):
			print "Size of the input array: " + str(len(input_arr))
			print "Number of the sensory neurons: " + str(len(self.sensory_neurons))
			print "Size of the input array and number of the sensory neurons are not matching! Please try again"
		else:
			step = 0
			for neuron in self.sensory_neurons:
				neuron.potential = input_arr[step]
				step += 1
		if output_arr is None:
			self.mini_batch = []
			step = 0
			for neuron in self.neurons:
				neuron.desired_potential = None
				step += 1
		else:
			if len(self.motor_neurons) != len(output_arr):
				print "Size of the output/target array: " + str(len(output_arr))
				print "Number of the motor_neurons: " + str(len(self.motor_neurons))
				print "Size of the output/target array and number of the motor neurons are not matching! Please try again"
			else:
				step = 0
				for neuron in self.motor_neurons:
					neuron.desired_potential = output_arr[step]
					step += 1
				self.mini_batch.append([input_arr,output_arr])
				if len(self.mini_batch) > self.reasoning_length:
					self.mini_batch.pop(0)

	def get_output(self):
		output = []
		for neuron in self.motor_neurons:
			output.append( round(neuron.potential, self.precision) )
		return output

	def visualize(self):
		thread = threading.Thread(target=self._visualize)
		thread.start()
		print "Visualization initiated"

	def _visualize(self):
		from pyqtgraph.Qt import QtGui, QtCore
		import pyqtgraph as pg

		app = QtGui.QApplication([])
		win = pg.GraphicsWindow(title="Scatter Plot Symbols")
		win.resize(1000,600)

		pg.setConfigOptions(antialias=True)

		plot = win.addPlot(title="Plotting with symbols")
		plot.addLegend()
		plot.plot([0, 1, 2, 3, 4], pen=(0,0,200), symbolBrush=(0,0,200), symbolPen='w', symbol='o', symbolSize=14, name="symbol='o'")
		plot.plot([1, 2, 3, 4, 5], pen=(0,128,0), symbolBrush=(0,128,0), symbolPen='w', symbol='t', symbolSize=14, name="symbol='t'")
		plot.plot([2, 3, 4, 5, 6], pen=(19,234,201), symbolBrush=(19,234,201), symbolPen='w', symbol='t1', symbolSize=14, name="symbol='t1'")
		plot.plot([3, 4, 5, 6, 7], pen=(195,46,212), symbolBrush=(195,46,212), symbolPen='w', symbol='t2', symbolSize=14, name="symbol='t2'")
		plot.plot([4, 5, 6, 7, 8], pen=(250,194,5), symbolBrush=(250,194,5), symbolPen='w', symbol='t3', symbolSize=14, name="symbol='t3'")
		plot.plot([5, 6, 7, 8, 9], pen=(54,55,55), symbolBrush=(55,55,55), symbolPen='w', symbol='s', symbolSize=14, name="symbol='s'")
		plot.plot([6, 7, 8, 9, 10], pen=(0,114,189), symbolBrush=(0,114,189), symbolPen='w', symbol='p', symbolSize=14, name="symbol='p'")
		plot.plot([7, 8, 9, 10, 11], pen=(217,83,25), symbolBrush=(217,83,25), symbolPen='w', symbol='h', symbolSize=14, name="symbol='h'")
		plot.plot([8, 9, 10, 11, 12], pen=(237,177,32), symbolBrush=(237,177,32), symbolPen='w', symbol='star', symbolSize=14, name="symbol='star'")
		plot.plot([9, 10, 11, 12, 13], pen=(126,47,142), symbolBrush=(126,47,142), symbolPen='w', symbol='+', symbolSize=14, name="symbol='+'")
		plot.plot([10, 11, 12, 13, 14], pen=(119,172,48), symbolBrush=(119,172,48), symbolPen='w', symbol='d', symbolSize=14, name="symbol='d'")
		plot.setXRange(-2, 4)

		import sys
		if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
			QtGui.QApplication.instance().exec_()
<commit_msg>Prepare the plot elements<commit_after>import random
import sys
import math
import threading
#import time

class Neuron():

	def __init__(self,network):
		self.network = network
		self.subscriptions = {}
		self.publications = {}
		self.potential = random.uniform(0.0, 1.0)
		self.desired_potential = None
		self.loss = None
		self.type = 0
		self.network.neurons.append(self)
		self.fire_counter = 0
		self.blame_lock = None
		self.ban_counter = 0

	def partially_subscribe(self):
		if len(self.subscriptions) == 0:
			sample_length = int(random.normalvariate(self.network.connectivity, self.network.connectivity_sqrt))
			if sample_length > len(self.network.nonmotor_neurons):
				sample_length = len(self.network.nonmotor_neurons)
			elected = random.sample(self.network.nonmotor_neurons, sample_length)
			for neuron in elected:
				if id(neuron) != id(self):
					self.subscriptions[neuron] = random.uniform(-1.0, 1.0)
					neuron.publications[self] = 0
			self.network.initiated_neurons += 1

	def calculate_potential(self):
		total = 0
		for neuron, weight in self.subscriptions.iteritems():
			total += neuron.potential * weight
		return self.activation_function(total)

	def activation_function(self,value):
		return 1 / (1 + math.exp(-value))

	def calculate_loss(self):
		try:
			return self.desired_potential - self.potential
		except:
			return None

	def fire(self):
		if self.type != 1:

			self.potential = self.calculate_potential()
			self.network.fire_counter += 1
			self.fire_counter += 1

			if self.desired_potential != None:

				if self.blame_lock:
					if (self.network.wave_counter - self.blame_lock) < (self.network.connectivity * len(self.network.nonsensory_neurons))**3:
						return True
					else:
						self.blame_lock = None

				self.loss = self.calculate_loss()
				if self.loss > 0:
					alteration_sign = 1
				elif self.loss < 0:
					alteration_sign = -1
				else:
					self.desired_potential = None
					return True

				alteration_value = (self.loss ** 4) / (len(self.subscriptions) + 1)

				for neuron, weight in self.subscriptions.iteritems():
					neuron.desired_potential = neuron.potential + (alteration_value * alteration_sign)
					self.subscriptions[neuron] = weight + (alteration_value * alteration_sign)
					#self.blame_lock = self.network.wave_counter

class Network():

	def __init__(self,size,input_dim=0,output_dim=0,connectivity=0.01,precision=2,randomly_fire=False,dynamic_output=False):
		self.precision = precision
		print "\nPrecision of the network will be " + str( 1.0 / (10**precision) )
		self.connectivity = int(size * connectivity)
		self.connectivity_sqrt = int(math.sqrt(self.connectivity))
		self.connectivity_sqrt_sqrt = int(math.sqrt(self.connectivity_sqrt))
		print "Each individual non-sensory neuron will subscribe to " + str(int(size * connectivity)) + " different neurons"

		self.neurons = []
		for i in range(size):
			Neuron(self)
		print "\n"
		print str(size) + " neurons created"

		self.sensory_neurons = []
		self.input_dim = input_dim
		self.pick_sensory_neurons(self.input_dim)

		self.motor_neurons = []
		self.output_dim = output_dim
		self.pick_motor_neurons(self.output_dim)

		self.nonsensory_neurons = [x for x in self.neurons if x not in self.sensory_neurons]
		self.nonmotor_neurons = [x for x in self.neurons if x not in self.motor_neurons]
		self.randomly_fire = randomly_fire
		self.motor_randomly_fire_rate = int(math.sqrt( len(self.nonsensory_neurons)/len(self.motor_neurons) ))

		self.reasoning_length = int(math.sqrt(self.input_dim))
		self.mini_batch = []

		self.dynamic_output = dynamic_output

		self.initiated_neurons = 0
		self.initiate_subscriptions()

		self.fire_counter = 0
		self.first_queue = {}
		self.next_queue = {}
		self.output = []
		self.wave_counter = 0
		self.batch_lock = 1

		print "\n"

		self.freezer = False
		self.thread = None
		self.visualize()
		self.ignite()

		print ""

	def initiate_subscriptions(self,only_new_ones=0):
		print ""
		for neuron in self.neurons:
			if neuron.type == 1:
				continue
			if only_new_ones and len(neuron.subscriptions) != 0:
				continue
			neuron.partially_subscribe()
			print "Initiated: " + str(self.initiated_neurons) + " neurons\r",
			sys.stdout.flush()
		print "\n"

	def add_neurons(self,units):
		for i in range(units):
			Neuron(self)
		print "\n"
		print str(units) + " neurons added"
		self.initiate_subscriptions(1)

	def _ignite(self):
		#t0 = time.time()
		motor_fire_counter = 0
		ban_list = []
		while not self.freezer:
			if self.randomly_fire:
				neuron = random.sample(self.nonsensory_neurons,1)[0]
				if neuron.type == 2:
					if 1 != random.randint(1,self.motor_randomly_fire_rate):
						continue
					else:
						motor_fire_counter += 1
				neuron.fire()
				if motor_fire_counter >= len(self.motor_neurons):
					if self.dynamic_output:
						print "Output: " + str(self.get_output()) + "\r",
						sys.stdout.flush()
					self.output = self.get_output()
					self.wave_counter += 1
					motor_fire_counter = 0

					if (self.wave_counter - self.batch_lock) > len(self.nonmotor_neurons):
						if self.mini_batch:
							[input_arr, output_arr] = random.sample(self.mini_batch,1)[0]
							step = 0
							for neuron in self.sensory_neurons:
								neuron.potential = input_arr[step]
								step += 1
							step = 0
							for neuron in self.motor_neurons:
								neuron.desired_potential = output_arr[step]
								step += 1
							self.batch_lock = self.wave_counter
			else:
				if not self.next_queue:
					#print "Delta time: " + str(time.time() - t0)
					#t0 = time.time()
					for neuron in self.motor_neurons:
						neuron.fire()
					for neuron in ban_list:
						neuron.ban_counter = 0
					ban_list = []
					if self.dynamic_output:
						print "Output: " + str(self.get_output()) + "\r",
						sys.stdout.flush()
					self.output = self.get_output()
					self.wave_counter += 1

					if (self.wave_counter - self.batch_lock) > len(self.nonmotor_neurons):
						if self.mini_batch:
							[input_arr, output_arr] = random.sample(self.mini_batch,1)[0]
							step = 0
							for neuron in self.sensory_neurons:
								neuron.potential = input_arr[step]
								step += 1
							step = 0
							for neuron in self.motor_neurons:
								neuron.desired_potential = output_arr[step]
								step += 1
							self.batch_lock = self.wave_counter

					if not self.first_queue:
						for neuron in self.sensory_neurons:
							self.first_queue.update(neuron.publications)
					self.next_queue = self.first_queue.copy()

				current_queue = self.next_queue.copy()
				self.next_queue = {}
				for neuron in ban_list:
					if neuron.ban_counter > self.connectivity_sqrt:
						current_queue.pop(neuron, None)
				while current_queue:
					neuron = random.choice(current_queue.keys())
					current_queue.pop(neuron, None)
					if neuron.ban_counter <= self.connectivity_sqrt:
						if neuron.type == 2:
							continue
						neuron.fire()
						ban_list.append(neuron)
						neuron.ban_counter += 1
						self.next_queue.update(neuron.publications)

	def ignite(self):
		self.freezer = False
		if not self.thread:
			self.thread = threading.Thread(target=self._ignite)
			self.thread.start()
		print "Network has been ignited"

	def freeze(self):
		self.freezer = True
		self.thread = None
		print "Network is now frozen"

	def breakit(self):
		for neuron in self.neurons:
			neuron.subscriptions = {}
		print "All the subscriptions are now broken"

	def pick_sensory_neurons(self,input_dim):
		available_neurons = []
		for neuron in self.neurons:
			if neuron.type is 0:
				available_neurons.append(neuron)
		for neuron in random.sample(available_neurons,input_dim):
			neuron.type = 1
			self.sensory_neurons.append(neuron)
		print str(input_dim) + " neuron picked as sensory neuron"

	def pick_motor_neurons(self,output_dim):
		available_neurons = []
		for neuron in self.neurons:
			if neuron.type is 0:
				available_neurons.append(neuron)
		for neuron in random.sample(available_neurons,output_dim):
			neuron.type = 2
			self.motor_neurons.append(neuron)
		print str(output_dim) + " neuron picked as motor neuron"

	def load(self,input_arr,output_arr=None):
		if len(self.sensory_neurons) != len(input_arr):
			print "Size of the input array: " + str(len(input_arr))
			print "Number of the sensory neurons: " + str(len(self.sensory_neurons))
			print "Size of the input array and number of the sensory neurons are not matching! Please try again"
		else:
			step = 0
			for neuron in self.sensory_neurons:
				neuron.potential = input_arr[step]
				step += 1
		if output_arr is None:
			self.mini_batch = []
			step = 0
			for neuron in self.neurons:
				neuron.desired_potential = None
				step += 1
		else:
			if len(self.motor_neurons) != len(output_arr):
				print "Size of the output/target array: " + str(len(output_arr))
				print "Number of the motor_neurons: " + str(len(self.motor_neurons))
				print "Size of the output/target array and number of the motor neurons are not matching! Please try again"
			else:
				step = 0
				for neuron in self.motor_neurons:
					neuron.desired_potential = output_arr[step]
					step += 1
				self.mini_batch.append([input_arr,output_arr])
				if len(self.mini_batch) > self.reasoning_length:
					self.mini_batch.pop(0)

	def get_output(self):
		output = []
		for neuron in self.motor_neurons:
			output.append( round(neuron.potential, self.precision) )
		return output

	def visualize(self):
		thread = threading.Thread(target=self._visualize)
		thread.start()
		print "Visualization initiated"

	def _visualize(self):
		from pyqtgraph.Qt import QtGui, QtCore
		import pyqtgraph as pg

		app = QtGui.QApplication([])
		win = pg.GraphicsWindow(title="Visualization of the Network")
		win.resize(1000,600)

		pg.setConfigOptions(antialias=True)

		plot = win.addPlot(title="the Network in the Form of a Scatter Plot")
		#plot.addLegend()

		plot.plot(x=[1], y=[1,2,3,4], pen=None, symbolBrush=(250,194,5), symbolPen='w', symbol='t1', symbolSize=14, name="sensory neuron")
		plot.plot(x=[2], y=[1,2,3,4,5,6,7,8], pen=None, symbolBrush=(195,46,212), symbolPen='w', symbol='h', symbolSize=14, name="interneuron")
		plot.plot(x=[3], y=[1,2,3,4,5,6,7,8], pen=None, symbolBrush=(195,46,212), symbolPen='w', symbol='h', symbolSize=14, name="interneuron")
		plot.plot(x=[4], y=[1,2], pen=None, symbolBrush=(19,234,201), symbolPen='w', symbol='s', symbolSize=14, name="motor neuron")

		plot.plot(x=[2,3], y=[4,6], pen=(195,46,212), symbolBrush=None, symbolPen='w', symbol='h', symbolSize=14, name="connection")
		plot.plot(x=[2,2], y=[4,6], pen=(195,46,212), symbolBrush=None, symbolPen='w', symbol='h', symbolSize=14, name="connection")

		plot.setXRange(0, 4)

		import sys
		if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
			QtGui.QApplication.instance().exec_()
<|endoftext|>


<commit_before>import random
import sys
import math
import threading
import time

class Neuron():

	def __init__(self,network):
		self.network = network
		self.subscriptions = {}
		self.publications = {}
		self.potential = random.uniform(0.0, 1.0)
		self.desired_potential = None
		self.loss = None
		self.type = 0
		self.network.neurons.append(self)
		self.fire_counter = 0
		self.ban_counter = 0
		self.position = (None, None)
		self.index = None

	def partially_subscribe(self):
		if len(self.subscriptions) == 0:
			sample_length = int(random.normalvariate(self.network.connectivity, self.network.connectivity_sqrt))
			if sample_length > len(self.network.nonmotor_neurons):
				sample_length = len(self.network.nonmotor_neurons)
			if sample_length <= 0: sample_length = 0
			elected = random.sample(self.network.nonmotor_neurons, sample_length)
			for neuron in elected:
				if id(neuron) != id(self):
					self.subscriptions[neuron] = random.uniform(-1.0, 1.0)
					neuron.publications[self] = 0
			self.network.initiated_neurons += 1

	def calculate_potential(self):
		total = 0
		for neuron, weight in self.subscriptions.iteritems():
			total += neuron.potential * weight
		return self.activation_function(total)

	def activation_function(self,x):
		return 1 / (1 + math.exp(-x))

	def derivative(self,x):
		return x*(1-x)

	def calculate_loss(self):
		try:
			return self.potential - self.desired_potential
		except:
			return None

	def fire(self):
		if self.type != 1:

			self.potential = self.calculate_potential()
			self.network.fire_counter += 1
			self.fire_counter += 1

			if self.desired_potential != None:

				self.loss = self.calculate_loss()
				if self.loss > 0:
					alteration_sign = -1
				elif self.loss < 0:
					alteration_sign = 1
				else:
					self.desired_potential = None
					return True

				alteration_value = (abs(self.loss) ** 2)
				alteration_value = alteration_value * (self.network.decay_factor ** (self.network.fire_counter/1000))

				for neuron, weight in self.subscriptions.iteritems():
					neuron.desired_potential = neuron.potential + alteration_sign * self.derivative(neuron.potential)
					self.subscriptions[neuron] = weight + (alteration_value * alteration_sign) * self.derivative(neuron.potential)

class Network():

	def __init__(self,size,input_dim=0,output_dim=0,connectivity=0.01,precision=2,randomly_fire=False,dynamic_output=False,visualization=False):
		self.precision = precision
		print "\nPrecision of the network will be " + str( 1.0 / (10**precision) )
		self.connectivity = int(size * connectivity)
		self.connectivity_sqrt = int(math.sqrt(self.connectivity))
		print "Each individual non-sensory neuron will subscribe to " + str(int(size * connectivity)) + " different neurons"

		self.neurons = []
		for i in range(size):
			Neuron(self)
		print "\n"
		print str(size) + " neurons created"

		self.sensory_neurons = []
		self.input_dim = input_dim
		self.pick_sensory_neurons(self.input_dim)

		self.motor_neurons = []
		self.output_dim = output_dim
		self.pick_motor_neurons(self.output_dim)

		self.nonsensory_neurons = [x for x in self.neurons if x.type is not 1]
		self.nonmotor_neurons = [x for x in self.neurons if x.type is not 2]
		self.interneurons = [x for x in self.neurons if x.type is 0]
		self.randomly_fire = randomly_fire
		self.motor_randomly_fire_rate = int(math.sqrt( len(self.nonsensory_neurons)/len(self.motor_neurons) ))

		self.dynamic_output = dynamic_output

		self.decay_factor = 0.99

		self.initiated_neurons = 0
		self.initiate_subscriptions()

		self.fire_counter = 0
		self.first_queue = {}
		self.next_queue = {}
		self.output = []
		self.wave_counter = 0

		print "\n"

		self.freezer = False
		self.thread1 = None
		self.thread2 = None
		self.thread_kill_signal = False
		if visualization:
			self.visualize()
		self.ignite()

		print ""

	def initiate_subscriptions(self):
		print ""
		for neuron in self.neurons:
			if neuron.type == 1:
				continue
			neuron.partially_subscribe()
			print "Initiated: " + str(self.initiated_neurons) + " neurons\r",
			sys.stdout.flush()
		print "\n"

	def add_neurons(self,units):
		for i in range(units):
			Neuron(self)
		print "\n"
		print str(units) + " neurons added"
		self.initiate_subscriptions()

	def _ignite(self):
		motor_fire_counter = 0
		ban_list = []
		while not self.freezer:
			if self.randomly_fire:
				neuron = random.sample(self.nonsensory_neurons,1)[0]
				if neuron.type == 2:
					if 1 != random.randint(1,self.motor_randomly_fire_rate):
						continue
					else:
						motor_fire_counter += 1
				neuron.fire()
				if motor_fire_counter >= len(self.motor_neurons):
					if self.dynamic_output:
						print "Output: " + str(self.get_output()) + "\r",
						sys.stdout.flush()
					self.output = self.get_output()
					self.wave_counter += 1
					motor_fire_counter = 0

			else:
				if not self.next_queue:
					for neuron in self.motor_neurons:
						neuron.fire()
					for neuron in ban_list:
						neuron.ban_counter = 0
					ban_list = []
					self.output = self.get_output()
					self.wave_counter += 1
					if self.dynamic_output:
						print "Output: " + str(self.output) + "\r",
						sys.stdout.flush()

					if not self.first_queue:
						for neuron in self.sensory_neurons:
							self.first_queue.update(neuron.publications)
					self.next_queue = self.first_queue.copy()

				current_queue = self.next_queue.copy()
				self.next_queue = {}
				for neuron in ban_list:
					if neuron.ban_counter > self.connectivity_sqrt:
						current_queue.pop(neuron, None)
				while current_queue:
					neuron = random.choice(current_queue.keys())
					current_queue.pop(neuron, None)
					if neuron.ban_counter <= self.connectivity_sqrt:
						if neuron.type == 2:
							continue
						neuron.fire()
						ban_list.append(neuron)
						neuron.ban_counter += 1
						self.next_queue.update(neuron.publications)

	def ignite(self):
		self.freezer = False
		if not self.thread1:
			self.thread1 = threading.Thread(target=self._ignite)
			self.thread1.start()
		print "Network has been ignited"

	def freeze(self):
		self.freezer = True
		self.thread1 = None
		self.thread2 = None
		self.thread_kill_signal = True
		print "Network is now frozen"

	def breakit(self):
		for neuron in self.neurons:
			neuron.subscriptions = {}
		print "All the subscriptions are now broken"

	def pick_sensory_neurons(self,input_dim):
		available_neurons = []
		for neuron in self.neurons:
			if neuron.type is 0:
				available_neurons.append(neuron)
		for neuron in random.sample(available_neurons,input_dim):
			neuron.type = 1
			self.sensory_neurons.append(neuron)
		print str(input_dim) + " neuron picked as sensory neuron"

	def pick_motor_neurons(self,output_dim):
		available_neurons = []
		for neuron in self.neurons:
			if neuron.type is 0:
				available_neurons.append(neuron)
		for neuron in random.sample(available_neurons,output_dim):
			neuron.type = 2
			self.motor_neurons.append(neuron)
		print str(output_dim) + " neuron picked as motor neuron"

	def load(self,input_arr,output_arr=None):
		if len(self.sensory_neurons) != len(input_arr):
			print "Size of the input array: " + str(len(input_arr))
			print "Number of the sensory neurons: " + str(len(self.sensory_neurons))
			print "Size of the input array and number of the sensory neurons are not matching! Please try again"
		else:
			step = 0
			for neuron in self.sensory_neurons:
				neuron.potential = input_arr[step]
				step += 1
		if output_arr is None:
			step = 0
			self.freezer = True
			for neuron in self.nonsensory_neurons:
				neuron.desired_potential = None
				step += 1
			self.freezer = False
		else:
			if len(self.motor_neurons) != len(output_arr):
				print "Size of the output/target array: " + str(len(output_arr))
				print "Number of the motor_neurons: " + str(len(self.motor_neurons))
				print "Size of the output/target array and number of the motor neurons are not matching! Please try again"
			else:
				step = 0
				for neuron in self.motor_neurons:
					neuron.desired_potential = output_arr[step]
					step += 1

	def get_output(self):
		output = []
		for neuron in self.motor_neurons:
			output.append( round(neuron.potential, self.precision) )
		return output

	def visualize(self):
		self.thread2 = threading.Thread(target=self._visualize)
		self.thread2.start()
		print "Visualization initiated"

	def _visualize(self):
		import pyqtgraph as pg
		from pyqtgraph.Qt import QtCore, QtGui
		import numpy as np

		# Enable antialiasing for prettier plots
		pg.setConfigOptions(antialias=True)

		w = pg.GraphicsWindow()
		w.setWindowTitle('Visualization of the Network')
		v = w.addViewBox()
		v.setAspectLocked()

		g = pg.GraphItem()
		v.addItem(g)

		positions = []
		symbols = []
		symbol_brushes = []
		x = 0
		y = 0

		x += 1
		for neuron in self.sensory_neurons:
			y += 1
			neuron.position = (x, y)
			#plot.plot(x=[neuron.position[0]], y=[neuron.position[1]], pen=None, symbolBrush=(250,194,5), symbolPen='w', symbol='t1', symbolSize=14, name="sensory neuron")
			positions.append(neuron.position)
			symbols.append('t')
			symbol_brushes.append((250,194,5))
			neuron.index = len(positions) - 1

		x += 1
		y = 0
		for neuron in self.interneurons:
			neuron.position = (random.uniform(x, round(math.sqrt(len(self.interneurons)))+1), random.uniform(y+1, round(math.sqrt(len(self.interneurons)))+1))
			#plot.plot(x=[neuron.position[0]], y=[neuron.position[1]], pen=None, symbolBrush=(195,46,212), symbolPen='w', symbol='h', symbolSize=14, name="interneuron")
			positions.append(neuron.position)
			symbols.append('h')
			symbol_brushes.append((195,46,212))
			neuron.index = len(positions) - 1

		x = round(math.sqrt(len(self.interneurons)))+2
		y = 0
		for neuron in self.motor_neurons:
			y += 1
			neuron.position = (x, y)
			#plot.plot(x=[neuron.position[0]], y=[neuron.position[1]], pen=None, symbolBrush=(19,234,201), symbolPen='w', symbol='s', symbolSize=14, name="motor neuron")
			positions.append(neuron.position)
			symbols.append('s')
			symbol_brushes.append((19,234,201))
			neuron.index = len(positions) - 1

		while True:
			connections = []
			lines = []
			for neuron2 in self.neurons:
				for neuron1, weight in neuron2.subscriptions.iteritems():
					connections.append((neuron1.index, neuron2.index))
					lines.append((55,55,55,((weight+1)/2)*255,(weight+1)))

			positions = np.asarray(positions)
			connections = np.asarray(connections)
			lines = np.asarray(lines, dtype=[('red',np.ubyte),('green',np.ubyte),('blue',np.ubyte),('alpha',np.ubyte),('width',float)])
			g.setData(pos=positions, adj=connections, pen=lines, size=0.1, symbolBrush=symbol_brushes, symbol=symbols, pxMode=False) # Update the graph

			pg.QtGui.QApplication.processEvents()
			if self.thread_kill_signal:
				break
			time.sleep(0.0333)
<commit_msg>Make decay factor optional<commit_after>import random
import sys
import math
import threading
import time

class Neuron():

	def __init__(self,network):
		self.network = network
		self.subscriptions = {}
		self.publications = {}
		self.potential = random.uniform(0.0, 1.0)
		self.desired_potential = None
		self.loss = None
		self.type = 0
		self.network.neurons.append(self)
		self.fire_counter = 0
		self.ban_counter = 0
		self.position = (None, None)
		self.index = None

	def partially_subscribe(self):
		if len(self.subscriptions) == 0:
			sample_length = int(random.normalvariate(self.network.connectivity, self.network.connectivity_sqrt))
			if sample_length > len(self.network.nonmotor_neurons):
				sample_length = len(self.network.nonmotor_neurons)
			if sample_length <= 0: sample_length = 0
			elected = random.sample(self.network.nonmotor_neurons, sample_length)
			for neuron in elected:
				if id(neuron) != id(self):
					self.subscriptions[neuron] = random.uniform(-1.0, 1.0)
					neuron.publications[self] = 0
			self.network.initiated_neurons += 1

	def calculate_potential(self):
		total = 0
		for neuron, weight in self.subscriptions.iteritems():
			total += neuron.potential * weight
		return self.activation_function(total)

	def activation_function(self,x):
		return 1 / (1 + math.exp(-x))

	def derivative(self,x):
		return x*(1-x)

	def calculate_loss(self):
		try:
			return self.potential - self.desired_potential
		except:
			return None

	def fire(self):
		if self.type != 1:

			self.potential = self.calculate_potential()
			self.network.fire_counter += 1
			self.fire_counter += 1

			if self.desired_potential != None:

				self.loss = self.calculate_loss()
				if self.loss > 0:
					alteration_sign = -1
				elif self.loss < 0:
					alteration_sign = 1
				else:
					self.desired_potential = None
					return True

				alteration_value = (abs(self.loss) ** 2)
				alteration_value = alteration_value * (self.network.decay_factor ** (self.network.fire_counter/1000))

				for neuron, weight in self.subscriptions.iteritems():
					neuron.desired_potential = neuron.potential + alteration_sign * self.derivative(neuron.potential)
					self.subscriptions[neuron] = weight + (alteration_value * alteration_sign) * self.derivative(neuron.potential)

class Network():

	def __init__(self,size,input_dim=0,output_dim=0,connectivity=0.01,precision=2,randomly_fire=False,dynamic_output=False,visualization=False,decay_factor=1.0):
		self.precision = precision
		print "\nPrecision of the network will be " + str( 1.0 / (10**precision) )
		self.connectivity = int(size * connectivity)
		self.connectivity_sqrt = int(math.sqrt(self.connectivity))
		print "Each individual non-sensory neuron will subscribe to " + str(int(size * connectivity)) + " different neurons"

		self.neurons = []
		for i in range(size):
			Neuron(self)
		print "\n"
		print str(size) + " neurons created"

		self.sensory_neurons = []
		self.input_dim = input_dim
		self.pick_sensory_neurons(self.input_dim)

		self.motor_neurons = []
		self.output_dim = output_dim
		self.pick_motor_neurons(self.output_dim)

		self.nonsensory_neurons = [x for x in self.neurons if x.type is not 1]
		self.nonmotor_neurons = [x for x in self.neurons if x.type is not 2]
		self.interneurons = [x for x in self.neurons if x.type is 0]
		self.randomly_fire = randomly_fire
		self.motor_randomly_fire_rate = int(math.sqrt( len(self.nonsensory_neurons)/len(self.motor_neurons) ))

		self.dynamic_output = dynamic_output

		self.decay_factor = decay_factor

		self.initiated_neurons = 0
		self.initiate_subscriptions()

		self.fire_counter = 0
		self.first_queue = {}
		self.next_queue = {}
		self.output = []
		self.wave_counter = 0

		print "\n"

		self.freezer = False
		self.thread1 = None
		self.thread2 = None
		self.thread_kill_signal = False
		if visualization:
			self.visualize()
		self.ignite()

		print ""

	def initiate_subscriptions(self):
		print ""
		for neuron in self.neurons:
			if neuron.type == 1:
				continue
			neuron.partially_subscribe()
			print "Initiated: " + str(self.initiated_neurons) + " neurons\r",
			sys.stdout.flush()
		print "\n"

	def add_neurons(self,units):
		for i in range(units):
			Neuron(self)
		print "\n"
		print str(units) + " neurons added"
		self.initiate_subscriptions()

	def _ignite(self):
		motor_fire_counter = 0
		ban_list = []
		while not self.freezer:
			if self.randomly_fire:
				neuron = random.sample(self.nonsensory_neurons,1)[0]
				if neuron.type == 2:
					if 1 != random.randint(1,self.motor_randomly_fire_rate):
						continue
					else:
						motor_fire_counter += 1
				neuron.fire()
				if motor_fire_counter >= len(self.motor_neurons):
					if self.dynamic_output:
						print "Output: " + str(self.get_output()) + "\r",
						sys.stdout.flush()
					self.output = self.get_output()
					self.wave_counter += 1
					motor_fire_counter = 0

			else:
				if not self.next_queue:
					for neuron in self.motor_neurons:
						neuron.fire()
					for neuron in ban_list:
						neuron.ban_counter = 0
					ban_list = []
					self.output = self.get_output()
					self.wave_counter += 1
					if self.dynamic_output:
						print "Output: " + str(self.output) + "\r",
						sys.stdout.flush()

					if not self.first_queue:
						for neuron in self.sensory_neurons:
							self.first_queue.update(neuron.publications)
					self.next_queue = self.first_queue.copy()

				current_queue = self.next_queue.copy()
				self.next_queue = {}
				for neuron in ban_list:
					if neuron.ban_counter > self.connectivity_sqrt:
						current_queue.pop(neuron, None)
				while current_queue:
					neuron = random.choice(current_queue.keys())
					current_queue.pop(neuron, None)
					if neuron.ban_counter <= self.connectivity_sqrt:
						if neuron.type == 2:
							continue
						neuron.fire()
						ban_list.append(neuron)
						neuron.ban_counter += 1
						self.next_queue.update(neuron.publications)

	def ignite(self):
		self.freezer = False
		if not self.thread1:
			self.thread1 = threading.Thread(target=self._ignite)
			self.thread1.start()
		print "Network has been ignited"

	def freeze(self):
		self.freezer = True
		self.thread1 = None
		self.thread2 = None
		self.thread_kill_signal = True
		print "Network is now frozen"

	def breakit(self):
		for neuron in self.neurons:
			neuron.subscriptions = {}
		print "All the subscriptions are now broken"

	def pick_sensory_neurons(self,input_dim):
		available_neurons = []
		for neuron in self.neurons:
			if neuron.type is 0:
				available_neurons.append(neuron)
		for neuron in random.sample(available_neurons,input_dim):
			neuron.type = 1
			self.sensory_neurons.append(neuron)
		print str(input_dim) + " neuron picked as sensory neuron"

	def pick_motor_neurons(self,output_dim):
		available_neurons = []
		for neuron in self.neurons:
			if neuron.type is 0:
				available_neurons.append(neuron)
		for neuron in random.sample(available_neurons,output_dim):
			neuron.type = 2
			self.motor_neurons.append(neuron)
		print str(output_dim) + " neuron picked as motor neuron"

	def load(self,input_arr,output_arr=None):
		if len(self.sensory_neurons) != len(input_arr):
			print "Size of the input array: " + str(len(input_arr))
			print "Number of the sensory neurons: " + str(len(self.sensory_neurons))
			print "Size of the input array and number of the sensory neurons are not matching! Please try again"
		else:
			step = 0
			for neuron in self.sensory_neurons:
				neuron.potential = input_arr[step]
				step += 1
		if output_arr is None:
			step = 0
			self.freezer = True
			for neuron in self.nonsensory_neurons:
				neuron.desired_potential = None
				step += 1
			self.freezer = False
		else:
			if len(self.motor_neurons) != len(output_arr):
				print "Size of the output/target array: " + str(len(output_arr))
				print "Number of the motor_neurons: " + str(len(self.motor_neurons))
				print "Size of the output/target array and number of the motor neurons are not matching! Please try again"
			else:
				step = 0
				for neuron in self.motor_neurons:
					neuron.desired_potential = output_arr[step]
					step += 1

	def get_output(self):
		output = []
		for neuron in self.motor_neurons:
			output.append( round(neuron.potential, self.precision) )
		return output

	def visualize(self):
		self.thread2 = threading.Thread(target=self._visualize)
		self.thread2.start()
		print "Visualization initiated"

	def _visualize(self):
		import pyqtgraph as pg
		from pyqtgraph.Qt import QtCore, QtGui
		import numpy as np

		# Enable antialiasing for prettier plots
		pg.setConfigOptions(antialias=True)

		w = pg.GraphicsWindow()
		w.setWindowTitle('Visualization of the Network')
		v = w.addViewBox()
		v.setAspectLocked()

		g = pg.GraphItem()
		v.addItem(g)

		positions = []
		symbols = []
		symbol_brushes = []
		x = 0
		y = 0

		x += 1
		for neuron in self.sensory_neurons:
			y += 1
			neuron.position = (x, y)
			#plot.plot(x=[neuron.position[0]], y=[neuron.position[1]], pen=None, symbolBrush=(250,194,5), symbolPen='w', symbol='t1', symbolSize=14, name="sensory neuron")
			positions.append(neuron.position)
			symbols.append('t')
			symbol_brushes.append((250,194,5))
			neuron.index = len(positions) - 1

		x += 1
		y = 0
		for neuron in self.interneurons:
			neuron.position = (random.uniform(x, round(math.sqrt(len(self.interneurons)))+1), random.uniform(y+1, round(math.sqrt(len(self.interneurons)))+1))
			#plot.plot(x=[neuron.position[0]], y=[neuron.position[1]], pen=None, symbolBrush=(195,46,212), symbolPen='w', symbol='h', symbolSize=14, name="interneuron")
			positions.append(neuron.position)
			symbols.append('h')
			symbol_brushes.append((195,46,212))
			neuron.index = len(positions) - 1

		x = round(math.sqrt(len(self.interneurons)))+2
		y = 0
		for neuron in self.motor_neurons:
			y += 1
			neuron.position = (x, y)
			#plot.plot(x=[neuron.position[0]], y=[neuron.position[1]], pen=None, symbolBrush=(19,234,201), symbolPen='w', symbol='s', symbolSize=14, name="motor neuron")
			positions.append(neuron.position)
			symbols.append('s')
			symbol_brushes.append((19,234,201))
			neuron.index = len(positions) - 1

		while True:
			connections = []
			lines = []
			for neuron2 in self.neurons:
				for neuron1, weight in neuron2.subscriptions.iteritems():
					connections.append((neuron1.index, neuron2.index))
					lines.append((55,55,55,((weight+1)/2)*255,(weight+1)))

			positions = np.asarray(positions)
			connections = np.asarray(connections)
			lines = np.asarray(lines, dtype=[('red',np.ubyte),('green',np.ubyte),('blue',np.ubyte),('alpha',np.ubyte),('width',float)])
			g.setData(pos=positions, adj=connections, pen=lines, size=0.1, symbolBrush=symbol_brushes, symbol=symbols, pxMode=False) # Update the graph

			pg.QtGui.QApplication.processEvents()
			if self.thread_kill_signal:
				break
			time.sleep(0.0333)
<|endoftext|>