API¶
fledge¶
Fledge: Spatial Programming with Reference Graphs.
- class fledge.Body(defining_edge, defining_frame, space=None)¶
A Body is an object in space, connected to a frame in the same space.
In Fledge, a Body has in-degree == 1 and out-degree == 0. This means it is defined precisely by exactly one reference frame (although it may have cached references to others).
Bodies are usually not created directly but rather by their defining edges via traverse().
- Parameters
defining_edge (fledge.core.Reference) –
defining_frame (fledge.core.Frame[fledge.core.S_co]) –
space (fledge.core.S_co) –
- Return type
None
- final connect(edge, frame=None, space=None)¶
TODO.
- Parameters
edge (fledge.core.Edge) –
frame (Union[None, str, fledge.core.Frame]) –
space (Union[None, str, fledge.core.Space]) –
- Return type
None
- is_orphan()¶
Bodies are never orphans, because they are attached to a frame.
- Return type
bool
- is_source()¶
Bodies are never sources, because only frames are.
- Return type
bool
- class fledge.Edge¶
An Edge exists as a mathematical description of spatial objects (Nodes).
An edge doesn’t know about the particular instances of the nodes that it goes between, only the types of those nodes, as class variables. These are upper bounds on the type of nodes that the edge can go between. The nodes, in turn have upper bounds on the type of space they can be in.
Edges usually have numrical representations. At least one of these should be implemented in the __array__() method.
Sub-classes must define input_type_bound and output_type join, which is used by __matmul__. join defines how the edge interracts with other edges. output_type is used by a frame’s traverse() method to traverse the edge.
Sub-classes may also wish to implement inverse(), which finds the inverse of the edge. The invertible() method simply checks whether inverse() returns None, in which case the edge is not invertible.
Finally, subclasses likely should have implementations of __array__ and/or __float__ as appropriate.
Broadly, there are two types of edges: - Defining edges: which are the unique descriptions of a node in space. There is only one per
node.
Projection edges: which go between spaces and result in new nodes to be created.
There are four types of edges. * An Identity is a self-loop. It isn’t very useful except as a building block for other edges. * A Reference is a defining Edge for a Body, where R == S is true.
References originate in Frames and are only stored in the Body’s they reference.
A search only traverses a reference if it starts at a Body.
References are not invertible or reveresible, since Body’s cannot have outgoing edges.
- A Transform is a defining Edge for a Frame.
Transform edges go from a Frame to a different Frame in the same space.
References may be invertible.
- A Projection is an Edge from a Frame in one space to a Frame in a different space.
An onto() search is limited to traversing one projection at a time.
Strictly speaking, projections are not invertible by definition, since they cannot be idempotent. However, for simplicity, we consider a projection to be invertible if there is a known projection in the opposite direction, even though it cannot return the original node exactly.
Edges can be composed together to form a shortcut over the path they form. This is done with the @ operator, as with matrix multiplication. Conceptually, edges can transform other edges but not non-edge nodes.
If an edge is invertible, it is responsible for handling its own inverse. For example, if a point is actually moved, so that the edge to it is changed, the edge must change its own inverse as well to match.
- copy()¶
Perform a deepcopy of self.
- inverse()¶
Get the inverse of the edge, if it exists.
- Returns
The inverse edge, if the edge is invertible.
- Return type
Optional[E_new]
- Raises
NotInvertibleError – If the edge is not invertible.
- invertible()¶
Determine whether the edge is invertible.
Sub-classes may wish to override this method if the invertibility is known without attempting to actually compute the inverse.
- Returns
True if the class is invertible.
- Return type
bool
- abstract join(other)¶
Join the two edges together.
This is the functional representation of the edge, meant to be overwridden by the user.
- Parameters
other (E) – The other edge.
- Returns
A new edge of type self.output_type.
- Return type
E_new
- class fledge.Frame(defining_edge=None, defining_frame=None, space=None, name=None)¶
A Frame provides a frame of reference to describe an object or Body in that space.
A Frame has in-degree <= 1 (not counting the self-loop, which all Frames have) and any out-degree. Frames are similar to Bodies, in that they usually have one incoming edge and can be referenced in other frames, but they are not the same. A frame may have no incoming edges, and Frames cannot be projected onto other spaces.
since they will be defined in connection to another frame, except for the “world” frame, which has no incoming edges. (There may be more than one world frame.)
That is, most Frames are also Bodies, from the perspective of their own reference frame.
Frames can be sources in the graph, a “world frame”. A “world” is a connected component of the overall universe, which is directed and acyclic, where the “world frame” is the source node.
Frames can be subclassed to specify how a point would be represented in that frame, and to have non-generic frames that only exist in one kind of space (e.g. CartesianFrame3D, which only exists in Euclidean3D space.) Sub-classes are responsible for calling super().
Sub-classes may wish to override: * identity() * space_type_bound, a class variable.
- Parameters
defining_edge (fledge.core.Transform) –
defining_frame (Union[None, str, Frame]) –
space (fledge.core.S_co) –
name (Optional[str]) –
- Return type
None
- connect(edge, frame=None, space=None)¶
TODO.
- Parameters
edge (fledge.core.Edge) –
frame (Union[None, str, fledge.core.Frame]) –
space (Union[None, str, fledge.core.Space]) –
- Return type
None
- full_name()¶
A full name for the frame, guaranteed to be unique.
- identity()¶
Get an identity transform on edges from this frame.
Should be overridden by sub-classes to get identities on those frame types.
- Return type
- is_orphan()¶
Whether the frame is completely unconnected.
- Return type
bool
- orphan()¶
Orphan this frame by removes all edges to/from it, except to bodies.
- rename(name)¶
Rename the frame and update the space.
Sub-classes may wish to modify the name somehow. They are responsible for calling super().rename(name).
- Parameters
name (str) –
- Return type
None
- traverse(edge, name=None)¶
Define new bodies or frames in the same space as this one, by traversing an edge.
Sub-classes may wish to implement wrappers around connect, like CartesianFrame3D.point(), which would create a new point, but they should not override connect.
The traverse method is unique to Frame nodes, since edges can only begin at frames.
- Parameters
edge (fledge.core.Edge) – the edge to follow. If a transform or reference, this is the defining edge of the resulting node. Cannot be a projection.
kwargs – other information to pass to the output node constructor.
name (Optional[str]) –
- Returns
A new node in the reference graph, either a frame or a body.
- Return type
- Raises
TypeError – If the frame type is not a subclass of edge.input_frame_type.
ValueError – If edge is a projection.
- vis_properties()¶
Visualization properties.
- Return type
Dict[str, Any]
- class fledge.Identity¶
The generic identity edge, which is a self-loop.
Sub-classes may wish to implement __array__ to represent numerically meaningful identity functions.
- inverse()¶
I^-1 = I.
- invertible()¶
I is always invertible.
- join(other)¶
The output contains the same values as the input, but it is not the same.
- Parameters
other (fledge.core.Edge[fledge.core.N1, fledge.core.N2]) –
- Return type
fledge.core.Edge[fledge.core.N1, fledge.core.N2]
- class fledge.Node(defining_edge=None, defining_frame=None, space=None)¶
A node represents an object in a physical space.
A node can only belong to one space. All nodes contain references to the space they are in, but only frames are referenced by their space.
- Parameters
- Return type
None
- defining_edge¶
the edge from defining_frame to self, if it exists.
- defining_frame¶
the frame which defines this node, if it exists.
- space¶
the space this node is in. If a name is provided, and the name is not used, a new space is created. If None, and defining_frame is provided as an instance, defining_frame.space is used.
- Type
fledge.core.S_co
- incoming_projections¶
mapping from projection names to projections.
- Type
- space_type_bound¶
This node can only belong to subtypes of space_type_variable. This class variable should be fixed for each class. It must correspond to the type of the Node.
- Type
type
- connect(edge, frame=None, space=None)¶
Add or modify an incoming edge to this Node.
Reposition this node by redefining its incoming edge, possibly in another frame.
Note that this does not create a new frame but rather redefines this existing one. To create a new frame, use defining_frame.traverse(defining_edge).
- Parameters
edge (fledge.core.Edge) – The new incoming edge which will define the frame.
frame (Union[None, str, fledge.core.Frame]) – The frame to define this frame in. If None, self.defining_frame is used. If self.defining_frame is None (i.e. self is a source node), then an existing frame or the name of an existing frame must be provided.
space (Union[None, str, fledge.core.Space]) – Must be provided if edge is a projection and only the name of the source frame is provided, to find the instance of the frame. Otherwise not needed.
- Raises
RuntimeError – If the space is not provided for frame lookup by string.
TypeError – If the types being connected do not align.
ValueError – If insufficient args are provided.
- Return type
None
- property defining_edge: Optional[fledge.core.Edge]¶
TODO.
- property defining_frame: Optional[fledge.core.Frame]¶
TODO.
- final in_frame(frame, projection=None)¶
Get the representation of the object in the given frame.
If no projection is provided, in_frame() will return a new edge which leads to the same node (theoretically) but from the given frame, in the same space.
If a projection is provided, in_frame() will return a new node by taking that projection from the projection’s input space to self.space, returning an edge to a wholly different node in frame.space.
If multiple projections are provided, only one is considered at a time. This is useful if the path to the desired frame passes through more than one intermediate space.
If the desired frame is reachable without traversing the given projection,
In general, the projection needs to be provided that links self.space to frame.space. This is because multiple projections might link the spaces, each of which would lead to a different end-node. GeoFrame resolves this ambiguity by only allowing one projection to be allowed to be traversed at a time.
- Parameters
frame (Union[str, fledge.core.Frame]) – the desired frame to represent self in, or the name of the frame.
projection (Union[None, str, fledge.core.Projection, list[typing.Union[str, ~P]]]) – a projection or list of projections which are valid to cross, in order.
- Returns
The edge from frame to self.
- Return type
- Raises
NoPathError – if there is no path to the desired frame utilizing the projection. This is also raised if the desired frame is reachable without using a projection provided, to prevent confusion about which space a frame is in.
RuntimeError – If errors are encountered in the reference graph.
- final into(frame, **kwargs)¶
Creates a new node defined in the new frame in the same location as this one.
The difference between in_frame() and into() is that in_frame() returns the edge representation without creating a new node. into() returns a new node which could be manipulated independently of the old one.
- Parameters
frame (Union[str, fledge.core.Frame]) –
- Return type
- is_orphan()¶
Should encompass any other incoming or outgoing edges for a frame.
- Return type
bool
- is_source()¶
Whether the node has a defining edge (and frame).
- Return type
bool
- orphan()¶
Orphan this node by disconnecting it from all other nodes.
Sub-classes should override this.
- Return type
None
- set_definition(edge, frame)¶
Set the defining edge or frame for this node.
Performs checks to ensure that both or neither are defined. Note that Bodies should have an additional check that neither are None.
Note that this cannot be used to remove definitions. That is, a value of None will not override an existing definition. For that, use the orphan() method.
- Parameters
edge (Optional[fledge.core.Edge]) –
frame (Union[None, str, fledge.core.Frame]) –
- space_type_bound¶
alias of
fledge.core.Space
- vis_properties()¶
Get the dictionary of custom properties to set for this node.
- Returns
Keyword arguments passed.
- Return type
Dict[str, Any]
- class fledge.Projection(name=None)¶
A Projection is an edge that goes to a different space.
Projections are not invertible, by definition. However, they may be reversible. If this is the case, the frame is responsible for adding the projection’s reverse to the graph.
The base Projection is generic.
Projections are named because they are uniquely identified paths between spaces and have no guarantee of maintaining spatial relationships with one another.
- Parameters
name (str) –
- input_type_bound¶
alias of
fledge.core.Frame
- final inverse()¶
Projections cannot be inverted.
- final invertible()¶
Projections cannot be inverted.
- join(other)¶
Join this projection with another edge.
Projections joined with references are references in a different space.
Projections joined with transforms or projections are also projections.
- ouput_type¶
alias of
fledge.core.Frame
- reverse(name=None)¶
Get the reverse of the projection.
This is used to add the projection that goes in the opposite direction. This is not the same as the inverse, since extra information would be needed to get the same object, but it is similar.
For example, a camera projection takes points in 3D and projections them onto 2D image indices. The reverse would be a projection that takes a 2D point on the image and returns the line connecting that point and the focal point.
- Parameters
name (Optional[str]) – The name for the reversed Projection.
- Returns
The projection that maps from the output space of self to the input space.
- Raises
NotReversibleError – If the projection is not reversible.
- Return type
- reversible()¶
Determine whether the projection is reversible.
Sub-classes may wish to implement a version that doesn’t require actually creating the reverse.
- Returns
Whether this projection is reversible.
- Return type
bool
- class fledge.Reference¶
A Reference is a Edge that terminates at a Body.
References are not invertible, and they cannot be joined together with matmul.
Note that the bodies these references describe may implement matmul, such as vectors being multiplied, but edges are descriptions, and only edges between frames can be joined.
The base reference is a so-called “generic” reference, because it can be used to connect nodes but it doesn’t contain any data.
- Return type
None
- input_type_bound¶
alias of
fledge.core.Frame
- inverse()¶
References are not invertible (in the spatial sense).
- invertible()¶
Can’t invert a reference.
- final join(other)¶
References have no join.
- output_type¶
alias of
fledge.core.Body
- class fledge.Space(name=None)¶
A space is a set of objects.
To be precise, a space is a subset of nodes in the reference graph. fledge.Space represents this abstraction by containing all the frames internally. It does not contain references to non-frame nodes, but it does support membership tests for these types, by checking the space attribute of the node.
A Space represents a physical space, like a room or a 2D sheet of paper. It contains nodes and can be refered to by a name. Spaces are created when someone instantiates a Frame without providing a space, or if the space name has not been made yet.
All space instances are mutually disjoint, by definition, since the .
- Parameters
name (str) –
- Return type
None
- add(frame)¶
Add the frame to the space.
- Parameters
frame (fledge.core.Frame) –
- Return type
None
- get(frame)¶
Get the frame by name or instance.
If a Frame instance is provided, this merely checks that frame is in self.
- Parameters
frame (Union[str, fledge.core.Frame[Any]]) –
- Return type
- remove(frame)¶
Destroy the given frame.
- Parameters
frame (Union[str, fledge.core.Frame]) –
- Return type
None
- final rename(name)¶
Rename the space.
- Parameters
name (str) –
- Return type
None
- class fledge.Transform¶
A Transform is an edge to a frame in the same space.
The base transform is invertible, defines only generic relationship, and stores no information. When joined with more sophisticated edges, it makes them generic.
- Return type
None
- input_type_bound¶
alias of
fledge.core.Frame
- inverse()¶
Inverse.
- invertible()¶
The generic transform is invertible.
- join(other)¶
The generic transform simply acts like the identity edge.
- output_type¶
alias of
fledge.core.Frame
- fledge.get_graph(*bodies)¶
Show the reference graph, with the provided bodies shown.
TODO items: * Invertible/reversible edges should have their inverse/reverse drawn in dashed lines. * Projections, Transforms, and References should all be different colors. * Projections, frames, and spaces should have their names on the graph. * Spaces should be represented as group:
- Parameters
bodies (B) – The bodies that are to be included in the graph.
- Returns
The reference graph including all spaces, frames, projections, and transforms. References are only included if the associated body is provided.
- Return type
networkx.classes.multigraph.MultiGraph
- fledge.get_projection(projection)¶
Get a projection by name.
- Parameters
projection (Union[str, fledge.core.P]) –
- Return type
fledge.core.P
- fledge.get_space(space)¶
Get a space by name.
- Parameters
space (Union[str, fledge.core.S]) –
- Return type
fledge.core.S
- fledge.show(*bodies, path='fledge_graph.html')¶
Get the reference graph and show it in an interactive window.
- Parameters
bodies (fledge.core.B) –
path (str) –
- Return type
None