![]() |
aimsdata
5.1.2
Neuroimaging data handling
|
Manage transformations (affine and non-linear) transformations graph. More...
#include <aims/transformation/transformationgraph3d.h>
Public Member Functions | |
TransformationGraph3d () | |
virtual | ~TransformationGraph3d () |
void | updateIds () |
Update the internal UUIDs cache. More... | |
Vertex * | referentialById (const std::string &id) const |
Get the vertex (referential) with given ID. More... | |
Edge * | transformationById (const std::string &id) const |
Get the edge (transformation) with given ID. More... | |
carto::rc_ptr< soma::Transformation3d > | transformation (const std::string &id) const |
Get the Transformation3d object for the given UUID. More... | |
Edge * | getTransformation (const std::string &src_ref, const std::string &dst_ref) const |
Get the transformation between source_ref and dst_ref. More... | |
Edge * | getTransformation (const std::string &src_ref, const std::string &dst_ref, bool allow_compose) |
Get the transformation between source_ref and dst_ref. More... | |
Edge * | getTransformation (const Vertex *src_ref, const Vertex *dst_ref) const |
Get the transformation between source_ref and dst_ref. More... | |
Edge * | getTransformation (Vertex *src_ref, Vertex *dst_ref, bool allow_compose) |
Get the transformation between source_ref and dst_ref. More... | |
Edge * | getTransformation_raw (const Vertex *src_ref, const Vertex *dst_ref) const |
same as getTransformation() but don't perform lazy loading. More... | |
Edge * | getTransformation_raw (const std::string &src_ref, const std::string &dst_ref) const |
same as getTransformation() but don't perform lazy loading. More... | |
Edge * | registerTransformation (const std::string &src_ref, const std::string &dst_ref, carto::rc_ptr< soma::Transformation3d >, bool deduced=false) |
Add (or register) the given transformation in the transformations graph. More... | |
Edge * | registerTransformation (Vertex *src_ref, Vertex *dst_ref, carto::rc_ptr< soma::Transformation3d >, bool deduced=false) |
Edge * | registerTransformation (const std::string &src_ref, const std::string &dst_ref, const std::string &filename) |
Edge * | registerTransformation (Vertex *src_ref, Vertex *dst_ref, const std::string &filename) |
void | loadTransformationsGraph (carto::Object desc, const std::string &dirname) |
Load a full transformations graph from a dict-like object. More... | |
carto::Object | asDict (bool affine_only=false, bool allow_read=false, bool embed_affines=false) const |
convert to a dict-like structure compatible with loadTransformationsGraph() More... | |
void | clearCache (bool chain_only=false) |
remove deduced transformations (built from composition or inversion). More... | |
void | registerInverseTransformations (bool loadAffines=false) |
register inverse transformations when they can be obtained. More... | |
std::list< Edge * > | loadAffineTransformations () |
carto::rc_ptr< soma::Transformation3d > | getTransformChain (const Vertex *src_ref, const Vertex *dst_ref) const |
Get a transformation chain between two vertices. More... | |
carto::rc_ptr< soma::Transformation3d > | getTransformChain (const std::string &src_ref, const std::string &dst_ref) const |
carto::rc_ptr< soma::Transformation3d > | loadTransformation (Edge *edge, bool affine_only=false) const |
![]() | |
Graph (const std::string &s="") | |
Graph (const FactoryPtr factory, const std::string &s="") | |
virtual | ~Graph () |
void | extract (Graph &graph, InputIterator iv1, InputIterator iv2) |
void | clear () |
Vertex * | addVertex (const std::string &s="") |
Vertex * | cloneVertex (const Vertex *vertex) |
bool | hasVertex (const Vertex *vertex) const |
void | removeVertex (Vertex *vertex) |
Vertex * | randomVertex () const |
const std::set< Vertex * > & | vertices () const |
std::set< Vertex * > | getVerticesWith (const std::string &s) const |
std::set< Vertex * > | getVerticesWith (const std::string &s, const T &t) const |
Edge * | addUndirectedEdge (Vertex *vertex1, Vertex *vertex2, std::string s) |
Edge * | addEdge (Vertex *vertex1, Vertex *vertex2, std::string s="") |
Edge * | addDirectedEdge (Vertex *vertex1, Vertex *vertex2, std::string s) |
bool | hasEdge (const Edge *edge) const |
void | removeEdge (Edge *edge) |
const std::set< Edge * > & | edges () const |
std::set< Edge * > | edges (const Vertex *vertex1, const Vertex *vertex2) const |
std::set< Edge * > | getEdgesWith (const std::string &s) const |
std::set< Edge * > | getEdgesWith (const std::string &s, const T &t) const |
iterator | begin () |
iterator | end () |
const_iterator | begin () const |
const_iterator | end () const |
reverse_iterator | rbegin () |
reverse_iterator | rend () |
const_reverse_iterator | rbegin () const |
const_reverse_iterator | rend () const |
size_t | order () const |
size_t | size () const __attribute__((__deprecated__("use edgeSize() for " "the number of edges. In a future release |
size_t | size () will return the " "number properties as it does in GenericObject"))) |
size_t | edgesSize () const |
virtual bool | isUndirected () const |
virtual bool | isDirected () const |
virtual bool | check (const carto::SyntaxSet &syntax, std::set< std::string > &missing) const |
void | clear () |
Vertex * | addVertex (const std::string &s="") |
Vertex * | cloneVertex (const Vertex *vertex) |
bool | hasVertex (const Vertex *vertex) const |
void | removeVertex (Vertex *vertex) |
Vertex * | randomVertex () const |
const std::set< Vertex * > & | vertices () const |
std::set< Vertex * > | getVerticesWith (const std::string &s) const |
std::set< Vertex * > | getVerticesWith (const std::string &s, const T &t) const |
Edge * | addUndirectedEdge (Vertex *vertex1, Vertex *vertex2, std::string s) |
Edge * | addEdge (Vertex *vertex1, Vertex *vertex2, std::string s="") |
Edge * | addDirectedEdge (Vertex *vertex1, Vertex *vertex2, std::string s) |
bool | hasEdge (const Edge *edge) const |
void | removeEdge (Edge *edge) |
const std::set< Edge * > & | edges () const |
std::set< Edge * > | edges (const Vertex *vertex1, const Vertex *vertex2) const |
std::set< Edge * > | getEdgesWith (const std::string &s) const |
std::set< Edge * > | getEdgesWith (const std::string &s, const T &t) const |
iterator | begin () |
iterator | end () |
const_iterator | begin () const |
const_iterator | end () const |
reverse_iterator | rbegin () |
reverse_iterator | rend () |
const_reverse_iterator | rbegin () const |
const_reverse_iterator | rend () const |
size_t | order () const |
size_t | size () const __attribute__((__deprecated__("use edgeSize() for " "the number of edges. In a future release |
size_t | size () will return the " "number properties as it does in GenericObject"))) |
size_t | edgesSize () const |
virtual bool | isUndirected () const |
virtual bool | isDirected () const |
virtual bool | check (const carto::SyntaxSet &syntax, std::set< std::string > &missing) const |
![]() | |
virtual | ~GraphObject () |
![]() | |
SyntaxedObject (const std::string &s) | |
SyntaxedObject (const SyntaxedObject &x) | |
SyntaxedObject (const SyntaxedObject< PropertySet > &x) | |
Static Public Member Functions | |
static std::string | referential (const Vertex *v) |
Get the referential ID in the Vertex (its uuid property) More... | |
static carto::rc_ptr< soma::Transformation3d > | transformation (const Edge *edge) |
Get the Transformation3d object inside an edge. More... | |
Additional Inherited Members | |
![]() | |
typedef std::set< Vertex * > | VSet |
typedef std::set< Edge * > | ESet |
typedef carto::rc_ptr< GraphFactory > | FactoryPtr |
typedef VSet::value_type | value_type |
typedef VSet::pointer | pointer |
typedef VSet::reference | reference |
typedef VSet::const_reference | const_reference |
typedef VSet::iterator | iterator |
typedef VSet::const_iterator | const_iterator |
typedef VSet::reverse_iterator | reverse_iterator |
typedef VSet::const_reverse_iterator | const_reverse_iterator |
![]() | |
typedef internal::SyntaxedObjectSwitch< T, SUPERSUBCLASS(Interface, T)>::ContentType | ContentType |
![]() | |
GraphObject (const std::string &s) | |
GraphObject (const GraphObject &x) | |
![]() | |
FactoryPtr | _factory |
Manage transformations (affine and non-linear) transformations graph.
It maintains a graph of directed transformations (vertices are referentials, edges are 3D transformations).
It can be populated from a dictionary (Object) which can be read from a JSON or YAML file, and performs lazy-loading: transformations are actually loaded when they are used, more precisely in getTransformation() and when building a chain of composed transformations.
The graph is oriented, and does not manage inverse transforms. We could thing this could be done automatically for affine or other invertible transformations, but the lazy loading feature does not allow to know if a not yet loaded transform will be invertible or not. So this has to be done manually for now.
The graph populates with composed transforms when they are used: indirect paths from a referential to another are generated when needed, and stored in the graph as "deduced" transforms. Later access will thus use this cache instead of reccomputing it. A drawback, thus, is that the graph has to be used "statically": any modification in the graph structure, or in any of its transformations, should invalidate a number of deduced, cached ones, which we do not handle for now (it's a quite difficult problem to manage it efficiently). To date the only solution is to completely clear the cached transforms (clearCache()) after any modification.
The TransformationGraph3d structure is a Graph, and its elements are Vertex or Edge objects. To manipulate transformations, the API generally allows to use identifiers (generally UUIDs) for elements, and the Transformation objects are accessed through the "transformation" property of edges, or using the transformation() convenience method:
Vertex *ref1 = tgraph.referentialById( "23df7ce8-e405-bc31-3863-d543e3cc89e5" ); Edge *trans_edge = tgraph.getTransformation( "23df7ce8-e405-bc31-3863-d543e3cc89e5", "52929a27-6838-1d08-d6fc-7905ed9413a0" ); if( trans_edge ) { rc_ptr<Transformation3d> trans = tgraph.transformation( trans_edge ); }
see also: https://hbp-spatial-backend.apps.hbp.eu/swagger-ui#/api_v1/get_v1_transform_point
Definition at line 90 of file transformationgraph3d.h.
aims::TransformationGraph3d::TransformationGraph3d | ( | ) |
|
virtual |
carto::Object aims::TransformationGraph3d::asDict | ( | bool | affine_only = false , |
bool | allow_read = false , |
||
bool | embed_affines = false |
||
) | const |
convert to a dict-like structure compatible with loadTransformationsGraph()
Options:
void aims::TransformationGraph3d::clearCache | ( | bool | chain_only = false | ) |
remove deduced transformations (built from composition or inversion).
If chain_only is true, then inverses of direct transforms are not removed.
Edge* aims::TransformationGraph3d::getTransformation | ( | const std::string & | src_ref, |
const std::string & | dst_ref | ||
) | const |
Get the transformation between source_ref and dst_ref.
If it is not a registered transformation, return 0. Lazy loading will take place, however.
Edge* aims::TransformationGraph3d::getTransformation | ( | const std::string & | src_ref, |
const std::string & | dst_ref, | ||
bool | allow_compose | ||
) |
Get the transformation between source_ref and dst_ref.
If it is not a registered transformation, return 0. Lazy loading will take place. If allow_compose is True and the transformation is not found, then a transformations chain path is looked for. If a matching one is found, it is then registered in the graph to allow fast access later. The drawback of this register operation is that it cannot react to changes in the transformation chain (if a new transformation is added and could make a shorter path, it will not be taken into account).
Edge* aims::TransformationGraph3d::getTransformation | ( | const Vertex * | src_ref, |
const Vertex * | dst_ref | ||
) | const |
Get the transformation between source_ref and dst_ref.
If it is not a registered transformation, return 0. Lazy loading will take place, however.
Edge* aims::TransformationGraph3d::getTransformation | ( | Vertex * | src_ref, |
Vertex * | dst_ref, | ||
bool | allow_compose | ||
) |
Get the transformation between source_ref and dst_ref.
If it is not a registered transformation, return 0. Lazy loading will take place. If allow_compose is True and the transformation is not found, then a transformations chain path is looked for. If a matching one is found, it is then registered in the graph to allow fast access later. The drawback of this register operation is that it cannot react to changes in the transformation chain (if a new transformation is added and could make a shorter path, it will not be taken into account).
Edge* aims::TransformationGraph3d::getTransformation_raw | ( | const std::string & | src_ref, |
const std::string & | dst_ref | ||
) | const |
same as getTransformation() but don't perform lazy loading.
Edge* aims::TransformationGraph3d::getTransformation_raw | ( | const Vertex * | src_ref, |
const Vertex * | dst_ref | ||
) | const |
same as getTransformation() but don't perform lazy loading.
carto::rc_ptr<soma::Transformation3d> aims::TransformationGraph3d::getTransformChain | ( | const std::string & | src_ref, |
const std::string & | dst_ref | ||
) | const |
carto::rc_ptr<soma::Transformation3d> aims::TransformationGraph3d::getTransformChain | ( | const Vertex * | src_ref, |
const Vertex * | dst_ref | ||
) | const |
Get a transformation chain between two vertices.
You normally don't need to call this method directly, il is called through getTransformation( src_ref, dst_ref, true ). This method however does not modify the transformations graph and does not register the combined transformation. It will, however, load lazy-loading transformations.
std::list<Edge *> aims::TransformationGraph3d::loadAffineTransformations | ( | ) |
carto::rc_ptr<soma::Transformation3d> aims::TransformationGraph3d::loadTransformation | ( | Edge * | edge, |
bool | affine_only = false |
||
) | const |
void aims::TransformationGraph3d::loadTransformationsGraph | ( | carto::Object | desc, |
const std::string & | dirname | ||
) |
Load a full transformations graph from a dict-like object.
The description dict may typically be read from a .json or a .yaml file.
The description is organized as a 2-level dictionary:
{ source_ref_id: { dest_ref_id1: transformation_filename1, dest_ref_id2: transformation_filename2, }, ... }
A referential ID is a string which may represent an UUID, or a name.
A transformatioon filename may be an affine (.trm) or non-linear (.ima) transformation file, or an empty string to represent an identity transformation.
The transformation files are found relatively to the directory given as the dirname parameter.
Alternatively to file names, an affine transformation may be given directly as its 4x4 matrix, written as a line vector (all 16 coefficients in a vecotr, describing the matrix horizontally). Ex:
{ source_ref_id: { dest_ref_id1: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], }, ... }
Or, a transformation may be a more complete description as a dictionary, containing an affine matrix as above, and possibly a header:
{ "source_ref": { "dest_ref": { "affine": [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1], "header": { "free_field": "free value" } } } }
|
static |
Get the referential ID in the Vertex (its uuid property)
Vertex* aims::TransformationGraph3d::referentialById | ( | const std::string & | id | ) | const |
Get the vertex (referential) with given ID.
void aims::TransformationGraph3d::registerInverseTransformations | ( | bool | loadAffines = false | ) |
register inverse transformations when they can be obtained.
This can be done only for loaded transformations. So the lazy loading feature will prevent for it to work on not already loaded transformations, since we cannot know if they are invertible before they are loaded.
For this reason, the loadAffines parameter allows to load affine transforms and register their inverses.
Edge* aims::TransformationGraph3d::registerTransformation | ( | const std::string & | src_ref, |
const std::string & | dst_ref, | ||
carto::rc_ptr< soma::Transformation3d > | , | ||
bool | deduced = false |
||
) |
Add (or register) the given transformation in the transformations graph.
transform may be a filename, or a Transformation instance. a Transformation is supposed to be a non-linear FFD (Free Form Deformation), not a linear transformation. If transform is a string, it may be:
Edge* aims::TransformationGraph3d::registerTransformation | ( | const std::string & | src_ref, |
const std::string & | dst_ref, | ||
const std::string & | filename | ||
) |
Edge* aims::TransformationGraph3d::registerTransformation | ( | Vertex * | src_ref, |
Vertex * | dst_ref, | ||
carto::rc_ptr< soma::Transformation3d > | , | ||
bool | deduced = false |
||
) |
Edge* aims::TransformationGraph3d::registerTransformation | ( | Vertex * | src_ref, |
Vertex * | dst_ref, | ||
const std::string & | filename | ||
) |
|
static |
Get the Transformation3d object inside an edge.
The returned reference counting pointer may contain a null pointer (lazy loading is not performed in transformaton(), contrarily to getTransformation()).
carto::rc_ptr<soma::Transformation3d> aims::TransformationGraph3d::transformation | ( | const std::string & | id | ) | const |
Get the Transformation3d object for the given UUID.
The returned reference counting pointer may contain a null pointer (lazy loading is not performed in transformaton(), contrarily to getTransformation()).
Edge* aims::TransformationGraph3d::transformationById | ( | const std::string & | id | ) | const |
Get the edge (transformation) with given ID.
void aims::TransformationGraph3d::updateIds | ( | ) |
Update the internal UUIDs cache.
Needs to be done after changes in elements UUIDs or insertion / deletions