diff --git a/resources/surface_description.json b/resources/surface_description.json
index 5530345..3e4cc21 100644
--- a/resources/surface_description.json
+++ b/resources/surface_description.json
@@ -113,9 +113,9 @@
"description": "
Difference between the alpha and beta electron densities
"
},
"fragment_patch": {
- "cmap": "Qualitative14Dark",
+ "cmap": "Turbo",
"displayName": "Fragment Patch",
- "occName": "fragment",
+ "occName": "fragment_patch",
"description": "The index of the associated neighbouring fragment/molecule
"
},
"de_idx": {
diff --git a/src/core/chemicalstructure.cpp b/src/core/chemicalstructure.cpp
index ccee3c4..9efcb28 100644
--- a/src/core/chemicalstructure.cpp
+++ b/src/core/chemicalstructure.cpp
@@ -10,9 +10,15 @@
#include
namespace impl {
-template
+
+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);
}
@@ -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));
}
@@ -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:
@@ -1163,9 +1169,10 @@ QString ChemicalStructure::getFragmentLabelForAtoms(
return "None";
// Get unique fragment indices for the atoms
- ankerl::unordered_dense::set uniqueFragments;
+ ankerl::unordered_dense::set
+ uniqueFragments;
for (const auto &idx : idxs) {
- uniqueFragments.insert(fragmentIndexForAtom(idx));
+ uniqueFragments.insert(fragmentIndexForGeneralAtom(idx));
}
// Get chemical formula for these atoms
diff --git a/src/core/chemicalstructure.h b/src/core/chemicalstructure.h
index 3bc13ca..5fbde9e 100644
--- a/src/core/chemicalstructure.h
+++ b/src/core/chemicalstructure.h
@@ -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;
diff --git a/src/crystal/crystalstructure.cpp b/src/crystal/crystalstructure.cpp
index d3ebfdb..42a5593 100644
--- a/src/crystal/crystalstructure.cpp
+++ b/src/crystal/crystalstructure.cpp
@@ -599,6 +599,7 @@ void CrystalStructure::completeFragmentContaining(GenericAtomIndex index) {
}
updateBondGraph();
}
+
void CrystalStructure::completeFragmentContaining(int atomIndex) {
if (atomIndex < 0 || atomIndex >= numberOfAtoms())
return;
@@ -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);
@@ -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);
}
diff --git a/src/crystal/crystalstructure.h b/src/crystal/crystalstructure.h
index 4ef57ca..21b21d1 100644
--- a/src/crystal/crystalstructure.h
+++ b/src/crystal/crystalstructure.h
@@ -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 &) override;
diff --git a/src/crystalx.cpp b/src/crystalx.cpp
index b0b4479..76e5552 100644
--- a/src/crystalx.cpp
+++ b/src/crystalx.cpp
@@ -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);
diff --git a/src/graphics/scene.cpp b/src/graphics/scene.cpp
index 6178025..06a5abe 100644
--- a/src/graphics/scene.cpp
+++ b/src/graphics/scene.cpp
@@ -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);
@@ -1424,7 +1425,7 @@ void Scene::generateAllExternalFragments() {
qDebug() << "Generate external fragment";
if (!mesh)
return;
- occ::IVec de_idxs = mesh->vertexProperty("de_idx").cast();
+ occ::IVec de_idxs = mesh->vertexProperty("External atom index").cast();
qDebug() << "num de_idxs" << de_idxs.size();
ankerl::unordered_dense::set unique(de_idxs.data(),
de_idxs.data() + de_idxs.size());
@@ -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 {
diff --git a/src/io/crystalclear.cpp b/src/io/crystalclear.cpp
index 0e08dd1..abbcba4 100644
--- a/src/io/crystalclear.cpp
+++ b/src/io/crystalclear.cpp
@@ -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 interactions;
QList> atomIndices;
+ QString modelName = "cg";
+ if(json.contains("model")) {
+ modelName = QString::fromStdString(json["model"]);
+ }
// Parse neighbor energies
auto pairsArray = json["pairs"];
interactions.resize(pairsArray.size());
@@ -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));
diff --git a/src/volume/isosurface_calculator.cpp b/src/volume/isosurface_calculator.cpp
index 056d556..f174683 100644
--- a/src/volume/isosurface_calculator.cpp
+++ b/src/volume/isosurface_calculator.cpp
@@ -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 fragmentIndices;
+
+ Mesh::ScalarPropertyValues fragmentPatch(mesh->numberOfVertices());
+ fragmentPatch.setConstant(-1.0);
+ occ::IVec de_idxs = mesh->vertexProperty("External atom index").cast();
+ 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 meshes = io::loadMeshes(m_fileNames);
@@ -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);