Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

PR: Add a year range option to the weather normals viewer #142

Merged
merged 30 commits into from
Jan 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ac72614
:recycle: Renamed WeatherAvgGraph to WeatherViewer
jnsebgosselin Jan 9, 2018
eed2bce
:art: Code style changes
jnsebgosselin Jan 9, 2018
578364f
Added a new RangeSpinBoxes class
jnsebgosselin Jan 9, 2018
5ca22c9
Added a year range widget to the weather viewer
jnsebgosselin Jan 9, 2018
89424e7
:book: Added some docstrings to functions
jnsebgosselin Jan 10, 2018
fd34b4f
:art: Some code style changes
jnsebgosselin Jan 10, 2018
fff15a1
:recycle: Added year range for normals calc
jnsebgosselin Jan 10, 2018
b7914bd
Removed annoying prints
jnsebgosselin Jan 11, 2018
e891eb3
:art: Code style changes
jnsebgosselin Jan 11, 2018
2b3b3df
Improved the RangeSpinBoxes implementation
jnsebgosselin Jan 11, 2018
d7460cb
Update the graph and table when year range change.
jnsebgosselin Jan 11, 2018
dd9141f
:art: More code style changes
jnsebgosselin Jan 11, 2018
cd3cba6
Updated the save normals to file functionality
jnsebgosselin Jan 11, 2018
c29d119
Merge remote-tracking branch 'refs/remotes/origin/master' into add_ye…
jnsebgosselin Jan 11, 2018
3f4994c
:wrench: Clean imports
jnsebgosselin Jan 11, 2018
7f65f89
:art: Some code style changes
jnsebgosselin Jan 11, 2018
ad2fabc
:recycle: Refactoring of how language is handled.
jnsebgosselin Jan 11, 2018
96fb2c4
Added the year range as a label of the x-axis
jnsebgosselin Jan 11, 2018
1907c8a
Tweaked bottom margin and fixed set_lang
jnsebgosselin Jan 11, 2018
2c0cfee
Show buttons by default in the SmartSpinBox
jnsebgosselin Jan 11, 2018
6d73c2a
Added a button in toolbar to expand year range
jnsebgosselin Jan 12, 2018
a17733b
Make table more pretty
jnsebgosselin Jan 12, 2018
e53207c
Updated tooltip and made window non resizable
jnsebgosselin Jan 12, 2018
5fad844
Imports
jnsebgosselin Jan 12, 2018
d78a159
Stretch the columns and rows
jnsebgosselin Jan 12, 2018
baf66c8
Remove the call to resize to contents
jnsebgosselin Jan 12, 2018
f8cd8e1
Make the height of the table not hard coded
jnsebgosselin Jan 12, 2018
ec94d74
:art: Some code style changes
jnsebgosselin Jan 13, 2018
9e8054f
Added 'Period' key to WXDataFrame
jnsebgosselin Jan 13, 2018
08d3da9
:wrench: clean imports
jnsebgosselin Jan 13, 2018
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
6 changes: 3 additions & 3 deletions gwhat/HydroPrint2.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

import gwhat.hydrograph4 as hydrograph
import gwhat.mplFigViewer3 as mplFigViewer
from gwhat.meteo.weather_viewer import WeatherAvgGraph
from gwhat.meteo.weather_viewer import WeatherViewer
from gwhat.colors2 import ColorsReader, ColorsSetupWin

from gwhat.common import QToolButtonNormal, QToolButtonSmall
Expand All @@ -54,7 +54,7 @@ def __init__(self, datamanager, parent=None):
self.dmngr.wldsetChanged.connect(self.wldset_changed)
self.dmngr.wxdsetChanged.connect(self.wxdset_changed)

self.weather_avg_graph = WeatherAvgGraph(self)
self.weather_avg_graph = WeatherViewer(self)

self.page_setup_win = PageSetupWin(self)
self.page_setup_win.newPageSetupSent.connect(self.layout_changed)
Expand Down Expand Up @@ -456,7 +456,7 @@ def show_weather_averages(self):
return

self.weather_avg_graph.save_fig_dir = self.workdir
self.weather_avg_graph.generate_graph(self.wxdset)
self.weather_avg_graph.set_weather_dataset(self.wxdset)
self.weather_avg_graph.show()

# ---- Datasets Handlers
Expand Down
3 changes: 0 additions & 3 deletions gwhat/colors2.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,11 @@ def load_colors_db(self):
self.save_colors_db()

else:
print('Loading the color settings...', end=" ")
with open(fname, 'r') as f:
reader = list(csv.reader(f, delimiter=','))

for row in reader:
self.RGB[row[0]] = [int(x) for x in row[1:]]
print('done')

