The goal is to create a wind rose like in this graphic:
The error itself occurs upon saving the plot via fig.savefig()
, but I got so far to realize that the error lies in the colormaps employed (e.g. taking into account this discussion).
The bar-plot was tried to be added to a WindroseAxes()
- axis - instance, which worked previously just fine.
This can be implemented via from windrose import WindroseAxes
.
I've mentioned it here for if it plays a role in the problem.
# * Instantiate windrose-axis related to the global figure and the just created rectangle
# NOTE on passing theta-labels: need to be passed, otherwise an error will be thrown like 'keyword "theta_labels" does not exist'
# --> from windrose.py: self.theta_labels = kwargs.pop("theta_labels") or ["E", "N-E", "N", "N-W", "W", "S-W", "S", "S-E"]
ax = WindroseAxes(fig, rect, theta_labels=theta_labels)
fig.add_axes(ax)
The specifics of the data-frame employed:
sub_df.info()
None
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 7130 entries, 2018-07-01 00:05:00+02:00 to 2018-07-31 23:55:00+02:00
Data columns (total 8 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Atm. pressure mean 7130 non-null float64
1 Daily cumulative precipitation 7130 non-null float64
2 Precipitation 7130 non-null float64
3 RH_mean 7130 non-null float64
4 T_mean 7130 non-null float64
5 Wind direction mean 7130 non-null float64
6 Wind speed max 7130 non-null float64
7 Wind speed mean 7130 non-null float64
dtypes: float64(8)
memory usage: 821.3 KB
In what follows, I'm going to delineate how the ax.bar()
- function (with the intent to plot a windrose) and the associated colorbar were plotted:
# * Define colormap
# Colormap increases the contrast from 0 to 1 in blue (or the color of choice)
# NOTE on type: <matplotlib.colors.LinearSegmentedColormap object at 0x7fd8b7d3d850>
cmap = plt.cm.Blues # pylint: disable=no-member
## * Get bins for colormap used for all subplots equally * ##
# i) Get maximum value
# Use .max() instead of max(), otherwise NaN could be considered the maximum
real_max_val = df[var_name].max()
# Maximum value here: 11 (m/s)
max_val = real_max_val.round()
# NOTE on scope: when rounded down, add 1 to make it greater than the actual maximum value
if max_val < real_max_val:
max_val += 1
# ii) Set the bins linearly (not logarithmically as often seen)
# NOTE: units are assumed in meters per second (m/s)
# NOTE on bins: divides each wind-bar into e.g. 6 bins == stepnumber in linspace (default)
# NOTE on minimum value: the lowest possible is 0 m/s
bins_bar_plot = np.linspace(0, max_val, num_of_bins) # (start, end, stepnumber)
cmap_norm = mpl.colors.Normalize(vmin=0, vmax=max_val)
# * Create plot based on the current sub-df
ax.bar(sub_df['Wind direction mean'],
sub_df['Wind speed mean'],
normed=True,
facecolor=(0.03137254901960784, 0.18823529411764706, 0.4196078431372549, 1.0),
bins=array([ 0. , 2.2, 4.4, 6.6, 8.8, 11. ]),
cmap=cmap,
alpha=1.0,
opening=1.0,
"grey"="grey",
linewidth=0.1)
The colorbar involved was then implemented like so:
fig.subplots_adjust(right=0.8)
# [x_coord start, y_coord start, total width, total height] - all in percent of the figure dimensions
cbar_ax = fig.add_axes([0.95, 0.15, 0.025, 0.7])
cbar = mpl.colorbar.ColorbarBase(cbar_ax,
cmap=cmap,
norm=cmap_norm,
spacing='proportional',
alpha=1.0)
cbar.set_label("{} {}".format('Wind speed mean', tools.units("Wind speed")),
color=None,
weight=None,
fontsize=None)
# NOTE: vertically oriented colorbar: y-label
# Length of ticklabels here: 6
new_yticklabels = np.linspace(0, max_val,
len(list(cbar.ax.get_yticklabels())))
new_yticklabels = np.around(new_yticklabels, decimals=1)
# New ticklabels here: array([ 0. , 2.2, 4.4, 6.6, 8.8, 11. ])
cbar.ax.set_yticklabels(new_yticklabels,
color=None,
weight=None,
fontsize=None)
The entire error-traceback printed in the console is:
ValueError Traceback (most recent call last)
~/Desktop/Programming/Python/Scripts/General/Plotting/windrose_plotting.py in <module>
184 textcolor="blue")
185 # * Carry out plot of the current sub-df
--> 186 plot.windrose_subplot(
187 df=df_plot.loc[m_loc],
188 desired_years=desired_years,
~/Dokumente/Allgemeines_material/Sonstiges/Programming/Python/Scripts/General/Plotting/plotting.py in windrose_subplot(df, figsize, groupby_freq, desired_years, desired_months, theta_labels, max_cols_per_row, ax_title_pos, cmap, y_coord_suptitle_dict, title_font_size, savepath, plot_file_extensions, normed, opening_bar_plot, num_of_bins, edgecolor, edge_linewidth, meteo_loc, add_info, transparent, alpha, label_color, font_weight, special_textfont_size, save_plotting_data_to_plain_text_AS_WELL, save_plotting_data_to_plain_text_ONLY)
6957
6958 # * Finally, either show or save the current plot
-> 6959 aux_plot.show_or_save_plot(path=savepath,
6960 basename=titlestr,
6961 transparent=transparent,
~/Dokumente/Allgemeines_material/Sonstiges/Programming/Python/Scripts/General/Plotting/auxiliary_plotting_functions.py in show_or_save_plot(fig, path, basename, file_extensions, dpi, legend, bbox_inches, transparent, legend_is_inside, remove_surrounding_whitespace, use_plotly, plotly_show_renderer, plotly_default_template, plotly_axlabel_size, plotly_title_label_size, plotly_font_family, plotly_font_color, linux_dir_sep, save_plotting_data_to_plain_text_AS_WELL, save_plotting_data_to_plain_text_ONLY)
3549
3550 # Carry out the saving procedure building up on the save-fig function
-> 3551 save_figs(path,
3552 fig=fig,
3553 file_extensions=file_extensions,
~/Dokumente/Allgemeines_material/Sonstiges/Programming/Python/Scripts/General/Plotting/auxiliary_plotting_functions.py in save_figs(filename, fig, file_extensions, dpi, standard_dpi, legend, bbox_inches, transparent, remove_surrounding_whitespace, legend_is_inside, linux_dir_sep, use_plotly, plotly_default_template, plotly_axlabel_size, plotly_title_label_size, plotly_font_family, plotly_font_color, save_plotting_data_to_plain_text_AS_WELL, save_plotting_data_to_plain_text_ONLY)
2395 if not remove_surrounding_whitespace:
2396 # Call savefig-method pertaining to a pyplot-fig-object with its provided kwargs
-> 2397 fig.savefig(filename + t,
2398 dpi=dpi,
2399 bbox_inches=bbox_inches,
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/figure.py in savefig(self, fname, transparent, **kwargs)
2309 patch.set_edgecolor('none')
2310
-> 2311 self.canvas.print_figure(fname, **kwargs)
2312
2313 if transparent:
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
2191 else suppress())
2192 with ctx:
-> 2193 self.figure.draw(renderer)
2194
2195 bbox_inches = self.figure.get_tightbbox(
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
39 renderer.start_filter()
40
---> 41 return draw(artist, renderer, *args, **kwargs)
42 finally:
43 if artist.get_agg_filter() is not None:
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/figure.py in draw(self, renderer)
1861
1862 self.patch.draw(renderer)
-> 1863 mimage._draw_list_compositing_images(
1864 renderer, self, artists, self.suppressComposite)
1865
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
130 if not_composite or not has_images:
131 for a in artists:
--> 132 a.draw(renderer)
133 else:
134 # Composite any adjacent images together
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/cbook/deprecation.py in wrapper(*inner_args, **inner_kwargs)
409 else deprecation_addendum,
410 **kwargs)
--> 411 return func(*inner_args, **inner_kwargs)
412
413 return wrapper
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/cbook/deprecation.py in wrapper(*inner_args, **inner_kwargs)
409 else deprecation_addendum,
410 **kwargs)
--> 411 return func(*inner_args, **inner_kwargs)
412
413 return wrapper
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/projections/polar.py in draw(self, renderer, *args, **kwargs)
993 self.yaxis.set_clip_path(self.patch)
994
--> 995 Axes.draw(self, renderer, *args, **kwargs)
996
997 def _gen_axes_patch(self):
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
39 renderer.start_filter()
40
---> 41 return draw(artist, renderer, *args, **kwargs)
42 finally:
43 if artist.get_agg_filter() is not None:
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/cbook/deprecation.py in wrapper(*inner_args, **inner_kwargs)
409 else deprecation_addendum,
410 **kwargs)
--> 411 return func(*inner_args, **inner_kwargs)
412
413 return wrapper
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/axes/_base.py in draw(self, renderer, inframe)
2746 renderer.stop_rasterizing()
2747
-> 2748 mimage._draw_list_compositing_images(renderer, self, artists)
2749
2750 renderer.close_group('axes')
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
130 if not_composite or not has_images:
131 for a in artists:
--> 132 a.draw(renderer)
133 else:
134 # Composite any adjacent images together
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
39 renderer.start_filter()
40
---> 41 return draw(artist, renderer, *args, **kwargs)
42 finally:
43 if artist.get_agg_filter() is not None:
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/axis.py in draw(self, renderer, *args, **kwargs)
1167
1168 for tick in ticks_to_draw:
-> 1169 tick.draw(renderer)
1170
1171 # scale up the axis label box to also find the neighbors, not
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
39 renderer.start_filter()
40
---> 41 return draw(artist, renderer, *args, **kwargs)
42 finally:
43 if artist.get_agg_filter() is not None:
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/axis.py in draw(self, renderer)
289 for artist in [self.gridline, self.tick1line, self.tick2line,
290 self.label1, self.label2]:
--> 291 artist.draw(renderer)
292 renderer.close_group(self.__name__)
293 self.stale = False
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
39 renderer.start_filter()
40
---> 41 return draw(artist, renderer, *args, **kwargs)
42 finally:
43 if artist.get_agg_filter() is not None:
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/text.py in draw(self, renderer)
695
696 gc = renderer.new_gc()
--> 697 gc.set_foreground(textobj.get_color())
698 gc.set_alpha(textobj.get_alpha())
699 gc.set_url(textobj._url)
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/backend_bases.py in set_foreground(self, fg, isRGBA)
953 self._rgb = fg
954 else:
--> 955 self._rgb = colors.to_rgba(fg)
956
957 def set_joinstyle(self, js):
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/colors.py in to_rgba(c, alpha)
187 rgba = None
188 if rgba is None: # Suppress exception chaining of cache lookup failure.
--> 189 rgba = _to_rgba_no_colorcycle(c, alpha)
190 try:
191 _colors_full_map.cache[c, alpha] = rgba
/home/linuxbrew/.linuxbrew/lib/python3.8/site-packages/matplotlib/colors.py in _to_rgba_no_colorcycle(c, alpha)
261 # tuple color.
262 if not np.iterable(c):
--> 263 raise ValueError(f"Invalid RGBA argument: {orig_c!r}")
264 if len(c) not in [3, 4]:
265 raise ValueError("RGBA sequence should have length 3 or 4")
ValueError: Invalid RGBA argument: None
As @JohanC pointed out, passing None
to the color
-kwarg of set_yticklabels
led to the quite counterintuitive error message of my question.
Avoiding None
did the trick, now it works.
To play it safe, I wrote a function which avoids passing None
to any of the key-value arguments ("kwargs") involved, which can be found below.
It is to automize everything and avoid too much coding in every plotting function where colored labels are desired. The function includes the cases of labeling axes, titles and colorbars.
def set_ticklabels_or_title_of_current_ax(ax_or_cbar=None,
labels=None,
label_type=None,
ax_title_pos=(0.5, 0.985),
label_color=None,
font_weight=None,
special_textfont_size=None):
"""Function docs:\n
Avoid too much code in the main plotting function.
# NOTE on scope: not all of them are accepted as None since they could override the initial value
# Docs: https://stackoverflow.com/questions/63245556/valueerror-invalid-rgba-argument-none-when-plotting-via-matplotlib-ax-bar?noredirect=1#comment111839077_63245556
"""
# Check tick type passed
if label_type is None:
raise Exception("The user must pass a tick type (x or y).")
# Check whether an axis has been passed by the user
if ax_or_cbar is None and label_type.lower() in [
"x", "x-axis", "y", "y-axis", "title"
]:
ax_or_cbar = plt.gca()
# In the case that all variables were passed as None, return the axis unchanged
# NOTE: the function used here "check_if_any_or_all_of_the_passed_vars_are_None()" is a custom function, not included here: can be ignored
if tools.check_if_any_or_all_of_the_passed_vars_are_None(
[label_color, font_weight, special_textfont_size],
raise_error_within_function=False,
any_is_None=False):
# Return the ax unchanged
return ax_or_cbar
# * Check if labels were passed * #
if labels is None:
if label_type.lower() in ["x", "x-axis"]:
labels = [elem.get_text() for elem in list(ax_or_cbar.get_xticklabels())]
elif label_type.lower() in ["y", "y-axis"]:
labels = [elem.get_text() for elem in list(ax_or_cbar.get_yticklabels())]
elif label_type.lower() in ["title", "cbar title"]:
raise Exception("No title label has been passed.")
elif label_type.lower() in [
"cbar yticklabels", "cbar yticks", "cbar y"
]:
labels = list(ax_or_cbar.ax.get_yticklabels())
# * Check which variables were passed as None * #
if label_color is not None and font_weight is not None and special_textfont_size is not None:
if label_type.lower() in ["x", "x-axis"]:
ax_or_cbar.set_xticklabels(labels,
color=label_color,
weight=font_weight,
fontsize=special_textfont_size)
elif label_type.lower() in ["y", "y-axis"]:
ax_or_cbar.set_yticklabels(labels,
color=label_color,
weight=font_weight,
fontsize=special_textfont_size)
elif label_type.lower() == "title":
ax_or_cbar.set_title(labels,
position=ax_title_pos,
color=label_color,
weight=font_weight,
fontsize=special_textfont_size)
elif label_type.lower() == "cbar title":
ax_or_cbar.set_label(labels,
color=label_color,
weight=font_weight,
fontsize=special_textfont_size)
elif label_type.lower() in [
"cbar yticklabels", "cbar yticks", "cbar y"
]:
ax_or_cbar.ax.set_yticklabels(labels,
color=label_color,
weight=font_weight,
fontsize=special_textfont_size)
elif label_color is not None and font_weight is not None and special_textfont_size is None:
if label_type.lower() in ["x", "x-axis"]:
ax_or_cbar.set_xticklabels(labels,
color=label_color,
weight=font_weight)
elif label_type.lower() in ["y", "y-axis"]:
ax_or_cbar.set_yticklabels(labels,
color=label_color,
weight=font_weight)
elif label_type.lower() == "title":
ax_or_cbar.set_title(labels,
position=ax_title_pos,
color=label_color,
weight=font_weight)
elif label_type.lower() == "cbar title":
ax_or_cbar.set_label(labels, color=label_color, weight=font_weight)
elif label_type.lower() in [
"cbar yticklabels", "cbar yticks", "cbar y"
]:
ax_or_cbar.ax.set_yticklabels(labels,
color=label_color,
weight=font_weight)
elif label_color is not None and font_weight is None and special_textfont_size is not None:
if label_type.lower() in ["x", "x-axis"]:
ax_or_cbar.set_xticklabels(labels,
color=label_color,
fontsize=special_textfont_size)
elif label_type.lower() in ["y", "y-axis"]:
ax_or_cbar.set_yticklabels(labels,
color=label_color,
fontsize=special_textfont_size)
elif label_type.lower() == "title":
ax_or_cbar.set_title(labels,
position=ax_title_pos,
color=label_color,
fontsize=special_textfont_size)
elif label_type.lower() == "cbar title":
ax_or_cbar.set_label(labels,
color=label_color,
fontsize=special_textfont_size)
elif label_type.lower() in [
"cbar yticklabels", "cbar yticks", "cbar y"
]:
ax_or_cbar.ax.set_yticklabels(labels,
color=label_color,
fontsize=special_textfont_size)
elif label_color is None and font_weight is not None and special_textfont_size is not None:
if label_type.lower() in ["x", "x-axis"]:
ax_or_cbar.set_xticklabels(labels,
weight=font_weight,
fontsize=special_textfont_size)
elif label_type.lower() in ["y", "y-axis"]:
ax_or_cbar.set_yticklabels(labels,
weight=font_weight,
fontsize=special_textfont_size)
elif label_type.lower() == "title":
ax_or_cbar.set_title(labels,
position=ax_title_pos,
weight=font_weight,
fontsize=special_textfont_size)
elif label_type.lower() == "cbar title":
ax_or_cbar.set_label(labels,
weight=font_weight,
fontsize=special_textfont_size)
elif label_type.lower() in [
"cbar yticklabels", "cbar yticks", "cbar y"
]:
ax_or_cbar.ax.set_yticklabels(labels,
weight=font_weight,
fontsize=special_textfont_size)
elif label_color is None and font_weight is None and special_textfont_size is not None:
if label_type.lower() in ["x", "x-axis"]:
ax_or_cbar.set_xticklabels(labels, fontsize=special_textfont_size)
elif label_type.lower() in ["y", "y-axis"]:
ax_or_cbar.set_yticklabels(labels, fontsize=special_textfont_size)
elif label_type.lower() == "title":
ax_or_cbar.set_title(labels,
position=ax_title_pos,
fontsize=special_textfont_size)
elif label_type.lower() == "cbar title":
ax_or_cbar.set_label(labels, fontsize=special_textfont_size)
elif label_type.lower() in [
"cbar yticklabels", "cbar yticks", "cbar y"
]:
ax_or_cbar.ax.set_yticklabels(labels,
fontsize=special_textfont_size)
elif label_color is None and font_weight is not None and special_textfont_size is None:
if label_type.lower() in ["x", "x-axis"]:
ax_or_cbar.set_xticklabels(labels, weight=font_weight)
elif label_type.lower() in ["y", "y-axis"]:
ax_or_cbar.set_yticklabels(labels, weight=font_weight)
elif label_type.lower() == "title":
ax_or_cbar.set_title(labels,
position=ax_title_pos,
weight=font_weight)
elif label_type.lower() == "cbar title":
ax_or_cbar.set_label(labels, weight=font_weight)
elif label_type.lower() in [
"cbar yticklabels", "cbar yticks", "cbar y"
]:
ax_or_cbar.ax.set_yticklabels(labels, weight=font_weight)
elif label_color is not None and font_weight is None and special_textfont_size is None:
if label_type.lower() in ["x", "x-axis"]:
ax_or_cbar.set_xticklabels(labels, color=label_color)
elif label_type.lower() in ["y", "y-axis"]:
ax_or_cbar.set_yticklabels(labels, color=label_color)
elif label_type.lower() == "title":
ax_or_cbar.set_title(labels,
position=ax_title_pos,
color=label_color)
elif label_type.lower() == "cbar title":
ax_or_cbar.set_label(labels, color=label_color)
elif label_type.lower() in [
"cbar yticklabels", "cbar yticks", "cbar y"
]:
ax_or_cbar.ax.set_yticklabels(labels, color=label_color)
# Return updated axis to user
return ax_or_cbar