aimsdata  5.1.2
Neuroimaging data handling
aims::TransformationGraph3d Class Reference

Manage transformations (affine and non-linear) transformations graph. More...

#include <aims/transformation/transformationgraph3d.h>

Inheritance diagram for aims::TransformationGraph3d:
Collaboration diagram for aims::TransformationGraph3d:

Public Member Functions

 TransformationGraph3d ()
 
virtual ~TransformationGraph3d ()
 
void updateIds ()
 Update the internal UUIDs cache. More...
 
VertexreferentialById (const std::string &id) const
 Get the vertex (referential) with given ID. More...
 
EdgetransformationById (const std::string &id) const
 Get the edge (transformation) with given ID. More...
 
carto::rc_ptr< soma::Transformation3dtransformation (const std::string &id) const
 Get the Transformation3d object for the given UUID. More...
 
EdgegetTransformation (const std::string &src_ref, const std::string &dst_ref) const
 Get the transformation between source_ref and dst_ref. More...
 
EdgegetTransformation (const std::string &src_ref, const std::string &dst_ref, bool allow_compose)
 Get the transformation between source_ref and dst_ref. More...
 
EdgegetTransformation (const Vertex *src_ref, const Vertex *dst_ref) const
 Get the transformation between source_ref and dst_ref. More...
 
EdgegetTransformation (Vertex *src_ref, Vertex *dst_ref, bool allow_compose)
 Get the transformation between source_ref and dst_ref. More...
 
EdgegetTransformation_raw (const Vertex *src_ref, const Vertex *dst_ref) const
 same as getTransformation() but don't perform lazy loading. More...
 
EdgegetTransformation_raw (const std::string &src_ref, const std::string &dst_ref) const
 same as getTransformation() but don't perform lazy loading. More...
 
