Example #1
0
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)
Example #2
0
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)
Example #3
0
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
Example #5
0
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)
Example #6
0
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
Example #8
0
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)
Example #10
0
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
Example #11
0
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
Example #12
0
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()
Example #13
0
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))
Example #15
0
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
Example #16
0
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
Example #17
0
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
Example #18
0
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
Example #19
0
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)
Example #20
0
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)
Example #21
0
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
Example #22
0
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
Example #23
0
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
Example #24
0
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(
Example #25
0
# 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')
Example #26
0
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