Closed pllim closed 9 years ago
@pllim, the usual way is to press the right (or drawing) button down where you want the starting (first) point and drag. On the keyboard with the other hand, press 'v' whenever you want an intermediate point. For the final point before completing the polygon, simply release the drawing button.
While during the drawing, if you ever decide the previous point was incorrect, you can press 'x' 'z' to remove it.
I'm open to other, possibly additional, drawing techniques for polygons. One idea I had was to also allow left clicks while drawing to place the intermediate points.
Probably the error is due to the polygon being created with two few points. This should be corrected. I'll see if I can reproduce it.
Sorry, in that last comment I made a mistake. It looks like the default binding is 'z' to remove the last point, not 'x'.
Okay, thanks! Somewhat related... Is there an existing method to extract data from inside the polygon? There does not seem to be very much documentation on Drawing
plugin.
@pllim, this would be a very welcome PR if you have the time to work on it. IMO, this is would be extremely useful. Ideally, we would have a method that we could pass a shape (any of the supported shapes), and it would return the data that exists within the shape. There is already a contains(x, y)
method that could be used to help implement the method.
Seems like what you want is to find the smallest rectangle containing the shape, then extract that rectangle and use the contains
method to set the non-interior pixels to masked out in a masked numpy array.
If ginga had something like this it would go a long way to becoming the basis of implementing ds9-like region analysis.
@ejeschke , do you think Ginga can benefit from https://github.com/spacetelescope/sphere in this matter?
It looks like there could be some useful synergy there. Maybe as a more accurate representation that has a mapping to 2D, either in WCS or data coordinates? I can well imagine that if you are combining or otherwise manipulating polygons that would be a desirable package to use.
Does it have a way to generate a bounding box from the sky polygon?
Regarding the bounding box, I think @bernie-simon or @mdboom might be able to answer.
sphere doesn't have a way to generate a bounding box from a sky polygon, basically because it doesn't have any projections from 3D to 2D at all. But it would be simple enough to project the polygon to 2D using a given projection and then compute a bounding box from that.
One "feature" or limitation of the sphere package is that the polygons it uses have sides that are constrained to be great circle arcs. I get the impression that that may not be the case for you
@bernie-simon, I think as long as there is a "reasonable mapping" from sphere polygons to 2D polygons in pixel (data) space it might be useful for the purpose @pllim is describing, which is to extract data regions inside the polygons. Would you agree?
Sorry, I have not responded earlier because I've been on vacation.
A polygon is usually defined by its vertices, so the edge defined by the great circle arc may deviate from the polygon edge if they are large. As you say, the deviation may be made arbitrarily small by specifying more vertices and edges. It sounds like you want to define a mask using a polygon and mask all pixels outside it. Off the top of my head, the way to do this would be to get the line defining one row of pixels and compute where it intersects the polygon. If no intersection, you would test the end points to see if the line lies entirely outside or inside the polygon. The code to compute the intersection and do the endpoint test is in the sphere package, but there is no code yet to apply it to an image using its wcs or to create the mask.
@pllim, I should have replied on this earlier, but there is now support for cutting out arbitrary geometric shapes in ginga (basically any shape you can draw). Once you have a handle on the shape (e.g. from getting it via the draw-event
callback) you can simply do:
arr_masked = image.cutout_shape(shape_obj)
You will get an array corresponding to the bounding box of the shape, with the non-containing pixels masked out. The containing test is done as a vector operation, which means it should be pretty fast.
This is fairly new and not well tested.
@pllim, BTW, is this still crashing for you when you draw a polygon "incorrectly"? I am unable to reproduce the crash even when I draw it (incorrectly) as you describe above. If it is not happening any more I'd like to close the issue.
BTW, I'm still interested in possibly incorporating the sphere package, but maybe this should go in as a separate issue, and maybe combined with collaborating/refactoring to use a new astropy "shapes" package.
@ejeschke , polygon does not crash anymore, and I see that you also updated the instructions on Drawing
plugin. Thanks! I'll check out the cutout_shape()
method, and open a separate issue regarding sphere
.
One of the constructors for the astropy sphere class takes a closed list of vertices. (Closed here means the last point on the list is identical to the first.) Since it sounds like Ginga is producing this list, there should be no problem passing it to sphere after transforming the pixel coordinates to world coordinates.
"Does it have a way to generate a bounding box from the sky polygon?"
I'm not sure what you mean by a bounding box. Do you mean the smallest rectangle that contains the polygon? Or the min and max right ascensions and declinations, for searching some catalog?
The answer is no to both, but if there was a need, it could be added. The latter problem is very simple to implement a solution for. I don't know right now a solution to the first problem.
To me, bounding box should be the smallest rectangle that contains the polygon.
What's the use case for this? Maybe this is a naive question, but it would be nice to know.
@bernie-simon , an example use case is 6 comments above yours, as mentioned by @ejeschke
If I read that comment correctly, that bounding box is aligned with some image. That suggests to me that an input to the bounding box computation would be a rotation matrix, by default the identity matrix.
I am unable to find much documentation on how to properly draw a polygon in the
Drawing.py
plugin. I use right click and managed to draw one side of the intended polygon. I released the click so I can draw a different side of the same polygon, but I get the traceback below. Am I using the plugin wrongly, or is this a bug?