Numpy best way to assign array to a single point in another array (4D) - arrays

I would like to store each one of the arrays (new_grid) at a given cell on another array (master_grid), which varies according to i and j:
master_grid[i][j]=new_grid
When I run the code it returns the following error for the above line:
<ipython-input-233-e449b6b2f1a1> in <module>
16 new_grid=coordinates_within_radius(coords_ref, coords_grid, radius)
17
---> 18 master_grid[i,j]=new_grid
TypeError: list indices must be integers or slices, not tuple
I'm using both numpy and xarray, but so far couldn't figure out a way of indexing the "inner" arrays into the master_grid.
As it can be seen in the code, there is a function that determines which points are within a radius and the result is a grid with latitude and longitude.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import xarray as xr
import cartopy.crs as ccrs
import seaborn as sns
import geopy.distance
### Code for locating points within a radius
def coordinates_within_radius( coords_ref, coords_grid, radius ):
if type(coords_grid) == np.ndarray or type(coords_grid) == list:
new_grid = [coords_grid[i] for i in range(len(coords_grid)) if geopy.distance.distance(coords_ref, coords_grid[i]).km < radius]
else:
if geopy.distance.distance(coords_ref, coords_grid).km < radius:
new_grid=coords_grid;
if len(new_grid) == 0:
print('the grid is empty')
return new_grid
storm=[1,2,3,4]
date_time=[1,2,3,4,5]
radius=500
scale_lat=6
master_grid=[]
for i in range(len(storm)):
for j in range(len(date_time)):
coords_ref = [30, -80]
lon = np.arange(coords_ref[1] - scale_lat,coords_ref[1] + scale_lat, 0.25)
lat = np.arange(coords_ref[0] - scale_lat,coords_ref[0] + scale_lat, 0.25)
coords_grid=np.zeros((len(lon) * len(lat), 2))
coords_grid = [[lat[y],lon[x]] for x in range(len(lat)) for y in range(len(lon))]
new_grid=coordinates_within_radius(coords_ref, coords_grid, radius)
master_grid[i,j]=new_grid

master_grid = np.zeros((len(storm), len(date_time)))
instead of master_grid=[] should solve the problem.

Related

Computing the Pearson Correlation coefficient between a set of model weights trained in Keras

I am training an ImageNet-pretrained VGG-16 model in Keras with two different hyperparameter settings. I prefer to see if there exists a linear relationship between the two sets of model weights. For simplicity, I have taken two VGG-16 models just to check if my approach works. I have computed the layer weights for each model and stored them as a 1-dimensional array, each having a shape of (1, 512). I wish to measure the Pearson Correlation coefficient between these two model weights as used in this study https://arxiv.org/pdf/1910.08475v2.pdf. My code is as shown below:
import os
from tensorflow import keras
from tensorflow.keras import backend as K
from tensorflow.keras.layers import *
from tensorflow.keras import applications
from tensorflow.keras.models import Model
from scipy.stats import pearsonr
from numpy import array
model_input = (224,224,3)
model1 = applications.VGG16(include_top=False,
weights='imagenet',
input_shape=model_input)
model1.summary()
n_layers1 = len(model1.get_weights())
for layer1 in range(n_layers1):
layer_weights1 = array([model1.get_weights()[layer1]]) # shape [1 x 512]
model2 = applications.VGG16(include_top=False,
weights='imagenet',
input_shape=model_input)
model2.summary()
n_layers2 = len(model2.get_weights())
for layer2 in range(n_layers2):
layer_weights2 = array([model2.get_weights()[layer2]]) # shape [1 x 512]
# calculate Pearson's correlation
corr, _ = pearsonr(layer_weights1, layer_weights2)
print('Pearsons correlation: %.3f' % corr)
I am getting the following error:
File "C:\Users\AppData\Local\Temp\2/ipykernel_16136/1139308701.py", line 1, in <module>
corr, _ = pearsonr(layer_weights1, layer_weights2)
File "C:\Users\AppData\Local\Continuum\anaconda3\envs\tf2.7\lib\site-packages\scipy\stats\stats.py", line 4016, in pearsonr
raise ValueError('x and y must have length at least 2.')
ValueError: x and y must have length at least 2.
Is my approach correct?
I found a solution to my problem. It is the shape mismatch error due to the syntax for the computation of the Pearson correlation coefficient. The revised code is as shown below:
import os
from tensorflow import keras
from tensorflow.keras import backend as K
from tensorflow.keras.layers import *
from tensorflow.keras import applications
from tensorflow.keras.models import Model
from scipy.stats import pearsonr
from numpy import array
import numpy as np
model_input = (224,224,3)
model1 = applications.VGG16(include_top=False,
weights='imagenet',
input_shape=model_input)
model1.summary()
n_layers1 = len(model1.get_weights())
for layer1 in range(n_layers1):
layer_weights1 = array([model1.get_weights()[layer1]])
model2 = applications.VGG16(include_top=False,
weights='imagenet',
input_shape=model_input)
model2.summary()
n_layers2 = len(model2.get_weights())
for layer2 in range(n_layers2):
layer_weights2 = array([model2.get_weights()[layer2]])
# calculate Pearson's correlation
x1 = layer_weights1.transpose()
x2 = layer_weights1.transpose()
x11 = x1.reshape(-1)
x22 = x2.reshape(-1)
corr, sig = pearsonr(x11, x22)
print('Pearsons correlation: %.4f' % corr)

