Skip to content

Commit

Permalink
Merge pull request #517 from moritz-h/table-flag-filter
Browse files Browse the repository at this point in the history
Add table flag filter module
  • Loading branch information
reinago committed Feb 6, 2020
2 parents b984c05 + da1cca8 commit 183e9df
Show file tree
Hide file tree
Showing 3 changed files with 266 additions and 0 deletions.
2 changes: 2 additions & 0 deletions plugins/mmstd_datatools/src/mmstd_datatools.cpp
Expand Up @@ -81,6 +81,7 @@
#include "table/MMFTDataWriter.h"
#include "table/TableColumnFilter.h"
#include "table/TableColumnScaler.h"
#include "table/TableFlagFilter.h"
#include "table/TableJoin.h"
#include "table/TableObserverPlane.h"
#include "table/TableToLines.h"
Expand Down Expand Up @@ -213,6 +214,7 @@ class plugin_instance : public megamol::core::utility::plugins::Plugin200Instanc
this->module_descriptions.RegisterAutoDescription<megamol::stdplugin::datatools::table::TableObserverPlane>();
this->module_descriptions.RegisterAutoDescription<megamol::stdplugin::datatools::table::TableJoin>();
this->module_descriptions.RegisterAutoDescription<megamol::stdplugin::datatools::table::TableColumnFilter>();
this->module_descriptions.RegisterAutoDescription<megamol::stdplugin::datatools::table::TableFlagFilter>();
this->module_descriptions.RegisterAutoDescription<megamol::stdplugin::datatools::ParticleVelocities>();
this->module_descriptions.RegisterAutoDescription<megamol::stdplugin::datatools::ParticleNeighborhood>();
this->module_descriptions.RegisterAutoDescription<megamol::stdplugin::datatools::ParticleThermodyn>();
Expand Down
181 changes: 181 additions & 0 deletions plugins/mmstd_datatools/src/table/TableFlagFilter.cpp
@@ -0,0 +1,181 @@
/*
* TableFlagFilter.cpp
*
* Copyright (C) 2020 by VISUS (University of Stuttgart)
* Alle Rechte vorbehalten.
*/

#include "stdafx.h"
#include "TableFlagFilter.h"

#include "mmcore/param/EnumParam.h"
#include "vislib/sys/Log.h"

using namespace megamol::stdplugin::datatools;
using namespace megamol::stdplugin::datatools::table;
using namespace megamol;

TableFlagFilter::TableFlagFilter()
: core::Module()
, tableInSlot("getDataIn", "Float table input")
, flagStorageInSlot("readFlagStorage", "Flag storage read input")
, tableOutSlot("getDataOut", "Float table output")
, filterModeParam("filterMode", "filter mode")
, tableInFrameCount(0)
, tableInDataHash(0)
, tableInColCount(0)
, dataHash(0)
, rowCount(0) {

this->tableInSlot.SetCompatibleCall<TableDataCallDescription>();
this->MakeSlotAvailable(&this->tableInSlot);

this->flagStorageInSlot.SetCompatibleCall<core::FlagCallRead_GLDescription>();
this->MakeSlotAvailable(&this->flagStorageInSlot);

this->tableOutSlot.SetCallback(TableDataCall::ClassName(),
TableDataCall::FunctionName(0),
&TableFlagFilter::getData);
this->tableOutSlot.SetCallback(TableDataCall::ClassName(),
TableDataCall::FunctionName(1),
&TableFlagFilter::getHash);
this->MakeSlotAvailable(&this->tableOutSlot);

auto* fmp = new core::param::EnumParam(FilterMode::FILTERED);
fmp->SetTypePair(FilterMode::FILTERED, "Filtered");
fmp->SetTypePair(FilterMode::SELECTED, "Selected");
this->filterModeParam << fmp;
this->MakeSlotAvailable(&this->filterModeParam);
}

TableFlagFilter::~TableFlagFilter() {
this->Release();
}

bool TableFlagFilter::create() {
return true;
}

void TableFlagFilter::release() {
}

bool TableFlagFilter::getData(core::Call &call) {
if (!this->handleCall(call)) {
return false;
}

auto *tableOutCall = dynamic_cast<TableDataCall *>(&call);
tableOutCall->SetFrameCount(this->tableInFrameCount);
tableOutCall->SetDataHash(this->dataHash);
tableOutCall->Set(this->tableInColCount, this->rowCount, this->colInfos.data(), this->data.data());

return true;
}

bool TableFlagFilter::getHash(core::Call &call) {
if (!this->handleCall(call)) {
return false;
}

auto *tableOutCall = dynamic_cast<TableDataCall *>(&call);
tableOutCall->SetFrameCount(this->tableInFrameCount);
tableOutCall->SetDataHash(this->dataHash);

return true;
}

