Program Listing for File DataArray.hpp

Return to documentation for file (include/nix/DataArray.hpp)

// Copyright (c) 2013, German Neuroinformatics Node (G-Node)
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted under the terms of the BSD License. See
// LICENSE file in the root of the Project.

#ifndef NIX_DATA_ARRAY_H
#define NIX_DATA_ARRAY_H

#include <nix/DataSet.hpp>

#include <nix/base/EntityWithSources.hpp>
#include <nix/base/IDataArray.hpp>
#include <nix/Dimensions.hpp>
#include <nix/Hydra.hpp>
#include <nix/DataFrame.hpp>

#include <nix/Platform.hpp>
#include <nix/util/util.hpp>


namespace nix {

// TODO add documentation for undocumented methods.

class NIXAPI DataArray : public base::EntityWithSources<base::IDataArray>, public DataSet {

public:

    DataArray()
        : EntityWithSources()
    {}

    DataArray(const DataArray &other)
        : EntityWithSources(other.impl())
    {
    }

    DataArray(const std::shared_ptr<base::IDataArray> &p_impl)
        : EntityWithSources(p_impl)
    {
    }

    DataArray(std::shared_ptr<base::IDataArray> &&ptr)
        : EntityWithSources(std::move(ptr))
    {
    }

    //--------------------------------------------------
    // Element getters and setters
    //--------------------------------------------------

    boost::optional<std::string> label() const {
        return backend()->label();
    }

    void label(const std::string &label);

    void label(const none_t t) {
        backend()->label(t);
    }

    boost::optional<std::string> unit() const {
        return backend()->unit();
    }

    void unit(const none_t t) {
        backend()->unit(t);
    }

    void unit(const std::string &unit);

    boost::optional<double> expansionOrigin() const {
        return backend()->expansionOrigin();
    }

    void expansionOrigin(double expansion_origin) {
        backend()->expansionOrigin(expansion_origin);
    }

    void expansionOrigin(const none_t t) {
        backend()->expansionOrigin(t);
    }

    void polynomCoefficients(const std::vector<double> &polynom_coefficients,
                             const Compression &compression=Compression::None) {
        backend()->polynomCoefficients(polynom_coefficients, compression);
    }

    std::vector<double> polynomCoefficients() const {
        return backend()->polynomCoefficients();
    }

    void polynomCoefficients(const none_t t) {
        backend()->polynomCoefficients(t);
    }

    //--------------------------------------------------
    // Methods concerning dimensions
    //--------------------------------------------------

    std::vector<Dimension> dimensions(const util::Filter<Dimension>::type &filter) const;

    std::vector<Dimension> dimensions() const {
        return dimensions(util::AcceptAll<Dimension>());
    }

    ndsize_t dimensionCount() const {
        return backend()->dimensionCount();
    }

    Dimension getDimension(ndsize_t id) const {
        return backend()->getDimension(id);
    }

    SetDimension appendSetDimension(const std::vector<std::string> &labels={}) {
        SetDimension dim = backend()->createSetDimension(backend()->dimensionCount() + 1);
        if (labels.size() > 0 )
            dim.labels(labels);
        return dim;
    }

    RangeDimension appendRangeDimension(const std::vector<double> &ticks, const std::string &label="",
                                        const std::string &unit="") {
        if (ticks.size() == 0) {
            throw nix::InvalidDimension("The ticks of a range dimension must not be empty!",
                                        "DataArray::appendRangeDimension");
        }
        RangeDimension dim = backend()->createRangeDimension(backend()->dimensionCount() + 1, ticks);
        if (label.size() > 0)
            dim.label(label);
        if (unit.size() > 0)
            dim.unit(unit);
        return dim;
    }

    RangeDimension appendAliasRangeDimension() {
        if (this->dataExtent().size() > 1) {
            throw nix::InvalidDimension("AliasRangeDimensions only allowed for 1D numeric DataArrays!",
                                        "DataArray::appendAliasRangeDimension");
        }
        if (!nix::data_type_is_numeric(this->dataType())) {
            throw nix::InvalidDimension("AliasRangeDimensions are only allowed for 1D numeric DataArrays!",
                                        "DataArray::appendAliasRangeDimension");
        }
        if (dimensionCount() > 0) {
            throw nix::InvalidDimension("Cannot append additional alias dimension. There must only be one!",
                                        "DataArray::appendAliasRangeDimension");
        }
        if (this->unit()) {
            std::string unit = *this->unit();
            if(!(util::isSIUnit(unit) || util::isCompoundSIUnit(unit))) {
                throw nix:: InvalidUnit("AliasRangeDimensions are only allowed when SI or composites of SI units are used.",
                                        "DataArray::appendAliasRangeDimension");
            }
        }
        return backend()->createAliasRangeDimension();
    }


