Hitting a specified target region on a sphere - python

I am attempting to create a program that will count the number of hits to a specific rectangular area on the surface of a sphere. How the programs is supposed to work, is random lines are generated and if one of those line hits in the target area the count goes up one. My problem is I do not think I am generating the lines correctly and I really have know idea how to correctly set the count parameters. This is the code I have so far and how I think the lines should be generated and what the count parameter might be.
import numpy as np
import random as rand
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_aspect("equal")
#rough model of the earth
theta, phi = np.mgrid[0:2*np.pi : 20j ,0:np.pi : 20j]
r = 6.3
x = r * np.cos(phi)*np.sin(theta)
y = r * np.sin(phi)*np.sin(theta)
z = r * np.cos(theta)
ax.plot_wireframe(x,y,z, color = "k")
#target area
lat1x = 46.49913179 * (2*np.pi/360)
lat2x = 46.4423682 * (2*np.pi/360)
long1y = -119.4049072 * (2*np.pi/360)
long2y = -119.5048141 * (2*np.pi/360)
lat3x = 46.3973998 * (2*np.pi/360)
lat4x = 46.4532495 * (2*np.pi/360)
long3y = -119.4495392 * (2*np.pi/360)
long4y = -119.3492884 * (2*np.pi/360)
def to_cartesian(lat,lon):
x = r * np.cos(lon)*np.cos(lat)
y = r * np.sin(lon)*np.cos(lat)
z = r * np.sin(lat)
return [x,y,z]
p1 = to_cartesian(lat1x,long1y)
p2 = to_cartesian(lat2x,long2y)
p3 = to_cartesian(lat3x,long3y)
p4 = to_cartesian(lat4x,long4y)
X = np.array([p1,p2,p3,p4])
ax.scatter(X[:,0],X[:,1],X[:,2], color = "r")
#random line path
n = 500
x0 = np.zeros(n)
y0 = np.zeros(n)
z0 = np.zeros(n)
x1 = np.zeros(n)
y1 = np.zeros(n)
z1 = np.zeros(n)
for k in range (n):
theta = rand.uniform(0.0, np.pi)
phi = rand.uniform(0, (2 * np.pi))
x0[k] = 100 * np.sin(phi) * np.cos(theta)
y0[k] = 100 * np.sin(phi) * np.sin(theta)
z0[k] = 100 * np.cos(theta)
for j in range (n):
theta = rand.uniform(0.0, np.pi)
phi = rand.uniform(0, (2 * np.pi))
x1[j] = 100 * np.sin(phi) * np.cos(theta)
y1[j] = 100 * np.sin(phi) * np.sin(theta)
z1[j] = 100 * np.cos(theta)
#ax.plot_wireframe([x0[k],x1[j]],[y0[k],y1[j]],[z0[k],z1[j]], color="g")
# count if hit target area
count = 0
for i in range (n):
if np.any([x1[i]<=X[:0]<=x0[i]]) and np.any([y1[i]<=X[:1]<=y0[i]]) and
np.any([z1[i]<=X[:2]<=z0[i]]):
count =+1
print (count)
plt.show()

Related

Plotting a vector field using quiver

I'm trying to reproduce a 2D vector map with components
v = 100/a * exp(-1/a^2 * ((x+0.55)^2+y^2))(-y,x) - 100/a * exp(-1/a^2 * ((x-0.55)^2+y^2))(-y,x)
and here are my codes. It did not give the map I want (see attached vector map). Could someone please help me with it?
import numpy as np
import matplotlib.pyplot as plt
import math
grid_resolution = 25
grid_size = 2*grid_resolution+1
a = 0.2
x = np.linspace(-1,1,grid_size)
y = np.linspace(-1,1,grid_size)
X,Y = np.meshgrid(x, y)
vx = np.zeros((grid_size,grid_size))
vy = np.zeros((grid_size,grid_size))
for i in range(0,grid_size):
for j in range(0,grid_size):
x0 = x[j]
y0 = y[i]
xx = (x0 + 0.55) ** 2 + y0 ** 2
yy = (x0 - 0.55) ** 2 + y0 ** 2
expf1 = math.exp(-xx / (a ** 2))
expf2 = math.exp(-yy / (a ** 2))
vx[i,j] = 100 / a * (-expf1 + expf2) * y0
vy[i,j] = 100 / a * (expf1 - expf2) * x0
fig, ax = plt.subplots()
ax.quiver(X, Y, vx, vy)
ax.set_aspect('equal')
plt.show()
In the last passage, when you compute vx[i,j] and vy[i,j], you are computing vector field components in (x0, y0), while you should compute it in the current point, so (x0 ± 0.55, y0). Moreover, you should change the sign of vx and vy in order to draw a vector field like the one you linked.
import numpy as np
import matplotlib.pyplot as plt
import math
grid_resolution = 25
grid_size = 2*grid_resolution + 1
a = 0.2
x = np.linspace(-1, 1, grid_size)
y = np.linspace(-1, 1, grid_size)
X, Y = np.meshgrid(x, y)
vx = np.zeros((grid_size, grid_size))
vy = np.zeros((grid_size, grid_size))
for i in range(0, grid_size):
for j in range(0, grid_size):
x0 = x[j]
y0 = y[i]
xx = (x0 + 0.55)**2 + y0**2
yy = (x0 - 0.55)**2 + y0**2
expf1 = math.exp(-xx/(a**2))
expf2 = math.exp(-yy/(a**2))
vx[i, j] = -100/a*(-expf1 + expf2)*y0
if x0 > 0:
vy[i, j] = -100/a*(expf1 - expf2)*(x0 - 0.55)
else:
vy[i, j] = -100/a*(expf1 - expf2)*(x0 + 0.55)
fig, ax = plt.subplots()
ax.quiver(X,Y,vx,vy)
ax.set_aspect('equal')
plt.show()

