Cylinders aren't getting the correct length in Vpython - vpython

Here's my code:
from vpython import *
from math import *
import numpy as np
from __future__ import division
stick = cylinder()
stick.pos = vec(0,5,-15)
stick.axis = vec(0,1,0)
stick.length = 30
stick.radius = 0.75
stick.color = vec(.5,.5,.8)
scene.forward = vec(-1,-1,-2)
scene.range = 15
spheres = []
for i in range (0, 15):
s = sphere()
s.radius = 1.5
s.theta_0 = -0.5
s.period = 75/(50+i)
s.color = color.hsv_to_rgb(vec(i/15, 0.75,0.9))
s.wire = cylinder()
s.wire.color = s.color
s.wire.pos = stick.pos + vec(0,0,i+0.5)*stick.length/15
s.wire.axis = vec(0,-1,0)
s.wire.length = 2*np.pi*9.81*s.period*s.period
s.wire.radius = 0.1
spheres.append(s)
dt = 0.2
t = 0
while True:
rate(1/dt)
for i in range(0, len(spheres)):
s = spheres[i]
theta = s.theta_0 * cos( 2*pi*t/s.period )
s.wire.axis = vec(np.sin(theta),-np.cos(theta),0)
s.pos = s.wire.pos + s.wire.axis*s.wire.length
t = t + dt
I want to make a dancing pendulum. However, the wire which should connect the spheres to the stick aren't the correct length. How do I make the wires the correct length?

