def convert_2dpath_to_3dpath(self, z, zdir = 'z'): ''' convert a path on flat surface to 3d path ''' #print("calling convert 2dpath to 3dpath") x1 = []; y1 = []; z1 =[]; norms = []; idxset = [] idxbase = 0 if zdir == 'x': norm = np.array([1., 0, 0.]) elif zdir == 'y': norm = np.array([0., 1, 0.]) else: norm = np.array([0., 0, 1.]) txs, tys, tzs, ones = self._vec xyzlist = [(txs[si:ei], tys[si:ei], tzs[si:ei]) \ for si, ei in self._segis] for v0, v1, v2 in xyzlist: x1.append(v0) y1.append(v1) idxset.append(np.arange(len(v0))+idxbase) z1.append(v2) # norms.append(np.hstack([norm]*len(v0))) idxbase = len(v0)+idxbase x1 = np.hstack(x1) y1 = np.hstack(y1) z1 = np.hstack(z1) # norms = np.hstack(norms).reshape(-1, 3) X3D, Y3D, Z3D = juggle_axes(x1, y1, z1, zdir) norms = np.array([norm]).reshape(-1, 3) self._gl_3dpath = [X3D, Y3D, Z3D, norms, idxset]
def convert_2dpath_to_3dpath(self, z=None, zdir = 'z'): x1 = []; y1 = []; z1 =[]; norms = []; idxset = [] idxbase = 0 if zdir == 'x': norm = np.array([1., 0, 0.]) elif zdir == 'y': norm = np.array([0., 1, 0.]) else: norm = np.array([0., 0, 1.]) xyzlist = [] for points in self._segments3d: points = np.vstack(points) xyzlist.append((points[:,0], points[:, 1], points[:,2],)) # xyzlist = [(points[:,0], points[:, 1], points[:,2]) # for points in self._segments3d] for v0, v1, v2 in xyzlist: x1.append(v0) y1.append(v1) idxset.append(np.arange(len(v0))+idxbase) z1.append(v2) norms.append(np.hstack([norm]*len(v0))) idxbase = len(v0)+idxbase x1 = np.hstack(x1) y1 = np.hstack(y1) z1 = np.hstack(z1) norms = np.hstack(norms).reshape(-1, 3) X3D, Y3D, Z3D = juggle_axes(x1, y1, z1, zdir) ##does norm may mean anything, but let's leave it... self._gl_3dpath = [X3D, Y3D, Z3D, norms, idxset]
def animate(i): gamma = point_defects(self,snap_to_time(snap_start+i,self)) gamma_transited = gamma.transi(tran) inter = gamma_transited['inter'][:] vac = gamma_transited['vac'][:] # 3 arrays containing the coordinates of the interstitials xi,yi,zi = np.transpose(inter) # 3 arrays containing the coordinates of the vacancies xv,yv,zv = np.transpose(vac) pi._offsets3d = juggle_axes(xi,yi,zi,'z') pv._offsets3d = juggle_axes(xv,yv,zv,'z') ''' ax.clear() ax.scatter(xi,yi,zi, label='Interstitials', c='r', marker='^') ax.scatter(xv,yv,zv, label='Vacancies', c='b', marker='o') ax.set_title('Movie of the defects from '+str(t_start)+' ps to '+str(snap_to_time(snap_end,self))+' ps') ax.set_xlabel('x axis[Angström]') ax.set_ylabel('y axis[Angström]') ax.set_zlabel('z axis[Angström]') ax.set_xlim3d(0,self.box_dim[0]) ax.set_ylim3d(0,self.box_dim[0]) ax.set_zlim3d(0,self.box_dim[0]) ax.legend(frameon = True, fancybox = True, ncol = 1, fontsize = 'x-small', loc = 'lower right') ''' # Display of the progression if i % round(0.2*(snap_end-snap_start+1))==0 and i // round(0.2*(snap_end-snap_start+1)) != 0: if i // round(0.2*(snap_end-snap_start+1)) == 1: print('Progression of defects_movie:') print(str(round(100*i/(snap_end-snap_start+1)))+'%')
def update(self, i): """ Use new particle position for drawing next frame """ data = next(self.stream) #data = np.transpose(data) #print data self.scat._offsets3d = juggle_axes(data[0,:],data[1,:],data[2,:], 'z') self.ax.view_init(30,self.angle) plt.draw() return self.scat,
def set_3d_properties(self, zs=0, zdir='z'): xs = self.get_xy()[:,0] ys = self.get_xy()[:,1] try: # If *zs* is a list or array, then this will fail and # just proceed to juggle_axes(). zs = float(zs) zs = [zs for x in xs] except TypeError: pass self._verts3d = juggle_axes(xs, ys, zs, zdir) self._invalidz = True
def moveTarget(self, index, target, speed): # Target circle x = target[0, 3] y = target[1, 3] z = target[2, 3] self.allTargetElements[index].circles._offsets3d = juggle_axes([x], [y], [z], 'z') # Line along X tmpVec = np.array([50, 0, 0, 1]).reshape(4, 1) tmpVec = target * tmpVec lx = tmpVec[0, 0] ly = tmpVec[1, 0] lz = tmpVec[2, 0] self.allTargetElements[index].frameXLines.set_data([x, lx], [y, ly]) self.allTargetElements[index].frameXLines.set_3d_properties([z, lz], 'z') # Line along Y tmpVec = np.array([0, 50, 0, 1]).reshape(4, 1) tmpVec = target * tmpVec lx = tmpVec[0, 0] ly = tmpVec[1, 0] lz = tmpVec[2, 0] self.allTargetElements[index].frameYLines.set_data([x, lx], [y, ly]) self.allTargetElements[index].frameYLines.set_3d_properties([z, lz], 'z') # Line along Z tmpVec = np.array([0, 0, 50, 1]).reshape(4, 1) tmpVec = target * tmpVec lx = tmpVec[0, 0] ly = tmpVec[1, 0] lz = tmpVec[2, 0] self.allTargetElements[index].frameZLines.set_data([x, lx], [y, ly]) self.allTargetElements[index].frameZLines.set_3d_properties([z, lz], 'z') # Speed vector sx = speed[0] sy = speed[1] sz = speed[2] # Arbitrary scaling, to make max. length of vector constant k = 400.0 / Params.inputForceMax self.allTargetElements[index].speedLines.set_data([x, x + sx * k], [y, y + sy * k]) self.allTargetElements[index].speedLines.set_3d_properties( [z, z + sz * k], 'z')
def update(t): pts._offsets3d = juggle_axes(seq[t, :, 0], seq[t, :, 1], seq[t, :, 2], 'z') for i, l in enumerate(lines): if l is not None: l.set_data(xline[t, i, :2]) l.set_3d_properties(xline[t, i, 2]) if ghost is not None: pts_g._offsets3d = juggle_axes(ghost[t, :, 0], ghost[t, :, 1], ghost[t, :, 2], 'z') for i, l in enumerate(lines_g): l.set_data(xline_g[t, i, :2]) l.set_3d_properties(xline_g[t, i, 2]) if pointer is not None: ax.quiv.remove() ax.quiv = ax.quiver(X[t], Y[t], Z[t], dX[t], dY[t], 0, color=pointer_color)
def set_3d_properties(self, zs, zdir): # Force the collection to initialize the face and edgecolors # just in case it is a scalarmappable with a colormap. self.update_scalarmappable() offsets = self.get_offsets() if len(offsets) > 0: xs, ys = list(zip(*offsets)) else: xs = [] ys = [] from mpl_toolkits.mplot3d.art3d import juggle_axes self._offsets3d = juggle_axes(xs, ys, np.atleast_1d(zs), zdir) self._facecolor3d = self.get_facecolor() self._edgecolor3d = self.get_edgecolor()
def update(tt): tt = int(tt) #update marker position marker_pos.set_data(tt, self.mean_dist[tt]) #update coordinate positions sc._offsets3d = juggle_axes(self.pos[tt][:, 0], self.pos[tt][:, 1], self.pos[tt][:, 2], 'z') #update marker sizes of coordinates sc._sizes3d = 25 * self.std[tt] #update title ax_3d.set_title('Correlation at {}'.format(time_array[tt])) #update color of markers: not working properly! sc._faceolor3d = (self.mean[tt]) fig.canvas.draw_idle()
def convert_2dpath_to_3dpath(self, z, zdir='z'): ''' convert a path on flat surface to 3d path ''' #print("calling convert 2dpath to 3dpath") x1 = [] y1 = [] z1 = [] norms = [] idxset = [] idxbase = 0 if zdir == 'x': norm = np.array([1., 0, 0.]) elif zdir == 'y': norm = np.array([0., 1, 0.]) else: norm = np.array([0., 0, 1.]) txs, tys, tzs, ones = self._vec if hasattr(self, '_segis'): xyzlist = [(txs[si:ei], tys[si:ei], tzs[si:ei]) for si, ei in self._segis] else: xyzlist = [(txs[sl], tys[sl], tzs[sl]) for sl in self._segslices] for v0, v1, v2 in xyzlist: x1.append(v0) y1.append(v1) idxset.append(np.arange(len(v0)) + idxbase) z1.append(v2) # norms.append(np.hstack([norm]*len(v0))) idxbase = len(v0) + idxbase x1 = np.hstack(x1) y1 = np.hstack(y1) z1 = np.hstack(z1) # norms = np.hstack(norms).reshape(-1, 3) X3D, Y3D, Z3D = juggle_axes(x1, y1, z1, zdir) norms = np.array([norm]).reshape(-1, 3) self._gl_3dpath = [X3D, Y3D, Z3D, norms, idxset]
def update_scatter(i, data, scat, acc=None, proj=None): scat.set_label("{}".format(i)) if proj == '3d': from mpl_toolkits.mplot3d import Axes3D from mpl_toolkits.mplot3d.art3d import juggle_axes xs = data[i,:,0] ys = data[i,:,1] zs = data[i,:,2] scat._offsets3d = juggle_axes(xs, ys, zs, 'z') else: scat.set_offsets(data[i,:,:]) if acc is not None and proj is None: scat.set_color(cm.RdYlGn(acc[i,:,0])) #plt.legend() return scat,
def _update_plot(i, scatters, worlds, species_list): world = worlds[i] for i, name in enumerate(species_list): xs, ys, zs = [], [], [] particles = world.list_particles_exact(Species(name)) if max_count is not None and len(particles) > max_count: particles = random.sample(particles, max_count) for pid, p in particles: pos = p.position() xs.append(pos[0]) ys.append(pos[1]) zs.append(pos[2]) scatters[i]._offsets3d = juggle_axes(xs, ys, zs, 'z') if rotate is not None: ax.elev += rotate[0] ax.azim += rotate[1] fig.canvas.draw()
def convert_2dpath_to_3dpath(self, z=None, zdir='z'): x1 = [] y1 = [] z1 = [] norms = [] idxset = [] idxbase = 0 if zdir == 'x': norm = np.array([1., 0, 0.]) elif zdir == 'y': norm = np.array([0., 1, 0.]) else: norm = np.array([0., 0, 1.]) xyzlist = [] for points in self._segments3d: points = np.vstack(points) xyzlist.append(( points[:, 0], points[:, 1], points[:, 2], )) # xyzlist = [(points[:,0], points[:, 1], points[:,2]) # for points in self._segments3d] for v0, v1, v2 in xyzlist: x1.append(v0) y1.append(v1) idxset.append(np.arange(len(v0)) + idxbase) z1.append(v2) norms.append(np.hstack([norm] * len(v0))) idxbase = len(v0) + idxbase x1 = np.hstack(x1) y1 = np.hstack(y1) z1 = np.hstack(z1) norms = np.hstack(norms).reshape(-1, 3) X3D, Y3D, Z3D = juggle_axes(x1, y1, z1, zdir) # does norm may mean anything, but let's leave it... self._gl_3dpath = [X3D, Y3D, Z3D, norms, idxset]
def plot_object2(phys_obj, ax=None): """Takes an instance of the physical object class, and plots it's current X, Y, and Z values such that a matplotlib figure can update whatever group of particles in the figure that correspond to phys_obj. This function doesn't return anything, rather it saves the particle data in <obj>.pdata. This means that any time a matplotlib figure object needs data, just give it <obj>.pdata. """ o = phys_obj if (o.pdata == None) and (ax == None): raise SyntaxError( "Didn't supply an axis, but there is no particle data embedded in the " + "object to work off of. Please fix either issue.") if (o.pdata != None) and (ax == None): # the 3D way for doing <matplotlib_line>.set_data(...) o.pdata._offsets3d = juggle_axes(o.X, o.Y, o.Z, 'z') else: # initialize matplotlib figure entity, and update <obj>.pdata with # the returned particle data object. o.pdata = ax.scatter(o.X,o.Y,o.Z,c='y')
def update(self, i): xs, ys, zs = next(self.data) self.scat._offsets3d = juggle_axes(xs, ys, zs, 'z') return self.scat,
def render(particles, a, filename, cleanup=True): global artist_particles, artist_text, ax_render # Print out progress message masterprint('Rendering and saving image "{}" ...'.format(filename)) # Switch to the render figure plt.figure(fig_render_nr) # Attach missing extension to filename if not filename.endswith('.png'): filename += '.png' # Extract particle data N = particles.N N_local = particles.N_local # Update particle positions on the figure artist_particles._offsets3d = juggle_axes(particles.posx_mv[:N_local], particles.posy_mv[:N_local], particles.posz_mv[:N_local], zdir='z') # The particle size on the figure. # The size is chosen such that the particles stand side by side in a # homogeneous unvierse (more or less). size = 1000*np.prod(fig_render.get_size_inches())/N**ℝ[2/3] # The particle alpha on the figure. # The alpha is chosen such that in a homogeneous unvierse, a column # of particles have a collective alpha of 1 (more or less). alpha = N**ℝ[-1/3] # Alpha values lower than alpha_min appear completely invisible. # Allow no alpha values lower than alpha_min. Shrink the size to # make up for the large alpha. alpha_min = 0.0059 if alpha < alpha_min: size *= alpha/alpha_min alpha = alpha_min # Apply size and alpha artist_particles.set_sizes([size]) artist_particles.set_alpha(alpha) # Print the current scale factor on the figure if master: artist_text.set_text('') a_str = significant_figures(a, 4, 'LaTeX') artist_text = ax_render.text(+0.25*boxsize, -0.3*boxsize, 0, '$a = {}$'.format(a_str), fontsize=16, ) # Make the text color black or white, dependent on the bgcolor if sum(bgcolor) < 1: artist_text.set_color('white') else: artist_text.set_color('black') # Update axis limits if a boxsize were explicitly passed if boxsize: ax_render.set_xlim(0, boxsize) ax_render.set_ylim(0, boxsize) ax_render.set_zlim(0, boxsize) # If running with a single process, save the render, make a call to # update the liverender and then return. if nprocs == 1: plt.savefig(filename, bbox_inches='tight', pad_inches=0) masterprint('done') update_liverender(filename) return # Running with multiple processes. # Each process save its rendered part to disk. # First, make a temporary directory to hold the render parts. dirname = os.path.dirname(filename) basename = os.path.basename(filename) renderparts_dirname = '{}/.renderparts'.format(dirname) renderpart_filename = '{}/{}.png'.format(renderparts_dirname, rank) if master: os.makedirs(renderparts_dirname, exist_ok=True) # Now save the render parts, including transparency Barrier() plt.savefig(renderpart_filename, bbox_inches='tight', pad_inches=0, transparent=True, ) Barrier() # The master process combines the parts using ImageMagick if master: # List of all newly created renderparts renderpart_filenames = ['{}/{}.png'.format(renderparts_dirname, r) for r in range(nprocs)] # Combine all render parts into one, # with the correct background color and no transparency. subprocess.call([paths['convert']] + renderpart_filenames + ['-background', 'rgb({}%, {}%, {}%)'.format(100*bgcolor[0], 100*bgcolor[1], 100*bgcolor[2]), '-layers', 'flatten', '-alpha', 'remove', filename]) # Remove the temporary directory, if cleanup is requested if cleanup: shutil.rmtree(renderparts_dirname) masterprint('done') # Update the live render (local and remote) update_liverender(filename)
def update_sctr(handle, newdata): if is_3d: handle._offsets3d = juggle_axes(*newdata.T, 'z') else: handle.set_offsets(newdata)
def plot_frame(i): plot._offsets3d = art3d.juggle_axes(*zip(*self.all_data[i]), "z")
def update(self, k, kObs, E=None, P=None, **kwargs): """Plot forecast state""" if self.skip_plotting(): return stats = self.stats mu = stats.mu m = self.xx.shape[1] ii, wrap = setup_wrapping(m) ##################### # Dashboard ##################### if hasattr(self, 'fga') and plt.fignum_exists(self.fga.number): plt.figure(self.fga.number) t = self.setup.t.tt[k] self.fga.suptitle('t[k]={:<5.2f}, k={:<d}'.format(t, k)) # -------------- # Amplitude plot # -------------- if hasattr(self, 'ax'): # Truth self.lx.set_ydata(wrap(self.xx[k])) # Analysis self.lmu.set_ydata(wrap(mu[k])) # Forecast if kObs is None: self.fcast.set_visible(False) else: self.fcast.set_ydata(wrap(mu.f[kObs])) self.fcast.set_visible(True) # Ensemble/Confidence if hasattr(self, 'lE'): w = stats.w[k] wmax = w.max() for i, l in enumerate(self.lE): l.set_ydata(wrap(E[i])) l.set_alpha((w[i] / wmax).clip(0.1)) else: self.CI.remove() self.CI = self.ax.fill_between(ii, \ wrap(mu[k] - self.ks*sqrt(stats.var[k])), \ wrap(mu[k] + self.ks*sqrt(stats.var[k])), alpha=0.4) plt.sca(self.ax) if hasattr(self, 'obs'): try: self.obs.remove() except Exception: pass if kObs is not None: self.obs = self.yplot(self.yy[kObs]) update_ylim([mu[k], self.xx[k]], self.ax) # -------------- # Correlation plot. # -------------- if hasattr(self, 'axC'): if E is not None: C = np.cov(E, rowvar=False) else: assert P is not None C = P.full if isinstance(P, CovMat) else P C = C.copy() std = sqrt(diag(C)) C /= std[:, None] C /= std[None, :] C2 = np.ma.masked_where(self.mask, C)[::-1] self.mesh.set_array(C2.ravel()) # Auto-corr function acf = circulant_ACF(C) ac6 = circulant_ACF(C, do_abs=True) self.l5.set_ydata(acf) self.l6.set_ydata(ac6) update_ylim([acf, ac6], self.ax5) # -------------- # Spectral error plot # -------------- if self.do_spectral_error: msft = abs(stats.umisf[k]) sprd = stats.svals[k] self.lew.set_ydata(sprd) self.lmf.set_ydata(msft) update_ylim(msft, self.ax2) plot_pause(0.01) ##################### # Diagnostics ##################### if hasattr(self, 'fgd') and plt.fignum_exists(self.fgd.number): plt.figure(self.fgd.number) chrono = self.setup.t # Indices with shift kkU = arange(chrono.pK) + max(0, k - chrono.pK) ttU = chrono.tt[kkU] # Indices for Obs-times kkA = kkU[0] <= chrono.kkObs kkA &= chrono.kkObs <= kkU[-1] def update_axd(ax, dict_of_dicts): ax.set_xlim(ttU[0], ttU[0] + 1.1 * (ttU[-1] - ttU[0])) for name, d in dict_of_dicts.items(): stat = getattr(stats, name) if isinstance(stat, np.ndarray): tt_ = chrono.ttObs[kkA] d['data'] = stat[kkA] if d.get('step', False): # Creat "step"-style graph d['data'] = d['data'].repeat(2) tt_ = tt_.repeat(2) right = tt_[ -1] # use ttU[-1] for continuous extrapolation tt_ = np.hstack([ttU[0], tt_[0:-2], right]) elif stat.dtype == 'bool': # Creat "impulse"-style graph tt_ = tt_.repeat(3) d['data'] = d['data'].repeat(3) tt_[2::3] = nan d['data'][::3] = False else: tt_ = ttU if stat.store_u: d['data'] = stat[kkU] else: # store .u manually tmp = stat[k] if self.prev_k != (k - 1): # Reset display d['data'][:] = nan if k >= chrono.pK: # Rolling display d['data'] = roll_n_sub(d['data'], tmp, -1) else: # Initial display: append d['data'][k] = tmp d['data'] = d['transf'](d['data']) d['h'].set_data(tt_, d['data']) def rm_absent(ax, dict_of_dicts): for name in list(dict_of_dicts): d = dict_of_dicts[name] if not np.any(np.isfinite(d['data'])): d['h'].remove() del dict_of_dicts[name] if dict_of_dicts: ax.legend(loc='upper left') update_axd(self.ax_d1, self.d1) update_axd(self.ax_d2, self.d2) #if k%(chrono.pK/5) <= 1: update_ylim([d['data'] for d in self.d1.values()], self.ax_d1, bottom=0, cC=0.2, cE=0.9) update_ylim([d['data'] for d in self.d2.values()], self.ax_d2, Max=4, Min=-4, cC=0.3, cE=0.9) # Check which diagnostics are present if (not self.has_checked_presence) and (k >= chrono.kkObs[0]): rm_absent(self.ax_d1, self.d1) rm_absent(self.ax_d2, self.d2) self.has_checked_presence = True plot_pause(0.01) ##################### # 3D phase space ##################### if hasattr(self, 'fg3') and plt.fignum_exists(self.fg3.number): plt.figure(self.fg3.number) def update_tail(handle, newdata): handle.set_data(newdata[:, 0], newdata[:, 1]) handle.set_3d_properties(newdata[:, 2]) # Reset if self.prev_k != (k - 1): self.tail_xx[:] = self.xx[k, :3] if hasattr(self, 'sE'): self.tail_E[:] = E[:, :3] else: self.tail_mu[:] = mu[k, :3] # Truth self.sx._offsets3d = juggle_axes(*tp(self.xx[k, :3]), 'z') self.tail_xx = roll_n_sub(self.tail_xx, self.xx[k, :3]) update_tail(self.ltx, self.tail_xx) if hasattr(self, 'sE'): # Ensemble self.sE._offsets3d = juggle_axes(*E.T[:3], 'z') clrs = self.sE.get_facecolor()[:, :3] w = stats.w[k] alpha = (w / w.max()).clip(0.1, 0.4) if len(clrs) == 1: clrs = clrs.repeat(len(w), axis=0) self.sE.set_color(np.hstack([clrs, alpha[:, None]])) self.tail_E = roll_n_sub(self.tail_E, E[:, :3]) for n in range(E.shape[0]): update_tail(self.ltE[n], self.tail_E[:, n, :]) self.ltE[n].set_alpha(alpha[n]) else: # Mean self.smu._offsets3d = juggle_axes(*tp(mu[k, :3]), 'z') self.tail_mu = roll_n_sub(self.tail_mu, mu[k, :3]) update_tail(self.ltmu, self.tail_mu) plot_pause(0.01) # For animation: #self.fg3.savefig('figs/l63_' + str(k) + '.png',format='png',dpi=70) ##################### # Weight histogram ##################### if kObs and hasattr(self, 'fgh') and plt.fignum_exists( self.fgh.number): plt.figure(self.fgh.number) axh = self.axh _ = [b.remove() for b in self.hst] w = stats.w[k] N = len(w) wmax = w.max() bins = exp(linspace(log(1e-5 / N), log(1), int(N / 20))) counted = w > bins[0] nC = np.sum(counted) nn, _, pp = axh.hist(w[counted], bins=bins, color='b') self.hst = pp #thresh = '#(w<$10^{'+ str(int(log10(bins[0]*N))) + '}/N$ )' axh.set_title('N: {:d}. N_eff: {:.4g}. Not shown: {:d}. '.\ format(N, 1/(w@w), N-nC)) update_ylim([nn], axh, cC=True) plot_pause(0.01) ##################### # User-defined state ##################### if hasattr(self, 'fgu') and plt.fignum_exists(self.fgu.number): plt.figure(self.fgu.number) self.setter_truth(self.xx[k]) self.setter_mean(mu[k]) plot_pause(0.01) # Trackers self.prev_k = k
def plot_frame(self, i=0): f_data = self.data[i] self.plot._offsets3d = art3d.juggle_axes(*zip(*f_data), "z") bbox = BBox(*zip(*f_data)) bbox.equal_3d_axes(self.ax, zoom=2) self._frame = i
def update_plot(num, positions, body_lines, ani_lines, sc): for line, (sp, ep) in zip(ani_lines, body_lines): line._verts3d = positions[[sp, ep], :, num].T.tolist() sc._offsets3d = juggle_axes(positions[:, 0, num], positions[:, 1, num], positions[:, 2, num], 'z') return sc
def run(num, data, points): # update the data print num print len(data[num][0]) points._offsets3d = juggle_axes(data[num][0],data[num][1],data[num][2], 'z') return range(num-1)
def update(frame): indicesdict = {} alts = [] lons = [] lats = [] global annolist i = 0 for i, plane in enumerate(time_slices[frame]): lon, lat = mymap(plane.lon, plane.lat) lons.append(int(lon)) lats.append(int(lat)) alts.append(int(plane.altitude)) indicesdict[plane.hex] = i time_text.set_text( time.strftime( "%F %H:%M:%S", time.localtime(first_time + (frame * args.sec_per_frame)))) # # Remove old texts from matplotlib's internal state # for anno in annolist: if anno: ax.texts.remove(anno) anno = None annolist = [] if args.display_hex or args.display_flt: for lastpoint in indicesdict: plane = time_slices[frame][indicesdict[lastpoint]] if args.display_hex and args.display_flt: txt = plane.hex + "/" + plane.flight elif args.display_hex: txt = plane.hex else: txt = plane.flight x, y = mymap(plane.lon, plane.lat) z = plane.altitude annolist.append(ax.text(x, y, z, txt, fontsize=8)) scat._offsets3d = juggle_axes(lons, lats, alts, 'z') if args.rotate: ax.view_init(30, (frame + 270) % 360) drawableslst = [] drawableslst.append(scat) drawableslst.append(time_text) for anno in annolist: if anno: drawableslst.append(anno) if args.debug: print( frame, time.strftime( "%F %H:%M:%S", time.localtime(first_time + (frame * args.sec_per_frame))), len(time_slices[frame]), len(indicesdict), len(annolist), len(ax.texts)) return tuple(drawableslst)