Wind Rose Differences


I was trying something out and noticed that there are differences in wind roses coming out of ladybug as compared to other (examples shown below). Can someone help me understand why clima website and climatestudio has similar output set than ladybug and epwvis (using the same weather file for all options)

clima website:

Climate Studio:



Hi Hmurya,

One key thing might be how they’re dealing with still conditions, some tools may assign data associated with still conditions to north direction (potentially what’s happening with Ladybug and EPWvis).

Clima and climate studio seem to be set to different numbers of radial segments which will also have an impact - best to set them all to same number of wind directions (eg 16) before comparing if possible.

Hey Charlie, tried setting different radial conditions but ladybug is heavily inclined still towards the North direction. Guess its just how ladybug is assigning the conditions.

Hey Hmurya, are you visualising wind speed on the wind rose or some other variable? Keen to have a look myself at what Ladybug does. Also are you using version 1 onwards or the legacy component?

Hey Charlie,

Doing just the wind speed using 1.4.0 version (but i checked legacy and the results are the same)

Below is a comparison of both of them in 12 directions, similar frequencies and just for the month of January:


Interesting. I get a similar issue to you for a Riyadh weather file

Here’s clima:

Here’s LBT 1.4:

I deconstructed the data and did a quick test using domains to categorise the epw data and moved points from the origin a distance based on the number of values in each domain. I got the same result as LBT, and I also spot checked the epw file to check LBT was reading it correctly (it was). That leaves me to think Clima is doing it incorrectly, which I can’t really believe. Would be good if someone else on the forum has other ideas.

Trying another weather file, Southampton UK, I get this:


Less of an extreme difference but LBT is still reporting more north than Clima is

I’ve also tried culling wind speeds below values based on a slider, but that doesn’t seem to impact things significantly enough to explain the difference.

Thanks for digging into this @charlie.brooker and @hmurya .

I feel pretty confident that Ladybug is doing a faithful interpretation of the EPW data but I still have a theory of what could be going on here.

I have seen some EPWs were the weather station source does not actually have wind direction data and, instead of using the EnergyPlus missing value of 999 (like they are supposed to), they use a wind direction of 0 or 360 for north. So it’s possible that Clima is using something implicit to determine that certain hours don’t actually have wind direction data and it’s therefore discounting them in the resulting wind rose. Maybe it’s that certain hours have a direction of 0 and this is (or is not) supposed to be counted as “real” data while a direction of 360 is (or is not) supposed to be treated as missing data.

If we can figure this out (and ideally confirm with the Clima people that this is the assumption they are using), I would be happy to add some options into the LB WindRose component that will try to discount these hours. Actually, you can probably already test this now using a conditional statement_.

@chris you are probably correct in your understanding. I went digging a bit more after what @charlie.brooker posted.

Checked a few weather sites for windroses for riyadh and they are very close to what ladybug is giving (predominant winds from N/NW side and SSE side), so I guess you are somewhat correct in the understanding that clima is probably not reading it right. I do have a question, if I am uploading the same EPW file I am using for ladybug onto clima, shouldnt it read the same data too?

Riyadh windroses links:

So I’m pretty sure that I figured out that Clima is disregarding all hours where the wind direction is less than 10 degrees and only counting wind directions of 350 as a valid North direction. A simple Ladybug conditional statement on the wind direction gives me something that is pretty much identical between Ladybug and Clima:


Now, the only thing that I’m unsure of is whether this is actually a bug in Clima or is this some implicit convention across EPW files that I am unaware of. The EnergyPlus reference on Wind Direction seems pretty clear that 0 is supposed to signify North so I’m a little hesitant to make any changes. This is especially because people can currently decide for themselves what is supposed to be valid by applying their own conditional statement.

Needless to say, if anyone with more knowledge on this knows some implicit convention that is being used in Clima that I’m unaware of, I’m happy to try to add support for it in Ladybug.


Thanks for looking into it. I was just cautious because we use these to do outdoor analysis so its good to know that ladybug is correct.

I’ll get in touch with someone at clima to see how they are presenting their wind roses.

1 Like

Hi Chris,
Giovanni here, one of the authors of Clima.
My suspicion is that there might be a difference in the way we treat the calm occurrences (wind speed less than 0.5m/s in Clima)
When the wind speed is so low the direction is usually defaulted to zero, but no wind doesn’t mean wind from the north in my mind :wink:
In Clima the “calm” is represented as a white circle at the centre of the wind rose, that equally offsets all directions. I believe Climate Studio takes a similar approach.
Ladybug reports “calm” occurrences, but I am not sure how they are visualized.

Of course it’s also possible there is a bug in our code! hope not! :sweat_smile:

1 Like

Thanks for the quick response @gbetti !

I tested your hypothesis but it unfortunately does not seem to be correct. The ladybug wind rose also supports the option of a calm circle in the center and people have the option of turning it on or off but the issue here seems to be independent of that and it’s specifically for the north direction only. You can see that this is what the wind rose for Riyadh (IWEC) looks like with the calm center:

Now, if I apply a conditional statement to remove any hours where the wind speed is less than 0.5 m/s, I get the following, which is still a far cry from the Clima wind rose:

I can remove all hours with a wind speed less than 1 m/s and it still does not look like Clima:

Only when I remove any wind directions that are 10 degrees or less do I get something that looks like the Clima wind rose for Riyadh:


Are you absolutely certain that there isn’t a bug in Clima here? Or some other explanation that is independent of the wind speed?

1 Like

Maybe the error’s at 11.25, not 10… For a windrose split into 16 segments, you include directions at 22.5 degree increments (360 / 16 = 22.5), but the north angle has an edge case of having to include directions less then 11.25 and greater then 360 - 11.25, which explains why it’s just north with the problem.

1 Like

This has been playing on my mind, so I just had a dig through the Clima code.

It looks like the wind rose code is here:

def wind_rose(df, title, month, hour, labels):
    """Return the wind rose figure.
    Based on:
    start_month = month[0]
    end_month = month[1]
    start_hour = hour[0]
    end_hour = hour[1]
    if start_month <= end_month:
        df = df.loc[(df["month"] >= start_month) & (df["month"] <= end_month)]
        df = df.loc[(df["month"] <= end_month) | (df["month"] >= start_month)]
    if start_hour <= end_hour:
        df = df.loc[(df["hour"] >= start_hour) & (df["hour"] <= end_hour)]
        df = df.loc[(df["hour"] <= end_hour) | (df["hour"] >= start_hour)]

    spd_colors = mapping_dictionary["wind_speed"]["color"]
    spd_bins = [-1, 0.5, 1.5, 3.3, 5.5, 7.9, 10.7, 13.8, 17.1, 20.7, np.inf]
    spd_labels = speed_labels(spd_bins, units="m/s")
    dir_bins = np.arange(-22.5 / 2, 370, 22.5)
    dir_labels = (dir_bins[:-1] + dir_bins[1:]) / 2
    total_count = df.shape[0]
    calm_count = df.query("wind_speed == 0").shape[0]
    rose = (
            WindSpd_bins=lambda df: pd.cut(
                df["wind_speed"], bins=spd_bins, labels=spd_labels, right=True
            WindDir_bins=lambda df: pd.cut(
                df["wind_dir"], bins=dir_bins, labels=dir_labels, right=False
        .replace({"WindDir_bins": {360: 0}})
        .groupby(by=["WindSpd_bins", "WindDir_bins"])
        .assign(calm=lambda df: calm_count / df.shape[0])
        .applymap(lambda x: x / total_count * 100)
    fig = go.Figure()

Trying to spot the issue by reading the code I think it could be in

dir_bins = np.arange(-22.5 / 2, 370, 22.5)

As the first bin will be -11.25:11.25 and the final bin will be 326.25:348.75. Am I right that Clima isn’t counting values from 348.75:360 as being north?


I think I must be making a mistake though (my python is very basic). Testing this out with a conditional statement in LBT doesn’t give the same result as Clima on the Riyadh weather file:

All wind directions:

Wind directions <349 with conditional statement:

Categorising the epw wind directions for non calm (<0.5m/s) hours there’s:

  • 7122 non calm hours
  • 579 0° hours
  • 332 10° hours
  • 370 350° hours

Chris your suggestion that values under 10° looks correct. Potentially this part is overwriting all values less than 11.25° with the values for when the direction is >348.75°

.replace({"WindDir_bins": {360: 0}})
1 Like

Maybe! It’s definitely omitting the >348.75 range, but it may be resolved later in the code, and I also don’t see how that aligns with the <11.25 behaviour we’re seeing. I can’t figure it out…

@gbetti what do you think?

1 Like

thank you all @charlie.brooker @chris @SaeranVasanthakumar and all the others that chimed in!
We had a bug on our end!
the line:

dir_bins = np.arange(-22.5/2, 370, 22.5)

(Why 370???)

was generating bins with the following labels

dir_labels = (dir_bins[:-1] + dir_bins[1:]) / 2
[  0.   22.5  45.   67.5  90.  112.5 135.  157.5 180.  202.5 225.  247.5
 270.  292.5 315.  337.5]

360 is missing!!!

the problem is solved with:

dir_bins = np.arange(-22.5/2, 360+22.5, 22.5)
dir_labels = (dir_bins[:-1] + dir_bins[1:]) / 2
[  0.   22.5  45.   67.5  90.  112.5 135.  157.5 180.  202.5 225.  247.5
 270.  292.5 315.  337.5 360. ]

and this is the resulting windrose for Riyadh:
CBE_Clima_RIYADH_Heating and Cooling Degree-Days (3)

Thank you for your help! :heart:
We’ll fix it asap in the live version


Thanks a lot for looking into this and fixing it so quickly!