Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# noaaplotter
A python package to create fancy plots with NOAA weather data.



## Install
#### Recommended conda install
I recommend to use a fresh conda environment
Expand All @@ -22,20 +20,29 @@ I recommend to use a fresh conda environment
- requests
- joblib
- tqdm
- geemap


## Examples
### Download data
#### Option 1: Download via script
#### Option 1 NOAA Daily Summaries: Download via script
Download daily summaries (temperature + precipitation) from Kotzebue (or other station) from 1970-01-01 until 2021-12-31
* NOAA API Token is required: https://www.ncdc.noaa.gov/cdo-web/token

`python download_data.py -o ./data/kotzebue.csv -sid GHCND:USW00026616 -start 1970-01-01 -end 2021-12-31 -t <NOAA API Token>`

#### Option 2: Download via browser
#### Option 2 NOAA Daily Summaries: Download via browser
CSV files of "daily summaries"
("https://www.ncdc.noaa.gov/cdo-web/search")
* Values: metric
* File types: csv

#### Option 3 ERA5 Daily: Download via script
Download daily summaries (temperature + precipitation) from Potsdam (13.05°E, 52.4°N) from 1980-01-01 until 2021-12-31
* Google Earthengine account is required
* Caution: full dataset may take a few minutes

`python download_data_ERA5.py -o ./data/potsdam_ERA5.csv -start 1980-01-01 -end 2021-12-31 -lat 52.4 -lon 13.05`

### Daily Mean Temperature and Precipitation values vs. Climate
#### Entire year 1 January until 31 December (e.g. 1992)
Expand Down
98 changes: 98 additions & 0 deletions download_data_ERA5.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Imports
import argparse
import csv
from datetime import datetime
import numpy as np
import os
import pandas as pd
import tqdm
from joblib import delayed, Parallel
from noaaplotter.utils import dl_noaa_api
import ee
import geemap


def main():
"""
Main Function
:return:
"""
##### Parse arguments #####
parser = argparse.ArgumentParser(description='Parse arguments.')

parser.add_argument('-o', dest='output_file', type=str, required=True,
default='data/data.csv',
help='csv file to save results')

parser.add_argument('-lat', dest='lat', type=float, required=True,
help='Latitude of selected location')

parser.add_argument('-lon', dest='lon', type=float, required=True,
help='Longitude of selected location')

parser.add_argument('-loc', dest='loc_name', type=str, required=False,
default='',
help='Location name')

parser.add_argument('-dt', dest='datatypes', type=list, required=False, default=['TMIN', 'TMAX', 'PRCP', 'SNOW'])

parser.add_argument('-start', dest='start_date', type=str, required=True,
help='start date of plot ("yyyy-mm-dd")')

parser.add_argument('-end', dest='end_date', type=str, required=True,
help='end date of plot ("yyyy-mm-dd")')

args = parser.parse_args()

# remove file if exists
if os.path.exists(args.output_file):
os.remove(args.output_file)

ee.Initialize()

EE_LAYER = 'ECMWF/ERA5/DAILY'

location = ee.Geometry.Point([args.lon, args.lat])

# load ImageCollection
col = ee.ImageCollection(EE_LAYER).filterBounds(location).filterDate(args.start_date, args.end_date)

# Download data
print("Start downloading daily ERA5 data.")
print("Download may take a while.\n1yr: ~5 seconds\n10yrs: ~35 seconds\n50yrs: ~8 min")
result = geemap.extract_pixel_values(col, region=location)
out_dict = result.getInfo()

df_gee = pd.DataFrame(data=[out_dict.keys(), out_dict.values()]).T

# parse dates and values
df_gee['time'] = df_gee[0].apply(lambda x: f'{x[:4]}-{x[4:6]}-{x[6:8]}')
df_gee['feature'] = df_gee[0].apply(lambda x: x[9:])
df_gee['value'] = df_gee[1]

df = df_gee.pivot_table(values='value', columns=['feature'], index='time')#.reset_index(drop=False)

# #### recalculate values
df_new = pd.DataFrame(index=df.index)

temperature_cols = ['mean_2m_air_temperature', 'minimum_2m_air_temperature', 'maximum_2m_air_temperature', 'dewpoint_2m_temperature']
precipitation_cols = ['total_precipitation']
df_joined = df_new.join(df[temperature_cols] - 273.15).join(df[precipitation_cols] *1e3).reset_index(drop=False)

# Create Output
rename_dict = {'time':'DATE', 'total_precipitation':'PRCP', 'mean_2m_air_temperature':'TAVG', 'maximum_2m_air_temperature':'TMAX', 'minimum_2m_air_temperature':'TMIN'}
df_renamed = df_joined.rename(columns=rename_dict)
df_renamed['NAME'] = ''
df_renamed['STATION'] = ''
df_renamed['SNWD'] = ''

output_cols = ["STATION","NAME","DATE","PRCP","SNWD","TAVG","TMAX","TMIN"]
df_save = df_renamed[output_cols].astype(str)

df_save.to_csv(args.output_file, index=False)


if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ dependencies:
- requests
- joblib
- tqdm
- geemap
11 changes: 10 additions & 1 deletion noaaplotter/noaaplotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import numpy as np
########################
from matplotlib import pyplot as plt, dates
import matplotlib.dates as mdates

from .dataset import NOAAPlotterDailyClimateDataset as DS_daily
from .dataset import NOAAPlotterDailySummariesDataset as Dataset
Expand Down Expand Up @@ -80,7 +81,8 @@ def plot_weather_series(self, start_date, end_date,
plot_pmax='auto', plot_snowmax='auto',
plot_extrema=True, show_plot=True,
show_snow_accumulation=True, save_path=False,
figsize=(9, 6), legend_fontsize='x-small', dpi=300):
figsize=(9, 6), legend_fontsize='x-small', dpi=300,
title=None):
"""
Plotting Function to show observed vs climate temperatures and snowfall
:param dpi:
Expand Down Expand Up @@ -203,6 +205,8 @@ def plot_weather_series(self, start_date, end_date,
ax_t.set_ylim(plot_tmin, plot_tmax)
ax_t.set_ylabel('Temperature in °C')
ax_t.set_xlabel('Date')
if title:
ax_t.set_title(title)

# add legend
legend_handle_t = [fb, cm, cm_hi, fill_r, fill_b]
Expand Down Expand Up @@ -282,6 +286,11 @@ def plot_weather_series(self, start_date, end_date,
bbox_to_anchor=(0.5, -0.2))
ax_p.legend(legend_handle_p, legend_text_p, loc='upper left', fontsize=legend_fontsize)

# set locator to monthly
locator = dates.MonthLocator()
ax_t.xaxis.set_major_locator(locator)
ax_p.xaxis.set_major_locator(locator)

fig.tight_layout()

# Save Figure
Expand Down
7 changes: 6 additions & 1 deletion plot_daily.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ def main():
default=[9, 6],
help='figure size in inches width x height. 15 10 recommended for 1 year, 30 10 for 2 years ...')

parser.add_argument('-title', dest='title', type=str, required=False,
default=None,
help='Plot title')

args = parser.parse_args()

##### Download from NOAA #####
Expand All @@ -91,7 +95,8 @@ def main():
plot_pmax=args.p_range,
plot_snowmax=args.s_range,
dpi=args.dpi,
figsize=args.figsize)
figsize=args.figsize,
title=args.title)

if __name__ == "__main__":
main()