Using PsychoPy changing origin coordinate - python

I am trying to make a program that gets Pen coordinate from wacom tablet which I manage to figure out using this:
data = display.Display().screen().root.query_pointer()._data
X = data["root_x"]-cfg['winpos'][0]-(cfg['width']/2)
Y = cfg['height']-(data["root_y"]-cfg['winpos'][1])-(cfg['height']/2)
print "Pen Position is: ", X, Y
but problem is that Psychopy has origin coordinate for screen at the centre please refer to pic:
and i am using a wacom INTUOS PTZ1230 12" 12" tablet which i want (0, 0) to start from regular monitor origin from top refer to second pic.
very long to read but all i need is to change my coordinate system in python using psychopy. thanks any bit helps

Experimenters generally present their stimuli symetrically around the center of the screen so, although top left and bottom left are (both) more conventional for the origin, the center of the screen makes most sense for scientists.
The window does have atributes viewScale and viewPos though. Although they aren't designed quite for this purpose I think you could use viewPos to shift the origin.
Jon

Related

Python OpenGL glRotatef - looking for the correct multiplier

I am using gluLookAt with a camera whose coordinates are xCam, yCam and zCam. The coordinates of the object the camera is looking at are xPos, yPos, and zPos. There are variables named mouseturnX and mouseturnY, which measure the deviation of the mouse from the middle of the screen in the x-axis and the y-axis. The variable camdist describes the distance between camera and the object it looks at.
The code of the cameraposition is this:
xCam = sin(mouseturnX)*camdist+xPos
yCam = mouseturnY+yPos
zCam = cos(mouseturnX)*camdist+zPos
I now made a polygon object, which I rotate with:
glRotatef(mouseturnX,0,1,0)
Usually it should only show me the backside of the object, it does not matter which position the camera has. But now it does not turn correctly. I tried it with other rotation-axises, there it works fine, but with the y-axis it just does not want to work. I tried changing the camdist from positive to negative, the mouseturnX in the glRotatef function from positive to negative and back to positive again. It just does not work. I used glPushMatrix before the rotation command and glPopMatrix after it. One line before the rotation command I used the translate function to set a fixpoint for the polygon.
Edit: The polygon actually spins, but not in the right amount. It seems like I have to multiply the rotation of the polygon with something.
I found the multiplicator by trying. It is 56.5. It is not perfect, but it works.

How to click relative to a window/application in python and how to handle multiple scripts that click?

Is there any way to click relative to an open window? For example, clicking a set amount of pixels to the right/up/left/down of an open tab of google chrome? I know how to click using absolute coordinates, or click on something that matches an image file, but I haven't been able to find anything regarding relative clicking.
Another part to this - when automating some process on a computer that uses the mouse or keyboard to input commands, if you run two or more of the same script, is there a possibility that the commands interrupt each other? Like if you move the mouse and then click, but another script moves it again before the first one is allowed to click? Is there an easy solution for this? What my mind jumps to first is using a queuing process similar to handling multiple processes in an OS.
You can use the library pyautogui.
I put an example here:
import pyautogui as pya
start = pya.locateCenterOnScreen('start.png')#If the file is not a png file it will not work
print(start)
pya.moveTo(start)#Moves the mouse to the coordinates of the image
#even you can make click with
pya.click(button='left',clicks=2,x=start.x,y=start.y) # you can do two click on the image
For anyone in the future coming across this post, using Python to move their mouse relative to a specific windows coordinates:
EASIEST WAY
(Requires pyautogui & pywin32 (win32gui successor))
Step 1: Get the HWND or the 'ID' of the 'Active Window' you want to move your mouse relative to:
hwnd = win32gui.FindWindow(None, 'Untitled - Notepad')
Step 2: Now let's get the global X and Y coordinates of the top left and bottom right corner of this app to determine where it is on your screen at the moment:
x0, y0, x1, y1 = win32gui.GetWindowRect(hwnd)
You can also get the dimensions of the window here as well:
w = x1 - x0 # width
h = y1 - y0 # height
Step 3: We only need the X0 and Y0 (top left corner global coordinates on our screen), so return those if you put this in its own method
Step 4: All you have to do now is create a custom method to moveMouse(x, y) which takes your relative coordinates in as an argument, and translates them using the newly acquired X0, Y0 coordinates. You're basically just adding the offset required to be 'relative' to the active window and that offset is acquired by determining the top left corners x, y position.
def MoveMouse(x, y):
x0, y0 = GetMyWindowSize() # Method I created to return the GetWindowRect() values
pyautogui.moveTo(x + bsX, y + bsY)
return
Good luck! If you're not restricted to Python, AHK (Auto Hotkey) is also worth checking out for automation of mouse and keyboard inputs. There are native methods to recreate this functionality.

Turtle graphics window's canvas color *not* showing up in Postscript (.ps) file [duplicate]

