-
Notifications
You must be signed in to change notification settings - Fork 28
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
Compute angle between a vector and a plane perpendicular to the image plane #370
Comments
@sfmig (and @niksirbi) wanted to get some clarification here, when it comes to regions of interest. What's described in the issue, I've drawn in the image below (on the right-hand-side) as I interpret it. I'm not sure what this is actually representing, or why it would be useful? There's also ambiguity regarding the sign of the boundary normal, amongst other things. This gets even more confusing when we start considering polygons too. If we really do want access to the normal to a line though, I can add an On the left of the above is what I imagined this feature would be bringing to the package. Given a forward vector and the point the forward vector originates from, compute the direction towards the closest point on the RoI boundary. Then, compute the angle between the current heading and the direction that follows the shortest heading towards the region. So the RoI class gets a general method class BaseRegionOfInterest
def angle_to(
data,
left_keypoint, # These two define
right_keypoint, # the forward direction
camera_view, # Also needed to determine "forwards"
position_keypoint, # Used to compute the vector towards the region of interest
) -> float:
"""Computes the signed angle between a forward vector and the direction of closest approach to a region of interest""" However I think I'm missing the overall objective of what this issue originally asked for 😅 Any guidance is appreciated - feel free to use diagrams too! |
Hi @willGraham01 ! I think both options above are equivalent, right? Just the angle obtained with option 1 is the supplementary of the one obtained in option 2. See diagram below (sorry it's huge!). v is the head (or forward) vector, and n the normal to the boundary plane pi. With option 1 you compute theta, with option 2, you compute 180-theta. But I think in both cases it may get tricky because of the fact that the boundary is made up of segments and not infinite lines... There may be another tricky aspect regarding the orientation of the normal - though if it is always closed polygons it may be alright? Just to clarify the suggestion was to: I need to leave now but happy to continue discussing how we can deal with the segments issue! |
I'm frankly confused about the confusion here 🤔 . |
For now just copying here Sepi's notes on boundary vectors, for easy reference:
|
@sfmig and I just had a in depth chat about this. I have tried to summarise it here (though please point out any inconsistencies @sfmig!):
Shamelessly stealing @sfmig's diagram, which encapsulates these two cases really well: There are two ways that seem logical (mathematically) for defining the orientation of an animal to a line segment.
Convention 1 results in a constant orientation, so long as the animal remains on the same side of the line segment. Convention 2 coincides with convention 1 when the closest point is an interior point of the line, but not the endpoints. There are merits to both, and @sfmig and I actually came down on the side that
from your quoted block in Sepi's notes... this would imply that
In the case of a Polygon, the closest point to the animal may belong to either 1 or 2 of its boundary segments. In the event that it only belongs to one, then the orientation is easily computed by reverting to the line-segment case for the appropriate boundary segment. Note that the Difficulty arises when the closest point to the animal is a corner, between two boundary segments. Convention Convention Given what @niksirbi has quoted from Sepi's wish list:
This gives me the impression that convention For the time being it isn't much effort to implement both in a draft PR. But we might want to show this to Sepi and ask for some explicit advice as to which convention she means, in the event that the region is not the entire enclosure. |
great summary @willGraham01 ! 🌟 Just to clarify for other readers:
When we say coincide, we mean they are basically the same because they just differ in a constant value (θ = 180 - α).
I think even if the region is a closed polygon, we could still have concave corners, for which the θ and α approach differ. Right? (I may be missing something tho). I think you mention it but just to highlight it - I would say a question to clarify with Sepi is: in the diagram here, would she interpret the animal has constant orientation with respect to the wall in all 5 cases? Or would she say 4 and 5 have different orientations? If she says definitely Yes to the first question, maybe we just implement the orientation wrt boundary function as a "compute angle to support plane of segment". If it is not clear cut or if she says both approaches are of interest, I would say we can have both |
Btw there is a typo in the diagram above, the arc representing α5 is wrong - sorry! Below the fixed version. I also added in yellow the vectors @willGraham01 calls "approach vectors" a. Note that in the diagram, the α angle actually changes sign for 5. |
Yeah you're right - us being inside doesn't stop there from being interior concave corners 😰 I was only thinking of enclosures that would be regular polygons (in which case we wouldn't have this issue, but we of course can for irregular shapes). |
Thanks both! This is an excellent summary of the problem, I understand it now! Let's define the following vectors, for supporting this discussion.
Essentially we can have two cases (illustrated below):
Is this a fair summary of the question? |
I would say so. I think it's important to note though that for a line (segment), both interpretations make sense (particularly with @sfmig's distinction into two cases / functions). The complication only comes when we consider polygons, and the "hard case" kind suddenly makes it clear we have a problem near the corners of these polygons (when the approach vector |
Yeah, I think that is about right! As Will says it is just missing the extension to a polygon case, but we can discuss that in person if that is unclear. I would suggest some things from @niksirbi's bit above, just to not change or add more nomenclature unnecessarily:
A small reframing: I wouldn't say that it is ambiguous - it just depends on how we translate the biological question into a math one. The biological question would be: What is the orientation of the animal('s head) relative to this boundary? Assuming the boundary is defined by the user as a segment, this could be translated into two possible math questions:
My current take: I think generally when thinking about orientation wrt a wall, people mean the second case. But a user may be interested in computing the angle between the head vector |
Re-reading the egocentric/allocentric distinction, this is my current understanding: If we are given a polygon (a list of connected segments) and the users want the..
If we are given a single segment we need to clarify what the users mean / decide and explain. If they want the..
|
Agreed.
Agreed with that as well, it's nice to reduce the "normal" to one specific vector. My motivation for introducing
Agreed for this discussion, important to distinguish between infinite lines and finite segments. Though in terms of code objects we only have
Biologically yes, boundary vectors are defined with respect to the head position and orientation, so using "head vector" for
This is a great framing of the whole issue! |
From the dev meeting today: It seems like using the angle between the approach vector and the head vector would be the most intuitive here, but not sure if the wall is treated differently than the rest of the polygon. |
Worth mentioning that in our current implementation the enclosing square and the wall that's "jutting out" would have to be separate RoIs (due to constraints on the underlying |
Ok good to know! Maybe in reality the jutting-out wall would always have a thickness so it wouldn't be a problem? |
Tagging @TomGeorge1234 to pick his brain on this. Tom, it seems like RatInABox cam simulate the responses of boundary vector cells given the arena and an agent with position and heading. This means that at some point you've probably contemplated the same issue we're discussing here. You also probably know the boundary vector literature better than any of us. Do you have opinions on what most neuroscientists would expect in edge cases like the ones we're discussing above? Feel free to ignore the ping if you don't have the capacity to chime in on this right now. No pressure. |
Good point, if you annotating a "real" arena, that's a more likely scenario, and it reduces to the problem of non-convex polygons. |
BVCs in literature (possible red herring) Comments on your issue
Closest equivalent problem in RiaB It's moderately well documented, the core function docstring is : def shortest_vectors_from_points_to_lines(positions, vectors):
"""
Takes a list of positions and a list of vectors (line segments) and returns the pairwise vectors of shortest distance
FROM the vector segments TO the positions.
Suppose we have a list of N_p positions and a list of N_v line segments (or vectors). Each position is a point like [x_p,y_p], or p_p as a vector.
Each vector is defined by two points [[x_v_0,y_v_0],[x_v_1,y_v_1]], or [p_v_0,p_v_1]. Thus
positions.shape = (N_p,2)
vectors.shape = (N_v,2,2)
Each vector defines an infinite line, parameterised by line_v = p_v_0 + l_v . (p_v_1 - p_v_0).
We want to solve for the l_v defining the point on the line with the shortest distance to p_p. This is given by:
l_v = dot((p_p-p_v_0),(p_v_1-p_v_0)/dot((p_v_1-p_v_0),(p_v_1-p_v_0)).
Or, using a diferrent notation
l_v = dot(d,s)/dot(s,s)
where
d = p_p-p_v_0
s = p_v_1-p_v_0""" what I forgot to say in the docstring but you'll see in the function is that |
Yeah this only holds for convex polygons. So when the polygon represents the whole arena we're usually OK, but we hit differences when we have a polygon representing part of the arena (EG a nest) and the animal is outside this region but still inside the experimental area. |
Had forgotten to say thank you for the very comprehensive response @TomGeorge1234! The pointers you've provided us will come in handy well beyond the scope of this particular issue. |
thanks @TomGeorge1234 you raised very good points that I think will become relevant for
As you hint, we ended up relying on the approach vector, following a sort of "proximity estimation" approach. But it is very useful for us to be aware of more biological approaches like the one you describe for BVC - it makes sense that the integral is the biologically relevant representation of how the environment "affects" the animal. |
Is your feature request related to a problem? Please describe.
In a 2D, top view camera case, a user may want to compute the angle between a vector (e.g. the head vector) and a line that represents a plane perpendicular to the image plane (e.g., the walls of an enclosure).
In that case we would need to compute the angle between the (head) vector and the normal to the (wall) plane.
Additional context
This could be useful for boundary vector cells analyses, alongside #368
The text was updated successfully, but these errors were encountered: