Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

mapPlot() should offer more control of axis labels #1707

Open
4 tasks done
dankelley opened this issue Jun 11, 2020 · 15 comments
Open
4 tasks done

mapPlot() should offer more control of axis labels #1707

dankelley opened this issue Jun 11, 2020 · 15 comments
Assignees

Comments

@dankelley
Copy link
Owner

dankelley commented Jun 11, 2020

Following up on discussion at #1706, maybe mapPlot() ought to have a new argument for controlling the labelling of axes.

it could be called axisStyle, and take numeric values, perhaps

  • 0 for signed numbers without labels
  • 1 (the default) for unsigned numbers followed by letters that indicate the hemisphere
  • 2 for signed numbers with a degree symbol to the right
  • 3 for unsigned numbers with a degree symbol to the right

with other varieties possibly coming later, perhaps with degrees and symbols (which might be quite ugly...)

@dankelley
Copy link
Owner Author

I have this working in "develop" (see ?mapPlot for the numerical codes and explanation, which supersedes what I wrote in the previous comment), and the test code

library(oce)
data("coastlineWorld")
proj <- "+proj=merc"
lonlim <- c(-20, 20)
latlim <- c(-20, 20)
if (!interactive()) png("1707a.png")
par(mfrow=c(2, 2), mar=c(2,2,1,1))
for (axisStyle in 1:4) {
    mapPlot(coastlineWorld, longitudelim=lonlim, latitudelim=latlim,
            col="tan", proj=proj, axisStyle=axisStyle, grid=c(5,5))
    mtext(paste0("axisStyle=", axisStyle), cex=par("cex"))
}
if (!interactive()) dev.off()

produces as below.

1707a

@dankelley
Copy link
Owner Author

@clayton33 since this stems from your #1706 issue, can I ask you to look at two things and comment here?

  1. Does the above look OK? (Note that the test code is also in https://github.com/dankelley/oce-issues/tree/master/17xx/1707, which I will update as appropriate)

  2. Do you want me to make an additional style, axisStyle=5 maybe, that has unsigned numbers followed by both a degree sign and a hemisphere letter? It would be just 5min of work, and I'm inclined to do it but I just didn't do it because you mentioned at consider supporting other languages for mapPlot() longitude/latitude labels #1706 that you thought that would be ugly

@clayton33
Copy link
Collaborator

  1. Yes, looks very very nice.
  2. Looking at it I'm inclined to include the additional style. Those who might doing it in two languages, might choose axisStyle = 3 or axisStyle = 1 for niceness, but others might want the degree and hemisphere, for say English.

@dankelley
Copy link
Owner Author

@clayton33 I added style 5, and I actually like it. What do you think?

library(oce)
data("coastlineWorld")
proj <- "+proj=merc"
lonlim <- c(-20, 20)
latlim <- c(-20, 20)
if (!interactive()) png("1707a.png", width=7, height=5, res=120, unit="in")
par(mfrow=c(2, 3), mar=c(2,2,1,1))
for (axisStyle in 1:5) {
    mapPlot(coastlineWorld, longitudelim=lonlim, latitudelim=latlim,
            col="tan", proj=proj, axisStyle=axisStyle, grid=c(5,5))
    mtext(paste0("axisStyle=", axisStyle), cex=par("cex"))
}
plot(0:1,0:1,xlab="",ylab="",axes=FALSE,type="n")
box()
text(0.5,0.5,"Test of\nmapPlot(...,axisType)\n(github issue 1707)")
if (!interactive()) dev.off()

1707a

@clayton33
Copy link
Collaborator

Looks nice :)

@dankelley
Copy link
Owner Author

Closing now. Thanks, @clayton33

@chrisdane
Copy link

Argument las from graphics::axis() please!

@dankelley
Copy link
Owner Author

@chrisdane I'll take a look. I reopened the issue because open issues are a to-do list.

NOTE: this won't make it to CRAN for 6 months to a year. We have a release that is being finalized on CRAN right now, and there are rules about frequent updates.

@dankelley dankelley reopened this Aug 19, 2024
@dankelley
Copy link
Owner Author

I'll make it accept las as either a 1-element or 2-element vector. Otherwise we'll get some odd things, like below. (I've never played with las before ... I like the default, which uses less margin space than if we have horizontal labels on the vertical axis.)

# Demo of why I will set up for las to be a 2-element vector,
# if the user wants more control.
library(oce)
data(coastlineWorld)
par(mfrow = c(2, 2))
for (las in 0:3) {
    mapPlot(coastlineCut(coastlineWorld, -100),
        longitudelim = c(-130, -55), latitudelim = c(35, 60),
        las = las,
        projection = "+proj=lcc +lat_0=30 +lat_1=60 +lon_0=-100", col = "gray"
    )
    mtext(sprintf("with las = %d", las), side = 3)
}

image

@dankelley
Copy link
Owner Author

Actually, on second thought, I am going to make it require a two-element vector. Otherwise the user might get odd results like the bottom two panels in the plot above. Making it a two-element vector lets me write the docs to explain things, as provisionally below (in Roxygen2 format).

#' @param las two-element axis label orientation, passed to [axis()]. The first
#' value is for the horizontal axis, and the second is for the vertical axis.
#' See [par()] for the meanings of the permitted values, 0, 1, 2 and 3.

@dankelley
Copy link
Owner Author

This shows the main part of the diff (not pushed to GH ... this is just a note to myself, really).

grep -n "axis(side = " map.R
657:                    axis(side = 1, at = at, label = formatLonLat(longitude, "longitude", axisStyle = axisStyle), las = las[1])
679:                    axis(side = 2, at = at, label = formatLonLat(latitude, "latitude", axisStyle = axisStyle), las = las[2], line = line)
2558:                                axis(side = 1, at = axisLabels1$at[!skip], labels = FALSE, mgp = mgp)
2560:                                axis(side = 1, at = axisLabels1$at[!skip], labels = axisLabels1$value[!skip], las = las[1], mgp = mgp)
2578:                                axis(side = 2, at = axisLabels2$at[!skip], labels = FALSE, mgp = mgp)
2580:                                axis(side = 2, at = axisLabels2$at[!skip], labels = axisLabels2$value[!skip], las = las[2], mgp = mgp)

@dankelley
Copy link
Owner Author

I've updated oce so that mapPlot() accepts las as a parameter. This is in the "develop" branch, commit ea6822c, and a test suite is shown below. Note that it makes 4 images, which I am inserting here in order of creation.

I think las=c(0,0) (the default) and las=c(0,1) will be the most useful cases.

@chrisdane -- if you can build oce from source, please do so and check to see if it seems useful, commenting here on what you find. If you like the results, I'll re-close the issue.

# Demo of why I will set up for las to be a 2-element vector,
# if the user wants more control.
library(oce)
data(coastlineWorld)
png("las_%d.png")
par(mfrow = c(2, 2))
for (las1 in 0:3) {
    for (las2 in 0:3) {
        mapPlot(coastlineCut(coastlineWorld, -100),
            longitudelim = c(-90, -50), latitudelim = c(35, 50),
            las = c(las1, las2),
            projection = "+proj=lcc +lat_0=40 +lat_1=45 +lon_0=-70", col = "gray"
        )
        label <- sprintf(
            "with las = c(%d, %d) %s", las1, las2,
            if (las1 == 0 && las2 == 0) " i.e. the default" else ""
        )
        mtext(label, side = 3, line = 0.5)
    }
}

las_1
las_2
las_3
las_4

@chrisdane
Copy link

Hi yes that works, thanks a lot.

I am wondering if its possible and, if yes, more generic to pass all default parameters from oce::mapAxis to graphics::axis via ....

Cheers,
Chris

@dankelley
Copy link
Owner Author

@chrisdane that's not really possible because we are talking about things that relate just to axes here.

This is a general thing in R. Imagine some function A in turn calls functions a, b, c, d, etc. If we have a ... parameter for A, then is that to be passed to a, or to b, or to ... or maybe to all of them? Unless all of the lower-case functions handles the same set of items that might be contained within ..., there would be an error of supplying parameters that the functions do not accept.

Not only would this be confusing to the R system, it might be quite confusing to the user, also.

One solution (used by oce and, I think, most R packages) is to name all the things that the user is allowed to control. Another approach is to let A take parameters like maybe aparameters which would be a list of parameters that would get handed down to a(), but not to b(), etc. But, again, that gets confusing for users.

This explains why a lot of R functions (especially those for plotting) have a lot of parameters. And, sometimes, parameters hold parameters within themselves. An example you might know is the control parameter of nls(). This is a list that is normally created by a call to nls.control().

Sorry this is long-winded. The short answer is that using ... is not a solution. Users just have to wade through a long list of parameters for mapPlot() and quite a lot of functions in quite a lot of packages.

Make sense?

@dankelley
Copy link
Owner Author

Oh, I forgot to say: I think most users don't use mapAxis(); they just use mapPlot(). In my own work, I often want a lot of control over things, and I sometimes write specialized code to make specialized axes. Doing low-level things like that is not a bad solution, because every new parameter added to a function is one more thing that users might have to think about.

Again, this is quite general, not related to mapPlot() or even to oce.

Generally, and this goes for all my research work, I either go with simple defaults or I make a highly-tailored plot that works for the particular diagram I am making for a particular paper.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants