# Wind barb bug

Hi Matplotlib Users,

When I make wind barbs with rounding enabled and custom barb increments I noticed that there were no wind barbs with half barbs above 2 full barbs. The reason seems to be a bug in the _find_tails method. The bug is illustrated by this small script (_find_tails is a copy of the one in matplotlib):

import numpy as np

def _find_tails(self, mag, rounding=True, half=5, full=10, flag=50):
‘’’
Find how many of each of the tail pieces is necessary. Flag
specifies the increment for a flag, barb for a full barb, and half for
half a barb. Mag should be the magnitude of a vector (ie. >= 0).

``````This returns a tuple of:

(*number of flags*, *number of barbs*, *half_flag*, *empty_flag*)

*half_flag* is a boolean whether half of a barb is needed,
since there should only ever be one half on a given
barb. *empty_flag* flag is an array of flags to easily tell if
a barb is empty (too low to plot any barbs/flags.
'''

#If rounding, round to the nearest multiple of half, the smallest
#increment
if rounding:
mag = half * (mag / half + 0.5).astype([np.int](http://np.int))

num_flags = np.floor(mag / flag).astype([np.int](http://np.int))
mag = np.mod(mag, flag)

num_barb = np.floor(mag / full).astype([np.int](http://np.int))
mag = np.mod(mag, full)

half_flag = mag >= half
empty_flag = ~(half_flag | (num_flags > 0) | (num_barb > 0))

return num_flags, num_barb, half_flag, empty_flag
``````

def main():
mag = np.arange(0,21,1)
barb_incs = {‘half’: 2.57222,
‘full’: 5.14444,
‘flag’: 25.7222}
print ‘With rounding’
num_flags, num_barb, half_flag, empty_flag = _find_tails(None, mag, rounding=True, **barb_incs)
for i in range(len(mag)):
print mag[i], num_flags[i], num_barb[i], half_flag[i], empty_flag[i]
print ‘Without rounding’
num_flags, num_barb, half_flag, empty_flag = _find_tails(None, mag, rounding=False, **barb_incs)
for i in range(len(mag)):
print mag[i], num_flags[i], num_barb[i], half_flag[i], empty_flag[i]

if name == ‘main’:
exit(main())

It seems like the error is not present when the barb increments are not set. I believe the reason for the bug is the float comparison (half_flag = mag >= half) where the value is rounded to a value very close to/identical to the ‘half’ increment. And it seems like python does the right thing when the “half” increment is a whole number but not always when it is not.

But in any case the code should probably not depend two floats being equal.

Best regards,

Jesper

Jesper,

Can you open an issue on this on github. If you are feeling ambitious a pull request fixing the bug (as you seem to have a good idea of where the problem is) would also be great!

Tom

···

On Fri, Apr 24, 2015 at 8:38 AM Jesper Larsen <jesper.webmail@…287…> wrote:

Hi Matplotlib Users,

When I make wind barbs with rounding enabled and custom barb increments I noticed that there were no wind barbs with half barbs above 2 full barbs. The reason seems to be a bug in the _find_tails method. The bug is illustrated by this small script (_find_tails is a copy of the one in matplotlib):

import numpy as np

def _find_tails(self, mag, rounding=True, half=5, full=10, flag=50):
‘’’
Find how many of each of the tail pieces is necessary. Flag
specifies the increment for a flag, barb for a full barb, and half for
half a barb. Mag should be the magnitude of a vector (ie. >= 0).

``````This returns a tuple of:

(*number of flags*, *number of barbs*, *half_flag*, *empty_flag*)

*half_flag* is a boolean whether half of a barb is needed,
since there should only ever be one half on a given
barb. *empty_flag* flag is an array of flags to easily tell if
a barb is empty (too low to plot any barbs/flags.
'''

#If rounding, round to the nearest multiple of half, the smallest
#increment
if rounding:
mag = half * (mag / half + 0.5).astype([np.int](http://np.int))

num_flags = np.floor(mag / flag).astype([np.int](http://np.int))
mag = np.mod(mag, flag)

num_barb = np.floor(mag / full).astype([np.int](http://np.int))
mag = np.mod(mag, full)

half_flag = mag >= half
empty_flag = ~(half_flag | (num_flags > 0) | (num_barb > 0))

return num_flags, num_barb, half_flag, empty_flag
``````

def main():
mag = np.arange(0,21,1)
barb_incs = {‘half’: 2.57222,
‘full’: 5.14444,
‘flag’: 25.7222}
print ‘With rounding’
num_flags, num_barb, half_flag, empty_flag = _find_tails(None, mag, rounding=True, **barb_incs)
for i in range(len(mag)):
print mag[i], num_flags[i], num_barb[i], half_flag[i], empty_flag[i]
print ‘Without rounding’
num_flags, num_barb, half_flag, empty_flag = _find_tails(None, mag, rounding=False, **barb_incs)
for i in range(len(mag)):
print mag[i], num_flags[i], num_barb[i], half_flag[i], empty_flag[i]

if name == ‘main’:
exit(main())

It seems like the error is not present when the barb increments are not set. I believe the reason for the bug is the float comparison (half_flag = mag >= half) where the value is rounded to a value very close to/identical to the ‘half’ increment. And it seems like python does the right thing when the “half” increment is a whole number but not always when it is not.

But in any case the code should probably not depend two floats being equal.

Best regards,

Jesper

One dashboard for servers and applications across Physical-Virtual-Cloud

Widest out-of-the-box monitoring support with 50+ applications

Performance metrics, stats and reports that give you Actionable Insights

Deep dive visibility with transaction tracing using APM Insight.

Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Hi Tom,

Thanks for the reply. I will open it as an issue on github.

Best regards,

Jesper

···

2015-04-25 22:20 GMT+02:00 Thomas Caswell <tcaswell@…287…>:

Jesper,

Can you open an issue on this on github. If you are feeling ambitious a pull request fixing the bug (as you seem to have a good idea of where the problem is) would also be great!

Tom

On Fri, Apr 24, 2015 at 8:38 AM Jesper Larsen <jesper.webmail@…287…> wrote:

Hi Matplotlib Users,

When I make wind barbs with rounding enabled and custom barb increments I noticed that there were no wind barbs with half barbs above 2 full barbs. The reason seems to be a bug in the _find_tails method. The bug is illustrated by this small script (_find_tails is a copy of the one in matplotlib):

import numpy as np

def _find_tails(self, mag, rounding=True, half=5, full=10, flag=50):
‘’’
Find how many of each of the tail pieces is necessary. Flag
specifies the increment for a flag, barb for a full barb, and half for
half a barb. Mag should be the magnitude of a vector (ie. >= 0).

``````This returns a tuple of:

(*number of flags*, *number of barbs*, *half_flag*, *empty_flag*)

*half_flag* is a boolean whether half of a barb is needed,
since there should only ever be one half on a given
barb. *empty_flag* flag is an array of flags to easily tell if
a barb is empty (too low to plot any barbs/flags.
'''

#If rounding, round to the nearest multiple of half, the smallest
#increment
if rounding:
mag = half * (mag / half + 0.5).astype([np.int](http://np.int))

num_flags = np.floor(mag / flag).astype([np.int](http://np.int))
mag = np.mod(mag, flag)

num_barb = np.floor(mag / full).astype([np.int](http://np.int))
mag = np.mod(mag, full)

half_flag = mag >= half
empty_flag = ~(half_flag | (num_flags > 0) | (num_barb > 0))

return num_flags, num_barb, half_flag, empty_flag
``````

def main():
mag = np.arange(0,21,1)
barb_incs = {‘half’: 2.57222,
‘full’: 5.14444,
‘flag’: 25.7222}
print ‘With rounding’
num_flags, num_barb, half_flag, empty_flag = _find_tails(None, mag, rounding=True, **barb_incs)
for i in range(len(mag)):
print mag[i], num_flags[i], num_barb[i], half_flag[i], empty_flag[i]
print ‘Without rounding’
num_flags, num_barb, half_flag, empty_flag = _find_tails(None, mag, rounding=False, **barb_incs)
for i in range(len(mag)):
print mag[i], num_flags[i], num_barb[i], half_flag[i], empty_flag[i]

if name == ‘main’:
exit(main())

It seems like the error is not present when the barb increments are not set. I believe the reason for the bug is the float comparison (half_flag = mag >= half) where the value is rounded to a value very close to/identical to the ‘half’ increment. And it seems like python does the right thing when the “half” increment is a whole number but not always when it is not.

But in any case the code should probably not depend two floats being equal.

Best regards,

Jesper

One dashboard for servers and applications across Physical-Virtual-Cloud

Widest out-of-the-box monitoring support with 50+ applications

Performance metrics, stats and reports that give you Actionable Insights

Deep dive visibility with transaction tracing using APM Insight.