<commit_before>from flask import request, redirect, url_for, Blueprint, render_template, \
    session, jsonify
import netCDF4
import pandas as pd
import numpy as np
import json
from atlas.utils.data_munger import DataMunger
from atlas.constants import MODELS, DATASETS, SCENARIOS, IRRIGATION, \
    CROPS, VARIABLES

mod = Blueprint('atlas', __name__,)

def initial_session(var=None):
    try:
        session['scenario'] = 0 if not session['scenario'] else session['scenario']
        session['irrigation'] = 0 if not session['irrigation'] else session['irrigation']
        session['time'] = 0 if not session['time'] else session['time']
    except KeyError:
        session['scenario'] = 0
        session['irrigation'] = 0
        session['time'] = 0

@mod.route('/globe/<lon>/<lat>/<model>/<dataset>/<scenario>/<irrigation>' +
           '/<crop>/<var>/<compare>')
@mod.route('/globe/<lon>/<lat>/<model>/<dataset>/<scenario>/<irrigation>' +
           '/<crop>/<var>', defaults={'compare': None, })
@mod.route('/globe/<lon>/<lat>',
           defaults={'model': 'papsim', 'dataset': 'wfdei.cru',
                     'scenario': 'fullharm', 'irrigation': 'firr',})
@mod.route('/',
           defaults={'lon': 0, 'lat': 0, 'model': 'papsim', 'dataset': 'wfdei.cru',
                     'scenario': 'fullharm', 'irrigation': 'firr',
                     'crop': 'whe', 'var': 'yield', 'compare': None})
def index(lon, lat, model, dataset, scenario, irrigation, crop, var, compare):
    initial_session()
    session['var'] = var
    session['lon'] = lon
    session['lat'] = lat
    session['model'] = model
    session['dataset'] = dataset
    session['irrigation'] = irrigation
    session['scenario'] = scenario
    session['crop'] = crop
    session['compare'] = compare
    return render_template(
        'index.html',
        map_type='globe',
        var=session['var'],
        model=session['model'],
        dataset=session['dataset'],
        irrigation=session['irrigation'],
        scenario=session['scenario'],
        compare=session['compare'],
        crop=session['crop'],
        lon=session['lon'],
        lat=session['lat'],
    )

@mod.route('/aggr/<lon>/<lat>/pdssat/hadgem/<scenario>/<irrigation>' +
           '/<crop>/<var>/<compare>', defaults={'model': 'pdssat', 'dataset': 'hadgem'})
@mod.route('/aggr/<lon>/<lat>/pdssat/hadgem/<scenario>/<irrigation>' +
           '/<crop>/<var>', defaults={'compare': None, 'model': 'pdssat', 'dataset': 'hadgem'})
def hadgem_view(lon, lat, model, dataset, scenario, irrigation, crop, var, compare):
    initial_session()
    session['var'] = var
    session['lon'] = lon
    session['lat'] = lat
    session['model'] = model
    session['dataset'] = dataset
    session['irrigation'] = irrigation
    session['scenario'] = scenario
    session['crop'] = crop
    session['compare'] = compare
    return render_template(
        'hadgem.html',
        map_type = 'grid',
        var=session['var'],
        lon=session['lon'],
        lat=session['lat'],
        model='pdssat',
        dataset='HADGEM',
        irrigation=session['irrigation'],
        scenario=session['scenario'],
        compare=session['compare'],
        crop=session['crop'],
    )

@mod.route('/aggr/<lon>/<lat>/<model>/<dataset>/<scenario>/<irrigation>' +
           '/<crop>/<var>/<compare>')
@mod.route('/aggr/<lon>/<lat>/<model>/<dataset>/<scenario>/<irrigation>' +
           '/<crop>/<var>', defaults={'compare': None, })
@mod.route('/aggr/<lon>/<lat>',
           defaults={'model': 'papsim', 'dataset': 'wfdei.cru',
                     'scenario': 'fullharm', 'irrigation': 'firr',
                     'crop': 'whe', 'var': 'yield', 'compare': None})
def aggr_view(lon, lat, model, dataset, scenario, irrigation, crop, var, compare):
    initial_session()
    session['var'] = var
    session['lon'] = lon
    session['lat'] = lat
    session['model'] = model
    session['dataset'] = dataset
    session['irrigation'] = irrigation
    session['scenario'] = scenario
    session['crop'] = crop
    session['compare'] = compare
    return render_template(
        'aggr/aggr.html',
        map_type = 'grid',
        var=session['var'],
        lon=session['lon'],
        lat=session['lat'],
        model=session['model'],
        dataset=session['dataset'],
        irrigation=session['irrigation'],
        scenario=session['scenario'],
        compare=session['compare'],
        crop=session['crop'],
    )

@mod.route('/grid/<lon>/<lat>/<model>/<dataset>/<scenario>/<irrigation>' +
           '/<crop>/<var>/<compare>')
@mod.route('/grid/<lon>/<lat>/<model>/<dataset>/<scenario>/<irrigation>' +
           '/<crop>/<var>',
           defaults={'compare': None, })
@mod.route('/grid/<lon>/<lat>',
           defaults={'model': 'papsim', 'dataset': 'wfdei.cru',
                     'scenario': 'fullharm', 'irrigation': 'firr',
                     'crop': 'whe', 'var': 'yield', 'compare': None})
def grid_view(lon, lat, model, dataset, scenario, irrigation, crop, var, compare):
    initial_session()
    session['var'] = var
    session['lon'] = lon
    session['lat'] = lat
    session['model'] = model
    session['dataset'] = dataset
    session['irrigation'] = irrigation
    session['scenario'] = scenario
    session['crop'] = crop
    session['compare'] = compare
    damn = DataMunger(
        model=[a for a, b, c in MODELS if b == model][0],
        dataset=[a for a, b, c, d, e in DATASETS if b == dataset][0],
        scenario=[a for a, b, c in SCENARIOS if b == scenario][0],
        irr=[a for a, b, c in IRRIGATION if b == irrigation][0],
        crop=[a for a, b, c in CROPS if b == crop][0],
        var=[a for a, b, c in VARIABLES if b == var][0],
        adm=1,
    )
    return render_template(
        'grid/grid.html',
        map_type = 'grid',
        var=session['var'],
        lon=session['lon'],
        lat=session['lat'],
        model=session['model'],
        dataset=session['dataset'],
        irrigation=session['irrigation'],
        scenario=session['scenario'],
        compare=session['compare'],
        crop=session['crop'],
        json=damn.grid_to_json(lon, lat),
    )

@mod.route('/magpie/<lon>/<lat>/<model>/<dataset>/<scenario>/<irrigation>' +
           '/<crop>/<var>/<compare>')
@mod.route('/magpie/<lon>/<lat>/<model>/<dataset>/<scenario>/<irrigation>' +
           '/<crop>/<var>', defaults={'compare': None, })
@mod.route('/magpie/<lon>/<lat>',
           defaults={'model': 'papsim', 'dataset': 'wfdei.cru',
                     'scenario': 'fullharm', 'irrigation': 'firr',
                     'crop': 'whe', 'var': 'yield', 'compare': None})
def magpie_view(lon, lat, model, dataset, scenario, irrigation, crop, var, compare):
    initial_session()
    session['var'] = var
    session['lon'] = lon
    session['lat'] = lat
    session['model'] = model
    session['dataset'] = dataset
    session['irrigation'] = irrigation
    session['scenario'] = scenario
    session['crop'] = crop
    session['compare'] = compare
    return render_template(
        'magpie.html',
        map_type = 'grid',
        var=session['var'],
        lon=session['lon'],
        lat=session['lat'],
        model=session['model'],
        dataset='MAgPIE',
        irrigation=session['irrigation'],
        scenario=session['scenario'],
        compare=session['compare'],
        crop=session['crop'],
    )

@mod.context_processor
def menu_options():
    return dict(
        models=MODELS,
        datasets=DATASETS,
        scenarios=SCENARIOS,
        irrigations=IRRIGATION,
        crops=CROPS,
        vars=VARIABLES,
    )

@mod.route('/update/<_data_type>/adm/<_adm>/var/<_var>/type/<_type>/value/<_value>', methods=['POST',])
def update(_data_type, _adm, _var, _type, _value):
    with open('./atlas/static/json/{}/gadm{}/{}_gadm{}.json'.format(_data_type, _adm, _var, _adm), 'r') as f:
        data = json.loads(f.read())
    session[_type] = _value
    data['data'] = {
        k: np.array(v)[:, session['scenario'], session['irrigation']].tolist()
        for k, v in data['data'].iteritems()
    }
    return jsonify(data)

<commit_msg>Remove old views<commit_after>from flask import Blueprint, render_template, \
    session, jsonify
import numpy as np
import json
from atlas.utils.data_munger import DataMunger
from atlas.constants import MODELS, DATASETS, SCENARIOS, IRRIGATION, \
    CROPS, VARIABLES

mod = Blueprint('atlas', __name__,)

def initial_session(var=None):
    try:
        session['scenario'] = 0 if not session['scenario'] else session['scenario']
        session['irrigation'] = 0 if not session['irrigation'] else session['irrigation']
        session['time'] = 0 if not session['time'] else session['time']
    except KeyError:
        session['scenario'] = 0
        session['irrigation'] = 0
        session['time'] = 0

@mod.route('/',
           defaults={'lon': 0, 'lat': 0, 'model': 'papsim', 'dataset': 'wfdei.cru',
                     'scenario': 'fullharm', 'irrigation': 'firr',
                     'crop': 'whe', 'var': 'yield', 'compare': None})
def index(lon, lat, model, dataset, scenario, irrigation, crop, var, compare):
    initial_session()
    session['var'] = var
    session['lon'] = lon
    session['lat'] = lat
    session['model'] = model
    session['dataset'] = dataset
    session['irrigation'] = irrigation
    session['scenario'] = scenario
    session['crop'] = crop
    session['compare'] = compare
    return render_template(
        'index.html',
        map_type='globe',
        var=session['var'],
        model=session['model'],
        dataset=session['dataset'],
        irrigation=session['irrigation'],
        scenario=session['scenario'],
        compare=session['compare'],
        crop=session['crop'],
        lon=session['lon'],
        lat=session['lat'],
    )

@mod.route('/aggr/<lon>/<lat>/<model>/<dataset>/<scenario>/<irrigation>' +
           '/<crop>/<var>/<compare>')
@mod.route('/aggr/<lon>/<lat>/<model>/<dataset>/<scenario>/<irrigation>' +
           '/<crop>/<var>', defaults={'compare': None, })
@mod.route('/aggr/<lon>/<lat>',
           defaults={'model': 'papsim', 'dataset': 'wfdei.cru',
                     'scenario': 'fullharm', 'irrigation': 'firr',
                     'crop': 'whe', 'var': 'yield', 'compare': None})
def aggr_view(lon, lat, model, dataset, scenario, irrigation, crop, var, compare):
    initial_session()
    session['var'] = var
    session['lon'] = lon
    session['lat'] = lat
    session['model'] = model
    session['dataset'] = dataset
    session['irrigation'] = irrigation
    session['scenario'] = scenario
    session['crop'] = crop
    session['compare'] = compare
    return render_template(
        'aggr/aggr.html',
        map_type = 'grid',
        var=session['var'],
        lon=session['lon'],
        lat=session['lat'],
        model=session['model'],
        dataset=session['dataset'],
        irrigation=session['irrigation'],
        scenario=session['scenario'],
        compare=session['compare'],
        crop=session['crop'],
    )

@mod.route('/grid/<lon>/<lat>/<model>/<dataset>/<scenario>/<irrigation>' +
           '/<crop>/<var>/<compare>')
@mod.route('/grid/<lon>/<lat>/<model>/<dataset>/<scenario>/<irrigation>' +
           '/<crop>/<var>',
           defaults={'compare': None, })
@mod.route('/grid/<lon>/<lat>',
           defaults={'model': 'papsim', 'dataset': 'wfdei.cru',
                     'scenario': 'fullharm', 'irrigation': 'firr',
                     'crop': 'whe', 'var': 'yield', 'compare': None})
def grid_view(lon, lat, model, dataset, scenario, irrigation, crop, var, compare):
    initial_session()
    session['var'] = var
    session['lon'] = lon
    session['lat'] = lat
    session['model'] = model
    session['dataset'] = dataset
    session['irrigation'] = irrigation
    session['scenario'] = scenario
    session['crop'] = crop
    session['compare'] = compare
    damn = DataMunger(
        model=[a for a, b, c in MODELS if b == model][0],
        dataset=[a for a, b, c, d, e in DATASETS if b == dataset][0],
        scenario=[a for a, b, c in SCENARIOS if b == scenario][0],
        irr=[a for a, b, c in IRRIGATION if b == irrigation][0],
        crop=[a for a, b, c in CROPS if b == crop][0],
        var=[a for a, b, c in VARIABLES if b == var][0],
        adm=1,
    )
    return render_template(
        'grid/grid.html',
        map_type = 'grid',
        var=session['var'],
        lon=session['lon'],
        lat=session['lat'],
        model=session['model'],
        dataset=session['dataset'],
        irrigation=session['irrigation'],
        scenario=session['scenario'],
        compare=session['compare'],
        crop=session['crop'],
        json=damn.grid_to_json(lon, lat),
    )

@mod.context_processor
def menu_options():
    return dict(
        models=MODELS,
        datasets=DATASETS,
        scenarios=SCENARIOS,
        irrigations=IRRIGATION,
        crops=CROPS,
        vars=VARIABLES,
    )

@mod.route('/update/<_data_type>/adm/<_adm>/var/<_var>/type/<_type>/value/<_value>', methods=['POST',])
def update(_data_type, _adm, _var, _type, _value):
    with open('./atlas/static/json/{}/gadm{}/{}_gadm{}.json'.format(_data_type, _adm, _var, _adm), 'r') as f:
        data = json.loads(f.read())
    session[_type] = _value
    data['data'] = {
        k: np.array(v)[:, session['scenario'], session['irrigation']].tolist()
        for k, v in data['data'].iteritems()
    }
    return jsonify(data)
<|endoftext|>


<commit_before>"""
Utility functions for plotting atmospheric data.
"""

import math
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import xray
from atmos.utils import print_if

# ----------------------------------------------------------------------
def degree_sign():
    """Return a degree sign for LaTeX interpreter."""
    return r'$^\circ$'

# ----------------------------------------------------------------------
def latlon_labels(vals, latlon='lat', fmt='%.0f'):
    """Return a label string for list of latitudes or longitudes."""

    if latlon.lower() == 'lat':
        pos, neg = 'N', 'S'
    elif latlon.lower() == 'lon':
        pos, neg = 'E', 'W'
    else:
        raise ValueError('Invalid input latlon = ' + latlon)

    labels = []
    for num in vals:
        if num >= 0:
            suffix = pos
            x = fmt % num
        else:
            suffix = neg
            x = fmt % abs(num)
        labels.append(x + degree_sign() + suffix)
    return labels

# ----------------------------------------------------------------------
def mapticks(lon_ticks, lat_ticks):
    """Add nicely formatted ticks to lat-lon map."""
    plt.xticks(lon_ticks, latlon_labels(lon_ticks,'lon'))
    plt.yticks(lat_ticks, latlon_labels(lat_ticks, 'lat'))

# ----------------------------------------------------------------------
def autoticks(axtype, axmin, axmax, width=None, nmax=8):
    """
    Return an array of sensible automatic tick positions for geo data.

    Parameters
    ----------
    axtype : {'pres', 'lat', 'lon'}
        Type of axis - longitude, latitude or pressure level
    axmin, axmax : float or int
        Axis limits
    width : float, optional
        Spacing of ticks.  Omit to let the function set an auto value.
    nmax : int, optional
        Maximum number of ticks.  This is ignored if width is specified.

    Returns
    -------
    ticks : ndarray
        Array of tick positions
    """

    if not width:
        # Set the width between ticks
        diff = axmax - axmin
        if axtype.lower() == 'lon' or axtype.lower() == 'lat':
            wlist = [10, 15, 30, 60]
        elif axtype.lower() == 'pres':
            wlist = [50, 100, 200]
        else:
            raise ValueError('Invalid axtype: ' + axtype)

        for w in wlist:
            n1 = math.ceil(float(axmin)/w)
            n2 = math.floor(float(axmax)/w)
            ntick = n2 - n1 + 1
            if ntick <= nmax:
                width = w
                break
    else:
        # Use the width specified in input
        n1 = math.ceil(float(axmin)/width)
        n2 = math.floor(float(axmax)/width)

    # Set the ticks
    ticks = np.arange(n1*width, (n2+0.1)*width, width)
    return ticks

# ----------------------------------------------------------------------
def clevels(data, cint, posneg='both', symmetric=False, omitzero=False):
    """
    Return array of contour levels spaced by a given interval.

    Parameters
    ----------
    data : ndarray
        Data to be contoured
    cint : float
        Spacing of contour intervals
    posneg : {'both', 'pos', 'neg'}, optional
        Return all contours or only pos/neg
    symmetric : bool, optional
        Return contour levels symmetric about zero
    omitzero : bool, optional
        Omit zero from the contour levels

    Returns
    -------
    clev: ndarray
        Array of contour levels
    """

    # Define max and min contour levels
    if symmetric:
        cabs = math.ceil(abs(data).max() / cint) * cint
        cmin, cmax = -cabs, cabs
    else:
        cmin = math.floor(data.min() / cint) * cint
        cmax = math.ceil(data.max() / cint) * cint
    if posneg == 'pos':
        cmin = 0
    elif posneg == 'neg':
        cmax = 0

    # Define contour levels, making sure to include the endpoint
    clev = np.arange(cmin, cmax + 0.1*cint, cint)

    # Omit zero, if selected
    if omitzero:
        ind = np.where(clev == 0)
        clev = np.delete(clev, ind)

    return clev

# ----------------------------------------------------------------------
def init_latlon(lat1=-90, lat2=90, lon1=0, lon2=360, labels=['left', 'bottom'],
                gridlinewidth=0.0):
    """Initialize lon-lat plot and return as a Basemap object."""

    m = Basemap(llcrnrlon=lon1, llcrnrlat=lat1, urcrnrlon=lon2, urcrnrlat=lat2)
    m.drawcoastlines()
    xticks = autoticks('lon', lon1, lon2)
    yticks = autoticks('lat', lat1, lat2)
    mapticks(xticks, yticks)
    plt.draw()
    return m

# ----------------------------------------------------------------------
def pcolor_latlon(data, lat=None, lon=None, m=None, cmap='RdBu_r',
                  axlims=(-90, 90, 0, 360)):
    """Create a pseudo-color plot of geo data.

    Parameters
    ----------
    data : ndarray or xray.DataArray
        Data to be plotted.
    lat, lon : ndarray, optional
        Latitude and longitude arrays.  Only used if data is an ndarray.
        If data is an xray.DataArray then lat = data['lat'] and
        lon = data['lon']
    m : Basemap object, optional
        Basemap to plot on.  If omitted, then a map is created with
        init_latlon().
    cmap : string or colormap object, optional
        Colormap to use.
    axlims : 4-tuple of ints or floats
        Lat-lon limits for map.

    Returns
    -------
    m : Basemap object
    """

    if isinstance(data, xray.DataArray):
        lat, lon = data['lat'], data['lon']
        vals = data.values
    else:
        vals = data

    # Use a masked array so that pcolormesh displays NaNs properly
    vals_plot = np.ma.array(vals, mask=np.isnan(vals))

    x, y = np.meshgrid(lon, lat)
    lat1, lat2, lon1, lon2 = axlims

    if m is None:
        m = init_latlon(lat1, lat2, lon1, lon2)
    m.pcolormesh(x, y, vals_plot, cmap=cmap, latlon=True)
    m.colorbar()
    plt.draw()
    return m

# ----------------------------------------------------------------------
def contourf_latlon(data, lat=None, lon=None, clev=None, m=None, cmap='RdBu_r',
                    symmetric=True, axlims=(-90, 90, 0, 360)):
    """Create a filled contour plot of geo data.

    Parameters
    ----------
    data : ndarray or xray.DataArray
        Data to be plotted.
    lat, lon : ndarray, optional
        Latitude and longitude arrays.  Only used if data is an ndarray.
        If data is an xray.DataArray then lat = data['lat'] and
        lon = data['lon']
    clev : scalar or array of ints or floats, optional
        Contour spacing (scalar) or contour levels (array).
    m : Basemap object, optional
        Basemap to plot on.  If omitted, then a map is created with
        init_latlon().
    cmap : string or colormap object, optional
        Colormap to use.
    symmetric : bool, optional
        Set contour levels to be symmetric about zero.
    axlims : 4-tuple of ints or floats
        Lat-lon limits for map.

    Returns
    -------
    m : Basemap object
    """

    if isinstance(data, xray.DataArray):
        lat, lon = data['lat'], data['lon']

    if isinstance(clev, float) or isinstance(clev, int):
        # Define contour levels from selected interval spacing
        clev = clevels(data, clev, symmetric=symmetric)

    lat1, lat2, lon1, lon2 = axlims
    x, y = np.meshgrid(lon, lat)

    if m is None:
        m = init_latlon(lat1, lat2, lon1, lon2)
    if clev is None:
        m.contourf(x, y, data, cmap=cmap, latlon=True)
    else:
        m.contourf(x,y, data, clev, cmap=cmap, latlon=True)
    m.colorbar()
    plt.draw()
    return m

# ----------------------------------------------------------------------
def contour_latlon(data, lat=None, lon=None, clev=None, m=None, colors='black',
                   linewidths=2.0, axlims=(-90, 90, 0, 360)):
    """Create a contour line plot of geo data.

    Parameters
    ----------
    data : ndarray or xray.DataArray
        Data to be plotted.
    lat, lon : ndarray, optional
        Latitude and longitude arrays.  Only used if data is an ndarray.
        If data is an xray.DataArray then lat = data['lat'] and
        lon = data['lon']
    clev : scalar or array of ints or floats, optional
        Contour spacing (scalar) or contour levels (array).
    m : Basemap object, optional
        Basemap to plot on.  If omitted, then a map is created with
        init_latlon().
    colors : string or mpl_color, optional
        Contour line color(s).
    linewidths : int or float, optional
        Line width for contour lines
    axlims : 4-tuple of ints or floats
        Lat-lon limits for map.

    Returns
    -------
    m : Basemap object
    """

    if isinstance(data, xray.DataArray):
        lat, lon = data['lat'], data['lon']

    if isinstance(clev, float) or isinstance(clev, int):
        # Define contour levels from selected interval spacing
        clev = clevels(data, clev)

    lat1, lat2, lon1, lon2 = axlims
    x, y = np.meshgrid(lon, lat)

    if m is None:
        m = init_latlon(lat1, lat2, lon1, lon2)
    if clev is None:
        m.contour(x, y, data, colors=colors, linewidths=linewidths,
                  latlon=True)
    else:
        m.contour(x,y, data, clev, colors=colors, linewidths=linewidths,
                  latlon=True)
    plt.draw()
    return m