Fitting curve with conditions

I'm trying to simulate an exoplanet transit and to determine its orbital characteristics with curve fitting. However, the intersection area between two circles needs to distinguish two cases: if the center of the smallest circle is in the biggest or not. This is a problem for scipy with the function curve_fit, calling an array in my function cacl_aire. The function transit simulates the smallest disc's evolution with time.
Here's my code:
import numpy as np
from matplotlib import pyplot as plt
from scipy.optimize import curve_fit
import xlrd
dt = 0.1
Vx = 0.08
Vy = 0
X0 = -5
Y0 = 0
R = 2
r = 0.7
X = X0
Y = Y0
doc = xlrd.open_workbook("transit data.xlsx")
feuille_1 = doc.sheet_by_index(0)
mag = [feuille_1.cell_value(rowx=k, colx=4) for k in range(115)]
T = [feuille_1.cell_value(rowx=k, colx=3) for k in range(115)]
def calc_aire(r, x, y):
D2 = x * x + y * y
if D2 >= (r + R)**2:
return 0
d = (r**2 - R**2 + D2) / (2 * (D2**0.5))
d2 = D2**0.5 - d
if abs(d) >= r:
return min([r * r * np.pi, R * R * np.pi])
H = (r * r - d * d)**0.5
As = np.arccos(d / r) * r * r - d * H
As2 = R * R * np.arccos(d2 / R) - d2 * H
return As + As2
def transit(t, r, X0, Y0, Vx, Vy):
return -calc_aire(r, X0 + Vx * t, Y0 + Vy * t)
best_vals = curve_fit(transit, T, mag)[0]
print('best_vals: {}'.format(best_vals))
plt.figure()
plt.plot(T, mag)
plt.draw()
I have the following error :
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() with the line 28 :
if D2 >= (r + R)**2:
Here is my database:
https://drive.google.com/file/d/1SP12rrHGjjpHfKBQ0l3nVMJDIRCPlkuf/view?usp=sharing
I don't see any trick to solve my problem.

Sine ploting python

How to get one graph which consist of two different sinusoidal waves? I wrote this code but it makes two separate waves..
Fs = 1000
f = 2
sample = 1000
sample_rate= 0.1
x = np.arange(sample)
noise = 0.0003*np.asarray(random.sample(range(0,1000),sample))
y = np.sin(2 * np.pi * f * x / Fs)+noise
f1 = 10
x1 = np.arange(sample)
y1 = np.sin(2 * np.pi * f1 * x / Fs)+noise
plt.plot(x, y, x1, y1)
plt.xlabel('Time(s)')
plt.ylabel('Amplitude(V)')
plt.show()
I got this
but I need to get this one
Aside from the "spike" joining the two different signals, this looks more like what you're looking for:
import numpy as np
import matplotlib.pyplot as plt
rng = np.random.default_rng()
Fs = 1000
def generate_noisy_signal(*, length, f, noise_amp=0):
x = np.arange(length)
noise = noise_amp * rng.random(length)
return np.sin(2 * np.pi * f * x / Fs) + noise
signal1 = generate_noisy_signal(length=1000, f=2, noise_amp=0.3)
signal2 = generate_noisy_signal(length=1000, f=10, noise_amp=0.3) + 1.5
signal = np.concatenate([signal1, signal2])
plt.plot(signal)
plt.xlabel("Time(s)")
plt.ylabel("Amplitude(V)")
plt.show()

I don't know why I get the multiple graphs of W versus PT using the attached python code