    SampledDimension appendSampledDimension(double sampling_interval, const std::string &label="",
                                            const std::string &unit="", double offset=0.0) {
        SampledDimension dim = backend()->createSampledDimension(backend()->dimensionCount() + 1,
                                                                 sampling_interval);
        if (label.size() > 0)
            dim.label(label);
        if (unit.size() > 0)
            dim.unit(unit);
        if (offset > 0.0)
            dim.offset(offset);
        return dim;
    }

    DataFrameDimension appendDataFrameDimension(const DataFrame &frame, unsigned column_index) {
        if (column_index > frame.columns().size()) {
            throw nix::OutOfBounds("DataArray::appendDataFrameDimensios: Invalid columnIndex ", column_index);
        }
        if (!frame) {
            throw nix::UninitializedEntity();
        }

        DataFrameDimension dim = backend()->createDataFrameDimension(backend()->dimensionCount() + 1, frame, column_index);
        return dim;
    };

    DataFrameDimension appendDataFrameDimension(const DataFrame &frame, const std::string &column_name) {
        if (!frame) {
            throw nix::UninitializedEntity();
        }
        unsigned index;
        try {
            index = frame.colIndex(column_name);
        } catch ( ... ) {
            throw nix::OutOfBounds("DataArray::appendDataFrameDimension: provided column name does not exist in the DataFrame!");
        }
        DataFrameDimension dim = backend()->createDataFrameDimension(backend()->dimensionCount() + 1, frame, index);
        return dim;
    };

    DataFrameDimension appendDataFrameDimension(const DataFrame &frame) {
        if (!frame) {
            throw nix::UninitializedEntity();
        }
        DataFrameDimension dim = backend()->createDataFrameDimension(backend()->dimensionCount() + 1, frame);
        return dim;
    };


    DEPRECATED SetDimension createSetDimension(ndsize_t id) {
        return appendSetDimension();
    }

    DEPRECATED RangeDimension createRangeDimension(ndsize_t id, const std::vector<double> &ticks) {
        return appendRangeDimension(ticks);
    }

    DEPRECATED RangeDimension createAliasRangeDimension() {
        return appendAliasRangeDimension();
    }

    DEPRECATED SampledDimension createSampledDimension(ndsize_t id, double sampling_interval) {
        return appendSampledDimension(sampling_interval);
    }

    bool deleteDimensions() {
        return backend()->deleteDimensions();
    }

    //--------------------------------------------------
    // Methods concerning data access.
    //--------------------------------------------------

    void getDataDirect(DataType dtype,
                       void *data,
                       const NDSize &count,
                       const NDSize &offset) const {
        backend()->read(dtype, data, count, offset);
    }

    void setDataDirect(DataType dtype,
                       const void *data,
                       const NDSize &count,
                       const NDSize &offset)
    {
        backend()->write(dtype, data, count, offset);
    }


    NDSize dataExtent() const {
        return backend()->dataExtent();
    }

    void dataExtent(const NDSize &extent) {
        backend()->dataExtent(extent);
    }

    DataType dataType(void) const {
        return backend()->dataType();
    }

    void appendData(DataType dtype, const void *data, const NDSize &count, size_t axis);

    //--------------------------------------------------
    // Other methods and functions
    //--------------------------------------------------

    DataArray &operator=(const none_t &t) {
        ImplContainer::operator=(t);
        return *this;
    }

    DataArray &operator=(const DataArray &other)  {
        ImplContainer::operator=(other);
        return *this;
    }

    NIXAPI friend std::ostream& operator<<(std::ostream &out, const DataArray &ent);

    //
protected:
    //implementation of the DataIO interface
    void ioRead(DataType dtype,
                void *data,
                const NDSize &count,
                const NDSize &offset) const;

    void ioWrite(DataType dtype,
                 const void *data,
                 const NDSize &count,
                 const NDSize &offset);
};


template<>
struct objectToType<nix::DataArray> {
    static const bool isValid = true;
    static const ObjectType value = ObjectType::DataArray;
    typedef nix::base::IDataArray backendType;
};

NIXAPI std::ostream& operator<<(std::ostream &out, const DataArray &ent);

} // namespace nix

#endif // NIX_DATA_ARRAY_H