only size-1 arrays can be converted to Python scalars / Rasterio

I have this code and my aim to calculate the sin of my raster in the power of 0.8.
import os
os.chdir('D:/NOA/Soil_Erosion/test_Project/Workspace/Input_Data_LS_Factor')
import rasterio
import math
data = rasterio.open('Slope_degrees_clipped.tif')
band = data.read(1) # array of float32 with size (3297,2537)
w = band.shape[0]
print(w)
h = band.shape[1]
print(h)
dtypes =data.dtypes[0]
band_calc = math.sin(band)**0.8 # the formula I would like to calculate
However, the following error pops up:
only size-1 arrays can be converted to Python scalars / Rasterio
May you know how I should fix this?
P.S. I tried to vectorize it (np.vectorize()) but it does not work as it needs a real number.
When I use the np.ndarray.flatten(band) the same error occurs.
I found the solution on Geographic Information Systems:
import os
os.chdir('D:/NOA/Soil_Erosion/test_Project/Workspace/Input_Data_LS_Factor')
import rasterio
import math
data = rasterio.open('Slope_degrees_clipped.tif')
from rasterio.plot import show
show(data)
band = data.read(1) # array of float32 with size (3297,2537)
w = band.shape[0]
print(w)
h = band.shape[1]
print(h)
dtypes =data.dtypes[0]
Calculate the sine of the raster in the power of 0.8
import numpy as np
band_calc2 = np.sin(band)**0.8 # the formula I would like to calculate
"""
another way to do it
band_calc = [ [] for i in range(len(band)) ]
for i,row in enumerate(band):
for element in row:
band_calc[i].append(math.sin(element*math.pi/180)**0.8)
"""

calculating logistic map in real time misses many results

Many code examples of calculating the logistic map function
use arrays. For example
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
def logistic(r, x):
return r * x * (1 - x)
n = 1000
r = np.linspace(2.5, 4., n)
iterations = 1000
last = 900
x = 1e-5 * np.ones(n)
fig, ax1 = plt.subplots(figsize=(8, 8))
for i in range(iterations):
x = logistic(r, x)
if i >= (iterations - last):
ax1.plot(r, x, ',k', alpha=.25)
ax1.set_xlim(2.5, 4)
ax1.set_title("Bifurcation diagram")
This is the result:
However, I am trying to make real time plot of the function. My attempt results in many values being omitted.
import ipywidgets as widgets
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
def logistic(r, s):
return r * s * (1 - s)
fig = plt.figure()
ax = fig.add_subplot(111)
plt.ion()
fig.show()
fig.canvas.draw()
#j goes from 2.5 to 4
for j in [float(j) / 100 for j in range(250, 400, 1)]:
x=0.2
# for a given value of j, iterate the logistic function 1000x
for i in range(1000):
y=logistic(j, x)
x=y
#plot the iterated logistic function for a given value of j
ax.plot(j,y,'ko',markersize=1)
fig.canvas.draw()
It looks really bad.
It seems half the data is missing and the data points for larger values of r appear sparse. How can I iterate the logistic function to obtain all the values for a given r?
I figured it out. Basically, the logistic map 'explodes' and becomes chaotic only after it is iterated a few times. So, I have to iterate a few times 'silently' (to allow the function to converge if it will) and then to print out the next few iterated values like so.
import ipywidgets as widgets
%matplotlib notebook
import numpy as np
import matplotlib.pyplot as plt
import time
def logistic(r, s):
return r * s * (1 - s)
fig = plt.figure()
ax = fig.add_subplot(111)
plt.ion()
fig.show()
fig.canvas.draw()
#j goes from 2.5 to 4
j=2.5
#for j in [float(j) / 500 for j in range(1250, 2000, 1)]:
while j<4:
x=0.2
# for a given value of j, iterate the logistic function 1000x
for i in range(30):
y=logistic(j, x)
x=y
for i in range(50):
y=logistic(j, x)
ax.plot(j,y,'ko',markersize=.2)
x=y
#plot the iterated logistic function for a given value of j
fig.canvas.draw()
j=j+.01
which gives