# ----------------------------------------------------------------------
def init_latpres(latmin=-90, latmax=90, pmin=0, pmax=1000, topo_ps=None,
                 topo_lat=None, topo_clr='black', p_units='hPa'):
    """Initialize a latitude-pressure plot.

    Parameters
    ----------
    latmin, latmax, pmin, pmax : int or float, optional
        Axes limits.
    topo_ps, topo_lat : ndarray or list of floats, optional
        Surface pressure profile to plot for topography.
    topo_clr : string or mpl_color, optional
        Color to fill topographic profile.
    p_units : string, optional
        Units of pressure for y-axis and surface pressure profile.
    """

    xticks = autoticks('lat', latmin, latmax)
    yticks = autoticks('pres', pmin, pmax)
    plt.xlim(latmin, latmax)
    plt.xticks(xticks)
    plt.ylim(pmin, pmax)
    plt.yticks(yticks)
    plt.gca().invert_yaxis()
    plt.xlabel('Latitude')
    plt.ylabel('Pressure (' + p_units + ')')

    if isinstance(topo_ps, np.ndarray) or isinstance(topo_ps, list):
        plt.fill_between(topo_lat, pmax, topo_ps, color=topo_clr)

    plt.draw()

# ----------------------------------------------------------------------
def contour_latpres(data, lat=None, plev=None, clev=None, colors='black',
                    topo=None, topo_clr='black', p_units='hPa',
                    axlims=(-90, 90, 0, 1000)):
    """
    Plot contour lines in latitude-pressure plane

    Parameters
    ----------
    data : ndarray or xray.DataArray
        Data to be contoured.
    lat : ndarray, optional
        Latitude (degrees).  If data is an xray.DataArray, lat is
        extracted from data['lat'].
    plev : ndarray, optional
        Pressure levels.  If data is an xray.DataArray, plev is
        extracted from data['plev'].
    clev : float or ndarray
        Contour levels (ndarray) or spacing interval (float)
    colors: string or mpl_color, optional
        Contour line color.
    topo : ndarray or xray.DataArray, optional
        Topography to shade (average surface pressure in units of plev).
        If topo is an ndarray, it must be on the same latitude grid as
        data.  If topo is an xray.DataArray, its latitude grid is
        extracted from topo['lat'].
    topo_clr : string or mpl_color, optional
        Color to fill topographic profile.
    p_units : string, optional
        Units for pressure axis.
    axlims : 4-tuple of floats or ints
        Axis limits (latmin, latmax, pmin, pmax).
    """

    # Data to be contoured
    if isinstance(data, xray.DataArray):
        lat, plev = data['lat'], data['plev']

    # Topography
    if isinstance(topo, np.ndarray) or isinstance(topo, list):
        topo_ps, topo_lat = topo, lat
    elif isinstance(topo, xray.DataArray):
        topo_ps, topo_lat = topo.values, topo['lat']
    else:
        topo_ps, topo_lat = None

    # Contour levels
    if isinstance(clev, float) or isinstance(clev, int):
        # Define contour levels from selected interval spacing
        clev = clevels(data, clev)

    # Grid for plotting
    y, z = np.meshgrid(lat, plev)

    # Plot contours
    latmin, latmax, pmin, pmax = axlims
    init_latpres(latmin, latmax, pmin, pmax, topo_ps=topo_ps,
                 topo_lat=topo_lat, topo_clr=topo_clr, p_units=p_units)
    if clev is None:
        plt.contour(y, z, data, colors=colors)
    else:
        plt.contour(y, z, data, clev, colors=colors)
    plt.draw()

# ----------------------------------------------------------------------

def pcolor_latpres():
    """Plot pseudo-color of data in latitude-pressure plane."""

def contourf_latpres():
    """Plot filled contours of data in latitude-pressure plane."""

def contourf_timelat():
    """Plot filled contours of data in time-latitude plane."""

"""
TO DO:

mapticks - change tick label formatting to 0-360E rather than 180W to 180E
        -> Define a function to return the formatted ticks and use fmt
           keyword argument in m.drawmeridians

mapaxes(m, axlims, xticks, yticks) - adjust limits, ticks and tick labels of
        existing map (might have to create new basemap object to do this)

contour_latpres - format dictionaries for contours and topography,
    - zero contours treated separately - omit or make different color/width
"""
<commit_msg>init_latpres and contour_latpres turn on/off plot init and specify tick spacing<commit_after>"""
Utility functions for plotting atmospheric data.
"""

import math
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import xray
from atmos.utils import print_if

# ----------------------------------------------------------------------
def degree_sign():
    """Return a degree sign for LaTeX interpreter."""
    return r'$^\circ$'

# ----------------------------------------------------------------------
def latlon_labels(vals, latlon='lat', fmt='%.0f'):
    """Return a label string for list of latitudes or longitudes."""

    if latlon.lower() == 'lat':
        pos, neg = 'N', 'S'
    elif latlon.lower() == 'lon':
        pos, neg = 'E', 'W'
    else:
        raise ValueError('Invalid input latlon = ' + latlon)

    labels = []
    for num in vals:
        if num >= 0:
            suffix = pos
            x = fmt % num
        else:
            suffix = neg
            x = fmt % abs(num)
        labels.append(x + degree_sign() + suffix)
    return labels

# ----------------------------------------------------------------------
def mapticks(lon_ticks, lat_ticks):
    """Add nicely formatted ticks to lat-lon map."""
    plt.xticks(lon_ticks, latlon_labels(lon_ticks,'lon'))
    plt.yticks(lat_ticks, latlon_labels(lat_ticks, 'lat'))

# ----------------------------------------------------------------------
def autoticks(axtype, axmin, axmax, width=None, nmax=8):
    """
    Return an array of sensible automatic tick positions for geo data.

    Parameters
    ----------
    axtype : {'pres', 'lat', 'lon'}
        Type of axis - longitude, latitude or pressure level
    axmin, axmax : float or int
        Axis limits
    width : float, optional
        Spacing of ticks.  Omit to let the function set an auto value.
    nmax : int, optional
        Maximum number of ticks.  This is ignored if width is specified.

    Returns
    -------
    ticks : ndarray
        Array of tick positions
    """

    if not width:
        # Set the width between ticks
        diff = axmax - axmin
        if axtype.lower() == 'lon' or axtype.lower() == 'lat':
            wlist = [10, 15, 30, 60]
        elif axtype.lower() == 'pres':
            wlist = [50, 100, 200]
        else:
            raise ValueError('Invalid axtype: ' + axtype)

        for w in wlist:
            n1 = math.ceil(float(axmin)/w)
            n2 = math.floor(float(axmax)/w)
            ntick = n2 - n1 + 1
            if ntick <= nmax:
                width = w
                break
    else:
        # Use the width specified in input
        n1 = math.ceil(float(axmin)/width)
        n2 = math.floor(float(axmax)/width)

    # Set the ticks
    ticks = np.arange(n1*width, (n2+0.1)*width, width)
    return ticks

# ----------------------------------------------------------------------
def clevels(data, cint, posneg='both', symmetric=False, omitzero=False):
    """
    Return array of contour levels spaced by a given interval.

    Parameters
    ----------
    data : ndarray
        Data to be contoured
    cint : float
        Spacing of contour intervals
    posneg : {'both', 'pos', 'neg'}, optional
        Return all contours or only pos/neg
    symmetric : bool, optional
        Return contour levels symmetric about zero
    omitzero : bool, optional
        Omit zero from the contour levels

    Returns
    -------
    clev: ndarray
        Array of contour levels
    """

    # Define max and min contour levels
    if symmetric:
        cabs = math.ceil(abs(data).max() / cint) * cint
        cmin, cmax = -cabs, cabs
    else:
        cmin = math.floor(data.min() / cint) * cint
        cmax = math.ceil(data.max() / cint) * cint
    if posneg == 'pos':
        cmin = 0
    elif posneg == 'neg':
        cmax = 0

    # Define contour levels, making sure to include the endpoint
    clev = np.arange(cmin, cmax + 0.1*cint, cint)

    # Omit zero, if selected
    if omitzero:
        ind = np.where(clev == 0)
        clev = np.delete(clev, ind)

    return clev

# ----------------------------------------------------------------------
def init_latlon(lat1=-90, lat2=90, lon1=0, lon2=360, labels=['left', 'bottom'],
                gridlinewidth=0.0):
    """Initialize lon-lat plot and return as a Basemap object."""

    m = Basemap(llcrnrlon=lon1, llcrnrlat=lat1, urcrnrlon=lon2, urcrnrlat=lat2)
    m.drawcoastlines()
    xticks = autoticks('lon', lon1, lon2)
    yticks = autoticks('lat', lat1, lat2)
    mapticks(xticks, yticks)
    plt.draw()
    return m

# ----------------------------------------------------------------------
def pcolor_latlon(data, lat=None, lon=None, m=None, cmap='RdBu_r',
                  axlims=(-90, 90, 0, 360)):
    """Create a pseudo-color plot of geo data.

    Parameters
    ----------
    data : ndarray or xray.DataArray
        Data to be plotted.
    lat, lon : ndarray, optional
        Latitude and longitude arrays.  Only used if data is an ndarray.
        If data is an xray.DataArray then lat = data['lat'] and
        lon = data['lon']
    m : Basemap object, optional
        Basemap to plot on.  If omitted, then a map is created with
        init_latlon().
    cmap : string or colormap object, optional
        Colormap to use.
    axlims : 4-tuple of ints or floats
        Lat-lon limits for map.

    Returns
    -------
    m : Basemap object
    """

    if isinstance(data, xray.DataArray):
        lat, lon = data['lat'], data['lon']
        vals = data.values
    else:
        vals = data

    # Use a masked array so that pcolormesh displays NaNs properly
    vals_plot = np.ma.array(vals, mask=np.isnan(vals))

    x, y = np.meshgrid(lon, lat)
    lat1, lat2, lon1, lon2 = axlims

    if m is None:
        m = init_latlon(lat1, lat2, lon1, lon2)
    m.pcolormesh(x, y, vals_plot, cmap=cmap, latlon=True)
    m.colorbar()
    plt.draw()
    return m

# ----------------------------------------------------------------------
def contourf_latlon(data, lat=None, lon=None, clev=None, m=None, cmap='RdBu_r',
                    symmetric=True, axlims=(-90, 90, 0, 360)):
    """Create a filled contour plot of geo data.

    Parameters
    ----------
    data : ndarray or xray.DataArray
        Data to be plotted.
    lat, lon : ndarray, optional
        Latitude and longitude arrays.  Only used if data is an ndarray.
        If data is an xray.DataArray then lat = data['lat'] and
        lon = data['lon']
    clev : scalar or array of ints or floats, optional
        Contour spacing (scalar) or contour levels (array).
    m : Basemap object, optional
        Basemap to plot on.  If omitted, then a map is created with
        init_latlon().
    cmap : string or colormap object, optional
        Colormap to use.
    symmetric : bool, optional
        Set contour levels to be symmetric about zero.
    axlims : 4-tuple of ints or floats
        Lat-lon limits for map.

    Returns
    -------
    m : Basemap object
    """

    if isinstance(data, xray.DataArray):
        lat, lon = data['lat'], data['lon']

    if isinstance(clev, float) or isinstance(clev, int):
        # Define contour levels from selected interval spacing
        clev = clevels(data, clev, symmetric=symmetric)

    lat1, lat2, lon1, lon2 = axlims
    x, y = np.meshgrid(lon, lat)

    if m is None:
        m = init_latlon(lat1, lat2, lon1, lon2)
    if clev is None:
        m.contourf(x, y, data, cmap=cmap, latlon=True)
    else:
        m.contourf(x,y, data, clev, cmap=cmap, latlon=True)
    m.colorbar()
    plt.draw()
    return m

