Calling a function from an external file in Python - python-3.x

Im trying to call a function from a different file in python. Im trying to process satellite images from Goes 16 in NetCDF format. Im extracting different values from the file necessary for the functions saved in a .py file called "remap". A piece of my main code goes like this:
from remap import remap
# Calculate the image extent required for the reprojection
H = nc.variables['goes_imager_projection'].perspective_point_height
x1 = nc.variables['x_image_bounds'][0] * H
x2 = nc.variables['x_image_bounds'][1] * H
y1 = nc.variables['y_image_bounds'][1] * H
y2 = nc.variables['y_image_bounds'][0] * H
# Projection Prameters
lat_0 = nc.variables['goes_imager_projection'].latitude_of_projection_origin
lon_0 = nc.variables['goes_imager_projection'].longitude_of_projection_origin
a = nc.variables['goes_imager_projection'].semi_major_axis
b = nc.variables['goes_imager_projection'].semi_minor_axis
f = 1/nc.variables['goes_imager_projection'].inverse_flattening
# Call the reprojection funcion
grid = remap(path, extent, resolution, x1, y1, x2, y2)
In the .py file that I called "remap", the function is defined as:
# Define KM_PER_DEGREE
KM_PER_DEGREE = 111.32
# GOES-16 Spatial Reference System
sourcePrj = osr.SpatialReference()
sourcePrj.ImportFromProj4('+proj=geos +h=' + H + ' +a=' + a + ' +b=' + b + ' +f=' + f + 'lat_0=' + lat_0 + ' +lon_0=' + lon_0 + ' +sweep=x +no_defs')
# Lat/lon WSG84 Spatial Reference System
targetPrj = osr.SpatialReference()
targetPrj.ImportFromProj4('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')
def remap(path, extent, resolution, x1, y1, x2, y2):
... (and so on)
Now I have two different problems:
(1) My frist problem is that Im getting an error from the system saying:
"remap() takes 4 positional arguments but 7 were given", which I dont understand why is happening, because I already defined those 7 arguments in the function from the second file called "remap"
(2) My second problem is that I don't know how to call values from my original code that where extracted from the NetCDF file such as: "lat_0, lon_0, a, b, f, and H" to be used in the second file which are necessary from the beginning to used the function "remap".
Any suggestions?

to your first problem:
How do you define the path, extent and resolution needed in remap()?
and to your second problem:
You don't need to call those arguments on the remap file, because from the main code your are calling remap and make the reprojection with those 7 arguments.

Related

Plotting graphs of differentiated functions on Octave

