Program Listing for File Block.hpp

Return to documentation for file (include/nix/Block.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_BLOCK_H
#define NIX_BLOCK_H

#include <nix/base/EntityWithMetadata.hpp>
#include <nix/base/IBlock.hpp>
#include <nix/Source.hpp>
#include <nix/DataArray.hpp>
#include <nix/DataFrame.hpp>
#include <nix/MultiTag.hpp>
#include <nix/Tag.hpp>
#include <nix/Group.hpp>
#include <nix/Platform.hpp>

#include <nix/util/util.hpp>

#include <string>
#include <memory>
#include <set>

namespace nix {

class NIXAPI Block : public base::EntityWithMetadata<base::IBlock> {

public:

    Block() {}

    Block(const Block &other)
        : EntityWithMetadata(other.impl())
    {
    }

    Block(const std::shared_ptr<base::IBlock> &p_impl)
        : EntityWithMetadata(p_impl)
    {
    }

    Block(std::shared_ptr<base::IBlock> &&ptr)
        : EntityWithMetadata(std::move(ptr))
    {
    }

    //--------------------------------------------------
    // Methods concerning sources
    //--------------------------------------------------

    bool hasSource(const std::string &name_or_id) const {
        return backend()->hasEntity({name_or_id, ObjectType::Source});
    }

    bool hasSource(const Source &source) const {
        if (!util::checkEntityInput(source, false)) {
            return false;
        }
        return backend()->hasEntity(source);
    }

    Source getSource(const std::string &name_or_id) const {
        return backend()->getEntity<base::ISource>(name_or_id);
    }

    Source getSource(ndsize_t index) const {
        if (index >= sourceCount()) {
            throw OutOfBounds("Block::getSource: index is out of bounds!");
        }
        return backend()->getEntity<base::ISource>(index);
    }

    ndsize_t sourceCount() const {
        return backend()->entityCount(ObjectType::Source);
    }

    std::vector<Source> sources(const util::Filter<Source>::type &filter = util::AcceptAll<Source>()) const;

    std::vector<Source> findSources(const util::Filter<Source>::type &filter = util::AcceptAll<Source>(),
                                    size_t max_depth = std::numeric_limits<size_t>::max()) const;

    Source createSource(const std::string &name, const std::string &type);

    bool deleteSource(const std::string &name_or_id) {
        return backend()->deleteSource(name_or_id);
    }

    bool deleteSource(const Source &source);

    //--------------------------------------------------
    // Methods concerning data arrays
    //--------------------------------------------------

    bool hasDataArray(const std::string &name_or_id) const {
        return backend()->hasEntity({name_or_id, ObjectType::DataArray});
    }

    bool hasDataArray(const DataArray &data_array) const {
        if (!util::checkEntityInput(data_array, false)) {
            return false;
        }
        return backend()->hasEntity(data_array);
    }

    DataArray getDataArray(const std::string &name_or_id) const {
        return backend()->getEntity<base::IDataArray>(name_or_id);
    }


    DataArray getDataArray(ndsize_t index) const {
        if (index >= dataArrayCount()) {
            throw OutOfBounds("Block::getDataArray: index is out of bounds!");
        }
        return backend()->getEntity<base::IDataArray>(index);
    }

    std::vector<DataArray> dataArrays(const util::AcceptAll<DataArray>::type &filter
                                      = util::AcceptAll<DataArray>()) const;

    ndsize_t dataArrayCount() const {
        return backend()->entityCount(ObjectType::DataArray);
    }

    DataArray createDataArray(const std::string &name,
                              const std::string &type,
                              nix::DataType      data_type,
                              const NDSize      &shape,
                              const Compression &compression=Compression::Auto);

    template<typename T>
    DataArray createDataArray(const std::string &name,
                              const std::string &type,
                              const T &data,
                              DataType data_type=DataType::Nothing,
                              const Compression &compression=Compression::Auto) {
         const Hydra<const T> hydra(data);

         if (data_type == DataType::Nothing) {
              data_type = hydra.element_data_type();
         }

         const NDSize shape = hydra.shape();
         DataArray da = createDataArray(name, type, data_type, shape, compression);

         const NDSize offset(shape.size(), 0);
         da.setData(data, offset);

         return da;
    }

    bool deleteDataArray(const std::string &name_or_id) {
        return backend()->removeEntity({name_or_id, ObjectType::DataArray});
    }

    bool deleteDataArray(const DataArray &data_array) {
        if (!util::checkEntityInput(data_array, false)) {
            return false;
        }
        return backend()->removeEntity(data_array);
    }

    //--------------------------------------------------
    // Methods concerning DataFrames
    //--------------------------------------------------

    DataFrame createDataFrame(const std::string &name,
                              const std::string &type,
                              const std::vector<Column> &cols,
                              const Compression &compression=Compression::Auto) {
        std::set<std::string> names;
        for (const Column &c : cols) {
            if (!Variant::supports_type(c.dtype)) {
                std::string msg = "Incompatible DataType for column ";
                throw std::invalid_argument(msg + c.name);
            }
            std::pair<std::set<std::string>::iterator, bool> inserted = names.insert(c.name);
            if (!inserted.second) {
                throw ConsistencyError("Block::createDataFrame: Column names must be unique!");
            }
        }
        return backend()->createDataFrame(name, type, cols, compression);
    }

    bool hasDataFrame(const std::string &name_or_id) const {
        return backend()->hasEntity({name_or_id, ObjectType::DataFrame});
    }

    bool hasDataFrame(const DataFrame &df) const {
        if (!util::checkEntityInput(df, false)) {
            return false;
        }
        return backend()->hasEntity(df);
    }

    DataFrame getDataFrame(const std::string &name_or_id) const {
        return backend()->getEntity<base::IDataFrame>(name_or_id);
    }

    DataFrame getDataFrame(ndsize_t index) const {
        if (index >= dataFrameCount()) {
            throw OutOfBounds("Block::getDataFrame: index is out of bounds!");
        }
        return backend()->getEntity<base::IDataFrame>(index);
    }

    std::vector<DataFrame> dataFrames(const util::AcceptAll<DataFrame>::type &filter
                                      = util::AcceptAll<DataFrame>()) const;

    ndsize_t dataFrameCount() const {
        return backend()->entityCount(ObjectType::DataFrame);
    }

    bool deleteDataFrame(const std::string &name_or_id) {
        return backend()->removeEntity({name_or_id, ObjectType::DataFrame});
    }

    bool deleteDataFrame(const DataFrame &df) {
        if (!util::checkEntityInput(df, false)) {
            return false;
        }
        return backend()->removeEntity(df);
    }


    //--------------------------------------------------
    // Methods concerning tags.
    //--------------------------------------------------

    bool hasTag(const std::string &name_or_id) const {
        return backend()->hasEntity({name_or_id, ObjectType::Tag});
    }

    bool hasTag(const Tag &tag) const {
        if (!util::checkEntityInput(tag, false)) {
            return false;
        }
        return backend()->hasEntity(tag);
    }

    Tag getTag(const std::string &name_or_id) const {
        return backend()->getEntity<base::ITag>(name_or_id);
    }

    Tag getTag(ndsize_t index) const {
        if (index >= tagCount()) {
            throw OutOfBounds("Block::getTag: index is out of bounds!");
        }
        return backend()->getEntity<base::ITag>(index);
    }

    std::vector<Tag> tags(const util::Filter<Tag>::type &filter
                          = util::AcceptAll<Tag>()) const;

    ndsize_t tagCount() const {
        return backend()->entityCount(ObjectType::Tag);
    }

    Tag createTag(const std::string &name, const std::string &type,
                              const std::vector<double> &position);

    bool deleteTag(const std::string &name_or_id) {
        return backend()->removeEntity({name_or_id, ObjectType::Tag});
    }

    bool deleteTag(const Tag &tag) {
        if (!util::checkEntityInput(tag, false)) {
            return false;
        }
        return backend()->removeEntity(tag);
    }

    //--------------------------------------------------
    // Methods concerning multi tags.
    //--------------------------------------------------

    bool hasMultiTag(const std::string &name_or_id) const {
        return backend()->hasEntity({name_or_id, ObjectType::MultiTag});
    }

    bool hasMultiTag(const MultiTag &multi_tag) const {
        if (!util::checkEntityInput(multi_tag, false)) {
            return false;
        }
        return backend()->hasEntity(multi_tag);
    }

    MultiTag getMultiTag(const std::string &name_or_id) const {
        return backend()->getEntity<base::IMultiTag>(name_or_id);
    }

    MultiTag getMultiTag(ndsize_t index) const {
        if (index >= multiTagCount()) {
            throw OutOfBounds("Block::getMultiTag: index is out of bounds!");
        }
        return backend()->getEntity<base::IMultiTag>(index);
    }

    std::vector<MultiTag> multiTags(const util::AcceptAll<MultiTag>::type &filter
                                  = util::AcceptAll<MultiTag>()) const;

    ndsize_t multiTagCount() const {
        return backend()->entityCount(ObjectType::MultiTag);
    }

    MultiTag createMultiTag(const std::string &name, const std::string &type,
                          const DataArray &positions);

    bool deleteMultiTag(const std::string &name_or_id) {
        return backend()->removeEntity({name_or_id, ObjectType::MultiTag});
    }

    bool deleteMultiTag(const MultiTag &multi_tag) {
        if (!util::checkEntityInput(multi_tag, false)) {
            return false;
        }
        return backend()->removeEntity(multi_tag);
    }

    //--------------------------------------------------
    // Methods concerning groups
    //--------------------------------------------------
    bool hasGroup(const std::string &name_or_id) const {
        return backend()->hasEntity({name_or_id, ObjectType::Group});
    }

    bool hasGroup(const Group &group) const {
        if (!util::checkEntityInput(group, false)) {
            return false;
        }
        return backend()->hasEntity(group);
    }

    Group getGroup(const std::string &name_or_id) const {
        return backend()->getEntity<base::IGroup>(name_or_id);
    }

    Group getGroup(ndsize_t index) const {
        if (index >= groupCount()) {
            throw OutOfBounds("Block::getGroup: index is out of bounds!");
        }
        return backend()->getEntity<base::IGroup>(index);
    }

    std::vector<Group> groups(const util::AcceptAll<Group>::type &filter
    = util::AcceptAll<Group>()) const;

    ndsize_t groupCount() const {
        return backend()->entityCount(ObjectType::Group);
    }

    Group createGroup(const std::string &name, const std::string &type);

    bool deleteGroup(const std::string &name_or_id) {
        return backend()->removeEntity({name_or_id, ObjectType::Group});
    }

    bool deleteGroup(const Group &group) {
        if (!util::checkEntityInput(group, false)) {
            return false;
        }
        return backend()->removeEntity(group);
    }

    //------------------------------------------------------
    // Operators and other functions
    //------------------------------------------------------

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

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

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

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

}


#endif // NIX_BLOCK_H