# ----------------------------------------------------------------------
def contour_latlon(data, lat=None, lon=None, clev=None, m=None, colors='black',
                   linewidths=2.0, axlims=(-90, 90, 0, 360)):
    """Create a contour line plot of geo data.

    Parameters
    ----------
    data : ndarray or xray.DataArray
        Data to be plotted.
    lat, lon : ndarray, optional
        Latitude and longitude arrays.  Only used if data is an ndarray.
        If data is an xray.DataArray then lat = data['lat'] and
        lon = data['lon']
    clev : scalar or array of ints or floats, optional
        Contour spacing (scalar) or contour levels (array).
    m : Basemap object, optional
        Basemap to plot on.  If omitted, then a map is created with
        init_latlon().
    colors : string or mpl_color, optional
        Contour line color(s).
    linewidths : int or float, optional
        Line width for contour lines
    axlims : 4-tuple of ints or floats
        Lat-lon limits for map.

    Returns
    -------
    m : Basemap object
    """

    if isinstance(data, xray.DataArray):
        lat, lon = data['lat'], data['lon']

    if isinstance(clev, float) or isinstance(clev, int):
        # Define contour levels from selected interval spacing
        clev = clevels(data, clev)

    lat1, lat2, lon1, lon2 = axlims
    x, y = np.meshgrid(lon, lat)

    if m is None:
        m = init_latlon(lat1, lat2, lon1, lon2)
    if clev is None:
        m.contour(x, y, data, colors=colors, linewidths=linewidths,
                  latlon=True)
    else:
        m.contour(x,y, data, clev, colors=colors, linewidths=linewidths,
                  latlon=True)
    plt.draw()
    return m

# ----------------------------------------------------------------------
def init_latpres(latmin=-90, latmax=90, pmin=0, pmax=1000, topo_ps=None,
                 topo_lat=None, topo_clr='black', p_units='hPa',
                 lattick_width=None, ptick_width=None):
    """Initialize a latitude-pressure plot.

    Parameters
    ----------
    latmin, latmax, pmin, pmax : int or float, optional
        Axes limits.
    topo_ps, topo_lat : ndarray or list of floats, optional
        Surface pressure profile to plot for topography.
    topo_clr : string or mpl_color, optional
        Color to fill topographic profile.
    p_units : string, optional
        Units of pressure for y-axis and surface pressure profile.
    lattick_width, ptick_width : int or float, optional
        Spacing for latitude and pressure ticks.
    """

    xticks = autoticks('lat', latmin, latmax, lattick_width)
    yticks = autoticks('pres', pmin, pmax, ptick_width)
    plt.xlim(latmin, latmax)
    plt.xticks(xticks, latlon_labels(xticks, latlon='lat', fmt='%.0f'))
    plt.ylim(pmin, pmax)
    plt.yticks(yticks)
    plt.gca().invert_yaxis()
    plt.xlabel('Latitude')
    plt.ylabel('Pressure (' + p_units + ')')

    if isinstance(topo_ps, np.ndarray) or isinstance(topo_ps, list):
        plt.fill_between(topo_lat, pmax, topo_ps, color=topo_clr)

    plt.draw()

# ----------------------------------------------------------------------
def contour_latpres(data, lat=None, plev=None, clev=None, init=True,
                    colors='black', topo=None, topo_clr='black', p_units='hPa',
                    axlims=(-90, 90, 0, 1000), lattick_width=None,
                    ptick_width=None, omitzero=False, zerolinewidth=2):
    """
    Plot contour lines in latitude-pressure plane

    Parameters
    ----------
    data : ndarray or xray.DataArray
        Data to be contoured.
    lat : ndarray, optional
        Latitude (degrees).  If data is an xray.DataArray, lat is
        extracted from data['lat'].
    plev : ndarray, optional
        Pressure levels.  If data is an xray.DataArray, plev is
        extracted from data['plev'].
    clev : float or ndarray, optional
        Contour levels (ndarray) or spacing interval (float)
    init : bool, optional
        If True, initialize plot axes and topography with init_latpres().
    colors: string or mpl_color, optional
        Contour line color.
    topo : ndarray or xray.DataArray, optional
        Topography to shade (average surface pressure in units of plev).
        If topo is an ndarray, it must be on the same latitude grid as
        data.  If topo is an xray.DataArray, its latitude grid is
        extracted from topo['lat']. Only used if init is True.
    topo_clr : string or mpl_color, optional
        Color to fill topographic profile. Only used if init is True.
    p_units : string, optional
        Units for pressure axis label.  Only used if init is True.
    axlims : 4-tuple of floats or ints
        Axis limits (latmin, latmax, pmin, pmax).  Only used if init is True.
    lattick_width, ptick_width : int or float, optional
        Spacing for latitude and pressure ticks.  Only used if init is True.
    omitzero : bool, optional
        If True, omit zero contour.
    zerolinewidth : int or float, optional
        Include zero contour with specified line width.
    """

    # Data to be contoured
    if isinstance(data, xray.DataArray):
        lat, plev = data['lat'], data['plev']

    # Initialize plot
    if init:

        # Topography data
        if isinstance(topo, np.ndarray) or isinstance(topo, list):
            topo_ps, topo_lat = topo, lat
        elif isinstance(topo, xray.DataArray):
            topo_ps, topo_lat = topo.values, topo['lat']
        else:
            topo_ps, topo_lat = None

        # Initialize axes and plot topography
        latmin, latmax, pmin, pmax = axlims
        init_latpres(latmin, latmax, pmin, pmax, topo_ps=topo_ps,
                     topo_lat=topo_lat, topo_clr=topo_clr, p_units=p_units,
                     lattick_width=lattick_width, ptick_width=ptick_width)

    # Contour levels
    if isinstance(clev, float) or isinstance(clev, int):
        # Define contour levels from selected interval spacing
        clev = clevels(data, clev, omitzero=omitzero)

    # Plot contours
    y, z = np.meshgrid(lat, plev)
    if clev is None:
        plt.contour(y, z, data, colors=colors)
    else:
        plt.contour(y, z, data, clev, colors=colors)

    # Zero contour
    if not omitzero and zerolinewidth > 0:
        plt.contour(y, z, data, 0, colors=colors, linewidths=zerolinewidth)

    plt.draw()

# ----------------------------------------------------------------------

def pcolor_latpres():
    """Plot pseudo-color of data in latitude-pressure plane."""

def contourf_latpres():
    """Plot filled contours of data in latitude-pressure plane."""

def contourf_timelat():
    """Plot filled contours of data in time-latitude plane."""

"""
TO DO:

mapticks - change tick label formatting to 0-360E rather than 180W to 180E
        -> Define a function to return the formatted ticks and use fmt
           keyword argument in m.drawmeridians

mapaxes(m, axlims, xticks, yticks) - adjust limits, ticks and tick labels of
        existing map (might have to create new basemap object to do this)

contour_latpres - format dictionaries for contours and topography,
    - zero contours treated separately - omit or make different color/width
"""
<|endoftext|>


<commit_before>'''
Utility functions for plotting atmospheric data.
'''

import math
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import xray
from atmos.utils import print_if

'''
TO DO:
clevels - omit zero option

mapticks - change tick label formatting to 0-360E rather than 180W to 180E
        -> Define a function to return the formatted ticks and use fmt
           keyword argument in m.drawmeridians

contour_latpres - format dictionaries for contours and topography,
    - zero contours treated separately - omit or make different color/width
'''

# ----------------------------------------------------------------------
def autoticks(axtype, axmin, axmax, width=None, nmax=8):
    '''
    Return an array of sensible automatic tick positions for geo data.

    Parameters
    ----------
    axtype : {'lon', 'lat', 'pres'}
        Type of axis - longitude, latitude or pressure level
    axmin, axmax : float or int
        Axis limits
    width : float, optional
        Spacing of ticks.  Omit to let the function set an auto value.
    nmax : int, optional
        Maximum number of ticks.  This is ignored if width is specified.

    Returns
    -------
    ticks : ndarray
        Array of tick positions
    '''

    if not width:
        # Set the width between ticks
        diff = axmax - axmin
        if axtype.lower() == 'lon' or axtype.lower() == 'lat':
            wlist = [10, 15, 30, 60]
        elif axtype.lower() == 'pres':
            wlist = [50, 100, 200]
        else:
            raise ValueError('Invalid axtype: ' + axtype)

        for w in wlist:
            n1 = math.ceil(float(axmin)/w)
            n2 = math.floor(float(axmax)/w)
            ntick = n2 - n1 + 1
            if ntick <= nmax:
                width = w
                break
    else:
        # Use the width specified in input
        n1 = math.ceil(float(axmin)/width)
        n2 = math.floor(float(axmax)/width)

    # Set the ticks
    ticks = np.arange(n1*width, (n2+0.1)*width, width)
    return ticks

# ----------------------------------------------------------------------
def mapticks(m, xticks, yticks, labels=['left', 'bottom'],
             gridlinewidth=0.0):
    """Add nicely formatted ticks to basemap."""

    label_dict = {'left' : 0, 'right' : 1, 'top' : 2, 'bottom' : 3}
    lvec = [0, 0, 0, 0]
    for nm in labels:
        lvec[label_dict[nm]] = 1

    plt.xticks(xticks, [])
    plt.yticks(yticks, [])
    m.drawmeridians(xticks, labels=lvec, labelstyle='E',
                    linewidth=gridlinewidth)
    m.drawparallels(yticks, labels=lvec, labelstyle='N/S',
                    linewidth=gridlinewidth)

# ----------------------------------------------------------------------
def clevels(data, cint, posneg='both', symmetric=False):
    '''
    Return array of contour levels spaced by a given interval.

    Parameters
    ----------
    data : ndarray
        Data to be contoured
    cint : float
        Spacing of contour intervals
    posneg : {'both', 'pos', 'neg'}, optional
        Return all contours or only pos/neg
    symmetric : bool, optional
        Return contour levels symmetric about zero

    Returns
    -------
    clev: ndarray
        Array of contour levels
    '''

    # Define max and min contour levels
    if symmetric:
        cabs = math.ceil(abs(data).max() / cint) * cint
        cmin, cmax = -cabs, cabs
    else:
        cmin = math.floor(data.min() / cint) * cint
        cmax = math.ceil(data.max() / cint) * cint
    if posneg == 'pos':
        cmin = 0
    elif posneg == 'neg':
        cmax = 0

    # Define contour levels, making sure to include the endpoint
    clev = np.arange(cmin, cmax + 0.1*cint, cint)
    return clev

# ----------------------------------------------------------------------
def init_lonlat(lon1=0, lon2=360, lat1=-90, lat2=90, labels=['left', 'bottom'],
                gridlinewidth=0.0):
    """Initialize lon-lat plot."""

    m = Basemap(llcrnrlon=lon1, llcrnrlat=lat1, urcrnrlon=lon2, urcrnrlat=lat2)
    m.drawcoastlines()
    xticks = autoticks('lon', lon1, lon2)
    yticks = autoticks('lat', lat1, lat2)
    mapticks(m, xticks, yticks, labels=labels, gridlinewidth=gridlinewidth)
    plt.draw()
    return m

# ----------------------------------------------------------------------
def pcolor_lonlat(lon, lat, data, cmap='RdBu_r', axlims=(0, 360, -90, 90),
                  axlabels=['left', 'bottom'], gridlinewidth=0.0):
    """Create a pseudo-color plot of geo data."""

    lon1, lon2, lat1, lat2 = axlims
    x, y = np.meshgrid(lon, lat)
    m = init_lonlat(lon1, lon2, lat1, lat2, labels=axlabels,
                    gridlinewidth=gridlinewidth)
    m.pcolormesh(x, y, data, cmap=cmap)
    m.colorbar()
    plt.draw()
    return m