why do i get "'numpy.ndarray' object is not callable" with if statement

Im new to programming and im trying to plot a graph where i want my "y" function to differ with a specific condition of x. This is how i tried to do it:
import matplotlib.pyplot as plt
import numpy as np
x= np.arange(0,10,0.1)
if x(x<5):
y=x
else:
y=0
plt.plot(x,y)
plt.show()
plt.plot(x, [x_ if x_ < 5 else 0 for x_ in x])
The plot method plots x versus y as lines and/or markers. The y array is created based on the values of x array using list comprehension
y = [x_ if x_ < 5 else 0 for x_ in x]
It is exactly same as
y = list()
for i in range(len(x)):
if x[i] < 5:
y.append(x[i])
else:
y.append(0)
The error originates from x(x<5). Python parses the first x as a function and try to call it for the argument x<5, thus triggering an error, because x is not a function that you can call, it's an numpy.ndarray, thus explaining the numpy.ndarray object is not callable error.
Try this:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0,10,0.1)
y = [(xx if xx<5 else 0) for xx in x]
plt.plot(x,y)
plt.show()

IndexError: list assignment index out of range in python 2.7.11

I was just solving a problem using python, and my codes are:
from math import sin,pi
import numpy
import numpy as np
import pylab
N=20
x = np.linspace(0,1, N)
def v(x):
return 100*sin(pi*x)
#set up initial condition
u0 = [0.0] # Boundary conditions at t= 0
for i in range(1,N):
u0[i] = v(x[i])
And I would want to plot the results by updating v(x) in range(0, N) after. it looks simple but perhaps you guys could help since it gives me an error, like
Traceback (most recent call last):
File "/home/universe/Desktop/Python/sample.py", line 13, in <module>
u0[i] = v(x[i])
IndexError: list assignment index out of range
You could change u0[i] = v(x[i]) to u0.append(v(x[i])). But you should write more elegantly as
u0 = [v(xi) for xi in x]
Indices i are bug magnets.
Since you are using numpy, I'd suggest using np.vectorize. That way you can pass the array x directly to the function and the function will return an array of the same size with the function applied on each element of the input array.
from math import sin,pi
import numpy
import numpy as np
import pylab
N=20
x = np.linspace(0,1, N)
def v(x):
return 100*sin(pi*x)
vectorized_v = np.vectorize(v) #so that the function takes an array of x's and returns an array again
u0 = vectorized_v(x)
Out:
array([ 0.00000000e+00, 1.64594590e+01, 3.24699469e+01,
4.75947393e+01, 6.14212713e+01, 7.35723911e+01,
8.37166478e+01, 9.15773327e+01, 9.69400266e+01,
9.96584493e+01, 9.96584493e+01, 9.69400266e+01,
9.15773327e+01, 8.37166478e+01, 7.35723911e+01,
6.14212713e+01, 4.75947393e+01, 3.24699469e+01,
1.64594590e+01, 1.22464680e-14])
u is a list with one element, so you can't assign values to indices that don't exist. Instead make u a dictionary
u = {}
u[0] = 0.0
for i in range(1,N):
u[i] = v(x[i])

Resources