def test_repeated_save_with_alpha(): # We want an image which has a background color of bluish green, with an # alpha of 0.25. fig = Figure([1, 0.4]) canvas = FigureCanvas(fig) fig.set_facecolor((0, 1, 0.4)) fig.patch.set_alpha(0.25) # The target color is fig.patch.get_facecolor() _, img_fname = tempfile.mkstemp(suffix='.png') try: fig.savefig(img_fname, facecolor=fig.get_facecolor(), edgecolor='none') # Save the figure again to check that the # colors don't bleed from the previous renderer. fig.savefig(img_fname, facecolor=fig.get_facecolor(), edgecolor='none') # Check the first pixel has the desired color & alpha # (approx: 0, 1.0, 0.4, 0.25) assert_array_almost_equal(tuple(imread(img_fname)[0, 0]), (0.0, 1.0, 0.4, 0.250), decimal=3) finally: os.remove(img_fname)
def test_repeated_save_with_alpha(): # We want an image which has a background color of bluish green, with an # alpha of 0.25. fig = Figure([1, 0.4]) fig.set_facecolor((0, 1, 0.4)) fig.patch.set_alpha(0.25) # The target color is fig.patch.get_facecolor() buf = io.BytesIO() fig.savefig(buf, facecolor=fig.get_facecolor(), edgecolor='none') # Save the figure again to check that the # colors don't bleed from the previous renderer. buf.seek(0) fig.savefig(buf, facecolor=fig.get_facecolor(), edgecolor='none') # Check the first pixel has the desired color & alpha # (approx: 0, 1.0, 0.4, 0.25) buf.seek(0) assert_array_almost_equal(tuple(imread(buf)[0, 0]), (0.0, 1.0, 0.4, 0.250), decimal=3)
def test_repeated_save_with_alpha(): # We want an image which has a background color of bluish green, with an # alpha of 0.25. fig = Figure([1, 0.4]) canvas = FigureCanvas(fig) fig.set_facecolor((0, 1, 0.4)) fig.patch.set_alpha(0.25) # The target color is fig.patch.get_facecolor() buf = io.BytesIO() fig.savefig(buf, facecolor=fig.get_facecolor(), edgecolor='none') # Save the figure again to check that the # colors don't bleed from the previous renderer. buf.seek(0) fig.savefig(buf, facecolor=fig.get_facecolor(), edgecolor='none') # Check the first pixel has the desired color & alpha # (approx: 0, 1.0, 0.4, 0.25) buf.seek(0) assert_array_almost_equal(tuple(imread(buf)[0, 0]), (0.0, 1.0, 0.4, 0.250), decimal=3)
def bargraph(request): p = request.GET try: d = [(float(p['d10']), float(p['d11']), float(p['d12']), float(p['d13']), float(p['d14'])), (float(p['d20']), float(p['d21']), float(p['d22']), float(p['d23']), float(p['d24'])), (float(p['d30']), float(p['d31']), float(p['d32']), float(p['d33']), float(p['d34'])), (float(p['d40']), float(p['d41']), float(p['d42']), float(p['d43']), float(p['d44'])), (float(p['d50']), float(p['d51']), float(p['d52']), float(p['d53']), float(p['d54'])), (float(p['d60']), float(p['d61']), float(p['d62']), float(p['d63']), float(p['d64'])), (float(p['d70']), float(p['d71']), float(p['d72']), float(p['d73']), float(p['d74'])), (float(p['d80']), float(p['d81']), float(p['d82']), float(p['d83']), float(p['d84']))] except: return render(request,"bad.html", { 'type':'bargraph' }) tickM = ["2. Culture for retreatment", "3. GeneXpert for HIV positive only", "4. GeneXpert for smear positive only", "5. GeneXpert for all", "6. GeneXpert for all, culture confirmed", "7. MODS/TLA", "8. Same-day smear microscopy", "9. Same-day GeneXpert"] colors = ["grey","blue","green","yellow","red"] ndata = zip(*d) loc = np.arange(len(ndata[0])) width = 0.15 fig = Figure(facecolor='white') canvas = FigureCanvas(fig) ax = fig.add_subplot(111) rect = [ax.bar(loc+width*i, ndata[i], width, color=colors[i]) for i in range(len(ndata))] ax.set_ylim(-50,100) ax.set_xlim(-width*4, len(loc) +(4*width)) ax.set_xticks(loc + (2.5*width)) ax.set_xticklabels(tickM, rotation='30', size='small', stretch='condensed', ha='right' ) ax.legend ((rect[0][0], rect[1][0], rect[2][0], rect[3][0], rect[4][0]), ("TBInc", "MDRInc", "TBMort", "Yr1Cost", "Yr5Cost"),loc='best') ax.set_title ("Graph Comparison") ax.axhline(color='black') ax.set_ylabel('percentage change from baseline') fig.tight_layout() response=HttpResponse(content_type='image/png') canvas.print_png(response,facecolor=fig.get_facecolor()) return response
def savefig(fig: Figure, filename: PathLike, *args, **kwargs): if "facecolor" not in kwargs: kwargs["facecolor"] = fig.get_facecolor() if "edgecolor" not in kwargs: kwargs["edgecolor"] = None filename = str(filename) if filename.endswith(".svg"): return save_svg(fig, filename, *args, **kwargs) else: return fig.savefig(filename, *args, **kwargs)
def dgraph1(request): p_val = request.GET order = [0, 1, 7, 6, 2, 8, 3, 4, 5] try: cmore = [float(p_val['c{}'.format(order[x])]) for x in range(9)] inc = [float(p_val['i{}'.format(order[x])]) for x in range(9)] except: return render(request, "bad.html", {'type': 'dot graph 1'}) fig = Figure(facecolor='white') canvas = FigureCanvas(fig) ax1 = fig.add_subplot(111) ax1.set_ylabel('% decrease in TB incidence at year 5 (more effective -->)') ax1.set_xlabel('% increase in cost at year 5 (more costly -->)') ax1.plot(cmore, inc, marker='.', linestyle='None') ax1.set_title("Percent change (%) in cost and TB incidence at year 5") ax1.axhline(color='r') ax1.axvline(color='r') #Add annotations, simple collision detection point_list = [] for i in xrange(9): dx, dy = placement(cmore[i], inc[i], point_list, ax1) point_list.append([cmore[i], inc[i], dx, dy]) ax1.annotate(str(i + 1), xy=(cmore[i], inc[i]), xytext=(cmore[i] + dx, inc[i] + dy), arrowprops=dict(color='red', arrowstyle="->")) fig.tight_layout() response = HttpResponse(content_type='image/png') canvas.print_png(response, facecolor=fig.get_facecolor()) return response
def dgraph1(request): p_val = request.GET order = [0,1,7,6,2,8,3,4,5] try: cmore = [float(p_val['c{}'.format(order[x])]) for x in range(9)] inc = [float(p_val['i{}'.format(order[x])]) for x in range(9)] except: return render(request,"bad.html", { 'type':'dot graph 1' }) fig = Figure(facecolor='white') canvas = FigureCanvas(fig) ax1 = fig.add_subplot(111) ax1.set_ylabel('% decrease in TB incidence at year 5 (more effective -->)') ax1.set_xlabel('% increase in cost at year 5 (more costly -->)') ax1.plot(cmore,inc,marker='.',linestyle='None') ax1.set_title("Percent change (%) in cost and TB incidence at year 5") ax1.axhline(color='r') ax1.axvline(color='r') #Add annotations, simple collision detection point_list = [] for i in xrange(9): dx,dy = placement(cmore[i],inc[i],point_list,ax1) point_list.append([cmore[i],inc[i],dx,dy]) ax1.annotate(str(i+1), xy=(cmore[i],inc[i]), xytext=(cmore[i]+dx,inc[i]+dy), arrowprops=dict(color='red',arrowstyle="->")) fig.tight_layout() response=HttpResponse(content_type='image/png') canvas.print_png(response,facecolor=fig.get_facecolor()) return response
def make_movie(args): """Actually make the movie of the atmosphere given command line arguments stored in `args`. """ # Initiate some GalSim random number generators. rng = galsim.BaseDeviate(args.seed) u = galsim.UniformDeviate(rng) # The GalSim atmospheric simulation code describes turbulence in the 3D atmosphere as a series # of 2D turbulent screens. The galsim.Atmosphere() helper function is useful for constructing # this screen list. # First, we estimate a weight for each screen, so that the turbulence is dominated by the lower # layers consistent with direct measurements. The specific values we use are from SCIDAR # measurements on Cerro Pachon as part of the 1998 Gemini site selection process # (Ellerbroek 2002, JOSA Vol 19 No 9). Ellerbroek_alts = [0.0, 2.58, 5.16, 7.73, 12.89, 15.46] # km Ellerbroek_weights = [0.652, 0.172, 0.055, 0.025, 0.074, 0.022] Ellerbroek_interp = galsim.LookupTable(Ellerbroek_alts, Ellerbroek_weights, interpolant='linear') # Use given number of uniformly spaced altitudes alts = np.max(Ellerbroek_alts)*np.arange(args.nlayers)/(args.nlayers-1) weights = Ellerbroek_interp(alts) # interpolate the weights weights /= sum(weights) # and renormalize # Each layer can have its own turbulence strength (roughly inversely proportional to the Fried # parameter r0), wind speed, wind direction, altitude, and even size and scale (though note that # the size of each screen is actually made infinite by "wrapping" the edges of the screen.) The # galsim.Atmosphere helper function is useful for constructing this list, and requires lists of # parameters for the different layers. spd = [] # Wind speed in m/s dirn = [] # Wind direction in radians r0_500 = [] # Fried parameter in m at a wavelength of 500 nm. for i in range(args.nlayers): spd.append(u()*args.max_speed) # Use a random speed between 0 and max_speed dirn.append(u()*360*galsim.degrees) # And an isotropically distributed wind direction. # The turbulence strength of each layer is specified by through its Fried parameter r0_500, # which can be thought of as the diameter of a telescope for which atmospheric turbulence # and unaberrated diffraction contribute equally to image resolution (at a wavelength of # 500nm). The weights above are for the refractive index structure function (similar to a # variance or covariance), however, so we need to use an appropriate scaling relation to # distribute the input "net" Fried parameter into a Fried parameter for each layer. For # Kolmogorov turbulence, this is r0_500 ~ (structure function)**(-3/5): r0_500.append(args.r0_500*weights[i]**(-3./5)) print("Adding layer at altitude {:5.2f} km with velocity ({:5.2f}, {:5.2f}) m/s, " "and r0_500 {:5.3f} m." .format(alts[i], spd[i]*dirn[i].cos(), spd[i]*dirn[i].sin(), r0_500[i])) # Additionally, we set the screen size and scale. atm = galsim.Atmosphere(r0_500=r0_500, speed=spd, direction=dirn, altitude=alts, rng=rng, screen_size=args.screen_size, screen_scale=args.screen_scale) # `atm` is now an instance of a galsim.PhaseScreenList object. # Place to store the cumulative PSF image if args.accumulate is set. psf_img_sum = galsim.ImageD(args.psf_nx, args.psf_nx, scale=args.psf_scale) # Field angle (angle on the sky wrt the telescope boresight) at which to compute the PSF. theta = (args.x*galsim.arcmin, args.y*galsim.arcmin) # Construct an Aperture object for computing the PSF. The Aperture object describes the # illumination pattern of the telescope pupil, and chooses good sampling size and resolution # for representing this pattern as an array. aper = galsim.Aperture(diam=args.diam, lam=args.lam, obscuration=args.obscuration, nstruts=args.nstruts, strut_thick=args.strut_thick, strut_angle=args.strut_angle*galsim.degrees, screen_list=atm, pad_factor=args.pad_factor, oversampling=args.oversampling) # Code to setup the Matplotlib animation. metadata = dict(title='Wavefront Movie', artist='Matplotlib') writer = anim.FFMpegWriter(fps=15, bitrate=5000, metadata=metadata) # For the animation code, we essentially draw a single figure first, and then use various # `set_XYZ` methods to update each successive frame. fig = Figure(facecolor='k', figsize=(11, 6)) FigureCanvasAgg(fig) # Axis for the PSF image on the left. psf_ax = fig.add_axes([0.08, 0.15, 0.35, 0.7]) psf_ax.set_xlabel("Arcsec") psf_ax.set_ylabel("Arcsec") psf_im = psf_ax.imshow(np.ones((128, 128), dtype=np.float64), animated=True, vmin=0.0, vmax=args.psf_vmax, cmap='hot', extent=np.r_[-1, 1, -1, 1]*0.5*args.psf_nx*args.psf_scale) # Axis for the wavefront image on the right. wf_ax = fig.add_axes([0.51, 0.15, 0.35, 0.7]) wf_ax.set_xlabel("Meters") wf_ax.set_ylabel("Meters") wf_im = wf_ax.imshow(np.ones((128, 128), dtype=np.float64), animated=True, vmin=-args.wf_vmax, vmax=args.wf_vmax, cmap='YlGnBu', extent=np.r_[-1, 1, -1, 1]*0.5*aper.pupil_plane_size) cbar_ax = fig.add_axes([0.88, 0.175, 0.03, 0.65]) cbar_ax.set_ylabel("Radians") fig.colorbar(wf_im, cax=cbar_ax) # Overlay an alpha-mask on the wavefront image showing which parts are actually illuminated. ilum = np.ma.masked_greater(aper.illuminated, 0.5) wf_ax.imshow(ilum, alpha=0.4, extent=np.r_[-1, 1, -1, 1]*0.5*aper.pupil_plane_size) # Color items white to show up on black background for ax in [psf_ax, wf_ax, cbar_ax]: for _, spine in ax.spines.items(): spine.set_color('w') ax.title.set_color('w') ax.xaxis.label.set_color('w') ax.yaxis.label.set_color('w') ax.tick_params(axis='both', colors='w') etext = psf_ax.text(0.05, 0.92, '', transform=psf_ax.transAxes) etext.set_color('w') nstep = int(args.exptime / args.time_step) t0 = 0.0 # Use astropy ProgressBar to keep track of progress and show an estimate for time to completion. with ProgressBar(nstep) as bar: with writer.saving(fig, args.outfile, 100): for i in range(nstep): # The wavefront() method accepts pupil plane coordinates `u` and `v` in meters, a # time `t` in seconds, and possibly a field angle `theta`. It returns the wavefront # lag or lead in nanometers with respect to the "perfect" planar wavefront at the # specified location angle and time. In normal use for computing atmospheric PSFs, # this is just an implementation detail. In this script, however, we include the # wavefront in the visualization. wf = atm.wavefront(aper.u, aper.v, t0, theta=theta) * 2*np.pi/args.lam # radians # To make an actual PSF GSObject, we use the makePSF() method, including arguments # for the wavelength `lam`, the field angle `theta`, the aperture `aper`, the # starting time t0, and the exposure time `exptime`. Here, since we're making a # movie, we set the exptime equal to just a single timestep, though normally we'd # want to set this to the full exposure time. psf = atm.makePSF(lam=args.lam, theta=theta, aper=aper, t0=t0, exptime=args.time_step) # `psf` is now just like an any other GSObject, ready to be convolved, drawn, or # transformed. Here, we just draw it into an image to add to our movie. psf_img0 = psf.drawImage(nx=args.psf_nx, ny=args.psf_nx, scale=args.psf_scale) if args.accumulate: psf_img_sum += psf_img0 psf_img = psf_img_sum/(i+1) else: psf_img = psf_img0 # Calculate simple estimate of size and ellipticity e = galsim.utilities.unweighted_shape(psf_img) # Update t0 for the next movie frame. t0 += args.time_step # Matplotlib code updating plot elements wf_im.set_array(wf) wf_ax.set_title("t={:5.2f} s".format(i*args.time_step)) psf_im.set_array(psf_img.array) etext.set_text("$e_1$={:6.3f}, $e_2$={:6.3f}, $r^2$={:6.3f}".format( e['e1'], e['e2'], e['rsqr']*args.psf_scale**2)) with warnings.catch_warnings(): warnings.simplefilter("ignore") writer.grab_frame(facecolor=fig.get_facecolor()) bar.update()
def make_movie(args): rng = galsim.BaseDeviate(args.seed) u = galsim.UniformDeviate(rng) # Generate 1D Gaussian random fields for each aberration. t = np.arange(-args.n/2, args.n/2) corr = np.exp(-0.5*t**2/args.ell**2) pk = np.fft.fft(np.fft.fftshift(corr)) ak = np.sqrt(2*pk) phi = np.random.uniform(size=(args.n, args.jmax)) zk = ak[:, None]*np.exp(2j*np.pi*phi) aberrations = args.n/2*np.fft.ifft(zk, axis=0).real measured_std = np.mean(np.std(aberrations, axis=0)) aberrations *= args.sigma/measured_std aberrations -= np.mean(aberrations, axis=0) if args.nlayers > 0: # For the atmosphere screens, we first estimates weights, so that the turbulence is dominated by # the lower layers consistent with direct measurements. The specific values we use are from # SCIDAR measurements on Cerro Pachon as part of the 1998 Gemini site selection process # (Ellerbroek 2002, JOSA Vol 19 No 9). Ellerbroek_alts = [0.0, 2.58, 5.16, 7.73, 12.89, 15.46] # km Ellerbroek_weights = [0.652, 0.172, 0.055, 0.025, 0.074, 0.022] Ellerbroek_interp = galsim.LookupTable(Ellerbroek_alts, Ellerbroek_weights, interpolant='linear') alts = np.max(Ellerbroek_alts)*np.arange(args.nlayers)/(args.nlayers-1) weights = Ellerbroek_interp(alts) # interpolate the weights weights /= sum(weights) # and renormalize spd = [] # Wind speed in m/s dirn = [] # Wind direction in radians r0_500 = [] # Fried parameter in m at a wavelength of 500 nm. for i in range(args.nlayers): spd.append(u()*args.max_speed) # Use a random speed between 0 and args.max_speed dirn.append(u()*360*galsim.degrees) # And an isotropically distributed wind direction. r0_500.append(args.r0_500*weights[i]**(-3./5)) print("Adding layer at altitude {:5.2f} km with velocity ({:5.2f}, {:5.2f}) m/s, " "and r0_500 {:5.3f} m." .format(alts[i], spd[i]*dirn[i].cos(), spd[i]*dirn[i].sin(), r0_500[i])) # Make two identical Atmospheres. They will diverge when one gets drawn using Fourier # optics and the other gets drawn with geometric optics. fft_atm = galsim.Atmosphere(r0_500=r0_500, speed=spd, direction=dirn, altitude=alts, rng=rng.duplicate(), screen_size=args.screen_size, screen_scale=args.screen_scale) geom_atm = galsim.Atmosphere(r0_500=r0_500, speed=spd, direction=dirn, altitude=alts, rng=rng.duplicate(), screen_size=args.screen_size, screen_scale=args.screen_scale) else: fft_atm = galsim.PhaseScreenList() geom_atm = galsim.PhaseScreenList() # Before either of this has been instantiated, they are identical assert fft_atm == geom_atm # If any AtmosphericScreens are included, we manually instantiate here so we can have a # uniformly updating ProgressBar both here and below when actually drawing PSFs. Normally, it's # okay to let the atms automatically instantiate, which happens when the first PSF is drawn, or # the first wavefront is queried. if args.nlayers > 0: print("Instantiating screens") with ProgressBar(2*args.nlayers) as bar: if args.do_fft: fft_atm.instantiate(_bar=bar) if args.do_geom: r0 = args.r0_500*(args.lam/500)**1.2 geom_atm.instantiate(kmax=0.2/r0, _bar=bar) # After instantiation, they're only equal if there's no atmosphere. assert fft_atm != geom_atm # Setup Fourier and geometric apertures fft_aper = galsim.Aperture(args.diam, args.lam, obscuration=args.obscuration, pad_factor=args.pad_factor, oversampling=args.oversampling, nstruts=args.nstruts, strut_thick=args.strut_thick, strut_angle=args.strut_angle*galsim.degrees) geom_aper = galsim.Aperture(args.diam, args.lam, obscuration=args.obscuration, pad_factor=args.geom_oversampling, oversampling=0.5, nstruts=args.nstruts, strut_thick=args.strut_thick, strut_angle=args.strut_angle*galsim.degrees) scale = args.size/args.nx extent = np.r_[-1,1,-1,1]*args.size/2 fft_img_sum = galsim.ImageD(args.nx, args.nx, scale=scale) geom_img_sum = galsim.ImageD(args.nx, args.nx, scale=scale) # Code to setup the Matplotlib animation. metadata = dict(title="FFT vs geom movie", artist='Matplotlib') if args.make_movie: writer = anim.FFMpegWriter(fps=15, bitrate=10000, metadata=metadata) fig = Figure(facecolor='k', figsize=(16, 9)) FigureCanvasAgg(fig) fft_ax = fig.add_axes([0.07, 0.08, 0.36, 0.9]) fft_ax.set_xlabel("Arcsec") fft_ax.set_ylabel("Arcsec") fft_ax.set_title("Fourier Optics") fft_im = fft_ax.imshow(np.ones((args.nx, args.nx), dtype=float), animated=True, extent=extent, vmin=0.0, vmax=args.vmax) # Axis for the wavefront image on the right. geom_ax = fig.add_axes([0.50, 0.08, 0.36, 0.9]) geom_ax.set_xlabel("Arcsec") geom_ax.set_ylabel("Arcsec") geom_ax.set_title("Geometric Optics") geom_im = geom_ax.imshow(np.ones((args.nx, args.nx), dtype=float), animated=True, extent=extent, vmin=0.0, vmax=args.vmax) # Color items white to show up on black background for ax in [fft_ax, geom_ax]: for _, spine in ax.spines.items(): spine.set_color('w') ax.title.set_color('w') ax.xaxis.label.set_color('w') ax.yaxis.label.set_color('w') ax.tick_params(axis='both', colors='w') ztext = [] for i in range(2, args.jmax+1): x = 0.88 y = 0.1 + (args.jmax-i)/args.jmax*0.8 ztext.append(fig.text(x, y, "Z{:d} = {:5.3f}".format(i, 0.0))) ztext[-1].set_color('w') M_fft = fft_ax.text(0.02, 0.955, '', transform=fft_ax.transAxes) M_fft.set_color('w') M_geom = geom_ax.text(0.02, 0.955, '', transform=geom_ax.transAxes) M_geom.set_color('w') etext_fft = fft_ax.text(0.02, 0.91, '', transform=fft_ax.transAxes) etext_fft.set_color('w') etext_geom = geom_ax.text(0.02, 0.91, '', transform=geom_ax.transAxes) etext_geom.set_color('w') fft_mom = np.empty((args.n, 8), dtype=float) geom_mom = np.empty((args.n, 8), dtype=float) fullpath = args.out+"movie.mp4" subdir, filename = os.path.split(fullpath) if subdir and not os.path.isdir(subdir): os.makedirs(subdir) print("Drawing PSFs") with ProgressBar(args.n) as bar: with writer.saving(fig, fullpath, 100) if args.make_movie else ExitStack(): t0 = 0.0 for i, aberration in enumerate(aberrations): optics = galsim.OpticalScreen(args.diam, obscuration=args.obscuration, aberrations=[0]+aberration.tolist(), annular_zernike=True) if args.do_fft: fft_psl = galsim.PhaseScreenList(fft_atm._layers+[optics]) fft_psf = fft_psl.makePSF( lam=args.lam, aper=fft_aper, t0=t0, exptime=args.time_step) fft_img0 = fft_psf.drawImage(nx=args.nx, ny=args.nx, scale=scale) if args.do_geom: geom_psl = galsim.PhaseScreenList(geom_atm._layers+[optics]) geom_psf = geom_psl.makePSF( lam=args.lam, aper=geom_aper, t0=t0, exptime=args.time_step) geom_img0 = geom_psf.drawImage(nx=args.nx, ny=args.nx, scale=scale, method='phot', n_photons=args.geom_nphot, rng=rng) t0 += args.time_step if args.accumulate: if args.do_fft: fft_img_sum += fft_img0 fft_img = fft_img_sum/(i+1) if args.do_geom: geom_img_sum += geom_img0 geom_img = geom_img_sum/(i+1) else: if args.do_fft: fft_img = fft_img0 if args.do_geom: geom_img = geom_img0 for j, ab in enumerate(aberration): if j == 0: continue ztext[j-1].set_text("Z{:d} = {:5.3f}".format(j+1, ab)) # Calculate simple estimate of ellipticity Is = ("$M_x$={: 6.4f}, $M_y$={: 6.4f}, $M_{{xx}}$={:6.4f}," " $M_{{yy}}$={:6.4f}, $M_{{xy}}$={: 6.4f}") if args.do_fft and (args.make_movie or args.make_plots): fft_im.set_array(fft_img.array) mom_fft = galsim.utilities.unweighted_moments(fft_img, origin=fft_img.true_center) e_fft = galsim.utilities.unweighted_shape(mom_fft) M_fft.set_text(Is.format(mom_fft['Mx']*fft_img.scale, mom_fft['My']*fft_img.scale, mom_fft['Mxx']*fft_img.scale**2, mom_fft['Myy']*fft_img.scale**2, mom_fft['Mxy']*fft_img.scale**2)) etext_fft.set_text("$e_1$={: 6.4f}, $e_2$={: 6.4f}, $r^2$={:6.4f}".format( e_fft['e1'], e_fft['e2'], e_fft['rsqr']*fft_img.scale**2)) fft_mom[i] = (mom_fft['Mx']*fft_img.scale, mom_fft['My']*fft_img.scale, mom_fft['Mxx']*fft_img.scale**2, mom_fft['Myy']*fft_img.scale**2, mom_fft['Mxy']*fft_img.scale**2, e_fft['e1'], e_fft['e2'], e_fft['rsqr']*fft_img.scale**2) if args.do_geom and (args.make_movie or args.make_plots): geom_im.set_array(geom_img.array) mom_geom = galsim.utilities.unweighted_moments(geom_img, origin=geom_img.true_center) e_geom = galsim.utilities.unweighted_shape(mom_geom) M_geom.set_text(Is.format(mom_geom['Mx']*geom_img.scale, mom_geom['My']*geom_img.scale, mom_geom['Mxx']*geom_img.scale**2, mom_geom['Myy']*geom_img.scale**2, mom_geom['Mxy']*geom_img.scale**2)) etext_geom.set_text("$e_1$={: 6.4f}, $e_2$={: 6.4f}, $r^2$={:6.4f}".format( e_geom['e1'], e_geom['e2'], e_geom['rsqr']*geom_img.scale**2)) geom_mom[i] = (mom_geom['Mx']*geom_img.scale, mom_geom['My']*geom_img.scale, mom_geom['Mxx']*geom_img.scale**2, mom_geom['Myy']*geom_img.scale**2, mom_geom['Mxy']*geom_img.scale**2, e_geom['e1'], e_geom['e2'], e_geom['rsqr']*geom_img.scale**2) if args.make_movie: writer.grab_frame(facecolor=fig.get_facecolor()) bar.update() def symmetrize_axis(ax): xlim = ax.get_xlim() ylim = ax.get_ylim() lim = min(xlim[0], ylim[0]), max(xlim[1], ylim[1]) ax.set_xlim(lim) ax.set_ylim(lim) ax.plot(lim, lim) if args.make_plots: # Centroid plot fig = Figure(figsize=(10, 6)) FigureCanvasAgg(fig) axes = [] axes.append(fig.add_subplot(1, 2, 1)) axes.append(fig.add_subplot(1, 2, 2)) axes[0].scatter(fft_mom[:, 0], geom_mom[:, 0]) axes[1].scatter(fft_mom[:, 1], geom_mom[:, 1]) axes[0].set_title("Mx") axes[1].set_title("My") for ax in axes: ax.set_xlabel("Fourier Optics") ax.set_ylabel("Geometric Optics") symmetrize_axis(ax) fig.tight_layout() fig.savefig(args.out+"centroid.png", dpi=300) # Second moment plot fig = Figure(figsize=(16, 6)) FigureCanvasAgg(fig) axes = [] axes.append(fig.add_subplot(1, 3, 1)) axes.append(fig.add_subplot(1, 3, 2)) axes.append(fig.add_subplot(1, 3, 3)) axes[0].scatter(fft_mom[:, 2], geom_mom[:, 2]) axes[1].scatter(fft_mom[:, 3], geom_mom[:, 3]) axes[2].scatter(fft_mom[:, 4], geom_mom[:, 4]) axes[0].set_title("Mxx") axes[1].set_title("Myy") axes[2].set_title("Mxy") for ax in axes: ax.set_xlabel("Fourier Optics") ax.set_ylabel("Geometric Optics") symmetrize_axis(ax) fig.tight_layout() fig.savefig(args.out+"2ndMoment.png", dpi=300) # Ellipticity plot fig = Figure(figsize=(16, 6)) FigureCanvasAgg(fig) axes = [] axes.append(fig.add_subplot(1, 3, 1)) axes.append(fig.add_subplot(1, 3, 2)) axes.append(fig.add_subplot(1, 3, 3)) axes[0].scatter(fft_mom[:, 5], geom_mom[:, 5]) axes[1].scatter(fft_mom[:, 6], geom_mom[:, 6]) axes[2].scatter(fft_mom[:, 7], geom_mom[:, 7]) axes[0].set_title("e1") axes[1].set_title("e2") axes[2].set_title("rsqr") for ax in axes: ax.set_xlabel("Fourier Optics") ax.set_ylabel("Geometric Optics") symmetrize_axis(ax) fig.tight_layout() fig.savefig(args.out+"ellipticity.png", dpi=300)
class VOAP2PPlot: """Program to plot .out files produced by voacap""" AUTOSCALE = -1.0 IMG_TYPE_DICT = { 0:{'title':'', 'min':0, 'max':1, 'y_labels':(0), 'formatter':'defaultFormat'}, \ 1:{'title':_('MUF Days (%)'), 'min':0, 'max':1, 'y_labels':(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1), 'formatter':'percent_format'}, \ 2:{'title':_('Circuit Reliability (%)'), 'min':0, 'max':1, 'y_labels':(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1), 'formatter':'percent_format'}, \ 3:{'title':_('SNR at Receiver (dB)'), 'min':20, 'max':70, 'y_labels':(20, 30, 40, 50, 60, 70), 'formatter':'SNR_format'}, \ 4:{'title':_('Signal Strength at Receiver (dBW)'), 'min':-151, 'max':-43, 'y_labels':(-151, -145, -139, -133, -127, -121,-115, -109, -103, -93, -83, -73, -63, -53, -43), 'formatter':'SDBW_format'} } mono_font = {'family' : 'monospace'} #default_font = {'family' : 'sans-serif'} S_LABELS = ['S1', 'S2', 'S3', 'S4', 'S5','S1', 'S2', 'S3', 'S4', 'S5','S1', 'S2', 'S3'] UK_BANDS = [(3.5, 3.8), (7.0, 7.2), (10.1, 10.15), (14.0, 14.35), (18.068, 18.168), \ (21.0, 21.45), (24.8, 24.99), (28.0, 29.7)] SWL_BANDS = [(3.200, 3.400), (3.900, 4.000), (4.750, 5.060), \ (5.950, 6.200), (7.100, 7.300), (9.500, 9.900), (11.650, 12.050), \ (13.600, 13.800), (15.100, 15.600), (17.550, 17.900), \ (18.900, 19.020), (21.450, 21.850), (25.670, 26.100)] KSA_BANDS = [(7.0, 7.2), (14.0, 14.35), (18.068, 18.168), \ (21.0, 21.45), (24.89, 24.99), (28.0, 29.7)] def __init__(self, data_file, plot_groups = [1], data_type = 2, color_map = 'jet', plot_contours = False, face_colour = "white", filled_contours = False, plot_label = "", plot_bands = None, time_zone = 0, plot_max_freq = 30.0, run_quietly = False, save_file = '', dpi=150, parent = None, user_bands=None, datadir=None): """ user_bands - a list of bands to be displayed. """ self.data_type = data_type self.run_quietly = run_quietly self.dpi=dpi self.face_colour = face_colour self.plot_filled_contours = filled_contours self.df = VOAOutFile(data_file, time_zone=time_zone, data_type=self.data_type, quiet=run_quietly) self.image_defs = self.IMG_TYPE_DICT[self.data_type] self.user_bands = user_bands #color_map = eval('P.cm.' + color_map) if plot_groups[0]=='a': num_grp = self.df.get_number_of_groups() plot_groups = list(range(0,num_grp)) self.subplots = [] number_of_subplots = len(plot_groups) #print matplotlib.get_backend() matplotlib.rcParams['axes.edgecolor'] = 'gray' matplotlib.rcParams['axes.facecolor'] = 'white' matplotlib.rcParams['axes.grid'] = True matplotlib.rcParams['legend.fancybox'] = True matplotlib.rcParams['legend.shadow'] = True matplotlib.rcParams['figure.subplot.hspace'] = 0.45 matplotlib.rcParams['figure.subplot.wspace'] = 0.35 matplotlib.rcParams['figure.subplot.right'] = 0.85 colorbar_fontsize = 12 if number_of_subplots <= 1: self.num_rows = 1 self.main_title_fontsize = 24 matplotlib.rcParams['legend.fontsize'] = 12 matplotlib.rcParams['axes.labelsize'] = 12 matplotlib.rcParams['axes.titlesize'] = 8 matplotlib.rcParams['xtick.labelsize'] = 10 matplotlib.rcParams['ytick.labelsize'] = 10 matplotlib.rcParams['figure.subplot.top'] = 0.79 # single figure plots have a larger title so require more space at the top. self.x_axes_ticks = np.arange(0,25,2) elif ((number_of_subplots >= 2) and (number_of_subplots <= 6 )): self.num_rows = 2 self.main_title_fontsize = 18 matplotlib.rcParams['legend.fontsize'] = 10 matplotlib.rcParams['axes.labelsize'] = 10 matplotlib.rcParams['axes.titlesize'] = 11 matplotlib.rcParams['xtick.labelsize'] = 8 matplotlib.rcParams['ytick.labelsize'] = 8 self.x_axes_ticks = np.arange(0,25,4) else: self.num_rows = 3 self.main_title_fontsize = 16 matplotlib.rcParams['legend.fontsize'] = 8 matplotlib.rcParams['axes.labelsize'] = 8 matplotlib.rcParams['axes.titlesize'] = 10 matplotlib.rcParams['xtick.labelsize'] = 6 matplotlib.rcParams['ytick.labelsize'] = 6 self.x_axes_ticks = np.arange(0,25,4) self.num_cols = int(math.ceil(float(number_of_subplots)/float(self.num_rows))) self.fig=Figure(figsize=(7,6.5), facecolor=face_colour) self.main_title_label = self.fig.suptitle(plot_label+str(self.image_defs['title']), fontsize=self.main_title_fontsize) for chan_grp in plot_groups: (group_name, group_info, fot, muf, hpf, image_buffer) = self.df.get_group_data(chan_grp) ax = self.fig.add_subplot(self.num_rows, self.num_cols, plot_groups.index(chan_grp)+1) self.subplots.append(ax) if number_of_subplots > 4: #save a little space by only labelling the outer edges of the plot ax.label_outer() _sign = '+' if (time_zone >= 0) else '' self.x_label = ax.set_xlabel(_('Time (UTC%(sig)s%(tz)s)') % {'sig':_sign, 'tz':time_zone}) self.y_label = ax.set_ylabel(_('Frequency (MHz)')) ## Autoscale y (frequency axis) if (plot_max_freq==self.AUTOSCALE) : y_max = math.ceil(max(muf) / 5.0) * 5.0 y_max = min(plot_max_freq, 30.0) y_max = max(plot_max_freq, 5.0) else : y_max = math.ceil(plot_max_freq / 5.0) * 5.0 #resize the image image_buffer = image_buffer[0:y_max-1,:] y_ticks = [2, 5] for y_tick_value in np.arange(10, y_max+1, 5): y_ticks.append(y_tick_value) ax.plot(list(range(0, 25)), muf,'r-', list(range(0, 25)), fot, 'g-') ax.set_ylim([2, y_max]) ax.set_xticks(self.x_axes_ticks) ax.set_yticks(y_ticks) self.add_legend(ax) title_str = group_info.strip() if number_of_subplots > 1: title_str = self.get_small_title(title_str) self.subplot_title_label = ax.set_title(title_str, multialignment='left', **self.mono_font) if (self.data_type > 0): if (self.plot_filled_contours): im = ax.contourf(image_buffer, self.image_defs['y_labels'], extent=(0, 24, 2, y_max), cmap=color_map) plot_contours =True else: im = ax.imshow(image_buffer, interpolation='bicubic', extent=(0, 24, 2, y_max), origin = 'lower', cmap=color_map, alpha = 0.95, norm = matplotlib.colors.Normalize(clip = False, vmin=self.image_defs['min'], vmax=self.image_defs['max'])) if plot_contours: ax.contour(image_buffer, self.image_defs['y_labels'][1:], extent=(0, 24, 2, y_max), linewidths=1.0, colors='k', alpha=0.6) if plot_bands: for a,b in plot_bands: ax.axhspan(a, b, alpha=0.5, ec='k', fc='k') if self.user_bands: for ch in self.user_bands: ax.axhspan(ch-0.04, ch+0.04, alpha=0.5, ec='0.5', fc='0.5') if (self.data_type > 0): self.cb_ax = self.fig.add_axes(self.get_cb_axes()) self.fig.colorbar(im, cax=self.cb_ax, orientation='vertical', format = FuncFormatter(eval('self.'+self.image_defs['formatter']))) for t in self.cb_ax.get_yticklabels(): t.set_fontsize(colorbar_fontsize) # TODO tight_layout looks a neater way to layout the grid #self.fig.tight_layout() canvas = FigureCanvasGTK3Agg(self.fig) self.fig.canvas.mpl_connect('draw_event', self.on_draw) canvas.show() if save_file : self.save_plot(save_file) if not self.run_quietly: # TODO consider using a scrolled pane here... dia = VOAPlotWindow('pythonProp - ' + self.image_defs['title'], canvas, parent=parent, dpi=self.dpi, datadir=datadir) return def get_png(self, id): print("creating a png") self.save_plot("test.png") def on_draw(self, event): top = self.fig.subplotpars.top bottom = self.fig.subplotpars.bottom hspace = self.fig.subplotpars.hspace wspace = self.fig.subplotpars.wspace needs_adjusting = False # Calculate the area required at the top of the plot # (Main title and subplot title) subplot_title_height = 0 main_title_height = 0 for subplot in self.subplots: if subplot.is_first_row(): bbox = subplot.title.get_window_extent() transformed_bbox = bbox.inverse_transformed(self.fig.transFigure) subplot_title_height = max(transformed_bbox.height, subplot_title_height) #print 'title = ', self.fig.get_label() bbox = self.main_title_label.get_window_extent() main_title_height = bbox.inverse_transformed(self.fig.transFigure).height preferred_top_space = 1.25*(subplot_title_height + main_title_height) if ((1 - top) < preferred_top_space) or (((1 - top) - preferred_top_space)>0.11): top = 0.99 - preferred_top_space needs_adjusting = True if needs_adjusting: #print 'adjusting' #todo if the colorbar dosn't exist, ignore this. self.fig.subplots_adjust(top = top, bottom = bottom, hspace = hspace, wspace = wspace) self.cb_ax.set_position(self.get_cb_axes()) self.fig.canvas.draw() return False def add_legend(self, ax): leg = ax.legend(('MUF', 'FOT'),ncol=1) leg.get_frame().set_alpha(0.75) return leg def save_plot(self, filename=None): #canvas.print_figure(filename, dpi=150, facecolor='white', edgecolor='white') self.fig.savefig(filename, dpi=self.dpi, facecolor=self.fig.get_facecolor(), edgecolor='none') def get_cb_axes(self): # an equivalent of get_tightbox would be really useful here... #bbox = self.subplots[0].get_window_extent() bbox = self.subplots[0].get_yaxis().get_clip_box() axis_upper_y = bbox.inverse_transformed(self.fig.transFigure).ymax bbox = self.subplots[-1].get_window_extent() axis_lower_y = bbox.inverse_transformed(self.fig.transFigure).ymin return [0.9, axis_lower_y, 0.02, axis_upper_y-axis_lower_y] #def percentFormat(x, pos): # 'The two args are the value and tick position' # return '%(percent)3d%% (%(days)d days)' % {'percent':x*100, 'days':x*30.0} def percent_format(self, x, pos): return '%(percent)3d%%' % {'percent':x*100} def SNR_format(self, x, pos): return '%3ddB' % x def defaultFormat(self, x, pos): return '%d' % x def SDBW_format(self, x, pos): S_DICT = {-151:'S1', -145:'S2', -139:'S3', -133:'S4', -127:'S5', \ -121:'S6', -115:'S7', -109:'S8', -103:'S9', -93:'S9+10dB', \ -83:'S9+20dB', -73:'S9+30dB', -63:'S9+40dB', -53:'S9+50dB', -43:'S9+60dB'} if x in S_DICT: return _('%(value)ddBW (%(s_value)s)') %{'value':x, 's_value':S_DICT[x]} else : return '%3d' % x def get_small_title(self, title_string): #Mar 2008 SSN = 7. Minimum Angle= 3.000 degrees #RIYADH (AR RIYAD) YORK AZIMUTHS N. MI. KM #24.63 N 46.71 E - 53.96 N 1.08 W 322.62 110.27 2753.7 5099.5 #XMTR 2-30 2-D Table [default/swwhip.voa ] Az=322.6 OFFaz= 0.0 0.005kW #RCVR 2-30 2-D Table [default/swwhip.voa ] Az=110.3 OFFaz=360.0 #3 MHz NOISE = -145.0 dBW REQ. REL = 90% REQ. SNR = 10.0 dB title_lines = title_string.split('\n') #Extract Month / year and SSN tmp_line = title_lines[0].split() tmp_str = tmp_line[0] + ' ' + tmp_line[1] + ' SSN:' + tmp_line[4].rstrip('.') return tmp_str
class VOAAreaPlot: IMG_TYPE_DICT = { 1: { "plot_type": "MUF", "title": _("Maximum Usable Frequency (MUF)"), "min": 2, "max": 30, "y_labels": (2, 5, 10, 15, 20, 25, 30), "formatter": "frequency_format", "first_char": 27, "last_char": 32, }, 2: { "plot_type": "REL", "title": _("Circuit Reliability (%)"), "min": 0, "max": 1, "y_labels": (0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1), "formatter": "percent_format", "first_char": 98, "last_char": 104, }, 3: { "plot_type": "SNR", "title": _("SNR at Receiver (dB)"), "min": 20, "max": 70, "y_labels": (20, 30, 40, 50, 60, 70), "formatter": "SNR_format", "first_char": 86, "last_char": 92, }, 4: { "plot_type": "SNRXX", "title": _("SNRxx"), "min": 0, "max": 100, "y_labels": (0, 20, 40, 60, 80, 100), "formatter": "SNR_format", "first_char": 130, "last_char": 134, }, 5: { "plot_type": "SDBW", "title": _("Signal Power"), "min": -160, "max": -40, "y_labels": (-160, -140, -120, -100, -80, -60, -40), "formatter": "SDBW_format", "first_char": 74, "last_char": 80, }, 6: { "plot_type": "SMETESNRXXR", "title": _("S-Meter"), "min": -151.18, "max": -43.01, "y_labels": (-151.18, -139.13, -127.09, -115.05, -103.01, -83.01, -63.01, -43.01), "formatter": "SMETER_format", "first_char": 74, "last_char": 80, }, } COLOUR_MAPS = [ _("autumn"), _("bone"), _("cool"), _("copper"), _("gray"), _("hot"), _("hsv"), _("jet"), _("pink"), _("spring"), _("summer"), _("winter"), ] default_font = {"family": "sans-serif"} show_subplot_frame = True def __init__( self, in_file, vg_files=[1], data_type=1, projection="cyl", color_map="jet", face_colour="white", time_zone=0, plot_contours=False, plot_center="t", plot_meridians=True, plot_parallels=True, plot_terminator=True, resolution="c", points_of_interest=[], save_file="", run_quietly=False, dpi=150, parent=None, ): self.run_quietly = run_quietly self.dpi = float(dpi) plot_parameters = VOAFile((in_file + ".voa")) plot_parameters.parse_file() if plot_parameters.get_projection() != "cyl": print _("Error: Only lat/lon (type 1) input files are supported") sys.exit(1) grid = plot_parameters.get_gridsize() self.image_defs = VOAAreaPlot.IMG_TYPE_DICT[int(data_type)] # TODO This needs a little more work... what if the pcenter card is not specified if plot_center == "p": plot_centre_location = plot_parameters.get_location(plot_parameters.P_CENTRE) else: plot_centre_location = plot_parameters.get_location(plot_parameters.TX_SITE) self.points_of_interest = [plot_centre_location] if len(points_of_interest) > 0: self.points_of_interest.extend(points_of_interest) imageBuf = P.zeros([grid, grid], float) area_rect = plot_parameters.get_area_rect() # The checks ought to be performed in the area_rect. # Do a few basic sanity checks # # if ( (area_rect.get_sw_lon() < -180) or (area_rect.get_ne_lon() > 180.0) or (area_rect.get_sw_lat() < -90) or (area_rect.get_ne_lat() > 90.0) ): # print "Input file latitudes/longitudes are out of range" # print "-180 < Latitude < 180.0, -90 < Longitude < 90" # sys.exit(1) # if ( (area_rect.get_sw_lon() == area_rect.get_ne_lon()) or (area_rect.get_sw_lat() == area_rect.get_ne_lat()) ): # print "Input file latitudes/longitudes are the same" # print "-180 < Latitude < 180.0, -90 < Longitude < 90" # sys.exit(1) points = P.zeros([grid, grid], float) lons = P.zeros(grid * grid, float) lats = P.zeros(grid * grid, float) lons = P.arange( area_rect.get_sw_lon(), area_rect.get_ne_lon() + 0.001, (area_rect.get_ne_lon() - area_rect.get_sw_lon()) / float(grid - 1), ) lats = P.arange( area_rect.get_sw_lat(), area_rect.get_ne_lat() + 0.001, (area_rect.get_ne_lat() - area_rect.get_sw_lat()) / float(grid - 1), ) colString = "P.cm." + color_map colMap = eval(colString) self.subplots = [] self.number_of_subplots = len(vg_files) matplotlib.rcParams["axes.edgecolor"] = "gray" matplotlib.rcParams["axes.facecolor"] = "white" matplotlib.rcParams["figure.facecolor"] = face_colour # matplotlib.rcParams['figure.figsize'] = (6, 10) matplotlib.rcParams["figure.subplot.hspace"] = 0.45 matplotlib.rcParams["figure.subplot.wspace"] = 0.35 matplotlib.rcParams["figure.subplot.right"] = 0.85 colorbar_fontsize = 12 if self.number_of_subplots <= 1: self.num_rows = 1 self.main_title_fontsize = 24 matplotlib.rcParams["legend.fontsize"] = 12 matplotlib.rcParams["axes.labelsize"] = 12 matplotlib.rcParams["axes.titlesize"] = 10 matplotlib.rcParams["xtick.labelsize"] = 10 matplotlib.rcParams["ytick.labelsize"] = 10 matplotlib.rcParams[ "figure.subplot.top" ] = 0.8 # single figure plots have a larger title so require more space at the top. elif (self.number_of_subplots >= 2) and (self.number_of_subplots <= 6): self.num_rows = 2 self.main_title_fontsize = 18 matplotlib.rcParams["legend.fontsize"] = 10 matplotlib.rcParams["axes.labelsize"] = 10 matplotlib.rcParams["axes.titlesize"] = 11 matplotlib.rcParams["xtick.labelsize"] = 8 matplotlib.rcParams["ytick.labelsize"] = 8 # self.x_axes_ticks = P.arange(0,25,4) else: self.num_rows = 3 self.main_title_fontsize = 16 matplotlib.rcParams["legend.fontsize"] = 8 matplotlib.rcParams["axes.labelsize"] = 8 matplotlib.rcParams["axes.titlesize"] = 10 matplotlib.rcParams["xtick.labelsize"] = 6 matplotlib.rcParams["ytick.labelsize"] = 6 # self.x_axes_ticks = P.arange(0,25,4) self.num_cols = int(math.ceil(float(self.number_of_subplots) / float(self.num_rows))) self.fig = Figure() self.main_title_label = self.fig.suptitle( unicode(self.image_defs["title"], "utf-8"), fontsize=self.main_title_fontsize ) if projection == "ortho": self.show_subplot_frame = False for plot_ctr in range(self.number_of_subplots): # ax = self.fig.add_subplot(plot_ctr) ax = self.fig.add_subplot( self.num_rows, self.num_cols, plot_ctr + 1, frame_on=self.show_subplot_frame, axisbg="white" ) self.subplots.append(ax) ax.label_outer() # print "opening: ",(in_file+'.vg'+str(vg_files[plot_ctr])) vgFile = open(in_file + ".vg" + str(vg_files[plot_ctr])) pattern = re.compile(r"[a-z]+") for line in vgFile: match = pattern.search(line) if not match: value = float(line[int(self.image_defs["first_char"]) : int(self.image_defs["last_char"])]) # TODO Does this need to be normalised here if it's also being done in the plot? value = max(self.image_defs["min"], value) value = min(self.image_defs["max"], value) # if value < self.image_defs[2] : value = self.image_defs[2] # if value > self.image_defs[3] : value = self.image_defs[3] points[int(line[3:6]) - 1][int(line[0:3]) - 1] = value vgFile.close() map = Basemap( llcrnrlon=area_rect.get_sw_lon(), llcrnrlat=area_rect.get_sw_lat(), urcrnrlon=area_rect.get_ne_lon(), urcrnrlat=area_rect.get_ne_lat(), projection=projection, lat_0=plot_centre_location.get_latitude(), lon_0=plot_centre_location.get_longitude(), resolution=resolution, ax=ax, ) map.drawcoastlines(color="black") map.drawcountries(color="grey") map.drawmapboundary(color="black", linewidth=1.0) warped = ma.zeros((grid, grid), float) warped, warped_lon, warped_lat = map.transform_scalar( points, lons, lats, grid, grid, returnxy=True, checkbounds=False, masked=True ) warped = warped.filled(self.image_defs["min"] - 1.0) colMap.set_under(color="k", alpha=0.0) im = map.imshow( warped, cmap=colMap, extent=(-180, 180, -90, 90), origin="lower", norm=P.Normalize(clip=False, vmin=self.image_defs["min"], vmax=self.image_defs["max"]), ) ####################### # Plot greyline ####################### if plot_terminator: the_sun = Sun() the_month = plot_parameters.get_month(vg_files[plot_ctr] - 1) the_day = plot_parameters.get_day(vg_files[plot_ctr] - 1) the_hour = plot_parameters.get_utc(vg_files[plot_ctr] - 1) if the_day == 0: the_day = 15 the_year = datetime.date.today().year num_days_since_2k = the_sun.daysSince2000Jan0(the_year, the_month, the_day) res = the_sun.sunRADec(num_days_since_2k) declination = res[1] if declination == 0.0: declination = -0.001 tau = the_sun.computeGHA(the_day, the_month, the_year, the_hour) if declination > 0: terminator_end_lat = area_rect.get_sw_lat() else: terminator_end_lat = area_rect.get_ne_lat() terminator_lat = [terminator_end_lat] terminator_lon = [area_rect.get_sw_lon()] for i in range(int(area_rect.get_sw_lon()), int(area_rect.get_ne_lon()), 1) + [ int(area_rect.get_ne_lon()) ]: longitude = i + tau tan_lat = -the_sun.cosd(longitude) / the_sun.tand(declination) latitude = the_sun.atand(tan_lat) latitude = max(latitude, area_rect.get_sw_lat()) latitude = min(latitude, area_rect.get_ne_lat()) xpt, ypt = map(i, latitude) terminator_lon.append(xpt) terminator_lat.append(ypt) terminator_lon.append(area_rect.get_ne_lon()) terminator_lat.append(terminator_end_lat) # This is a little simplistic and doesn't work for ortho plots.... ax.plot(terminator_lon, terminator_lat, color="grey", alpha=0.75) ax.fill(terminator_lon, terminator_lat, facecolor="grey", alpha=0.5) tau = -tau if tau > 180.0: tau = tau - 360.0 if tau < -180.0: tau = tau + 360.0 # Plot the position of the sun (if it's in the coverage area) if area_rect.contains(declination, tau): xpt, ypt = map(tau, declination) # sbplt_ax.plot([xpt],[ypt],'yh') ax.plot([xpt], [ypt], "yh") ########################## # Points of interest ########################## for location in self.points_of_interest: if area_rect.contains(location.get_latitude(), location.get_longitude()): xpt, ypt = map(location.get_longitude(), location.get_latitude()) ax.plot([xpt], [ypt], "ro") ax.text(xpt + 100000, ypt + 100000, location.get_name()) if plot_meridians: if area_rect.get_lon_delta() <= 90.0: meridians = P.arange(-180, 190.0, 10.0) elif area_rect.get_lon_delta() <= 180.0: meridians = P.arange(-180.0, 210.0, 30.0) else: meridians = P.arange(-180, 240.0, 60.0) if (projection == "ortho") or (projection == "vandg"): map.drawmeridians(meridians) else: map.drawmeridians(meridians, labels=[1, 1, 0, 1]) if plot_parallels: if area_rect.get_lat_delta() <= 90.0: parallels = P.arange(-90.0, 120.0, 60.0) else: parallels = P.arange(-90.0, 120.0, 30.0) if (projection == "ortho") or (projection == "vandg"): map.drawparallels(parallels) else: map.drawparallels(parallels, labels=[1, 1, 0, 1]) if plot_contours: map.contour( warped_lon, warped_lat, warped, self.image_defs["y_labels"], linewidths=1.0, colors="k", alpha=0.5 ) # add a title title_str = plot_parameters.get_plot_description_string( vg_files[plot_ctr] - 1, self.image_defs["plot_type"], time_zone ) if self.number_of_subplots == 1: title_str = plot_parameters.get_plot_description_string( vg_files[plot_ctr] - 1, self.image_defs["plot_type"], time_zone ) title_str = ( title_str + "\n" + plot_parameters.get_detailed_plot_description_string(vg_files[plot_ctr] - 1) ) else: title_str = plot_parameters.get_minimal_plot_description_string( vg_files[plot_ctr] - 1, self.image_defs["plot_type"], time_zone ) self.subplot_title_label = ax.set_title(title_str) # Add a colorbar on the right hand side, aligned with the # top of the uppermost plot and the bottom of the lowest # plot. self.cb_ax = self.fig.add_axes(self.get_cb_axes()) self.fig.colorbar( im, cax=self.cb_ax, orientation="vertical", ticks=self.image_defs["y_labels"], format=P.FuncFormatter(eval("self." + self.image_defs["formatter"])), ) # print self.image_defs['y_labels'] for t in self.cb_ax.get_yticklabels(): t.set_fontsize(colorbar_fontsize) canvas = FigureCanvasGTK3Agg(self.fig) self.fig.canvas.mpl_connect("draw_event", self.on_draw) canvas.show() if save_file: self.save_plot(canvas, save_file) # todo this ought to a command line param if not self.run_quietly: dia = VOAPlotWindow("pythonProp - " + self.image_defs["title"], canvas, parent=parent) return def on_draw(self, event): top = self.fig.subplotpars.top bottom = self.fig.subplotpars.bottom hspace = self.fig.subplotpars.hspace wspace = self.fig.subplotpars.wspace fig_height = self.fig.get_figheight() needs_adjusting = False # Area required at the top of the plot (Main title and subplot title) bbox = self.subplot_title_label.get_window_extent() subplot_title_bbox = bbox.inverse_transformed(self.fig.transFigure) bbox = self.main_title_label.get_window_extent() main_title_bbox = bbox.inverse_transformed(self.fig.transFigure) _preferred_top_space = 1.25 * (subplot_title_bbox.height + main_title_bbox.height) _actual_top_space = 1 - top if (_actual_top_space < _preferred_top_space) or ((_actual_top_space - _preferred_top_space) > 0.11): top = 0.99 - _preferred_top_space needs_adjusting = True if needs_adjusting: self.fig.subplots_adjust(top=top, bottom=bottom, hspace=hspace, wspace=wspace) self.cb_ax.set_position(self.get_cb_axes()) self.fig.canvas.draw() return False def save_plot(self, canvas, filename=None): canvas.print_figure(filename, dpi=self.dpi, facecolor=self.fig.get_facecolor(), edgecolor="none") def get_cb_axes(self): bbox = self.subplots[0].get_window_extent() axis_upper_y = bbox.inverse_transformed(self.fig.transFigure).ymax bbox = self.subplots[-1].get_window_extent() axis_lower_y = bbox.inverse_transformed(self.fig.transFigure).ymin return [0.87, axis_lower_y, 0.02, axis_upper_y - axis_lower_y] def percent_format(self, x, pos): return "%(percent)3d%%" % {"percent": x * 100} def SNR_format(self, x, pos): return "%3ddB" % x def SDBW_format(self, x, pos): return "%3ddBW" % x """ The values below are derived from material presented at http://www.voacap.com/s-meter.html """ def SMETER_format(self, x, pos): print x S_DICT = { -151.18: "S1", -145.15: "S2", -139.13: "S3", -133.11: "S4", -127.09: "S5", -121.07: "S6", -115.05: "S7", -109.03: "S8", -103.01: "S9", -93.01: "S9+10dB", -83.01: "S9+20dB", -73.01: "S9+30dB", -63.01: "S9+40dB", -53.01: "S9+50dB", -43.01: "S9+60dB", } if S_DICT.has_key(x): return "%s" % S_DICT[x] # return _('%(value)ddBW (%(s_value)s)') %{'value':x, 's_value':S_DICT[x]} else: return "%3d" % x def frequency_format(self, x, pos): return "%2dMHz" % x def default_format(self, x, pos): return "%d" % x
def make_movie(args): rng = galsim.BaseDeviate(args.seed) u = galsim.UniformDeviate(rng) # Generate 1D Gaussian random fields for each aberration. t = np.arange(-args.n/2, args.n/2) corr = np.exp(-0.5*t**2/args.ell**2) pk = np.fft.fft(np.fft.fftshift(corr)) ak = np.sqrt(2*pk) phi = np.random.uniform(size=(args.n, args.jmax)) zk = ak[:, None]*np.exp(2j*np.pi*phi) aberrations = args.n/2*np.fft.ifft(zk, axis=0).real measured_std = np.mean(np.std(aberrations, axis=0)) aberrations *= args.sigma/measured_std aberrations -= np.mean(aberrations, axis=0) # For the atmosphere screens, we first estimates weights, so that the turbulence is dominated by # the lower layers consistent with direct measurements. The specific values we use are from # SCIDAR measurements on Cerro Pachon as part of the 1998 Gemini site selection process # (Ellerbroek 2002, JOSA Vol 19 No 9). Ellerbroek_alts = [0.0, 2.58, 5.16, 7.73, 12.89, 15.46] # km Ellerbroek_weights = [0.652, 0.172, 0.055, 0.025, 0.074, 0.022] Ellerbroek_interp = galsim.LookupTable(Ellerbroek_alts, Ellerbroek_weights, interpolant='linear') alts = np.max(Ellerbroek_alts)*np.arange(args.nlayers)/(args.nlayers-1) weights = Ellerbroek_interp(alts) # interpolate the weights weights /= sum(weights) # and renormalize spd = [] # Wind speed in m/s dirn = [] # Wind direction in radians r0_500 = [] # Fried parameter in m at a wavelength of 500 nm. for i in range(args.nlayers): spd.append(u()*args.max_speed) # Use a random speed between 0 and args.max_speed dirn.append(u()*360*galsim.degrees) # And an isotropically distributed wind direction. r0_500.append(args.r0_500*weights[i]**(-3./5)) print("Adding layer at altitude {:5.2f} km with velocity ({:5.2f}, {:5.2f}) m/s, " "and r0_500 {:5.3f} m." .format(alts[i], spd[i]*dirn[i].cos(), spd[i]*dirn[i].sin(), r0_500[i])) if args.nlayers > 0: # Make two identical Atmospheres. They will diverge when one gets drawn using Fourier # optics and the other gets drawn with geometric optics. fft_atm = galsim.Atmosphere(r0_500=r0_500, speed=spd, direction=dirn, altitude=alts, rng=rng.duplicate(), screen_size=args.screen_size, screen_scale=args.screen_scale) geom_atm = galsim.Atmosphere(r0_500=r0_500, speed=spd, direction=dirn, altitude=alts, rng=rng.duplicate(), screen_size=args.screen_size, screen_scale=args.screen_scale) else: fft_atm = galsim.PhaseScreenList() geom_atm = galsim.PhaseScreenList() # Before either of this has been instantiated, they are identical assert fft_atm == geom_atm # If any AtmosphericScreens are included, we manually instantiate here so we can have a # uniformly updating ProgressBar both here and below when actually drawing PSFs. Normally, it's # okay to let the atms automatically instantiate, which happens when the first PSF is drawn, or # the first wavefront is queried. if args.nlayers > 0: print("Instantiating screens") with ProgressBar(2*args.nlayers) as bar: fft_atm.instantiate(_bar=bar) r0 = args.r0_500*(args.lam/500)**1.2 geom_atm.instantiate(kmax=0.2/r0, _bar=bar) # After instantiation, they're only equal if there's no atmosphere. assert fft_atm != geom_atm # Setup Fourier and geometric apertures fft_aper = galsim.Aperture(args.diam, args.lam, obscuration=args.obscuration, pad_factor=args.pad_factor, oversampling=args.oversampling, nstruts=args.nstruts, strut_thick=args.strut_thick, strut_angle=args.strut_angle*galsim.degrees) geom_aper = galsim.Aperture(args.diam, args.lam, obscuration=args.obscuration, pad_factor=args.geom_oversampling, oversampling=0.5, nstruts=args.nstruts, strut_thick=args.strut_thick, strut_angle=args.strut_angle*galsim.degrees) scale = args.size/args.nx extent = np.r_[-1,1,-1,1]*args.size/2 fft_img_sum = galsim.ImageD(args.nx, args.nx, scale=scale) geom_img_sum = galsim.ImageD(args.nx, args.nx, scale=scale) # Code to setup the Matplotlib animation. metadata = dict(title="FFT vs geom movie", artist='Matplotlib') writer = anim.FFMpegWriter(fps=15, bitrate=10000, metadata=metadata) fig = Figure(facecolor='k', figsize=(16, 9)) FigureCanvasAgg(fig) fft_ax = fig.add_axes([0.07, 0.08, 0.36, 0.9]) fft_ax.set_xlabel("Arcsec") fft_ax.set_ylabel("Arcsec") fft_ax.set_title("Fourier Optics") fft_im = fft_ax.imshow(np.ones((args.nx, args.nx), dtype=float), animated=True, extent=extent, vmin=0.0, vmax=args.vmax) # Axis for the wavefront image on the right. geom_ax = fig.add_axes([0.50, 0.08, 0.36, 0.9]) geom_ax.set_xlabel("Arcsec") geom_ax.set_ylabel("Arcsec") geom_ax.set_title("Geometric Optics") geom_im = geom_ax.imshow(np.ones((args.nx, args.nx), dtype=float), animated=True, extent=extent, vmin=0.0, vmax=args.vmax) # Color items white to show up on black background for ax in [fft_ax, geom_ax]: for _, spine in ax.spines.items(): spine.set_color('w') ax.title.set_color('w') ax.xaxis.label.set_color('w') ax.yaxis.label.set_color('w') ax.tick_params(axis='both', colors='w') ztext = [] for i in range(2, args.jmax+1): x = 0.88 y = 0.1 + (args.jmax-i)/args.jmax*0.8 ztext.append(fig.text(x, y, "Z{:d} = {:5.3f}".format(i, 0.0))) ztext[-1].set_color('w') M_fft = fft_ax.text(0.02, 0.955, '', transform=fft_ax.transAxes) M_fft.set_color('w') M_geom = geom_ax.text(0.02, 0.955, '', transform=geom_ax.transAxes) M_geom.set_color('w') etext_fft = fft_ax.text(0.02, 0.91, '', transform=fft_ax.transAxes) etext_fft.set_color('w') etext_geom = geom_ax.text(0.02, 0.91, '', transform=geom_ax.transAxes) etext_geom.set_color('w') fft_mom = np.empty((args.n, 8), dtype=float) geom_mom = np.empty((args.n, 8), dtype=float) fullpath = args.out+"movie.mp4" subdir, filename = os.path.split(fullpath) if subdir and not os.path.isdir(subdir): os.makedirs(subdir) print("Drawing PSFs") with ProgressBar(args.n) as bar: with writer.saving(fig, fullpath, 100): t0 = 0.0 for i, aberration in enumerate(aberrations): optics = galsim.OpticalScreen(args.diam, obscuration=args.obscuration, aberrations=[0]+aberration.tolist()) fft_psl = galsim.PhaseScreenList(fft_atm._layers+[optics]) geom_psl = galsim.PhaseScreenList(geom_atm._layers+[optics]) fft_psf = fft_psl.makePSF( lam=args.lam, aper=fft_aper, t0=t0, exptime=args.time_step) geom_psf = geom_psl.makePSF( lam=args.lam, aper=geom_aper, t0=t0, exptime=args.time_step) fft_img0 = fft_psf.drawImage(nx=args.nx, ny=args.nx, scale=scale) geom_img0 = geom_psf.drawImage(nx=args.nx, ny=args.nx, scale=scale, method='phot', n_photons=100000) t0 += args.time_step if args.accumulate: fft_img_sum += fft_img0 geom_img_sum += geom_img0 fft_img = fft_img_sum/(i+1) geom_img = geom_img_sum/(i+1) else: fft_img = fft_img0 geom_img = geom_img0 fft_im.set_array(fft_img.array) geom_im.set_array(geom_img.array) for j, ab in enumerate(aberration): if j == 0: continue ztext[j-1].set_text("Z{:d} = {:5.3f}".format(j+1, ab)) # Calculate simple estimate of ellipticity mom_fft = galsim.utilities.unweighted_moments(fft_img, origin=fft_img.true_center) mom_geom = galsim.utilities.unweighted_moments(geom_img, origin=geom_img.true_center) e_fft = galsim.utilities.unweighted_shape(mom_fft) e_geom = galsim.utilities.unweighted_shape(mom_geom) Is = ("$M_x$={: 6.4f}, $M_y$={: 6.4f}, $M_{{xx}}$={:6.4f}," " $M_{{yy}}$={:6.4f}, $M_{{xy}}$={: 6.4f}") M_fft.set_text(Is.format(mom_fft['Mx']*fft_img.scale, mom_fft['My']*fft_img.scale, mom_fft['Mxx']*fft_img.scale**2, mom_fft['Myy']*fft_img.scale**2, mom_fft['Mxy']*fft_img.scale**2)) M_geom.set_text(Is.format(mom_geom['Mx']*geom_img.scale, mom_geom['My']*geom_img.scale, mom_geom['Mxx']*geom_img.scale**2, mom_geom['Myy']*geom_img.scale**2, mom_geom['Mxy']*geom_img.scale**2)) etext_fft.set_text("$e_1$={: 6.4f}, $e_2$={: 6.4f}, $r^2$={:6.4f}".format( e_fft['e1'], e_fft['e2'], e_fft['rsqr']*fft_img.scale**2)) etext_geom.set_text("$e_1$={: 6.4f}, $e_2$={: 6.4f}, $r^2$={:6.4f}".format( e_geom['e1'], e_geom['e2'], e_geom['rsqr']*geom_img.scale**2)) fft_mom[i] = (mom_fft['Mx']*fft_img.scale, mom_fft['My']*fft_img.scale, mom_fft['Mxx']*fft_img.scale**2, mom_fft['Myy']*fft_img.scale**2, mom_fft['Mxy']*fft_img.scale**2, e_fft['e1'], e_fft['e2'], e_fft['rsqr']*fft_img.scale**2) geom_mom[i] = (mom_geom['Mx']*geom_img.scale, mom_geom['My']*geom_img.scale, mom_geom['Mxx']*geom_img.scale**2, mom_geom['Myy']*geom_img.scale**2, mom_geom['Mxy']*geom_img.scale**2, e_geom['e1'], e_geom['e2'], e_geom['rsqr']*geom_img.scale**2) writer.grab_frame(facecolor=fig.get_facecolor()) bar.update() def symmetrize_axis(ax): xlim = ax.get_xlim() ylim = ax.get_ylim() lim = min(xlim[0], ylim[0]), max(xlim[1], ylim[1]) ax.set_xlim(lim) ax.set_ylim(lim) ax.plot(lim, lim) # Centroid plot fig = Figure(figsize=(10, 6)) FigureCanvasAgg(fig) axes = [] axes.append(fig.add_subplot(1, 2, 1)) axes.append(fig.add_subplot(1, 2, 2)) axes[0].scatter(fft_mom[:, 0], geom_mom[:, 0]) axes[1].scatter(fft_mom[:, 1], geom_mom[:, 1]) axes[0].set_title("Mx") axes[1].set_title("My") for ax in axes: ax.set_xlabel("Fourier Optics") ax.set_ylabel("Geometric Optics") symmetrize_axis(ax) fig.tight_layout() fig.savefig(args.out+"centroid.png", dpi=300) # Second moment plot fig = Figure(figsize=(16, 6)) FigureCanvasAgg(fig) axes = [] axes.append(fig.add_subplot(1, 3, 1)) axes.append(fig.add_subplot(1, 3, 2)) axes.append(fig.add_subplot(1, 3, 3)) axes[0].scatter(fft_mom[:, 2], geom_mom[:, 2]) axes[1].scatter(fft_mom[:, 3], geom_mom[:, 3]) axes[2].scatter(fft_mom[:, 4], geom_mom[:, 4]) axes[0].set_title("Mxx") axes[1].set_title("Myy") axes[2].set_title("Mxy") for ax in axes: ax.set_xlabel("Fourier Optics") ax.set_ylabel("Geometric Optics") symmetrize_axis(ax) fig.tight_layout() fig.savefig(args.out+"2ndMoment.png", dpi=300) # Ellipticity plot fig = Figure(figsize=(16, 6)) FigureCanvasAgg(fig) axes = [] axes.append(fig.add_subplot(1, 3, 1)) axes.append(fig.add_subplot(1, 3, 2)) axes.append(fig.add_subplot(1, 3, 3)) axes[0].scatter(fft_mom[:, 5], geom_mom[:, 5]) axes[1].scatter(fft_mom[:, 6], geom_mom[:, 6]) axes[2].scatter(fft_mom[:, 7], geom_mom[:, 7]) axes[0].set_title("e1") axes[1].set_title("e2") axes[2].set_title("rsqr") for ax in axes: ax.set_xlabel("Fourier Optics") ax.set_ylabel("Geometric Optics") symmetrize_axis(ax) fig.tight_layout() fig.savefig(args.out+"ellipticity.png", dpi=300)
prmsl_m = prmsl.collapsed('member', iris.analysis.MEAN) prmsl_s = prmsl.collapsed('member', iris.analysis.STD_DEV) #prmsl_m.data[numpy.where(prmsl_s.data>300)]=numpy.nan mg.pressure.plot(ax_left, prmsl_m, scale=0.01, resolution=0.25, levels=numpy.arange(875, 1050, 10), colors='black', label=True, linewidths=2) mg.utils.plot_label(ax_left, '20CRv3', fontsize=16, facecolor=fig.get_facecolor(), x_fraction=0.04, horizontalalignment='left') mg.utils.plot_label(ax_left, '%04d-%02d-%02d:%02d' % (year, month, day, hour), fontsize=16, facecolor=fig.get_facecolor(), x_fraction=0.96, horizontalalignment='right') # In the centre - spaghetti-contour plot of scout 4.6.1 ax_centre = fig.add_axes([0.335, 0.01, 0.323, 0.98], projection=projection) ax_centre.set_axis_off() ax_centre.set_extent(extent, crs=projection) ax_centre.background_patch.set_facecolor((0.88, 0.88, 0.88, 1))
def dgraph4(request): p_val = request.GET try: cmore = [float(p_val['cb{}'.format(x)]) for x in range(1,9)] mdr = [float(p_val['mb{}'.format(x)]) for x in range(1,9)] c_hi = [float(p_val['cbh{}'.format(x)]) for x in xrange(1,9)] c_lo = [float(p_val['cbl{}'.format(x)]) for x in xrange(1,9)] mdr_hi= [float(p_val['mbh{}'.format(x)]) for x in xrange(1,9)] mdr_lo= [float(p_val['mbl{}'.format(x)]) for x in xrange(1,9)] except: return render(request,"bad.html",{ 'type':'dot graph 2' }) which = -1 try: which = int(p_val['ref']) except: pass if p_val['flag'] == 'E': try: e2m = [float(p_val['e1%dm'%(x)]) for x in xrange(1,9)] e2c = [float(p_val['e1%dc'%(x)]) for x in xrange(1,9)] except: return render(request,"bad.html", { 'type':'uncert_e bargraph' }) elif p_val['flag'] == 'P': try: p2m = [float(p_val['p1%dm'%(x)]) for x in xrange(1,9)] p2c = [float(p_val['p1%dc'%(x)]) for x in xrange(1,9)] except: return render(request,"bad.html", { 'type':'uncert_p bargraph' }) elif p_val['flag'] == 'R': try: r2m = [float(p_val['r1%dm'%(x)]) for x in xrange(1,9)] r2c = [float(p_val['r1%dc'%(x)]) for x in xrange(1,9)] except: return render(request,"bad.html", { 'type':'uncert_r bargraph' }) fig = Figure(facecolor='white', dpi=150) canvas = FigureCanvas(fig) ax = fig.add_subplot(111) ax.set_xlabel('% decrease in MDR-TB incidence at year 5 (more effective -->)',{'fontweight':'bold'}) ax.set_ylabel('% increase in cost at year 5 (more costly -->)',{'fontweight':'bold'}) ax.axvline(color='r') #n_colours = ['#fb9902','#fd5308','#fe2712','#a7194b','#8601af','#3d01a4','#0247fe','#0392ce','#66b032'] n_colours = ['#000000','#e41a1c','#377eb8','#4daf4a','#984ea3','#ff7f00','#a65628','#f781bf','#999999'] colours = ['#CC0000','#EC6002','#CC9999','#FFFF99','#CCFF00','#02C5F4','#0188A9','#006699','#2E014B'] t_delta_y = 2 t_delta_x = 0.25 ax.text(0,0,'0') for i in xrange(8): ax.text(mdr[i]+t_delta_x,cmore[i]+t_delta_y,str(i+1)) delta = 0.00002 errorbars = [] errorbars.append(ax.plot([0],[0],color='black', marker='*')); for i in xrange(8): centre_color = n_colours[i+1] if which-2 == i: centre_color = 'black' errorbars.append(ax.errorbar([mdr[i]],[cmore[i]], xerr=[[mdr[i] - mdr_lo[i]],[mdr_hi[i] - mdr[i]]], yerr=[[cmore[i] - c_lo[i]],[c_hi[i] - cmore[i]]], color=centre_color, ecolor=centre_color, linewidth=2)) ax.axhline(color='r') ax.plot ([0],[0],marker='*',c='black',linestyle='None') if p_val['flag'] == 'E': for x in range(8): ax.plot([e2m[x]],[e2c[x]],marker='o',c=n_colours[x+1],linestyle='None') elif p_val['flag'] == 'P': for x in range(8): ax.plot([p2m[x]],[p2c[x]],marker='o',c=n_colours[x+1],linestyle='None') elif p_val['flag'] == 'R': for x in range(8): ax.plot([r2m[x]],[r2c[x]],marker='o',c=n_colours[x+1],linestyle='None') ax.set_title("Change (%) in cost and MDR incidence at year 5",{'fontweight':'bold'}) box = ax.get_position() ax.set_position([box.x0, box.y0-0.05, box.width, box.height+0.05]) #ax.legend(errorbars,range(1,9),numpoints=1,bbox_to_anchor=(0.98,-0.08),ncol=9,columnspacing=1) fig.tight_layout() ax.legend ((errorbars[0][0],errorbars[1][0],errorbars[2][0],errorbars[3][0],errorbars[4][0],errorbars[5][0],errorbars[6][0],errorbars[7][0],errorbars[8][0]), (strat_names[0], strat_names[1], strat_names[2], strat_names[3], strat_names[4], strat_names[5], strat_names[6], strat_names[7], strat_names[8]), loc='best', numpoints=1,prop={'size':'9'}) response=HttpResponse(content_type='image/png') canvas.print_png(response,facecolor=fig.get_facecolor()) return response
def dgraph2(request): p_val = request.GET try: cmore = [float(p_val['c{}'.format(x)]) for x in range(9)] mdr = [float(p_val['m{}'.format(x)]) for x in range(9)] except: return render(request,"bad.html",{ 'type':'dot graph 2' }) which = -1 try: which = int(p_val['ref']) except: pass s8name = strat_names[8] try: s8name = p_val['s8name'] except: pass fig = Figure(facecolor='white', dpi=150) canvas = FigureCanvas(fig) ax2 = fig.add_subplot(111) ax2.set_xlabel('% decrease in MDR-TB incidence at year 5 (more effective -->)',{'fontweight':'bold'}) ax2.set_ylabel('% increase in cost at year 5 (more costly -->)',{'fontweight':'bold'}) points = [ ax2.plot(mdr[i],cmore[i],color='blue',marker='.',linestyle='None') for i in xrange(9) ] ax2.set_title("Change (%) in cost and MDR incidence at year 5",{'fontweight':'bold'}) ax2.axhline(color='r') ax2.axvline(color='r') ax2.plot ([0],[0],marker='*',c='black',linestyle='None') point_list = [] for i in xrange(9): dx,dy = placement(mdr[i],cmore[i],point_list,ax2) point_list.append([mdr[i],cmore[i],dx,dy]) ref_color = '#000000' if i == which: ref_color = 'red' ax2.annotate(str(i), xy=(mdr[i],cmore[i]), xytext=(mdr[i]+dx,cmore[i]+dy), color=ref_color, arrowprops=dict(color='red',arrowstyle="->")) fig.tight_layout() ax2.legend ((points[0][0],points[1][0],points[2][0],points[3][0],points[4][0],points[5][0],points[6][0],points[7][0],points[8][0]), (strat_names[0], strat_names[1], strat_names[2], strat_names[3], strat_names[4], strat_names[5], strat_names[6], strat_names[7], "8. {}".format(s8name)), loc='best', numpoints=1,prop={'size':'9'}) response=HttpResponse(content_type='image/png') canvas.print_png(response,facecolor=fig.get_facecolor()) return response
def graph(sensor_id): # TODO: Add date filtering options sensor_config = current_app.config["SENSOR_CONFIG"] data_dir = current_app.config["DATA_DIR"] logfile = util.get_logfile_path(data_dir, sensor_id) if sensor_id not in util.get_sensor_list(sensor_config): abort(500, "Sensor ID is not in the sensor list.") if not os.path.isfile(logfile): abort(500, "No data exists for the sensor.") json_data = util.get_json(util.get_logfile_path(data_dir, sensor_id)) args = request.args if "field" in args: field = args["field"] else: return abort(400, "Field not specified.") if len(json_data) > 0: valid_fields = [field for field in json_data[next(iter(json_data))]["data"] if field != "id"] if field not in valid_fields: return abort(500, "Invalid field.") filter_dates = False if "hours" in request.args: filter_dates = True hours_back = int(request.args["hours"]) test_dates = [util.get_local_datetime(date) for date in json_data.keys()] test_dates.sort() latest_date = test_dates[-1] dates = [] values = [] for date_str, all_info in json_data.items(): if not filter_dates or (latest_date - util.get_local_datetime(date_str)).total_seconds() / 3600 < hours_back: if field in all_info["data"]: dates.append(util.get_local_datetime(date_str)) values.append(all_info["data"][field]) else: print("Warning: data line did not contain {}!".format(field)) # The key to using matplotlib with flask: don't use pyplot! # https://matplotlib.org/3.1.1/faq/howto_faq.html fig = Figure(figsize=(13, 3)) ax = fig.subplots() ax.plot(dates, values, util.plot_formats[field], markersize=3) ax.set_title("{} vs. Time".format(util.data_units[field][0]), fontname="Roboto", fontweight="light") #ax.set_xlabel("Time", fontname="Roboto") ax.set_ylabel("{} ({})".format(*[val for i, val in enumerate(util.data_units[field]) if i != 1]), fontname="Roboto", fontweight="light") for tick in ax.get_xticklabels(): tick.set_fontname("Roboto") tick.set_fontweight("light") for tick in ax.get_yticklabels(): tick.set_fontname("Roboto") tick.set_fontweight("light") ax.grid() ax.margins(x=0.01, y=0.15) # Margins are percentages fig.tight_layout() bg_color = "#ededed00" fig.patch.set_facecolor(bg_color) ax.patch.set_facecolor(bg_color) img_io = BytesIO() fig.savefig(img_io, format='png', facecolor=fig.get_facecolor()) img_io.seek(0) response = make_response(img_io.getvalue()) response.headers['Content-Type'] = 'image/png' # Disable caching response.headers['Last-Modified'] = datetime.datetime.now() response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0, max-age=0' response.headers['Pragma'] = 'no-cache' response.headers['Expires'] = '-1' return response
def bargraph(request): p = request.GET try: d = [(float(p['d10']), float(p['d11']), float(p['d12']), float(p['d13']), float(p['d14'])), (float(p['d20']), float(p['d21']), float(p['d22']), float(p['d23']), float(p['d24'])), (float(p['d30']), float(p['d31']), float(p['d32']), float(p['d33']), float(p['d34'])), (float(p['d40']), float(p['d41']), float(p['d42']), float(p['d43']), float(p['d44'])), (float(p['d50']), float(p['d51']), float(p['d52']), float(p['d53']), float(p['d54'])), (float(p['d60']), float(p['d61']), float(p['d62']), float(p['d63']), float(p['d64'])), (float(p['d70']), float(p['d71']), float(p['d72']), float(p['d73']), float(p['d74'])), (float(p['d80']), float(p['d81']), float(p['d82']), float(p['d83']), float(p['d84']))] except: return render(request, "bad.html", {'type': 'bargraph'}) tickM = [ "2. Culture for retreatment", "3. GeneXpert for HIV positive only", "4. GeneXpert for smear positive only", "5. GeneXpert for all", "6. GeneXpert for all, culture confirmed", "7. MODS/TLA", "8. Same-day smear microscopy", "9. Same-day GeneXpert" ] colors = ["grey", "blue", "green", "yellow", "red"] ndata = zip(*d) loc = np.arange(len(ndata[0])) width = 0.15 fig = Figure(facecolor='white') canvas = FigureCanvas(fig) ax = fig.add_subplot(111) rect = [ ax.bar(loc + width * i, ndata[i], width, color=colors[i]) for i in range(len(ndata)) ] ax.set_ylim(-50, 100) ax.set_xlim(-width * 4, len(loc) + (4 * width)) ax.set_xticks(loc + (2.5 * width)) ax.set_xticklabels(tickM, rotation='30', size='small', stretch='condensed', ha='right') ax.legend((rect[0][0], rect[1][0], rect[2][0], rect[3][0], rect[4][0]), ("TBInc", "MDRInc", "TBMort", "Yr1Cost", "Yr5Cost"), loc='best') ax.set_title("Graph Comparison") ax.axhline(color='black') ax.set_ylabel('percentage change from baseline') fig.tight_layout() response = HttpResponse(content_type='image/png') canvas.print_png(response, facecolor=fig.get_facecolor()) return response
class PlotWidget(custom_result.ResultWidget): __gsignals__ = { 'button-press-event': 'override', 'button-release-event': 'override', 'expose-event': 'override', 'size-allocate': 'override', 'unrealize': 'override' } def __init__(self, result): custom_result.ResultWidget.__init__(self) figsize = (DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_HEIGHT) self.figure = Figure(facecolor='white', figsize=figsize) self.canvas = _PlotResultCanvas(self.figure) self.axes = self.figure.add_subplot(111) self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE) self.cached_contents = None self.sidebar_width = -1 def do_expose_event(self, event): cr = self.window.cairo_create() if not self.cached_contents: self.cached_contents = cr.get_target().create_similar( cairo.CONTENT_COLOR, self.allocation.width, self.allocation.height) renderer = RendererCairo(self.figure.dpi) renderer.set_width_height(self.allocation.width, self.allocation.height) renderer.set_ctx_from_surface(self.cached_contents) self.figure.draw(renderer) # event.region is not bound: http://bugzilla.gnome.org/show_bug.cgi?id=487158 # gdk_context = gtk.gdk.CairoContext(renderer.ctx) # gdk_context.region(event.region) # gdk_context.clip() cr.set_source_surface(self.cached_contents, 0, 0) cr.paint() def do_size_allocate(self, allocation): if allocation.width != self.allocation.width or allocation.height != self.allocation.height: self.cached_contents = None gtk.DrawingArea.do_size_allocate(self, allocation) def do_unrealize(self): gtk.DrawingArea.do_unrealize(self) self.cached_contents = None def do_button_press_event(self, event): if event.button == 3: custom_result.show_menu(self, event, save_callback=self.__save) return True else: return True def do_button_release_event(self, event): return True def do_realize(self): gtk.DrawingArea.do_realize(self) cursor = gtk.gdk.Cursor(gtk.gdk.LEFT_PTR) self.window.set_cursor(cursor) def do_size_request(self, requisition): try: # matplotlib < 0.98 requisition.width = self.figure.bbox.width() requisition.height = self.figure.bbox.height() except TypeError: # matplotlib >= 0.98 requisition.width = self.figure.bbox.width requisition.height = self.figure.bbox.height def recompute_figure_size(self): width = (self.sidebar_width / self.figure.dpi) height = width / DEFAULT_ASPECT_RATIO self.figure.set_figwidth(width) self.figure.set_figheight(height) self.queue_resize() def sync_dpi(self, dpi): self.figure.set_dpi(dpi) if self.sidebar_width >= 0: self.recompute_figure_size() def set_sidebar_width(self, width): if self.sidebar_width == width: return self.sidebar_width = width if self.sidebar_width >= 0: self.recompute_figure_size() def sync_style(self, style): self.cached_contents = None matplotlib.rcParams[ 'font.size'] = self.parent.style.font_desc.get_size() / pango.SCALE def __save(self, filename): # The save/restore here was added to matplotlib's after 0.90. We duplicate # it for compatibility with older versions. (The code would need modification # for 0.98 and newer, which is the reason for the particular version in the # check) version = [int(x) for x in matplotlib.__version__.split('.')] need_save = version[:2] < [0, 98] if need_save: orig_dpi = self.figure.dpi.get() orig_facecolor = self.figure.get_facecolor() orig_edgecolor = self.figure.get_edgecolor() try: self.canvas.print_figure(filename) finally: if need_save: self.figure.dpi.set(orig_dpi) self.figure.set_facecolor(orig_facecolor) self.figure.set_edgecolor(orig_edgecolor) self.figure.set_canvas(self.canvas)
class PlotWidget(custom_result.ResultWidget): __gsignals__ = { 'button-press-event': 'override', 'button-release-event': 'override', 'expose-event': 'override', 'size-allocate': 'override', 'unrealize': 'override' } def __init__(self, result): custom_result.ResultWidget.__init__(self) figsize=(DEFAULT_FIGURE_WIDTH, DEFAULT_FIGURE_HEIGHT) self.figure = Figure(facecolor='white', figsize=figsize) self.canvas = _PlotResultCanvas(self.figure) self.axes = self.figure.add_subplot(111) self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE) self.cached_contents = None self.sidebar_width = -1 def do_expose_event(self, event): cr = self.window.cairo_create() if not self.cached_contents: self.cached_contents = cr.get_target().create_similar(cairo.CONTENT_COLOR, self.allocation.width, self.allocation.height) renderer = RendererCairo(self.figure.dpi) renderer.set_width_height(self.allocation.width, self.allocation.height) renderer.set_ctx_from_surface(self.cached_contents) self.figure.draw(renderer) # event.region is not bound: http://bugzilla.gnome.org/show_bug.cgi?id=487158 # gdk_context = gtk.gdk.CairoContext(renderer.ctx) # gdk_context.region(event.region) # gdk_context.clip() cr.set_source_surface(self.cached_contents, 0, 0) cr.paint() def do_size_allocate(self, allocation): if allocation.width != self.allocation.width or allocation.height != self.allocation.height: self.cached_contents = None gtk.DrawingArea.do_size_allocate(self, allocation) def do_unrealize(self): gtk.DrawingArea.do_unrealize(self) self.cached_contents = None def do_button_press_event(self, event): if event.button == 3: custom_result.show_menu(self, event, save_callback=self.__save) return True else: return True def do_button_release_event(self, event): return True def do_realize(self): gtk.DrawingArea.do_realize(self) cursor = gtk.gdk.Cursor(gtk.gdk.LEFT_PTR) self.window.set_cursor(cursor) def do_size_request(self, requisition): try: # matplotlib < 0.98 requisition.width = self.figure.bbox.width() requisition.height = self.figure.bbox.height() except TypeError: # matplotlib >= 0.98 requisition.width = self.figure.bbox.width requisition.height = self.figure.bbox.height def recompute_figure_size(self): width = (self.sidebar_width / self.figure.dpi) height = width / DEFAULT_ASPECT_RATIO self.figure.set_figwidth(width) self.figure.set_figheight(height) self.queue_resize() def sync_dpi(self, dpi): self.figure.set_dpi(dpi) if self.sidebar_width >= 0: self.recompute_figure_size() def set_sidebar_width(self, width): if self.sidebar_width == width: return self.sidebar_width = width if self.sidebar_width >= 0: self.recompute_figure_size() def sync_style(self, style): self.cached_contents = None matplotlib.rcParams['font.size'] = self.parent.style.font_desc.get_size() / pango.SCALE def __save(self, filename): # The save/restore here was added to matplotlib's after 0.90. We duplicate # it for compatibility with older versions. (The code would need modification # for 0.98 and newer, which is the reason for the particular version in the # check) version = [int(x) for x in matplotlib.__version__.split('.')] need_save = version[:2] < [0, 98] if need_save: orig_dpi = self.figure.dpi.get() orig_facecolor = self.figure.get_facecolor() orig_edgecolor = self.figure.get_edgecolor() try: self.canvas.print_figure(filename) finally: if need_save: self.figure.dpi.set(orig_dpi) self.figure.set_facecolor(orig_facecolor) self.figure.set_edgecolor(orig_edgecolor) self.figure.set_canvas(self.canvas)
class VOAAreaPlot: IMG_TYPE_DICT = { \ 1:{'plot_type':'MUF', 'title':_('Maximum Usable Frequency (MUF)'), 'min':2, 'max':30, 'y_labels':(2, 5, 10, 15, 20, 25, 30), 'formatter':'frequency_format', 'first_char':27, 'last_char':32}, \ 2:{'plot_type':'REL', 'title':_('Circuit Reliability (%)'), 'min':0, 'max':1, 'y_labels':(0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1), 'formatter':'percent_format', 'first_char':98, 'last_char':104}, \ 3:{'plot_type':'SNR', 'title':_('SNR at Receiver (dB)'), 'min':20, 'max':70, 'y_labels':(20, 30, 40, 50, 60, 70), 'formatter':'SNR_format', 'first_char':86, 'last_char':92}, \ 4:{'plot_type':'SNRXX', 'title':_('SNRxx'), 'min':0, 'max':100, 'y_labels':(0, 20, 40, 60, 80, 100), 'formatter':'SNR_format', 'first_char':130, 'last_char':134}, \ 5:{'plot_type':'SDBW', 'title':_('Signal Power'), 'min':-160, 'max':-40, 'y_labels':(-160, -140, -120, -100, -80, -60, -40), 'formatter':'SDBW_format', 'first_char':74, 'last_char':80}, \ 6:{'plot_type':'SMETESNRXXR', 'title':_('S-Meter'), 'min':-151.18, 'max':-43.01, 'y_labels':(-151.18, -139.13, -127.09, -115.05, -103.01, -83.01, -63.01, -43.01), 'formatter':'SMETER_format', 'first_char':74, 'last_char':80} } COLOUR_MAPS = [ _('autumn'), _('bone'), _('cool'), _('copper'), _('gray'), \ _('hot'), _('hsv'), _('jet'), _('pink'), _('spring'), \ _('summer'), _('winter') ] default_font = {'family' : 'sans-serif'} show_subplot_frame = True def __init__(self, in_file, vg_files = [1], data_type = 1, projection = 'cyl', color_map = 'jet', face_colour = "white", time_zone = 0, filled_contours = False, plot_contours = False, plot_center = 't', plot_meridians = True, plot_parallels = True, plot_nightshade = True, resolution = 'c', points_of_interest = [], save_file = '', run_quietly = False, dpi = 150, parent = None, datadir=None): self.run_quietly = run_quietly self.dpi=float(dpi) self.datadir = datadir try: plot_parameters = VOAFile((in_file)) plot_parameters.parse_file() except zipfile.BadZipFile as e: if parent is None: print("Invalid .vgz file") sys.exit(1) if (plot_parameters.get_projection() != 'cyl'): print(_("Error: Only lat/lon (type 1) input files are supported")) sys.exit(1) grid = plot_parameters.get_gridsize() self.image_defs = VOAAreaPlot.IMG_TYPE_DICT[int(data_type)] # TODO This needs a little more work... what if the pcenter card is not specified if plot_center == 'p': plot_centre_location = plot_parameters.get_location(plot_parameters.P_CENTRE) else: plot_centre_location = plot_parameters.get_location(plot_parameters.TX_SITE) self.points_of_interest = [plot_centre_location] if len(points_of_interest) > 0: self.points_of_interest.extend(points_of_interest) imageBuf = np.zeros([grid, grid], float) area_rect = plot_parameters.get_area_rect() # The checks ought to be performed in the area_rect. # Do a few basic sanity checks # #if ( (area_rect.get_sw_lon() < -180) or (area_rect.get_ne_lon() > 180.0) or (area_rect.get_sw_lat() < -90) or (area_rect.get_ne_lat() > 90.0) ): # print "Input file latitudes/longitudes are out of range" # print "-180 < Latitude < 180.0, -90 < Longitude < 90" # sys.exit(1) #if ( (area_rect.get_sw_lon() == area_rect.get_ne_lon()) or (area_rect.get_sw_lat() == area_rect.get_ne_lat()) ): # print "Input file latitudes/longitudes are the same" # print "-180 < Latitude < 180.0, -90 < Longitude < 90" # sys.exit(1) colString = 'matplotlib.cm.'+color_map colMap = eval(colString) self.subplots = [] self.number_of_subplots = len(vg_files) matplotlib.rcParams['axes.edgecolor'] = 'gray' matplotlib.rcParams['axes.facecolor'] = 'white' matplotlib.rcParams['figure.facecolor'] = face_colour #matplotlib.rcParams['figure.figsize'] = (6, 10) matplotlib.rcParams['figure.subplot.hspace'] = 0.45 matplotlib.rcParams['figure.subplot.wspace'] = 0.35 matplotlib.rcParams['figure.subplot.right'] = 0.85 colorbar_fontsize = 12 if self.number_of_subplots <= 1: self.num_rows = 1 self.main_title_fontsize = 24 matplotlib.rcParams['legend.fontsize'] = 12 matplotlib.rcParams['axes.labelsize'] = 12 matplotlib.rcParams['axes.titlesize'] = 10 matplotlib.rcParams['xtick.labelsize'] = 10 matplotlib.rcParams['ytick.labelsize'] = 10 matplotlib.rcParams['figure.subplot.top'] = 0.8 # single figure plots have a larger title so require more space at the top. elif ((self.number_of_subplots >= 2) and (self.number_of_subplots <= 6 )): self.num_rows = 2 self.main_title_fontsize = 18 matplotlib.rcParams['legend.fontsize'] = 10 matplotlib.rcParams['axes.labelsize'] = 10 matplotlib.rcParams['axes.titlesize'] = 11 matplotlib.rcParams['xtick.labelsize'] = 8 matplotlib.rcParams['ytick.labelsize'] = 8 #self.x_axes_ticks = P.arange(0,25,4) else: self.num_rows = 3 self.main_title_fontsize = 16 matplotlib.rcParams['legend.fontsize'] = 8 matplotlib.rcParams['axes.labelsize'] = 8 matplotlib.rcParams['axes.titlesize'] = 10 matplotlib.rcParams['xtick.labelsize'] = 6 matplotlib.rcParams['ytick.labelsize'] = 6 #self.x_axes_ticks = P.arange(0,25,4) self.num_cols = int(math.ceil(float(self.number_of_subplots)/float(self.num_rows))) self.fig=Figure() self.main_title_label = self.fig.suptitle(str(self.image_defs['title']), fontsize=self.main_title_fontsize) if projection == 'ortho': self.show_subplot_frame = False for plot_ctr, vg_file in enumerate(vg_files): points = np.zeros([grid,grid], float) lons = np.arange(area_rect.get_sw_lon(), area_rect.get_ne_lon()+0.001,(area_rect.get_ne_lon()-area_rect.get_sw_lon())/float(grid-1)) lons[-1] = min(180.0, lons[-1]) lats = np.arange(area_rect.get_sw_lat(), area_rect.get_ne_lat()+0.001,(area_rect.get_ne_lat()-area_rect.get_sw_lat())/float(grid-1)) lats[-1] = min(90.0, lats[-1]) ax = self.fig.add_subplot(self.num_rows, self.num_cols, plot_ctr+1, frame_on = self.show_subplot_frame, axisbg = 'white') self.subplots.append(ax) ax.label_outer() if in_file.endswith('.vgz'): base_filename = get_base_filename(in_file) zf = zipfile.ZipFile(in_file) vgFile = io.TextIOWrapper(zf.open("{:s}.vg{:d}".format(base_filename, vg_file)), 'utf-8') else: vgFile = open("{:s}.vg{:d}".format(os.path.splitext(in_file)[0], vg_file)) pattern = re.compile(r"[a-z]+") for line in vgFile: match = pattern.search( line ) if not match: value = float(line[int(self.image_defs['first_char']):int(self.image_defs['last_char'])]) # TODO Does this need to be normalised here if it's also being done in the plot? value = max(self.image_defs['min'], value) value = min(self.image_defs['max'], value) points[int(line[3:6])-1][int(line[0:3])-1] = value vgFile.close() if 'zf' in locals(): zf.close() m_args={} if projection in ('cyl', 'mill', 'gall'): m_args.update({"llcrnrlon":area_rect.get_sw_lon(), "llcrnrlat":area_rect.get_sw_lat(), "urcrnrlon":area_rect.get_ne_lon(), "urcrnrlat":area_rect.get_ne_lat()}) if projection in ('robin', 'vandg', 'sinu', 'mbtfpq', 'eck4', 'kav7', 'moll', 'hammer', 'gnom', 'laea', 'aeqd', 'cea', 'merc'): m_args.update({"lat_0":plot_centre_location.get_latitude(), "lon_0":plot_centre_location.get_longitude()}) if projection in ('cea', 'merc'): m_args['lat_ts']=0 m = Basemap(ax=ax, projection=projection, resolution=resolution, **m_args) m.drawcoastlines(color='black') m.drawcountries(color='grey') m.drawmapboundary(color='black', linewidth=1.0) #points = np.clip(points, self.image_defs['min'], self.image_defs['max']) #colMap.set_under(color ='k', alpha=0.0) lons, lats = np.meshgrid(lons, lats) points = np.clip(points, self.image_defs['min'], self.image_defs['max']) if (filled_contours): im = m.contourf(lons, lats, points, self.image_defs['y_labels'], latlon=True, cmap = colMap) plot_contours = True else: im = m.pcolormesh(lons, lats, points, latlon=True, vmin = self.image_defs['min'], vmax = self.image_defs['max'], cmap = colMap, shading='gouraud') if plot_contours: ct = m.contour(lons, lats, points, self.image_defs['y_labels'][1:], latlon=True, linestyles='solid', linewidths=0.5, colors='k', vmin=self.image_defs['min'], vmax=self.image_defs['max'] ) ####################### # Plot greyline ####################### if plot_nightshade: m.nightshade(plot_parameters.get_daynight_datetime(vg_files[plot_ctr]-1)) ########################## # Points of interest ########################## for location in self.points_of_interest: if area_rect.contains(location.get_latitude(), location.get_longitude()): xpt,ypt = m(location.get_longitude(),location.get_latitude()) ax.plot([xpt],[ypt],'ro') ax.text(xpt+100000,ypt+100000,location.get_name()) if plot_meridians: if (area_rect.get_lon_delta() <= 90.0): meridians = np.arange(-180, 190.0, 10.0) elif (area_rect.get_lon_delta() <= 180.0): meridians = np.arange(-180.0, 210.0, 30.0) else: meridians = np.arange(-180, 240.0, 60.0) if ((projection == 'ortho') or (projection == 'vandg')): m.drawmeridians(meridians) else: m.drawmeridians(meridians,labels=[1,1,0,1]) if plot_parallels: if (area_rect.get_lat_delta() <= 90.0): parallels = np.arange(-90.0, 120.0, 60.0) else: parallels = np.arange(-90.0, 120.0, 30.0) if ((projection == 'ortho') or (projection == 'vandg')): m.drawparallels(parallels) else: m.drawparallels(parallels,labels=[1,1,0,1]) #add a title title_str = plot_parameters.get_plot_description_string(vg_files[plot_ctr]-1, self.image_defs['plot_type'], time_zone) if self.number_of_subplots == 1: title_str = plot_parameters.get_plot_description_string(vg_files[plot_ctr]-1, self.image_defs['plot_type'], time_zone) title_str = title_str + "\n" + plot_parameters.get_detailed_plot_description_string(vg_files[plot_ctr]-1) else : title_str = plot_parameters.get_minimal_plot_description_string(vg_files[plot_ctr]-1, self.image_defs['plot_type'], time_zone) self.subplot_title_label = ax.set_title(title_str) # Add a colorbar on the right hand side, aligned with the # top of the uppermost plot and the bottom of the lowest # plot. # create an axes on the right side of ax. The width of cax will be 5% # of ax and the padding between cax and ax will be fixed at 0.05 inch. if self.number_of_subplots > 1: self.cb_ax = self.fig.add_axes(self.get_cb_axes()) else: divider = make_axes_locatable(ax) self.cb_ax = divider.append_axes("right", size="5%", pad=0.05) self.fig.colorbar(im, cax=self.cb_ax, orientation='vertical', ticks=self.image_defs['y_labels'], format = FuncFormatter(eval('self.'+self.image_defs['formatter']))) #print self.image_defs['y_labels'] for t in self.cb_ax.get_yticklabels(): t.set_fontsize(colorbar_fontsize) #self.fig.tight_layout() canvas = FigureCanvas(self.fig) self.fig.canvas.mpl_connect('draw_event', self.on_draw) canvas.show() if save_file : self.save_plot(canvas, save_file) #todo this ought to a command line param if not self.run_quietly: dia = VOAPlotWindow('pythonProp - ' + self.image_defs['title'], canvas, parent=parent, datadir=self.datadir) return def on_draw(self, event): top = self.fig.subplotpars.top bottom = self.fig.subplotpars.bottom hspace = self.fig.subplotpars.hspace wspace = self.fig.subplotpars.wspace fig_height = self.fig.get_figheight() needs_adjusting = False # Area required at the top of the plot (Main title and subplot title) bbox = self.subplot_title_label.get_window_extent() subplot_title_bbox = bbox.inverse_transformed(self.fig.transFigure) bbox = self.main_title_label.get_window_extent() main_title_bbox = bbox.inverse_transformed(self.fig.transFigure) _preferred_top_space = 1.25*(subplot_title_bbox.height + main_title_bbox.height) _actual_top_space = 1-top if (_actual_top_space < _preferred_top_space) or ((_actual_top_space - _preferred_top_space)>0.11): top = 0.99 - _preferred_top_space needs_adjusting = True if needs_adjusting: self.fig.subplots_adjust(top = top, bottom = bottom, hspace = hspace, wspace = wspace) self.cb_ax.set_position(self.get_cb_axes()) self.fig.canvas.draw() return False def save_plot(self, canvas, filename=None): canvas.print_figure(filename, dpi=self.dpi, facecolor=self.fig.get_facecolor(), edgecolor='none') def get_cb_axes(self): bbox = self.subplots[0].get_window_extent() axis_upper_y = bbox.inverse_transformed(self.fig.transFigure).ymax bbox = self.subplots[-1].get_window_extent() axis_lower_y = bbox.inverse_transformed(self.fig.transFigure).ymin return [0.87, axis_lower_y, 0.02, axis_upper_y-axis_lower_y] def percent_format(self, x, pos): return '%(percent)3d%%' % {'percent':x*100} def SNR_format(self, x, pos): return '%3ddB' % x def SDBW_format(self, x, pos): return '%3ddBW' % x """ The values below are derived from material presented at http://www.voacap.com/s-meter.html """ def SMETER_format(self, x, pos): S_DICT = {-151.18:'S1', -145.15:'S2', -139.13:'S3', -133.11:'S4', -127.09:'S5', \ -121.07:'S6', -115.05:'S7', -109.03:'S8', -103.01:'S9', -93.01:'S9+10dB', \ -83.01:'S9+20dB', -73.01:'S9+30dB', -63.01:'S9+40dB', -53.01:'S9+50dB', -43.01:'S9+60dB'} if x in S_DICT: return '%s' % S_DICT[x] #return _('%(value)ddBW (%(s_value)s)') %{'value':x, 's_value':S_DICT[x]} else : return '%3d' % x def frequency_format(self, x, pos): return '%2dMHz' % x def default_format(self, x, pos): return '%d' % x
class MatPlotLibBase(QWidget): def __init__(self, parent, file_dialog_service, h_margin=(0.8, 0.1), v_margin=(0.5, 0.15), h_axes=[Size.Scaled(1.0)], v_axes=[Size.Scaled(1.0)], nx_default=1, ny_default=1): QWidget.__init__(self, parent) self._file_dialog_service = file_dialog_service self._figure = Figure() self._canvas = FigureCanvas(self._figure) h = [Size.Fixed(h_margin[0]), *h_axes, Size.Fixed(h_margin[1])] v = [Size.Fixed(v_margin[0]), *v_axes, Size.Fixed(v_margin[1])] self._divider = Divider(self._figure, (0.0, 0.0, 1.0, 1.0), h, v, aspect=False) self._axes = LocatableAxes(self._figure, self._divider.get_position()) self._axes.set_axes_locator( self._divider.new_locator(nx=nx_default, ny=ny_default)) self._axes.set_zorder(2) self._axes.patch.set_visible(False) for spine in ['top', 'right']: self._axes.spines[spine].set_visible(False) self._figure.add_axes(self._axes) self._canvas.setParent(self) self._layout = QVBoxLayout(self) self._layout.setContentsMargins(0, 0, 0, 0) self._layout.addWidget(self._canvas) self.setLayout(self._layout) self._figure.canvas.mpl_connect('scroll_event', self._on_scroll) self._xy_extents = None self._background_cache = None self._decoration_artists = [] self._is_panning = False self._zoom_selector = _RectangleSelector(self._axes, self._zoom_selected) self._zoom_selector.set_active(False) self._x_extent_padding = 0.01 self._y_extent_padding = 0.01 self._axes.ticklabel_format(style='sci', axis='x', scilimits=(-4, 4)) self._axes.ticklabel_format(style='sci', axis='y', scilimits=(-4, 4)) self._active_tools = {} self._span = _SpanSeletor(self._axes, self._handle_span_select, 'horizontal', rectprops=dict(alpha=0.2, facecolor='red', edgecolor='k'), span_stays=True) self._span.set_on_select_none(self._handle_span_select_none) self.span = self._previous_span = None self._span_center_mouse_event = None self._span_left_mouse_event = None self._span_right_mouse_event = None self._figure.canvas.mpl_connect('button_press_event', self._handle_press) self._figure.canvas.mpl_connect('motion_notify_event', self._handle_move) self._figure.canvas.mpl_connect('button_release_event', self._handle_release) self._figure.canvas.mpl_connect('resize_event', self._handle_resize) self.activateTool(ToolType.span, self.isActiveDefault(ToolType.span)) self._pan_event = None self._pending_draw = None self._pending_artists_draw = None self._other_draw_events = [] self._draw_timer = QTimer(self) self._draw_timer.timeout.connect(self._do_draw_events) self._draw_timer.start(20) self._zoom_skew = None self._menu = QMenu(self) self._copy_image_action = QAction(self.tr('Copy To Clipboard'), self) self._copy_image_action.triggered.connect(self.copyToClipboard) self._copy_image_action.setShortcuts(QKeySequence.Copy) self._save_image_action = QAction(self.tr('Save As Image'), self) self._save_image_action.triggered.connect(self.saveAsImage) self._show_table_action = QAction(self.tr('Show Table'), self) self._show_table_action.triggered.connect(self.showTable) self._menu.addAction(self._copy_image_action) self._menu.addAction(self._save_image_action) self._menu.addAction(self._show_table_action) self.addAction(self._copy_image_action) self._table_view = None self._single_axis_zoom_enabled = True self._cached_label_width_height = None if hasattr(type(self), 'dataChanged'): self.dataChanged.connect(self._on_data_changed) self._options_view = None self._secondary_axes = self._secondary_y_extent = self._secondary_x_extent = None self._legend = None self._draggable_legend = None self._setting_axis_limits = False self.hasHiddenSeries = False enabledToolsChanged = pyqtSignal() spanChanged = pyqtSignal(SpanModel) hasHiddenSeriesChanged = pyqtSignal(bool) span = AutoProperty(SpanModel) hasHiddenSeries = AutoProperty(bool) def setOptionsView(self, options_view): self._options_view = options_view self._options_view.setSecondaryYLimitsEnabled( self._secondary_y_enabled()) self._options_view.setSecondaryXLimitsEnabled( self._secondary_x_enabled()) self._options_view.showGridLinesChanged.connect( self._update_grid_lines) self._options_view.xAxisLowerLimitChanged.connect( self._handle_options_view_limit_changed(x_min_changed=True)) self._options_view.xAxisUpperLimitChanged.connect( self._handle_options_view_limit_changed(x_max_changed=True)) self._options_view.yAxisLowerLimitChanged.connect( self._handle_options_view_limit_changed(y_min_changed=True)) self._options_view.yAxisUpperLimitChanged.connect( self._handle_options_view_limit_changed(y_max_changed=True)) self._options_view.xAxisLimitsChanged.connect( self._handle_options_view_limit_changed(x_min_changed=True, x_max_changed=True)) self._options_view.yAxisLimitsChanged.connect( self._handle_options_view_limit_changed(y_min_changed=True, y_max_changed=True)) self._options_view.secondaryXAxisLowerLimitChanged.connect( self._handle_options_view_secondary_limit_changed( x_min_changed=True)) self._options_view.secondaryXAxisUpperLimitChanged.connect( self._handle_options_view_secondary_limit_changed( x_max_changed=True)) self._options_view.secondaryYAxisLowerLimitChanged.connect( self._handle_options_view_secondary_limit_changed( y_min_changed=True)) self._options_view.secondaryYAxisUpperLimitChanged.connect( self._handle_options_view_secondary_limit_changed( y_max_changed=True)) self._options_view.secondaryXAxisLimitsChanged.connect( self._handle_options_view_secondary_limit_changed( x_min_changed=True, x_max_changed=True)) self._options_view.secondaryYAxisLimitsChanged.connect( self._handle_options_view_secondary_limit_changed( y_min_changed=True, y_max_changed=True)) def setLegendControl(self, legend_control): self._legend_control = legend_control self._legend_control.seriesUpdated.connect(self._legend_series_updated) self._legend_control.showLegendChanged.connect(self._show_legend) self._legend_control.seriesNameChanged.connect( self._handle_series_name_changed) self._legend_control.showSeriesChanged.connect( self._handle_show_series_changed) bind(self._legend_control, self, 'hasHiddenSeries', two_way=False) def _legend_series_updated(self): if self._legend is not None: self._show_legend(self._legend_control.showLegend) def _show_legend(self, show): if self._legend and not show: self._legend.remove() self._legend = None self.draw() elif show: if self._legend: self._legend.remove() show_series = self._legend_control.showSeries handles = [ h for h, s in zip(self._legend_control.seriesHandles, show_series) if s ] names = [ n for n, s in zip(self._legend_control.seriesNames, show_series) if s ] axes = (self._secondary_axes if self._secondary_axes and self._secondary_axes.get_visible() and self._secondary_axes.get_zorder() > self._axes.get_zorder() else self._axes) self._legend = self._create_legend( axes, handles, names, markerscale=self._get_legend_markerscale()) if self._get_legend_text_color() is not None: for text in self._legend.texts: text.set_color(self._get_legend_text_color()) self._draggable_legend = DraggableLegend(self._legend) self.draw() def _get_legend_markerscale(self): return 5 def _create_legend(self, axes, handles, names, **kwargs): return axes.legend(handles, names, **kwargs) def _get_legend_text_color(self): return None def _handle_series_name_changed(self, index, series_name): if self._legend is not None and index < len( self._legend_control.seriesHandles): visible_handles = [ h for h, s in zip(self._legend_control.seriesHandles, self._legend_control.showSeries) if s and h is not None ] try: legend_index = visible_handles.index( self._legend_control.seriesHandles[index]) except ValueError: return if legend_index < len(self._legend.texts): self._legend.texts[legend_index].set_text(series_name) self.draw() def _handle_show_series_changed(self, index, show_series): if index < len(self._legend_control.seriesHandles): self._set_series_visibility( self._legend_control.seriesHandles[index], show_series) if self._legend is not None: self._show_legend(self._legend_control.showLegend) else: self.draw() def _set_series_visibility(self, handle, visible): if not handle: return if hasattr(handle, 'set_visible'): handle.set_visible(visible) elif hasattr(handle, 'get_children'): for child in handle.get_children(): self._set_series_visibility(child, visible) def _update_grid_lines(self): show_grid_lines = False if self._options_view is None else self._options_view.showGridLines gridline_color = self._axes.spines['bottom'].get_edgecolor() gridline_color = gridline_color[0], gridline_color[1], gridline_color[ 2], 0.5 kwargs = dict(color=gridline_color, alpha=0.5) if show_grid_lines else {} self._axes.grid(show_grid_lines, **kwargs) self.draw() def _handle_options_view_limit_changed(self, x_min_changed=False, x_max_changed=False, y_min_changed=False, y_max_changed=False): def _(): if self._options_view is None or self._setting_axis_limits: return (x_min, x_max), (y_min, y_max) = (new_x_min, new_x_max), ( new_y_min, new_y_max) = self._get_xy_extents() (x_opt_min, x_opt_max), (y_opt_min, y_opt_max) = self._get_options_view_xy_extents() if x_min_changed: new_x_min = x_opt_min if x_max_changed: new_x_max = x_opt_max if y_min_changed: new_y_min = y_opt_min if y_max_changed: new_y_max = y_opt_max if [new_x_min, new_x_max, new_y_min, new_y_max ] != [x_min, x_max, y_min, y_max]: self._xy_extents = (new_x_min, new_x_max), (new_y_min, new_y_max) self._set_axes_limits() self.draw() return _ def _get_options_view_xy_extents(self): (x_data_min, x_data_max), (y_data_min, y_data_max) = self._get_data_xy_extents() x_min = x_data_min if np.isnan( self._options_view.xAxisLowerLimit ) else self._options_view.xAxisLowerLimit x_max = x_data_max if np.isnan( self._options_view.xAxisUpperLimit ) else self._options_view.xAxisUpperLimit y_min = y_data_min if np.isnan( self._options_view.yAxisLowerLimit ) else self._options_view.yAxisLowerLimit y_max = y_data_max if np.isnan( self._options_view.yAxisUpperLimit ) else self._options_view.yAxisUpperLimit return (x_min, x_max), (y_min, y_max) def _handle_options_view_secondary_limit_changed(self, x_min_changed=False, x_max_changed=False, y_min_changed=False, y_max_changed=False): def _(): if self._options_view is None or self._setting_axis_limits: return updated = False (x_opt_min, x_opt_max), ( y_opt_min, y_opt_max) = self._get_options_view_secondary_xy_extents() if self._has_secondary_y_extent() and (y_min_changed or y_max_changed): y_min, y_max = new_y_min, new_y_max = self._get_secondary_y_extent( ) if y_min_changed: new_y_min = y_opt_min if y_max_changed: new_y_max = y_opt_max if [new_y_min, new_y_max] != [y_min, y_max]: self._secondary_y_extent = (new_y_min, new_y_max) updated = True if self._has_secondary_x_extent() and (x_min_changed or x_max_changed): x_min, x_max = new_x_min, new_x_max = self._get_secondary_x_extent( ) if x_min_changed: new_x_min = x_opt_min if x_max_changed: new_x_max = x_opt_max if [new_x_min, new_x_max] != [x_min, x_max]: self._secondary_x_extent = (new_x_min, new_x_max) updated = True if updated: self._set_axes_limits() self.draw() return _ def _get_options_view_secondary_xy_extents(self): x_data_min, x_data_max = self._get_data_secondary_x_extent() y_data_min, y_data_max = self._get_data_secondary_y_extent() x_min = x_data_min if np.isnan( self._options_view.secondaryXAxisLowerLimit ) else self._options_view.secondaryXAxisLowerLimit x_max = x_data_max if np.isnan( self._options_view.secondaryXAxisUpperLimit ) else self._options_view.secondaryXAxisUpperLimit y_min = y_data_min if np.isnan( self._options_view.secondaryYAxisLowerLimit ) else self._options_view.secondaryYAxisLowerLimit y_max = y_data_max if np.isnan( self._options_view.secondaryYAxisUpperLimit ) else self._options_view.secondaryYAxisUpperLimit return (x_min, x_max), (y_min, y_max) def _on_data_changed(self): self._cached_label_width_height = None def closeEvent(self, event): QWidget.closeEvent(self, event) if event.isAccepted(): self._zoom_selector.onselect = self._span.onselect = self._span._select_none_handler = None def set_divider_h_margin(self, h_margin): h = [ Size.Fixed(h_margin[0]), Size.Scaled(1.0), Size.Fixed(h_margin[1]) ] self._divider.set_horizontal(h) def set_divider_v_margin(self, v_margin): v = [ Size.Fixed(v_margin[0]), Size.Scaled(1.0), Size.Fixed(v_margin[1]) ] self._divider.set_vertical(v) @property def x_extent_padding(self): return self._x_extent_padding @x_extent_padding.setter def x_extent_padding(self, value): self._x_extent_padding = value @property def y_extent_padding(self): return self._y_extent_padding @y_extent_padding.setter def y_extent_padding(self, value): self._y_extent_padding = value def _in_interval(self, value, interval): return interval[0] <= value <= interval[1] def _interval_skew(self, value, interval): return (value - interval[0]) / (interval[1] - interval[0]) def _in_x_scroll_zone(self, event): return self._in_interval(event.x, self._axes.bbox.intervalx ) and event.y <= self._axes.bbox.intervaly[1] def _in_y_scroll_zone(self, event): return self._in_interval(event.y, self._axes.bbox.intervaly ) and event.x <= self._axes.bbox.intervalx[1] def _on_scroll(self, event): if self._secondary_axes is not None: self._handle_scroll_secondary(event) in_x = self._in_x_scroll_zone(event) in_y = self._in_y_scroll_zone(event) if in_x or in_y and event.button in ['up', 'down']: (x_min, x_max), (y_min, y_max) = self._get_actual_xy_extents() if (in_x and self._single_axis_zoom_enabled) or (in_x and in_y): skew = self._zoom_skew and self._zoom_skew[0] skew = self._interval_skew( event.x, self._axes.bbox.intervalx) if skew is None else skew x_min, x_max = self._zoom(x_min, x_max, skew, event.button) if (in_y and self._single_axis_zoom_enabled) or (in_x and in_y): skew = self._zoom_skew and self._zoom_skew[1] skew = self._interval_skew( event.y, self._axes.bbox.intervaly) if skew is None else skew y_min, y_max = self._zoom(y_min, y_max, skew, event.button) self._xy_extents = (x_min, x_max), (y_min, y_max) self._set_axes_limits() self.draw() def _in_secondary_y_scroll_zone(self, event): return self._in_interval(event.y, self._axes.bbox.intervaly) and \ event.x >= self._axes.bbox.intervalx[1] def _in_secondary_x_scroll_zone(self, event): return self._in_interval(event.x, self._axes.bbox.intervalx) and \ event.y >= self._axes.bbox.intervaly[1] def _handle_scroll_secondary(self, event): if self._has_secondary_y_extent(): in_secondary_y = self._in_secondary_y_scroll_zone(event) if in_secondary_y and event.button in ['up', 'down']: self._secondary_y_extent = self._zoom( *self._get_secondary_y_extent(), self._interval_skew(event.y, self._axes.bbox.intervaly), event.button) if self._has_secondary_x_extent(): in_secondary_x = self._in_secondary_x_scroll_zone(event) if in_secondary_x and event.button in ['up', 'down']: self._secondary_x_extent = self._zoom( *self._get_secondary_x_extent(), self._interval_skew(event.x, self._axes.bbox.intervalx), event.button) def _get_zoom_multiplier(self): return 20 / 19 def _zoom(self, min_, max_, skew, direction): zoom_multiplier = self._get_zoom_multiplier( ) if direction == 'up' else 1 / self._get_zoom_multiplier() range_ = max_ - min_ diff = (range_ * (1 / zoom_multiplier)) - range_ max_ += diff * (1 - skew) min_ -= diff * skew return min_, max_ def _set_axes_limits(self): try: self._setting_axis_limits = True if self._secondary_axes is not None: self._set_secondary_axes_limits() self._update_ticks() (x_min, x_max), (y_min, y_max) = self._get_xy_extents() if self._options_view is not None: if self._options_view.x_limits: self._options_view.setXLimits(float(x_min), float(x_max)) if self._options_view.y_limits: self._options_view.setYLimits(float(y_min), float(y_max)) self._axes.set_xlim(*_safe_limits(x_min, x_max)) self._axes.set_ylim(*_safe_limits(y_min, y_max)) finally: self._setting_axis_limits = False def _set_secondary_axes_limits(self): if self._options_view is not None: if self._options_view.secondary_y_limits: enabled = self._secondary_y_enabled() secondary_y_min, secondary_y_max = self._get_secondary_y_extent( ) if enabled else (float('nan'), float('nan')) self._options_view.setSecondaryYLimitsEnabled(enabled) self._options_view.setSecondaryYLimits(float(secondary_y_min), float(secondary_y_max)) if self._options_view.secondary_x_limits: enabled = self._secondary_x_enabled() secondary_x_min, secondary_x_max = self._get_secondary_x_extent( ) if enabled else (float('nan'), float('nan')) self._options_view.setSecondaryXLimitsEnabled(enabled) self._options_view.setSecondaryXLimits(float(secondary_x_min), float(secondary_x_max)) if self._has_secondary_y_extent(): self._secondary_axes.set_ylim(*_safe_limits( *self._get_secondary_y_extent())) if self._has_secondary_x_extent(): self._secondary_axes.set_xlim(*_safe_limits( *self._get_secondary_x_extent())) def _secondary_y_enabled(self): return True if self._secondary_axes and self._secondary_axes.get_visible( ) and self._has_secondary_y_extent() else False def _secondary_x_enabled(self): return True if self._secondary_axes and self._secondary_axes.get_visible( ) and self._has_secondary_x_extent() else False def _set_axes_labels(self): self._axes.set_xlabel(self.data.xAxisTitle) self._axes.set_ylabel(self.data.yAxisTitle) def _set_center(self, center): if not all(c is not None for c in center): center = (0, 0) x_extent, y_extent = self._get_xy_extents() span = x_extent[1] - x_extent[0], y_extent[1] - y_extent[0] x_extent = center[0] - span[0] / 2, center[0] + span[0] / 2 y_extent = center[1] - span[1] / 2, center[1] + span[1] / 2 self._xy_extents = x_extent, y_extent def _get_xy_extents(self): if self.data is None: return (0, 0), (0, 0) if self._xy_extents is None: return self._get_data_xy_extents() return self._xy_extents def _get_data_xy_extents(self): if self.data is None: return (0, 0), (0, 0) (x_min, x_max), (y_min, y_max) = self.data.get_xy_extents() return self._pad_extent(x_min, x_max, self.x_extent_padding), self._pad_extent( y_min, y_max, self.y_extent_padding) def _has_secondary_y_extent(self): return hasattr(self.data, 'get_secondary_y_extent') def _get_secondary_y_extent(self): if self._secondary_y_extent is not None: return self._secondary_y_extent if self.data is not None: return self._get_data_secondary_y_extent() return (0, 0) def _get_data_secondary_y_extent(self): if self.data is None: return (0, 0) return self._pad_extent(*self.data.get_secondary_y_extent(), self.y_extent_padding) def _has_secondary_x_extent(self): return hasattr(self.data, 'get_secondary_x_extent') def _get_secondary_x_extent(self): if self._secondary_x_extent is not None: return self._secondary_x_extent if self.data is not None: return self._get_data_secondary_x_extent() return (0, 0) def _get_data_secondary_x_extent(self): if self.data is None or not hasattr(self.data, 'get_secondary_x_extent'): return (0, 0) return self._pad_extent(*self.data.get_secondary_x_extent(), self.x_extent_padding) def _get_actual_xy_extents(self): return self._axes.get_xlim(), self._axes.get_ylim() def _pad_extent(self, min_, max_, padding): min_, max_ = self._zero_if_nan(min_), self._zero_if_nan(max_) range_ = max_ - min_ return min_ - padding * range_, max_ + padding * range_ def _zoom_selected(self, start_pos, end_pos): x_min, x_max = min(start_pos.xdata, end_pos.xdata), max(start_pos.xdata, end_pos.xdata) y_min, y_max = min(start_pos.ydata, end_pos.ydata), max(start_pos.ydata, end_pos.ydata) self._xy_extents = (x_min, x_max), (y_min, y_max) self._set_axes_limits() self.draw() def _handle_span_select(self, x_min, x_max): x_min, x_max = self._round_to_bin_width(x_min, x_max) self._update_span_rect(x_min, x_max) self.span = SpanModel(self, x_min, x_max) self.draw() def _handle_span_select_none(self): self.span = None def _handle_press(self, event): if event.button == 1: if self._is_panning: self._pan_event = event elif self._span.active: self._handle_span_press(event) def _handle_move(self, event): if event.xdata and self._pan_event: self._handle_pan_move(event) elif event.xdata and any(self._span_events()): self._handle_span_move(event) def _handle_release(self, event): if self._pan_event: self._pan_event = None elif any(self._span_events()): self._handle_span_release(event) def _handle_pan_move(self, event): from_x, from_y = self._axes.transData.inverted().transform( (self._pan_event.x, self._pan_event.y)) to_x, to_y = self._axes.transData.inverted().transform( (event.x, event.y)) self._pan(from_x - to_x, from_y - to_y) self._pan_event = event def _pan(self, delta_x, delta_y): (x_min, x_max), (y_min, y_max) = self._get_xy_extents() self._xy_extents = (x_min + delta_x, x_max + delta_x), (y_min + delta_y, y_max + delta_y) self._set_axes_limits() self.draw() def _span_events(self): return self._span_center_mouse_event, self._span_left_mouse_event, self._span_right_mouse_event def _handle_span_press(self, event): if not event.xdata: return span_min, span_max = (self.span.left, self.span.right) if self.span else (0, 0) edge_tolerance = self._span_tolerance() if abs(span_min - event.xdata) < edge_tolerance: self._span.active = False self._span_left_mouse_event = event elif abs(span_max - event.xdata) < edge_tolerance: self._span.active = False self._span_right_mouse_event = event elif span_min < event.xdata < span_max: self._span.active = False self._span_center_mouse_event = event def _handle_span_move(self, event): if not self.span: return x_min, x_max = self.span.left, self.span.right last_event = next(x for x in self._span_events() if x) diff_x = event.xdata - last_event.xdata if self._span_center_mouse_event is not None: self._update_span_rect(x_min + diff_x) elif self._span_left_mouse_event is not None: self._update_span_rect(x_min + diff_x, x_max) elif self._span_right_mouse_event is not None: self._update_span_rect(x_min, x_max + diff_x) self.draw([self._span.rect]) def _handle_span_release(self, _event): x_min = self._span.rect.get_x() x_max = x_min + self._span.rect.get_width() x_min, x_max = self._round_to_bin_width(x_min, x_max) self._update_span_rect(x_min, x_max) self.span = SpanModel(self, x_min, x_max) self.draw() self._span.active = True self._span_center_mouse_event = self._span_left_mouse_event = self._span_right_mouse_event = None def _update_span_rect(self, x_min, x_max=None): self._span.rect.set_x(x_min) self._span.stay_rect.set_x(x_min) if x_max: self._span.rect.set_width(x_max - x_min) self._span.stay_rect.set_width(x_max - x_min) def _round_to_bin_width(self, x_min, x_max): return x_min, x_max def _span_tolerance(self): return 5 def toolEnabled(self, _tool_type): return False def toolAvailable(self, _tool_type): return False def activateTool(self, tool_type, active): if tool_type == ToolType.zoom: self._zoom_selector.set_active(active) elif tool_type == ToolType.span: if self._span.active and not active: self._previous_span = self.span self.span = None for r in [self._span.rect, self._span.stay_rect]: self._remove_artist(r) elif not self._span.active and active: self.span = self._previous_span for r in [self._span.rect, self._span.stay_rect]: self._add_artist(r) self._span.active = active self.draw() elif tool_type == ToolType.pan: self._is_panning = active self._active_tools[tool_type] = active def toolActive(self, tool_type): return self._active_tools.get(tool_type, False) def isActiveDefault(self, _tool_type): return False def _add_artist(self, artist): self._axes.add_artist(artist) self._decoration_artists.append(artist) def _remove_artist(self, artist): artist.remove() if artist in self._decoration_artists: self._decoration_artists.remove(artist) def _handle_resize(self, _event): self._update_ticks() return self.draw() def draw(self, artists=None): if artists is None: def _update(): for a in self._decoration_artists: a.remove() self._canvas.draw() self._background_cache = self._canvas.copy_from_bbox( self._figure.bbox) for a in self._decoration_artists: self._axes.add_artist(a) self._axes.draw_artist(a) self._canvas.update() self._pending_draw = _update else: def _update(): if self._background_cache is None: raise RuntimeError('Must run draw before drawing artists!') self._canvas.restore_region(self._background_cache) for a in artists: self._axes.draw_artist(a) self._canvas.update() self._pending_artists_draw = _update def _do_draw_events(self): if self._pending_draw is not None: self._pending_draw() self._pending_draw = None if self._pending_artists_draw is not None: self._pending_artists_draw() self._pending_artists_draw = None if self._other_draw_events: for draw_event in self._other_draw_events: draw_event() self._other_draw_events = [] def addDrawEvent(self, draw_event): self._other_draw_events.append(draw_event) def resetZoom(self): self._secondary_y_extent = self._secondary_x_extent = None self._xy_extents = None self._set_axes_limits() self.draw() def _twinx(self, ylabel): axes = self._axes.twinx() for spine in ['top', 'left']: axes.spines[spine].set_visible(False) axes.set_ylabel(ylabel) axes.set_zorder(1) return axes @property def axes(self): return self._axes @property def secondary_axes(self): if self._secondary_axes is None: self._set_secondary_axes(self._twinx('')) return self._secondary_axes def _set_secondary_axes(self, axes): self._secondary_axes = axes @staticmethod def sizeHint(): """function::sizeHint() Override the default sizeHint to ensure the plot has an initial size """ return QSize(600, 400) def minimumSizeHint(self): """function::sizeHint() Override the default sizeHint to ensure the plot does not shrink below minimum size """ return self.sizeHint() @staticmethod def _zero_if_nan(value): return value if not isinstance(value, float) or not np.isnan(value) else 0 def canShowTable(self): return hasattr(self, 'data') and self.data is not None and hasattr( self.data, 'table') def contextMenuEvent(self, event): self._show_table_action.setEnabled(self.canShowTable()) self._menu.exec_(event.globalPos()) def copyToClipboard(self): with BytesIO() as buffer: self._figure.savefig(buffer, facecolor=self._figure.get_facecolor()) QApplication.clipboard().setImage( QImage.fromData(buffer.getvalue())) def saveAsImage(self): filename = self._file_dialog_service.get_save_filename( self, self.tr('Portable Network Graphics (*.png)')) if filename: self._figure.savefig(filename, facecolor=self._figure.get_facecolor()) def showTable(self): if self.canShowTable(): self._table_view = TableView(None) self._table_view.pasteEnabled = False self._table_view.setModel(self.data.table) self._table_view.setMinimumSize(800, 600) self._table_view.show() def _update_ticks(self): if not self.data: return if hasattr(self.data, 'x_labels'): step = self.data.x_tick_interval if hasattr( self.data, 'x_tick_interval') else None x_ticks, x_labels = self._get_labels(self.data.x_labels, step, horizontal=True) self._axes.set_xticks(x_ticks) self._axes.set_xticklabels(x_labels) if hasattr(self.data, 'y_labels'): step = self.data.y_tick_interval if hasattr( self.data, 'y_tick_interval') else None y_ticks, y_labels = self._get_labels(self.data.y_labels, step, horizontal=False) self._axes.set_yticks(y_ticks) self._axes.set_yticklabels(y_labels) def _get_labels(self, labels, step, horizontal=True): (x0, x1), (y0, y1) = self._get_xy_extents() start, end = (int(x0), int(x1)) if horizontal else (int(y0), int(y1)) visible_points = end - start if not (step and step > 0): width, height = self._get_label_width_height(labels) axes_bbox = self._axes.get_window_extent( self._figure.canvas.get_renderer()).transformed( self._figure.dpi_scale_trans.inverted()) plot_size = (axes_bbox.width if horizontal else axes_bbox.height) * self._figure.dpi size = (width if horizontal else height) if plot_size == 0 or size == 0: n_labels = 16 else: n_labels = int(plot_size / size) if n_labels == 0: n_labels = 16 step = int(visible_points / n_labels) + 1 else: step = int(step) indexes = list(range(len(labels))) display_labels = list(labels) for i in indexes: if i % step: display_labels[i] = '' return indexes, display_labels def _get_label_width_height(self, labels): if not self._cached_label_width_height: font = MatPlotLibFont.default() width = 0 height = 0 for label in labels: next_width, next_height = font.get_size( str(label), matplotlib.rcParams['font.size'], self._figure.dpi) width = max(width, next_width) height = max(height, next_height) self._cached_label_width_height = width, height return self._cached_label_width_height def _create_new_axes(self, nx=1, ny=1) -> LocatableAxes: axes = LocatableAxes(self._figure, self._divider.get_position()) axes.set_axes_locator(self._divider.new_locator(nx=nx, ny=ny)) self._figure.add_axes(axes) return axes @staticmethod def _create_secondary_xy_axes(figure, divider, nx=1, ny=1, visible=False, z_order=1): axes = LocatableAxes(figure, divider.get_position()) axes.set_axes_locator(divider.new_locator(nx=nx, ny=ny)) axes.xaxis.tick_top() axes.xaxis.set_label_position('top') axes.yaxis.tick_right() axes.yaxis.set_label_position('right') axes.patch.set_visible(visible) axes.set_zorder(z_order) figure.add_axes(axes) axes.ticklabel_format(style='sci', axis='x', scilimits=(-4, 4)) axes.ticklabel_format(style='sci', axis='y', scilimits=(-4, 4)) return axes @staticmethod def _create_shared_axes(figure, divider, shared_axes, nx=1, ny=1, visible=False, z_order=1): axes = LocatableAxes(figure, divider.get_position(), sharex=shared_axes, sharey=shared_axes, frameon=False) axes.set_axes_locator(divider.new_locator(nx=nx, ny=ny)) for spine in axes.spines.values(): spine.set_visible(False) for axis in axes.axis.values(): axis.set_visible(False) axes.patch.set_visible(False) axes.set_visible(False) axes.set_zorder(z_order) figure.add_axes(axes) return axes
def bargraph(request): p = request.GET try: d = [(float(p['d10']), float(p['d11']), float(p['d12']), float(p['d13']), float(p['d14'])), (float(p['d20']), float(p['d21']), float(p['d22']), float(p['d23']), float(p['d24'])), (float(p['d30']), float(p['d31']), float(p['d32']), float(p['d33']), float(p['d34'])), (float(p['d40']), float(p['d41']), float(p['d42']), float(p['d43']), float(p['d44'])), (float(p['d50']), float(p['d51']), float(p['d52']), float(p['d53']), float(p['d54'])), (float(p['d60']), float(p['d61']), float(p['d62']), float(p['d63']), float(p['d64'])), (float(p['d70']), float(p['d71']), float(p['d72']), float(p['d73']), float(p['d74'])), (float(p['d80']), float(p['d81']), float(p['d82']), float(p['d83']), float(p['d84']))] except: return render(request,"bad.html", { 'type':'bargraph' }) s8name = strat_names[8] try: s8name = p['s8name'] except: pass colors = ["grey","blue","green","yellow","red"] cdata = [] for array in zip(*d): #Invert the numbers for proper display cdata.append([-1 * x for x in array]) loc = np.arange(len(cdata[0])) width = 0.15 fig = Figure(facecolor='white', dpi=150, figsize=(8,6)) canvas = FigureCanvas(fig) ax = fig.add_subplot(111) rect = [ax.bar(loc+width*i, cdata[i], width, color=colors[i]) for i in range(len(cdata))] max_height = max(chain(cdata[0],cdata[1],cdata[2],cdata[3],cdata[4])) + 10 min_height = min(chain(cdata[0],cdata[1],cdata[2],cdata[3],cdata[4])) - 10 print max_height, min_height ax.set_ylim(min_height,max_height) ax.set_xlim(-width*4, len(loc) +(4*width)) ax.set_xticks(loc + (2.5*width)) mod_strat_names = strat_names[1:-1] + ["8. {}".format(s8name)] ax.set_xticklabels(mod_strat_names, rotation='30', size='small', stretch='condensed', ha='right' ) ax.legend ((rect[0][0], rect[1][0], rect[2][0], rect[3][0], rect[4][0]), ("TB Incidence", "MDR Incidence", "TB Mortality","Cost at Year 1", "Cost at Year 5"),loc='best', prop={'size':'8'}) ax.set_title ("Side-by-Side Comparison of the Strategies Using 5 Key Metrics", {'fontweight':'bold'}) ax.axhline(color='black') ax.set_ylabel('percentage change from baseline',{'fontweight':'bold'}) fig.tight_layout() response=HttpResponse(content_type='image/png') canvas.print_png(response,facecolor=fig.get_facecolor()) return response
lons = t2m.coord('longitude').points t2m_img = ax_turbo.pcolorfast(lons, lats, t2m.data, cmap=ListedColormap(turbo_colormap_data), vmin=0, vmax=20, alpha=0.5) # Add a label showing the date label = "Turbo" mg.utils.plot_label(ax_turbo, label, x_fraction=0.97, y_fraction=0.92, facecolor=fig.get_facecolor()) # Top right - jet ax_jet = fig.add_axes([0.525, 0.525, 0.45, 0.45], projection=projection) ax_jet.set_axis_off() # Don't want surrounding x and y axis ax_jet.background_patch.set_facecolor((0.88, 0.88, 0.88, 1)) extent = [-180.0, 180.0, -90.0, 90.0] ax_jet.set_extent(extent, crs=projection) matplotlib.rc('image', aspect='auto') # Add the land land_img = ax_jet.background_img(name='GreyT', resolution='low') # Plot as a colour map t2m_img = ax_jet.pcolorfast(
# Draw a lat:lon grid mg.background.add_grid(ax, sep_major=5, sep_minor=2.5, color=(0, 0.3, 0, 0.2)) # Add the land land_img = ax.background_img(name='GreyT', resolution='low') # Get the wind data from the Meteorographica example_data # Mystical incantation to get filenames udf = pkg_resources.resource_filename( pkg_resources.Requirement.parse('Meteorographica'), 'example_data/20CR2c.1987101606.uwnd.10m.nc') uwnd = iris.load_cube(udf) vdf = pkg_resources.resource_filename( pkg_resources.Requirement.parse('Meteorographica'), 'example_data/20CR2c.1987101606.vwnd.10m.nc') vwnd = iris.load_cube(vdf) # Reduce to a single ensemble member uwnd = uwnd.extract(iris.Constraint(member=1)) vwnd = vwnd.extract(iris.Constraint(member=1)) # Plot the wind vectors mg.wind.plot(ax, uwnd, vwnd) # Add a label showing the date label = "16th October 1987 at 06 GMT" mg.utils.plot_label(ax, label, facecolor=fig.get_facecolor()) # Render the figure as a png fig.savefig('wind.png')
def bargraph_uncert(request): p = request.GET #BASIC TEST try: ca = [float(p['ca{}'.format(x)]) for x in range(1,9)] cal = [float(p['cal{}'.format(x)]) for x in range(1,9)] cah = [float(p['cah{}'.format(x)]) for x in range(1,9)] cb = [float(p['cb{}'.format(x)]) for x in range(1,9)] cbl = [float(p['cbl{}'.format(x)]) for x in range(1,9)] cbh = [float(p['cbh{}'.format(x)]) for x in range(1,9)] tb = [float(p['tb{}'.format(x)]) for x in xrange(1,9)] tbl = [float(p['tbl{}'.format(x)]) for x in xrange(1,9)] tbh = [float(p['tbh{}'.format(x)]) for x in xrange(1,9)] mb = [float(p['mb{}'.format(x)]) for x in xrange(1,9)] mbl = [float(p['mbl{}'.format(x)]) for x in xrange(1,9)] mbh = [float(p['mbh{}'.format(x)]) for x in range(1,9)] ob = [float(p['ob{}'.format(x)]) for x in range(1,9)] obl = [float(p['obl{}'.format(x)]) for x in range(1,9)] obh = [float(p['obh{}'.format(x)]) for x in range(1,9)] except: return render(request,"bad.html", { 'type':'bargraph' }) colors = ["grey","blue","green","yellow","red"] pdata = [ tb, mb, ob, ca, cb ] #ndata = zip(*d) height = max(chain(tbh,mbh,obh,cah,cbh,tb,mb,ob,ca,cb)) + 10 #loc = np.arange(len(ndata[0])) loc = np.arange(len(ca)) width = 0.15 fig = Figure(facecolor='white', dpi=150, figsize=(8,6)) canvas = FigureCanvas(fig) ax = fig.add_subplot(111) rect = [ax.bar(loc+width*i, pdata[i], width, color=colors[i]) for i in range(len(pdata))] [ax.errorbar([i+(width*.5)], tb[i], yerr=[[tb[i] - tbl[i]],[tbh[i] - tb[i]]], color='black', ecolor='black', linewidth=1) for i in xrange(8)] #TBIncidence Errorbar [ax.errorbar([i+(width*1.5)], mb[i], yerr=[[mb[i] - mbl[i]],[mbh[i] - mb[i]]], color='black', ecolor='black', linewidth=1) for i in xrange(8)] #MDRIncidence Errorbar [ax.errorbar([i+(width*2.5)], ob[i], yerr=[[ob[i] - obl[i]],[obh[i] - ob[i]]], color='black', ecolor='black', linewidth=1) for i in xrange(8)] #Mortality Errorbar [ax.errorbar([i+(width*3.5)], ca[i], yerr=[[ca[i] - cal[i]],[cah[i] - ca[i]]], color='black', ecolor='black', linewidth=1) for i in xrange(8)] #Cost Yr 1 Errorbar [ax.errorbar([i+(width*4.5)], cb[i], yerr=[[cb[i] - cbl[i]],[cbh[i] - cb[i]]], color='black', ecolor='black', linewidth=1) for i in xrange(8)] #Cost Yr 5 Errorbar ax.set_ylim(-50,height) ax.set_xlim(-width*4, len(loc) +(4*width)) ax.set_xticks(loc + (2.5*width)) ax.set_xticklabels(strat_names[1:], rotation='30', size='small', stretch='condensed', ha='right' ) ax.legend ((rect[0][0], rect[1][0], rect[2][0], rect[3][0], rect[4][0] ), ("TB Incidence", "MDR Incidence", "TB Mortality","Cost at Year 1", "Cost at Year 5"),loc='best', prop={'size':'8'}) ax.set_title ("Side-by-Side Comparison of the Strategies Using 5 Key Metrics", {'fontweight':'bold'}) ax.axhline(color='black') ax.set_ylabel('percentage change from baseline',{'fontweight':'bold'}) fig.tight_layout() response=HttpResponse(content_type='image/png') canvas.print_png(response,facecolor=fig.get_facecolor()) return response