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
Return type

None

final connect(edge, frame=None, space=None)

TODO.

Parameters
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
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

fledge.core.Identity

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

Union[Frame, Body]

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
  • space (fledge.core.S_co) – the name of the space this node is in. If not provided, or name does not already refer to this space, a new space is created of type self.space_type_bound.

  • defining_edge (Optional[Edge]) –

  • defining_frame (Union[None, str, Frame]) –

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

Dict[fledge.core.Projection, fledge.core.Frame]

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

Edge

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

fledge.core.Node

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
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

fledge.core.Projection

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

fledge.core.Frame

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