Skip to content

Commit

Permalink
Merge branch 'master' into 'release'
Browse files Browse the repository at this point in the history
Added subweights, macmolplt export, non-cubic voxels, deselect all button and tooltips

See merge request luechow-group/inPsights!2
  • Loading branch information
heueristik committed Feb 17, 2021
2 parents 37eea00 + 03c21dc commit be525a7
Show file tree
Hide file tree
Showing 19 changed files with 453 additions and 117 deletions.
1 change: 1 addition & 0 deletions src/BaseLib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ set(HEADER_FILES
include/MolecularSelection.h
include/PermutationHandling.h
include/GraphAnalysis.h
include/Formatting.h
)


Expand Down
30 changes: 30 additions & 0 deletions src/BaseLib/include/Formatting.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (C) 2021 Leonard Reuter.
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef INPSIGHTS_FORMATTING_H
#define INPSIGHTS_FORMATTING_H

#include <spdlog/fmt/bundled/format.h>
#include <Eigen/Core>
#include <cstdint>

// this user-defined type formatter is needed for settings of VoxelCubeGeneration
// it is written based on a documentation example: https://fmt.dev/latest/api.html#udt
// it is needed, because settings defaults are printed by speedlog in Property.h

template<typename T>
struct fmt::formatter<Eigen::Matrix<T,3,1>> {
// Dummy parse routine
constexpr auto parse(format_parse_context& ctx) {
return ctx.end();
}

template <typename FormatContext>
auto format(const Eigen::Matrix<T,3,1>& matrix, FormatContext& ctx) {
return format_to(
ctx.out(),
"[{}, {}, {}]", matrix[0], matrix[1], matrix[2]);
}
};

#endif //INPSIGHTS_FORMATTING_H
3 changes: 2 additions & 1 deletion src/BaseLib/include/ToString.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ namespace ToString {

std::string doubleToString(double a,
unsigned decimalPlaces = 5,
unsigned leadingSpaces = 1);
unsigned leadingSpaces = 1,
bool spaceForPositiveNumber = true);

