mitgcm
Analysis of MITgcm output using python
visualisation.py
Go to the documentation of this file.
1 """!
2 Visualisation functions.
3 
4 Each function has a detailed docstring.
5 """
6 
7 import numpy as np
8 import netCDF4
9 import numba
10 import sys
11 import matplotlib.pyplot as plt
12 import matplotlib.colors
13 import glob
14 import scipy.interpolate
15 import warnings
16 import copy
17 import mitgcm
18 
19 
20 def LIC2_sparse(u,v,points,grid_object,trace_length,kernel='anisotropic_linear',delta_t=3600.):
21  """!Line integral convolution with a sparse noise field. This produces discrete points that flow around the visualisation.
22 
23  LIC is a method for visualising flow fields.
24 
25  -------------
26  ##Parameters
27  * kernel - the convolution kernel. Options are:
28  * 'box'
29  * 'anisotropic_linear'
30 
31 
32 
33  -------------
34  ##Example call
35 
36  \code{.py}
37  output = LIC2_sparse(m.zonal_velocity['UVEL'][3,:,:],m.meridional_velocity['VVEL'][3,:,:],
38  5000,m.grid,15*86400,kernel='anisotropic_linear',delta_t=10*3600)
39 
40  white_var_alpha = mitgcm.visualisation.create_cmap_vary_alpha(colour='k')
41  \endcode
42 
43  Then plot with
44 
45  \code{.py}
46  plt.pcolormesh(m.grid['X'][:],m.grid['Yp1'][:],m.meridional_velocity['VVEL'][level,:,:],cmap='winter',vmin=-1,vmax=1)
47  plt.colorbar()
48  for i in xrange(output.shape[1]):
49  plt.scatter(output[0,i,:],output[1,i,:],
50  c=output[2,i,:],cmap=white_var_alpha,lw=0,vmin=0,vmax=1,s=4)
51  \endcode
52 
53  \callgraph
54 
55  """
56 
57 
58  # temporary variable for setting up the convolution kernel and noise field.
59  trace_length = float(trace_length)
60  delta_t = float(delta_t)
61  steps_per_trace = int(trace_length/delta_t)
62 
63 
64  if kernel == 'anisotropic_linear':
65  k = np.ones(steps_per_trace)
66  for i in xrange(steps_per_trace):
67  k[i] = 1 - float(i)/float(steps_per_trace-1)
68  #k[:int(steps_per_trace/2.)] = 0
69  #k[int(2*kernel_length/4.):] = 0
70  #k = k/np.sum(delta_t*k)
71 
72  #plt.plot(k)
73 
74  noise = np.zeros(2*steps_per_trace)
75  noise[steps_per_trace] = 1
76 
77  intensity = np.zeros((steps_per_trace))
78  for i in xrange(steps_per_trace):
79  intensity[i] = np.sum(k*noise[i:steps_per_trace+i])
80  intensity = intensity/np.max(intensity)
81  #plt.plot(intensity)
82 
83  elif kernel == 'box':
84  k = np.ones(kernel_length)
85  # k[:int(kernel_length/4.)] = 0
86  # k[int(3*kernel_length/4.):] = 0
87  #k = k/np.sum(delta_t*k)
88 
89  noise = np.zeros(2*steps_per_trace)
90  noise[steps_per_trace] = 1
91 
92  intensity = np.zeros((steps_per_trace))
93  for i in xrange(steps_per_trace):
94  intensity[i] = np.sum(k*noise[i:steps_per_trace+i])
95  intensity = intensity/np.max(intensity)
96 
97  else:
98  raise ValueError('Valid options for kernel are: anisotropic_linear, box')
99 
100 
101  x_start = (np.random.random_sample(points)*(np.max(grid_object['Xp1'][:]) - np.min(grid_object['Xp1'][:])) +
102  np.min(grid_object['Xp1'][:]))
103  y_start = (np.random.random_sample(points)*(np.max(grid_object['Yp1'][:]) - np.min(grid_object['Yp1'][:])) +
104  np.min(grid_object['Yp1'][:]))
105 
106  output = np.zeros((3,points,steps_per_trace))
107 
108  for i in xrange(points):
109  x_stream,y_stream,t_stream = mitgcm.streamlines.stream2(u,v,x_start[i],y_start[i],
110  grid_object,trace_length,delta_t)
111 
112  output[0,i,:steps_per_trace] = x_stream[:steps_per_trace]
113  output[1,i,:steps_per_trace] = y_stream[:steps_per_trace]
114  output[2,i,:steps_per_trace] = intensity[:steps_per_trace]
115 
116  return output
117 
118 
119 def LIC2_sparse_animate(u,v,nparticles,grid_object,animation_length,trace_length,kernel='anisotropic_linear',
120  delta_t=3600.):
121  """!Line integral convolution with a sparse noise field. The sparse noise field produces discrete points that travel around with the flow field.
122 
123  This function produces data that can be used to animate a static flow field.
124 
125  LIC is a method for visualising flow fields.
126 
127  returns:
128 
129  * output_matrix = [Variables (this axis has three values: x,y,intensity_ramp),trace_number ,time]
130  * intensity = vector containing the convolved kernel and noise field
131 
132 
133  -------------
134  ##Parameters
135  * kernel - the convolution kernel. Options are:
136  * 'box' - same intensity for the entire trace
137  * 'anisotropic_linear' - intensity ramps up over the trace
138 
139 
140  ------------
141  ##Example call
142 
143  \code{.py}
144  output,intensity = LIC2_sparse_animate(m.zonal_velocity['UVEL'][1,:,:],
145  m.meridional_velocity['VVEL'][1,:,:],
146  15,m.grid,
147  300*86400,60*86400,
148  kernel='anisotropic_linear',delta_t=4*3600)
149  white_var_alpha = mitgcm.visualisation.create_cmap_vary_alpha(colour='k')
150  \endcode
151 
152  and then plot with
153 
154  \code{.py}
155  trace_length= len(intensity)
156 
157  for t0 in xrange(output.shape[2]-len(intensity)):
158  for i in xrange(output.shape[0]):
159  plt.scatter(output[i,0,t0:t0+trace_length],output[i,1,t0:t0+trace_length],
160  c = intensity,cmap='winter',lw=0,vmin=0,vmax=1,s=20)
161 
162  filename = '../OLIC animation{:04g}.png'.format(t0)
163  plt.savefig(filename)
164  plt.clf()
165  \endcode
166 
167  \callgraph
168  """
169 
170 
171  # temporary variable for setting up the convolution kernel and noise field.
172  trace_length = float(trace_length)
173  kernel_length = float(trace_length/4)
174  delta_t = float(delta_t)
175  animation_length = float(animation_length)
176  steps_per_trace = int(trace_length/delta_t)
177  steps_per_kernel = int(kernel_length/delta_t)
178  steps_per_ani = int(animation_length/delta_t)
179 
180 
181  if kernel == 'anisotropic_linear':
182  k = np.ones(steps_per_kernel)
183  for i in xrange(steps_per_kernel):
184  k[i] = 1 - float(i)/float(steps_per_kernel-1)
185  k[:int(steps_per_kernel/2.)] = 0
186  #k[int(2*kernel_length/4.):] = 0
187  #k = k/np.sum(delta_t*k)
188 
189  #plt.plot(k)
190 
191  noise = np.zeros(steps_per_ani)
192  noise[steps_per_kernel] = 1
193 
194  intensity = np.zeros((steps_per_ani))
195  for i in xrange(steps_per_ani - steps_per_kernel):
196  intensity[i] = np.sum(k*noise[i:steps_per_kernel+i])
197  intensity = intensity/np.max(intensity)
198  #plt.plot(intensity)
199 
200  elif kernel == 'box':
201  k = np.ones(kernel_length)
202  # k[:int(kernel_length/4.)] = 0
203  # k[int(3*kernel_length/4.):] = 0
204  #k = k/np.sum(delta_t*k)
205 
206  noise = np.zeros((steps_per_trace))
207  noise[int(len(noise)/2)] = 1
208 
209  intensity = np.zeros((steps_per_ani))
210  for i in xrange(kernel_length):
211  intensity[i] = np.sum(k*noise[i:kernel_length+i])
212  intensity = intensity/np.max(intensity)
213 
214  else:
215  raise ValueError('Valid options for kernel are: anisotropic_linear, box')
216 
217 
218 
219 
220  output = np.zeros((nparticles,2,steps_per_ani))
221  #intensity = np.zeros((2,nparticles,steps_per_ani+steps_per_trace))
222 
223  x_start = (np.random.random_sample(nparticles)*(np.max(grid_object['Xp1'][:]) - np.min(grid_object['Xp1'][:])) +
224  np.min(grid_object['Xp1'][:]))
225  y_start = (np.random.random_sample(nparticles)*(np.max(grid_object['Yp1'][:]) - np.min(grid_object['Yp1'][:])) +
226  np.min(grid_object['Yp1'][:]))
227  # first lot of particle tracks
228  for i in xrange(nparticles):
229 
230 
231  x_stream,y_stream,t_stream = mitgcm.streamlines.stream2(u,v,x_start[i],y_start[i],
232  grid_object,trace_length,delta_t)
233 
234 
235  output[i,0,:steps_per_trace] = x_stream[:steps_per_trace]
236  output[i,1,:steps_per_trace] = y_stream[:steps_per_trace]
237 
238 
239  # second lot of particle tracks
240  # these ones start randomly during the first lot
241  x_start = (np.random.random_sample(nparticles)*(np.max(grid_object['Xp1'][:]) - np.min(grid_object['Xp1'][:])) +
242  np.min(grid_object['Xp1'][:]))
243  y_start = (np.random.random_sample(nparticles)*(np.max(grid_object['Yp1'][:]) - np.min(grid_object['Yp1'][:])) +
244  np.min(grid_object['Yp1'][:]))
245  for i in xrange(nparticles):
246 
247  x_stream,y_stream,t_stream = mitgcm.streamlines.stream2(u,v,x_start[i],y_start[i],
248  grid_object,trace_length,delta_t)
249 
250  t0 = int(np.random.random_sample(1)*(steps_per_trace))
251 
252 
253  output[i,0,t0:t0+steps_per_trace] = x_stream[:steps_per_trace]
254  output[i,1,t0:t0+steps_per_trace] = y_stream[:steps_per_trace]
255 
256 
257  # Now have two sets of particle tracks for each particle
258  # and the second lot have starting times that are random
259  # Now, go through and put in the rest of the animations worth of tracks
260  # Do this by finding places in the output array where there aren't yet particle tracks
261  for n in xrange(nparticles):
262 
263  for trace in xrange(int(np.floor(animation_length/trace_length)-2)):
264 
265  indices = np.where(output[n,0,:]==output[n,1,:])
266  t_ind = indices[0][0]
267 
268  if t_ind+steps_per_trace < steps_per_ani:
269 
270  x_start = (np.random.random_sample(1)*(np.max(grid_object['Xp1'][:]) - np.min(grid_object['Xp1'][:])) +
271  np.min(grid_object['Xp1'][:]))
272  y_start = (np.random.random_sample(1)*(np.max(grid_object['Yp1'][:]) - np.min(grid_object['Yp1'][:])) +
273  np.min(grid_object['Yp1'][:]))
274 
275  x_stream,y_stream,t_stream = mitgcm.streamlines.stream2(u,v,x_start,y_start,
276  grid_object,trace_length,delta_t)
277 
278  output[n,0,t_ind:t_ind+steps_per_trace] = x_stream[:steps_per_trace]
279  output[n,1,t_ind:t_ind+steps_per_trace] = y_stream[:steps_per_trace]
280 
281 
282  return output,intensity[:int(steps_per_kernel/2.)]
283 
284 
285 def create_cmap_vary_alpha(colour='white'):
286  """!Create a colour map with variable alpha. This can be used to sketch out particles as they move.
287 
288  The only input variable 'coour' defines the colour that is used to create the colour map. It can be any colour code that matplotlib recognises: single letter codes, hex colour string, a standard colour name, or a string representation of a float (e.g. '0.4') for gray on a 0-1 scale."""
289 
290  rgb = matplotlib.colors.colorConverter.to_rgb(colour) # convert the input colour to an rgb tuple
291 
292  # take a predefined colour map and hack it.
293  newCM = copy.deepcopy(plt.cm.get_cmap('bone_r'))
294  newCM._init()
295 
296  alphas = np.abs(np.linspace(0, 1.0, newCM.N))
297  newCM._lut[:-3,-1] = alphas
298  newCM._lut[:,0] = rgb[0]
299  newCM._lut[:,1] = rgb[1]
300  newCM._lut[:,2] = rgb[2]
301 
302  return newCM
def LIC2_sparse
Line integral convolution with a sparse noise field.
def create_cmap_vary_alpha
Create a colour map with variable alpha.
def LIC2_sparse_animate
Line integral convolution with a sparse noise field.
def stream2
A two-dimensional streamline solver.
Definition: streamlines.py:29