def save_colors_db(self):
"""Save the color settings to Colors.db."""
Expand All @@ -80,7 +78,6 @@ def save_colors_db(self):
fcontent.append([key])
fcontent[-1].extend(self.RGB[key])
save_content_to_csv(fname, fcontent)
print('Color settings saved successfully.')


class ColorsSetupWin(myqt.DialogWindow):
Expand Down
7 changes: 7 additions & 0 deletions gwhat/common/icons.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

dirname = os.path.join(__rootdir__, 'ressources', 'icons_png')
ICON_NAMES = {'master': 'WHAT',
'expand_range_vert': 'expand_range_vert',
'info': 'info',
'calc_brf': 'start',
'setup': 'page_setup',
Expand Down Expand Up @@ -131,3 +132,9 @@ class QToolButtonSmall(QToolButtonBase):
def __init__(self, Qicon, *args, **kargs):
super(QToolButtonSmall, self).__init__(Qicon, *args, **kargs)
self.setIconSize(QSize(20, 20))


class QToolButtonVRectSmall(QToolButtonBase):
def __init__(self, Qicon, *args, **kargs):
super(QToolButtonVRectSmall, self).__init__(Qicon, *args, **kargs)
self.setIconSize(QSize(8, 20))
3 changes: 2 additions & 1 deletion gwhat/common/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,8 @@ def __init__(self, parent=None, resizable=False, maximize=True):
else:
self.__resizable = resizable
self.setWindowFlags(Qt.Window |
Qt.WindowMinimizeButtonHint)
Qt.WindowMinimizeButtonHint |
Qt.WindowCloseButtonHint)

self.setWindowIcon(icons.get_icon('master'))

Expand Down
76 changes: 56 additions & 20 deletions gwhat/meteo/weather_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,16 @@ def __init__(self, filename, *args, **kwargs):
'Ptot': np.array([]),
'Rain': None,
'Snow': None,
'PET': None}
'PET': None,
'Period': (None, None)}

# -------------------------------------------- Import primary data ----
# ---- Import primary data

data = read_weather_datafile(filename)
for key in data.keys():
self[key] = data[key]

# ------------------------------------------------- Import missing ----
# ---- Import missing

finfo = filename[:-3] + 'log'
if os.path.exists(finfo):
Expand All @@ -102,30 +103,33 @@ def __init__(self, filename, *args, **kwargs):
self['Missing Tavg'] = load_weather_log(finfo, 'Mean Temp (deg C)')
self['Missing Ptot'] = load_weather_log(finfo, 'Total Precip (mm)')

# ---------------------------------------------------- format data ----

print('Make daily time series continuous.')
# ---- Format Data

time = copy(self['Time'])
date = [copy(self['Year']), copy(self['Month']), copy(self['Day'])]
vbrs = ['Tmax', 'Tavg', 'Tmin', 'Ptot', 'Rain', 'PET']
data = [self[x] for x in vbrs]

# Make daily time series continuous :

time, date, data = make_timeserie_continuous(self['Time'], date, data)
self['Time'] = time
self['Year'], self['Month'], self['Day'] = date[0], date[1], date[2]
for i, vbr in enumerate(vbrs):
self[vbr] = data[i]

print('Fill missing with estimated values.')
self['normals']['Period'] = (np.min(self['Year']),
np.max(self['Year']))

# Fill missing with estimated values :

for vbr in ['Tmax', 'Tavg', 'Tmin', 'PET']:
self[vbr] = fill_nan(self['Time'], self[vbr], vbr, 'interp')

for vbr in ['Ptot', 'Rain', 'Snow']:
self[vbr] = fill_nan(self['Time'], self[vbr], vbr, 'zeros')

# ---------------------------------------------- monthly & normals ----
# ---- Monthly & Normals

# Temperature based variables:

Expand All @@ -136,7 +140,7 @@ def __init__(self, filename, *args, **kwargs):
x = calc_monthly_mean(self['Year'], self['Month'], self[vrb])
self['monthly'][vrb] = x[2]

self['normals'][vrb] = calcul_monthly_normals(x[1], x[2])
self['normals'][vrb] = calcul_monthly_normals(x[0], x[1], x[2])

# Precipitation :

Expand All @@ -149,11 +153,11 @@ def __init__(self, filename, *args, **kwargs):
self['monthly']['Year'] = x[0]
self['monthly']['Month'] = x[1]

self['normals']['Ptot'] = calcul_monthly_normals(x[1], x[2])
self['normals']['Ptot'] = calcul_monthly_normals(x[0], x[1], x[2])

# ------------------------------------------------- secondary vrbs ----
# ---- Secondary Variables

# ---- Rain ----
# Rain