bool TableFlagFilter::handleCall(core::Call &call) {
auto *tableOutCall = dynamic_cast<TableDataCall *>(&call);
auto *tableInCall = this->tableInSlot.CallAs<TableDataCall>();
auto *flagsInCall = this->flagStorageInSlot.CallAs<core::FlagCallRead_GL>();

if (tableOutCall == nullptr) {
return false;
}

if (tableInCall == nullptr) {
vislib::sys::Log::DefaultLog.WriteMsg(
vislib::sys::Log::LEVEL_ERROR, "TableFlagFilter requires a table!");
return false;
}

if (flagsInCall == nullptr) {
vislib::sys::Log::DefaultLog.WriteMsg(
vislib::sys::Log::LEVEL_ERROR, "TableFlagFilter requires a flag storage!");
return false;
}

tableInCall->SetFrameID(tableOutCall->GetFrameID());
(*tableInCall)(1);
(*tableInCall)(0);
(*flagsInCall)(core::FlagCallRead_GL::CallGetData);

if (this->tableInFrameCount != tableInCall->GetFrameCount() || this->tableInDataHash != tableInCall->DataHash() || flagsInCall->hasUpdate()) {
vislib::sys::Log::DefaultLog.WriteMsg(vislib::sys::Log::LEVEL_INFO, "TableFlagFilter: Filter table.");

this->dataHash++;

this->tableInFrameCount = tableInCall->GetFrameCount();
this->tableInDataHash = tableInCall->DataHash();
this->tableInColCount = tableInCall->GetColumnsCount();
size_t tableInRowCount = tableInCall->GetRowsCount();

// download flags
flagsInCall->getData()->validateFlagCount(tableInRowCount);
auto flags = flagsInCall->getData()->flags;
uint32_t *flagsData = new uint32_t[flags->getByteSize() / sizeof(uint32_t)];
flags->bind();
glGetBufferSubData(flags->getTarget(), 0, flags->getByteSize(), flagsData);

// copy column infos
this->colInfos.resize(this->tableInColCount);
for (size_t i = 0; i < this->tableInColCount; ++i) {
this->colInfos[i] = tableInCall->GetColumnsInfos()[i];
this->colInfos[i].SetMinimumValue(std::numeric_limits<float>::max());
this->colInfos[i].SetMaximumValue(std::numeric_limits<float>::lowest());
}

core::FlagStorage::FlagItemType testMask = core::FlagStorage::ENABLED | core::FlagStorage::FILTERED;
core::FlagStorage::FlagItemType passMask = core::FlagStorage::ENABLED;;
if (static_cast<FilterMode>(this->filterModeParam.Param<core::param::EnumParam>()->Value()) == FilterMode::SELECTED) {
testMask = core::FlagStorage::ENABLED | core::FlagStorage::SELECTED | core::FlagStorage::FILTERED;
passMask = core::FlagStorage::ENABLED | core::FlagStorage::SELECTED;
}

// Resize data to size of input table. With this we only need to allocate memory once.
this->data.resize(this->tableInColCount * tableInRowCount);
this->rowCount = 0;

const float *tableInData = tableInCall->GetData();
for (size_t r = 0; r < tableInRowCount; ++r) {
if ((flagsData[r] & testMask) == passMask) {
for (size_t c = 0; c < this->tableInColCount; ++c) {
float val = tableInData[this->tableInColCount * r + c];
this->data[this->tableInColCount * this->rowCount + c] = val;
if (val < this->colInfos[c].MinimumValue()) {
this->colInfos[c].SetMinimumValue(val);
}
if (val > this->colInfos[c].MaximumValue()) {
this->colInfos[c].SetMaximumValue(val);
}
}
this->rowCount++;
}
}

// delete memory of filtered rows
this->data.resize(this->tableInColCount * this->rowCount);

delete[] flagsData;

// nicer output
if (this->rowCount == 0) {
for (size_t i = 0; i < this->tableInColCount; ++i) {
this->colInfos[i].SetMinimumValue(0.0);
this->colInfos[i].SetMaximumValue(0.0);
}
}
}

return true;
}
83 changes: 83 additions & 0 deletions plugins/mmstd_datatools/src/table/TableFlagFilter.h
@@ -0,0 +1,83 @@
/*
* TableFlagFilter.h
*
* Copyright (C) 2020 by VISUS (University of Stuttgart)
* Alle Rechte vorbehalten.
*/

#ifndef MEGAMOL_DATATOOLS_FLOATTABLE_FLOATTABLEFLAGFILTER_H_INCLUDED
#define MEGAMOL_DATATOOLS_FLOATTABLE_FLOATTABLEFLAGFILTER_H_INCLUDED

#include "mmcore/Module.h"
#include "mmcore/CalleeSlot.h"
#include "mmcore/CallerSlot.h"
#include "mmcore/FlagCall_GL.h"
#include "mmcore/param/ParamSlot.h"
#include "mmstd_datatools/table/TableDataCall.h"

namespace megamol {
namespace stdplugin {
namespace datatools {
namespace table {

/*
* Module to filter rows from a table based on a flag storage.
*/
class TableFlagFilter : public core::Module {
public:
/** Return module class name */
static const char* ClassName() { return "TableFlagFilter"; }

/** Return module class description */
static const char* Description() { return "Filters rows from a table based on a flag storage."; }

/** Module is always available */
static bool IsAvailable() { return true; }

/** Ctor */
TableFlagFilter();

/** Dtor */
~TableFlagFilter() override;

protected:
bool create() override;

void release() override;

bool getData(core::Call &call);

bool getHash(core::Call &call);

bool handleCall(core::Call &call);

private:
enum FilterMode {
FILTERED = 0,
SELECTED = 1
};

core::CallerSlot tableInSlot;
core::CallerSlot flagStorageInSlot;
core::CalleeSlot tableOutSlot;

core::param::ParamSlot filterModeParam;

// input table properties
unsigned int tableInFrameCount;
size_t tableInDataHash;
size_t tableInColCount;

// filtered table
size_t dataHash;
size_t rowCount;
std::vector<TableDataCall::ColumnInfo> colInfos;
std::vector<float> data;
};

} /* end namespace table */
} /* end namespace datatools */
} /* end namespace stdplugin */
} /* end namespace megamol */

#endif /* MEGAMOL_DATATOOLS_FLOATTABLE_FLOATTABLEFLAGFILTER_H_INCLUDED */

0 comments on commit 183e9df

Please sign in to comment.