I am new to Python and have been working with the turtle module as a way of learning the language.
Thanks to stackoverflow, I researched and learned how to copy the image into an encapsulated postscript file and it works great. There is one problem, however. The turtle module allows background color which shows on the screen but does not show in the .eps file. All other colors, i.e. pen color and turtle color, make it through but not the background color.
As a matter of interest, I do not believe the import of Tkinter is necessary since I do not believe I am using any of the Tkinter module here. I included it as a part of trying to diagnose the problem. I had also used bgcolor=Orange rather than the s.bgcolor="orange".
No Joy.
I am including a simple code example:
# Python 2.7.3 on a Mac
import turtle
from Tkinter import *
s=turtle.Screen()
s.bgcolor("orange")
bob = turtle.Turtle()
bob.circle(250)
ts=bob.getscreen()
ts.getcanvas().postscript(file = "turtle.eps")
I tried to post the images of the screen and the .eps file but stackoverflow will not allow me to do so as a new user. Some sort of spam prevention. Simple enough to visualize though, screen has background color of orange and the eps file is white.
I would appreciate any ideas.
Postscript was designed for making marks on some medium like paper or film, not raster graphics. As such it doesn't have a background color per se that can be set to given color because that would normally be the color of the paper or unexposed film being used.
In order to simulate this you need to draw a rectangle the size of the canvas and fill it with the color you want as the background. I didn't see anything in the turtle module to query the canvas object returned by getcanvas() and the only alternative I can think of is to read the turtle.cfg file if there is one, or just hardcode the default 300x400 size. You might be able to look at the source and figure out where the dimensions of the current canvas are stored and access them directly.
Update:
I was just playing around in the Python console with the turtle module and discovered that what the canvas getcanvas() returns has a private attribute called _canvas which is a <Tkinter.Canvas instance>. This object has winfo_width() and winfo_height() methods which seem to contain the dimensions of the current turtle graphics window. So I would try drawing a filled rectangle of that size and see if that gives you what you want.
Update 2:
Here's code showing how to do what I suggested. Note: The background must be drawn before any other graphics are because otherwise the solid filled background rectangle created will cover up everything else on the screen.
Also, the added draw_background() function makes an effort to save and later restore the graphics state to what it was. This may not be necessary depending on your exact usage case.
import turtle
def draw_background(a_turtle):
""" Draw a background rectangle. """
ts = a_turtle.getscreen()
canvas = ts.getcanvas()
height = ts.getcanvas()._canvas.winfo_height()
width = ts.getcanvas()._canvas.winfo_width()
turtleheading = a_turtle.heading()
turtlespeed = a_turtle.speed()
penposn = a_turtle.position()
penstate = a_turtle.pen()
a_turtle.penup()
a_turtle.speed(0) # fastest
a_turtle.goto(-width/2-2, -height/2+3)
a_turtle.fillcolor(turtle.Screen().bgcolor())
a_turtle.begin_fill()
a_turtle.setheading(0)
a_turtle.forward(width)
a_turtle.setheading(90)
a_turtle.forward(height)
a_turtle.setheading(180)
a_turtle.forward(width)
a_turtle.setheading(270)
a_turtle.forward(height)
a_turtle.end_fill()
a_turtle.penup()
a_turtle.setposition(*penposn)
a_turtle.pen(penstate)
a_turtle.setheading(turtleheading)
a_turtle.speed(turtlespeed)
s = turtle.Screen()
s.bgcolor("orange")
bob = turtle.Turtle()
draw_background(bob)
ts = bob.getscreen()
canvas = ts.getcanvas()
bob.circle(250)
canvas.postscript(file="turtle.eps")
s.exitonclick() # optional
And here's the actual output produced (rendered onscreen via Photoshop):
I haven't found a way to get the canvas background colour on the generated (Encapsulated) PostScript file (I suspect it isn't possible). You can however fill your circle with a colour, and then use Canvas.postscript(colormode='color') as suggested by #mgilson:
import turtle
bob = turtle.Turtle()
bob.fillcolor('orange')
bob.begin_fill()
bob.circle(250)
bob.begin_fill()
ts = bob.getscreen()
ts.getcanvas().postscript(file='turtle.eps', colormode='color')
Improving #martineau's code after a decade
import turtle as t
Screen=t.Screen()
Canvas=Screen.getcanvas()
Width, Height = Canvas.winfo_width(), Canvas.winfo_height()
HalfWidth, HalfHeight = Width//2, Height//2
Background = t.Turtle()
Background.ht()
Background.speed(0)
def BackgroundColour(Colour:str="white"):
Background.clear() # Prevents accumulation of layers
Background.penup()
Background.goto(-HalfWidth,-HalfHeight)
Background.color(Colour)
Background.begin_fill()
Background.goto(HalfWidth,-HalfHeight)
Background.goto(HalfWidth,HalfHeight)
Background.goto(-HalfWidth,HalfHeight)
Background.goto(-HalfWidth,-HalfHeight)
Background.end_fill()
Background.penup()
Background.home()
BackgroundColour("orange")
Bob=t.Turtle()
Bob.circle(250)
Canvas.postscript(file="turtle.eps")
This depends on what a person is trying to accomplish but generally, having the option to select which turtle to use to draw your background to me is unnecessary and can overcomplicate things so what one can do instead is have one specific turtle (which I named Background) to just update the background when desired.
Plus, rather than directing the turtle object via magnitude and direction with setheading() and forward(), its cleaner (and maybe faster) to simply give the direct coordinates of where the turtle should go.
Also for any newcomers: Keeping all of the constants like Canvas, Width, and Height outside the BackgroundColour() function speeds up your code since your computer doesn't have to recalculate or refetch any values every time the function is called.

Creating DampedRotarySpring in pymunk between a dynamic body and a moving static body

I'm trying to do what the title says. I have a character with a gun constrained to its hand, and I'm trying to get the gun to point at the cursor. I figured that a DampedRotarySpring would be a nice way to do it, but it turns out not to be as simple as that. The gun is a dynamic body with a Segment shape, and for the cursor I create a static body whose position I set to the mouse location with pygame each step.
When I run the program, the gun simply does not move at all except for the effect of gravity or collisions.
Here is the relevant code:
# add crosshairs at the location of the mouse
pointer_body = pymunk.Body()
pointer_shape1 = pymunk.Segment(pointer_body, (0,CROSSHAIRS_SIZE), (0,-CROSSHAIRS_SIZE), 1) # vertical segment
pointer_shape2 = pymunk.Segment(pointer_body, (-CROSSHAIRS_SIZE,0), (CROSSHAIRS_SIZE,0), 1) # horizontal segment
# add a spring that will angle the gun toward the mouse
spring = pymunk.DampedRotarySpring(me.gun.body, pointer_body, 0, 0.01, 1)
space.add(pointer_shape1, pointer_shape2, spring)
while True:
# handle event queue
for event in pygame.event.get():
if event.type == pygame.MOUSEMOTION:
from math import atan2
# update location of pointer
pointer_body.position = flipy(pygame.mouse.get_pos())
pointer_body.angle = atan2( (pointer_body.position.y - me.gun.body.position.y), (pointer_body.position.x - me.gun.body.position.x) )
Edit:
Here is a Gist repository of all my code: https://gist.github.com/4470807.
The main loop is in ragdoll.py.
The problem with the code in the gist is that you have attached the gun to the hand with two joints to keep them in the same place and same rotation. However, the the hand is a rouge body and wont rotate. Therefor the gun wont rotate when its pulled by the spring between it and the cursor, because that other joint is stronger.
Im not sure exactly how you want the setup, but you can see that it all works if you remove the RotaryLimitJoint from the gun-hand.
Take a look at a fixed fork of the code for the exact details: https://gist.github.com/4505219
Some tips for future troubleshooting that I did to find the problem:
Make everything 10x bigger so its easy to see what happens. I know pymunk only draws in one size, but it was easy to just add a 0 on the end of all sizes in the code.
Make the hand not move so its easier to see how it rotates (removed all stuff in the update_hand_position method)
Disable collisions between all shapes in the scene so that the rotating gun is not hindered by some body part. (did a simple loop of space.shapes and ran shape.group=1)
Maybe your problem is with the spring parameters? The stiffness and damping looks very low unless the gun is extremely light.
Check out this code example I added to pymunk yesterday: http://code.google.com/p/pymunk/source/browse/trunk/examples/damped_rotary_spring_pointer.py
(There is one thing going on with the rotation when it flip over between positive and negative pi that I will look at)

Can you change the attributes of a Canvas object after creation?

I'm trying to simulate an American traffic light, with 3 circles on a rectangle, all drawn on a set Canvas. The simulation is supposed to mirror "animation" by changing which light is displayed every 2 seconds in the following order: green > yellow > red > green, etc forever.
The only way I can think of to do this is by using a canvas.move(), canvas.after(), canvas.update() pattern to move a filled oval object to superimpose one unfilled circle at a time. I've gotten the logic down to move a circle at the proper speed and in the correct order. The thing is, I just instantiate a circle filled with "green", but I can't change it to be "yellow" or "red" using this method. It seems silly to have to canvas.delete("filled") and redraw it in a new place with a different fill every 2 seconds, because that's a lot to do for such a simple program.
Question 1: Is there a way I can just alter the fill option for my filled Canvas object at will, using some method or other means?
Question 2: Am I approaching this scenario incorrectly? Is there a better way to simulate this?
Yes you should be able to change settings of the canvas with config().
Likewise, use itemconfig() to change items on the canvas. This does require that you save a handle to the item or tag them.
Example based on tkinterbook:
item = canvas.create_line(xy, fill="red")
canvas.coords(item, new_xy) # change coordinates
canvas.itemconfig(item, fill="blue") # change color

Categories

Resources