if self['Rain'] is None:
self['Rain'] = calcul_rain_from_ptot(
Expand All @@ -166,9 +170,9 @@ def __init__(self, filename, *args, **kwargs):
x = calc_monthly_sum(self['Year'], self['Month'], self['Rain'])
self['monthly']['Rain'] = x[2]

self['normals']['Rain'] = calcul_monthly_normals(x[1], x[2])
self['normals']['Rain'] = calcul_monthly_normals(x[0], x[1], x[2])

# ---- Snow ----
# Snow

if self['Snow'] is None:
self['Snow'] = self['Ptot'] - self['Rain']
Expand All @@ -180,9 +184,9 @@ def __init__(self, filename, *args, **kwargs):
x = calc_monthly_sum(self['Year'], self['Month'], self['Snow'])
self['monthly']['Snow'] = x[2]

self['normals']['Snow'] = calcul_monthly_normals(x[1], x[2])
self['normals']['Snow'] = calcul_monthly_normals(x[0], x[1], x[2])

# ---- Potential Evapotranspiration ----
# Potential Evapotranspiration

if self['PET'] is None:
dates = [self['Year'], self['Month'], self['Day']]
Expand All @@ -198,7 +202,7 @@ def __init__(self, filename, *args, **kwargs):
x = calc_monthly_sum(self['Year'], self['Month'], self['PET'])
self['monthly']['PET'] = x[2]

self['normals']['PET'] = calcul_monthly_normals(x[1], x[2])
self['normals']['PET'] = calcul_monthly_normals(x[0], x[1], x[2])

print('-'*78)

Expand Down Expand Up @@ -349,7 +353,7 @@ def add_PET_to_weather_datafile(filename):

Tavg = data[:, vrbs.index('Mean Temp (deg C)')]
x = calc_monthly_mean(Year, Month, Tavg)
Ta = calcul_monthly_normals(x[1], x[2])
Ta = calcul_monthly_normals(x[0], x[1], x[2])

PET = calcul_Thornthwaite(Dates, Tavg, lat, Ta)

Expand Down Expand Up @@ -518,10 +522,18 @@ def fill_nan(time, data, name='data', fill_mode='zeros'):
# ----- Base functions: monthly downscaling

def calc_monthly_sum(yy_dly, mm_dly, x_dly):
"""
Calcul monthly cumulative values from daily values, where yy_dly are the
years, mm_dly are the months (1 to 12), and x_dly are the daily values.
"""
return calc_monthly(yy_dly, mm_dly, x_dly, np.sum)


def calc_monthly_mean(yy_dly, mm_dly, x_dly):
"""
Calcul monthly mean values from daily values, where yy_dly are the
years, mm_dly are the months (1 to 12), and x_dly are the daily values.
"""
return calc_monthly(yy_dly, mm_dly, x_dly, np.mean)


Expand All @@ -543,10 +555,26 @@ def calc_monthly(yy_dly, mm_dly, x_dly, func):
return yy_mly, mm_mly, x_mly


def calcul_monthly_normals(mm_mly, x_mly):
def calcul_monthly_normals(years, months, x_mly, yearmin=None, yearmax=None):
"""Calcul the monthly normals from monthly values."""
if len(years) != len(months) != len(x_mly):
raise ValueError("The dimension of the years, months, and x_mly array"
" must match exactly.")
if np.min(months) < 1 or np.max(months) > 12:
raise ValueError("Months values must be between 1 and 12.")

# Mark as nan monthly values that are outside the year range that is
# defined by yearmin and yearmax :
x_mly = np.copy(x_mly)
if yearmin is not None:
x_mly[years < yearmin] = np.nan
if yearmax is not None:
x_mly[years > yearmax] = np.nan

# Calcul the monthly normals :
x_norm = np.zeros(12)
for i, mm in enumerate(range(1, 13)):
indx = np.where((mm_mly == mm) & (~np.isnan(x_mly)))[0]
indx = np.where((months == mm) & (~np.isnan(x_mly)))[0]
if len(indx) > 0:
x_norm[i] = np.mean(x_mly[indx])
else:
Expand All @@ -558,10 +586,18 @@ def calcul_monthly_normals(mm_mly, x_mly):
# ----- Base functions: yearly downscaling

def calc_yearly_sum(yy_dly, x_dly):
"""
Calcul yearly cumulative values from daily values, where yy_dly are the
years and x_dly are the daily values.
"""
return calc_yearly(yy_dly, x_dly, np.sum)


def calc_yearly_mean(yy_dly, x_dly):
"""
Calcul yearly mean values from daily values, where yy_dly are the years
and x_dly are the daily values.
"""
return calc_yearly(yy_dly, x_dly, np.mean)


Expand Down
Loading