<commit_before>/*
 * ADIOSFlexVolume.h
 *
 * Copyright (C) 2019 by Universitaet Stuttgart (VISUS).
 * Alle Rechte vorbehalten.
 */

#include "ADIOSFlexVolume.h"
#include "mmadios/CallADIOSData.h"
#include "mmcore/param/EnumParam.h"
#include "mmcore/param/FlexEnumParam.h"
#include "mmcore/utility/log/Log.h"
#include <math.h>
#include <numeric>

using namespace megamol::geocalls;

namespace megamol {
namespace adios {

ADIOSFlexVolume::ADIOSFlexVolume()
        : core::Module()
        , volumeSlot("volumeSlot", "Slot to send volume data.")
        , adiosSlot("adiosSlot", "Slot to request ADIOS IO")
        , flexVelocitySlot("vxvyvz", "")
        , memoryLayoutSlot("memLayout", "dimension increments (fastest to slowest)") {

    this->volumeSlot.SetCallback(geocalls::VolumetricDataCall::ClassName(),
        VolumetricDataCall::FunctionName(VolumetricDataCall::IDX_GET_DATA), &ADIOSFlexVolume::onGetData);
    this->volumeSlot.SetCallback(geocalls::VolumetricDataCall::ClassName(),
        VolumetricDataCall::FunctionName(VolumetricDataCall::IDX_GET_EXTENTS), &ADIOSFlexVolume::onGetExtents);
    this->volumeSlot.SetCallback(geocalls::VolumetricDataCall::ClassName(),
        VolumetricDataCall::FunctionName(VolumetricDataCall::IDX_GET_METADATA), &ADIOSFlexVolume::onGetExtents);
    this->volumeSlot.SetCallback(geocalls::VolumetricDataCall::ClassName(),
        VolumetricDataCall::FunctionName(VolumetricDataCall::IDX_START_ASYNC), &ADIOSFlexVolume::onStartAsync);
    this->volumeSlot.SetCallback(geocalls::VolumetricDataCall::ClassName(),
        VolumetricDataCall::FunctionName(VolumetricDataCall::IDX_STOP_ASYNC), &ADIOSFlexVolume::onStopAsync);
    this->volumeSlot.SetCallback(geocalls::VolumetricDataCall::ClassName(),
        VolumetricDataCall::FunctionName(VolumetricDataCall::IDX_TRY_GET_DATA), &ADIOSFlexVolume::onTryGetData);
    this->MakeSlotAvailable(&this->volumeSlot);

    this->adiosSlot.SetCompatibleCall<CallADIOSDataDescription>();
    this->MakeSlotAvailable(&this->adiosSlot);

    this->flexVelocitySlot << new core::param::FlexEnumParam("undef");
    this->MakeSlotAvailable(&this->flexVelocitySlot);

    auto memLayout = new core::param::EnumParam(0);
    memLayout->SetTypePair(0, "xyz");
    memLayout->SetTypePair(1, "zyx");
    this->memoryLayoutSlot.SetParameter(memLayout);
    this->MakeSlotAvailable(&this->memoryLayoutSlot);
}

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

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

void ADIOSFlexVolume::release() {}

bool ADIOSFlexVolume::onGetData(core::Call& call) {
    auto* vdc = dynamic_cast<geocalls::VolumetricDataCall*>(&call);
    if (vdc == nullptr)
        return false;

    auto* cad = this->adiosSlot.CallAs<CallADIOSData>();
    if (cad == nullptr)
        return false;

    if (!(*cad)(1)) {
        megamol::core::utility::log::Log::DefaultLog.WriteError("[ADIOSFlexConvert] Error during GetHeader");
        return false;
    }
    bool dathashChanged = (vdc->DataHash() != cad->getDataHash());
    if ((vdc->FrameID() != currentFrame) || dathashChanged || this->AnyParameterDirty()) {
        this->ResetAllDirtyFlags();

        // get adios meta data
        auto availVars = cad->getAvailableVars();
        for (auto var : availVars) {
            this->flexVelocitySlot.Param<core::param::FlexEnumParam>()->AddValue(var);
        }
        cad->setFrameIDtoLoad(vdc->FrameID());


        const std::string vel_str =
            std::string(this->flexVelocitySlot.Param<core::param::FlexEnumParam>()->ValueString());
        if (vel_str != "undef") {
            if (!cad->inquireVar(vel_str)) {
                megamol::core::utility::log::Log::DefaultLog.WriteError(
                    "[ADIOSFlexVolume] variable \"%s\" does not exist.", vel_str.c_str());
            }
        } else {
            return false;
        }
        if (!(*cad)(0)) {
            megamol::core::utility::log::Log::DefaultLog.WriteError("[ADIOSFlexVolume] Error during GetData");
            return false;
        }
        auto the_velocities = cad->getData(vel_str);

        std::vector<float> VXVYVZ;
        std::size_t cell_count = 0;

        if (vel_str != "undef") {
            VXVYVZ = cad->getData(vel_str)->GetAsFloat();
            cell_count = VXVYVZ.size() / 3;
        } else {
            return false;
        }
        VMAG.resize(cell_count);
        mins.resize(1);
        maxes.resize(1);
        float min = std::numeric_limits<float>::max();
        float max = std::numeric_limits<float>::lowest();
        int xfactor = 1;
        int yfactor = 1;
        int zfactor = 1;
        switch (memoryLayoutSlot.Param<megamol::core::param::EnumParam>()->Value()) {
        case 0: // xyz
            xfactor = 1;
            yfactor = the_velocities->shape[0];
            zfactor = the_velocities->shape[0] * the_velocities->shape[1];
            break;
        case 1: // zyx
            xfactor = the_velocities->shape[1] * the_velocities->shape[2];
            yfactor = the_velocities->shape[1];
            zfactor = 1;
            break;
        }
        for (auto x = 0; x < the_velocities->shape[0]; ++x) {
            for (auto y = 0; y < the_velocities->shape[1]; ++y) {
                for (auto z = 0; z < the_velocities->shape[2]; ++z) {
                    auto offset_in = z * zfactor + y * yfactor + x * xfactor;
                    auto offset_out =
                        z * the_velocities->shape[0] * the_velocities->shape[1] + y * the_velocities->shape[0] + x;
                    auto vx = VXVYVZ[offset_in * 3 + 0];
                    auto vy = VXVYVZ[offset_in * 3 + 1];
                    auto vz = VXVYVZ[offset_in * 3 + 2];
                    auto vmag = std::sqrtf(vx * vx + vy * vy + vz * vz);
                    VMAG[offset_out] = vmag;
                    min = std::min(min, vmag);
                    max = std::max(max, vmag);
                }
            }
        }
        //for (auto x = 0; x < cell_count; ++x) {
        //    auto offset = x +<commit_msg>sqrt fix<commit_after>/*
 * ADIOSFlexVolume.h
 *
 * Copyright (C) 2019 by Universitaet Stuttgart (VISUS).
 * Alle Rechte vorbehalten.
 */

#include "ADIOSFlexVolume.h"
#include "mmadios/CallADIOSData.h"
#include "mmcore/param/EnumParam.h"
#include "mmcore/param/FlexEnumParam.h"
#include "mmcore/utility/log/Log.h"
#include <cmath>
#include <numeric>

using namespace megamol::geocalls;

namespace megamol {
namespace adios {

ADIOSFlexVolume::ADIOSFlexVolume()
        : core::Module()
        , volumeSlot("volumeSlot", "Slot to send volume data.")
        , adiosSlot("adiosSlot", "Slot to request ADIOS IO")
        , flexVelocitySlot("vxvyvz", "")
        , memoryLayoutSlot("memLayout", "dimension increments (fastest to slowest)") {

    this->volumeSlot.SetCallback(geocalls::VolumetricDataCall::ClassName(),
        VolumetricDataCall::FunctionName(VolumetricDataCall::IDX_GET_DATA), &ADIOSFlexVolume::onGetData);
    this->volumeSlot.SetCallback(geocalls::VolumetricDataCall::ClassName(),
        VolumetricDataCall::FunctionName(VolumetricDataCall::IDX_GET_EXTENTS), &ADIOSFlexVolume::onGetExtents);
    this->volumeSlot.SetCallback(geocalls::VolumetricDataCall::ClassName(),
        VolumetricDataCall::FunctionName(VolumetricDataCall::IDX_GET_METADATA), &ADIOSFlexVolume::onGetExtents);
    this->volumeSlot.SetCallback(geocalls::VolumetricDataCall::ClassName(),
        VolumetricDataCall::FunctionName(VolumetricDataCall::IDX_START_ASYNC), &ADIOSFlexVolume::onStartAsync);
    this->volumeSlot.SetCallback(geocalls::VolumetricDataCall::ClassName(),
        VolumetricDataCall::FunctionName(VolumetricDataCall::IDX_STOP_ASYNC), &ADIOSFlexVolume::onStopAsync);
    this->volumeSlot.SetCallback(geocalls::VolumetricDataCall::ClassName(),
        VolumetricDataCall::FunctionName(VolumetricDataCall::IDX_TRY_GET_DATA), &ADIOSFlexVolume::onTryGetData);
    this->MakeSlotAvailable(&this->volumeSlot);

    this->adiosSlot.SetCompatibleCall<CallADIOSDataDescription>();
    this->MakeSlotAvailable(&this->adiosSlot);

    this->flexVelocitySlot << new core::param::FlexEnumParam("undef");
    this->MakeSlotAvailable(&this->flexVelocitySlot);

    auto memLayout = new core::param::EnumParam(0);
    memLayout->SetTypePair(0, "xyz");
    memLayout->SetTypePair(1, "zyx");
    this->memoryLayoutSlot.SetParameter(memLayout);
    this->MakeSlotAvailable(&this->memoryLayoutSlot);
}

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

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

void ADIOSFlexVolume::release() {}

bool ADIOSFlexVolume::onGetData(core::Call& call) {
    auto* vdc = dynamic_cast<geocalls::VolumetricDataCall*>(&call);
    if (vdc == nullptr)
        return false;

    auto* cad = this->adiosSlot.CallAs<CallADIOSData>();
    if (cad == nullptr)
        return false;

    if (!(*cad)(1)) {
        megamol::core::utility::log::Log::DefaultLog.WriteError("[ADIOSFlexConvert] Error during GetHeader");
        return false;
    }
    bool dathashChanged = (vdc->DataHash() != cad->getDataHash());
    if ((vdc->FrameID() != currentFrame) || dathashChanged || this->AnyParameterDirty()) {
        this->ResetAllDirtyFlags();

        // get adios meta data
        auto availVars = cad->getAvailableVars();
        for (auto var : availVars) {
            this->flexVelocitySlot.Param<core::param::FlexEnumParam>()->AddValue(var);
        }
        cad->setFrameIDtoLoad(vdc->FrameID());


        const std::string vel_str =
            std::string(this->flexVelocitySlot.Param<core::param::FlexEnumParam>()->ValueString());
        if (vel_str != "undef") {
            if (!cad->inquireVar(vel_str)) {
                megamol::core::utility::log::Log::DefaultLog.WriteError(
                    "[ADIOSFlexVolume] variable \"%s\" does not exist.", vel_str.c_str());
            }
        } else {
            return false;
        }
        if (!(*cad)(0)) {
            megamol::core::utility::log::Log::DefaultLog.WriteError("[ADIOSFlexVolume] Error during GetData");
            return false;
        }
        auto the_velocities = cad->getData(vel_str);

        std::vector<float> VXVYVZ;
        std::size_t cell_count = 0;

        if (vel_str != "undef") {
            VXVYVZ = cad->getData(vel_str)->GetAsFloat();
            cell_count = VXVYVZ.size() / 3;
        } else {
            return false;
        }
        VMAG.resize(cell_count);
        mins.resize(1);
        maxes.resize(1);
        float min = std::numeric_limits<float>::max();
        float max = std::numeric_limits<float>::lowest();
        int xfactor = 1;
        int yfactor = 1;
        int zfactor = 1;
        switch (memoryLayoutSlot.Param<megamol::core::param::EnumParam>()->Value()) {
        case 0: // xyz
            xfactor = 1;
            yfactor = the_velocities->shape[0];
            zfactor = the_velocities->shape[0] * the_velocities->shape[1];
            break;
        case 1: // zyx
            xfactor = the_velocities->shape[1] * the_velocities->shape[2];
            yfactor = the_velocities->shape[1];
            zfactor = 1;
            break;
        }
        for (auto x = 0; x < the_velocities->shape[0]; ++x) {
            for (auto y = 0; y < the_velocities->shape[1]; ++y) {
                for (auto z = 0; z < the_velocities->shape[2]; ++z) {
                    auto offset_in = z * zfactor + y * yfactor + x * xfactor;
                    auto offset_out =
                        z * the_velocities->shape[0] * the_velocities->shape[1] + y * the_velocities->shape[0] + x;
                    auto vx = VXVYVZ[offset_in * 3 + 0];
                    auto vy = VXVYVZ[offset_in * 3 + 1];
                    auto vz = VXVYVZ[offset_in * 3 + 2];
                    auto vmag = std::sqrt(vx * vx + vy * vy + vz * vz);
                    VMAG[offset_out] = vmag;
                    min = std::min(min, vmag);
                    max = std::max(max, vmag);
                }
            }
        }
        //for (auto x = 0; x < cell_count; ++x) {
        //    auto offset = x +
{'fraction_non_alphanumeric': 0.14356558393255642, 'fraction_numerical': 0.006942722539052815, 'mean_word_length': 2.8351822503961963, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 125, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1545819', 'n_tokens_mistral': 4020, 'n_tokens_neox': 3817, 'n_words': 629}