Skyfield and apparent diameter - skyfield

Can Skyfield calculate the apparent diameter of a planet, the Sun or Moon?
Something along the lines of:
place.at(utc).observe(moon).apparent().angular_diameter

You can work out the apparent diameter if you know the object's radius, with simple trigonometry:
from numpy import arcsin
MOON_RADIUS = 1737.1 # km
appdiam = 360 / pi * arcsin(MOON_RADIUS / place.at(utc).observe(moon).distance().km)

Related

Matplotlib.odeint giving wrong solution for simple formula of acc = Gm/r**2

I made a program to calculate the motion of any object (in this case moon) by earth's pull, with zero initial velocity, the moon should just oscillate in a straight line back and forth the earth until it stops at earth exactly right on top of the Earth, so plotting time versus distance I should get a graph similar to a damping signal, instead, I am getting an infinitely decrementing plot.
I have tried :-
giving different initial speeds to the moon, but got the same result, it seems like the way I am using odeint to solve the differential equation is wrong? Not sure. Very new to coding.
Assuming 1000 seconds in not enough for this to happen, so I increased the time to 1e+5,1e+10,1e+20, it seems like odeint couldn't handle that because it gave a different solution every time I run the program for the exact same parameters, received the follow warning:
ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information. warnings.warn(warning_msg, ODEintWarning)
Is there some other function I should use to solve this differential equation?
Reduced the masses to 10,20 and G and r to 10,10, and received the same warning as in case (2)
Any feed back helps
from scipy.integrate import odeint
import matplotlib.pyplot as plt
G=6.67408e-11 #N-m2/kg2 #N-m2/kg2
m1 = 5.972e+24 # kg , mass of earth
m2 = 7.348e+22 # kg , mass of moon
def dvdt(S, t):
# v = dr./dt, so a = dv/dt
r,v = S
return [v,
-G*m1 / r**2]
# initial values
r10 = 0 # position of earth in meters
r20 = 4e+8 # position of moon from earth in meters
v10 = 0 # velocity of earth m/s
v20 = 0 # velocity of moon relative to earth m/s
S0 = [r20, v20]
t = np.linspace(0,1000,100)
# solving the differential eqn
acc = odeint(dvdt,S0, t)
r,v = acc.T
# plotting
plt.plot(t,r)
plt.xlabel('Time')
plt.ylabel('Distance between earth and moon')
plt.show()
The scenario assumes that the two bodies are "shifted out of phase", so that they behave like dark matter to each other, no electro-weak or strong nuclear forces.
The effective gravity below the radius of Earth is determined by the mass inside the current radius, the influences of the outer shell add to zero.
The force vector always points to the center, for the one-dimensional motion the sign of the force has always to be opposite to the sign of the coordinate.
In total thus
R1 = 6.7e+6 # m
acc = -sign(r) * G*(m1*min(1,abs(r)/R1)**3) / abs(r)**2
= -G*m1 * r/max(R1,abs(r))**3
If this is implemented, one gets the expected oscillating plot

FFT real/imaginary/abs parts interpretation

