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
Related
I have a list of lists in the form of a multi-value function
*[[var1, [a1,b1,...,z1], [var2, [a2,b2,...,z2]],,,[varn, [an,bn,,,,zn]]]*.
I would like to convert this into a multi-value list first in the form of
*[[var1,a1], [var1,b1],,,[var1,z1],[var2,a2],[var2,b2],,,[var2,z2],,,,]*
so I can then plot those as scattered plot and do further analysis with them. Is there an easier way to do it? If not, how do you do such a conversion?
If I was dealing with a single-value list of lists, here is what I have learned (from this post of mine How to make a binned version of a barplot?):
import numpy as np
import matplotlib.pyplot as plt
A = [[var1,val1], [var2,val2], ...[varn,valn]] # Some single value list of lists
A = np.array(A)
numbins = 7
xmin = 8
xmax = xmin + numbins * 0.6
xrange = xmax - xmin
bounds = np.linspace(xmin, xmax, numbins + 1, endpoint=True)
mids = (bounds[:-1] + bounds[1:]) / 2
bins = [[] for _ in range(numbins)]
for x, y in A:
bins[int((x - xmin) / xrange * numbins)].append(y)
bins = [np.array(b) for b in bins]
means = np.array([np.mean(bin) if len(bin) > 0 else np.nan for bin in bins])
stds = np.array([np.std(bin) if len(bin) > 0 else np.nan for bin in bins])
plt.stem(mids, means + stds, linefmt='k-', markerfmt='k_', use_line_collection=True)
plt.bar(mids, means, width=xrange / numbins, color='salmon', ec='k', zorder=2)
plt.scatter(A[:, 0]+np.random.uniform(-.02, .02, A.shape[0]), A[:, 1],
s=2, color='b', alpha=0.5, zorder=3)
plt.xticks(bounds, [f'{b:.1f}' for b in bounds])
plt.yscale('log')
plt.show()
Thanks,
Try:
[[x[0], x[1][i]] for x in A for i in range(len(x[1]))]
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.
I'm learning python3 and I'd like to print a matrix/2d-array which is color-coded (CLI). So let's say I'd like to assign each of these integers a certain background color, creating a mosaic-style look.
I've figured out how to fill a matrix of a given size with random integers, but I can't wrap my head around on how to continue from here on to achieve background coloring for each individual entry in the matrix, depending on its value. This is how far I've come:
from random import randint
import numpy as np
def generate():
n = 10
m = 0
map = np.random.randint(4 + 1, size=(n, n))
print(map)
for element in np.nditer(map):
# iterating over each column is probably not the way to go...
generate()
Is there a way to do this? I was thinking of iterating through every column of the matrix and check by several if conditions whether the entry is 0,1,2,3 or 4 and, based on the condition, append that value with a certain background color to a new matrix, but I assume there is a far more elegant way to do this...
The following will print a colored output on console...
>>> map = np.random.randint(4 + 1, size=(10, 10))
>>> def get_color_coded_str(i):
... return "\033[3{}m{}\033[0m".format(i+1, i)
...
>>> map_modified = np.vectorize(get_color_coded_str)(map)
>>> print("\n".join([" ".join(["{}"]*10)]*10).format(*[x for y in map_modified.tolist() for x in y]))
>>>
To add background color use following fn
>>> def get_color_coded_str(i):
... return "\033[4{}m{}\033[0m".format(i+1, i)
from random import randint
import numpy as np
def get_color_coded_str(i):
return "\033[3{}m{}\033[0m".format(i+1, i)
def get_color_coded_background(i):
return "\033[4{}m {} \033[0m".format(i+1, i)
def print_a_ndarray(map, row_sep=" "):
n, m = map.shape
fmt_str = "\n".join([row_sep.join(["{}"]*m)]*n)
print(fmt_str.format(*map.ravel()))
n = 10
m = 20
map = np.random.randint(4 + 1, size=(n, m))
map_modified = np.vectorize(get_color_coded_str)(map)
print_a_ndarray(map_modified)
back_map_modified = np.vectorize(get_color_coded_background)(map)
print("-------------------------------------------------------")
print_a_ndarray(back_map_modified, row_sep="")
PS: print function modified as suggested by #hpaulj
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()
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])