std::string vector3dToString(const Eigen::Vector3d &vector,
unsigned decimalPlaces = 5,
Expand Down
5 changes: 3 additions & 2 deletions src/BaseLib/source/ToString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ std::string ToString::vector3dToString(const Eigen::Vector3d &vector,
return vectorXdToString(vectorXd,decimalPlaces,leadingSpaces);
}

std::string ToString::doubleToString(double a, unsigned decimalPlaces, unsigned leadingSpaces) {
std::string ToString::doubleToString(double a, unsigned decimalPlaces, unsigned leadingSpaces,
bool spaceForPositiveNumber) {
std::stringstream sstream;
if (a >= 0){
if (a >= 0 && spaceForPositiveNumber){
sstream << " ";
}
for (unsigned i = 1; i <= leadingSpaces; i++){
Expand Down
4 changes: 4 additions & 0 deletions src/GUI/include/InPsightsWidget.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (C) 2018-2019 Michael Heuer.
// Copyright (C) 2021 Leonard Reuter.
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef INPSIGHTS_INPSIGHTSWIDGET_H
Expand Down Expand Up @@ -27,6 +28,8 @@ public slots:
void onSpinCorrelationsChecked(int stateId= 0);
void onPlotAllChecked(int stateId= 0);
void onSpinCorrelationsBoxChanged(double value);
void onSedsExport(bool);
void onDeselectAll(bool);

private:
std::string filename_;
Expand All @@ -35,6 +38,7 @@ public slots:
QCheckBox *atomsCheckBox, *bondsCheckBox, *axesCheckBox, *sampleAverageCheckBox, *spinCorrelationsCheckBox,
*sedsCheckBox,*maximaHullsCheckBox, *plotAllCheckBox, *coloredCheckBox;
QDoubleSpinBox *spinCorrelationBox, *sedPercentageBox;
QPushButton *sedsExportButton, *deselectAllButton;
QTreeWidget *maximaList;
QLabel *probabilitySum;
std::vector<ClusterData> clusterCollection_;
Expand Down
4 changes: 2 additions & 2 deletions src/GUI/include/MaximaProcessingWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ Q_OBJECT
QTreeWidget& atomsTreeWidget();
QTreeWidget& electronsTreeWidget();

Q_SIGNALS:
signals:
void atomsChecked(std::vector<int> selectedIds);
void electronsChecked(std::vector<int> selectedIds);
void atomsHighlighted(std::vector<int> selectedIds);
void electronsHighlighted(std::vector<int> selectedIds);

public Q_SLOTS:
public slots:
void onAtomItemChanged();
void onElectronItemChanged();
void onAtomSelectionChanged();
Expand Down
2 changes: 1 addition & 1 deletion src/GUI/include/MoleculeWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class MoleculeWidget : public QWidget{
void addMaximaHulls(int clusterId, const std::vector<ClusterData> &clusterData);
void removeMaximaHulls(int clusterId);

public Q_SLOTS:
public slots:
void activateCompatabilityMode();
void onAtomsChecked(std::vector<int>);
void onElectronsChecked(std::vector<int>);
Expand Down
94 changes: 76 additions & 18 deletions src/GUI/source/InPsightsWidget.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (C) 2018-2020 Michael Heuer.
// Copyright (C) 2018-2021 Michael Heuer.
// Copyright (C) 2021 Leonard Reuter.
// SPDX-License-Identifier: GPL-3.0-or-later

#include <InPsightsWidget.h>
Expand Down Expand Up @@ -28,14 +29,16 @@ InPsightsWidget::InPsightsWidget(QWidget *parent, const std::string& filename)
axesCheckBox(new QCheckBox("Axes", this)),
sampleAverageCheckBox(new QCheckBox("Sample Average", this)),
spinCorrelationsCheckBox(new QCheckBox("Spin Correlations", this)),
sedsExportButton(new QPushButton("export SEDs", this)),
sedsCheckBox(new QCheckBox("SEDs", this)),
maximaHullsCheckBox(new QCheckBox("Maxima Hulls", this)),
plotAllCheckBox(new QCheckBox("All of Cluster", this)),
coloredCheckBox(new QCheckBox("Multicolored", this)),
spinCorrelationBox(new QDoubleSpinBox(this)),
sedPercentageBox(new QDoubleSpinBox(this)),
maximaList(new QTreeWidget(this)),
probabilitySum(new QLabel(this))
probabilitySum(new QLabel(this)),
deselectAllButton(new QPushButton("deselect all", this))
{

loadData();
Expand All @@ -61,17 +64,28 @@ void InPsightsWidget::createWidget() {
hbox->addLayout(vboxOuter, 1);

// put into MaximaTreeWidget class
auto headerLabels = QList<QString>({"ID", "Prob.", "min(-ln|Ψ|²)", "max(-ln|Ψ|²)"});
auto headerLabels = QList<QString>({"ID", "P", "min(Φ)", "max(Φ)"});
maximaList->setColumnCount(headerLabels.size());
maximaList->setHeaderLabels(headerLabels);
maximaList->header()->setStretchLastSection(false);

maximaList->headerItem()->setToolTip(0,QString("IDs sorted by Φ value"));
maximaList->headerItem()->setToolTip(1,QString("Probability"));
maximaList->headerItem()->setToolTip(2,QString("Φ = -ħ/2m ln|Ψ|²"));
maximaList->headerItem()->setToolTip(3,QString("Φ = -ħ/2m ln|Ψ|²"));

maximaList->header()->setSectionResizeMode(0,QHeaderView::Stretch);
maximaList->header()->setSectionResizeMode(1,QHeaderView::ResizeToContents);
maximaList->header()->setSectionResizeMode(2,QHeaderView::ResizeToContents);
maximaList->header()->setSectionResizeMode(3,QHeaderView::ResizeToContents);

vboxOuter->addWidget(maximaList, 1);
vboxOuter->addWidget(probabilitySum);

auto lineGrid = new QGridLayout();
vboxOuter->addLayout(lineGrid,1);
lineGrid->addWidget(probabilitySum,0,0);
lineGrid->addWidget(deselectAllButton,0,1);

vboxOuter->addWidget(maximaProcessingWidget,1);
vboxOuter->addWidget(gbox);
gbox->setLayout(vboxInner);
Expand All @@ -85,6 +99,7 @@ void InPsightsWidget::createWidget() {
checkboxGrid->addWidget(atomsCheckBox,0,0);
checkboxGrid->addWidget(bondsCheckBox,1,0);
checkboxGrid->addWidget(axesCheckBox,2,0);
checkboxGrid->addWidget(sedsExportButton,3,0);

// second column
checkboxGrid->addWidget(sampleAverageCheckBox,0,1);
Expand Down Expand Up @@ -136,6 +151,9 @@ void InPsightsWidget::connectSignals() {
moleculeWidget, &MoleculeWidget::onAtomsHighlighted);
connect(maximaProcessingWidget, &MaximaProcessingWidget::electronsHighlighted,
moleculeWidget, &MoleculeWidget::onElectronsHighlighted);

connect(sedsExportButton, &QPushButton::clicked, this, &InPsightsWidget::onSedsExport);
connect(deselectAllButton, &QPushButton::clicked, this, &InPsightsWidget::onDeselectAll);
}

void InPsightsWidget::setupSpinBoxes() {
Expand Down Expand Up @@ -328,8 +346,8 @@ void InPsightsWidget::loadData() {
auto item = new IntegerSortedTreeWidgetItem(
maximaList, {QString::number(clusterId),
QString::number(1.0 * cluster.N_ / doc["NSamples"].as<unsigned>(), 'f', 4),
QString::number(cluster.valueStats_.cwiseMin()[0], 'f', 3),
QString::number(cluster.valueStats_.cwiseMax()[0], 'f', 3)});
QString::number(cluster.valueStats_.cwiseMin()[0]/2.0, 'f', 3),
QString::number(cluster.valueStats_.cwiseMax()[0]/2.0, 'f', 3)});

item->setCheckState(0, Qt::CheckState::Unchecked);

Expand All @@ -338,18 +356,25 @@ void InPsightsWidget::loadData() {

auto structures = doc["Clusters"][clusterId]["Structures"];

for (int structureId = 1; structureId < static_cast<int>(structures.size()); ++structureId) {
auto subItem = new IntegerSortedTreeWidgetItem(item, QStringList({QString::number(structureId)}));
subItem->setCheckState(0, Qt::CheckState::Unchecked);

id = {clusterId, structureId};
subItem->setData(0, Qt::ItemDataRole::UserRole, id);
item->addChild(subItem);
}

maximaList->addTopLevelItem(item);
for (int i = 0; i < maximaList->columnCount(); ++i) {
maximaList->resizeColumnToContents(i);
if (structures.size() > 1) {
for (int structureId = 0; structureId < static_cast<int>(structures.size()); ++structureId) {
auto subItem = new IntegerSortedTreeWidgetItem(item, QStringList({
QString::number(structureId),
QString::number(1.0 *
cluster.subN_[structureId] /
cluster.N_,
'f', 4)}));
subItem->setCheckState(0, Qt::CheckState::Unchecked);

id = {clusterId, structureId};
subItem->setData(0, Qt::ItemDataRole::UserRole, id);
item->addChild(subItem);
}

maximaList->addTopLevelItem(item);
for (int i = 0; i < maximaList->columnCount(); ++i) {
maximaList->resizeColumnToContents(i);
}
}
}
}
Expand All @@ -364,6 +389,14 @@ double InPsightsWidget::sumProbabilities(){
if(root->child(i)->checkState(0) == Qt::Checked) {
summedProbability += root->child(i)->text(1).toDouble();
}
else{
for (int j = 0; j<root->child(i)->childCount(); ++j){
if(root->child(i)->child(j)->checkState(0) == Qt::Checked){
summedProbability += root->child(i)->child(j)->text(1).toDouble()*
root->child(i)->text(1).toDouble();
}
}
}
}
return summedProbability;
}
Expand Down Expand Up @@ -392,3 +425,28 @@ std::string InPsightsWidget::filenameWithoutExtension(){
bool InPsightsWidget::plotAllActiveQ() {
return plotAllCheckBox->checkState() == Qt::Checked;
}

void InPsightsWidget::onSedsExport(bool) {
for (auto &sed : moleculeWidget->activeSedsMap_){
auto clusterId = sed.first;
int i = 0;
for (auto &voxelCube : clusterCollection_[clusterId].voxelCubes_){
std::string fileName = "sed-"+std::to_string(clusterId)+"-"+std::to_string(i)+".txt";
std::string comment = filename_ + " cluster " + std::to_string(clusterId) + " SED " + std::to_string(i);
voxelCube.exportMacmolplt(fileName, comment);
i += 1;
}
}
spdlog::info("Exported SEDs");
}

void InPsightsWidget::onDeselectAll(bool) {
auto* root = maximaList->invisibleRootItem();
// iterate over topLevelItems
for (int i = 0; i < root->childCount(); ++i) {
root->child(i)->setCheckState(0, Qt::Unchecked);
for (int j = 0; j<root->child(i)->childCount(); ++j){
root->child(i)->child(j)->setCheckState(0, Qt::Unchecked);
}
}
}
12 changes: 6 additions & 6 deletions src/GUI/tests/ASurfaceTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,12 @@ TEST(ASurfaceTest, SphereFromDensity) {
VoxelCube::offset_,
VoxelCube::offset_);
int32_t p = 0;
for (int32_t z = 0; z < cube.getDimension(); ++z) {
float const nZ = float(z) * cube.inverseDimension_;
for (int32_t y = 0; y < cube.getDimension(); ++y) {
float const nY = float(y) * cube.inverseDimension_;
for (int32_t x = 0; x < cube.getDimension(); ++x, ++p) {
float const nX = float(x) * cube.inverseDimension_;
for (int32_t z = 0; z < cube.getDimensions()[2]; ++z) {
float const nZ = float(z) * cube.inverseDimensions_[2];
for (int32_t y = 0; y < cube.getDimensions()[1]; ++y) {
float const nY = float(y) * cube.inverseDimensions_[1];
for (int32_t x = 0; x < cube.getDimensions()[0]; ++x, ++p) {
float const nX = float(x) * cube.inverseDimensions_[0];

float rho = a.eval(nX, nY, nZ);
if (rho > 1.0f) rho = 1.0f;
Expand Down
8 changes: 6 additions & 2 deletions src/Methods/MaximaProcessing/include/ClusterData.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (C) 2018-2019 Michael Heuer.
// Copyright (C) 2021 Leonard Reuter.
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef INPSIGHTS_CLUSTERDATA_H
Expand Down Expand Up @@ -31,7 +32,8 @@ class ClusterData {
const TriangularMatrixStatistics & ReeStats,
const MatrixStatistics RenStats,
const std::vector<VoxelCube>& seds,
const Eigen::MatrixXd& sedOverlaps
const Eigen::MatrixXd& sedOverlaps,
const std::vector<unsigned>& subCounts
);

// TODO Refactor (hacky solution for local clustering)
Expand All @@ -53,12 +55,14 @@ class ClusterData {
const std::vector<VoxelCube>& seds,
const Eigen::MatrixXd& sedOverlaps,
const SelectionEnergyCalculator::SelectionInteractionEnergies & selectionInteractionEnergies,
const std::vector<MolecularSelection>& selections
const std::vector<MolecularSelection>& selections,
const std::vector<unsigned>& subCounts
);

ElectronsVector representativeStructure() const;

unsigned N_;
std::vector<unsigned> subN_;
std::vector<ElectronsVector> exemplaricStructures_;
ElectronsVector sampleAverage_;
Motifs motifs_;
Expand Down
16 changes: 11 additions & 5 deletions src/Methods/MaximaProcessing/include/VoxelCubeGeneration.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (C) 2019 Michael Heuer.
// Copyright (C) 2021 Leonard Reuter.
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef INPSIGHTS_VOXELCUBEGENERATION_H
Expand All @@ -11,17 +12,19 @@ class Cluster;

#include <ISettings.h>
#include <Property.h>
#include <Formatting.h>

namespace Settings {
class VoxelCubeGeneration : public ISettings {
inline static const std::string className = {VARNAME(VoxelCubeGeneration)};
public:
Property<bool> generateVoxelCubesQ = {false, VARNAME(generateVoxelCubesQ)};
Property<bool> centerCubesAtElectronsQ = {true, VARNAME(centerCubesAtElectronsQ)};
Property<uint16_t> dimension = {16, VARNAME(dimension)};
Property<Eigen::Matrix<VoxelCube::IndexType , 3, 1>> dimensions = {{16, 16, 16}, VARNAME(dimensions)};
Property<bool> smoothingQ = {false, VARNAME(smoothingQ)};
Property<uint16_t> smoothingNeighbors = {0, VARNAME(smoothingNeighbors)};
Property<VoxelCube::VertexComponentsType > length = {4, VARNAME(length)};
Property<Eigen::Matrix<VoxelCube::VertexComponentsType , 3, 1>> lengths = {{4, 4, 4}, VARNAME(lengths)};
Property<Eigen::Matrix<VoxelCube::VertexComponentsType , 3, 1>> center = {{0, 0, 0}, VARNAME(center)};


VoxelCubeGeneration();
Expand All @@ -37,9 +40,12 @@ namespace VoxelCubeGeneration{

std::vector<VoxelCube> fromCluster(const Cluster &maxima, const std::vector<Sample> &samples);

std::vector<VoxelCube> getVoxels(const Cluster &maxima, const std::vector<Sample> &samples, uint16_t dimension,
VoxelCube::VertexComponentsType length, bool centerCubesAtElectronsQ, bool smoothingQ,
uint16_t smoothingNeighbors);
std::vector<VoxelCube> getVoxels(const Cluster &maxima, const std::vector<Sample> &samples,
Eigen::Matrix<VoxelCube::IndexType, 3, 1> dimensions,
Eigen::Matrix<VoxelCube::VertexComponentsType , 3, 1> lengths,
bool centerCubesAtElectronsQ, bool smoothingQ,
VoxelCube::IndexType smoothingNeighbors,
Eigen::Matrix<VoxelCube::VertexComponentsType , 3, 1> center);
};

#endif //INPSIGHTS_VOXELCUBEGENERATION_H
Loading

0 comments on commit be525a7

Please sign in to comment.