I'm currently learning about discret Fourier transform and I'm playing with numpy to understand it better.
I tried to plot a "sin x sin x sin" signal and obtained a clean FFT with 4 non-zero points. I naively told myself : "well, if I plot a "sin + sin + sin + sin" signal with these amplitudes and frequencies, I should obtain the same "sin x sin x sin" signal, right?
Well... not exactly
(First is "x" signal, second is "+" signal)
Both share the same amplitudes/frequencies, but are not the same signals, even if I can see they have some similarities.
Ok, since I only plotted absolute values of FFT, I guess I lost some informations.
Then I plotted real part, imaginary part and absolute values for both signals :
Now, I'm confused. What do I do with all this? I read about DFT from a mathematical point of view. I understand that complex values come from the unit circle. I even had to learn about Hilbert space to understand how it works (and it was painful!...and I only scratched the surface). I only wish to understand if these real/imaginary plots have any concrete meaning outside mathematical world:
abs(fft) : frequencies + amplitudes
real(fft) : ?
imaginary(fft) : ?
code :
import numpy as np
import matplotlib.pyplot as plt
N = 512 # Sample count
fs = 128 # Sampling rate
st = 1.0 / fs # Sample time
t = np.arange(N) * st # Time vector
signal1 = \
1 *np.cos(2*np.pi * t) *\
2 *np.cos(2*np.pi * 4*t) *\
0.5 *np.cos(2*np.pi * 0.5*t)
signal2 = \
0.25*np.sin(2*np.pi * 2.5*t) +\
0.25*np.sin(2*np.pi * 3.5*t) +\
0.25*np.sin(2*np.pi * 4.5*t) +\
0.25*np.sin(2*np.pi * 5.5*t)
_, axes = plt.subplots(4, 2)
# Plot signal
axes[0][0].set_title("Signal 1 (multiply)")
axes[0][0].grid()
axes[0][0].plot(t, signal1, 'b-')
axes[0][1].set_title("Signal 2 (add)")
axes[0][1].grid()
axes[0][1].plot(t, signal2, 'r-')
# FFT + bins + normalization
bins = np.fft.fftfreq(N, st)
fft = [i / (N/2) for i in np.fft.fft(signal1)]
fft2 = [i / (N/2) for i in np.fft.fft(signal2)]
# Plot real
axes[1][0].set_title("FFT 1 (real)")
axes[1][0].grid()
axes[1][0].plot(bins[:N/2], np.real(fft[:N/2]), 'b-')
axes[1][1].set_title("FFT 2 (real)")
axes[1][1].grid()
axes[1][1].plot(bins[:N/2], np.real(fft2[:N/2]), 'r-')
# Plot imaginary
axes[2][0].set_title("FFT 1 (imaginary)")
axes[2][0].grid()
axes[2][0].plot(bins[:N/2], np.imag(fft[:N/2]), 'b-')
axes[2][1].set_title("FFT 2 (imaginary)")
axes[2][1].grid()
axes[2][1].plot(bins[:N/2], np.imag(fft2[:N/2]), 'r-')
# Plot abs
axes[3][0].set_title("FFT 1 (abs)")
axes[3][0].grid()
axes[3][0].plot(bins[:N/2], np.abs(fft[:N/2]), 'b-')
axes[3][1].set_title("FFT 2 (abs)")
axes[3][1].grid()
axes[3][1].plot(bins[:N/2], np.abs(fft2[:N/2]), 'r-')
plt.show()
For each frequency bin, the magnitude sqrt(re^2 + im^2) tells you the amplitude of the component at the corresponding frequency. The phase atan2(im, re) tells you the relative phase of that component. The real and imaginary parts, on their own, are not particularly useful, unless you are interested in symmetry properties around the data window's center (even vs. odd).
With respect to some reference point, say the center of a fixed time window, a sine wave and a cosine wave of the same frequency will look different (have different starting phases with respect to any fixed time reference point). They will also be mathematically orthogonal over any integer periodic width, so can represent independent basis vector components of a transform.
The real portion of an FFT result is how much each frequency component resembles a cosine wave, the imaginary component, how much each component resembles a sine wave. Various ratios of sine and cosine components together allow one to construct a sinusoid of any arbitrary or desired phase, thus allowing the FFT result to be complete.
Magnitude alone can't tell the difference between a sine and cosine wave. An IFFT(imag(FFT)) would screw up the reconstruction of any signal with a different phase than pure cosines. Same with IFFT(re(FFT)) and pure sine waves (with respect to the FFT aperture window).
You can convert the signal 1, which consists of a product of three cos functions to a sum of four cos functions. This makes the difference to function 2 which is a sum of four sine functions.
A cos function is an even function cos(-x) == cos(x).
The Fourier Transformation of an even function is pure real.
That is the reason why the plot of the imaginary part of the fft of function 1 contains only values close to zero (1e-15).
A sine function is an odd function sin(-x) == -sin(x).
The Fourier Transformation of an odd function is pure imaginary.
That is the reason why the plot of the real part of the fft of function 2 contains only values close to zero (1e-15).
If you want to understand FFT and DFT in more detail read a textbook of signal analysis for electrical engineering.
Although ... you must be a good expert now :)
For others: Please notice that
with this set of Correct mathematical equation
so correcting the sum as:
signal1 = \
1 *np.cos(2*np.pi * t) *\
2 *np.cos(2*np.pi * 4*t) *\
0.5 *np.cos(2*np.pi * 0.5*t)
signal2 = \
0.25*np.cos(-2*np.pi * 2.5*t) +\
0.25*np.cos(2*np.pi * 3.5*t) +\
0.25*np.cos(-2*np.pi * 4.5*t) +\
0.25*np.cos(2*np.pi * 5.5*t)
Now gives following result
(Now results are)
So point is that real part should also be the same

