Facing issues when doing progressive refinement
-
void Surfaces::calculateEDT(Type type, float defaultResolution) { if (type == Unknown && m_dialog != nullptr) type = m_dialog->surfaceType(); if (!m_cube) m_cube = m_molecule->addCube(); // Start with 0.5 resolution (1st pass) QFuture futureLowRes = QtConcurrent::run([=]() { calculateEDTpass(type, 0.5); }); m_displayMeshWatcher.setFuture(futureLowRes); // end with 0.1 resolution (1st pass) QFuture futureHighRes = QtConcurrent::run([=]() { calculateEDTpass(type, 0.1); }); m_displayMeshWatcher.setFuture(futureHighRes) }
This is the calculateEDTpass function.
void Surfaces::calculateEDTpass(Type type, float defaultResolution) { double probeRadius = 0.0; switch (type) { case VanDerWaals: m_cube->setCubeType(Core::Cube::Type::VdW); break; case SolventAccessible: m_cube->setCubeType(Core::Cube::Type::SolventAccessible); case SolventExcluded: probeRadius = 1.4; m_cube->setCubeType(Core::Cube::Type::SolventExcluded); break; default: break; } // first, make a list of all atom positions and radii Array<Vector3> atomPositions = m_molecule->atomPositions3d(); auto* atoms = new std::vector<std::pair<Vector3, double>>(); double max_radius = probeRadius; QtGui::RWLayerManager layerManager; for (size_t i = 0; i < m_molecule->atomCount(); i++) { if (!layerManager.visible(m_molecule->layer(i))) continue; // ignore invisible atoms auto radius = Core::Elements::radiusVDW(m_molecule->atomicNumber(i)) + probeRadius; atoms->emplace_back(atomPositions[i], radius); if (radius > max_radius) max_radius = radius; } double padding = max_radius + probeRadius; const float res = resolution(defaultResolution); m_cube->setLimits(*m_molecule, res, padding); m_cube->fill(-1.0); const Vector3 min = m_cube->min(); // then, for each atom, set cubes around it up to a certain radius QFuture innerFuture = QtConcurrent::map(*atoms, [=](std::pair<Vector3, double>& in) { double startPosX = in.first(0) - in.second; double endPosX = in.first(0) + in.second; int startIndexX = (startPosX - min(0)) / res; int endIndexX = (endPosX - min(0)) / res + 1; for (int indexX = startIndexX; indexX < endIndexX; indexX++) { double posX = indexX * res + min(0); double radiusXsq = square(in.second) - square(posX - in.first(0)); if (radiusXsq < 0.0) continue; double radiusX = sqrt(radiusXsq); double startPosY = in.first(1) - radiusX; double endPosY = in.first(1) + radiusX; int startIndexY = (startPosY - min(1)) / res; int endIndexY = (endPosY - min(1)) / res + 1; for (int indexY = startIndexY; indexY < endIndexY; indexY++) { double posY = indexY * res + min(1); double lengthXYsq = square(radiusX) - square(posY - in.first(1)); if (lengthXYsq < 0.0) continue; double lengthXY = sqrt(lengthXYsq); double startPosZ = in.first(2) - lengthXY; double endPosZ = in.first(2) + lengthXY; int startIndexZ = (startPosZ - min(2)) / res; int endIndexZ = (endPosZ - min(2)) / res + 1; m_cube->fillStripe(indexX, indexY, startIndexZ, endIndexZ - 1, 1.0f); } } }); innerFuture.waitForFinished(); }
Here I have my displayMesh function
connect(&m_displayMeshWatcher, SIGNAL(finished()), SLOT(displayMesh()));
here's the displayMesh()
void Surfaces::displayMesh() { if (!m_cube) return; if (m_dialog != nullptr) m_smoothingPasses = m_dialog->smoothingPassesValue(); else m_smoothingPasses = 0; if (!m_mesh1) m_mesh1 = m_molecule->addMesh(); if (!m_meshGenerator1) { m_meshGenerator1 = new QtGui::MeshGenerator; connect(m_meshGenerator1, SIGNAL(finished()), SLOT(meshFinished())); } m_meshGenerator1->initialize(m_cube, m_mesh1, m_isoValue, m_smoothingPasses); bool isMO = false; // if it's from a file we should "play it safe" if (m_cube->cubeType() == Cube::Type::MO || m_cube->cubeType() == Cube::Type::FromFile) { isMO = true; } if (isMO) { if (!m_mesh2) m_mesh2 = m_molecule->addMesh(); if (!m_meshGenerator2) { m_meshGenerator2 = new QtGui::MeshGenerator; connect(m_meshGenerator2, SIGNAL(finished()), SLOT(meshFinished())); } m_meshGenerator2->initialize(m_cube, m_mesh2, -m_isoValue, m_smoothingPasses, true); } // Start the mesh generation - this needs an improved mutex with a read lock // to function as expected. Write locks are exclusive, read locks can have // many read locks but no write lock. m_meshGenerator1->start(); if (isMO) m_meshGenerator2->start(); // Track how many meshes are left to show. if (isMO) m_meshesLeft = 2; else m_meshesLeft = 1; }
Looking for a help. I am busy resolving this but unable to, so someone suggested me to ask this in the discuss fourm. Hope to get a reply from you guys
-
void Surfaces::calculateEDT(Type type, float defaultResolution) { if (type == Unknown && m_dialog != nullptr) type = m_dialog->surfaceType(); if (!m_cube) m_cube = m_molecule->addCube(); // Start with 0.5 resolution (1st pass) QFuture futureLowRes = QtConcurrent::run([=]() { calculateEDTpass(type, 0.5); }); m_displayMeshWatcher.setFuture(futureLowRes); // end with 0.1 resolution (1st pass) QFuture futureHighRes = QtConcurrent::run([=]() { calculateEDTpass(type, 0.1); }); m_displayMeshWatcher.setFuture(futureHighRes) }
This is the calculateEDTpass function.
void Surfaces::calculateEDTpass(Type type, float defaultResolution) { double probeRadius = 0.0; switch (type) { case VanDerWaals: m_cube->setCubeType(Core::Cube::Type::VdW); break; case SolventAccessible: m_cube->setCubeType(Core::Cube::Type::SolventAccessible); case SolventExcluded: probeRadius = 1.4; m_cube->setCubeType(Core::Cube::Type::SolventExcluded); break; default: break; } // first, make a list of all atom positions and radii Array<Vector3> atomPositions = m_molecule->atomPositions3d(); auto* atoms = new std::vector<std::pair<Vector3, double>>(); double max_radius = probeRadius; QtGui::RWLayerManager layerManager; for (size_t i = 0; i < m_molecule->atomCount(); i++) { if (!layerManager.visible(m_molecule->layer(i))) continue; // ignore invisible atoms auto radius = Core::Elements::radiusVDW(m_molecule->atomicNumber(i)) + probeRadius; atoms->emplace_back(atomPositions[i], radius); if (radius > max_radius) max_radius = radius; } double padding = max_radius + probeRadius; const float res = resolution(defaultResolution); m_cube->setLimits(*m_molecule, res, padding); m_cube->fill(-1.0); const Vector3 min = m_cube->min(); // then, for each atom, set cubes around it up to a certain radius QFuture innerFuture = QtConcurrent::map(*atoms, [=](std::pair<Vector3, double>& in) { double startPosX = in.first(0) - in.second; double endPosX = in.first(0) + in.second; int startIndexX = (startPosX - min(0)) / res; int endIndexX = (endPosX - min(0)) / res + 1; for (int indexX = startIndexX; indexX < endIndexX; indexX++) { double posX = indexX * res + min(0); double radiusXsq = square(in.second) - square(posX - in.first(0)); if (radiusXsq < 0.0) continue; double radiusX = sqrt(radiusXsq); double startPosY = in.first(1) - radiusX; double endPosY = in.first(1) + radiusX; int startIndexY = (startPosY - min(1)) / res; int endIndexY = (endPosY - min(1)) / res + 1; for (int indexY = startIndexY; indexY < endIndexY; indexY++) { double posY = indexY * res + min(1); double lengthXYsq = square(radiusX) - square(posY - in.first(1)); if (lengthXYsq < 0.0) continue; double lengthXY = sqrt(lengthXYsq); double startPosZ = in.first(2) - lengthXY; double endPosZ = in.first(2) + lengthXY; int startIndexZ = (startPosZ - min(2)) / res; int endIndexZ = (endPosZ - min(2)) / res + 1; m_cube->fillStripe(indexX, indexY, startIndexZ, endIndexZ - 1, 1.0f); } } }); innerFuture.waitForFinished(); }
Here I have my displayMesh function
connect(&m_displayMeshWatcher, SIGNAL(finished()), SLOT(displayMesh()));
here's the displayMesh()
void Surfaces::displayMesh() { if (!m_cube) return; if (m_dialog != nullptr) m_smoothingPasses = m_dialog->smoothingPassesValue(); else m_smoothingPasses = 0; if (!m_mesh1) m_mesh1 = m_molecule->addMesh(); if (!m_meshGenerator1) { m_meshGenerator1 = new QtGui::MeshGenerator; connect(m_meshGenerator1, SIGNAL(finished()), SLOT(meshFinished())); } m_meshGenerator1->initialize(m_cube, m_mesh1, m_isoValue, m_smoothingPasses); bool isMO = false; // if it's from a file we should "play it safe" if (m_cube->cubeType() == Cube::Type::MO || m_cube->cubeType() == Cube::Type::FromFile) { isMO = true; } if (isMO) { if (!m_mesh2) m_mesh2 = m_molecule->addMesh(); if (!m_meshGenerator2) { m_meshGenerator2 = new QtGui::MeshGenerator; connect(m_meshGenerator2, SIGNAL(finished()), SLOT(meshFinished())); } m_meshGenerator2->initialize(m_cube, m_mesh2, -m_isoValue, m_smoothingPasses, true); } // Start the mesh generation - this needs an improved mutex with a read lock // to function as expected. Write locks are exclusive, read locks can have // many read locks but no write lock. m_meshGenerator1->start(); if (isMO) m_meshGenerator2->start(); // Track how many meshes are left to show. if (isMO) m_meshesLeft = 2; else m_meshesLeft = 1; }
Looking for a help. I am busy resolving this but unable to, so someone suggested me to ask this in the discuss fourm. Hope to get a reply from you guys
@Perminder-Singh
Looking for help with what? Resolving what? Where do you give any indication what issue you have?FWIW, at a quick glance
switch
code incalculateEDTpass
looks "flawed", no idea if that is the case or relevant. -
So sorry @JonB if my question wasn't clear to you. In my project, I'm successfully generating three types of meshes: solventExcluded, van der Waals, and solventAccessible. However, when creating a high-resolution mesh with a resolution value of 0.1, it takes a significant amount of time to render on the screen.
To address this, I’m considering an approach where a low-resolution mesh is initially displayed. While the low-resolution mesh is visible in the screen, the high-resolution mesh should be generated in the background. Once the high-resolution mesh is fully prepared at the default resolution of 0.1, it would replace the low-resolution mesh on the screen. For low resolution mesh, res = resolution(0.5) (at calculateEDTpass).
from my thinking calculateEDTpass is working correctly,
void Surfaces::calculateEDT(Type type, float defaultResolution) { if (type == Unknown && m_dialog != nullptr) type = m_dialog->surfaceType(); if (!m_cube) m_cube = m_molecule->addCube(); // Start with 0.5 resolution (1st pass) QFuture futureLowRes = QtConcurrent::run([=]() { calculateEDTpass(type, 0.5); // if you write 0.1 instead of 0.5 you will get a high resolution mesh }); m_displayMeshWatcher.setFuture(futureLowRes);
so in this case I am generating a low resolution mesh with calculateEDT function. How can I make it a two pass so that I can start with low resolution and end with a high resolution mesh? What I am doing wrong in the code I provided earlier? I think calculateEDTpass is correct, but still if it's something wrong can you please help me knowing how can I have a 2 pass algorithm for it?
-
Am I able to explain things correctly to you @JonB ?? Mind replying whenever you get a time.
-
So sorry @JonB if my question wasn't clear to you. In my project, I'm successfully generating three types of meshes: solventExcluded, van der Waals, and solventAccessible. However, when creating a high-resolution mesh with a resolution value of 0.1, it takes a significant amount of time to render on the screen.
To address this, I’m considering an approach where a low-resolution mesh is initially displayed. While the low-resolution mesh is visible in the screen, the high-resolution mesh should be generated in the background. Once the high-resolution mesh is fully prepared at the default resolution of 0.1, it would replace the low-resolution mesh on the screen. For low resolution mesh, res = resolution(0.5) (at calculateEDTpass).
from my thinking calculateEDTpass is working correctly,
void Surfaces::calculateEDT(Type type, float defaultResolution) { if (type == Unknown && m_dialog != nullptr) type = m_dialog->surfaceType(); if (!m_cube) m_cube = m_molecule->addCube(); // Start with 0.5 resolution (1st pass) QFuture futureLowRes = QtConcurrent::run([=]() { calculateEDTpass(type, 0.5); // if you write 0.1 instead of 0.5 you will get a high resolution mesh }); m_displayMeshWatcher.setFuture(futureLowRes);
so in this case I am generating a low resolution mesh with calculateEDT function. How can I make it a two pass so that I can start with low resolution and end with a high resolution mesh? What I am doing wrong in the code I provided earlier? I think calculateEDTpass is correct, but still if it's something wrong can you please help me knowing how can I have a 2 pass algorithm for it?
@Perminder-Singh
Well that is certainly a better description of your situation to get someone to answer! I am afraid I know nothing about your area, I don't even know what it has to do with Qt, maybe it's to do with Qt3D. You will have to wait for someone who knows what this about to help you, best of luck.All I commented on was the
switch
statement incalculateEDTpass()
. If you want two of thecase
s to behave the same, and don't get a compiler warning from your code, I guess that's OK, I wouldn't know. That may well have nothing to do with your issue. -
@Perminder-Singh
Well that is certainly a better description of your situation to get someone to answer! I am afraid I know nothing about your area, I don't even know what it has to do with Qt, maybe it's to do with Qt3D. You will have to wait for someone who knows what this about to help you, best of luck.All I commented on was the
switch
statement incalculateEDTpass()
. If you want two of thecase
s to behave the same, and don't get a compiler warning from your code, I guess that's OK, I wouldn't know. That may well have nothing to do with your issue.@JonB Thanks btw for your response. I'll wait for someone to answer my question. It involves development in c++ where it also uses qt
-
void Surfaces::calculateEDT(Type type, float defaultResolution) { if (type == Unknown && m_dialog != nullptr) type = m_dialog->surfaceType(); if (!m_cube) m_cube = m_molecule->addCube(); // Start with 0.5 resolution (1st pass) QFuture futureLowRes = QtConcurrent::run([=]() { calculateEDTpass(type, 0.5); }); m_displayMeshWatcher.setFuture(futureLowRes); // end with 0.1 resolution (1st pass) QFuture futureHighRes = QtConcurrent::run([=]() { calculateEDTpass(type, 0.1); }); m_displayMeshWatcher.setFuture(futureHighRes) }
This is the calculateEDTpass function.
void Surfaces::calculateEDTpass(Type type, float defaultResolution) { double probeRadius = 0.0; switch (type) { case VanDerWaals: m_cube->setCubeType(Core::Cube::Type::VdW); break; case SolventAccessible: m_cube->setCubeType(Core::Cube::Type::SolventAccessible); case SolventExcluded: probeRadius = 1.4; m_cube->setCubeType(Core::Cube::Type::SolventExcluded); break; default: break; } // first, make a list of all atom positions and radii Array<Vector3> atomPositions = m_molecule->atomPositions3d(); auto* atoms = new std::vector<std::pair<Vector3, double>>(); double max_radius = probeRadius; QtGui::RWLayerManager layerManager; for (size_t i = 0; i < m_molecule->atomCount(); i++) { if (!layerManager.visible(m_molecule->layer(i))) continue; // ignore invisible atoms auto radius = Core::Elements::radiusVDW(m_molecule->atomicNumber(i)) + probeRadius; atoms->emplace_back(atomPositions[i], radius); if (radius > max_radius) max_radius = radius; } double padding = max_radius + probeRadius; const float res = resolution(defaultResolution); m_cube->setLimits(*m_molecule, res, padding); m_cube->fill(-1.0); const Vector3 min = m_cube->min(); // then, for each atom, set cubes around it up to a certain radius QFuture innerFuture = QtConcurrent::map(*atoms, [=](std::pair<Vector3, double>& in) { double startPosX = in.first(0) - in.second; double endPosX = in.first(0) + in.second; int startIndexX = (startPosX - min(0)) / res; int endIndexX = (endPosX - min(0)) / res + 1; for (int indexX = startIndexX; indexX < endIndexX; indexX++) { double posX = indexX * res + min(0); double radiusXsq = square(in.second) - square(posX - in.first(0)); if (radiusXsq < 0.0) continue; double radiusX = sqrt(radiusXsq); double startPosY = in.first(1) - radiusX; double endPosY = in.first(1) + radiusX; int startIndexY = (startPosY - min(1)) / res; int endIndexY = (endPosY - min(1)) / res + 1; for (int indexY = startIndexY; indexY < endIndexY; indexY++) { double posY = indexY * res + min(1); double lengthXYsq = square(radiusX) - square(posY - in.first(1)); if (lengthXYsq < 0.0) continue; double lengthXY = sqrt(lengthXYsq); double startPosZ = in.first(2) - lengthXY; double endPosZ = in.first(2) + lengthXY; int startIndexZ = (startPosZ - min(2)) / res; int endIndexZ = (endPosZ - min(2)) / res + 1; m_cube->fillStripe(indexX, indexY, startIndexZ, endIndexZ - 1, 1.0f); } } }); innerFuture.waitForFinished(); }
Here I have my displayMesh function
connect(&m_displayMeshWatcher, SIGNAL(finished()), SLOT(displayMesh()));
here's the displayMesh()
void Surfaces::displayMesh() { if (!m_cube) return; if (m_dialog != nullptr) m_smoothingPasses = m_dialog->smoothingPassesValue(); else m_smoothingPasses = 0; if (!m_mesh1) m_mesh1 = m_molecule->addMesh(); if (!m_meshGenerator1) { m_meshGenerator1 = new QtGui::MeshGenerator; connect(m_meshGenerator1, SIGNAL(finished()), SLOT(meshFinished())); } m_meshGenerator1->initialize(m_cube, m_mesh1, m_isoValue, m_smoothingPasses); bool isMO = false; // if it's from a file we should "play it safe" if (m_cube->cubeType() == Cube::Type::MO || m_cube->cubeType() == Cube::Type::FromFile) { isMO = true; } if (isMO) { if (!m_mesh2) m_mesh2 = m_molecule->addMesh(); if (!m_meshGenerator2) { m_meshGenerator2 = new QtGui::MeshGenerator; connect(m_meshGenerator2, SIGNAL(finished()), SLOT(meshFinished())); } m_meshGenerator2->initialize(m_cube, m_mesh2, -m_isoValue, m_smoothingPasses, true); } // Start the mesh generation - this needs an improved mutex with a read lock // to function as expected. Write locks are exclusive, read locks can have // many read locks but no write lock. m_meshGenerator1->start(); if (isMO) m_meshGenerator2->start(); // Track how many meshes are left to show. if (isMO) m_meshesLeft = 2; else m_meshesLeft = 1; }
Looking for a help. I am busy resolving this but unable to, so someone suggested me to ask this in the discuss fourm. Hope to get a reply from you guys
@Perminder-Singh said in Facing issues when doing progressive refinement:
switch (type) {
case VanDerWaals:
m_cube->setCubeType(Core::Cube::Type::VdW);
break;
case SolventAccessible:
m_cube->setCubeType(Core::Cube::Type::SolventAccessible);
case SolventExcluded:
probeRadius = 1.4;
m_cube->setCubeType(Core::Cube::Type::SolventExcluded);
break;
default:
break;
}Hi @Perminder-Singh ,
it's a little much code to dive into for any not involved person.
In case @JonB 's statement wasn't explicit enough:
You are missing abreak;
incase SolventAccessible
.
So every time it will continue to execute the code inSolventExcluded
as well and break there.Is it possible to break (no pun intended) your code down to a more simple example?
Then it might be easier to track down possible render issues.Maybe some Qt 3D / Rendering expert is able to spot the issue right away... which I am also not.
-
So sorry @JonB if my question wasn't clear to you. In my project, I'm successfully generating three types of meshes: solventExcluded, van der Waals, and solventAccessible. However, when creating a high-resolution mesh with a resolution value of 0.1, it takes a significant amount of time to render on the screen.
To address this, I’m considering an approach where a low-resolution mesh is initially displayed. While the low-resolution mesh is visible in the screen, the high-resolution mesh should be generated in the background. Once the high-resolution mesh is fully prepared at the default resolution of 0.1, it would replace the low-resolution mesh on the screen. For low resolution mesh, res = resolution(0.5) (at calculateEDTpass).
from my thinking calculateEDTpass is working correctly,
void Surfaces::calculateEDT(Type type, float defaultResolution) { if (type == Unknown && m_dialog != nullptr) type = m_dialog->surfaceType(); if (!m_cube) m_cube = m_molecule->addCube(); // Start with 0.5 resolution (1st pass) QFuture futureLowRes = QtConcurrent::run([=]() { calculateEDTpass(type, 0.5); // if you write 0.1 instead of 0.5 you will get a high resolution mesh }); m_displayMeshWatcher.setFuture(futureLowRes);
so in this case I am generating a low resolution mesh with calculateEDT function. How can I make it a two pass so that I can start with low resolution and end with a high resolution mesh? What I am doing wrong in the code I provided earlier? I think calculateEDTpass is correct, but still if it's something wrong can you please help me knowing how can I have a 2 pass algorithm for it?
@Perminder-Singh said in Facing issues when doing progressive refinement:
How can I make it a two pass so that I can start with low resolution and end with a high resolution mesh?
What I am doing wrong in the code I provided earlier?If you want two things to happen in serial then do not start them at the same time in two threads; they will try to progress in parallel. It's unclear to me, but it looks like calculateEDTpass() modifies structures that are shared, which may not end well.
When the coarse calculateEDTpass() finishes it should display its result and then start the fine calculateEDTpass() (unless there is a reason not to, e.g. user pressed Cancel). When the fine pass finishes it should display its result.
I cannot comment on the calculateEDTpass() implementation logic itself. I do note that you seem to be using even more threads to do short-running activities. Maybe sensible, maybe a shortcut to anguish.