Back

Decomposer

Overview

The Decomposer is the abstract base class for all attribute decomposition strategies. It defines the interface that concrete decomposers (like Components and Coordinates) must implement. You can also create custom decomposers by inheriting from GenDecomposer<Derived>.

Include
#include <dataframe/attributes/Manager.h>  // Decomposer is defined here

Decomposer Base Class

Decomposer Interface
namespace df::attributes {

class Decomposer {
public:
    virtual ~Decomposer() = default;

    // Create a polymorphic clone of this decomposer
    virtual std::unique_ptr<Decomposer> clone() const = 0;

    // Get decomposed attribute names for a given serie
    virtual Strings names(
        const Dataframe& dataframe,
        DecompDimension targetDim,
        const SerieBase& serie,
        const String& name) const = 0;

    // Extract a specific decomposed attribute
    virtual Serie<double> serie(
        const Dataframe& dataframe,
        DecompDimension targetDim,
        const std::string& name) const = 0;

protected:
    // Get component count for a given type
    template <typename T>
    static size_t getComponentCount();

    // Extract a single component from a serie at a given index
    template <typename T>
    static Serie<double> extractComponent(
        const Serie<T>& serie, size_t index);
};

}
MethodDescription
clone()Creates a deep copy of the decomposer for polymorphic ownership
names()Returns all decomposed attribute names for a serie at the given dimension
serie()Extracts a specific component as Serie<double>
getComponentCount<T>()Returns the number of scalar components in type T
extractComponent<T>()Extracts the i-th scalar component from a typed serie

GenDecomposer (CRTP Helper)

GenDecomposer<C> uses the Curiously Recurring Template Pattern to provide automatic clone() and forwarding implementations. Derive from this instead of Decomposer directly.

GenDecomposer Template
namespace df::attributes {

template <typename C>
class GenDecomposer : public Decomposer {
public:
    // Automatic clone via CRTP
    std::unique_ptr<Decomposer> clone() const override;

    // Forwards to derived class names() implementation
    Strings names(const Dataframe&, DecompDimension,
                  const SerieBase&, const String&) const override;

    // Forwards to derived class serie() implementation
    Serie<double> serie(const Dataframe&, DecompDimension,
                        const std::string&) const override;
};

}

Creating a Custom Decomposer

Custom Decomposer Example
#include <dataframe/attributes/Manager.h>

using namespace df;
using namespace df::attributes;

// Custom decomposer that extracts magnitude from vectors
class MagnitudeDecomposer : public GenDecomposer<MagnitudeDecomposer> {
public:
    Strings names(
        const Dataframe& dataframe,
        DecompDimension targetDim,
        const SerieBase& serie,
        const String& name) const override
    {
        if (targetDim == DecompDimension::Scalar) {
            return {name + "_mag"};
        }
        return {};
    }

    Serie<double> serie(
        const Dataframe& dataframe,
        DecompDimension targetDim,
        const std::string& name) const override
    {
        // Parse the base name (remove "_mag" suffix)
        auto baseName = name.substr(0, name.size() - 4);
        auto& base = dataframe.get<Vector3D>(baseName);

        return base.map([](const Vector3D& v, size_t) {
            return std::sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
        });
    }
};

// Usage
Manager manager(dataframe);
manager.addDecomposer(MagnitudeDecomposer());
auto mag = manager.getSerie<double>("velocity_mag");

Built-in Decomposers

DecomposerPurposeNaming Pattern
Components Decomposes vectors, matrices, and tensors into individual scalar components Vectors: Px, Py, Pz
Matrices: M11, M12, ...
Stress: Sxx, Sxy, ...
Coordinates Spatial coordinate decomposition for vector types P_x, P_y, P_z (customizable)