Start with:> x <- c(1:7,1) > dim(x) <- c(2,4) > x[,1] [,2] [,3] [,4] [1,] 1 3 5 7 [2,] 2 4 6 1 2 Rows of 4 Columns. Upper-left and lower-right elements of the matrix are the same. All to this point makes good sense.> image(x)However, this image shows 2 columns of 4 rows. The lower-left and upper-right elements are the same. This does not make sense to me. Did I miss some simple parameter to "fix" all of this naturally? Why would the numeric matrix of "x" and the image of "x" have such a different geometry? I'd love to use R for some simple image processing, but I don't want to spend my time "fixing" all my images. Because Image Pro Plus wasn't doing a calculation the way we wanted, I dumped 16-bit pixel data into Excel and used Excel to create CSVs. All of this went much faster than figuring out the "surprise" that R didn't display the images "correctly". Did I miss something simple? I really don't want to do this: ReadImageMatrix <- function(filename) { x <- as.matrix(read.csv(filename,header=FALSE)) x <- t(x) return( x[,ncol(x):1] ) } oldpar <- par(mfrow=c(2,2)) x <- ReadImageMatrix("1n.csv") image(x, col=gray((0:255)/255), main="1N", axes=FALSE) y <- ReadImageMatrix("2n.csv") image(y, col=gray((0:255)/255), main="2N", axes=FALSE) z <- ReadImageMatrix("3n.csv") image(z, col=gray((0:255)/255), main="3N", axes=FALSE) par(oldpar) efg -- Earl F. Glynn Scientific Programmer Stowers Institute for Medical Research [[alternative HTML version deleted]]
On Thu, 26 Aug 2004, Glynn, Earl wrote:> Start with: > > > x <- c(1:7,1) > > dim(x) <- c(2,4) > > x > [,1] [,2] [,3] [,4] > [1,] 1 3 5 7 > [2,] 2 4 6 1 > > 2 Rows of 4 Columns. Upper-left and lower-right elements of the matrix > are the same. > > All to this point makes good sense.It's pure convention: see below.> > image(x) > > However, this image shows 2 columns of 4 rows. The lower-left and > upper-right elements are the same. This does not make sense to me. > Did I miss some simple parameter to "fix" all of this naturally? Why > would the numeric matrix of "x" and the image of "x" have such a > different geometry?Did you try reading the help for image? You don't seem to understand it if you actually did. It seems you are looking for image(t(x)[ncol(x):1, ]) Easy! Mathematical conventions are just that, conventions. They differ by field of mathematics. Don't ask us why matrix rows are numbered down but graphs are numbered up the y axis, nor why x comes before y but row before column. But the matrix layout has always seemed illogical to me. -- Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
Prof Ripley: Thank you for your prompt reply.> It's pure convention: see below. > > Did you try reading the help for image? You don't seem to > understand it > if you actually did. It seems you are looking for > > image(t(x)[ncol(x):1, ])I think you guys are too close to "R" to understand how hard it is to use sometimes. What may be blatantly obvious to you is quite a problem especially to beginners. Some of us may be beginners to R, but we know math, science, programming, and how to solve problems with other tools and languages. I re-read the guidelines before posting fearing condemnation. Before posting I searched the online R-help Google interface with keywords "image", "flip", "rotate". A discussion from 1998 touched on this issue but I was hoping that this was deemed a "bug" at some point and fixed -- or had an easy workaround, like some parameter I was missing. I read the "?image" help before posting. Was the part I didn't understand buried in this "note"? "Based on a function by Thomas Lumley tlumley at u.washington.edu." I asked the question because I did not find the answer under "?image". Please quote the portion that I missed that you think explains this. I was tempted to post the whole "?image" section here to prove my point. There is no entry on that page with transpose, "t(", or "ncol" the way you explained above. I'm not sure what you think I missed, but I did my homework on this problem before posting.> Easy! > > Mathematical conventions are just that, conventions. They > differ by field > of mathematics. Don't ask us why matrix rows are numbered > down but graphs > are numbered up the y axis, nor why x comes before y but row before > column. But the matrix layout has always seemed illogical to me.My 30+ years of software experience says this is a design flaw. A good design would reconcile the differences between conventions. Coordinate transformations are not that hard, but I wouldn't burden the end-user with them needlessly. I'll go back to lurking in the daily R-Helps and not ask any more questions until I've read all the old R-help messages. I'm working on December 1998 right now and reading forward. Perhaps by next year I'll will have read all the old R-help postings and I'll dare ask another question then. efg
Deepayan Sarkar <deepayan at cs.wisc.edu> wrote: You seem to be thinking that Prof Ripley's solution had something to do with image(). "Glynn, Earl" <EFG at Stowers-Institute.org> could certainly be excused for thinking so, because what Prof Ripley wrote included this: > > Did you try reading the help for image? You don't seem to > > understand it if you actually did. That certainly sounds to me as though the answer should have been obvious from ?image Now, the image() function is trying to be extremely helpful and offers you lots of ways of providing the data, and that is explained in ?image. In fact a key piece of information *IS* in ?image, so it really DOES have something to do with image(): Details: The length of 'x' should be equal to the 'nrow(z)+1' or 'nrow(z)'. In the first case 'x' specifies the boundaries between the cells: in the second case 'x' specifies the midpoints of the cells. This tells us that the "x" direction of the image goes along the *rows* of the matrix and by implication that the "y" direction goes along the *columns* of the matrix, and is precisely what you need to figure out that image(t(x)) is the thing to use. One does have to be a little subtle at reading between the lines to see the relevance of details about a parameter one is not passing, but the information _is_ there and it _is_ 'something to do with image()', not something to do with matrices. The 'volcano' example from ?image also points the same way. The basic problem here is that the standard visual layout of matrices sets up such a strong expectation that it's difficult for any text to override it. I don't see anything that explicitly discusses the direction of the axes, I don't see anything explicit, but I took it that ?image would follow the usual "horizontal axis increases from left to right, vertical axis increases from bottom to top" convention, which means "horizontal gives ROW number increasing left to right, vertical gives COLUMN number increasing bottom to top" so when I do image(t(x)) I see my columns as vertical strips but they are "upside down", so the last step, to image(t(x)[ncol(x):1,]) does make sense, provided you read ?image as *implying* without actually stating "follows the usual graphical conventions for axes". But again, this really is a fact about image(), not about matrices. As for the claim that It doesn't, it has to do with manipulating a matrix. image() visualizes a matrix in a particular and well-defined way. Well yes, it is a particular way, and I suppose you could say that the code is defined well, but it really isn't, when you get right down to it, and *EXPLICITLY* documented way. You really have to work at it. This is NOT a criticism of R documentation. Of all the open-source programs I use, I reckon R is by far the best documented, and its on-line documentation can more than withstand comparison against most of the commercial programs I've seen. The real problem is that R is just so big and there are only so many people writing documentation for it. Given the wide range of ways that the x, y, z arguments can be passed to image(), it would actually make sense to have some kind of flip and/or mirror operations specified via an argument to image(). The source code of image is available (image.default) so it wouldn't be a lot of work for someone who wants it to produce such a thing.
> From: Richard A. O'Keefe[snip]> Given the wide range of ways that the x, y, z arguments can be passed > to image(), it would actually make sense to have some kind of > flip and/or > mirror operations specified via an argument to image(). > The source code of image is available (image.default) so it > wouldn't be > a lot of work for someone who wants it to produce such a thing.I'd suggest adding an `as.matrix' argument to image.default. Best, Andy
Deepayan Sarkar <deepayan at cs.wisc.edu> wrote: I agree with you that the issues are related, but your (edited) quoting is misleading. My quotes were selective but not otherwise edited. I interpret Prof Ripley's comment as implying that reading ?image would tell the user what happens when he calls image(x). And that's how I interpreted it too. This is distinct from how to manipulate a matrix, which is what t(x)[ncol(x):1, ] is doing. It doesn't seem obvious to me that this information should be in ?image, Nobody whatsoever has suggested that the matrix manipulation code *SHOULD* be in ?image. Nobody. Not me. Not anyone else. The original poster's problem was not "how do I manipulate a matrix" but "why is the image the wrong way around". and I still don't see how Prof Ripley's comment suggested that it was. It didn't. NOBODY has made any such suggestion. One can hardly expect all possible interactions to be documented. Nobody has suggested that either. All I was saying is this: (1) The original poster's problem was a problem about image(), NOT a problem about matrix manipulation. (2) We have no reason whatsoever to assert, hint, believe, or opine that the original poster was any less competent at matrix manipulation per se than anyone else reading this mail list. He didn't have a matrix problem. (3) The problem basically is precisely where Prof Ripley located it: a clash between (a) an extremely strong "cultural" expectation that the elements of a matrix will be presented with rows running from 1 at top to m at bottom and columns running from 1 at left to n at right, and (b) an extremely strong "cultural" expectation that the vertical axis of a plot runs from low at the bottom to high at the top, and (c) the fact that image() maps the "row" axis of a matrix to the horizontal axis of a plot and the "column" axis of a matrix to the vertical axis of a plot. Expectations (a) and (b) are not only part of general computing, they are strongly supported by R itself. As for (c), it doesn't seem to me that it _had_ to be that way. (4) Point (c) is a sufficiently strange quirk of image() that it is a stumbling block waiting to trip people up. I've stumbled over it myself, which is how come I knew where to look in ?image. That makes it *essential* that it should be documented. (5) And it *IS* documented. It really is an image() problem, not a matrix problem, and the essential part of it *IS* documented. Pointing out that a obvious nasty interaction *is* documented is hardly a demand that all possible interactions should be documented. How about this addition to the documentation? "The x axis corresponds to the rows of the matrix (first on the left to last on the right). The y axis corresponds to the columns of the matrix (first at the bottom to last at the top)." Once you know what image() is _intended_ to do with a matrix, you can figure out the transposing and reversing you need for any other view. It's knowing you need to that's the problem.