Ejemplo n.º 1
0
def main():
    download_dataset()

    parser = argparse.ArgumentParser()
    parser.add_argument('-m',
                        '--map',
                        help='Which type of map to be generated.')
    args = parser.parse_args()

    if args.map == 'verywide':
        map_ = map_utils.VeryWide()
    elif args.map == 'regional':
        map_ = map_utils.Regional()
    elif args.map == 'local':
        map_ = map_utils.Local()
    else:
        print("Invalid Map Type Requested.")
        return

    # Open dataset
    file = '../output/DHLPCoR_data.grb2'
    data = pygrib.open(file)

    # Grab the keys from the data we want
    maximum_temperatures = data.select(name='Maximum temperature')
    minimum_temperatures = data.select(name='Minimum temperature')
    percent_chance_rain = data.select(
        name='Probability of 0.01 inch of precipitation (POP)')

    # loops Day by day (1-5)
    day = 1
    for max_temperatures, min_temperatures, percent_chance_rains in zip(
            maximum_temperatures, minimum_temperatures, percent_chance_rain):
        # Max Temperature data
        max_temperature_data = []
        max_temp_latitudes, max_temp_longitudes = max_temperatures.latlons()
        max_temp_values = max_temperatures.values
        for latitudes, longitudes, values in zip(max_temp_latitudes,
                                                 max_temp_longitudes,
                                                 max_temp_values):
            for lat, lon, value in zip(latitudes, longitudes, values):
                max_temperature_data.append({
                    'lat': lat,
                    'lon': lon,
                    'value': value
                })

        # Min Temperature data
        min_temperature_data = []
        min_temp_lats, min_temp_lons = min_temperatures.latlons()
        min_temp_values = min_temperatures.values
        for latitudes, longitudes, values in zip(min_temp_lats, min_temp_lons,
                                                 min_temp_values):
            for lat, lon, value in zip(latitudes, longitudes, values):
                min_temperature_data.append({
                    'lat': lat,
                    'lon': lon,
                    'value': value
                })

        # Percent chance of rain data
        percent_chance_rain_data = []
        per_chance_rain_lats, per_chance_rain_lons = percent_chance_rains.latlons(
        )
        per_chance_rain_values = percent_chance_rains.values
        for latitudes, longitudes, values in zip(per_chance_rain_lats,
                                                 per_chance_rain_lons,
                                                 per_chance_rain_values):
            for lat, lon, value in zip(latitudes, longitudes, values):
                percent_chance_rain_data.append({
                    'lat': lat,
                    'lon': lon,
                    'value': value
                })

        # Create the figure for graphing
        fig = plt.figure(figsize=(15, 9))
        ax = fig.add_subplot(1, 1, 1, projection=ccrs.Mercator())
        ax.set_extent(map_.NorthSouthEastWest[::-1], crs=ccrs.Geodetic())

        # Add boundaries to plot
        ax.add_feature(cfeature.OCEAN, facecolor=cfeature.COLORS['water'])
        if map_.map_type == 'verywide':
            ax.add_feature(cfeature.STATES.with_scale('50m'),
                           linewidth=0.5,
                           facecolor=cfeature.COLORS['land'])
        elif map_.map_type == 'regional' or map_.map_type == 'local':
            ax.add_feature(cfeature.STATES.with_scale('50m'),
                           linewidth=0.5,
                           facecolor=cfeature.COLORS['land'])
            reader = shpreader.Reader('../county_data/countyl010g.shp')
            counties = list(reader.geometries())
            COUNTIES = cfeature.ShapelyFeature(counties, ccrs.PlateCarree())
            ax.add_feature(COUNTIES,
                           facecolor='none',
                           edgecolor='black',
                           linewidth=0.3)
        elif map_.map_type == 'tropical':
            countries = cfeature.NaturalEarthFeature(category='cultural',
                                                     name='admin_0_countries',
                                                     scale='50m',
                                                     facecolor='none')
            ax.add_feature(cfeature.LAND)
            ax.add_feature(countries, edgecolor='black', linewidth=0.5)

        # Set the additional info on the map
        ax.set_title('Daily High / Low / Percent Chance of Rain taken ' +
                     str(max_temperatures.validDate)[:-9] + ' UTC',
                     fontsize=12,
                     loc='left')
        text = AnchoredText(r'$\mathcircled{{c}}$ NickelBlock Forecasting',
                            loc=4,
                            prop={'size': 9},
                            frameon=True)
        ax.add_artist(text)

        # Data Model
        data_model = AnchoredText('NWS/NDFD CONUS model',
                                  loc=3,
                                  prop={'size': 9},
                                  frameon=True)
        ax.add_artist(data_model)

        # Add logo
        logo = Utils.get_logo()
        if map_.map_type == 'verywide':
            ax.figure.figimage(logo, 1140, 137, zorder=1)
        elif map_.map_type == 'regional':
            ax.figure.figimage(logo, 1000, 137, zorder=1)
        elif map_.map_type == 'local':
            ax.figure.figimage(logo, 973, 137, zorder=1)
        else:
            ax.figure.figimage(logo, 1140, 181, zorder=1)

        # Plot the cities' information
        if map_.map_type is not 'tropical':
            for city in map_.cities:
                for max_temp, min_temp, per_chance_rain in zip(
                        max_temperature_data, min_temperature_data,
                        percent_chance_rain_data):
                    if round(city.lat,
                             1) == round(max_temp['lat'], 1) and round(
                                 city.lon, 1) == round(max_temp['lon'], 1):
                        ax.plot(city.lon,
                                city.lat,
                                'ro',
                                zorder=9,
                                markersize=1.90,
                                transform=ccrs.Geodetic())

                        # City Name
                        if city.city_name == 'Pensacola' and map_.map_type == 'verywide':
                            ax.text(city.lon - 0.13,
                                    city.lat + 0.045,
                                    city.city_name,
                                    fontsize='small',
                                    fontweight='bold',
                                    transform=ccrs.PlateCarree())
                        elif map_.map_type == 'local':
                            ax.text(city.lon - 0.2,
                                    city.lat + 0.04,
                                    city.city_name,
                                    fontsize='small',
                                    fontweight='bold',
                                    transform=ccrs.PlateCarree())
                        else:
                            ax.text(city.lon - 0.45,
                                    city.lat + 0.07,
                                    city.city_name,
                                    fontsize='small',
                                    fontweight='bold',
                                    transform=ccrs.PlateCarree())

                        # City Min/Max Temperature
                        text = str(int(round(
                            min_temp['value'] * 1.8 - 459.67))) + ' / ' + str(
                                int(round(max_temp['value'] * 1.8 - 459.67)))
                        if map_.map_type == 'local':
                            ax.text(city.lon - 0.17,
                                    city.lat - 0.1,
                                    text,
                                    fontsize='small',
                                    fontweight='bold',
                                    transform=ccrs.PlateCarree())
                        else:
                            ax.text(city.lon - 0.34,
                                    city.lat - 0.175,
                                    text,
                                    fontsize='small',
                                    fontweight='bold',
                                    transform=ccrs.PlateCarree())

                        # City Percent Chance of Rain
                        text = str(int(round(per_chance_rain['value']))) + '%'
                        if map_.map_type == 'local':
                            ax.text(city.lon - 0.07,
                                    city.lat - 0.18,
                                    text,
                                    fontsize='small',
                                    fontweight='bold',
                                    transform=ccrs.PlateCarree())
                        else:
                            ax.text(city.lon - 0.2,
                                    city.lat - 0.36,
                                    text,
                                    fontsize='small',
                                    fontweight='bold',
                                    transform=ccrs.PlateCarree())
                        break

        plt.savefig('Day_{}_{}_DailyHighLowPerChanceRain.png'.format(
            day, map_.map_type))
        day += 1
