aboutsummaryrefslogtreecommitdiff
path: root/pixelcore/Screen.py
blob: 1bed4f1fa226360bc8a98777a21a4d5ac6fd28f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
from pixelcore.Pixel import * 
from pixelcore.PixelStrip import *
from operationscore.PixelEvent import *
from operationscore.PixelMapper import *
import util.Search as Search
import util.ComponentRegistry as compReg
import util.Strings as Strings
import util.TimeOps as timeops
import itertools
import sys
import pdb
from logger import main_log
class Screen:
    """Class representing a collection of Pixels grouped into PixelStrips.  Needs a
    PixelMapper, currently set via setMapper by may be migrated into the argDict."""
    
    def __init__(self):
        self.responseQueue = []
        self.pixelStrips = []
        self.xSortedPixels = []
        self.xPixelLocs = []
        sizeValid = False 
        self.pixelsSorted = False 
    
    def addStrip(self, strip):
        self.pixelStrips.append(strip)
        self.sizeValid = False #keep track of whether or not our screen size has
        self.pixelsSorted = False
        #been invalidated by adding more pixels
        
    def pixelsInRange(self, minX, maxX):
        """Returns (pixelIndex, pixel).  Does a binary search.  Sorts first if neccesary."""
        if not self.pixelsSorted:
            self.computeXSortedPixels()
        minIndex = Search.find_ge(self.xPixelLocs, minX) 
        maxIndex = Search.find_le(self.xPixelLocs, maxX)+1
        return self.xSortedPixels[minIndex:maxIndex]
        
    def computeXSortedPixels(self):
        self.xSortedPixels = []
        for pixel in self:
            self.xSortedPixels.append((pixel.location[0], pixel))
        self.xSortedPixels.sort()
        self.xPixelLocs = [p[0] for p in self.xSortedPixels]
        self.pixelsSorted = True 
    
    def __iter__(self): #the iterator of all our pixel strips chained togther
        return itertools.chain(*[strip.__iter__() for strip in \
            self.pixelStrips]) #the * operator breaks the list into args 
            
    #SUBVERTING DESIGN FOR EFFICIENCY 1/24/11, RCOH -- It would be cleaner to store the time on the responses
    #themselves, however, it is faster to just pass it in.
    def timeStep(self, currentTime=None):
        """Increments time -- This processes all queued responses, adding that to a queue that will
        be processed on the next time step."""
        if currentTime == None:
            currentTime = timeops.time()
        tempQueue = list(self.responseQueue)
        self.responseQueue = []
        for response in tempQueue:
            self.processResponse(response, currentTime)
        
    #public
    def respond(self, responseInfo):
        self.responseQueue.append(responseInfo)
        
    def getSize(self):
        """Returns the size of the screen in the form: (minx, miny, maxx, maxy)"""
        if self.sizeValid:
            return self.size
        (minX, minY, maxX, maxY) = (sys.maxint,sys.maxint,-sys.maxint,-sys.maxint)
        for light in self:
            (x,y) = light.location
            
            minX = min(x, minX)
            maxX = max(x, maxX)

            minY = min(y, minY)
            maxY = max(y, maxY)
        self.size = (0,0, maxX, maxY)
        self.sizeValid = True
        return (minX, minY, maxX, maxY) 
        
    #private
    def processResponse(self, responseInfo, currentTime=None): #we need to make a new dict for
        #each to prevent interference
        if currentTime == None:
            currentTime = timeops.time()
        if type(responseInfo) != type(dict()):
            pass
        if 'Mapper' in responseInfo:
            mapper = compReg.getComponent(responseInfo['Mapper']) 
        else:
            mapper = compReg.getComponent(Strings.DEFAULT_MAPPER)
        pixelWeightList = mapper.mapEvent(responseInfo['Location'], self)
        main_log.debug('Screen processing response.  ' + str(len(pixelWeightList)) + ' events\
generated')
        PixelEvent.addPixelEventIfMissing(responseInfo)
        for (pixel, weight) in pixelWeightList: 
            pixel.processInput(responseInfo['PixelEvent'], 0,weight, currentTime) #TODO: z-index