Commit f28beeda authored by Tobias WEBER's avatar Tobias WEBER

continued with space groups

parent f633a2d0
...@@ -14,7 +14,8 @@ set(CMAKE_AUTOMOC ON) ...@@ -14,7 +14,8 @@ set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
add_definitions(-std=c++17 -fconcepts) add_definitions(-std=c++17 -fconcepts)
include_directories("${PROJECT_SOURCE_DIR}" "../..") include_directories("${PROJECT_SOURCE_DIR}" "../.."
"../../ext/gemmi/include" "../../ext/gemmi/third_party")
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
......
...@@ -7,9 +7,9 @@ ...@@ -7,9 +7,9 @@
*/ */
#include "browser.h" #include "browser.h"
#include <sstream> #include "../structfact/loadcif.h"
#include <QtWidgets/QMenuBar> #include <QtWidgets/QMenuBar>
#include <sstream>
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
...@@ -50,84 +50,87 @@ SgBrowserDlg::SgBrowserDlg(QWidget* pParent, QSettings *pSett) ...@@ -50,84 +50,87 @@ SgBrowserDlg::SgBrowserDlg(QWidget* pParent, QSettings *pSett)
// load data // load data
SetupSpaceGroups(); SetupMagSpaceGroups();
SetupNuclSpaceGroups();
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// connections // connections
connect(m_pTree, &QTreeWidget::currentItemChanged, this, &SgBrowserDlg::SpaceGroupSelected); connect(treeMagSG, &QTreeWidget::currentItemChanged, this, &SgBrowserDlg::MagSpaceGroupSelected);
connect(treeNuclSG, &QTreeWidget::currentItemChanged, this, &SgBrowserDlg::NuclSpaceGroupSelected);
connect(pShowBNS, &QAction::toggled, this, &SgBrowserDlg::SwitchToBNS); connect(pShowBNS, &QAction::toggled, this, &SgBrowserDlg::SwitchToBNS);
// synchronise symops when switching the sg tab
connect(tabSGs, &QTabWidget::currentChanged, this, [this](int idx) -> void
{
switch(idx)
{
case 0: MagSpaceGroupSelected(treeMagSG->currentItem()); break;
case 1: NuclSpaceGroupSelected(treeNuclSG->currentItem()); break;
}
});
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** /**
* load space group list * load magnetic space group list
*/ */
void SgBrowserDlg::SetupSpaceGroups() void SgBrowserDlg::SetupMagSpaceGroups()
{ {
std::cerr << "Loading space groups ... "; std::cerr << "Loading magnetic space groups ... ";
m_sgs.Load("magsg.info"); m_magsgs.Load("magsg.info");
std::cerr << "Done." << std::endl; std::cerr << "Done." << std::endl;
const auto *pSgs = m_sgs.GetSpacegroups(); const auto *pSgs = m_magsgs.GetSpacegroups();
if(pSgs) if(!pSgs) return;
{
for(const auto& sg : *pSgs)
SetupSpaceGroup(sg);
}
}
for(const auto& sg : *pSgs)
/**
* add space group to tree widget
*/
void SgBrowserDlg::SetupSpaceGroup(const Spacegroup<t_mat_sg, t_vec_sg>& sg)
{
int iNrStruct = sg.GetStructNumber();
int iNrMag = sg.GetMagNumber();
// find top-level item with given structural sg number
auto get_topsg = [](QTreeWidget *pTree, int iStructNr) -> QTreeWidgetItem*
{ {
for(int item=0; item<pTree->topLevelItemCount(); ++item) int iNrStruct = sg.GetStructNumber();
int iNrMag = sg.GetMagNumber();
// find top-level item with given structural sg number
auto get_topsg = [](QTreeWidget *pTree, int iStructNr) -> QTreeWidgetItem*
{ {
QTreeWidgetItem *pItem = pTree->topLevelItem(item); for(int item=0; item<pTree->topLevelItemCount(); ++item)
if(!pItem) continue; {
QTreeWidgetItem *pItem = pTree->topLevelItem(item);
if(!pItem) continue;
if(pItem->data(0, Qt::UserRole) == iStructNr) if(pItem->data(0, Qt::UserRole) == iStructNr)
return pItem; return pItem;
} }
return nullptr; return nullptr;
}; };
// find existing top-level structural space group or insert new one // find existing top-level structural space group or insert new one
auto *pTopItem = get_topsg(m_pTree, iNrStruct); auto *pTopItem = get_topsg(treeMagSG, iNrStruct);
if(!pTopItem) if(!pTopItem)
{ {
QString structname = ("(" + std::to_string(iNrStruct) + ") " + sg.GetName()).c_str(); QString structname = ("(" + std::to_string(iNrStruct) + ") " + sg.GetName()).c_str();
pTopItem = new QTreeWidgetItem(); pTopItem = new QTreeWidgetItem();
pTopItem->setText(0, structname); pTopItem->setText(0, structname);
pTopItem->setData(0, Qt::UserRole, iNrStruct); pTopItem->setData(0, Qt::UserRole, iNrStruct);
pTopItem->setData(0, Qt::UserRole+1, iNrMag); pTopItem->setData(0, Qt::UserRole+1, iNrMag);
m_pTree->addTopLevelItem(pTopItem); treeMagSG->addTopLevelItem(pTopItem);
} }
// create magnetic group and add it as sub-item for the corresponding structural group // create magnetic group and add it as sub-item for the corresponding structural group
QString magname = ("(" + sg.GetNumber() + ") " + sg.GetName()).c_str(); QString magname = ("(" + sg.GetNumber() + ") " + sg.GetName()).c_str();
auto *pSubItem = new QTreeWidgetItem(); auto *pSubItem = new QTreeWidgetItem();
pSubItem->setText(0, magname); pSubItem->setText(0, magname);
pSubItem->setData(0, Qt::UserRole, iNrStruct); pSubItem->setData(0, Qt::UserRole, iNrStruct);
pSubItem->setData(0, Qt::UserRole+1, iNrMag); pSubItem->setData(0, Qt::UserRole+1, iNrMag);
pTopItem->addChild(pSubItem); pTopItem->addChild(pSubItem);
}
} }
// ----------------------------------------------------------------------------
/** /**
...@@ -136,25 +139,26 @@ void SgBrowserDlg::SetupSpaceGroup(const Spacegroup<t_mat_sg, t_vec_sg>& sg) ...@@ -136,25 +139,26 @@ void SgBrowserDlg::SetupSpaceGroup(const Spacegroup<t_mat_sg, t_vec_sg>& sg)
void SgBrowserDlg::SwitchToBNS(bool bBNS) void SgBrowserDlg::SwitchToBNS(bool bBNS)
{ {
m_showBNS = bBNS; m_showBNS = bBNS;
SpaceGroupSelected(m_pTree->currentItem()); MagSpaceGroupSelected(treeMagSG->currentItem());
} }
/** /**
* space group selected * magnetic space group selected
*/ */
void SgBrowserDlg::SpaceGroupSelected(QTreeWidgetItem *pItem) void SgBrowserDlg::MagSpaceGroupSelected(QTreeWidgetItem *pItem)
{ {
if(!pItem) return; if(!pItem) return;
// clean up // clean up
m_pSymOps->clear(); listSymOps->clear();
m_pWyc->clear(); listWyc->clear();
int iNrStruct = pItem->data(0, Qt::UserRole).toInt(); int iNrStruct = pItem->data(0, Qt::UserRole).toInt();
int iNrMag = pItem->data(0, Qt::UserRole+1).toInt(); int iNrMag = pItem->data(0, Qt::UserRole+1).toInt();
const auto* pSg = m_sgs.GetSpacegroupByNumber(iNrStruct, iNrMag); const auto* pSg = m_magsgs.GetSpacegroupByNumber(iNrStruct, iNrMag);
if(!pSg) return; if(!pSg) return;
...@@ -233,7 +237,7 @@ void SgBrowserDlg::SpaceGroupSelected(QTreeWidgetItem *pItem) ...@@ -233,7 +237,7 @@ void SgBrowserDlg::SpaceGroupSelected(QTreeWidgetItem *pItem)
auto *pOpItem = new QListWidgetItem(); auto *pOpItem = new QListWidgetItem();
pOpItem->setText(print_sym(rot, trans, inv).c_str()); pOpItem->setText(print_sym(rot, trans, inv).c_str());
m_pSymOps->addItem(pOpItem); listSymOps->addItem(pOpItem);
} }
} }
...@@ -259,13 +263,136 @@ void SgBrowserDlg::SpaceGroupSelected(QTreeWidgetItem *pItem) ...@@ -259,13 +263,136 @@ void SgBrowserDlg::SpaceGroupSelected(QTreeWidgetItem *pItem)
pWycItem->addChild(pSubItem); pWycItem->addChild(pSubItem);
} }
m_pWyc->addTopLevelItem(pWycItem); listWyc->addTopLevelItem(pWycItem);
pWycItem->setExpanded(true); pWycItem->setExpanded(true);
} }
} }
} }
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
/**
* load nuclear space group list
*/
void SgBrowserDlg::SetupNuclSpaceGroups()
{
m_nuclsgs = get_sgs<t_mat44_sg>(false, false);
for(int iSG=0; iSG<static_cast<int>(m_nuclsgs.size()); ++iSG)
{
int iNrStruct = std::get<0>(m_nuclsgs[iSG]);
const std::string& strName = std::get<1>(m_nuclsgs[iSG]);
// find top-level item with given structural sg number
auto get_topsg = [](QTreeWidget *pTree, int iStructNr) -> QTreeWidgetItem*
{
for(int item=0; item<pTree->topLevelItemCount(); ++item)
{
QTreeWidgetItem *pItem = pTree->topLevelItem(item);
if(!pItem) continue;
if(pItem->data(0, Qt::UserRole) == iStructNr)
return pItem;
}
return nullptr;
};
// find existing top-level structural space group or insert new one
auto *pTopItem = get_topsg(treeNuclSG, iNrStruct);
if(!pTopItem)
{
QString structname = ("(" + std::to_string(iNrStruct) + ") " + strName).c_str();
pTopItem = new QTreeWidgetItem();
pTopItem->setText(0, structname);
pTopItem->setData(0, Qt::UserRole, iNrStruct);
pTopItem->setData(0, Qt::UserRole+1, iSG);
treeNuclSG->addTopLevelItem(pTopItem);
}
// create nuclear group config and add it as sub-item for the corresponding structural group
QString magname = ("(" + std::to_string(iNrStruct) +
"-" + std::to_string(pTopItem->childCount()+1) + ") " + strName).c_str();
auto *pSubItem = new QTreeWidgetItem();
pSubItem->setText(0, magname);
pSubItem->setData(0, Qt::UserRole, iNrStruct);
pSubItem->setData(0, Qt::UserRole+1, iSG);
pTopItem->addChild(pSubItem);
}
}
/**
* nuclear space group selected
*/
void SgBrowserDlg::NuclSpaceGroupSelected(QTreeWidgetItem *pItem)
{
if(!pItem) return;
// clean up
listSymOps->clear();
listWyc->clear();
int iNrStruct = pItem->data(0, Qt::UserRole).toInt();
int iNrSG = pItem->data(0, Qt::UserRole+1).toInt();
if(iNrSG < 0 || iNrSG >= m_nuclsgs.size())
return;
const auto& sg = m_nuclsgs[iNrSG];
const auto& trafos = std::get<2>(sg);
// print a symmetry operator
auto print_sym = [](const t_mat44_sg& mat) -> std::string
{
std::ostringstream ostr;
for(std::size_t i=0; i<3; ++i)
{
// rotation matrix
ostr << "( ";
for(std::size_t j=0; j<3; ++j)
ostr << std::setw(ostr.precision()*1.5) << std::right << mat(i,j);
ostr << " )";
// translation vector
ostr << std::setw(ostr.precision()*2) << std::right << "( ";
ostr << std::setw(ostr.precision()*1.5) << std::right << mat(i, 3);
ostr << " )";
if(i < mat.size1()-2)
ostr << "\n";
}
return ostr.str();
};
// iterate over symmetries
for(std::size_t iOp=0; iOp<trafos.size(); ++iOp)
{
const auto& trafo = trafos[iOp];
auto *pOpItem = new QListWidgetItem();
pOpItem->setText(print_sym(trafo).c_str());
listSymOps->addItem(pOpItem);
}
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
void SgBrowserDlg::showEvent(QShowEvent *pEvt) void SgBrowserDlg::showEvent(QShowEvent *pEvt)
{ {
QDialog::showEvent(pEvt); QDialog::showEvent(pEvt);
...@@ -289,5 +416,4 @@ void SgBrowserDlg::closeEvent(QCloseEvent *pEvt) ...@@ -289,5 +416,4 @@ void SgBrowserDlg::closeEvent(QCloseEvent *pEvt)
QDialog::closeEvent(pEvt); QDialog::closeEvent(pEvt);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
...@@ -25,18 +25,22 @@ ...@@ -25,18 +25,22 @@
using t_real_sg = double; using t_real_sg = double;
using t_vec_sg = m::qvec_adapter<int, 3, t_real_sg, QGenericMatrix>; using t_vec_sg = m::qvec_adapter<int, 3, t_real_sg, QGenericMatrix>;
using t_mat_sg = m::qmat_adapter<int, 3, 3, t_real_sg, QGenericMatrix>; using t_mat_sg = m::qmat_adapter<int, 3, 3, t_real_sg, QGenericMatrix>;
using t_mat44_sg = m::qmat_adapter<int, 4, 4, t_real_sg, QGenericMatrix>;
class SgBrowserDlg : public QDialog, Ui::SgBrowserDlg class SgBrowserDlg : public QDialog, Ui::SgBrowserDlg
{ {
private: private:
QSettings *m_pSettings = nullptr; QSettings *m_pSettings = nullptr;
Spacegroups<t_mat_sg, t_vec_sg> m_sgs;
Spacegroups<t_mat_sg, t_vec_sg> m_magsgs;
std::vector<std::tuple<int, std::string, std::vector<t_mat44_sg>>> m_nuclsgs;
bool m_showBNS = true; bool m_showBNS = true;
private: private:
void SetupSpaceGroup(const Spacegroup<t_mat_sg, t_vec_sg>& sg); void SetupMagSpaceGroups();
void SetupSpaceGroups(); void SetupNuclSpaceGroups();
protected: protected:
virtual void showEvent(QShowEvent *pEvt) override; virtual void showEvent(QShowEvent *pEvt) override;
...@@ -44,7 +48,9 @@ protected: ...@@ -44,7 +48,9 @@ protected:
virtual void closeEvent(QCloseEvent *pEvt) override; virtual void closeEvent(QCloseEvent *pEvt) override;
// slots // slots
void SpaceGroupSelected(QTreeWidgetItem *pItem); void MagSpaceGroupSelected(QTreeWidgetItem *pItem);
void NuclSpaceGroupSelected(QTreeWidgetItem *pItem);
void SwitchToBNS(bool bBNS); void SwitchToBNS(bool bBNS);
public: public:
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* space group browser
* @author Tobias Weber <tweber@ill.fr>
* @date Apr-2018
* @license GPLv3, see 'LICENSE' file
* @desc The present version was forked on 8-Nov-2018 from the privately developed "magtools" project (https://github.com/t-weber/magtools).
*/
-->
<ui version="4.0"> <ui version="4.0">
<class>SgBrowserDlg</class> <class>SgBrowserDlg</class>
<widget class="QDialog" name="SgBrowserDlg"> <widget class="QDialog" name="SgBrowserDlg">
...@@ -15,8 +6,8 @@ ...@@ -15,8 +6,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>640</width> <width>610</width>
<height>420</height> <height>440</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
...@@ -25,7 +16,7 @@ ...@@ -25,7 +16,7 @@
<property name="sizeGripEnabled"> <property name="sizeGripEnabled">
<bool>true</bool> <bool>true</bool>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout_4">
<property name="leftMargin"> <property name="leftMargin">
<number>4</number> <number>4</number>
</property> </property>
...@@ -43,38 +34,137 @@ ...@@ -43,38 +34,137 @@
</property> </property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QSplitter" name="splitter"> <widget class="QSplitter" name="splitter">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<widget class="QTreeWidget" name="m_pTree"> <widget class="QTabWidget" name="tabSGs">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch> <horstretch>1</horstretch>
<verstretch>1</verstretch> <verstretch>1</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="showDropIndicator" stdset="0"> <property name="currentIndex">
<bool>false</bool> <number>0</number>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property> </property>
<attribute name="headerVisible"> <widget class="QWidget" name="tabMag">
<bool>false</bool> <attribute name="title">
</attribute> <string>Magnetic</string>
<column> </attribute>
<property name="text"> <layout class="QGridLayout" name="gridLayout">
<string notr="true">1</string> <property name="leftMargin">
</property> <number>4</number>
</column> </property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<property name="spacing">
<number>2</number>
</property>
<item row="0" column="0">
<widget class="QTreeWidget" name="treeMagSG">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabNucl">
<attribute name="title">
<string>Nuclear</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<property name="spacing">
<number>2</number>
</property>
<item row="0" column="0">
<widget class="QTreeWidget" name="treeNuclSG">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="tabKeyNavigation">
<bool>false</bool>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="dragDropOverwriteMode">
<bool>false</bool>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<property name="headerHidden">
<bool>true</bool>
</property>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</widget> </widget>
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabOps">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>2</horstretch> <horstretch>2</horstretch>
...@@ -105,7 +195,13 @@ ...@@ -105,7 +195,13 @@
<number>2</number> <number>2</number>
</property> </property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QListWidget" name="m_pSymOps"> <widget class="QListWidget" name="listSymOps">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="showDropIndicator" stdset="0"> <property name="showDropIndicator" stdset="0">
<bool>false</bool> <bool>false</bool>
</property> </property>
...@@ -143,7 +239,7 @@ ...@@ -143,7 +239,7 @@
<number>2</number> <number>2</number>
</property> </property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QTreeWidget" name="m_pWyc"> <widget class="QTreeWidget" name="listWyc">
<property name="showDropIndicator" stdset="0"> <property name="showDropIndicator" stdset="0">
<bool>false</bool> <bool>false</bool>
</property> </property>
...@@ -174,10 +270,12 @@ ...@@ -174,10 +270,12 @@
</layout> </layout>
</widget> </widget>
<tabstops> <tabstops>
<tabstop>m_pTree</tabstop> <tabstop>tabSGs</tabstop>
<tabstop>tabWidget</tabstop> <tabstop>treeMagSG</tabstop>
<tabstop>m_pSymOps</tabstop> <tabstop>treeNuclSG</tabstop>
<tabstop>m_pWyc</tabstop> <tabstop>tabOps</tabstop>
<tabstop>listSymOps</tabstop>
<tabstop>listWyc</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>
<connections/> <connections/>
......
...@@ -182,14 +182,16 @@ load_cif(const std::string& filename, t_real eps=1e-6) ...@@ -182,14 +182,16 @@ load_cif(const std::string& filename, t_real eps=1e-6)
*/ */
template<class t_mat, class t_real = typename t_mat::value_type> template<class t_mat, class t_real = typename t_mat::value_type>
std::vector<std::tuple<int, std::string, std::vector<t_mat>>> std::vector<std::tuple<int, std::string, std::vector<t_mat>>>
get_sgs() get_sgs(bool bAddNr=true, bool bAddHall=true)
{ {
std::vector<std::tuple<int, std::string, std::vector<t_mat>>> sgs; std::vector<std::tuple<int, std::string, std::vector<t_mat>>> sgs;
for(const auto &sg : gemmi::spacegroup_tables::main)