I want to get three graphs (W vs. X, W vs. y, W vs PT). But I can get two proper graphs (W vs. X and W vs. y). Unfortunately, I finally got multiple graphs of W vs PT (green lines). I don't know how to handle it. Anything you could do for me would be highly appreciated.
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
def PBR(X, W):
a = 9.8*10**(-5)
y = (1-a*W)**0.5
PH2 = PT0*(1.5-X)*y
PB = PT0 * X * y
PT = PT0 * (1 - X)*y
r = -k * PT * PH2 / (1 + KB*PB + KT *PT)
dXdW = -r/FT0
return dXdW
W = np.linspace(0, 10000)
KT = 1.038
KB = 1.39
FT0 = 50
k = 0.00087
PT0 = 12
X0 = 0
a = 9.8*10**(-5)
y = (1-a*W)**0.5
PT = PT0 * (1 - X)*y
X = odeint(PBR, X0, W)
plt.plot(W, PT, 'g', linewidth=0.5)
plt.plot(W, X,'r', linewidth=3.0)
plt.plot(W, y,'b', linewidth=5.0)
enter image description here
Are you looking for output like this. If yes - small issue in your script. Look at line marked as #**. You want to multiply with first dimension of X array.
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
def PBR(X, W):
a = 9.8*10**(-5)
y = (1-a*W)**0.5
PH2 = PT0*(1.5-X)*y
PB = PT0 * X * y
PT = PT0 * (1 - X)*y
r = -k * PT * PH2 / (1 + KB*PB + KT *PT)
dXdW = -r/FT0
return dXdW
W = np.linspace(0, 10000)
KT = 1.038
KB = 1.39
FT0 = 50
k = 0.00087
PT0 = 12
X0 = 0
a = 9.8*10**(-5)
y = (1-a*W)**0.5
X = odeint(PBR, X0, W)
PT = PT0 * np.multiply(1 - X[:,0],y) #**
print(PT)
plt.plot(W, PT, 'g', linewidth=0.5)
plt.plot(W, X,'r', linewidth=3.0)
plt.plot(W, y,'b', linewidth=5.0)

Using functions to create Electric Field array for 2d Density Plot and 3d Surface Plot

Below is my code, I'm supposed to use the electric field equation and the given variables to create a density plot and surface plot of the equation. I'm getting "invalid dimensions for image data" probably because the function E takes multiple variables and is trying to display them all as multiple dimensions. I know the issue is that I have to turn E into an array so that the density plot can be displayed, but I cannot figure out how to do so. Please help.
import numpy as np
from numpy import array,empty,linspace,exp,cos,sqrt,pi
import matplotlib.pyplot as plt
lam = 500 #Nanometers
x = linspace(-10*lam,10*lam,10)
z = linspace(-20*lam,20*lam,10)
w0 = lam
E0 = 5
def E(E0,w0,x,z,lam):
E = np.zeros((len(x),len(z)))
for i in z:
for j in x:
E = ((E0 * w0) / w(z,w0,zR(w0,lam)))
E = E * exp((-r(x)**2) / (w(z,w0,zR(w0,lam)))**2)
E = E * cos((2 * pi / lam) * (z + (r(x)**2 / (2 * Rz(z,zR,lam)))))
return E
def r(x):
r = sqrt(x**2)
return r
def w(z,w0,lam):
w = w0 * sqrt(1 + (z / zR(w0,lam))**2)
return w
def Rz(z,w0,lam):
Rz = z * (1 + (zR(w0,lam) / z)**2)
return Rz
def zR(w0,lam):
zR = pi * lam
return zR
p = E(E0,w0,x,z,lam)
plt.imshow(p)
It took me way too much time and thinking but I finally figured it out after searching for similar examples of codes for similar problems. The correct code looks like:
import numpy as np
from numpy import array,empty,linspace,exp,cos,sqrt,pi
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
lam = 500*10**-9 #Nanometers
x1 = linspace(-10*lam,10*lam,100)
z1 = linspace(-20*lam,20*lam,100)
[x,y] = np.meshgrid(x1,z1)
w0 = lam
E0 = 5
r = sqrt(x**2)
zR = pi * lam
w = w0 * sqrt(1 + (y / zR)**2)
Rz = y * (1 + (zR / y)**2)
E = (E0 * w0) / w
E = E * exp((-r**2 / w**2))
E = E * cos((2 * pi / lam) * (y + (r**2 / (2 * Rz))))
def field(x,y):
lam = 500*10**-9
k = (5 * lam) / lam * sqrt(1 + (y / (pi*lam))**2)
k *= exp(((-sqrt(x**2)**2 / (lam * sqrt(1 + (y / pi * lam)**2))**2)))
k *= cos((2 / lam) * (y + ((sqrt(x**2)**2 / (2 * y * (1 + (pi * lam / y)**2))))))
return k
#Density Plot
f = field(x,y)
plt.imshow(f)
plt.show()
#Surface Plot
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(x,y,E,rstride=1,cstride=1)
plt.show

Categories