You don't need from math import * (that's contained in from vpython import *), and in the Jupyter environment you can choose a VPython notebook that executes "from future import division, print_function" (in any case, such a statement must be the first statement in the file, so your program couldn't have run as is). No reason to import numpy and use it for pi and sin and cos. In fact, Python's own sin and cos functions are faster than those of numpy if the argument is a single number.
A more "Pythonic" way of handling the loop over spheres is to write it like this:
for s in spheres:
theta = .....
I dont' know what your intent is, but I suggest you temporarily make the spheres invisible (visible=False), comment out the rate statement, and insert scene.pause() in the loop over spheres in order to see what's going on. You'll see that the wires are initially drawn downwards from the spheres and then apparently collapsed to very short lengths.
I'll advertise that a better place to pose VPython questions is in the VPython forum at
https://groups.google.com/forum/?fromgroups&hl=en#!forum/vpython-users

Related

Discrepancy in histograms generated by plt.hist() [duplicate]

This question already has answers here:
numpy arange: how to make "precise" array of floats?
(4 answers)
Closed 1 year ago.
I need help figuring out why there is a discrepancy in the histogram A and B generated in the code below. I'm a physicist and some colleagues and me noted this as we were plotting the same data in python, IDL and Matlab. Python and IDL have the same problem, however Matlab does not. Matlab always reproduce histogram B.
import numpy as np
import matplotlib.pyplot as plt
t = np.random.randint(-1000,1000,10**3)
# A
tA = t/1000
binsizeA = 0.05
xminA = -1
xmaxA = 1
binsA = np.arange(xminA, xmaxA+binsizeA, binsizeA)
hA, _ , _ = plt.hist(tA, bins=binsA, histtype="step", label="A")
# B
tB = t
binsizeB = 50
xminB = -1000
xmaxB = 1000
binsB = np.arange(xminB, xmaxB+binsizeB, binsizeB)
hB, _ , _ = plt.hist(tB/1000, bins=binsB/1000, histtype="step", label="B")
plt.legend()
plt.show()
print(hA==hB)
Plot showing the histograms
The original data are time tagged measurements with microsecond presision saved as integers. The problems seems to be when the array are divided by 1000 (from microsecond to millisecond). Is there a way to avoid this?
I start by "recreating" scenario A, but directly by scaling everything (data + bins) from B:
C - binsB / 1000
# C
tC = tB / 1000
xminC = xminB / 1000
xmaxC = xmaxB / 1000
binsC = binsB / 1000
hC, _ , _ = plt.hist(tC, bins=binsC, histtype="step", label="C")
assert((hB == hC).all())
This produces the same histogram as hB, so the problem is in the way binsA is made:
binsA = np.arange(xminA, xmaxA+binsizeA, binsizeA)
From its docstring:
When using a non-integer step, such as 0.1, the results will often not
be consistent. It is better to use numpy.linspace for these cases.
So either go route C or use linspace to create the non-integer bins with less rounding errors.
D - np.linspace
Interestingly, using linspace does not yield floating-point equal bins as binsB / 1000 does:
# D
tD = t / 1000
bincountD = 41
xminD = -1
xmaxD = 1
binsD = np.linspace(xminD, xmaxD, 41)
hC, _ , _ = plt.hist(tC, bins=binsC, histtype="step", label="C")
hD, _ , _ = plt.hist(tD, bins=binsD, histtype="step", label="D")
plt.legend()
plt.show()
By inspection, both binsC look equal to binsD, but still differ in their least signifcant digits. I can "clamp" them to yield the same histogram by binsX.round(2).
But in total, this serves as a reminder how tricky it is to achieve "exact" results. But note that this fact is amplified here, as all your samples were integers to begin with. If your data is floating point as well, bins and samples would not be value-identical.

Choice of IMODE in gekko optimisation problems

I'm seeing here that imode=3 is equivalent to the steady-state simulation (which I guess imode=2) except that additional degrees of freedom are allowed.
How do I decide to use imode=3 instead of imode=2?
I'm doing optimization using imode=2 where I'm defining variables calculated by solver to meet constraint using m.Var & other using m.Param. What changes I need to do in variables to use imode=3 ?
Niladri,
IMODE 2 is for steady state problems with multiple data points.
Here is an example:
from gekko import GEKKO
import numpy as np
xm = np.array([0,1,2,3,4,5])
ym = np.array([0.1,0.2,0.3,0.5,1.0,0.9])
m = GEKKO()
m.x = m.Param(value=np.linspace(-1,6))
m.y = m.Var()
m.options.IMODE=2
m.cspline(m.x,m.y,xm,ym)
m.solve(disp=False)
This is a Cubic Spline approximation with multiple data points. When you switch to IMODE 3, it is very similar but it only considers one instance of your model. All of the value properties should only have 1 value such as when you optimize the Cubic spline to find the maximum value.
p = GEKKO()
p.x = p.Var(value=1,lb=0,ub=5)
p.y = p.Var()
p.cspline(p.x,p.y,xm,ym)
p.Obj(-p.y)
p.solve(disp=False)
Here is additional information on IMODE:
https://apmonitor.com/wiki/index.php/Main/OptionApmImode
https://apmonitor.com/wiki/index.php/Main/Modes
https://gekko.readthedocs.io/en/latest/imode.html
Best regards,
John Hedengren

Solving and Graphing a Nonlinear first-order ODE

So far I've been semi-successful in solving and graphing the nonlinear ode dn/dt = n^2-2n-3 for two initial conditions, n(0)=-5 and n(0)=1, but when I add one last line to the graph with the initial condition n(0)=10, everything gets wacky, and the graph doesn't look like what it's supposed or behave like the other two lines.
the code is:
import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate
#import warnings
#warnings.simplefilter('ignore')
def func(N, t):
return(N**2 - 2*N - 3)
tvec = np.arange(0,11)
s_1 = scipy.integrate.odeint(func, y0=-5,t = tvec)
s_2 = scipy.integrate.odeint(func,y0=1, t=tvec)
s_3 = scipy.integrate.odeint(func, y0 = 10, t=tvec)
%matplotlib inline
plt.plot(tvec,s_1, label="N0=-5")
plt.plot(tvec,s_2, label="N0=1")
plt.plot(tvec, s_3, label="N0=10")
plt.ylim(-5,10)
plt.legend();
the culprit here being s_3.
Any ideas on how to fix this?
Your differential equation has an unstable equilibrium point at N = 3. Any initial condition larger than 3 results in a solution that blows up in finite time. That's the mathematical statement; numerically, the values will become extremely large, and the ODE solver will eventually start generating nonsense. If any of the "nonsense" values happen to end up being less than 3, the "solution" will then converge to the stable equilibrium at N = -1.

Using local variables in one function in a main function

I'm completely new to programming and python as a whole but I have recently joined a class. Currently I am trying to make a program which prompts the user for an input of the coordinates of the center of an object on the screen.
The program will then take the X and Y coordinates of the item and randomize the coordinates within a range of +- 15. So if the X coordinate is 30, the program will pick a random number of 15 to 45.
Then the program will take a random delay between 3.2 to 4.3 seconds and move the mouse from it's current position to the randomized coordinates within the random time delay.
I want it to be able to loop endlessly until I prompt it to stop, and I think I can figure that out. However, I do not understand how to properly use parameters to allow the local variables coords_x , coords_y and click_delay to be used in the function main()
Here is what I have so far:
#! python3
import pyautogui, sys
import random
from random import randint
center_x = int(input("Please enter the X coordinate of the center of the item:"))
center_y = int(input("Please enter the Y coordinate of the center of the item:"))
#y = 23 long 735 - 712
#x = 23 862 - 838
buffer = 17
def randomizex():
min_x = center_x - buffer
max_x = center_x + buffer
coords_x = randint(min_x, max_x)
def randomizey():
min_y = center_y - buffer
max_y = center_y + buffer
coords_y = randint(min_y, max_y)
def randomizedelay():
click_delay = random.uniform(3.2, 4.3)
def main():
randomizex()
randomizey()
randomizedelay()
pyautogui.moveTo(coords_x, coords_y, click_delay)
main()
I appreciate any help. The other answers I have found to questions like these are rather confusing to a newbie and some of them are for python 2.
Welcome to SO (and to programming)!
You are almost there with this, the thing you are missing is saving the return values of the randomizex(), randomizey(), randomizedelay() functions to variables, so they can be used within main. Even though you name the variables within their respective functions, that naming does not go beyond the scope of these functions, so main has no idea they are called that. Something like this should work:
def main():
coords_x = randomizex()
coords_y = randomizey()
click_delay = randomizedelay()
pyautogui.moveTo(coords_x, coords_y, click_delay)
def main():
your_x_coords = randomizex()
your_y_coords = randomizey()
Your functions return x_coords, so you have to assign them to another local variable inside of main.

Python Index and Bounds error using data set

Our class is using Python as a solution tool for models. However, this is my first time with python or any programming language since VB in 1997 so I'm struggling. We have the following code provided to us.
from numpy import loadtxt, array, ones, column_stack
from numpy import dot, sqrt
from scipy.linalg import inv
from scipy.stats import norm, t
f = loadtxt('text data.raw')
y = f[:,4]
n = y.size
x = array([f[:,2],f[:,8],f[:,4]])
one = ones(n)
#xa = column_stack([one,f[:,3],f[:,4]])
xa = column_stack([one,x.T])
k = xa.shape[1]
xx = dot(xa.T,xa)
invx = inv(xx)
xy = dot(xa.T,y)
b = dot(invx,xy)
# Compute cov(b)
e = y - dot(xa,b)
s2 = dot(e.T,e)/(n-k)
covb = invx*s2
# Compute t-stat
tstat = b[1]/sqrt(covb[1][1])
#compute p-value
p = 1 - norm.cdf(tstat,0,1)
pt = 1 - t.cdf(tstat,88)
Our data set is a 10x88 matrix. Our goal is to create a linear program and find a few answers. On our data column 1 is already set to price which in our linear program is our desired out put and I need to use column 3,4, and 5. as my x1,x2, and x3. I'm not sure how or what line 9 and 11 values need to be changed to in order to accomplish that task nor am I currently understanding what those two lines are specifically calling for or doing in the program. Again, I'm not familiar with programming.
Everything I try generally yields an error similar to
IndexError: index 5 is out of bounds for axis 1 with size 5
Any suggestions?

Resources