Ejemplo n.º 2
0
import os
import argparse

import cartopy.crs as ccrs
import cartopy.feature as cfeature
import cartopy.io.shapereader as shpreader
import matplotlib.pyplot as plt
from matplotlib.offsetbox import AnchoredText
import pygrib

import Map_Utils as map_utils
Utils = map_utils.Utils()


def main():
    download_dataset()

    parser = argparse.ArgumentParser()
    parser.add_argument('-m',
                        '--map',
                        help='Which type of map to be generated.')
    args = parser.parse_args()

    if args.map == 'verywide':
        map_ = map_utils.VeryWide()
    elif args.map == 'regional':
        map_ = map_utils.Regional()
    elif args.map == 'local':
        map_ = map_utils.Local()
    else:
        print("Invalid Map Type Requested.")
Ejemplo n.º 3
0
def main():
    download_dataset()

    parser = argparse.ArgumentParser()
    parser.add_argument('-m',
                        '--map',
                        help='Which type of map to be generated.')
    args = parser.parse_args()

    if args.map == 'verywide':
        map_ = map_utils.VeryWide()
    elif args.map == 'regional':
        map_ = map_utils.Regional()
    elif args.map == 'local':
        map_ = map_utils.Local()
    elif args.map == 'tropical':
        map_ = map_utils.Tropical()
    elif args.map == 'country':
        map_ = map_utils.Country()

    # Open dataset and capture relevant info
    file = '../output/CPC_data.grb2'
    dataset = pygrib.open(file)

    # Grab the temperature and precipitation data from the dataset
    precipitation_data = []
    temperature_data = dataset.select(name='Temperature')
    for d in dataset:
        if str(d) not in str(temperature_data):
            precipitation_data.append(d)

    temperature_precipitation_data = {
        'Temperatures': temperature_data,
        'Precipitations': precipitation_data,
    }.items()

    for key, values in temperature_precipitation_data:
        fig = plt.figure(figsize=(15, 9))
        ax = fig.add_subplot(1, 1, 1, projection=ccrs.Mercator())
        ax.set_extent(map_.NorthSouthEastWest[::-1], crs=ccrs.Geodetic())
        for value in values:
            lats, lons = value.latlons()
            vals = value.values
            # Add boundaries to plot
            ax.add_feature(cfeature.OCEAN, facecolor=cfeature.COLORS['water'])
            if map_.map_type == 'verywide':
                ax.add_feature(cfeature.STATES.with_scale('50m'),
                               linewidth=0.5)
            elif map_.map_type == 'regional' or map_.map_type == 'local':
                ax.add_feature(cfeature.STATES.with_scale('50m'),
                               linewidth=0.5)
                reader = shpreader.Reader('../county_data/countyl010g.shp')
                counties = list(reader.geometries())
                COUNTIES = cfeature.ShapelyFeature(counties,
                                                   ccrs.PlateCarree())
                ax.add_feature(COUNTIES,
                               facecolor='none',
                               edgecolor='black',
                               linewidth=0.3)
            elif map_.map_type == 'tropical' or map_.map_type == 'country':
                countries = cfeature.NaturalEarthFeature(
                    category='cultural',
                    name='admin_0_countries',
                    scale='50m',
                    facecolor='none')
                ax.add_feature(cfeature.LAND)
                ax.add_feature(countries, edgecolor='black', linewidth=0.5)
                ax.add_feature(cfeature.STATES.with_scale('50m'),
                               linewidth=0.5)

            # Contour temperature value at each lat/lon depending on the key
            if 'event below' in str(value):
                if key == 'Temperatures':
                    # Contour temperature at each lat/long
                    cf = ax.contourf(lons,
                                     lats,
                                     vals,
                                     levels=[33, 40, 50, 60, 70, 80, 90],
                                     transform=ccrs.PlateCarree(),
                                     cmap='Blues')
                    cb1 = plt.colorbar(cf,
                                       ax=ax,
                                       orientation='horizontal',
                                       fraction=0.045,
                                       pad=0.04)
                elif key == 'Precipitations':
                    # Contour temperature at each lat/long
                    cf = ax.contourf(lons,
                                     lats,
                                     vals,
                                     levels=[33, 40, 50, 60, 70, 80, 90],
                                     transform=ccrs.PlateCarree(),
                                     cmap='Blues')
                    cb1 = plt.colorbar(cf,
                                       ax=ax,
                                       orientation='horizontal',
                                       fraction=0.035,
                                       pad=0.08)
                cb1.ax.set_xlabel('Probability of Below (%)')
            elif 'event above' in str(value):
                if key == 'Temperatures':
                    # Contour temperature at each lat/long
                    cf = ax.contourf(lons,
                                     lats,
                                     vals,
                                     levels=[33, 40, 50, 60, 70, 80, 90],
                                     transform=ccrs.PlateCarree(),
                                     cmap='Reds')
                    cb2 = plt.colorbar(cf,
                                       ax=ax,
                                       orientation='horizontal',
                                       fraction=0.0395,
                                       pad=0.08)
                elif key == 'Precipitations':
                    # Contour temperature at each lat/long
                    cf = ax.contourf(lons,
                                     lats,
                                     vals,
                                     levels=[33, 40, 50, 60, 70, 80, 90],
                                     transform=ccrs.PlateCarree(),
                                     cmap='Greens')
                    cb2 = plt.colorbar(cf,
                                       ax=ax,
                                       orientation='horizontal',
                                       fraction=0.0395,
                                       pad=0.04)
                cb2.ax.set_xlabel('Probability of Above (%)')

            # Plot all the cities
            if map_.map_type is not 'tropical' and map_.map_type is not 'country':
                for city in map_.cities:
                    ax.plot(city.lon,
                            city.lat,
                            'ro',
                            zorder=9,
                            markersize=1.90,
                            transform=ccrs.Geodetic())

                    if map_.map_type == 'local':
                        ax.text(city.lon - 0.3,
                                city.lat + 0.04,
                                city.city_name,
                                fontsize='small',
                                fontweight='bold',
                                transform=ccrs.PlateCarree())
                    else:
                        ax.text(city.lon - 0.5,
                                city.lat + 0.09,
                                city.city_name,
                                fontsize='small',
                                fontweight='bold',
                                transform=ccrs.PlateCarree())
            # Title
            ax.set_title('{} Probability for {} UTC'.format(
                key, str(value.validDate)),
                         fontsize=12,
                         loc='left')

            # Company copyright bottom right corner
            text = AnchoredText(r'$\mathcircled{{c}}$ NickelBlock Forecasting',
                                loc=4,
                                prop={'size': 9},
                                frameon=True)
            ax.add_artist(text)

            # Data model
            data_model = AnchoredText('CPC Probability Outlook model',
                                      loc=3,
                                      prop={'size': 9},
                                      frameon=True)
            ax.add_artist(data_model)

            # Add logo
            logo = Utils.get_logo()
            if map_.map_type == 'verywide':
                if key == 'Temperatures':
                    ax.figure.figimage(logo, 1040, 272, zorder=1)
                elif key == 'Precipitations':
                    ax.figure.figimage(logo, 1045, 265, zorder=1)
            elif map_.map_type == 'regional':
                if key == 'Temperatures':
                    ax.figure.figimage(logo, 925, 273, zorder=1)
                elif key == 'Precipitations':
                    ax.figure.figimage(logo, 930, 267, zorder=1)
            elif map_.map_type == 'local':
                if key == 'Temperatures':
                    ax.figure.figimage(logo, 904, 270, zorder=1)
                elif key == 'Precipitations':
                    ax.figure.figimage(logo, 909, 265, zorder=1)
            elif map_.map_type == 'tropical':
                if key == 'Temperatures':
                    ax.figure.figimage(logo, 1110, 272, zorder=1)
                elif key == 'Precipitations':
                    ax.figure.figimage(logo, 1115, 267, zorder=1)
            elif map_.map_type == 'country':
                if key == 'Temperatures':
                    ax.figure.figimage(logo, 1070, 271, zorder=1)
                elif key == 'Precipitations':
                    ax.figure.figimage(logo, 1075, 266, zorder=1)

        plt.savefig('CPC_{}_{}_Map.png'.format(key, value.validDate))
def main():
    # Parse the arguments from the command line
    parser = argparse.ArgumentParser()
    parser.add_argument('-m',
                        '--map',
                        help='Which type of map to be generated.')
    parser.add_argument('-t',
                        '--time',
                        nargs='+',
                        help='Access and plot weather data X hours from now.',
                        type=int,
                        default=0)
    args = parser.parse_args()

    if args.map == 'verywide':
        map_ = map_utils.VeryWide()
    elif args.map == 'regional':
        map_ = map_utils.Regional()
    elif args.map == 'local':
        map_ = map_utils.Local()
    elif args.map == 'tropical':
        map_ = map_utils.Tropical()
    else:
        print("Invalid Map Type Requested.")
        return

    # Create maps for each time declared on command line
    for t in args.time:
        # Acquire the datasets from the GFS Global Catalog
        GFS_data = TDSCatalog(
            'http://thredds.ucar.edu/thredds/catalog/grib/NCEP/GFS/'
            'Global_0p25deg/catalog.xml?dataset=grib/NCEP/GFS/Global_0p25deg/Best'
        )

        # Pull out our dataset and get the NCSS access point used to query data from the dataset
        dataset = GFS_data.datasets[0]
        ncss = dataset.subset()

        # Use the `ncss` object to create a new query object
        query = ncss.query()
        time = (datetime.utcnow() + timedelta(hours=t)
                )  # Time of data requested
        query.time(time)
        query.accept('netcdf4')
        query.variables('Temperature_surface')

        # Set the lat lon box for which specific area of the dataset to query
        if map_.map_type is not 'tropical':
            query.lonlat_box(north=map_.NorthSouthEastWest[0],
                             south=map_.NorthSouthEastWest[1],
                             east=map_.NorthSouthEastWest[2],
                             west=map_.NorthSouthEastWest[3])
        else:
            query.lonlat_box(north=map_.NorthSouthEastWest[0] + 10,
                             south=map_.NorthSouthEastWest[1],
                             east=map_.NorthSouthEastWest[2],
                             west=map_.NorthSouthEastWest[3])

        data = ncss.get_data(query)

        # Grab the keys from the data we want
        temperatures = data.variables['Temperature_surface']
        latitudes = data.variables['lat']
        longitudes = data.variables['lon']

        # Remove 1d arrays from data for plotting
        temperatures = temperatures[:].squeeze()
        latitudes = latitudes[:].squeeze()
        longitudes = longitudes[:].squeeze()

        # Convert temps to Fahrenheit from Kelvin
        temperatures = convert_temperature_to_fahrenheit(temperatures)

        # Combine 1D latitude and longitudes into a 2D grid of locations
        lon_2d, lat_2d = np.meshgrid(longitudes, latitudes)

        # Create figure for plotting
        fig = plt.figure(figsize=(15, 9))
        ax = fig.add_subplot(1, 1, 1, projection=ccrs.Mercator())
        ax.set_extent(map_.NorthSouthEastWest[::-1], crs=ccrs.Geodetic())

        # Add map features depending on map type
        ax.add_feature(cfeature.STATES.with_scale('50m'), linewidth=0.5)
        if map_.map_type == 'regional' or map_.map_type == 'local':
            reader = shpreader.Reader('../county_data/countyl010g.shp')
            counties = list(reader.geometries())
            COUNTIES = cfeature.ShapelyFeature(counties, ccrs.PlateCarree())
            ax.add_feature(COUNTIES,
                           facecolor='none',
                           edgecolor='black',
                           linewidth=0.3)
        elif map_.map_type == 'tropical':
            countries = cfeature.NaturalEarthFeature(category='cultural',
                                                     name='admin_0_countries',
                                                     scale='50m',
                                                     facecolor='none')
            ax.add_feature(cfeature.LAND)
            ax.add_feature(countries, edgecolor='black', linewidth=0.5)

        # Contour temperature value at each lat/lon
        cf = ax.contourf(lon_2d,
                         lat_2d,
                         temperatures,
                         40,
                         extend='both',
                         transform=ccrs.PlateCarree(),
                         cmap='coolwarm')

        # Plot a colorbar to show temperature values
        colorbar = plt.colorbar(cf, ax=ax, fraction=0.032)
        colorbar.set_label('Temperature (\u00b0F)')

        # Plot all the cities
        if map_.map_type is not 'tropical':
            for city in map_.cities:
                for lat in range(len(latitudes)):
                    for lon in range(len(longitudes)):
                        if round_temps(
                                city.lat) == latitudes[lat] and round_temps(
                                    city.lon) == (longitudes[lon] - 360):
                            cityTemp_latlon = Utils.plot_latlon_cityTemp_by_maptype(
                                lat=city.lat,
                                lon=city.lon,
                                map_type=map_.map_type)
                            ax.text(cityTemp_latlon[1],
                                    cityTemp_latlon[0],
                                    int(round(temperatures[lat][lon])),
                                    fontsize='10',
                                    fontweight='bold',
                                    transform=ccrs.PlateCarree())
                ax.plot(city.lon,
                        city.lat,
                        'ro',
                        zorder=9,
                        markersize=2.00,
                        transform=ccrs.Geodetic())
                cityName_latlon = Utils.plot_latlon_cityName_by_maptype(
                    lat=city.lat, lon=city.lon, map_type=map_.map_type)
                ax.text(cityName_latlon[1],
                        cityName_latlon[0],
                        city.city_name,
                        fontsize='small',
                        fontweight='bold',
                        transform=ccrs.PlateCarree())

        # Create a title with the time value
        ax.set_title('Temperature forecast (\u00b0F) for {} UTC'.format(
            str(time)[:-7]),
                     fontsize=12,
                     loc='left')

        # Company copyright
        text = AnchoredText(r'$\mathcircled{{c}}$ NickelBlock Forecasting',
                            loc=4,
                            prop={'size': 9},
                            frameon=True)
        ax.add_artist(text)

        # Data model
        data_model = AnchoredText('GFS 12z model',
                                  loc=3,
                                  prop={'size': 9},
                                  frameon=True)
        ax.add_artist(data_model)

        # Add logo
        logo = Utils.get_logo()
        if map_.map_type is not 'tropical':
            ax.figure.figimage(logo, 1105, 137, zorder=1)
        else:
            ax.figure.figimage(logo, 1105, 181, zorder=1)

        plt.savefig('{}_Temperature_Hour_{}.png'.format(map_.map_type, t))
