Skip to content

Commit

Permalink
Add fragment patch, fix importing of occ elat results
Browse files Browse the repository at this point in the history
  • Loading branch information
peterspackman committed Nov 15, 2024
1 parent 8248208 commit 03a7b5a
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 14 deletions.
4 changes: 2 additions & 2 deletions resources/surface_description.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@
"description": "<p>Difference between the alpha and beta electron densities</p>"
},
"fragment_patch": {
"cmap": "Qualitative14Dark",
"cmap": "Turbo",
"displayName": "Fragment Patch",
"occName": "fragment",
"occName": "fragment_patch",
"description": "<p>The index of the associated neighbouring fragment/molecule</p>"
},
"de_idx": {
Expand Down
19 changes: 13 additions & 6 deletions src/core/chemicalstructure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,15 @@
#include <occ/core/kdtree.h>

namespace impl {
template <typename Index>

MaybeFragment getFragmentForAtom(const ChemicalStructure &structure,
GenericAtomIndex atomIndex) {
auto fragIndex = structure.fragmentIndexForGeneralAtom(atomIndex);
return structure.getFragment(fragIndex);
}

MaybeFragment getFragmentForAtom(const ChemicalStructure &structure,
Index atomIndex) {
int atomIndex) {
auto fragIndex = structure.fragmentIndexForAtom(atomIndex);
return structure.getFragment(fragIndex);
}
Expand Down Expand Up @@ -572,7 +578,7 @@ FragmentIndex ChemicalStructure::fragmentIndexForAtom(int atomIndex) const {
}

FragmentIndex
ChemicalStructure::fragmentIndexForAtom(GenericAtomIndex idx) const {
ChemicalStructure::fragmentIndexForGeneralAtom(GenericAtomIndex idx) const {
return fragmentIndexForAtom(genericIndexToIndex(idx));
}

Expand Down Expand Up @@ -627,7 +633,7 @@ QColor ChemicalStructure::atomColor(GenericAtomIndex atomIndex) const {
return Qt::black;
}
case AtomColoring::Fragment: {
auto fragIndex = fragmentIndexForAtom(atomIndex);
auto fragIndex = fragmentIndexForGeneralAtom(atomIndex);
return getFragmentColor(fragIndex);
}
case AtomColoring::Index:
Expand Down Expand Up @@ -1163,9 +1169,10 @@ QString ChemicalStructure::getFragmentLabelForAtoms(
return "None";

// Get unique fragment indices for the atoms
ankerl::unordered_dense::set<FragmentIndex, FragmentIndexHash> uniqueFragments;
ankerl::unordered_dense::set<FragmentIndex, FragmentIndexHash>
uniqueFragments;
for (const auto &idx : idxs) {
uniqueFragments.insert(fragmentIndexForAtom(idx));
uniqueFragments.insert(fragmentIndexForGeneralAtom(idx));
}

// Get chemical formula for these atoms
Expand Down
2 changes: 1 addition & 1 deletion src/core/chemicalstructure.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ class ChemicalStructure : public QObject {

inline size_t numberOfFragments() const { return m_fragments.size(); }
FragmentIndex fragmentIndexForAtom(int) const;
FragmentIndex fragmentIndexForAtom(GenericAtomIndex) const;
virtual FragmentIndex fragmentIndexForGeneralAtom(GenericAtomIndex) const;

MaybeFragment getFragmentForAtom(int) const;
MaybeFragment getFragmentForAtom(GenericAtomIndex) const;
Expand Down
16 changes: 15 additions & 1 deletion src/crystal/crystalstructure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,7 @@ void CrystalStructure::completeFragmentContaining(GenericAtomIndex index) {
}
updateBondGraph();
}

void CrystalStructure::completeFragmentContaining(int atomIndex) {
if (atomIndex < 0 || atomIndex >= numberOfAtoms())
return;
Expand Down Expand Up @@ -1098,6 +1099,17 @@ const FragmentMap &CrystalStructure::symmetryUniqueFragments() const {
return m_symmetryUniqueFragments;
}

FragmentIndex
CrystalStructure::fragmentIndexForGeneralAtom(GenericAtomIndex index) const {
if(m_unitCellAtomFragments.size() == 0) return ChemicalStructure::fragmentIndexForGeneralAtom(index);
qDebug() << m_unitCellAtomFragments.size() << index.unique;
FragmentIndex fragmentIndex = m_unitCellAtomFragments.at(index.unique);
fragmentIndex.h += index.x;
fragmentIndex.k += index.y;
fragmentIndex.l += index.z;
return fragmentIndex;
}

Fragment::State CrystalStructure::getSymmetryUniqueFragmentState(
FragmentIndex fragmentIndex) const {
const auto kv = m_symmetryUniqueFragments.find(fragmentIndex);
Expand Down Expand Up @@ -1331,7 +1343,9 @@ void CrystalStructure::setPairInteractionsFromDimerAtoms(
params.fragmentDimer = ud;
params.nearestAtomDistance = d.nearestAtomDistance;
params.centroidDistance = d.centroidDistance;
params.hasInversionSymmetry = false;
// TODO better handling of inversion symmetry
QString modelName = pair->interactionModel();
params.hasInversionSymmetry = !(modelName == "cg" || modelName.startsWith("crystalclear"));
pair->setParameters(params);
p->add(pair);
}
Expand Down
1 change: 1 addition & 0 deletions src/crystal/crystalstructure.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class CrystalStructure : public ChemicalStructure {
inline const auto &spaceGroup() const { return m_crystal.space_group(); }
occ::Mat3N convertCoordinates(const occ::Mat3N &pos, ChemicalStructure::CoordinateConversion) const override;

FragmentIndex fragmentIndexForGeneralAtom(GenericAtomIndex) const override;
void deleteFragmentContainingAtomIndex(int atomIndex) override;
void deleteIncompleteFragments() override;
void deleteAtoms(const std::vector<GenericAtomIndex> &) override;
Expand Down
4 changes: 4 additions & 0 deletions src/crystalx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,10 @@ void Crystalx::loadExternalFileData(QString filename) {
showStatusMessage(
QString("Loading crystal clear output from %1").arg(filename));
project->loadCrystalClearJson(filename);
}
if (filename.endsWith("elat_results.json")) {
showStatusMessage(QString("Loading occ elat output from %1").arg(filename));
project->loadCrystalClearJson(filename);
} else if (filename.endsWith("surface.json")) {
showStatusMessage(QString("Loading crystal surface from %1").arg(filename));
project->loadCrystalClearSurfaceJson(filename);
Expand Down
7 changes: 4 additions & 3 deletions src/graphics/scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,8 @@ void Scene::setSelectStatusForAtomDoubleClick(int atom) {
auto atomIndex = m_structure->indexToGenericIndex(atom);
if (m_structure->testAtomFlag(atomIndex, AtomFlag::Contact))
return;
const auto fragmentIndex = m_structure->fragmentIndexForAtom(atomIndex);
const auto fragmentIndex =
m_structure->fragmentIndexForGeneralAtom(atomIndex);
const auto &atomIndices = m_structure->atomIndicesForFragment(fragmentIndex);
auto idx = m_structure->indexToGenericIndex(atom);
m_structure->setAtomFlag(idx, AtomFlag::Selected, true);
Expand Down Expand Up @@ -1424,7 +1425,7 @@ void Scene::generateAllExternalFragments() {
qDebug() << "Generate external fragment";
if (!mesh)
return;
occ::IVec de_idxs = mesh->vertexProperty("de_idx").cast<int>();
occ::IVec de_idxs = mesh->vertexProperty("External atom index").cast<int>();
qDebug() << "num de_idxs" << de_idxs.size();
ankerl::unordered_dense::set<int> unique(de_idxs.data(),
de_idxs.data() + de_idxs.size());
Expand Down Expand Up @@ -1540,7 +1541,7 @@ void Scene::colorSelectedAtoms(const QColor &color, bool fragments) {
auto idxs = m_structure->atomsWithFlags(AtomFlag::Selected);
if (fragments) {
for (const auto &idx : idxs) {
const auto frag = m_structure->fragmentIndexForAtom(idx);
const auto frag = m_structure->fragmentIndexForGeneralAtom(idx);
m_structure->setFragmentColor(frag, color);
}
} else {
Expand Down
7 changes: 6 additions & 1 deletion src/io/crystalclear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,15 @@ CrystalStructure *loadCrystalClearJson(const QString &filename) {
return nullptr;

occ::crystal::Crystal crystal = loadOccCrystal(json["crystal"]);
// TODO check if it's cg and then set symmetry of interactions

QList<PairInteractions::PairInteractionList> interactions;
QList<QList<DimerAtoms>> atomIndices;

QString modelName = "cg";
if(json.contains("model")) {
modelName = QString::fromStdString(json["model"]);
}
// Parse neighbor energies
auto pairsArray = json["pairs"];
interactions.resize(pairsArray.size());
Expand All @@ -69,7 +74,7 @@ CrystalStructure *loadCrystalClearJson(const QString &filename) {
auto &neighbors = interactions[i];
auto &offsets = atomIndices[i];
for (int j = 0; j < siteEnergies.size(); ++j) {
auto *pair = new PairInteraction("cg");
auto *pair = new PairInteraction(modelName);
auto dimerObj = siteEnergies[j];
auto energiesObj = dimerObj["energies"];
pair->setLabel(QString::number(j + 1));
Expand Down
32 changes: 32 additions & 0 deletions src/volume/isosurface_calculator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,37 @@ QString IsosurfaceCalculator::surfaceName() {
.arg(m_parameters.isovalue);
}

void setFragmentPatchForMesh(Mesh * mesh, ChemicalStructure *structure) {
if(!mesh) return;
if(!structure) return;
ankerl::unordered_dense::map<FragmentIndex, int, FragmentIndexHash> fragmentIndices;

Mesh::ScalarPropertyValues fragmentPatch(mesh->numberOfVertices());
fragmentPatch.setConstant(-1.0);
occ::IVec de_idxs = mesh->vertexProperty("External atom index").cast<int>();
auto atomIndices = mesh->atomsOutside();
for (int i = 0; i < de_idxs.size(); i++) {
int idx = de_idxs(i);
if (idx >= atomIndices.size()) {
continue;
}
const auto &genericIndex = atomIndices[idx];
FragmentIndex fidx = structure->fragmentIndexForGeneralAtom(genericIndex);
if(fidx.u == -1) {
continue;
}
const auto kv = fragmentIndices.find(fidx);
if(kv != fragmentIndices.end()) {
fragmentPatch(i) = kv->second;
}
else {
fragmentPatch(i) = fragmentIndices.size();
fragmentIndices.insert({fidx, fragmentIndices.size()});
}
}
mesh->setVertexProperty("Fragment Patch", fragmentPatch);
}

void IsosurfaceCalculator::surfaceComplete() {
qDebug() << "Task" << m_name << "finished in IsosurfaceCalculator";
QList<Mesh *> meshes = io::loadMeshes(m_fileNames);
Expand All @@ -155,6 +186,7 @@ void IsosurfaceCalculator::surfaceComplete() {
}
mesh->setAtomsInside(m_atomsInside);
mesh->setAtomsOutside(m_atomsOutside);
setFragmentPatchForMesh(mesh, params.structure);
mesh->setParent(m_structure);
// create the child instance that will be shown
MeshInstance *instance = new MeshInstance(mesh);
Expand Down

0 comments on commit 03a7b5a

Please sign in to comment.