# ----------------------------------------------------------------------
def contourf_lonlat(lon, lat, data, clev=None, cmap='RdBu_r',
                  axlims=(0, 360, -90, 90), axlabels=['left', 'bottom'],
                  gridlinewidth=0.0):
    """Create a filled contour plot of geo data."""

    if isinstance(clev, float) or isinstance(clev, int):
        # Define contour levels from selected interval spacing
        clev = clevels(data, clev)

    lon1, lon2, lat1, lat2 = axlims
    x, y = np.meshgrid(lon, lat)
    m = init_lonlat(lon1, lon2, lat1, lat2, labels=axlabels,
                    gridlinewidth=gridlinewidth)

    if clev is None:
        m.contourf(x, y, data, cmap=cmap)
    else:
        m.contourf(x,y, data, clev, cmap=cmap)
    m.colorbar()
    plt.draw()
    return m

# ----------------------------------------------------------------------
def contour_latpres(lat, pres, data, clev, c_color='black', topo=None):
    '''
    Plot contour lines in latitude-pressure plane

    Parameters
    ----------
    lat : ndarray
        Latitude (degrees)
    pres : ndarray
        Pressure levels (hPa)
    data : ndarray
        Data to be contoured
    clev : float or ndarray
        Contour levels (ndarray) or spacing interval (float)
    c_color: string or mpl_color, optional
        Contour line color
    topo : ndarray, optional
        Topography to shade (average surface pressure in units of pres)
    '''

    # Contour levels
    if not isinstance(clev, list) and not isinstance(clev, np.ndarray):
        clev = clevels(data, clev)

    # Grid for plotting
    y, z = np.meshgrid(lat, pres)

    # Plot contours
    pmin, pmax = 0, 1000
    if isinstance(topo, np.ndarray) or isinstance(topo, list):
        plt.fill_between(lat, pmax, topo, color='black')
    plt.contour(y, z, data, clev, colors=c_color)
    plt.ylim(pmin, pmax)
    plt.gca().invert_yaxis()
    plt.xticks(np.arange(-90, 90, 30))
    plt.xlabel('Latitude')
    plt.ylabel('Pressure (hPa)')
    plt.draw()
<commit_msg>Added contour_lonlat() for contour line plots<commit_after>'''
Utility functions for plotting atmospheric data.
'''

import math
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import xray
from atmos.utils import print_if

'''
TO DO:
clevels - omit zero option

mapticks - change tick label formatting to 0-360E rather than 180W to 180E
        -> Define a function to return the formatted ticks and use fmt
           keyword argument in m.drawmeridians

mapaxes(m, axlims, xticks, yticks) - adjust limits, ticks and tick labels of
        existing map (might have to create new basemap object to do this)

contour_latpres - format dictionaries for contours and topography,
    - zero contours treated separately - omit or make different color/width
'''

# ----------------------------------------------------------------------
def autoticks(axtype, axmin, axmax, width=None, nmax=8):
    '''
    Return an array of sensible automatic tick positions for geo data.

    Parameters
    ----------
    axtype : {'lon', 'lat', 'pres'}
        Type of axis - longitude, latitude or pressure level
    axmin, axmax : float or int
        Axis limits
    width : float, optional
        Spacing of ticks.  Omit to let the function set an auto value.
    nmax : int, optional
        Maximum number of ticks.  This is ignored if width is specified.

    Returns
    -------
    ticks : ndarray
        Array of tick positions
    '''

    if not width:
        # Set the width between ticks
        diff = axmax - axmin
        if axtype.lower() == 'lon' or axtype.lower() == 'lat':
            wlist = [10, 15, 30, 60]
        elif axtype.lower() == 'pres':
            wlist = [50, 100, 200]
        else:
            raise ValueError('Invalid axtype: ' + axtype)

        for w in wlist:
            n1 = math.ceil(float(axmin)/w)
            n2 = math.floor(float(axmax)/w)
            ntick = n2 - n1 + 1
            if ntick <= nmax:
                width = w
                break
    else:
        # Use the width specified in input
        n1 = math.ceil(float(axmin)/width)
        n2 = math.floor(float(axmax)/width)

    # Set the ticks
    ticks = np.arange(n1*width, (n2+0.1)*width, width)
    return ticks

# ----------------------------------------------------------------------
def mapticks(m, xticks, yticks, labels=['left', 'bottom'],
             gridlinewidth=0.0):
    """Add nicely formatted ticks to basemap."""

    label_dict = {'left' : 0, 'right' : 1, 'top' : 2, 'bottom' : 3}
    lvec = [0, 0, 0, 0]
    for nm in labels:
        lvec[label_dict[nm]] = 1

    plt.xticks(xticks, [])
    plt.yticks(yticks, [])
    m.drawmeridians(xticks, labels=lvec, labelstyle='E',
                    linewidth=gridlinewidth)
    m.drawparallels(yticks, labels=lvec, labelstyle='N/S',
                    linewidth=gridlinewidth)

# ----------------------------------------------------------------------
def clevels(data, cint, posneg='both', symmetric=False):
    '''
    Return array of contour levels spaced by a given interval.

    Parameters
    ----------
    data : ndarray
        Data to be contoured
    cint : float
        Spacing of contour intervals
    posneg : {'both', 'pos', 'neg'}, optional
        Return all contours or only pos/neg
    symmetric : bool, optional
        Return contour levels symmetric about zero

    Returns
    -------
    clev: ndarray
        Array of contour levels
    '''

    # Define max and min contour levels
    if symmetric:
        cabs = math.ceil(abs(data).max() / cint) * cint
        cmin, cmax = -cabs, cabs
    else:
        cmin = math.floor(data.min() / cint) * cint
        cmax = math.ceil(data.max() / cint) * cint
    if posneg == 'pos':
        cmin = 0
    elif posneg == 'neg':
        cmax = 0

    # Define contour levels, making sure to include the endpoint
    clev = np.arange(cmin, cmax + 0.1*cint, cint)
    return clev

# ----------------------------------------------------------------------
def init_lonlat(lon1=0, lon2=360, lat1=-90, lat2=90, labels=['left', 'bottom'],
                gridlinewidth=0.0):
    """Initialize lon-lat plot."""

    m = Basemap(llcrnrlon=lon1, llcrnrlat=lat1, urcrnrlon=lon2, urcrnrlat=lat2)
    m.drawcoastlines()
    xticks = autoticks('lon', lon1, lon2)
    yticks = autoticks('lat', lat1, lat2)
    mapticks(m, xticks, yticks, labels=labels, gridlinewidth=gridlinewidth)
    plt.draw()
    return m

# ----------------------------------------------------------------------
def pcolor_lonlat(lon, lat, data, m=None, cmap='RdBu_r',
                  axlims=(0, 360, -90, 90), axlabels=['left', 'bottom'],
                  gridlinewidth=0.0):
    """Create a pseudo-color plot of geo data."""

    lon1, lon2, lat1, lat2 = axlims
    x, y = np.meshgrid(lon, lat)
    if m is None:
        m = init_lonlat(lon1, lon2, lat1, lat2, labels=axlabels,
                        gridlinewidth=gridlinewidth)
    m.pcolormesh(x, y, data, cmap=cmap, latlon=True)
    m.colorbar()
    plt.draw()
    return m

# ----------------------------------------------------------------------
def contourf_lonlat(lon, lat, data, clev=None, m=None, cmap='RdBu_r',
                    symmetric=True, axlims=(0, 360, -90, 90),
                    axlabels=['left', 'bottom'], gridlinewidth=0.0):
    """Create a filled contour plot of geo data."""

    if isinstance(clev, float) or isinstance(clev, int):
        # Define contour levels from selected interval spacing
        clev = clevels(data, clev, symmetric=symmetric)

    lon1, lon2, lat1, lat2 = axlims
    x, y = np.meshgrid(lon, lat)

    if m is None:
        m = init_lonlat(lon1, lon2, lat1, lat2, labels=axlabels,
                        gridlinewidth=gridlinewidth)
    if clev is None:
        m.contourf(x, y, data, cmap=cmap, latlon=True)
    else:
        m.contourf(x,y, data, clev, cmap=cmap, latlon=True)
    m.colorbar()
    plt.draw()
    return m

# ----------------------------------------------------------------------
def contour_lonlat(lon, lat, data, clev=None, m=None,
                   colors='black', linewidths=2.0,
                   axlims=(0, 360, -90, 90), axlabels=['left', 'bottom'],
                   gridlinewidth=0.0):
    """Create a contour line plot of geo data."""

    if isinstance(clev, float) or isinstance(clev, int):
        # Define contour levels from selected interval spacing
        clev = clevels(data, clev)

    lon1, lon2, lat1, lat2 = axlims
    x, y = np.meshgrid(lon, lat)

    if m is None:
        m = init_lonlat(lon1, lon2, lat1, lat2, labels=axlabels,
                        gridlinewidth=gridlinewidth)
    if clev is None:
        m.contour(x, y, data, colors=colors, linewidths=linewidths,
                  latlon=True)
    else:
        m.contour(x,y, data, clev, colors=colors, linewidths=linewidths,
                  latlon=True)
    plt.draw()
    return m

# ----------------------------------------------------------------------
def contour_latpres(lat, pres, data, clev, c_color='black', topo=None):
    '''
    Plot contour lines in latitude-pressure plane

    Parameters
    ----------
    lat : ndarray
        Latitude (degrees)
    pres : ndarray
        Pressure levels (hPa)
    data : ndarray
        Data to be contoured
    clev : float or ndarray
        Contour levels (ndarray) or spacing interval (float)
    c_color: string or mpl_color, optional
        Contour line color
    topo : ndarray, optional
        Topography to shade (average surface pressure in units of pres)
    '''

    # Contour levels
    if not isinstance(clev, list) and not isinstance(clev, np.ndarray):
        clev = clevels(data, clev)

    # Grid for plotting
    y, z = np.meshgrid(lat, pres)

    # Plot contours
    pmin, pmax = 0, 1000
    if isinstance(topo, np.ndarray) or isinstance(topo, list):
        plt.fill_between(lat, pmax, topo, color='black')
    plt.contour(y, z, data, clev, colors=c_color)
    plt.ylim(pmin, pmax)
    plt.gca().invert_yaxis()
    plt.xticks(np.arange(-90, 90, 30))
    plt.xlabel('Latitude')
    plt.ylabel('Pressure (hPa)')
    plt.draw()
<|endoftext|>


<commit_before>import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)

GPIO.setup(14, GPIO.OUT)

count = 0
while (count < 3):
   print 'The count is:', count
   count = count + 1
   GPIO.output(14, True)
   print "Start : %s" % time.ctime()
   time.sleep(2)
   GPIO.output(14, False)
   time.sleep(2)
   print "End : %s" % time.ctime()

GPIO.cleanup()

print "Good bye!"
print "========="<commit_msg>Test again<commit_after>import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)

GPIO.setup(14, GPIO.OUT)

count = 0
while (count < 3):
   print 'The count is:', count
   count = count + 1
   GPIO.output(14, True)
   print "Start : %s" % time.ctime()
   time.sleep(2)
   GPIO.output(14, False)
   time.sleep(2)
   print "End : %s" % time.ctime()

GPIO.cleanup()

print "Good bye!"
print "========="
print "========="<|endoftext|>


<commit_before>from rest_framework.response import Response

from threepio import logger

from core.query import only_current_provider
from core.models.group import Group
from core.models.identity import Identity as CoreIdentity
from core.models.provider import Provider

from api import failure_response, invalid_provider, invalid_provider_identity,
from api.v1.serializers import IdentitySerializer, IdentityDetailSerializer
from api.v1.views.base import AuthAPIView