pyplot scatter plot marker size

In the pyplot document for scatter plot:
matplotlib.pyplot.scatter(x, y, s=20, c='b', marker='o', cmap=None, norm=None,
vmin=None, vmax=None, alpha=None, linewidths=None,
faceted=True, verts=None, hold=None, **kwargs)
The marker size
s:
size in points^2. It is a scalar or an array of the same length as x and y.
What kind of unit is points^2? What does it mean? Does s=100 mean 10 pixel x 10 pixel?
Basically I'm trying to make scatter plots with different marker sizes, and I want to figure out what does the s number mean.
This can be a somewhat confusing way of defining the size but you are basically specifying the area of the marker. This means, to double the width (or height) of the marker you need to increase s by a factor of 4. [because A = WH => (2W)(2H)=4A]
There is a reason, however, that the size of markers is defined in this way. Because of the scaling of area as the square of width, doubling the width actually appears to increase the size by more than a factor 2 (in fact it increases it by a factor of 4). To see this consider the following two examples and the output they produce.
# doubling the width of markers
x = [0,2,4,6,8,10]
y = [0]*len(x)
s = [20*4**n for n in range(len(x))]
plt.scatter(x,y,s=s)
plt.show()
gives
Notice how the size increases very quickly. If instead we have
# doubling the area of markers
x = [0,2,4,6,8,10]
y = [0]*len(x)
s = [20*2**n for n in range(len(x))]
plt.scatter(x,y,s=s)
plt.show()
gives
Now the apparent size of the markers increases roughly linearly in an intuitive fashion.
As for the exact meaning of what a 'point' is, it is fairly arbitrary for plotting purposes, you can just scale all of your sizes by a constant until they look reasonable.
Edit: (In response to comment from #Emma)
It's probably confusing wording on my part. The question asked about doubling the width of a circle so in the first picture for each circle (as we move from left to right) it's width is double the previous one so for the area this is an exponential with base 4. Similarly the second example each circle has area double the last one which gives an exponential with base 2.
However it is the second example (where we are scaling area) that doubling area appears to make the circle twice as big to the eye. Thus if we want a circle to appear a factor of n bigger we would increase the area by a factor n not the radius so the apparent size scales linearly with the area.
Edit to visualize the comment by #TomaszGandor:
This is what it looks like for different functions of the marker size:
x = [0,2,4,6,8,10,12,14,16,18]
s_exp = [20*2**n for n in range(len(x))]
s_square = [20*n**2 for n in range(len(x))]
s_linear = [20*n for n in range(len(x))]
plt.scatter(x,[1]*len(x),s=s_exp, label='$s=2^n$', lw=1)
plt.scatter(x,[0]*len(x),s=s_square, label='$s=n^2$')
plt.scatter(x,[-1]*len(x),s=s_linear, label='$s=n$')
plt.ylim(-1.5,1.5)
plt.legend(loc='center left', bbox_to_anchor=(1.1, 0.5), labelspacing=3)
plt.show()
Because other answers here claim that s denotes the area of the marker, I'm adding this answer to clearify that this is not necessarily the case.
Size in points^2
The argument s in plt.scatter denotes the markersize**2. As the documentation says
s : scalar or array_like, shape (n, ), optional
size in points^2. Default is rcParams['lines.markersize'] ** 2.
This can be taken literally. In order to obtain a marker which is x points large, you need to square that number and give it to the s argument.
So the relationship between the markersize of a line plot and the scatter size argument is the square. In order to produce a scatter marker of the same size as a plot marker of size 10 points you would hence call scatter( .., s=100).
import matplotlib.pyplot as plt
fig,ax = plt.subplots()
ax.plot([0],[0], marker="o", markersize=10)
ax.plot([0.07,0.93],[0,0], linewidth=10)
ax.scatter([1],[0], s=100)
ax.plot([0],[1], marker="o", markersize=22)
ax.plot([0.14,0.86],[1,1], linewidth=22)
ax.scatter([1],[1], s=22**2)
plt.show()
Connection to "area"
So why do other answers and even the documentation speak about "area" when it comes to the s parameter?
Of course the units of points**2 are area units.
For the special case of a square marker, marker="s", the area of the marker is indeed directly the value of the s parameter.
For a circle, the area of the circle is area = pi/4*s.
For other markers there may not even be any obvious relation to the area of the marker.
In all cases however the area of the marker is proportional to the s parameter. This is the motivation to call it "area" even though in most cases it isn't really.
Specifying the size of the scatter markers in terms of some quantity which is proportional to the area of the marker makes in thus far sense as it is the area of the marker that is perceived when comparing different patches rather than its side length or diameter. I.e. doubling the underlying quantity should double the area of the marker.
What are points?
So far the answer to what the size of a scatter marker means is given in units of points. Points are often used in typography, where fonts are specified in points. Also linewidths is often specified in points. The standard size of points in matplotlib is 72 points per inch (ppi) - 1 point is hence 1/72 inches.
It might be useful to be able to specify sizes in pixels instead of points. If the figure dpi is 72 as well, one point is one pixel. If the figure dpi is different (matplotlib default is fig.dpi=100),
1 point == fig.dpi/72. pixels
While the scatter marker's size in points would hence look different for different figure dpi, one could produce a 10 by 10 pixels^2 marker, which would always have the same number of pixels covered:
import matplotlib.pyplot as plt
for dpi in [72,100,144]:
fig,ax = plt.subplots(figsize=(1.5,2), dpi=dpi)
ax.set_title("fig.dpi={}".format(dpi))
ax.set_ylim(-3,3)
ax.set_xlim(-2,2)
ax.scatter([0],[1], s=10**2,
marker="s", linewidth=0, label="100 points^2")
ax.scatter([1],[1], s=(10*72./fig.dpi)**2,
marker="s", linewidth=0, label="100 pixels^2")
ax.legend(loc=8,framealpha=1, fontsize=8)
fig.savefig("fig{}.png".format(dpi), bbox_inches="tight")
plt.show()
If you are interested in a scatter in data units, check this answer.
You can use markersize to specify the size of the circle in plot method
import numpy as np
import matplotlib.pyplot as plt
x1 = np.random.randn(20)
x2 = np.random.randn(20)
plt.figure(1)
# you can specify the marker size two ways directly:
plt.plot(x1, 'bo', markersize=20) # blue circle with size 10
plt.plot(x2, 'ro', ms=10,) # ms is just an alias for markersize
plt.show()
From here
It is the area of the marker. I mean if you have s1 = 1000 and then s2 = 4000, the relation between the radius of each circle is: r_s2 = 2 * r_s1. See the following plot:
plt.scatter(2, 1, s=4000, c='r')
plt.scatter(2, 1, s=1000 ,c='b')
plt.scatter(2, 1, s=10, c='g')
I had the same doubt when I saw the post, so I did this example then I used a ruler on the screen to measure the radii.
I also attempted to use 'scatter' initially for this purpose. After quite a bit of wasted time - I settled on the following solution.
import matplotlib.pyplot as plt
input_list = [{'x':100,'y':200,'radius':50, 'color':(0.1,0.2,0.3)}]
output_list = []
for point in input_list:
output_list.append(plt.Circle((point['x'], point['y']), point['radius'], color=point['color'], fill=False))
ax = plt.gca(aspect='equal')
ax.cla()
ax.set_xlim((0, 1000))
ax.set_ylim((0, 1000))
for circle in output_list:
ax.add_artist(circle)
This is based on an answer to this question
If the size of the circles corresponds to the square of the parameter in s=parameter, then assign a square root to each element you append to your size array, like this: s=[1, 1.414, 1.73, 2.0, 2.24] such that when it takes these values and returns them, their relative size increase will be the square root of the squared progression, which returns a linear progression.
If I were to square each one as it gets output to the plot: output=[1, 2, 3, 4, 5]. Try list interpretation: s=[numpy.sqrt(i) for i in s]

Determine if a latitude/longitude is within a polygon on Earth's surface

I am trying to figure out if a latitude/longitude point is contained within a polygon defined by vertexes that represent points on the earth (also lat/lon's, in clockwise order). This is trivial for polygons that can be mapped to the 2D lat/lon space.
Where this becomes increasingly difficult is circle's (now switching back to 3D) that may go from pole to pole covering half the earth. The translation to lat/lon looks like a sine wave. The 2D point in polygon test no longer applies to this case. Is there an algorithm that exists that solves this problem?
================== Clarifications on comments below: ===================
The polygon is defined as (lon, lat) pairs in degrees, i.e., (60, 90), (60, 110), (-30, 110), (-30, 90).
I do have code that implements the ray casting algorithm, and that works. however, certain polygons on the surface of the earth do not translate to closed polygons in the 2D space.
As stated by denniston.t, if you are only interested in circles, and you have a radius, you can simply check if the Great Circle Distance between the center point and the point is less than the radius. To find the great circle distance you typically use the Haversine Formula. The following is my implementation in python:
from math import radians, sin, cos, asin, sqrt
def haversine(point1, point2):
"""Gives the distance between two points on earth.
The haversine formula, given two sets of latitude and longitude,
returns the distance along the surface of the earth in miles,
ignoring potential changes in elevation. The points must be in
decimal degrees.
"""
earth_radius_miles = 3956
lat1, lon1 = (radians(coord) for coord in point1)
lat2, lon2 = (radians(coord) for coord in point2)
dlat, dlon = (lat2 - lat1, lon2 - lon1)
a = sin(dlat/2.0)**2 + cos(lat1) * cos(lat2) * sin(dlon/2.0)**2
great_circle_distance = 2 * asin(min(1,sqrt(a)))
d = earth_radius_miles * great_circle_distance
return d
If you have the center point and radius of your circle drawn on the surface of the sphere, calculate the Great-circle distance between the center point and target point. If it's less than the radius of the circle, the target point lies in the circle.
This will not generalize to arbitrary polygons drawn on your sphere, but you only asked about circles, so I don't know if it matters to you.
containsLocation(point:LatLng, polygon:Polygon)

Vertical circular motion : time(x/y) versus velocity equation

I wanted to simulate the following through animation :
A ball starts with a certain velocity at the bottom most point of
a vertical circular loop and keeps rolling in it until its velocity permits.
For this, I wanted to find velocity/x/y vs. time equation.
For e.g. if the ball had mass : 5Kg, radius of the circular loop = 10m,
and initial velocity of the ball is 200 m/s, what will its velocity and (x,y) position
be after 5 seconds?
thanks.
Sliding, frictionless case with a point-particle ball
In this case we aren't worrying about rotational energy and are assuming that the ball is actually a point particle. Then, in order for the ball to stay on at the top, the centripetal force condition has to be satisfied:
m * v_top^2 / r = m * g
so
v_top = sqrt(r * g)
So the minimum initial velocity is determined by:
1 / 2 * m * v0^2 >= 1 / 2 * m * v_top^2 + m * g * 2 * r
v0 >= sqrt(5 * r * g)
This is similar to what Pete said, except that he forgot the centripetal force condition to stay on at the top.
Next, the acceleration tangential to the track is given by:
a = - g * sin(theta)
but a = r * alpha = r * d^2(theta)/dt^2 where alpha is the rotational acceleration. Thus, we get
r * d^2(theta)/dt^2 = g * sin(theta)
However, I don't know of an analytical solution to this differential equation and Mathematica was stumbling with finding one too. You can't just move the dts to the other side and integrate because theta is a function of t. I would recommend solving it by numerical means such as a Runga-Kutte or maybe the Verlet method. I solved it using Mathematica for the parameters you gave, but with the ball moving so quickly, it doesn't really slow down much in going around. When I lowered the initial velocity though, I was able to see the speeding up and slowing down by plotting theta as a function of time.
Adding in other things like a finite ball radius, rotational energy and friction are certainly doable, but I would worry about being able to solve this first case before moving on because it only gets more complicated from here. By the way, with the friction you will have to choose some kinetic coefficient of friction for your given materials which will of course be proportional to the normal force exerted on the ball by the track which can be solved for by summing the force components along the radius of the circle and don't forget to include the centripetal force condition.
If you haven't done this sort of physics before, I definitely recommend getting a introductory good book on physics (with calculus) and working through it. You only need to bother with the sections that apply to mechanics though that is a very large section of the book probably. There might be better routes to pursue though like some of the resources in this question.
If there are no acceleration (x,y) =(xstart+ vx*time ,ystart + vy*time) and speed remain the same, and it is not related to the radius
Since the velocity is constant you will have an angular velocity of omega = vel / radius. You will obtain how many radians you ball will move per second over its circular path.
To get the position at time t you just have to exploit polar coordinates:
x = x_center + sin( 3/2*PI + omega*t)*radius
y = y_center + cos( 3/2*PI + omega*t)*radius
This because you start from bottom point of the circle (so its 3/2*PI) plus how many radiants you move every second (we obtained it from tangential velocity). All multiplied for the radius, otherwise you will consider a unity circle.
EDIT: Since you wonder how to find a position of an object that is subject to many different forces I can tell you that usually a physical engine doesn't care about finding equations of moving objects. It just applies forces to objects considering their intended motions (like your circular one) or environmental factors (like gravity or friction) and calculates coordinates step by step by applying forces and using an integrator to see the results.
Ignoring friction, the forces on the ball are gravity and the track.
First, there are two main cases - is the velocity enough for the ball to loop-the-loop or not:
initial energy = 1/2 m v² = 0.5 * 5 * 200 * 200
potential energy = m g h = 5 * 9.8 * 20
so it will go round the whole loop.
Initially the ball is at the bottom of the loop, theta = 0
The acceleration on the ball is the component of g along the track
a = g⋅sin theta
The distance travelled is theta * radius. It is also the double integral of acceleration against time.
theta ⋅ radius = double integral of acceleration against time
Integrating acceleration once gives velocity, integrating velocity gives distance.
so solve this for t:
theta ⋅ r = ∫(∫ g⋅sin theta.dt).dt
then your x and y are trivial functions of theta.
Whether you solve it analytically or numerically is up to you.
With dynamic friction, friction is usually proportional to the normal force on the bodies. So this will equal the centripetal force - proportional to the square of the angular velocity, and the component of gravity normal to the track (g sin theta)
You didn't tell anything about how you want your velocity to change. Do you have any friction model? If there is no friction, then the formulas are simple:
length = velocity*t
x = sin(length)*radius
y = -cos(length)*radius
If the velocity is changing, then you have to change length to something like
length = integral over dt[0..t] (velocity dt)
The only thing I wanted to add is the if this is real ball (sphere) with mass 5kg then it must have a diameter dia=(6*m/(PI*rho))^(1/3) where rho is the density of the material. For steel (rho=7680) the diameter is dia=0.1075 meters. Therefore the pitch radius (radius at which the center of gravity of the ball rides on) is equal to R=10-(dia/2) or R=9.9466 meters.
The problem gets a little more complex when friction is included. For one you have to consider the direction of friction (assuming dry friction theory). That depends on the amount the ball rotates in its axis and that depends on moment of inertia of the ball.
When you do the simulation you might want to monitor the total kinetic energy + the total potential energy and make sure your are not adding energy to the system (or taking away). [Don't forget to include the rotational component for the kinetic energy]
Get a standard book on dynamics, and I am sure a similar problem is already described in the book.I would recommend "Vector Mechanic for Engineers - Dynamics".