def main():
    download_dataset()

    parser = argparse.ArgumentParser()
    parser.add_argument('-m',
                        '--map',
                        help='Which type of map to be generated.')
    args = parser.parse_args()

    if args.map == 'verywide':
        map_ = map_utils.VeryWide()
    elif args.map == 'regional':
        map_ = map_utils.Regional()
    elif args.map == 'local':
        map_ = map_utils.Local()
    elif args.map == 'tropical':
        map_ = map_utils.Tropical()
    elif args.map == 'country':
        map_ = map_utils.Country()
    else:
        print("Invalid Map Type Requested.")
        return

    # Open dataset and capture relevant info
    file = '../output/SPC_data.grb2'
    dataset = pygrib.open(file)
    data = pygrib.open(file)

    valid_days_data = get_valid_days(dataset, data)

    for data in valid_days_data:
        print(data.validDate)
        lats, lons = data.latlons()
        values = data.values

        # Create the figure for graphing
        fig = plt.figure(figsize=(15, 9))
        ax = fig.add_subplot(1, 1, 1, projection=ccrs.Mercator())
        ax.set_extent(map_.NorthSouthEastWest[::-1], crs=ccrs.Geodetic())

        # Add boundaries to plot
        ax.add_feature(cfeature.OCEAN, facecolor=cfeature.COLORS['water'])
        if map_.map_type == 'verywide':
            ax.add_feature(cfeature.STATES.with_scale('50m'), linewidth=0.5)
        elif map_.map_type == 'regional' or map_.map_type == 'local':
            ax.add_feature(cfeature.STATES.with_scale('50m'), linewidth=0.5)
            reader = shpreader.Reader('../county_data/countyl010g.shp')
            counties = list(reader.geometries())
            COUNTIES = cfeature.ShapelyFeature(counties, ccrs.PlateCarree())
            ax.add_feature(COUNTIES,
                           facecolor='none',
                           edgecolor='black',
                           linewidth=0.3)
        elif map_.map_type == 'tropical' or map_.map_type == 'country':
            countries = cfeature.NaturalEarthFeature(category='cultural',
                                                     name='admin_0_countries',
                                                     scale='50m',
                                                     facecolor='none')
            ax.add_feature(cfeature.LAND)
            ax.add_feature(countries, edgecolor='black', linewidth=0.5)
            ax.add_feature(cfeature.STATES.with_scale('50m'), linewidth=0.5)

        # Contour temperature at each lat/long
        cf = ax.contourf(lons,
                         lats,
                         values,
                         levels=[0, 1, 2, 3, 4, 5],
                         transform=ccrs.PlateCarree(),
                         cmap='Greens')

        # Plot all the cities
        if map_.map_type is not 'tropical' and map_.map_type is not 'country':
            for city in map_.cities:
                ax.plot(city.lon,
                        city.lat,
                        'ro',
                        zorder=9,
                        markersize=1.90,
                        transform=ccrs.Geodetic())
                ax.text(city.lon - 0.5,
                        city.lat + 0.09,
                        city.city_name,
                        fontsize='small',
                        fontweight='bold',
                        transform=ccrs.PlateCarree())

        # Make a title with the time value
        ax.set_title('SPC Categorical Outlook for {} UTC'.format(
            str(data.validDate)),
                     fontsize=12,
                     loc='left')

        # Company copyright on the bottom right corner
        text = AnchoredText(r'$\mathcircled{{c}}$ NickelBlock Forecasting',
                            loc=4,
                            prop={'size': 9},
                            frameon=True)
        ax.add_artist(text)

        # Data Model
        data_model = AnchoredText(
            'SPC Probabilistic to Categorical Outlook model',
            loc=3,
            prop={'size': 9},
            frameon=True)
        ax.add_artist(data_model)

        # Add logo
        logo = Utils.get_logo()
        if map_.map_type == 'verywide':
            ax.figure.figimage(logo, 1090, 205, zorder=1)
        elif map_.map_type == 'regional':
            ax.figure.figimage(logo, 960, 205, zorder=1)
        elif map_.map_type == 'local':
            ax.figure.figimage(logo, 937, 205, zorder=1)
        elif map_.map_type == 'tropical':
            ax.figure.figimage(logo, 1170, 205, zorder=1)
        elif map_.map_type == 'country':
            ax.figure.figimage(logo, 1124, 205, zorder=1)

        # Plot a colorbar to show temperature and reduce the size of it
        cb = plt.colorbar(cf,
                          ax=ax,
                          fraction=0.056,
                          orientation='horizontal',
                          pad=0.04)
        cb.ax.set_xlabel('(  1:MRGL,  2:SLGT,  3:ENH,  4:MDT,  5:HIGH  )')
        plt.savefig('SPC_{}_{}_Map.png'.format(map_.map_type,
                                               str(data.validDate)))
