Skip to content

Commit

Permalink
BRAYNS-661 Vector field. (#1282)
Browse files Browse the repository at this point in the history
  • Loading branch information
Adrien4193 authored Sep 10, 2024
1 parent 8f576db commit b5ee397
Show file tree
Hide file tree
Showing 12 changed files with 348 additions and 2 deletions.
2 changes: 2 additions & 0 deletions plugins/AtlasExplorer/api/AtlasFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "atlases/LayerDistanceAtlas.h"
#include "atlases/OrientationAtlas.h"
#include "atlases/ScalarAtlas.h"
#include "atlases/VectorAtlas.h"

namespace
{
Expand Down Expand Up @@ -60,6 +61,7 @@ AtlasFactory AtlasFactory::createDefault()
builder.registerType<LayerDistanceAtlas>();
builder.registerType<OrientationAtlas>();
builder.registerType<ScalarAtlas>();
builder.registerType<VectorAtlas>();
return AtlasFactory(std::move(builder.factories));
}

Expand Down
2 changes: 2 additions & 0 deletions plugins/AtlasExplorer/api/UseCaseManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <api/usecases/LayerDistance.h>
#include <api/usecases/OrientationField.h>
#include <api/usecases/OutlineShell.h>
#include <api/usecases/VectorField.h>

UseCaseManager UseCaseManager::createDefault()
{
Expand All @@ -36,6 +37,7 @@ UseCaseManager UseCaseManager::createDefault()
useCases.push_back(std::make_unique<HighlightColumn>());
useCases.push_back(std::make_unique<LayerDistance>());
useCases.push_back(std::make_unique<OrientationField>());
useCases.push_back(std::make_unique<VectorField>());
useCases.push_back(std::make_unique<OutlineShell>());
useCases.push_back(std::make_unique<FlatmapAreas>());
return UseCaseManager(std::move(useCases));
Expand Down
3 changes: 2 additions & 1 deletion plugins/AtlasExplorer/api/VoxelType.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ enum class VoxelType
Scalar,
Orientation,
Flatmap,
LayerDistance
LayerDistance,
Vector,
};
101 changes: 101 additions & 0 deletions plugins/AtlasExplorer/api/atlases/VectorAtlas.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/* Copyright (c) 2015-2024, EPFL/Blue Brain Project
* All rights reserved. Do not distribute without permission.
* Responsible Author: Nadir Roman Guerrero <[email protected]>
*
* This file is part of Brayns <https://github.com/BlueBrain/Brayns>
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License version 3.0 as published
* by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "VectorAtlas.h"

#include <cassert>

namespace
{
float finiteOrZero(float value)
{
if (std::isfinite(value))
{
return value;
}

return 0.0F;
}

brayns::Vector3f sanitizeVector(brayns::Vector3f vector)
{
for (auto i = std::size_t(0); i < std::size_t(3); ++i)
{
vector[i] = finiteOrZero(vector[i]);
}

auto norm = brayns::math::length(vector);

if (norm == 0.0F)
{
return vector;
}

return vector / norm;
}

std::vector<brayns::Vector3f> extractVectors(const IDataMangler &data)
{
auto floats = data.asFloats();
auto itemCount = floats.size() / 3;

auto result = std::vector<brayns::Vector3f>(itemCount);

#pragma omp parallel for
for (size_t i = 0; i < itemCount; ++i)
{
auto index = i * 3;

auto x = floats[index];
auto y = floats[index + 1];
auto z = floats[index + 2];

result[i] = sanitizeVector({x, y, z});
}

return result;
}
}

VectorAtlas::VectorAtlas(
const brayns::Vector3ui &size,
const brayns::Vector3f &spacing,
const IDataMangler &dataMangler):
Atlas(size, spacing),
_voxels(extractVectors(dataMangler))
{
}

bool VectorAtlas::isValidVoxel(size_t index) const noexcept
{
assert(_isValidIndex(index));
return brayns::math::dot(_voxels[index], _voxels[index]) > 0.f;
}

VoxelType VectorAtlas::getVoxelType() const noexcept
{
return type;
}

const brayns::Vector3f &VectorAtlas::operator[](size_t index) const noexcept
{
assert(_isValidIndex(index));
return _voxels[index];
}
40 changes: 40 additions & 0 deletions plugins/AtlasExplorer/api/atlases/VectorAtlas.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* Copyright (c) 2015-2024, EPFL/Blue Brain Project
* All rights reserved. Do not distribute without permission.
* Responsible Author: Nadir Roman Guerrero <[email protected]>
*
* This file is part of Brayns <https://github.com/BlueBrain/Brayns>
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License version 3.0 as published
* by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#pragma once

#include <api/Atlas.h>
#include <api/DataMangler.h>

class VectorAtlas final : public Atlas
{
public:
static inline const VoxelType type = VoxelType::Vector;

public:
VectorAtlas(const brayns::Vector3ui &size, const brayns::Vector3f &spacing, const IDataMangler &dataMangler);

bool isValidVoxel(size_t linealIndex) const noexcept override;
VoxelType getVoxelType() const noexcept override;
const brayns::Vector3f &operator[](size_t index) const noexcept;

private:
std::vector<brayns::Vector3f> _voxels;
};
150 changes: 150 additions & 0 deletions plugins/AtlasExplorer/api/usecases/VectorField.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/* Copyright (c) 2015-2024, EPFL/Blue Brain Project
* All rights reserved. Do not distribute without permission.
* Responsible Author: Adrien Fleury <[email protected]>
*
* This file is part of Brayns <https://github.com/BlueBrain/Brayns>
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License version 3.0 as published
* by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "VectorField.h"

#include <brayns/engine/components/Geometries.h>
#include <brayns/engine/components/GeometryViews.h>
#include <brayns/engine/geometry/types/Capsule.h>
#include <brayns/engine/systems/GenericBoundsSystem.h>
#include <brayns/engine/systems/GeometryDataSystem.h>
#include <ospray/ospray_cpp/ext/rkcommon.h>

#include <api/ModelType.h>
#include <api/atlases/VectorAtlas.h>

#include <cassert>

namespace
{
float getAxisColor(float value)
{
return (value + 1.0F) / 2.0F;
}

brayns::Vector4f getVectorColor(const brayns::Vector3f &vector)
{
return {
getAxisColor(vector.x),
getAxisColor(vector.y),
getAxisColor(vector.z),
1.0F,
};
}

std::vector<std::size_t> getNonEmptyVoxelIndices(const VectorAtlas &atlas)
{
auto indices = std::vector<std::size_t>();

auto itemCount = atlas.getVoxelCount();

for (auto i = std::size_t(0); i < itemCount; ++i)
{
if (atlas[i] != brayns::Vector3f())
{
indices.push_back(i);
}
}

return indices;
}

struct ColoredCapsules
{
std::vector<brayns::Capsule> capsules;
std::vector<brayns::Vector4f> colors;
};

ColoredCapsules createVectorCapsules(const VectorAtlas &atlas)
{
auto indices = getNonEmptyVoxelIndices(atlas);
auto indexCount = indices.size();

auto result = ColoredCapsules();
result.capsules.resize(indexCount);
result.colors.resize(indexCount);

#pragma omp parallel for
for (auto i = std::size_t(0); i < indexCount; ++i)
{
auto index = indices[i];
const auto &direction = atlas[index];

assert(direction != brayns::Vector3f());

auto bounds = atlas.getVoxelBounds(index);
auto origin = bounds.center();

const auto &spacing = atlas.getSpacing();
auto length = brayns::math::reduce_min(spacing) * 0.5F;

auto radius = 0.05F * length;

auto vector = direction * length;
auto tip = origin + vector;

result.capsules[i] = brayns::CapsuleFactory::cone(origin, radius, tip, 0.0F);
result.colors[i] = getVectorColor(direction);
}

return result;
}

void buildVectorModel(brayns::Model &model, ColoredCapsules capsules)
{
auto &components = model.getComponents();

auto &geometries = components.add<brayns::Geometries>();
auto &geometry = geometries.elements.emplace_back(std::move(capsules.capsules));

auto &views = components.add<brayns::GeometryViews>();
auto &view = views.elements.emplace_back(geometry);
view.setColorPerPrimitive(ospray::cpp::CopiedData(capsules.colors));

auto &systems = model.getSystems();
systems.setBoundsSystem<brayns::GenericBoundsSystem<brayns::Geometries>>();
systems.setDataSystem<brayns::GeometryDataSystem>();
}
}

std::string VectorField::getName() const
{
return "Vector field";
}

bool VectorField::isValidAtlas(const Atlas &atlas) const
{
return atlas.getVoxelType() == VoxelType::Vector;
}

std::shared_ptr<brayns::Model> VectorField::run(const Atlas &atlas, const brayns::JsonValue &payload) const
{
(void)payload;

assert(dynamic_cast<const VectorAtlas *>(&atlas));
const auto &vectorAtlas = static_cast<const VectorAtlas &>(atlas);

auto capsules = createVectorCapsules(vectorAtlas);

auto model = std::make_shared<brayns::Model>(ModelType::atlas);
buildVectorModel(*model, std::move(capsules));

return model;
}
31 changes: 31 additions & 0 deletions plugins/AtlasExplorer/api/usecases/VectorField.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* Copyright (c) 2015-2024, EPFL/Blue Brain Project
* All rights reserved. Do not distribute without permission.
* Responsible Author: Adrien Fleury <[email protected]>
*
* This file is part of Brayns <https://github.com/BlueBrain/Brayns>
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License version 3.0 as published
* by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#pragma once

#include <api/IUseCase.h>

class VectorField : public IUseCase
{
public:
std::string getName() const override;
bool isValidAtlas(const Atlas &atlas) const override;
std::shared_ptr<brayns::Model> run(const Atlas &atlas, const brayns::JsonValue &payload) const override;
};
4 changes: 3 additions & 1 deletion plugins/AtlasExplorer/io/NRRDLoadeParameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ struct EnumReflector<VoxelType>
{"scalar", VoxelType::Scalar},
{"orientation", VoxelType::Orientation},
{"flatmap", VoxelType::Flatmap},
{"layer_distance", VoxelType::LayerDistance}};
{"layer_distance", VoxelType::LayerDistance},
{"vector", VoxelType::Vector},
};
}
};

Expand Down
2 changes: 2 additions & 0 deletions python/brayns/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@
AtlasOrientationField,
AtlasShellOutline,
AtlasUsecase,
AtlasVectorField,
BbpCells,
BbpLoader,
BbpReport,
Expand Down Expand Up @@ -251,6 +252,7 @@
"AtlasOrientationField",
"AtlasShellOutline",
"AtlasUsecase",
"AtlasVectorField",
"Axis",
"BbpCells",
"BbpLoader",
Expand Down
Loading

0 comments on commit b5ee397

Please sign in to comment.