def get_provider(user, provider_uuid):
    """
    Given the (request) user and a provider uuid,
    return None or an Active provider
    """
    try:
        group = Group.objects.get(name=user.username)
    except Group.DoesNotExist:
        logger.warn("Group %s DoesNotExist" % user.username)
        return None

    try:
        provider = group.current_providers.get(uuid=provider_uuid)
        return provider
    except Provider.DoesNotExist:
        logger.warn("Provider %s DoesNotExist for User:%s in Group:%s"
                    % (provider_uuid, user, group))
        return None

def get_identity_list(user, provider=None):
    """
    Given the (request) user
    return all identities on all active providers
    """
    try:
        group = Group.objects.get(name=user.username)
        if provider:
            identity_list = group.current_identities.filter(
                provider=provider)
        else:
            identity_list = group.current_identities.all()
        return identity_list
    except Group.DoesNotExist:
        logger.warn("Group %s DoesNotExist" % user.username)
        return None
    except CoreIdentity.DoesNotExist:
        logger.warn("Identity %s DoesNotExist" % identity_uuid)
        return None

def get_identity(user, identity_uuid):
    """
    Given the (request) user and an identity uuid,
    return None or an Active Identity
    """
    try:
        identity_list = get_identity_list(user)
        if not identity_list:
            raise CoreIdentity.DoesNotExist(
                "No identities found for user %s" %
                user.username)
        identity = identity_list.get(uuid=identity_uuid)
        return identity
    except CoreIdentity.DoesNotExist:
        logger.warn("Identity %s DoesNotExist" % identity_uuid)
        return None

class IdentityDetail(AuthAPIView):

    """
    The identity contains every credential necessary for atmosphere
    to connect 'The Provider' with a specific user.
    These credentials can vary from provider to provider.
    """

    def get(self, request, identity_uuid):
        """
        Authentication Required, all identities available to the user
        """
        identity = get_identity(request.user, identity_uuid)
        if not identity:
            return failure_response(
                status.HTTP_404_NOT_FOUND,
                "The requested Identity ID %s was not found on an active"
                "provider" % identity_uuid)
        serialized_data = IdentityDetailSerializer(identity).data
        return Response(serialized_data)

class IdentityDetailList(AuthAPIView):

    """
    The identity contains every credential necessary for atmosphere
    to connect 'The Provider' with a specific user.
    These credentials can vary from provider to provider.
    """

    def get(self, request):
        """
        Authentication Required, all identities available to the user.
        """
        identities = get_identity_list(request.user)
        serialized_data = IdentityDetailSerializer(identities, many=True).data
        return Response(serialized_data)

class IdentityList(AuthAPIView):

    """
    The identity contains every credential necessary for atmosphere
    to connect 'The Provider' with a specific user.
    These credentials can vary from provider to provider.
    """

    def get(self, request, provider_uuid, format=None):
        """
        List of identities for the user on the selected provider.
        """
        provider = get_provider(request.user, provider_uuid)
        if not provider:
            return invalid_provider(provider_uuid)

        identities = get_identity_list(request.user, provider)
        serialized_data = IdentitySerializer(identities, many=True).data
        return Response(serialized_data)

class Identity(AuthAPIView):

    """
    The identity contains every credential necessary for atmosphere
    to connect 'The Provider' with a specific user.
    These credentials can vary from provider to provider.
    """

    def get(self, request, provider_uuid, identity_uuid, format=None):
        """
        Authentication Required, Get details for a specific identity.
        """
        provider = get_provider(request.user, provider_uuid)
        identity = get_identity(request.user, identity_uuid)
        if not provider or not identity:
            return invalid_provider_identity(provider_uuid, identity_uuid)
        serialized_data = IdentitySerializer(identity).data
        logger.debug(type(serialized_data))
        return Response(serialized_data)
<commit_msg>SyntaxErrors found in file<commit_after>from rest_framework import status
from rest_framework.response import Response

from threepio import logger

from core.models.group import Group
from core.models.identity import Identity as CoreIdentity
from core.models.provider import Provider

from api import failure_response, invalid_provider, invalid_provider_identity
from api.v1.serializers import IdentitySerializer, IdentityDetailSerializer
from api.v1.views.base import AuthAPIView

def get_provider(user, provider_uuid):
    """
    Given the (request) user and a provider uuid,
    return None or an Active provider
    """
    try:
        group = Group.objects.get(name=user.username)
    except Group.DoesNotExist:
        logger.warn("Group %s DoesNotExist" % user.username)
        return None

    try:
        provider = group.current_providers.get(uuid=provider_uuid)
        return provider
    except Provider.DoesNotExist:
        logger.warn("Provider %s DoesNotExist for User:%s in Group:%s"
                    % (provider_uuid, user, group))
        return None

def get_identity_list(user, provider=None):
    """
    Given the (request) user
    return all identities on all active providers
    """
    try:
        group = Group.objects.get(name=user.username)
        if provider:
            identity_list = group.current_identities.filter(
                provider=provider)
        else:
            identity_list = group.current_identities.all()
        return identity_list
    except Group.DoesNotExist:
        logger.warn("Group %s DoesNotExist" % user.username)
        return None
    except CoreIdentity.DoesNotExist:
        logger.warn("Identity DoesNotExist for user %s" % user.username)
        return None

def get_identity(user, identity_uuid):
    """
    Given the (request) user and an identity uuid,
    return None or an Active Identity
    """
    try:
        identity_list = get_identity_list(user)
        if not identity_list:
            raise CoreIdentity.DoesNotExist(
                "No identities found for user %s" %
                user.username)
        identity = identity_list.get(uuid=identity_uuid)
        return identity
    except CoreIdentity.DoesNotExist:
        logger.warn("Identity %s DoesNotExist" % identity_uuid)
        return None

class IdentityDetail(AuthAPIView):

    """
    The identity contains every credential necessary for atmosphere
    to connect 'The Provider' with a specific user.
    These credentials can vary from provider to provider.
    """

    def get(self, request, identity_uuid):
        """
        Authentication Required, all identities available to the user
        """
        identity = get_identity(request.user, identity_uuid)
        if not identity:
            return failure_response(
                status.HTTP_404_NOT_FOUND,
                "The requested Identity ID %s was not found on an active"
                "provider" % identity_uuid)
        serialized_data = IdentityDetailSerializer(identity).data
        return Response(serialized_data)

class IdentityDetailList(AuthAPIView):

    """
    The identity contains every credential necessary for atmosphere
    to connect 'The Provider' with a specific user.
    These credentials can vary from provider to provider.
    """

    def get(self, request):
        """
        Authentication Required, all identities available to the user.
        """
        identities = get_identity_list(request.user)
        serialized_data = IdentityDetailSerializer(identities, many=True).data
        return Response(serialized_data)

class IdentityList(AuthAPIView):

    """
    The identity contains every credential necessary for atmosphere
    to connect 'The Provider' with a specific user.
    These credentials can vary from provider to provider.
    """

    def get(self, request, provider_uuid, format=None):
        """
        List of identities for the user on the selected provider.
        """
        provider = get_provider(request.user, provider_uuid)
        if not provider:
            return invalid_provider(provider_uuid)

        identities = get_identity_list(request.user, provider)
        serialized_data = IdentitySerializer(identities, many=True).data
        return Response(serialized_data)

class Identity(AuthAPIView):

    """
    The identity contains every credential necessary for atmosphere
    to connect 'The Provider' with a specific user.
    These credentials can vary from provider to provider.
    """

    def get(self, request, provider_uuid, identity_uuid, format=None):
        """
        Authentication Required, Get details for a specific identity.
        """
        provider = get_provider(request.user, provider_uuid)
        identity = get_identity(request.user, identity_uuid)
        if not provider or not identity:
            return invalid_provider_identity(provider_uuid, identity_uuid)
        serialized_data = IdentitySerializer(identity).data
        logger.debug(type(serialized_data))
        return Response(serialized_data)
<|endoftext|>


<commit_before>import io
import sys

sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

import json
import os.path

from flask import Flask, abort

from common import file, page, console

rss = None
menu_list = None
page_name_list = list()
cache_page = dict()
template_config = None
app = Flask(__name__)

console.log("info", "Loading configuration")

system_config = json.loads(file.read_file("./config/system.json"))

if system_config["Author_Image"] == "" and system_config["Author_Name"] != "":
    import urllib.request

    r = {"entry": [{"hash": ""}]}
    console.log("info", "Get the Gravatar URL")
    try:
        r = urllib.request.urlopen(
            "https://en.gravatar.com/{0}.json".format(system_config["Author_Name"])).read().decode('utf-8')
    except urllib2.HTTPError:
        console.log("Error", "Get the error")
        pass
    req = json.loads(r)
    gravatar_hash = req["entry"][0]["hash"]
    system_config["Author_Image"] = "https://secure.gravatar.com/avatar/{0}".format(gravatar_hash)
    file.write_file("./config/system.json", json.dumps(system_config))

page_list = json.loads(file.read_file("./config/page.json"))

if os.path.exists("./config/menu.json"):
    menu_list = json.loads(file.read_file("./config/menu.json"))

for item in page_list:
    page_name_list.append(item["name"])

if os.path.exists("./document/rss.xml"):
    rss = file.read_file("document/rss.xml")

if os.path.exists("./templates/{0}/config.json".format(system_config["Theme"])):
    template_config = json.loads(file.read_file("./templates/{0}/config.json".format(system_config["Theme"])))

system_config["API_Password"] = None

console.log("Success", "load the configuration file successfully")

# Subscribe
@app.route("/rss")
@app.route("/feed")
def load_rss():
    if rss is None:
        abort(404)
    return rss, 200, {'Content-Type': 'text/xml; charset=utf-8'}

@app.route("/static/")
def static_file():
    abort(400)

@app.route("/")
@app.route("/index")
@app.route("/index/")
@app.route('/index/p/<int:page_index>')
@app.route('/index/p/<int:page_index>/')
def index_route(page_index=1):
    result = None
    page_url = "/index/p/{0}".format(page_index)
    if page_url in cache_page:
        console.log("info", "Get cache Success: {0}".format(page_url))
        return cache_page[page_url]

    console.log("info", "Trying to build: {0}".format(page_url))

    if result is None:
        result, row = page.build_index(page_index, system_config, page_list, menu_list, False, template_config)

    console.log("info", "Writing to cache: {0}".format(page_url))
    if len(cache_page) >= 100:
        page_keys = sorted(cache_page.keys())
        console.log("info", "Delete cache: {0}".format(page_keys[0]))
        del cache_page[page_keys[0]]
    cache_page[page_url] = result
    console.log("Success", "Get success: {0}".format(page_url))

    return result

@app.route("/post/<file_name>")
@app.route("/post/<file_name>/")
def post_route(file_name=None):
    result = None
    if file_name is None or not os.path.exists("document/{0}.md".format(file_name)):
        abort(404)
    if page_url in cache_page:
        console.log("info", "Get cache Success: {0}".format(page_url))
        return cache_page[page_url]
    if result is None:
        add_head_list = map(add_post_header, page_list)
        result = page.build_page(file_name, system_config, add_head_list, page_name_list, menu_list,
                                 False,
                                 template_config)
    console.log("info", "Writing to cache: {0}".format(page_url))
    if len(cache_page) >= 100:
        page_keys = sorted(cache_page.keys())
        console.log("info", "Delete cache: {0}".format(page_keys[0]))
        del cache_page[page_keys[0]]
    cache_page[page_url] = result
    console.log("Success", "Get success: {0}".format(page_url))

    return result

def add_post_header(list_item):
    list_item["name"] = "post/{0}".format(list_item["name"])
    return list_item
<commit_msg>添加list对象<commit_after>import io
import sys

sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

import json
import os.path

from flask import Flask, abort

from common import file, page, console

rss = None
menu_list = None
page_name_list = list()
cache_page = dict()
template_config = None
app = Flask(__name__)

console.log("info", "Loading configuration")

system_config = json.loads(file.read_file("./config/system.json"))

if system_config["Author_Image"] == "" and system_config["Author_Name"] != "":
    import urllib.request

    r = {"entry": [{"hash": ""}]}
    console.log("info", "Get the Gravatar URL")
    try:
        r = urllib.request.urlopen(
            "https://en.gravatar.com/{0}.json".format(system_config["Author_Name"])).read().decode('utf-8')
    except urllib2.HTTPError:
        console.log("Error", "Get the error")
        pass
    req = json.loads(r)
    gravatar_hash = req["entry"][0]["hash"]
    system_config["Author_Image"] = "https://secure.gravatar.com/avatar/{0}".format(gravatar_hash)
    file.write_file("./config/system.json", json.dumps(system_config))

page_list = json.loads(file.read_file("./config/page.json"))

if os.path.exists("./config/menu.json"):
    menu_list = json.loads(file.read_file("./config/menu.json"))

for item in page_list:
    page_name_list.append(item["name"])

if os.path.exists("./document/rss.xml"):
    rss = file.read_file("document/rss.xml")

if os.path.exists("./templates/{0}/config.json".format(system_config["Theme"])):
    template_config = json.loads(file.read_file("./templates/{0}/config.json".format(system_config["Theme"])))

system_config["API_Password"] = None

console.log("Success", "load the configuration file successfully")

# Subscribe
@app.route("/rss")
@app.route("/feed")
def load_rss():
    if rss is None:
        abort(404)
    return rss, 200, {'Content-Type': 'text/xml; charset=utf-8'}

@app.route("/static/")
def static_file():
    abort(400)

@app.route("/")
@app.route("/index")
@app.route("/index/")
@app.route('/index/p/<int:page_index>')
@app.route('/index/p/<int:page_index>/')
def index_route(page_index=1):
    result = None
    page_url = "/index/p/{0}".format(page_index)
    if page_url in cache_page:
        console.log("info", "Get cache Success: {0}".format(page_url))
        return cache_page[page_url]

    console.log("info", "Trying to build: {0}".format(page_url))

    if result is None:
        result, row = page.build_index(page_index, system_config, page_list, menu_list, False, template_config)

    console.log("info", "Writing to cache: {0}".format(page_url))
    if len(cache_page) >= 100:
        page_keys = sorted(cache_page.keys())
        console.log("info", "Delete cache: {0}".format(page_keys[0]))
        del cache_page[page_keys[0]]
    cache_page[page_url] = result
    console.log("Success", "Get success: {0}".format(page_url))

    return result

@app.route("/post/<file_name>")
@app.route("/post/<file_name>/")
def post_route(file_name=None):
    result = None
    if file_name is None or not os.path.exists("document/{0}.md".format(file_name)):
        abort(404)
    if page_url in cache_page:
        console.log("info", "Get cache Success: {0}".format(page_url))
        return cache_page[page_url]
    if result is None:
        add_head_list = list(map(add_post_header, page_list))
        result = page.build_page(file_name, system_config, add_head_list, page_name_list, menu_list,
                                 False,
                                 template_config)
    console.log("info", "Writing to cache: {0}".format(page_url))
    if len(cache_page) >= 100:
        page_keys = sorted(cache_page.keys())
        console.log("info", "Delete cache: {0}".format(page_keys[0]))
        del cache_page[page_keys[0]]
    cache_page[page_url] = result
    console.log("Success", "Get success: {0}".format(page_url))

    return result

def add_post_header(list_item):
    list_item["name"] = "post/{0}".format(list_item["name"])
    return list_item
<|endoftext|>


<commit_before>import os

#### OS Specifics ####
ABS_WORK_DIR = os.path.join(os.getcwd(), "build")
BINARY_PATH = os.path.join(ABS_WORK_DIR, "firefox", "firefox.exe")
INSTALLER_PATH = os.path.join(ABS_WORK_DIR, "installer.zip")
XPCSHELL_NAME = 'xpcshell.exe'
DISABLE_SCREEN_SAVER = False
ADJUST_MOUSE_AND_SCREEN = True
#####
config = {
    ### BUILDBOT
    "buildbot_json_path": "buildprops.json",
    "exes": {
        'python': 'c:/mozilla-build/python27/python',
        'virtualenv': ['c:/mozilla-build/python27/python', 'c:/mozilla-build/buildbotve/virtualenv.py'],
        'hg': 'c:/mozilla-build/hg/hg',
    },
    ###
    "installer_path": INSTALLER_PATH,
    "binary_path": BINARY_PATH,
    "xpcshell_name": XPCSHELL_NAME,
    "virtualenv_path": 'c:/talos-slave/test/build/venv',
    "virtualenv_python_dll": 'c:/mozilla-build/python27/python27.dll',
    "simplejson_url": "http://build.mozilla.org/talos/zips/simplejson-2.2.1.tar.gz",
    "run_file_names": {
        "mochitest": "runtests.py",
        "reftest": "runreftest.py",
        "xpcshell": "runxpcshelltests.py"
    },
    "minimum_tests_zip_dirs": ["bin/*", "certs/*", "modules/*", "mozbase/*"],
    "specific_tests_zip_dirs": {
        "mochitest": ["mochitest/*"],
        "reftest": ["reftest/*", "jsreftest/*"],
        "xpcshell": ["xpcshell/*"]
    },
    "reftest_options": [
        "--appname=%(binary_path)s", "--utility-path=tests/bin",
        "--extra-profile-file=tests/bin/plugins", "--symbols-path=%(symbols_path)s"
    ],
    "mochitest_options": [
        "--appname=%(binary_path)s", "--utility-path=tests/bin",
        "--extra-profile-file=tests/bin/plugins", "--symbols-path=%(symbols_path)s",
        "--certificate-path=tests/certs", "--autorun", "--close-when-done",
        "--console-level=INFO"
    ],
    "xpcshell_options": [
        "--symbols-path=%(symbols_path)s"
    ],
    #local mochi suites
    "all_mochitest_suites":
    {
        "plain1": ["--total-chunks=5", "--this-chunk=1", "--chunk-by-dir=4"],
        "plain2": ["--total-chunks=5", "--this-chunk=2", "--chunk-by-dir=4"],
        "plain3": ["--total-chunks=5", "--this-chunk=3", "--chunk-by-dir=4"],
        "plain4": ["--total-chunks=5", "--this-chunk=4", "--chunk-by-dir=4"],
        "plain5": ["--total-chunks=5", "--this-chunk=5", "--chunk-by-dir=4"],
        "chrome": ["--chrome"],
        "browser-chrome": ["--browser-chrome"],
        "a11y": ["--a11y"],
        "plugins": ['--setpref=dom.ipc.plugins.enabled=false',
                    '--setpref=dom.ipc.plugins.enabled.x86_64=false',
                    '--ipcplugins']
    },
    #local reftest suites
    "all_reftest_suites": {
        "reftest": ["tests/reftest/tests/layout/reftests/reftest.list"],
        "crashtest": ["tests/reftest/tests/testing/crashtest/crashtests.list"],
        "jsreftest": ["--extra-profile-file=tests/jsreftest/tests/user.js", "tests/jsreftest/tests/jstests.list"],
    },
    "all_xpcshell_suites": {
        "xpcshell": ["--manifest=tests/xpcshell/tests/all-test-dirs.list",
        "%(abs_app_dir)s/" + XPCSHELL_NAME]
    },
    "run_cmd_checks_enabled": True,
    "preflight_run_cmd_suites": [
        # NOTE 'enabled' is only here while we have unconsolidated configs
        {
            "name": "disable_screen_saver",
            "cmd": ["xset", "s", "off", "s", "reset"],
            "architectures": ["32bit", "64bit"],
            "halt_on_failure": False,
            "enabled": DISABLE_SCREEN_SAVER
        },
        {
            "name": "run mouse & screen adjustment script",
            "cmd": [
                # when configs are consolidated this python path will only show
                # for windows.
                "C:\\mozilla-build\\python25\\python.exe", "../scripts/external_tools/mouse_and_screen_resolution.py",
                "--configuration-url",
                "http://hg.mozilla.org/%(branch)s/raw-file/%(revision)s/" +
                    "testing/machine-configuration.json"],
            "architectures": ["32bit"],
            "halt_on_failure": True,
            "enabled": ADJUST_MOUSE_AND_SCREEN
        },
    ],
    "repos": [{"repo": "http://hg.mozilla.org/build/tools",}],
    "minidump_stackwalk_path": "%(abs_work_dir)s/tools/breakpad/win32/minidump_stackwalk",
    "minidump_save_path": "%(abs_work_dir)s/../minidumps",
}
<commit_msg>bug 806651 - fix windows unittest minidump_stackwalk path. r=armenzg<commit_after>import os

#### OS Specifics ####
ABS_WORK_DIR = os.path.join(os.getcwd(), "build")
BINARY_PATH = os.path.join(ABS_WORK_DIR, "firefox", "firefox.exe")
INSTALLER_PATH = os.path.join(ABS_WORK_DIR, "installer.zip")
XPCSHELL_NAME = 'xpcshell.exe'
DISABLE_SCREEN_SAVER = False
ADJUST_MOUSE_AND_SCREEN = True
#####
config = {
    ### BUILDBOT
    "buildbot_json_path": "buildprops.json",
    "exes": {
        'python': 'c:/mozilla-build/python27/python',
        'virtualenv': ['c:/mozilla-build/python27/python', 'c:/mozilla-build/buildbotve/virtualenv.py'],
        'hg': 'c:/mozilla-build/hg/hg',
    },
    ###
    "installer_path": INSTALLER_PATH,
    "binary_path": BINARY_PATH,
    "xpcshell_name": XPCSHELL_NAME,
    "virtualenv_path": 'c:/talos-slave/test/build/venv',
    "virtualenv_python_dll": 'c:/mozilla-build/python27/python27.dll',
    "simplejson_url": "http://build.mozilla.org/talos/zips/simplejson-2.2.1.tar.gz",
    "run_file_names": {
        "mochitest": "runtests.py",
        "reftest": "runreftest.py",
        "xpcshell": "runxpcshelltests.py"
    },
    "minimum_tests_zip_dirs": ["bin/*", "certs/*", "modules/*", "mozbase/*"],
    "specific_tests_zip_dirs": {
        "mochitest": ["mochitest/*"],
        "reftest": ["reftest/*", "jsreftest/*"],
        "xpcshell": ["xpcshell/*"]
    },
    "reftest_options": [
        "--appname=%(binary_path)s", "--utility-path=tests/bin",
        "--extra-profile-file=tests/bin/plugins", "--symbols-path=%(symbols_path)s"
    ],
    "mochitest_options": [
        "--appname=%(binary_path)s", "--utility-path=tests/bin",
        "--extra-profile-file=tests/bin/plugins", "--symbols-path=%(symbols_path)s",
        "--certificate-path=tests/certs", "--autorun", "--close-when-done",
        "--console-level=INFO"
    ],
    "xpcshell_options": [
        "--symbols-path=%(symbols_path)s"
    ],
    #local mochi suites
    "all_mochitest_suites":
    {
        "plain1": ["--total-chunks=5", "--this-chunk=1", "--chunk-by-dir=4"],
        "plain2": ["--total-chunks=5", "--this-chunk=2", "--chunk-by-dir=4"],
        "plain3": ["--total-chunks=5", "--this-chunk=3", "--chunk-by-dir=4"],
        "plain4": ["--total-chunks=5", "--this-chunk=4", "--chunk-by-dir=4"],
        "plain5": ["--total-chunks=5", "--this-chunk=5", "--chunk-by-dir=4"],
        "chrome": ["--chrome"],
        "browser-chrome": ["--browser-chrome"],
        "a11y": ["--a11y"],
        "plugins": ['--setpref=dom.ipc.plugins.enabled=false',
                    '--setpref=dom.ipc.plugins.enabled.x86_64=false',
                    '--ipcplugins']
    },
    #local reftest suites
    "all_reftest_suites": {
        "reftest": ["tests/reftest/tests/layout/reftests/reftest.list"],
        "crashtest": ["tests/reftest/tests/testing/crashtest/crashtests.list"],
        "jsreftest": ["--extra-profile-file=tests/jsreftest/tests/user.js", "tests/jsreftest/tests/jstests.list"],
    },
    "all_xpcshell_suites": {
        "xpcshell": ["--manifest=tests/xpcshell/tests/all-test-dirs.list",
        "%(abs_app_dir)s/" + XPCSHELL_NAME]
    },
    "run_cmd_checks_enabled": True,
    "preflight_run_cmd_suites": [
        # NOTE 'enabled' is only here while we have unconsolidated configs
        {
            "name": "disable_screen_saver",
            "cmd": ["xset", "s", "off", "s", "reset"],
            "architectures": ["32bit", "64bit"],
            "halt_on_failure": False,
            "enabled": DISABLE_SCREEN_SAVER
        },
        {
            "name": "run mouse & screen adjustment script",
            "cmd": [
                # when configs are consolidated this python path will only show
                # for windows.
                "C:\\mozilla-build\\python25\\python.exe", "../scripts/external_tools/mouse_and_screen_resolution.py",
                "--configuration-url",
                "http://hg.mozilla.org/%(branch)s/raw-file/%(revision)s/" +
                    "testing/machine-configuration.json"],
            "architectures": ["32bit"],
            "halt_on_failure": True,
            "enabled": ADJUST_MOUSE_AND_SCREEN
        },
    ],
    "repos": [{"repo": "http://hg.mozilla.org/build/tools",}],
    "minidump_stackwalk_path": "%(abs_work_dir)s/tools/breakpad/win32/minidump_stackwalk.exe",
    "minidump_save_path": "%(abs_work_dir)s/../minidumps",
}
<|endoftext|>