I learnt how to differentiate on octave through this. But I now want to plot graph of the same function on octave. I am not able to do so. I want to know what the right command for plotting the 'ffd' equation in the code is.
`f = #(x) x.^2 + 3*x - 1 + 5*x.*sin(x);
pkg load symbolic
syms x;
ff = f(x);
ffd = diff(ff, x) `
What I have tried so far: I have tried adding these lines of code to the end and it didn't work. The graph was empty and I got an error.
real
ffd = (sym) 5⋅x⋅cos(x) + 2⋅x + 5⋅sin(x) + 3
error: __go_line__: invalid value for array property "ydata", unable to create graphics handle
error: called from
__plt__\>__plt2vs__ at line 466 column 15
__plt__\>__plt2__ at line 245 column 14
__plt__ at line 112 column 18
plot at line 229 column 10
real at line 10 column 1\`
I was expecting it to plot the graph of (sym) 5⋅x⋅cos(x) + 2⋅x + 5⋅sin(x) + 3 i.e., ffd, but it didn't work
In order to draw graphs of the differentiated functions we need to have code similar to this and in this case I am using pkg symbolic
pkg load symbolic
syms x;
x = sym('x');
y = #(x) x.^3;
yy = y(x);
ffd = diff(diff(yy,x));
ffe = diff(yy,x);
ez1=ezplot(y,[-10,10])
hold on
ez2=ezplot(ffe,[-10,10])
hold on
ez3=ezplot(ffd,[-10,10])
note: hold on function is used to draw more than one graphs on the same screen. However, if you modify the program and run it again it doesn't clear the screen of the previous graphs, if anyone knows how to do this, please leave a comment.

Solving vector second order differential equation while indexing into an array

I'm attempting to solve the differential equation:
m(t) = M(x)x'' + C(x, x') + B x'
where x and x' are vectors with 2 entries representing the angles and angular velocity in a dynamical system. M(x) is a 2x2 matrix that is a function of the components of theta, C is a 2x1 vector that is a function of theta and theta' and B is a 2x2 matrix of constants. m(t) is a 2*1001 array containing the torques applied to each of the two joints at the 1001 time steps and I would like to calculate the evolution of the angles as a function of those 1001 time steps.
I've transformed it to standard form such that :
x'' = M(x)^-1 (m(t) - C(x, x') - B x')
Then substituting y_1 = x and y_2 = x' gives the first order linear system of equations:
y_2 = y_1'
y_2' = M(y_1)^-1 (m(t) - C(y_1, y_2) - B y_2)
(I've used theta and phi in my code for x and y)
def joint_angles(theta_array, t, torques, B):
phi_1 = np.array([theta_array[0], theta_array[1]])
phi_2 = np.array([theta_array[2], theta_array[3]])
def M_func(phi):
M = np.array([[a_1+2.*a_2*np.cos(phi[1]), a_3+a_2*np.cos(phi[1])],[a_3+a_2*np.cos(phi[1]), a_3]])
return np.linalg.inv(M)
def C_func(phi, phi_dot):
return a_2 * np.sin(phi[1]) * np.array([-phi_dot[1] * (2. * phi_dot[0] + phi_dot[1]), phi_dot[0]**2])
dphi_2dt = M_func(phi_1) # (torques[:, t] - C_func(phi_1, phi_2) - B # phi_2)
return dphi_2dt, phi_2
t = np.linspace(0,1,1001)
initial = theta_init[0], theta_init[1], dtheta_init[0], dtheta_init[1]
x = odeint(joint_angles, initial, t, args = (torque_array, B))
I get the error that I cannot index into torques using the t array, which makes perfect sense, however I am not sure how to have it use the current value of the torques at each time step.
I also tried putting odeint command in a for loop and only evaluating it at one time step at a time, using the solution of the function as the initial conditions for the next loop, however the function simply returned the initial conditions, meaning every loop was identical. This leads me to suspect I've made a mistake in my implementation of the standard form but I can't work out what it is. It would be preferable however to not have to call the odeint solver in a for loop every time, and rather do it all as one.
If helpful, my initial conditions and constant values are:
theta_init = np.array([10*np.pi/180, 143.54*np.pi/180])
dtheta_init = np.array([0, 0])
L_1 = 0.3
L_2 = 0.33
I_1 = 0.025
I_2 = 0.045
M_1 = 1.4
M_2 = 1.0
D_2 = 0.16
a_1 = I_1+I_2+M_2*(L_1**2)
a_2 = M_2*L_1*D_2
a_3 = I_2
Thanks for helping!
The solver uses an internal stepping that is problem adapted. The given time list is a list of points where the internal solution gets interpolated for output samples. The internal and external time lists are in no way related, the internal list only depends on the given tolerances.
There is no actual natural relation between array indices and sample times.
The translation of a given time into an index and construction of a sample value from the surrounding table entries is called interpolation (by a piecewise polynomial function).
Torque as a physical phenomenon is at least continuous, a piecewise linear interpolation is the easiest way to transform the given function value table into an actual continuous function. Of course one also needs the time array.
So use numpy.interp1d or the more advanced routines of scipy.interpolate to define the torque function that can be evaluated at arbitrary times as demanded by the solver and its integration method.

How to make a double loop inside a dictionary in Python?

I have a data cube with 2 dimensions of coordinates and a third dimension for wavelength. My goal is to write a mask for coordinates outside a circle of given radius to the central coordinates (x0 and y0 in my code). For this, I'm trying to use a dictionary, but I'm having throuble because it seems that I'll have to make a double loop inside the dictionary to iterate over the two dimensions, and as a beginner with dictionaries, I don't know yet how to do that.
I wrote the following code
x0 = 38
y0 = 45
radius = 9
xcoords = np.arange(1,flux.shape[1]+1,1)
ycoords = np.arange(1,flux.shape[2]+1,1)
mask = {'xmask': [xcoords[np.sqrt((xcoords[:]-x0)**2 + (y-y0)**2) < radius] for y in ycoords], 'ymask': [ycoords[np.sqrt((x-x0)**2 + (ycoords[:]-y0)**2) < radius] for x in xcoords]}
And it returned several arrays, one for each value of y (for xmasks), and one for each value of x (for ymasks), although I want just one array for each one. Could anyone say what I made wrong and how to achieve my goal?
Note: I also made it without using a dictionary, as
xmask = []
for x in xcoords:
for y in ycoords:
if np.sqrt((x-x0)**2 + (y-y0)**2) < radius:
xmask.append(x)
break
ymask = []
for y in xcoords:
for x in ycoords:
if np.sqrt((x-x0)**2 + (y-y0)**2) < radius:
ymask.append(y)
break
but I hope it's possible to make it more efficiently.
Thanks for any help!
Edit: I realized that no loop was needed. If I select y = y0 and x = x0, I get the values of x and y that are inside the circle, respectively. So I stayed with
mask = {'xmask': [xcoords[abs(xcoords[:]-x0) < radius]], 'ymask': [ycoords[abs(ycoords[:]-y0) < radius]]}
The OP explains that assigning
mask = {'xmask': [xcoords[abs(xcoords[:] - x0) < radius]],
'ymask': [ycoords[abs(ycoords[:] - y0) < radius]]}
solves the problem.

Defining a dynamic function in Python

I'm trying to minimise a function using BFGS method. Initially, I'm creating my functions as expressions. In the first iteration, my first expression is
f_sym = ((x0 - x6)**2 + (y0 - y6)**2)**0.5 + ((x0 - x9)**2 + (y0 - y9)**2)**0.5 + ((-x1 + 36)**2 + (-y1 + 9)**2)**0.5 + ((x1 - x7)**2 + (y1 - y7)**2)**0.5 + ((-x10 + x3)**2 + (-y10 + y3)**2)**0.5 + ((-x10 + x7)**2 + (-y10 + y7)**2)**0.5 + ((-x12 + x3)**2 + (-y12 + y3)**2)**0.5 + ((-x12 + x6)**2 + (-y12 + y6)**2)**0.5 + ((-x9 + 48)**2 + (-y9 + 97)**2)**0.5
variables = [x1, y1, x9, y9, x0, y0, x6, y6, x7, y7, x3, y3, x10, y10, x12, y12] #variables of the function expression f_sym
fprime_sym = [f_sym.diff(x_) for x_ in variables] # derivative of f_sym
To create vectorised functions for the above symbolic expressions, I use sympy.lamdify as follows:
f_lmbda = sympy.lambdify(symvar, f_sym, 'numpy')
fprime_lmbda = sympy.lambdify(symvar, fprime_sym, 'numpy')
The functions produced by sympy.lambdify take one argument for each variable in the corresponding expression. Also the SciPy optimization functions expect a vectorized function where all coordinates are packed into one array. To obtain functions that are compatible with the SciPy optimization routines, we need to wrap each of the functions generated by sympy.lambdify with a Python function that reshuffles the arguments.I tried it as follows:
def func_XY_to_X_Y(f):
""" Wrapper for f(X) -> f(X[0], X[1])"""
return lambda X: np.array(f(X[0],X[1],X[2],X[3],X[4],X[5],X[6],X[7],X[8],X[9],X[10],X[11],X[12],X[13],X[14])) #since f_sym has 14 parameters we need 14 X[i]s
f = func_XY_to_X_Y(f_lmbda)
fprime = func_XY_to_X_Y(fprime_lmbda)
Now the functions f and fprime are vectorized Python functions. Then,
x_opt = optimize.fmin_ncg(f, x_0, fprime=fprime, fhess=fhess) #x_0 is the initial condition for all the variables
This solves the function and returns the new array of values for variables.
If there's only one function expression, this process can be done manually.
But if this happens inside a loop, the number of variables in each function expression will be different. Hence I need to make my def func_XY_to_X_Y(f): a dynamic one.
Can someone please help me to make this a dynamic one?
Use the *-argument unpacking operator:
def func_XY_to_X_Y(f):
""" Wrapper for f(X) -> f(X[0], X[1], ..., X[n])"""
return lambda X: np.array(f(*X))

Generate a random point on an elliptical curve

I'm writing a program which randomly chooses two integers within a certain interval. I also wrote a class (which I didn't add below) which uses two numbers 'a' and 'b' and creates an elliptical curve of the form:
y^2 = x^3 + ax + b
I've written the following to create the two random numbers.
def numbers():
n = 1
while n>0:
a = random.randint(-100,100)
b = random.randint(-100,100)
if -16 * (4 * a ** 3 + 27 * b ** 2) != 0:
result = [a,b]
return result
n = n+1
Now I would like to generate a random point on this elliptical curve. How do I do that?
The curve has an infinite length, as for every y ϵ ℝ there is at least one x ϵ ℝ so that (x, y) is on the curve. So if we speak of a random point on the curve we cannot hope to have a homogeneous distribution of the random point over the whole curve.
But if that is not important, you could take a random value for y within some range, and then calculate the roots of the following function:
f(x) = x3 + ax + b - y2
This will result in three roots, of which possibly two are complex (not real numbers). You can take a random real root from that. This will be the x coordinate for the random point.
With the help of numpy, getting the roots is easy, so this is the function for getting a random point on the curve, given values for a and b:
def randomPoint(a, b):
y = random.randint(-100,100)
# Get roots of: f(x) = x^3 + ax + b - y^2
roots = numpy.roots([1, 0, a, b - y**2])
# 3 roots are returned, but ignore potential complex roots
# At least one will be real
roots = [val.real for val in roots if val.imag == 0]
# Choose a random root among those real root(s)
x = random.choice(roots)
return [x, y]
See it run on repl.it.

Resources