def update(self, *, sigma1=0.1, weight1=0, sigma2=0.1, weight2=0, offset=0): print('U') pixelScale = -self.seq.fft_width_px * self.seq.fft_height_px / self.seq.getSpatialFilteredFieldWidth_um( ) / self.seq.getSpatialFilteredFieldHeight_um() sigma1 = 1 / 6.283185307179586476925286766559 / sigma1 weight1 = weight1 * pixelScale sigma2 = 1 / 6.283185307179586476925286766559 / sigma2 weight2 = weight2 * pixelScale offset = -offset Component.update( self, sigma1=sigma1, weight1=weight1, sigma2=sigma2, weight2=weight2, offset=offset, ) self.width_um = sigma1 * 5 + 20 self.height_um = sigma1 * 5 + 20 self.maximum = weight1 / ( sigma1 * 6.283185307179586476925286766559 * sigma1) + weight2 / ( sigma2 * 6.283185307179586476925286766559 * sigma2) self.minimum = self.maximum * -0.125 gears.updateSpatialKernel()
def onWheel(self, event, owner): if self.keyDown: if self.isDirection: self.angle += event.deltaY() * self.step / 120 if self.angle > self.maximum: self.angle = self.maximum if self.angle < self.minimum: self.angle = self.minimum self.value = (math.cos(self.angle), math.sin(self.angle)) gears.setText( self.label, "[{key}]+wheel: {label}: {value} {unit}, step {step} {unit}" .format(key=self.key, label=self.label, value=self.angle, unit=self.unit, step=self.step)) else: self.value += event.deltaY() * self.step / 120 if self.value > self.maximum: self.value = self.maximum if self.value < self.minimum: self.value = self.minimum gears.setText( self.label, "[{key}]+wheel: {label}: {value} {unit}, step {step} {unit}" .format(key=self.key, label=self.label, value=self.value, unit=self.unit, step=self.step)) owner.refresh()
def start(self, launcherWindow): print("Starting media window.") print(datetime.datetime.now().time()) self.launcherWindow = launcherWindow sequence = gears.getSequence().getPythonObject() self.expectedFrameInterval_s = sequence.getFrameInterval_s() self.measuredFrameInterval_s = self.expectedFrameInterval_s self.gracePeriodForFpsMeasurement = 60 if sequence.getUsesBusyWaitingThreadForSingals(): self.ticker = gears.startTicker() else: self.ticker = None self.timer = QTimer(self) self.timer.setInterval(0) self.timer.timeout.connect(self.onTimer) self.stimulusWindow.mediaWindow = self self.timer.start() self.firstFrame = True self.setFocus() print("Showing media window.") print(datetime.datetime.now().time()) self.showFullScreen()
def onWheel(self, event) : stimulus = self.spass.getStimulus() sequence = stimulus.getSequence().getPythonObject() if self.speedKeyDown : travelLength = math.fabs(sequence.field_width_um * self.facing[0]) + math.fabs(sequence.field_height_um * self.facing[1]) + self.shapeLength_um currentOffs = self.fmod(self.time + self.phase, self.radius * 2) - self.radius currentOffs *= self.speed self.speed += event.deltaY() * self.speedStep / 120 if self.speed < self.minSpeed: self.speed = self.minSpeed if self.speed > self.maxSpeed: self.speed = self.maxSpeed if self.speed > 0.01 : self.radius = travelLength / self.speed / 2 currentOffs /= self.speed elif self.speed < -0.01 : self.radius = travelLength / -self.speed / 2 currentOffs /= self.speed self.phase = self.fmod((currentOffs + self.radius) - self.time, self.radius * 2) gears.setText("speed", "[V]+wheel: speed: {speed} um/s in[{minSpeed},{maxSpeed}], step {step}".format(speed = self.speed, minSpeed=self.minSpeed, maxSpeed = self.maxSpeed, step=self.speedStep)) elif self.angleKeyDown : self.angle += event.deltaY() * self.angleStep / 120 self.facing = (math.cos(self.angle), math.sin(self.angle)) gears.setText("direction", "[D]+wheel: angle: {angle} radians, step {step}".format(angle = self.angle, step=self.angleStep))
def render(self, iFrame): #TODO handle skipped frames self.time += self.speed #self.time = 0.1 * iFrame glEnable(GL_DEPTH_TEST) glDepthMask(GL_TRUE) glClearColor(0.0, 0, 0.0, 1.0 ) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(45, 1, 0.1, 1000) glMatrixMode(GL_MODELVIEW) glLoadIdentity() pos, vel = self.kbSpline.get(self.time) #gluLookAt(16, 0.5, 20- iFrame * 0.1, 16, 0.5, 19 - iFrame * 0.1, 0, 1, 0) #print(pos) gluLookAt(pos[0], pos[1], pos[2], pos[0]+vel[0], pos[1]+vel[1], pos[2]+vel[2], 0, 1, 0) #print("{t}: {x}, {y}, {z}".format( t=iFrame, x=pos[0], y=pos[1], z=pos[2])) glEnable(GL_TEXTURE_2D) glActiveTexture(GL_TEXTURE0) #gears.bindTexture('./Project/Media/leopard.png') gears.bindTexture('./Project/Media/tron.jpg') glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) glCallList(self.glist) glDisable(GL_DEPTH_TEST) glDepthMask(GL_FALSE);
def update(self, *, sigma1=0.1, weight1=0, sigma2=0.1, weight2=0, offset=0, pixelScale=1): sigma1 = 1 / 6.283185307179586476925286766559 / sigma1 weight1 = weight1 * pixelScale sigma2 = 1 / 6.283185307179586476925286766559 / sigma2 weight2 = weight2 * pixelScale offset = -offset Component.update( self, sigma1=sigma1, weight1=weight1, sigma2=sigma2, weight2=weight2, offset=offset, ) self.width_um = sigma1 * 5 + 20 self.height_um = sigma1 * 5 + 20 self.maximum = weight1 / ( sigma1 * 6.283185307179586476925286766559 * sigma1) + weight2 / ( sigma2 * 6.283185307179586476925286766559 * sigma2) self.minimum = self.maximum * -0.125 gears.updateSpatialKernel()
def update(self, *, sigma1=0.1, weight1=0, sigma2=0.1, weight2=0, offset=0): Component.update( self, sigma1=sigma1, weight1=weight1, sigma2=sigma2, weight2=weight2, offset=offset, ) #self.setShaderVariable(name="sigma1", value=sigma1) #self.setShaderVariable(name="weight1", value=weight1) #self.setShaderVariable(name="sigma2", value=sigma2) #self.setShaderVariable(name="weight2", value=weight2) #self.setShaderVariable(name="offset", value=offset) self.width_um = sigma1 * 5 self.height_um = sigma1 * 5 self.maximum = weight1 / ( sigma1 * 6.283185307179586476925286766559 * sigma1) + weight2 / ( sigma2 * 6.283185307179586476925286766559 * sigma2) self.minimum = self.maximum * -0.125 gears.updateSpatialKernel()
def update(self, *, halfEdge_um=1): Component.update(self, halfEdge_um=halfEdge_um) self.width_um = halfEdge_um * 4 self.height_um = halfEdge_um * 4 self.maximum = 0.25 / (halfEdge_um * halfEdge_um) self.minimum = self.maximum * -0.125 gears.updateSpatialKernel()
def applyWithArgs( self, stimulus, ) : stimulus.enableColorMode() stimulus.setForwardRenderingCallback(self.render) stimulus.registerCallback(gears.BeginStimulus(), self.start) stimulus.registerCallback(gears.FinishStimulus(), self.finish )
def onKey(self, event): if event.text() == 'D': self.angleKeyDown = True elif event.text() == ' ': gears.setText( "direction", "[D]+wheel: angle: {angle} radians, step {step}".format( angle=self.angle, step=self.angleStep))
def update(self, *, R=1000, r=10): Component.update(self, R=R, r=r) self.width_um = R * 2 self.height_um = R * 2 self.maximum = 1 self.minimum = 0 gears.updateSpatialKernel()
def applyWithArgs( self, spass, functionName, *, size_um: 'Dimensions of the rectangle shape, as a (width, height) pair [um,um].' = ( 2000, 200), facing: "The shape orientation in radians (or 'east', 'northeast', 'north', 'northwest', 'west', 'southwest', 'south', or 'southeast')" = 'east', follow_distance_um: 'Distance between instances of the rectangle along the width axis [um].' = 100000000, wingmen_distance_um: 'Distance between instances of the rectangle along the height axis [um].' = 100000000, filterRadius_um: 'Antialiasing filter size [um] (shape blur).' = 0.1 ): facing = processDirection(facing, self.tb) s = math.sin(facing) c = math.cos(facing) spass.setShaderVector(name=functionName + '_rect', x=size_um[0], y=size_um[1]) spass.setShaderVector(name=functionName + '_facing', x=c, y=s) spass.setShaderVector(name=functionName + '_repetitionDistance', x=follow_distance_um, y=wingmen_distance_um) spass.setShaderVariable(name=functionName + '_filterRadius', value=filterRadius_um) spass.setShaderFunction(name=functionName, src=self.glslEsc(''' vec3 @<X>@ (vec2 x, float time){ vec2 rotatedX = vec2( x.x * `facing.x + x.y * `facing.y, x.x * `facing.y - x.y * `facing.x); rotatedX = mod(rotatedX + `repetitionDistance*0.5 , `repetitionDistance) - `repetitionDistance * 0.5; float xDiff = abs(rotatedX.x) - `rect.x * 0.5; float yDiff = abs(rotatedX.y) - `rect.y * 0.5; // Figure/MouseRect.py float inOrOut = (1-smoothstep( -`filterRadius, +`filterRadius, xDiff )) * (1-smoothstep( -`filterRadius, +`filterRadius, yDiff )); return vec3(inOrOut, inOrOut, inOrOut); } ''').format(X=functionName)) self.functionName = functionName self.spass = spass stimulus = spass.getStimulus().getPythonObject() stimulus.registerCallback(gears.WheelEvent.typeId, self.onWheel) stimulus.registerCallback(gears.KeyPressedEvent.typeId, self.onKey) stimulus.registerCallback(gears.KeyReleasedEvent.typeId, self.onKeyUp) stimulus.registerCallback(gears.FrameEvent.typeId, self.onFrame) self.angleStep = 0.1 self.angle = 0 self.facing = (1, 0) self.angleKeyDown = False gears.setText( "direction", "[D]+wheel: angle: {angle} radians, step {step}".format( angle=self.angle, step=self.angleStep))
def applyWithArgs( self, patch, *, size_um: 'Dimensions of the rectangle shape, as a (width, height) pair [um,um].' = ( 2000, 200), facing: "The shape orientation in radians (or 'east', 'northeast', 'north', 'northwest', 'west', 'southwest', 'south', or 'southeast')" = 'east', follow_distance_um: 'Distance between instances of the rectangle along the width axis [um].' = 100000000, wingmen_distance_um: 'Distance between instances of the rectangle along the height axis [um].' = 100000000, filterRadius_um: 'Antialiasing filter size [um] (shape blur).' = 0.1 ): facing = processDirection(facing, self.tb) s = math.sin(facing) c = math.cos(facing) patch.setShaderVector(name='rect', x=size_um[0], y=size_um[1]) patch.setShaderVector(name='facing', x=c, y=s) patch.setShaderVector(name='repetitionDistance', x=follow_distance_um, y=wingmen_distance_um) patch.setShaderVector(name='rect', x=size_um[0], y=size_um[1]) patch.setShaderVariable(name='filterRadius', value=filterRadius_um) patch.setShaderFunction(name='shape', src=''' vec3 shape(vec2 x){ vec2 rotatedX = vec2( x.x * facing.x + x.y * facing.y, x.x * facing.y - x.y * facing.x); rotatedX = mod(rotatedX + repetitionDistance*0.5 , repetitionDistance) - repetitionDistance * 0.5; float xDiff = abs(rotatedX.x) - rect.x * 0.5; float yDiff = abs(rotatedX.y) - rect.y * 0.5; // PatternYard/Shape/MouseRect.py float inOrOut = (1-smoothstep( -filterRadius, +filterRadius, xDiff )) * (1-smoothstep( -filterRadius, +filterRadius, yDiff )); return vec3(inOrOut, inOrOut, inOrOut); } ''') self.patch = patch stimulus = patch.getStimulus().getPythonObject() #stimulus.onMouse += [ self.onMouse ] #stimulus.onMouseClick += [ self.onMouseClick ] #self.prevX = 0 #self.prevY = 0 stimulus.registerCallback(gears.WheelEvent.typeId, self.onWheel) stimulus.registerCallback(gears.KeyPressedEvent.typeId, self.onKey) stimulus.registerCallback(gears.KeyReleasedEvent.typeId, self.onKeyUp) stimulus.registerCallback(gears.FrameEvent.typeId, self.onFrame) self.angleStep = 0.1 self.angle = 0 self.facing = (1, 0) self.angleKeyDown = False gears.setText( "direction", "[D]+wheel: angle: {angle} radians, step {step}".format( angle=self.angle, step=self.angleStep))
def onWheel(self, event): sequence = self.spass.getSequence().getPythonObject() if self.angleKeyDown: self.angle += event.deltaY() * self.angleStep / 120 self.facing = (math.cos(self.angle), math.sin(self.angle)) gears.setText( "direction", "[D]+wheel: angle: {angle} radians, step {step}".format( angle=self.angle, step=self.angleStep))
def onKey(self, event): if event.text() == 'O': self.speed = 0 elif event.text() == ' ': gears.setText("speed", "[V]+wheel: speed: {speed} um/s in[{minSpeed},{maxSpeed}], step {step}".format(speed = self.speed, minSpeed=self.minSpeed, maxSpeed = self.maxSpeed, step=self.speedStep)) gears.setText("direction", "[D]+wheel: angle: {angle} radians, step {step}".format(angle = self.angle, step=self.angleStep)) elif event.text() == 'V': self.speedKeyDown = True elif event.text() == 'D': self.angleKeyDown = True
def stop(self): self.timer.stop() sequence = gears.getSequence().getPythonObject() if self.ticker: self.ticker.stop() self.launcherWindow.wake() QApplication.instance().processEvents() gears.reset() self.hide() self.lower()
def paintGL(self): #self.painter = QPainter(self) #self.painter.beginNativePainting() gears.drawStimulusTimeline(self.margin, 0, self.width - self.margin, self.height) #self.painter.endNativePainting() emHeight = self.fontMetrics.height() emWidth = self.fontMetrics.width('M') self.renderText(0, self.height * (0.1), 'Intensity') self.renderText(self.margin - emWidth, self.height * 0.0 + emHeight * 0.5, '1') self.renderText(self.margin - 2 * emWidth, self.height * 0.2 + emHeight * 0.25, '0.5') self.renderText(self.margin - emWidth, self.height * 0.4 + emHeight * 0.0, '0') stim = gears.getSelectedStimulus() expr = gears.getSequence() channels = expr.getChannels() nChannels = stim.getChannelCount() i = 0 for channel in channels: if stim.usesChannel(channel.key()): if channel.data().raiseFunc == 3 or channel.data( ).raiseFunc == 4: signal = 'RTS' elif channel.data().raiseFunc == 8 or channel.data( ).raiseFunc == 9: signal = 'BREAK' elif channel.data().raiseFunc == 5 or channel.data( ).raiseFunc == 6: signal = 'DTR' else: signal = '???' channelZoneHeight = self.height / 2 / nChannels lpos = self.height * 0.5 + channelZoneHeight * i self.renderText(0, lpos + channelZoneHeight * 0.5, channel.key()) self.renderText( 0, lpos + channelZoneHeight * 0.5 + emHeight * 0.5, channel.data().portName + ':' + signal, QFont('Candara', 6)) self.renderText( self.margin - emWidth, lpos + channelZoneHeight * 0.5 + emHeight * 0.25, '1') self.renderText( self.margin - emWidth, lpos + channelZoneHeight * 0.75 + emHeight * 0.25, '0') i += 1 #stim = gears.getSelectedStimulus() #self.renderText(stim.data().getStartingFrame() * self.width / expr.getDuration(), 50, str(stim.data().getDuration()) ) self.painter = None
def onMouseReleasedLeft(self, event): seq = self.getSequence() x = event.globalPercentX() * seq.field_width_um - seq.field_width_um / 2 y = -(event.globalPercentY() * seq.field_height_um - seq.field_height_um / 2) for button in self.buttons: if (button[1] - button[3] / 2 < x < button[1] + button[3] / 2 and button[2] - button[4] / 2 < y < button[2] + button[4] / 2): print(button[0]) ILog.log.put("@{time} s: {var} = {value}".format( time=gears.getTime(), var=self.question, value=button[0])) gears.setResponded()
def onKey(self, event): print(event.text()) for button in self.buttons: if event.text() == button[5]: print("@{time} s: {var} = {value}".format(time=gears.getTime(), var=self.question, value=button[0])) ILog.log.put("@{time} s: {var} = {value}".format( time=gears.getTime(), var=self.question, value=button[0])) gears.setResponded() return True return False
def setDirection(self): self.isDirection = True self.angle = processDirection(self.value, None) self.value = (math.cos(self.angle), math.sin(self.angle)) gears.setText( self.label, "[{key}]+wheel: {label}: {value} {unit}, step {step} {unit}". format(key=self.key, label=self.label, value=self.angle, unit=self.unit, step=self.step))
def mousePressEvent(self, e): if e.button() == Qt.LeftButton: expr = gears.getSequence() if e.pos().x() - self.margin < 0: gears.toggleChannelsOrPreview() else: gears.pickStimulus( ((e.pos().x() - self.margin) / (self.width - self.margin) * self.sequenceTimelineZoom + self.sequenceTimelineStartFrame) / expr.getDuration(), e.pos().y() / self.height) self.launcher.stimulusChanged() self.prevMouseX = e.x()
def applyWithArgs( self, stimulus, *, controlPoints : 'list of Kohanek-Bertels control points for camera movement. Every entry is a tuple (t, x, y, z, tension, bias).' #= [(0, 10, 0.5, 10, 0.9, 0.5), (120, 22, 0.5, 22, 0.9, 0.5), (240, 10, 0.5, 22, 0.9, 0.5)], #= [(0, 10, 0.5, 10, 0, 0.5), (180, 22, 0.5, 22, 0, 0.5)], = [(0, 10, 2.5, 10, 0, 0.5), (20, 20, 2.5, 10, 0, 0.5), (240, 20, 2.5, 20, 0, 0.5)], loopTime : '' = 360, minSpeed = -1, maxSpeed = 1, grid : '' = """XXXXXXXXXXXXXXXX X X X X X X X X X X X X X X XXX XX X X X X X X X X XX XX XX X X X X X X X XX X X X X X X X X X X X XXXXXXXXXXXXXXXX""" ) : self.kbSpline = KohenekBartels(controlPoints, loopTime) self.grid = grid stimulus.enableColorMode() gears.loadTexture('./Project/Media/tron.jpg') #gears.loadTexture('./Project/Media/leopard.png') stimulus.setForwardRenderingCallback(self.render) stimulus.registerCallback(gears.StimulusStartEvent.typeId, self.start) stimulus.registerCallback(gears.StimulusEndEvent.typeId, self.finish ) stimulus.registerCallback(gears.WheelEvent.typeId, self.onMouseWheel ) stimulus.registerCallback(gears.KeyPressedEvent.typeId, self.onKey ) self.time = 0 self.speed = 0.01 self.minSpeed = minSpeed self.maxSpeed = maxSpeed self.prevX = 0 self.prevY = 0
def applyWithArgs( self, spass, *, brightColor: 'Modulating color at unit modulated intensity.' = 'white', darkColor: 'Modulating color at zero modulated intensity.' = 'black', switches: 'List of time points when intensity is toggled [s]. Negative values are measured back from duration end.' = [ 2, -2 ], weighting: 'Temporal filter used for intensity filtering.' = Temporal. Nop()): duration = spass.getDuration_s() self.switches = [t if t > 0 else duration + t for t in switches] self.brightColor = processColor(brightColor, self.tb) self.darkColor = processColor(darkColor, self.tb) self.stimulus = self.getStimulus() self.weights = weighting.getTemporalWeights(self.stimulus) self.weights.reverse() print(self.weights) spass.setShaderColor(name='globalIntensity', red=0, green=0, blue=0) spass.setShaderFunction( name='intensity', src='vec3 intensity(float time){ return globalIntensity; }') self.stimulus.registerCallback(gears.StimulusFrame(), self.onFrame) self.stimulus.setTemporalWeights( weighting.getTemporalWeights(self.stimulus), False)
def keyReleaseEvent(self, event): stimulus = gears.getCurrentStimulus().getPythonObject() try: for cb in stimulus.onKeyUp: cb(event) except AttributeError: pass
def mousePressEvent(self, event): stimulus = gears.getCurrentStimulus().getPythonObject() try: for cb in stimulus.onMouseClick: cb(event) except AttributeError: pass
def wheelEvent(self, event): stimulus = gears.getCurrentStimulus().getPythonObject() try: for cb in stimulus.onWheel: cb(event) except AttributeError: pass
def onSpecs(self): box = QMessageBox(self) horizontalSpacer = QSpacerItem(1000, 0, QSizePolicy.Minimum, QSizePolicy.Expanding) box.setText(gears.getSpecs()) box.setWindowTitle('System specs') box.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog) box.setStandardButtons(QMessageBox.Ok) box.setDefaultButton(QMessageBox.Ok) layout = box.layout() layout.addItem(horizontalSpacer, layout.rowCount(), 0, 1, layout.columnCount()) box.exec()
def __init__( self, *, initialValue: 'Initial value.' = 1, minimum: 'Minimum.' = 0, maximum: 'Maximum.' = 1, step: 'Step size' = 0, key: 'Mouse wheel control is active when this key is held down.' = 'X', label: 'Text displayed on-screen. Must be unique, or only the last item of the same name is displayed.' = 'Interactive setting' ): super().__init__() self.isDirection = False self.step = step self.maximum = maximum self.minimum = minimum if self.step == 0: self.step = (self.maximum - self.minimum) / 100 self.keyDown = False self.label = label self.key = key self.unit = 'um' self.keyDown = False #try: # self.angle = processDirection(initialValue, None) # self.value = (math.cos(self.angle), math.sin(self.angle)) # gears.setText(self.label, "[{key}]+wheel: {label}: {value} {unit}, step {step} {unit}".format(key = self.key, label=self.label, value=self.angle, unit=self.unit, step=self.step)) #except: self.value = initialValue gears.setText( self.label, "[{key}]+wheel: {label}: {value} {unit}, step {step} {unit}". format(key=self.key, label=self.label, value=self.value, unit=self.unit, step=self.step))
def refresh(self): d = {} for key, control in self.interactiveControls.items(): if isinstance(control, tuple): list = () for i in control: try: list += (i.value, ) ILog.log.put("@{time} s: {var} = {value}".format( time=gears.getTime(), var=i.label, value=i.value)) except: list += (i, ) control = list try: d[key] = control.value ILog.log.put("@{time} s: {var} = {value}".format( time=gears.getTime(), var=control.label, value=control.value)) except: d[key] = control self.update(**d)
def onKey(self, event): if event.text() == self.key: self.keyDown = True elif event.text() == ' ': if self.isDirection: gears.setText( self.label, "[{key}]+wheel: {label}: {value} {unit}, step {step} {unit}" .format(key=self.key, label=self.label, value=self.angle, unit=self.unit, step=self.step)) else: gears.setText( self.label, "[{key}]+wheel: {label}: {value} {unit}, step {step} {unit}" .format(key=self.key, label=self.label, value=self.value, unit=self.unit, step=self.step))