<commit_before># Copyright (C) 2015 Tom Barron <tpb@dyncloud.net>
# Copyright (C) 2015 Kevin Fox <kevin@efox.cc>
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

"""Implementation of a backup service that uses a posix filesystem as the
   backend."""

import os
import os.path
import stat

from oslo_config import cfg
from oslo_log import log as logging
from oslo_utils import timeutils

from cinder.backup import chunkeddriver
from cinder import exception
from cinder import interface

LOG = logging.getLogger(__name__)

SHA_SIZE = 32768
# Multiple of SHA_SIZE, close to a characteristic OS max file system size.
BACKUP_FILE_SIZE = 61035 * 32768

posixbackup_service_opts = [
    cfg.IntOpt('backup_file_size',
               default=BACKUP_FILE_SIZE,
               help='The maximum size in bytes of the files used to hold '
                    'backups. If the volume being backed up exceeds this '
                    'size, then it will be backed up into multiple files.'
                    'backup_file_size must be a multiple of '
                    'backup_sha_block_size_bytes.'),
    cfg.IntOpt('backup_sha_block_size_bytes',
               default=SHA_SIZE,
               help='The size in bytes that changes are tracked '
                    'for incremental backups. backup_file_size has '
                    'to be multiple of backup_sha_block_size_bytes.'),
    cfg.BoolOpt('backup_enable_progress_timer',
                default=True,
                help='Enable or Disable the timer to send the periodic '
                     'progress notifications to Ceilometer when backing '
                     'up the volume to the backend storage. The '
                     'default value is True to enable the timer.'),
    cfg.StrOpt('backup_posix_path',
               default='$state_path/backup',
               help='Path specifying where to store backups.'),
    cfg.StrOpt('backup_container',
               help='Custom directory to use for backups.'),
]

CONF = cfg.CONF
CONF.register_opts(posixbackup_service_opts)

@interface.backupdriver
class PosixBackupDriver(chunkeddriver.ChunkedBackupDriver):
    """Provides backup, restore and delete using a Posix file system."""

    def __init__(self, context, db=None, backup_path=None):
        chunk_size_bytes = CONF.backup_file_size
        sha_block_size_bytes = CONF.backup_sha_block_size_bytes
        backup_default_container = CONF.backup_container
        enable_progress_timer = CONF.backup_enable_progress_timer
        super(PosixBackupDriver, self).__init__(context, chunk_size_bytes,
                                                sha_block_size_bytes,
                                                backup_default_container,
                                                enable_progress_timer,
                                                db)
        self.backup_path = backup_path
        if not backup_path:
            self.backup_path = CONF.backup_posix_path
        if not self.backup_path:
            raise exception.ConfigNotFound(path='backup_path')
        LOG.debug("Using backup repository: %s", self.backup_path)

    def update_container_name(self, backup, container):
        if container is not None:
            return container
        id = backup['id']
        return os.path.join(id[0:2], id[2:4], id)

    def put_container(self, container):
        path = os.path.join(self.backup_path, container)
        if not os.path.exists(path):
            os.makedirs(path)
            permissions = (
                stat.S_IRUSR |
                stat.S_IWUSR |
                stat.S_IXUSR |
                stat.S_IRGRP |
                stat.S_IWGRP |
                stat.S_IXGRP)
            os.chmod(path, permissions)

    def get_container_entries(self, container, prefix):
        path = os.path.join(self.backup_path, container)
        return [i for i in os.listdir(path) if i.startswith(prefix)]

    def get_object_writer(self, container, object_name, extra_metadata=None):
        path = os.path.join(self.backup_path, container, object_name)
        f = open(path, 'wb')
        permissions = (
            stat.S_IRUSR |
            stat.S_IWUSR |
            stat.S_IRGRP |
            stat.S_IWGRP)
        os.chmod(path, permissions)
        return f

    def get_object_reader(self, container, object_name, extra_metadata=None):
        path = os.path.join(self.backup_path, container, object_name)
        return open(path, 'rb')

    def delete_object(self, container, object_name):
        # TODO(tbarron):  clean up the container path if it is empty
        path = os.path.join(self.backup_path, container, object_name)
        try:
            os.remove(path)
        except OSError:
            pass

    def _generate_object_name_prefix(self, backup):
        timestamp = timeutils.utcnow().strftime("%Y%m%d%H%M%S")
        prefix = 'volume_%s_%s_backup_%s' % (backup.volume_id, timestamp,
                                             backup.id)
        LOG.debug('_generate_object_name_prefix: %s', prefix)
        return prefix

    def get_extra_metadata(self, backup, volume):
        return None

def get_backup_driver(context):
    return PosixBackupDriver(context)
<commit_msg>Improve deleting-missing-backup exception handling<commit_after># Copyright (C) 2015 Tom Barron <tpb@dyncloud.net>
# Copyright (C) 2015 Kevin Fox <kevin@efox.cc>
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

"""Implementation of a backup service that uses a posix filesystem as the
   backend."""

import errno
import os
import os.path
import stat

from oslo_config import cfg
from oslo_log import log as logging
from oslo_utils import timeutils

from cinder.backup import chunkeddriver
from cinder import exception
from cinder import interface

LOG = logging.getLogger(__name__)

SHA_SIZE = 32768
# Multiple of SHA_SIZE, close to a characteristic OS max file system size.
BACKUP_FILE_SIZE = 61035 * 32768

posixbackup_service_opts = [
    cfg.IntOpt('backup_file_size',
               default=BACKUP_FILE_SIZE,
               help='The maximum size in bytes of the files used to hold '
                    'backups. If the volume being backed up exceeds this '
                    'size, then it will be backed up into multiple files.'
                    'backup_file_size must be a multiple of '
                    'backup_sha_block_size_bytes.'),
    cfg.IntOpt('backup_sha_block_size_bytes',
               default=SHA_SIZE,
               help='The size in bytes that changes are tracked '
                    'for incremental backups. backup_file_size has '
                    'to be multiple of backup_sha_block_size_bytes.'),
    cfg.BoolOpt('backup_enable_progress_timer',
                default=True,
                help='Enable or Disable the timer to send the periodic '
                     'progress notifications to Ceilometer when backing '
                     'up the volume to the backend storage. The '
                     'default value is True to enable the timer.'),
    cfg.StrOpt('backup_posix_path',
               default='$state_path/backup',
               help='Path specifying where to store backups.'),
    cfg.StrOpt('backup_container',
               help='Custom directory to use for backups.'),
]

CONF = cfg.CONF
CONF.register_opts(posixbackup_service_opts)

@interface.backupdriver
class PosixBackupDriver(chunkeddriver.ChunkedBackupDriver):
    """Provides backup, restore and delete using a Posix file system."""

    def __init__(self, context, db=None, backup_path=None):
        chunk_size_bytes = CONF.backup_file_size
        sha_block_size_bytes = CONF.backup_sha_block_size_bytes
        backup_default_container = CONF.backup_container
        enable_progress_timer = CONF.backup_enable_progress_timer
        super(PosixBackupDriver, self).__init__(context, chunk_size_bytes,
                                                sha_block_size_bytes,
                                                backup_default_container,
                                                enable_progress_timer,
                                                db)
        self.backup_path = backup_path
        if not backup_path:
            self.backup_path = CONF.backup_posix_path
        if not self.backup_path:
            raise exception.ConfigNotFound(path='backup_path')
        LOG.debug("Using backup repository: %s", self.backup_path)

    def update_container_name(self, backup, container):
        if container is not None:
            return container
        id = backup['id']
        return os.path.join(id[0:2], id[2:4], id)

    def put_container(self, container):
        path = os.path.join(self.backup_path, container)
        if not os.path.exists(path):
            os.makedirs(path)
            permissions = (
                stat.S_IRUSR |
                stat.S_IWUSR |
                stat.S_IXUSR |
                stat.S_IRGRP |
                stat.S_IWGRP |
                stat.S_IXGRP)
            os.chmod(path, permissions)

    def get_container_entries(self, container, prefix):
        path = os.path.join(self.backup_path, container)
        return [i for i in os.listdir(path) if i.startswith(prefix)]

    def get_object_writer(self, container, object_name, extra_metadata=None):
        path = os.path.join(self.backup_path, container, object_name)
        f = open(path, 'wb')
        permissions = (
            stat.S_IRUSR |
            stat.S_IWUSR |
            stat.S_IRGRP |
            stat.S_IWGRP)
        os.chmod(path, permissions)
        return f

    def get_object_reader(self, container, object_name, extra_metadata=None):
        path = os.path.join(self.backup_path, container, object_name)
        return open(path, 'rb')

    def delete_object(self, container, object_name):
        # TODO(tbarron):  clean up the container path if it is empty
        path = os.path.join(self.backup_path, container, object_name)
        try:
            os.remove(path)
        except OSError as e:
            # ignore exception if path does not exsit
            if e.errno != errno.ENOENT:
                raise

    def _generate_object_name_prefix(self, backup):
        timestamp = timeutils.utcnow().strftime("%Y%m%d%H%M%S")
        prefix = 'volume_%s_%s_backup_%s' % (backup.volume_id, timestamp,
                                             backup.id)
        LOG.debug('_generate_object_name_prefix: %s', prefix)
        return prefix

    def get_extra_metadata(self, backup, volume):
        return None

def get_backup_driver(context):
    return PosixBackupDriver(context)
<|endoftext|>