def main():
    # Parse the arguments from the command line
    parser = argparse.ArgumentParser()
    parser.add_argument('-m',
                        '--map',
                        help='Which type of map to be generated.')
    parser.add_argument('-t',
                        '--time',
                        nargs='+',
                        help='Access and plot weather data X hours from now.',
                        type=int,
                        default=0)
    args = parser.parse_args()

    if args.map == 'verywide':
        map_ = map_utils.VeryWide()
    elif args.map == 'regional':
        map_ = map_utils.Regional()
    elif args.map == 'local':
        map_ = map_utils.Local()
    elif args.map == 'tropical':
        map_ = map_utils.Tropical()
    else:
        print("Invalid Map Type Requested.")
        return

    for t in args.time:
        # Acquire the datasets from the GFS Global Catalog
        GFS_data = TDSCatalog(
            'http://thredds.ucar.edu/thredds/catalog/grib/NCEP/GFS/'
            'Global_0p25deg/catalog.xml?dataset=grib/NCEP/GFS/Global_0p25deg/Best'
        )

        # Pull out our dataset and get the NCSS access point used to query data from the dataset
        dataset = GFS_data.datasets[0]
        ncss = dataset.subset()

        # Use the `ncss` object to create a new query object
        query = ncss.query()
        time = (datetime.utcnow() + timedelta(hours=t)
                )  # Time of data requested
        query.time(time)
        query.accept('netcdf4')
        query.variables('Precipitation_rate_surface')

        # Set the lat lon box for which specific area of the dataset to query
        if map_.map_type is not 'tropical':
            query.lonlat_box(north=map_.NorthSouthEastWest[0],
                             south=map_.NorthSouthEastWest[1],
                             east=map_.NorthSouthEastWest[2],
                             west=map_.NorthSouthEastWest[3])
        else:
            query.lonlat_box(north=map_.NorthSouthEastWest[0] + 10,
                             south=map_.NorthSouthEastWest[1],
                             east=map_.NorthSouthEastWest[2],
                             west=map_.NorthSouthEastWest[3])

        data = ncss.get_data(query)

        # Grab the keys from the data we want
        precipitations = data.variables['Precipitation_rate_surface']
        latitudes = data.variables['lat']
        longitudes = data.variables['lon']

        # Remove 1d arrays from data for plotting
        precipitations = precipitations[:].squeeze()
        latitudes = latitudes[:].squeeze()
        longitudes = longitudes[:].squeeze()

        # Convert all precipitation values from kg/m^2/s (kilograms per meter squared per second) to inches
        for i in range(len(latitudes)):
            for k in range(len(longitudes)):
                precipitations[i][k] = kg_per_msquared_to_inches(
                    precipitations[i][k])

        # Combine 1D latitude and longitudes into a 2D grid of locations
        lon_2d, lat_2d = np.meshgrid(longitudes, latitudes)

        # Create figure for plotting
        fig = plt.figure(figsize=(15, 9))
        ax = fig.add_subplot(1, 1, 1, projection=ccrs.Mercator())
        ax.set_extent(map_.NorthSouthEastWest[::-1], crs=ccrs.Geodetic())

        # Add map features depending on map type
        ax.add_feature(cfeature.STATES.with_scale('50m'), linewidth=0.5)
        if map_.map_type == 'regional' or map_.map_type == 'local':
            reader = shpreader.Reader('../county_data/countyl010g.shp')
            counties = list(reader.geometries())
            COUNTIES = cfeature.ShapelyFeature(counties, ccrs.PlateCarree())
            ax.add_feature(COUNTIES,
                           facecolor='none',
                           edgecolor='black',
                           linewidth=0.3)
        elif map_.map_type == 'tropical':
            countries = cfeature.NaturalEarthFeature(category='cultural',
                                                     name='admin_0_countries',
                                                     scale='50m',
                                                     facecolor='none')
            ax.add_feature(cfeature.LAND)
            ax.add_feature(countries, edgecolor='black', linewidth=0.5)

        # Create the custom color map for rain
        colormap = ListedColormap([
            'white',
            # Greens
            '#7dcf65',
            '#6fba59',
            '#63a351',
            '#5c914d',
            '#508641',
            '#48793b',
            '#396a2d',
            '#315d27',
            '#245817',
            '#1c4711',
            '#1c4711',
            '#1c4711',
            '#1c4711',
            '#1c4711',
            '#1c4711',
            # Oranges
            '#ffea5d',
            '#ffea5d',
            '#dddf32',
            '#dfcc4b',
            '#DBC634',
            'orange'
        ])

        # Contour temperature at each lat/long
        cf = ax.contourf(lon_2d,
                         lat_2d,
                         precipitations,
                         levels=[
                             0.001, 0.01, 0.025, 0.045, 0.065, 0.085, 0.105,
                             0.125, 0.150, 0.175, 0.200, 0.250, 0.5, 1.0
                         ],
                         extend='both',
                         transform=ccrs.PlateCarree(),
                         cmap=colormap)

        # Plot a colorbar to show temperature and reduce the size of it
        colorbar = plt.colorbar(cf,
                                ax=ax,
                                cmap=colormap,
                                fraction=0.032,
                                ticks=[
                                    0.001, 0.01, 0.025, 0.045, 0.065, 0.085,
                                    0.105, 0.125, 0.150, 0.175, 0.200, 0.250,
                                    0.500, 1.00
                                ])
        colorbar.set_label('Precipitation Rate (inches per hour)')

        # Plot all the cities
        if map_.map_type is not 'tropical':
            for city in map_.cities:
                ax.plot(city.lon,
                        city.lat,
                        'ro',
                        zorder=9,
                        markersize=1.90,
                        transform=ccrs.Geodetic())
                cityName_latlon = Utils.plot_latlon_cityName_by_maptype(
                    lat=city.lat, lon=city.lon, map_type=map_.map_type)
                ax.text(cityName_latlon[1],
                        cityName_latlon[0],
                        city.city_name,
                        fontsize='small',
                        fontweight='bold',
                        transform=ccrs.PlateCarree())

        # Create a title with the time value
        ax.set_title('Precipitation Rate Forecast (inches) for {} UTC'.format(
            str(time)[:-7]),
                     fontsize=12,
                     loc='left')

        # Company copyright
        text = AnchoredText(r'$\mathcircled{{c}}$ NickelBlock Forecasting',
                            loc=4,
                            prop={'size': 9},
                            frameon=True)
        ax.add_artist(text)

        # Data model
        data_model = AnchoredText('GFS 12z model',
                                  loc=3,
                                  prop={'size': 9},
                                  frameon=True)
        ax.add_artist(data_model)

        # Add logo
        logo = Utils.get_logo()
        if map_.map_type is not 'tropical':
            ax.figure.figimage(logo, 1105, 137, zorder=1)
        else:
            ax.figure.figimage(logo, 1105, 181, zorder=1)

        plt.savefig('{}_Precipitation_Hour_{}.png'.format(map_.map_type, t))