dankelley / oce

R package for oceanographic processing
http://dankelley.github.io/oce/
GNU General Public License v3.0
142 stars 42 forks source link

Meteorology Display #2191

Closed dankelley closed 5 months ago

dankelley commented 6 months ago

Discussed in https://github.com/dankelley/oce/discussions/2190

Originally posted by **mdupilka** February 17, 2024 Hi, I use the OCE package regularly to map meteorology fields for my work. Do you have any thoughts of possibly extending OCE to display meteorology data such as wind fields using wind barbs? Regards, Max
dankelley commented 6 months ago

Hi. First, I made this into an issue, not a discussion. That's because I regularly look at issues, as a sort of to-do list. Also, I'm tagging @richardsc and @clayton33, who might have thoughts on whether this would be useful.

As for your question, that's something that I've thought of, but wasn't sure there would be enough interest. I am always thinking of new ways to plot data, and usually try them outside oce to start (see e.g. https://dankelley.github.io/dek_blog/2024/02/03/scotian-shelf-shaded.html) because then testing is a lot faster. (Building oce takes about 5 minutes on my machine, for example, and lots of users don't even have the C compilers, etc. required to build oce from source.)

Question: is there a source that you consider definitive, for how to draw barbs? For example, I just searched and found a top hit as https://www.weather.gov/hfo/windbarbinfo but that is in Empirical units (mps and knots) and I wonder if that is what is used outside the US, where km/h is likely used. I would need a source that is stable, non-commercial, and of course that does not need registration or the answering of questions about cookies. (CRAN does not permit using any such web citations. Packages that cite websources that cannot be reached by their algorithm get rejected. That's quite a lot of sites that you can visit easily ... it has something to do with whether sites can answer certain queries, not whether you can see them in a browser.)

If you can provide some sources for me to read, that would help. I like having something I can cite in the help for a function. For example, I might say "see page 145 of https://tc.canada.ca/sites/default/files/2020-10/aim-2020-2_met-e.pdf", which is something from the Transport Canada federal agency. Also, if I can get a list of sources I can see variants. Some will be much faster to plot than others. If it can be done with straight lines, for example, that will be a lot faster. I think it will be a slow function anyway, but waiting 20 seconds or so for a plot that is desired is better than waiting 0.5 seconds for something that is unwanted.

PS. you're aware of https://dankelley.github.io/oce/reference/drawDirectionField.html I assume? The last diagram you see there might be a start. I realize it's not the same, of course. This is how ocean people usually like to plot flow fields. But there is the problem of overlap, and that is alleviated by barbs, which are of equal length. That is where I think this could be useful.

PPS. it's too bad you didn't ask before Christmas. Last term I was teaching an oceanography class in which half the students were meteorologists. They could tell me in a flash things like (a) whether definitions vary across nations, (b) which is preferred in today's practice and (c) are there variants that would make sense to them, but not be expensive to plot. (This last is because things with line segments will be faster than things with curved segments. Faster by a lot.)

dankelley commented 6 months ago

PS. I found the following but it's from a site that we cannot use as a source (it's not open enough) and it says that it comes from another site that doesn't even exist.

dankelley commented 6 months ago

https://www.weather.gov/hfo/windbarbinfo seems like a source that could be cited and is likely definitive (for an audience in the USA, anyway ... I still do wonder whether knots are used in all nations.) Below is a snapshot.

So far, I see three notations for the starting location: show open circle, show filled circle or show no circle.

Interestingly, I see in the below that the angles are quantized. I never realized that before. This is fun.

Screenshot 2024-02-18 at 7 33 53 AM
dankelley commented 6 months ago

Um, the image in the just-previous comment lacks barb examples for 40 and 45 knots. So it is not really rounded to nearest 5 knots, as they state. Surely something is supposed to be plotted in those categories. Can you shed light on this, @mdupilka? I imagine there is a better source out there somewhere.

dankelley commented 6 months ago

Another source http://ww2010.atmos.uiuc.edu/(Gh)/guides/maps/sfcobs/wnd.rxml is similar (apart from the ugly starting point) but it lacks some categories.

Screenshot 2024-02-18 at 9 21 30 AM
dankelley commented 6 months ago

I see that matplotlib has something (https://matplotlib.org/stable/gallery/images_contours_and_fields/barb_demo.html) and my guess is that some users will be familiar with that notation. I'll look into this, whilst waiting to see if others in this thread have any suggestions.

My main concerns right now are

  1. what to do in the speed gaps that I see in the examples?
  2. which of many conventions to follow
  3. what is a (CRAN-acceptable) source that can be cited in docs?
dankelley commented 6 months ago

Below is a reprex of an initial test. If you rerun it, you'll get different results because it uses a random number. This just tests

  1. setting to uniform length
  2. discretization of angles on a "36 point compass", which I see in one of the sources noted above
  3. categorization into barb category (which is an unsettled issue given the speed-gaps alluded to previously)

This draws just 1 barb, and the feathers are not yet drawn. I would like to have clarity on the speed gaps before doing that. I think the scheme is a bit like "making change" on a cash register. Put another way, it's a bit like Roman numerals. (I realize that making change and Roman numerals are historical artifacts, but so are these weather maps, I think.)

Please click the word below, to see this test. (@richardsc and @clayton33 will know that I am just doing my usual thing, of starting with something crude and simple. I do lots of little modifications of tests like this. Only when things are pretty clear do I consider putting code into oce.)

``` r met <- TRUE # set TRUE for barbs pointing to wind source scale <- 0.5 debug <- TRUE par(mar = c(3, 3, 4, 2)) # using top margin for notes plot(c(-1, 1), c(-1, 1), xlab = "", ylab = "", asp = 1, type = "n") x0 <- 0 y0 <- 0 u <- rnorm(1, sd = 10) v <- rnorm(1, sd = 10) uOrig <- u vOrig <- v if (met) { u <- -u v <- -v } angle <- 180 / pi * atan2(v, u) # Barbs are drawn at angles on a 36-point compass angle36 <- 10 * round(angle / 10) # Barbs are defined in terms of knots, rounded to nearest 5 speed <- sqrt(u^2 + v^2) knot <- speed * 1.94384 knot5 <- 5L * as.integer(round(knot / 5)) barbType <- 1 + knot5 / 5 points(x0, y0) S <- sinpi(angle36 / 180) C <- cospi(angle36 / 180) speed #> [1] 7.438785 x1 <- x0 + scale * S y1 <- y0 + scale * C # guiding circles to test angle and length if (debug) { circlex <- scale * cos(pi / 180 * seq(0, 360, 10)) circley <- scale * sin(pi / 180 * seq(0, 360, 10)) lines(circlex, circley, type = "o", pch = 20, col = 4) } notStill <- knot5 != 0 segments(x0[notStill], y0[notStill], x1[notStill], y1[notStill]) mtext(sprintf( "x0=%.2g y0=%.2g u=%.2gm/s v=%.2gm/s speed=%.2gm/s knot=%.2g knot5=%g barbType=%d", x0, y0, uOrig, vOrig, speed, knot, knot5, barbType ), line = 0) mtext("FIXME: draw barbs", line = 1) ``` ![](https://i.imgur.com/95UsKBP.png) Created on 2024-02-18 with [reprex v2.1.0](https://reprex.tidyverse.org)
dankelley commented 6 months ago

Oh, I think the diagram above at https://github.com/dankelley/oce/issues/2191#issuecomment-1951198920 answers my questions about wind-speed gaps. I'll take a shot at coding this. It really is like making change, drawing in the reverse order as you do the sums in your head.

dankelley commented 6 months ago

Here's a sketch of the 'making change' type algorithm.

feathers <- function(u) {
    pos <- 0
    # Handle triangle feathers
    while (u > 50) {
        cat("draw 50 at", pos, "\n")
        u <- u - 50
        pos <- pos + 1
    }
    # Handle Long feathers
    while (u > 10) {
        cat("draw 10 at", pos, "\n")
        u <- u - 10
        pos <- pos + 1
    }
    # Handle short feathers
    while (u > 5) {
        cat("draw 5 at", pos, "\n")
        u <- u - 5
        pos <- pos + 1
    }
}
richardsc commented 6 months ago

Hi all!

First, because this was opened as a "discussion", I think it's worth discussing whether it makes sense to add more meteorology functionality to oce (this is a discussion that @dankelley and I have more and more with new feature requests, due to the burdens of maintaining what is already a very large package, and that the build requirements for users are somewhat challenging). I can see a number of different points, for and against:

  1. oce is a package designed for oceanographic data analysis, so functionality that drifts too far from that might be better in a dedicated package
  2. However, oceanography and meteorology are intrinsically linked so it could be argued that having the functionality together makes sense
  3. A change like the one being discussed (and that @dankelley has already started working on, lol) might be as simple as just adding a new "arrow type" to the existing drawDirectionField() and mapDirectionField() (so, fairly minimal change)
  4. As mentioned already, oce is very big (bloated?) and already difficult to maintain. Adding new features might be better added as separate packages that depend on oce (e.g. as the argoFloats package does).

There are probably more points that could be made, but that's a start.

I think I'm mostly in the camp of number 3, and kind of like the idea of being able to have wind-barb maps. But I would caution about adding too many other meteorologically-specific functions beyond that (if that is what @mdupilka is proposing).

richardsc commented 6 months ago

Oh, and I don't know if this meets any of your needs @mdupilka, but do you know about the metR package?

dankelley commented 6 months ago

I'll add another question to Clark's good list:

  1. How many oceanographers (oce users and others) understand the barbs on a wind diagram? I didn't, until this morning. And it took me a while to figure it out, from a fair bit of web searching.
dankelley commented 6 months ago

Re clark's item 3, it is not actually that minimal. There is that "making change" computation, for one thing. And the there is the matter of doing the trig to add the feathers. The existing drawDirectionField() relies on built-in arrow types, which are done in C, so the trig is (a) much faster and (b) well-tested against problem cases.

I've enjoyed playing with this, but thinking of it during my run, it doesn't feel like a good fit for oce. I'd vote -0.8 on "add this feature". Perhaps @richardsc and @clayton33 can vote on the -1 to 1 scale we use for making decisions. No rush -- I think tomorrow is a holiday here anyway.

mdupilka commented 6 months ago

Thanks for the discussion. I can only imagine the work required for maintain the OCE package. Thanks a lot for that. I do use the mapDirectionField functions to draw wind vectors. It works very well. I do not have any reference for the wind barbs, The https://www.weather.gov/hfo/windbarbinfo is a standard format for wind barbs. Meteorology pretty much always uses knots for speed, which is a standard for aviation. But some software does give options for km/h display. I can understand the extra work to incorporate meteorology displays would make the package even more "bloated". Tomorrow is a holiday in parts of Canada as well.

mdupilka commented 6 months ago

I don't know if this may be of any interest, back many years ago I wrote a C++ program to display wind winds. Here is the code for the wind barbs

const double DegToRad = 3.141593/180.; const int BarbLength = 30; const double BarbSpeedAngle = 60.; const int BarbSpeedLength = 10; const int BarbInt = 3; double WindDirection = 90. - WndDir; TPoint TriangleVert[3]; dc->SelectObject(*BlackPen); dc->SelectObject(*BlackBrush); //Draw wind barb from center of station int Num; if(DrawAll) //Draw all stations and ignore the passed station number Num = NumStations; else //Just draw for the passed station number Num = StnNum + 1; for(int i = StnNum; i < Num; i++) { if(Stations[i].y > yFrontPosition && Stations[i].spd > 0) { //Set the origin int x0 = Stations[i].x; int y0 = Stations[i].y; //Set the end point int x1 = x0 + BarbLength * cos(WindDirection*DegToRad); int y1 = y0 + BarbLength * sin(WindDirection*DegToRad); dc->MoveTo(x0, maxY - y0); dc->LineTo(x1, maxY - y1); //Draw the wind speed 50 knot triangles //Number of 50 knots int Num50Tri = int((Stations[i].spd + 2.5)/50.); int Space = 0; //Draw the 50 knot triangles for(int j = 0; j < Num50Tri; j++) { TriangleVert[0].x = x0 + (BarbLength - j*BarbSpeedLength) * cos(WindDirection*DegToRad); TriangleVert[0].y = y0 + (BarbLength - j*BarbSpeedLength) * sin(WindDirection*DegToRad); TriangleVert[1].x = x0 + (BarbLength - BarbSpeedLength - j*BarbSpeedLength) * cos(WindDirection*DegToRad); TriangleVert[1].y = y0 + (BarbLength - BarbSpeedLength - j*BarbSpeedLength) * sin(WindDirection*DegToRad); TriangleVert[2].x = TriangleVert[1].x + BarbSpeedLength * cos((WindDirection - BarbSpeedAngle)*DegToRad); TriangleVert[2].y = TriangleVert[1].y + BarbSpeedLength * sin((WindDirection - BarbSpeedAngle)*DegToRad); TriangleVert[0].y = maxY - TriangleVert[0].y; TriangleVert[1].y = maxY - TriangleVert[1].y; TriangleVert[2].y = maxY - TriangleVert[2].y; dc->Polygon(TriangleVert, 3); //Set position for next 10 knot barbs Space = (j+1)*BarbSpeedLength + BarbInt; } //Draw the 10 knots wind speed barbs //Number of 10 knot barbs int Num10Barbs = int(fmod((Stations[i].spd + 2.5), 50.)/10.); //Draw the 10 knot barbs for(j = 0; j < Num10Barbs; j++) { int x2 = x0 + (BarbLength - (j*BarbInt + Space)) * cos(WindDirection*DegToRad); int y2 = y0 + (BarbLength - (j*BarbInt + Space)) * sin(WindDirection*DegToRad); int x3 = x2 + BarbSpeedLength * cos((WindDirection - BarbSpeedAngle)*DegToRad); int y3 = y2 + BarbSpeedLength * sin((WindDirection - BarbSpeedAngle)*DegToRad); dc->MoveTo(x2, maxY - y2); dc->LineTo(x3, maxY - y3); //Set space for next 5 knot barbs if(j == Num10Barbs - 1) Space += (j+1)*BarbInt; } //Draw the 5 knot barb if there is one if((fmod(Stations[i].spd, 10.) + 2.5) >= 5. && (fmod(Stations[i].spd, 10.) + 2.5) < 10.) { int x2 = x0 + (BarbLength - Space) * cos(WindDirection*DegToRad); int y2 = y0 + (BarbLength - Space) * sin(WindDirection*DegToRad); int x3 = x2 + (BarbSpeedLength+2)/2 * cos((WindDirection - BarbSpeedAngle)*DegToRad); int y3 = y2 + (BarbSpeedLength+2)/2 * sin((WindDirection - BarbSpeedAngle)*DegToRad); dc->MoveTo(x2, maxY - y2); dc->LineTo(x3, maxY - y3); } } }
dankelley commented 6 months ago

I made a trial code that does something crude. Rather than get into drawing triangles and lines, I am showing a solid square for 50kt, a big circle for 10kt and a small circle for 5kt. This is just to test my "making change" thought process.

The image shows faked data, with flow going around a circle and increasing with distance from the centre. Frankly, this kind of diagram does not really evoke much to my eye. (The barbs do not, either.). I prefer the convention of longer arrows for stronger fields, as we already have in oce.

A trick with R is that loops etc are slow. The sine and cosine values can be precomputed because the angles are on a 10 degree grid, so that will speed things up. Redrawing the view below takes 0.13s user time but 0.37s elapsed time on my machine. I don't think it's entirely feasible to draw fields with a whole lot more points than this (because over overlap) so it seems that maybe a code in R would not be too slow even if not well vectorized. Say 2X the grid density for 4X the processing time, maybe throw in 2X to draw triangles and such, but that only gets us to about 8X, or on my machine still under 4 seconds.

Still, the arguments against adding this (even cleaned up for barbs) to oce are quite strong, I think. The audience would be small, to begin with. Add to that the fact that any code that is written has to be maintained. And pretty soon we would get requests that it work on projected maps. Then options would be needed. I would want m/s instead of knots, for example.

@mdupilka I don't think you'd find it too hard to translate your C code into R, if you really wanted to. The key functions you'd want are plot(), points(), segments() and polygon(). Oh, and the aspect ratio of the plot comes into it as well, of course. Lots of fiddly details. But it could be done. Some vectorization work might be needed to get speed, and it would make sense to precompute the sine and cosine values, which is possible because I think the official schemes quantize to 10degree increments.

Perhaps @richardsc and @clayton33 will have comments on Tuesday, after the long weekend.

Screenshot 2024-02-18 at 5 37 29 PM

mdupilka commented 6 months ago

Thanks for working on that. Meteorologists would be the ones using the barbs as that is the standard display for wind fields. Maybe that audience is not too large. I will look into adapting my code. I need it to run as fast as possible as the charts are used operationally in our forecasting.

dankelley commented 6 months ago

I decided to look at the barbs again. There are some adjustable parameters to the aesthetics (angle of barbs, length of barbs, thickness of lines) that all ought to be parameters of a function to do this work. Below is a snapshot of something I just tried. I think it looks a lot like what I see at one of the examples shown above (reproduced here too).

Trial version

barb05

An official diagram

Screenshot 2024-02-26 at 10 17 37 AM

mdupilka commented 6 months ago

It looks very good. Just like what is on weather charts. Just a note for speeds of 3-7 units, there is just the short feather positioned one space from the end. Like the second barb you have, only without the 10 unit feather. Just as a side note about me, I have been a professional and research meteorologist/atmospheric scientist for longer than I care to remember.

dankelley commented 6 months ago

Thanks @mdupilka. I'll change that. What I'm doing is to round to nearest 5 knots, so that category would be from 2.5 to 7.5 knots.

Also, I've seen that Canadians (or maybe Canadian modellers) have a similar-looking set of symbols that represent km/hour. I think that scheme is useful for the public since all cars here show speeds in that unit, so you can imagine rolling down your window and feeling the wind, to get an idea what numbers mean. I guess Americans just reckon a knot is like a mile per hour ... and 10% is beyond our ability to intuit, so no problems.

dankelley commented 6 months ago

@mdupilka how does the top row look now? The image is not very clear, because I was trying to reproduce the "official" image. (I wouldn't use such a thick line width, I don't think.)

Trial version

barb06

An official diagram

Screenshot 2024-02-26 at 10 17 37 AM

richardsc commented 6 months ago

I have to say, despite the work involved in getting this implemented, I'm coming around that it makes sense to have wind barbs included in oce. Most large-scale oceanography papers, which need to be concerned with atmospheric forcing and buoyancy fluxes etc, will include maps of barometric pressure and wind, and this makes it easy to satisfy both the oceanographic (arrows) and meteorologic (barbs) people.

As an aside, a quick google suggests that you've been involved in the CMOS community in the past. I've mostly only been involved since about 2016, but I wonder if you ever crossed paths with my father, Bill Richards, who was a meteorologist with the MSC in NS and NB?

dankelley commented 6 months ago

@richardsc I agree it will be good to have in oce. I'll likely add it on the weekend, I just need to get the 50-knot triangles working, then figure a scheme to do things in km/hour for Canadians (maybe others too) and then, if that all seems ok aesthetically, I can do the next thing, which is save all the plot adornments into a vector that I can use to paint all the barbs at once, for speed. So that's a few little things, but during the week when people tend to be working, I do hope to get the aesthetics right.

mdupilka commented 6 months ago

The top row looks very good. I would not worry about any units. Just make the feather values unitless and let the user decide what units they wish to use. The wind barbs history is from the aviation world where all speeds are in knots throughout the world, even in Canada. But, for my purposes, I actually use km/h as the folks we deal with in our forecasting do not really understand knots.

I was a chair in CMOS for several years. I did not cross paths with your father. I will ask some other met guys I know if they have. A bit more on my use of OCE, the company I contract with does fire weather forecasting for the Northwest Territories during the summer months. I produce a number of charts related to fire weather prediction and use OCE to map the fields. You may have heard of the fire season the past year in Canada and the NWT, it was insane. I worked nearly every day and I am supposed to be mostly retired. Your OCE charts play an integral part in our forecasts and briefing.

dankelley commented 6 months ago

@mdupilka how does this look. It's speeds 0, 5kn, 10kn, etc. in reading order from top left.

I see some variability in how the triangles get draw, even in the images preceding this in this thread. I kind of like this look. The ones that have asymmetric triangles look kind of weird to me. Thanks for your help and patience. Dan.

(Oh, and thanks a million for those kind words about oce. It's always nice to make something that is useful in fields beyond those initially envisioned!)

barb07

mdupilka commented 6 months ago

That looks really good. The symmetric triangles are the standard. A light wind, less than the 5 barb could just be indicated as a line with no barb.

dankelley commented 6 months ago

Thanks. If wind is zero, which I imagine never happens, is just a dot shown? Or nothing at all?

mdupilka commented 6 months ago

Just a dot, to let users know it is not actually missing.

dankelley commented 6 months ago

Thanks, @mdupilka. I think I have the aesthetics done, as in the snapshot below. The numbers above the locations are just for demonstation purposes -- so you can see that a speed of 2 knots becomes a line, not a circle.). I elected to draw a little circle because the large circle I see at https://github.com/dankelley/oce/issues/2191#issuecomment-1951206825 just seems, well, too large.

Q: Are you okay with the small circle? Obviously, it's trivial for me to change it.

Screenshot 2024-02-28 at 1 44 41 PM
dankelley commented 6 months ago

@mdupilka if I put this into oce, my plan would be to do drawDirectionField() first, because for that we don't get into issues with map projections that crop up with mapDirectionField(). For example, consider views that show the whole world, in which case an arrow pointing say east at the east side of the rendered map should go to the edge of the world on that side, and then re-enter at the other edge of the world, in a different place. There are other issues, too.

Would drawDirectionField() be useful to you, or are you using map projections and thus need mapDirectionField()?

mdupilka commented 6 months ago

The little circle looks good. As you say, a big circle would get in the way. Just as a note, there is no upper limit for the speeds. Once you have filled up the barb with the 95 units, then you would add another 50 triangle to the end, and start over with the line feathers as before. Wind speeds in the upper atmosphere often exceed 100 knots.

dankelley commented 6 months ago

Um, you mean say if it's 110 knots, it is two triangles and a long line? That's my understanding. I guess I should ask if it's conventional to make the triangles touch at the base (as opposed to overlapping), as I see in the figure at comment https://github.com/dankelley/oce/issues/2191#issuecomment-1951206825

mdupilka commented 6 months ago

I use the mapDirectionField() with mostly the proj=lcc projection.

mdupilka commented 6 months ago

Yes, 110 knots (units) is two triangles touching at the base, and a long line. If a person is using km/h then is is not hard to get 200 km/h in the upper atmosphere.

dankelley commented 6 months ago

Thanks, @mdupilka, for your continued patience. I'll likely code drawDirectionField() first, but mapDirectionField() won't be far behind. I'll use the following as test code. (It is an informal example in the docs. I removed it as a formal example because CRAN wants examples to be quick.)


library(oce)
data(coastlineWorld)
par(mar=rep(2, 4))
mapPlot(coastlineWorld, longitudelim=c(-120,-55), latitudelim=c(35, 50),
        projection="+proj=laea +lat0=40 +lat1=60 +lon_0=-110")
lon <- seq(-120, -60, 15)
lat <- 45 + seq(-15, 15, 5)
lonm <- matrix(expand.grid(lon, lat)[, 1], nrow=length(lon))
latm <- matrix(expand.grid(lon, lat)[, 2], nrow=length(lon))
# vectors pointed 45 degrees clockwise from north
u <- matrix(1/sqrt(2), nrow=length(lon), ncol=length(lat))
v <- matrix(1/sqrt(2), nrow=length(lon), ncol=length(lat))
mapDirectionField(lon, lat, u, v, scale=3)
mapDirectionField(lonm, latm, 0, 1, scale=3, col="red")
# Color code by longitude, using thick lines
col <- colormap(lonm)$zcol
mapDirectionField(lonm, latm, 1, 0, scale=3, col=col, lwd=2)
Screenshot 2024-02-28 at 2 10 18 PM
mdupilka commented 6 months ago

Hey, no sweat. It is nice to actually be a part of this project. One of the meteorology fields I produce is wind gusts that are spit out by the weather models. I do a contouring of the gust field. With the wind barbs, I can add those to the plot so that it is easy to see both the steady wind and the wind gusts on the one map.

dankelley commented 6 months ago

I'm taking a look at this again. I had planned to vectorize the plotting of the barbs (or whatever is the right name for those things that hang off the lines) but see that in the very-latest R, on the very latest version of macOS Sonoma, the plot is fast enough that there is no need to vectorize. You can see this in action at https://youtu.be/bAb8mndlXC4, in which the example redraws in about the time it takes my pinkie finger to return to it's normal position after striking the return key.

NOTE: I know there are problems with the placement. I've recoded some of my placement calculations, and I see two bugs in the view shown in the video. I'll fix them up, then try a bunch of angles and scales, etc. Then I'll refactor the code into a function, in preparation for making oce::drawDirectionField() accept this. There will of course be some new documentation to write, and in particular some decisions about what I should let the user specify. I don't really want to let them specify a lot of the aesthetic aspects. For example, the code relies on the triangle being isosceles, in its computation of where to put following graphical elements.

When/if I get things working for oce::drawDirectionField(), I'll turn to mapDirectionField(). I expect some hiccups there because that code kind of works between xy and long-lat space. (Explaining it would take longer than just showing the code, so I won't bother.)

dankelley commented 6 months ago

Update: this is what my code makes as of now. (I corrected the things that were wrong in the video that I mentioned in my last comment.). The numbers are speeds in knots. I think I have the aesthetics OK, although if someone comments about errors, I should be able to fix things up easily since the refactored code is "in my head".

barb09

richardsc commented 6 months ago

Looks great to me!

I'll have to try updating R, and soon hopefully Sonoma. I never noticed any of the redrawing issues in R that you (and many on the R-sig-mac list) were complaining about, but I did notice a random and periodic redrawing of my Emacs buffers. Hopefully that will be fixed too.

mdupilka commented 6 months ago

That is looking just super. I think, like you, the less the user can specify the better. The triangles should be isosceles as that is the standard. Allowing the user to specify the overall size would be good, but really not much more than that. Just being a user on Windows, I never realize how much work it takes to make sure things work on other OS systems.

dankelley commented 6 months ago

Here's what I get in my test of whether the rendering works across angles. Seems ok to me. I'm guessing that most applications will only involve speeds in the top 5 rows, so the crowding seems okay. I found black triangles a bit brutal, so in this test I used gray.

barb10

mdupilka commented 6 months ago

That looks really good. Personally, I like the black triangles. that is a standard on weather charts. Maybe a bit darker grey fill. Yes, most of the time just the top 5 rows would be used. With km/h, the lower atmosphere can get to 100 km/h, but rarely, unless they are gusts. In the upper levels, speeds over 200 km/h are not rare. If possible, it would be good to leave the upper speed open ended.

mdupilka commented 6 months ago

I am not sure about the wind directions. The winds directions are not as standard meteorology, but maybe the user could adjust them. Angles are measured clockwise from 0 degrees as north and the barb pointing south (the the barb points the direction the wind is coming from).

mdupilka commented 6 months ago

Opps, forget my last comment. I had been thinking the numbers were indicating directions. Duh

dankelley commented 6 months ago

Oh, it's open-ended. It's just that, with my default geometric parameters, the triangles extend from the "start" of the arrow.

Q: what words should I use for things?

  1. what is the name of the stroke (the main line)?
  2. what is the name of the angled lines?
  3. what is the name of the triangles?

I think 2 is "barb" and 3 is "flag" but maybe "barb" refers to the whole thing. I don't know what to call the main line.

I will need to know words to use when I write the documentation. Writing documentation tends to take a fair bit of time. And I like to do it when I add something. Normally, my process is to fiddle with things outside of oce, then I write documentation, which cements notation and often tells me that I'm mixed-up. Then I put it into the package. This last step I do only once I really think the code is useful to somebody, and documented well enough that a person at sea with poor communications can figure stuff out.

I'll be offline now until about 0900UTC.

mdupilka commented 6 months ago

A good explanation of the whole lot, https://windy.app/blog/learn-to-read-wind-barbs.html

dankelley commented 5 months ago

Hi @mdupilka and @richardsc.

I'm sorry for the long delay in getting to this. As John Lennon wrote, "Life is what happens to you...".

I am attaching a PNG form a trial solution. In it, the numbers near the starts of the barbs are the speeds in knots. I started the sequence with some particular speeds, and after that they increase uniformly to a high value. (The test code explains more clearly than I could in words.) Don't worry about the details of how I set up the test field. I could also have invented a pressure field and done geostrophy, but I wanted to exercise the range of speeds with a bit more control than that.

Do things seem OK?

Nothing is documented, but I think the code may be self-explanatory. Of course, if this went into oce, I would document the function parameters, the appearance of barbs, and so forth. (Documenting a function can take nearly as long as writing it.)

NOTE: github does not permit uploading .R files, so they have names ending in .R.md, and you ought to rename them to end in .R before trying. Just run the code with 'test' in the filename, for it will then load the other file.

PS. I am using debug=TRUE in my test so it will show the speeds as numbers, for testing. This also creates quite a lot of debugging output that can be ignored. I fiddled with lots of things in the code -- I should not have started with plotting in xy space since I had to rethink everything for map space -- and if things look OK I will likely clean up the code a bit. I don't think I have any dangling (unused) variables anymore, but I might.

barbgeo04 barbgeo04-test.R.md barbgeo04.R.md

dankelley commented 5 months ago

@mdupilka oh, I forgot to say:

  1. I am rounding angles to 1deg. I think the convention is to round to 10deg, so that is an argument to the function, which is FALSE by default, but I could make it TRUE, if I got a reference for this being the convention.
  2. I round speeds to 5 knots (although very slow speeds are treated differently). Perhaps things are truncated downwards to the nearest multiple of 5 knots, though. I'm basically guessing. If this code were to be inserted into oce, I'd want some citable references stating conventions.
  3. Speaking of conventions, I imagine there are several. For example, I often check the Canadian site, https://hpfx.collab.science.gc.ca/~smar001/winds/, and I see that it has barbs at 10 km/h and a flag at 50 km/h. That's about a factor of 2 shift, which really surprises me. I would have guessed that the folks making that site would have used 20km/h and 100km/h to get symbols that were within 10% of a map with knots.

Notice that 2 of the 3 comments above use the word "reference". Citation is a big thing for R packages, and we are talking here about trying to reproduce symbols used on diagrams that have a multi-decade history. I think CRAN might accept a wikipedia reference, but I'd prefer something from some national meteorology service, or some royal society, etc. -- something that exists in semi-permanent form, unlike wikipedia, which could have changed as I typed this sentence.

Thanks!

mdupilka commented 5 months ago

When it comes to wind units, there is no real standard units for a wind barb. It can be in whatever units the user wishes. The barbs are just a unitless display. Canada uses km/h, World aviation almost always use knots. But a user could choose to display in m/s. I would not confine the barbs to needing knots. Let the user decide what units to use.

As far as references for wind barbs, I do not really know of any. They developed as a common wind display on weather map plots. You may have seen this from Wikipedia https://en.wikipedia.org/wiki/Station_model. I found this discussion which suggests no one really knows just how the wind barb came into being. It looks like it became the norm in 1941. https://stormtrack.org/threads/history-of-station-plots.6010/ Tim Vasquex is a well known storm tracker. The discussion states, The consensus is that the station model used prior to August 1, 1941 was probably a U.S. standard. The one in use after August 1, 1942 was almost certainly a WMO standard. But we don't know if the one in use between those dates was a U.S. modification of the WMO standard and we later switched to the WMO standard or if it was the WMO standard at the time and the WMO standard changed. We have no documentation here that would shed any light on this.

mdupilka commented 5 months ago

Your map display looks very good. Just one point, the line is rather long and takes up a lot of space. Is there a way to adjust its length? I have not downloaded the code yet.