EdgeregisterTransformation (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...
 
EdgeregisterTransformation (Vertex *src_ref, Vertex *dst_ref, carto::rc_ptr< soma::Transformation3d >, bool deduced=false)
 
EdgeregisterTransformation (const std::string &src_ref, const std::string &dst_ref, const std::string &filename)
 
EdgeregisterTransformation (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::Transformation3dgetTransformChain (const Vertex *src_ref, const Vertex *dst_ref) const
 Get a transformation chain between two vertices. More...
 
carto::rc_ptr< soma::Transformation3dgetTransformChain (const std::string &src_ref, const std::string &dst_ref) const
 
carto::rc_ptr< soma::Transformation3dloadTransformation (Edge *edge, bool affine_only=false) const
 
- Public Member Functions inherited from Graph
 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 ()
 
VertexaddVertex (const std::string &s="")
 
VertexcloneVertex (const Vertex *vertex)
 
bool hasVertex (const Vertex *vertex) const
 
void removeVertex (Vertex *vertex)
 
VertexrandomVertex () 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
 
EdgeaddUndirectedEdge (Vertex *vertex1, Vertex *vertex2, std::string s)
 
EdgeaddEdge (Vertex *vertex1, Vertex *vertex2, std::string s="")
 
EdgeaddDirectedEdge (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 ()
 
VertexaddVertex (const std::string &s="")
 
VertexcloneVertex (const Vertex *vertex)
 
bool hasVertex (const Vertex *vertex) const
 
void removeVertex (Vertex *vertex)
 
VertexrandomVertex () 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
 
EdgeaddUndirectedEdge (Vertex *vertex1, Vertex *vertex2, std::string s)
 
EdgeaddEdge (Vertex *vertex1, Vertex *vertex2, std::string s="")
 
EdgeaddDirectedEdge (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
 
- Public Member Functions inherited from GraphObject
virtual ~GraphObject ()
 
- Public Member Functions inherited from carto::SyntaxedObject< class >
 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::Transformation3dtransformation (const Edge *edge)
 Get the Transformation3d object inside an edge. More...
 

Additional Inherited Members

- Public Types inherited from Graph
typedef std::set< Vertex * > VSet
 
typedef std::set< Edge * > ESet
 
typedef carto::rc_ptr< GraphFactoryFactoryPtr
 
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
 
- Public Types inherited from carto::SyntaxedObject< class >
typedef internal::SyntaxedObjectSwitch< T, SUPERSUBCLASS(Interface, T)>::ContentType ContentType
 
- Protected Member Functions inherited from GraphObject
 GraphObject (const std::string &s)
 
 GraphObject (const GraphObject &x)
 
- Protected Attributes inherited from Graph
FactoryPtr _factory
 

Detailed Description

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.

Constructor & Destructor Documentation

◆ TransformationGraph3d()

aims::TransformationGraph3d::TransformationGraph3d ( )

◆ ~TransformationGraph3d()

virtual aims::TransformationGraph3d::~TransformationGraph3d ( )
virtual

Member Function Documentation

◆ asDict()

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:

  • affine_only: if true, inclue only affine transformations
  • allow_read: if true, and if affine_only or embed_affines is also true, all affine transformations will be read in order to determine which are affine. Otherwise only those already loaded in memory (via the lazy reading mechanism) will be known to be affine. This parameter has no effect on non-affine transformations.
  • embed_affines: if true, affine transformations are not recorded as a file name (.trm format), but as an embedded 4x4 matrix.

◆ clearCache()

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.

◆ getTransformation() [1/4]

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.

◆ getTransformation() [2/4]

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

◆ getTransformation() [3/4]

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.

◆ getTransformation() [4/4]

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

◆ getTransformation_raw() [1/2]

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.

◆ getTransformation_raw() [2/2]

Edge* aims::TransformationGraph3d::getTransformation_raw ( const Vertex src_ref,
const Vertex dst_ref 
) const

same as getTransformation() but don't perform lazy loading.

◆ getTransformChain() [1/2]

carto::rc_ptr<soma::Transformation3d> aims::TransformationGraph3d::getTransformChain ( const std::string &  src_ref,
const std::string &  dst_ref 
) const

◆ getTransformChain() [2/2]

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.

◆ loadAffineTransformations()

std::list<Edge *> aims::TransformationGraph3d::loadAffineTransformations ( )

◆ loadTransformation()

carto::rc_ptr<soma::Transformation3d> aims::TransformationGraph3d::loadTransformation ( Edge edge,
bool  affine_only = false 
) const

◆ loadTransformationsGraph()

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

◆ referential()

static std::string aims::TransformationGraph3d::referential ( const Vertex v)
static

Get the referential ID in the Vertex (its uuid property)

◆ referentialById()

Vertex* aims::TransformationGraph3d::referentialById ( const std::string &  id) const

Get the vertex (referential) with given ID.

◆ registerInverseTransformations()

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.

◆ registerTransformation() [1/4]

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:

  • an empty string will be an identity transformation
  • a .trm file will be an affine transformation, and will be passed to the builtin Anatomist system
  • another file (.ima) will be a FFD transformation file and will be registered as its filename. Loading will happen only when the transformation is used, in geTransformation().

◆ registerTransformation() [2/4]

Edge* aims::TransformationGraph3d::registerTransformation ( const std::string &  src_ref,
const std::string &  dst_ref,
const std::string &  filename 
)

◆ registerTransformation() [3/4]

Edge* aims::TransformationGraph3d::registerTransformation ( Vertex src_ref,
Vertex dst_ref,
carto::rc_ptr< soma::Transformation3d ,
bool  deduced = false 
)

◆ registerTransformation() [4/4]

Edge* aims::TransformationGraph3d::registerTransformation ( Vertex src_ref,
Vertex dst_ref,
const std::string &  filename 
)

◆ transformation() [1/2]

static carto::rc_ptr<soma::Transformation3d> aims::TransformationGraph3d::transformation ( const Edge edge)
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()).

◆ transformation() [2/2]

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()).

◆ transformationById()

Edge* aims::TransformationGraph3d::transformationById ( const std::string &  id) const

Get the edge (transformation) with given ID.

◆ updateIds()

void aims::TransformationGraph3d::updateIds ( )

Update the internal UUIDs cache.

Needs to be done after changes in elements UUIDs or insertion / deletions


The documentation for this class was generated from the following file: