2
$\begingroup$

If I were to have a data for a one-dimensional system evolving in time, essentially a two-dimensional array, and the array at each point in time is of the same size, how would I produce something like this:

Example

(Taken from Turing’s model for biological pattern formation and the robustness problem by Maini et al., 2012)

I have tried to replicate this with matplotlib by resizing (or rather synthesising) each instance in time to an array of specific length, according to the growth of the domain, and filling the rest of the array with NaNs.

import numpy as np
import matplotlib.pyplot as plt

N = 750
x = []

t = np.linspace(0, N, N)

def asize(i, N):        # Computes the necessary size of the array
    return int(N*np.exp(2*(i-N)/N))

for i in range(N):      # Concatenating data with whitespace 
    x.append(np.concatenate((np.sin(np.linspace(0,3*np.pi,asize(i,N)))**2,
                             np.NaN*np.zeros(N-asize(i,N)))))


x = np.transpose(np.array(x))
plt.imshow(x, cmap = 'Spectral_r', origin = 'lower')
plt.plot(t, N*np.exp(2*(t-N)/N), c='white', lw = 2)     # Making the boundary smoother
plt.axis([0,N,0,N])
plt.xlabel('$t$')
plt.ylabel('$x$')
plt.xticks([0,250,500,750])
plt.yticks([0,250,500,750])
plt.show()

Attempt

Naturally, with actual data this method would be even more tedious, requiring to somehow squish the arrays. Is there a more reasonable way of doing this with matplotlib, Mathematica or any other tool?

$\endgroup$
2
  • $\begingroup$ If are able to explain how the original figure is obtained, maybe we can help you with how to do it. $\endgroup$
    – nicoguaro
    Apr 13, 2020 at 1:53
  • $\begingroup$ It is a simulation of a system on a 1D domain using finite differences. The growth of the domain is supposedly achieved by changing the value of a parameter with time, so the actual number of points doesn't change. The problem then is to "squeeze" this data under an appropriate growth curve. $\endgroup$
    – strider
    Apr 13, 2020 at 9:09

1 Answer 1

1
$\begingroup$

I answered a similar question in StackOverflow.

The main "trick" is to transform your grid before plotting. For example, using the following transformation

\begin{align} &t' = t\, ,\\ &x' = x e^t\, , \end{align}

and then use $(t', x')$ for your plot with contourf() or pcolormesh().

Following is a snippet showing the main idea.

import numpy as np
import matplotlib.pyplot as plt

t, x = np.pi*np.mgrid[0:1:100j, 0:1:100j]
val = x
new_x = x*np.exp(t)

# plt.contourf(t, new_x, val)
plt.pcolormesh(t, new_x, val)
plt.xlabel("t")
plt.ylabel("x")
plt.show()

And this is the result.

enter image description here

$\endgroup$
1
  • $\begingroup$ Thanks, this is what I was looking for! $\endgroup$
    – strider
    Apr 14, 2020 at 9:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.