diff --git a/Core/Lattice/Lattice.cpp b/Core/Lattice/Lattice.cpp index d69811b3c8ac1e370eac6b7b1b0df3a06e6f7645..775fa83ff133e10f14854a98259fd348c18d2bb9 100644 --- a/Core/Lattice/Lattice.cpp +++ b/Core/Lattice/Lattice.cpp @@ -143,6 +143,14 @@ std::vector<kvector_t> Lattice::reciprocalLatticeVectorsWithinRadius( input_vector, nearest_coords, radius, m_ra, m_rb, m_rc, m_a, m_b, m_c); } +Lattice Lattice::createCubicLattice(double a) +{ + kvector_t a1(a, 0.0, 0.0); + kvector_t a2(0.0, a, 0.0); + kvector_t a3(0.0, 0.0, a); + return Lattice(a1, a2, a3); +} + Lattice Lattice::createFCCLattice(double a) { double b = a/2.0; @@ -152,14 +160,38 @@ Lattice Lattice::createFCCLattice(double a) return Lattice(a1, a2, a3); } -Lattice Lattice::createTrigonalLattice(double a, double c) +Lattice Lattice::createHexagonalLattice(double a, double c) +{ + kvector_t a1(a, 0.0, 0.0); + kvector_t a2(-a/2.0, std::sqrt(3.0)*a/2.0, 0.0); + kvector_t a3(0.0, 0.0, c); + return Lattice(a1, a2, a3); +} + +Lattice Lattice::createHCPLattice(double a, double c) { kvector_t a1(a, 0.0, 0.0); kvector_t a2(-a/2.0, std::sqrt(3.0)*a/2.0, 0); + kvector_t a3(a/2.0, a/std::sqrt(3.0)/2.0, c/2.0); + return Lattice(a1, a2, a3); +} + +Lattice Lattice::createTetragonalLattice(double a, double c) +{ + kvector_t a1(a, 0.0, 0.0); + kvector_t a2(0.0, a, 0.0); kvector_t a3(0.0, 0.0, c); return Lattice(a1, a2, a3); } +Lattice Lattice::createBCTLattice(double a, double c) +{ + kvector_t a1(a, 0.0, 0.0); + kvector_t a2(0.0, a, 0.0); + kvector_t a3(a/2.0, a/2.0, c/2.0); + return Lattice(a1, a2, a3); +} + void Lattice::onChange() { m_cache_ok = false; diff --git a/Core/Lattice/Lattice.h b/Core/Lattice/Lattice.h index 099f31fa0349ded24afe29cc419950c4e3d16eec..b7e087e46cd071039e1dffd659ebb69226002bef 100644 --- a/Core/Lattice/Lattice.h +++ b/Core/Lattice/Lattice.h @@ -75,9 +75,17 @@ public: //! Sets a selection rule for the reciprocal vectors void setSelectionRule(const ISelectionRule& p_selection_rule); + static Lattice createCubicLattice(double a); + static Lattice createFCCLattice(double a); - static Lattice createTrigonalLattice(double a, double c); + static Lattice createHexagonalLattice(double a, double c); + + static Lattice createHCPLattice(double a, double c); + + static Lattice createTetragonalLattice(double a, double c); + + static Lattice createBCTLattice(double a, double c); void onChange() override; diff --git a/Core/Lattice/LatticeUtils.cpp b/Core/Lattice/LatticeUtils.cpp index 8d7d7d49fc93e6c6528ae7db59352a2c7c294d11..6c0965d7a1982ead05e44a60fefbf962f41885a3 100644 --- a/Core/Lattice/LatticeUtils.cpp +++ b/Core/Lattice/LatticeUtils.cpp @@ -18,11 +18,30 @@ Lattice LatticeUtils::CreateFCCLattice(double lattice_constant, const ILatticeOrientation& orientation) { - Lattice prim_cubic( {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0} ); + Lattice prim_cubic = Lattice::createCubicLattice(1.0); std::unique_ptr<ILatticeOrientation> P_orientation(orientation.clone()); P_orientation->usePrimitiveLattice(prim_cubic); auto rotation = P_orientation->transformationMatrix(); - double a = lattice_constant/2.0; - Lattice fcc( {a, a, 0.0}, {0.0, a, a}, {a, 0.0, a} ); + Lattice fcc = Lattice::createFCCLattice(lattice_constant); return fcc.createTransformedLattice(rotation); } + +Lattice LatticeUtils::CreateHCPLattice(double a, double c, const ILatticeOrientation &orientation) +{ + Lattice prim_hexagonal = Lattice::createHexagonalLattice(1.0, c/a); + std::unique_ptr<ILatticeOrientation> P_orientation(orientation.clone()); + P_orientation->usePrimitiveLattice(prim_hexagonal); + auto rotation = P_orientation->transformationMatrix(); + Lattice hcp = Lattice::createHCPLattice(a, c); + return hcp.createTransformedLattice(rotation); +} + +Lattice LatticeUtils::CreateBCTLattice(double a, double c, const ILatticeOrientation &orientation) +{ + Lattice prim_tetragonal = Lattice::createTetragonalLattice(1.0, c/a); + std::unique_ptr<ILatticeOrientation> P_orientation(orientation.clone()); + P_orientation->usePrimitiveLattice(prim_tetragonal); + auto rotation = P_orientation->transformationMatrix(); + Lattice hcp = Lattice::createBCTLattice(a, c); + return hcp.createTransformedLattice(rotation); +} diff --git a/Core/Lattice/LatticeUtils.h b/Core/Lattice/LatticeUtils.h index b908c4bb5a74c22e2b78b0b75ccf047352157f34..1c3eb7fe0821cc15b62de8226dc7b33e4d9b3de3 100644 --- a/Core/Lattice/LatticeUtils.h +++ b/Core/Lattice/LatticeUtils.h @@ -24,6 +24,10 @@ namespace LatticeUtils { BA_CORE_API_ Lattice CreateFCCLattice(double lattice_constant, const ILatticeOrientation& orientation); +BA_CORE_API_ Lattice CreateHCPLattice(double a, double c, + const ILatticeOrientation& orientation); +BA_CORE_API_ Lattice CreateBCTLattice(double a, double c, + const ILatticeOrientation& orientation); } // namespace LatticeUtils #endif // LATTICEUTILS_H diff --git a/GUI/coregui/Views/FitWidgets/FitComparisonWidget1D.cpp b/GUI/coregui/Views/FitWidgets/FitComparisonWidget1D.cpp index a70277f32a48fb7958b50cabf57d6c05179e73de..c9d0b9d1bc6295ecbe8420d2f817e24d9caf11b3 100644 --- a/GUI/coregui/Views/FitWidgets/FitComparisonWidget1D.cpp +++ b/GUI/coregui/Views/FitWidgets/FitComparisonWidget1D.cpp @@ -105,6 +105,7 @@ void FitComparisonWidget1D::subscribeToItem() void FitComparisonWidget1D::unsubscribeFromItem() { + m_diff_plot->setItem(nullptr); m_comparisonController->clear(); } diff --git a/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant.cpp b/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant.cpp index b89a60b57d96db130320ee92cf343d7740769fcf..8e16448256b70e38d89c68fd122d088d5cadbc96 100644 --- a/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant.cpp +++ b/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant.cpp @@ -23,22 +23,26 @@ #include <QVBoxLayout> #include <QFileDialog> #include <QMessageBox> +#include <QMenu> namespace { -const QSize default_dialog_size(600, 800); +const QSize default_dialog_size(300, 400); } -CsvImportAssistant::CsvImportAssistant(QString dir, QString file, QWidget* parent): +CsvImportAssistant::CsvImportAssistant(QString& dir, QString& file, QWidget* parent): QDialog(parent), m_dirName(dir), m_fileName(file), + m_lastDataRow(0), + m_intensityCol(0), + m_coordinateCol(0), + m_singleCol(0), m_tableWidget(nullptr), - m_filePathField(nullptr), m_separatorField(nullptr), m_firstDataRowSpinBox(nullptr), - m_lastDataRowSpinBox(nullptr), - m_singleDataColSpinBox(nullptr) + m_singleDataColSpinBox(nullptr), + m_importButton(nullptr) { setWindowTitle("Data Importer"); setMinimumSize(128, 128); @@ -54,7 +58,7 @@ CsvImportAssistant::CsvImportAssistant(QString dir, QString file, QWidget* paren StyleUtils::setResizable(this); if(!m_fileName.isEmpty()) - CsvImportAssistant::onReloadButton(); + CsvImportAssistant::Reload(); } @@ -64,8 +68,9 @@ QBoxLayout* CsvImportAssistant::createLayout() auto result = new QVBoxLayout; auto preresult = new QHBoxLayout; - auto importButton = new QPushButton("Import"); - connect(importButton, &QPushButton::clicked, this, &CsvImportAssistant::onImportButton); + m_importButton = new QPushButton("Import"); + m_importButton->setDefault(true); + connect(m_importButton, &QPushButton::clicked, this, &CsvImportAssistant::onImportButton); auto rejectButton = new QPushButton("Cancel"); connect(rejectButton, &QPushButton::clicked, this, &CsvImportAssistant::onRejectButton); @@ -74,148 +79,84 @@ QBoxLayout* CsvImportAssistant::createLayout() m_tableWidget = new QTableWidget(); preresult->setMargin(10); - //preresult->setSpacing(5); - //preresult->addStretch(1); preresult->addWidget(rejectButton); - preresult->addWidget(importButton); + preresult->addWidget(m_importButton); result->setMargin(10); - //result->setSpacing(5); - //result->addStretch(1); + result->addWidget(new QLabel("Right click on the table or use the controls below to modify what will be imported")); result->addWidget(m_tableWidget); - // result->addLayout(CsvImportAssistant::createFileDetailsLayout()); - // result->addLayout(preresult); + m_tableWidget->setContextMenuPolicy(Qt::CustomContextMenu); + m_tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); + connect(m_tableWidget, &QTableWidget::cellClicked, this, &CsvImportAssistant::OnColumnClicked); + connect(m_tableWidget, &QTableWidget::customContextMenuRequested, this, &CsvImportAssistant::onColumnRightClick); return result; } QBoxLayout* CsvImportAssistant::createFileDetailsLayout(){ - auto result = new QVBoxLayout; + auto result = new QHBoxLayout; result->setMargin(10); - //result->setSpacing(5); - //result->addStretch(1); - - auto labelFilepath = new QLabel("File to import: "); - m_filePathField = new QLineEdit(m_fileName,this); - auto browseButton = new QPushButton("browse"); - connect(browseButton, &QPushButton::clicked, this, &CsvImportAssistant::onBrowseButton); - auto lay1 = new QHBoxLayout; - //lay1->setMargin(10); - //lay1->setSpacing(5); - //lay1->addStretch(1); - lay1->addWidget(labelFilepath); - lay1->addWidget(m_filePathField); - lay1->addWidget(browseButton); - - result->addLayout(lay1); auto labelSeparator = new QLabel("Separator: "); m_separatorField = new QLineEdit(QString(guessSeparator())); m_separatorField->setMaxLength(1); - auto lay2 = new QHBoxLayout; - //lay2->setMargin(10); - //lay2->setSpacing(5); - //lay2->addStretch(1); + m_separatorField->setMaximumWidth(50); + auto lay2 = new QVBoxLayout; lay2->addWidget(labelSeparator); lay2->addWidget(m_separatorField); - result->addLayout(lay2); + //result->addLayout(lay2); + connect(m_separatorField, &QLineEdit::editingFinished, this, &CsvImportAssistant::Reload); - // auto labelHeaderRow = new QLabel("Headers row (zero for no headers): "); - // m_headersRowSpinBox = new QSpinBox(); - // m_headersRowSpinBox->setMinimum(0); - // m_headersRowSpinBox->setMaximum(0); - // m_headersRowSpinBox->setValue(0); - // auto lay3 = new QHBoxLayout; - // //lay3->setMargin(10); - // //lay3->setSpacing(5); - // //lay3->addStretch(1); - // lay3->addWidget(labelHeaderRow); - // lay3->addWidget(m_headersRowSpinBox); - // result->addLayout(lay3); + auto lay3 = new QVBoxLayout; auto labelFirstDataRow = new QLabel("First data row: "); m_firstDataRowSpinBox = new QSpinBox(); m_firstDataRowSpinBox->setMinimum(1); m_firstDataRowSpinBox->setMaximum(1); m_firstDataRowSpinBox->setValue(1); - auto lay4 = new QHBoxLayout; - //lay4->setMargin(10); - //lay4->setSpacing(5); - //lay4->addStretch(1); - lay4->addWidget(labelFirstDataRow); - lay4->addWidget(m_firstDataRowSpinBox); - result->addLayout(lay4); + m_firstDataRowSpinBox->setMaximumWidth(50); + lay3->addWidget(labelFirstDataRow); + lay3->addWidget(m_firstDataRowSpinBox); - auto labelLastDataRow = new QLabel("Last data row (zero to read until last row found): "); - m_lastDataRowSpinBox = new QSpinBox(); - m_lastDataRowSpinBox->setMinimum(0); - m_lastDataRowSpinBox->setMaximum(0); - m_lastDataRowSpinBox->setValue(0); - auto lay5 = new QHBoxLayout; - //lay5->setMargin(10); - //lay5->setSpacing(5); - //lay5->addStretch(1); - lay5->addWidget(labelLastDataRow); - lay5->addWidget(m_lastDataRowSpinBox); - result->addLayout(lay5); + connect(m_firstDataRowSpinBox, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), + [this](){ Reload(); }); + auto lay4 = new QVBoxLayout; auto labelSingleColImport = new QLabel("Import Single Column (zero to import all): "); m_singleDataColSpinBox = new QSpinBox(); m_singleDataColSpinBox->setMinimum(0); m_singleDataColSpinBox->setMaximum(0); m_singleDataColSpinBox->setValue(0); - auto laySingleDataCol = new QHBoxLayout; - //lay5->setMargin(10); - //lay5->setSpacing(5); - //lay5->addStretch(1); - laySingleDataCol->addWidget(labelSingleColImport); - laySingleDataCol->addWidget(m_singleDataColSpinBox); - result->addLayout(laySingleDataCol); - + m_singleDataColSpinBox->setMaximumWidth(50); + lay4->addWidget(labelSingleColImport); + lay4->addWidget(m_singleDataColSpinBox); + connect(m_singleDataColSpinBox, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), + [this](int i){ m_singleCol = unsigned(i); Reload(); }); - auto lay6 = new QVBoxLayout; - auto reloadButton = new QPushButton("Reload"); - connect(reloadButton, &QPushButton::clicked, this, &CsvImportAssistant::onReloadButton); - //lay6->setMargin(10); - lay6->addWidget(reloadButton); - result->addLayout(lay1); result->addLayout(lay2); - //result->addLayout(lay3); + result->addSpacing(20); + result->addLayout(lay3); + result->addSpacing(20); result->addLayout(lay4); - result->addLayout(lay5); - result->addLayout(lay6); return result; } -void CsvImportAssistant::onBrowseButton() -{ - const QString filter_string = "Intensity File (*.txt *.dat *.ascii *.int *.gz *.tif *.tiff *.csv);;All files (*.*)"; - QString fileName = QFileDialog::getOpenFileName(nullptr, QStringLiteral("Open Intensity File"), - this->m_dirName, filter_string); - if(fileName != nullptr){ - m_filePathField->setText(fileName); - m_fileName = fileName; - CsvImportAssistant::onReloadButton(); - } - -} - -void CsvImportAssistant::onReloadButton() +void CsvImportAssistant::Reload() { - std::ifstream f(filepath().toStdString()); + std::ifstream f(m_fileName.toStdString()); if(f.good()){ generate_table(); }else{ QMessageBox msgBox; - std::string message = "There was a problem opening the file \"" + filepath().toStdString() + "\""; + std::string message = "There was a problem opening the file \"" + m_fileName.toStdString() + "\""; message += "\n Check for any errors in the path and try again."; msgBox.setText(QString::fromStdString(message)); msgBox.setIcon(msgBox.Critical); @@ -233,7 +174,7 @@ void CsvImportAssistant::onImportButton() try { auto data = getData(); accept(); - } catch(std::exception& e){ + } catch(...){ QString message = QString("Unable to import, check that the table contains only numerical values"); QMessageBox::warning(nullptr, "Wrong data format", message); } @@ -242,16 +183,14 @@ void CsvImportAssistant::onImportButton() std::unique_ptr<OutputData<double>> CsvImportAssistant::getData() { - using namespace std; - int nTableRows = m_tableWidget->rowCount(); int nTableCols = m_tableWidget->columnCount(); - vector<vector<string>> StringVectorVector; - vector<string> StringVector; + std::vector<std::vector<std::string>> StringVectorVector; + std::vector<std::string> StringVector; //save the values of the array - std::size_t nDataCols = 0; - std::size_t nDataRows = 0; + size_t nDataCols = 0; + size_t nDataRows = 0; for(int i = 0; i < nTableRows; i++){ StringVector.clear(); nDataCols = 0; @@ -267,7 +206,7 @@ std::unique_ptr<OutputData<double>> CsvImportAssistant::getData() } std::unique_ptr<OutputData<double>> result; - result.reset(new OutputData<double>()); + result = std::make_unique<OutputData<double>>(); if( (nDataCols < 2) || (nDataRows < 2) ){ size_t nElem = std::max(nDataCols,nDataRows); @@ -278,8 +217,8 @@ std::unique_ptr<OutputData<double>> CsvImportAssistant::getData() for(unsigned col=0; col<nDataCols; col++) { axes_indices[0] = item; size_t global_index = result->toGlobalIndex(axes_indices); - string string_to_parse; - vector<double> parsed_doubles; + std::string string_to_parse; + std::vector<double> parsed_doubles; string_to_parse = StringVectorVector[row][col]; parsed_doubles = DataFormatUtils::parse_doubles(string_to_parse); (*result)[global_index] = parsed_doubles[0]; @@ -287,6 +226,31 @@ std::unique_ptr<OutputData<double>> CsvImportAssistant::getData() } } } + else if(m_coordinateName != ""){ + //Fill intensity values and coordinate values: + size_t intensityCol = 1; + size_t coordinateCol = 0; + std::vector<double> coordValues; + std::vector<double> intensityValues; + for(unsigned row=0; row < nDataRows; row++) { + std::string string_to_parse; + std::vector<double> parsed_doubles; + + string_to_parse = StringVectorVector[row][coordinateCol]; + parsed_doubles = DataFormatUtils::parse_doubles(string_to_parse); + coordValues.push_back(parsed_doubles[0]); + + string_to_parse = StringVectorVector[row][intensityCol]; + parsed_doubles = DataFormatUtils::parse_doubles(string_to_parse); + intensityValues.push_back(parsed_doubles[0]); + } + auto axisName = m_coordinateName.toStdString(); + PointwiseAxis coordAxis(axisName, coordValues); + result->addAxis(coordAxis); + + for(unsigned i = 0; i < intensityValues.size(); i++) + (*result)[i] = intensityValues[i]; + } else{ result->addAxis("x", nDataCols, 0.0, double(nDataCols)); result->addAxis("y", nDataRows, 0.0, double(nDataRows)); @@ -296,8 +260,8 @@ std::unique_ptr<OutputData<double>> CsvImportAssistant::getData() axes_indices[0] = col; axes_indices[1] = static_cast<unsigned>(nDataRows) - 1 - row; size_t global_index = result->toGlobalIndex(axes_indices); - string string_to_parse; - vector<double> parsed_doubles; + std::string string_to_parse; + std::vector<double> parsed_doubles; string_to_parse = StringVectorVector[row][col]; parsed_doubles = DataFormatUtils::parse_doubles(string_to_parse); (*result)[global_index] = parsed_doubles[0]; @@ -308,126 +272,127 @@ std::unique_ptr<OutputData<double>> CsvImportAssistant::getData() } -void CsvImportAssistant::generate_table() -{ - CSVFile* csvFile; - try{ - csvFile = new CSVFile(filepath().toStdString(), separator(), headersLine()); +void CsvImportAssistant::generate_table() { + std::unique_ptr<CSVFile> csvFile; + try { + csvFile = std::make_unique<CSVFile>(m_fileName.toStdString(), separator()); } - catch(...){ + catch (...) { QMessageBox msgBox; - std::string message = "There was a problem opening the file \"" + filepath().toStdString() + "\""; + std::string message = "There was a problem opening the file \"" + m_fileName.toStdString() + "\""; msgBox.setText(QString::fromStdString(message)); msgBox.setIcon(msgBox.Critical); msgBox.exec(); return; } - - m_tableWidget->clearContents(); - m_tableWidget->setColumnCount(int(csvFile->NumberOfColumns())); - m_tableWidget->setRowCount(0); - m_lastDataRowSpinBox->setMaximum(int(csvFile->NumberOfRows())); m_firstDataRowSpinBox->setMaximum(int(csvFile->NumberOfRows())); m_singleDataColSpinBox->setMaximum(int(csvFile->NumberOfColumns())); - //m_headersRowSpinBox->setMaximum(csvFile->NumberOfRows()); + m_lastDataRow = unsigned(int(csvFile->NumberOfRows())); + std::vector<std::vector<std::string>> csvArray = csvFile->asArray(); - set_table_data(csvFile); - remove_unwanted(); - setRowNumbering(); + if (m_lastDataRow < 1) { + m_importButton->setDisabled(true); + return; + } + + + //Remove empty lines at the end automatically: + while(QString::fromStdString(accumulate(csvArray[m_lastDataRow-1].begin(), csvArray[m_lastDataRow-1].end(), std::string(""))).trimmed() == ""){ + m_lastDataRow--; + m_firstDataRowSpinBox->setMaximum(int(m_lastDataRow)); + if (m_lastDataRow < 1) { + m_importButton->setDisabled(true); + return; + } + } + + std::vector<std::vector<std::string>> dataArray( csvArray.begin() + firstLine()-1, csvArray.begin() + m_lastDataRow ); + + removeBlankColumns(dataArray); - return; + extractDesiredColumns(dataArray); + + set_table_data(dataArray); + + setRowNumbering(); } -void CsvImportAssistant::set_table_data(CSVFile* csvFile){ +void CsvImportAssistant::set_table_data(std::vector<std::vector<std::string>> dataArray){ + + if(dataArray.empty()){ + m_tableWidget->clearContents(); + m_tableWidget->setRowCount(0); + return; + } + + size_t nRows = dataArray.size(); + size_t nCols = dataArray[0].size(); + m_tableWidget->clearContents(); + m_tableWidget->setColumnCount(int(nCols)); + m_tableWidget->setRowCount(0); - unsigned firstDataLine = firstLine() - 1; - unsigned lastDataLine = lastLine() == 0 ? unsigned(m_lastDataRowSpinBox->maximum()) : lastLine(); - for(unsigned i = firstDataLine; i < lastDataLine; i++){ + for(unsigned i = 0; i < nRows ; i++){ m_tableWidget->insertRow(m_tableWidget->rowCount()); unsigned I = unsigned(m_tableWidget->rowCount()) - 1; - for(unsigned j = 0; j < csvFile->NumberOfColumns(); j++){ - std::string aasdf = csvFile->operator [](i)[j]; - m_tableWidget->setItem(int(I),int(j),new QTableWidgetItem(QString::fromStdString(aasdf))); + for(unsigned j = 0; j < dataArray[i].size(); j++){ + m_tableWidget->setItem(int(I),int(j),new QTableWidgetItem(QString::fromStdString(dataArray[i][j]))); } } } -void CsvImportAssistant::remove_unwanted(){ - using namespace std; - int nRows = m_tableWidget->rowCount(); - int nCols = m_tableWidget->columnCount(); - vector<vector<string>> StringVectorVector; - vector<string> StringVector; - vector<int> to_be_removed; +void CsvImportAssistant::removeBlankColumns(std::vector<std::vector<std::string> > &dataArray){ - //save the inices of blank cols - for(int j = 0; j < nCols; j++){ + if(dataArray.empty()) + return; - if(singleColumnImport() > 0){ - if( unsigned(j+1) != singleColumnImport()){ - to_be_removed.push_back(j); - continue; - } - } + std::vector<std::vector<std::string>> buffer2d; + std::vector<std::string> buffer1d; + std::vector<int> to_be_removed; - int i = 0; - bool this_col_is_blank = cell_is_blank(i,j); - while(this_col_is_blank && i < nRows ){ - this_col_is_blank = cell_is_blank(i,j); - i++; - } - if(i == nRows){ - to_be_removed.push_back(j); - } + size_t nRows = dataArray.size(); + size_t nCols = dataArray[0].size(); + + if(!hasEqualLengthLines(dataArray)){ + throw Exceptions::NotImplementedException("All inner vectors should have the same length already."); } - //save the values of the array - for(int i = 0; i < nRows; i++){ - StringVector.clear(); - for(int j = 0; j < nCols; j++){ - string contents = m_tableWidget->item(i,j) != nullptr ? m_tableWidget->item(i,j)->text().toStdString() : ""; - StringVector.push_back(contents); + //traverse the array columnwise -- this may be inneficient. + for(size_t j = 0; j < nCols; j++){ + buffer1d.clear(); + for(size_t i = 0; i < nRows; i++){ + buffer1d.push_back(dataArray[i][j]); } - //Skip last row if it is an empty line: - if(i == nRows - 1) - if(QString::fromStdString(std::accumulate(StringVector.begin(), StringVector.end(), std::string(""))).trimmed() == "") - continue; + if(QString::fromStdString(accumulate(buffer1d.begin(), buffer1d.end(), std::string(""))).trimmed() == "") + continue; - StringVectorVector.push_back(StringVector); + buffer2d.push_back(buffer1d); } - //correct the size of the table - m_tableWidget->clearContents(); - m_tableWidget->setRowCount(0); - m_tableWidget->setColumnCount(nCols-int(to_be_removed.size())); - nRows = int(StringVectorVector.size()); + if(buffer2d.empty()){ + dataArray.clear(); + return; + } - //put values into a new table - for(int i = 0; i < nRows; i++){ - m_tableWidget->insertRow(m_tableWidget->rowCount()); - int J = 0; - for(int j = 0; j < nCols; j++){ - if( std::find(to_be_removed.begin(), to_be_removed.end(), j) == to_be_removed.end()){ - std::string retrievedString = StringVectorVector[unsigned(i)][unsigned(j)]; - m_tableWidget->setItem(i,J,new QTableWidgetItem(QString::fromStdString(retrievedString))); - J++; - } + //now buffer2d has the original array, without blank columns, transposed. + nCols = buffer2d.size(); + nRows = buffer2d[0].size(); + + //Save the modified array --i.e. transpose buffer2d + dataArray.clear(); + for(size_t i = 0; i < nRows; i++){ + buffer1d.clear(); + for(size_t j = 0; j < nCols; j++){ + buffer1d.push_back(buffer2d[j][i]); } + dataArray.push_back(buffer1d); } - - //set header labels: - QStringList headers; - for(int j = 0; j < nCols; j++) - if( std::find(to_be_removed.begin(), to_be_removed.end(), j) == to_be_removed.end()) - headers.append(QString::fromStdString(std::string("Column ") + std::to_string(j+1))); - m_tableWidget->setHorizontalHeaderLabels(headers); } void CsvImportAssistant::setRowNumbering(){ unsigned firstDataLine = firstLine(); - unsigned lastDataLine = lastLine() == 0 ? unsigned(m_lastDataRowSpinBox->maximum()) : lastLine(); + unsigned lastDataLine = lastLine(); QStringList displayRowNumbers; @@ -438,29 +403,6 @@ void CsvImportAssistant::setRowNumbering(){ } -bool CsvImportAssistant::cell_is_blank(int iRow, int jCol){ - - if ( m_tableWidget->item(iRow,jCol) == nullptr) - return true; - - if ( m_tableWidget->item(iRow,jCol)->text() == nullptr) - return true; - - if( m_tableWidget->item(iRow,jCol)->text().trimmed() == "") - return true; - - return false; -} - -QString CsvImportAssistant::filepath() const{ - return m_filePathField->text().trimmed(); -} - -void CsvImportAssistant::setFilepath(QString fpath){ - m_fileName = fpath; - m_filePathField->setText(m_fileName); -} - char CsvImportAssistant::separator() const{ char separator; QString tmpstr = m_separatorField->text(); @@ -479,13 +421,12 @@ char CsvImportAssistant::separator() const{ } char CsvImportAssistant::guessSeparator() const{ - using namespace std; int frequencies[127] = {0}; //The actual characters that may be realistically //used as separators are only a handfull... //And this list seems already exagerated. - vector<char> preferredSeparators; + std::vector<char> preferredSeparators; preferredSeparators.push_back(' '); preferredSeparators.push_back(','); preferredSeparators.push_back(';'); @@ -502,8 +443,10 @@ char CsvImportAssistant::guessSeparator() const{ //count number of occurences of each char in the file: char c; std::ifstream is(m_fileName.toStdString()); - while (is.get(c)) - frequencies[int(c)]++; + while (is.get(c)){ + if(unsigned(c) < 127) + frequencies[unsigned(c)]++; + } is.close(); //set the guessed separator as the most frequent among the @@ -527,8 +470,14 @@ char CsvImportAssistant::guessSeparator() const{ return guessedSep; } -unsigned CsvImportAssistant::headersLine() const{ - return 0;//m_headersRowSpinBox->value(); +void CsvImportAssistant::setHeaders(){ + //Reset header labels + QStringList headers; + + for(int j = 0; j < m_tableWidget->columnCount(); j++) + headers.append(QString::number(j + 1)); + + m_tableWidget->setHorizontalHeaderLabels(headers); } unsigned CsvImportAssistant::firstLine() const{ @@ -536,9 +485,225 @@ unsigned CsvImportAssistant::firstLine() const{ } unsigned CsvImportAssistant::lastLine() const{ - return unsigned(m_lastDataRowSpinBox->value()); + return m_lastDataRow; +} + +void CsvImportAssistant::OnColumnClicked(int row, int column) +{ + if(column < -1) return; + if(row < -1) return; + + //m_tableWidget->clearSelection(); + //m_tableWidget->selectionModel()->select +// QModelIndex left = m_tableWidget->model()->index(row, 0); + // QModelIndex right = m_tableWidget->model()->index(row, m_tableWidget->columnCount() - 1); + // QModelIndex top = m_tableWidget->model()->index(0, column); + // QModelIndex bottom = m_tableWidget->model()->index(m_tableWidget->rowCount() - 1, column); + +// QItemSelection selection(left, right); +// selection.merge(QItemSelection(top, bottom), QItemSelectionModel::Select); +// m_tableWidget->selectionModel()->select(selection, QItemSelectionModel::Select); +} + +void CsvImportAssistant::onColumnRightClick(const QPoint position) +{ + auto item = m_tableWidget->itemAt(position); + if(!item) return; + auto row = item->row(); + auto col = item->column(); + + if(row*col < 0) return; + + OnColumnClicked(row,col); + QMenu menu; + + + //Use single column + QAction onlyThisColumn("Use single column as intensity bins",nullptr); + onlyThisColumn.setDisabled(m_coordinateCol+m_intensityCol > 0 || m_singleCol > 0); + menu.addAction(&onlyThisColumn); + connect(&onlyThisColumn,&QAction::triggered,this, + [this](int col){ + m_intensityCol = 0; + m_coordinateCol = 0; + m_coordinateName = ""; + m_singleCol = unsigned(col+1); + m_singleDataColSpinBox->setValue(col+1); + m_tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem( relevantHeaders[_intensity_]) ); + } + ); + + //Action "select from this row" + QAction selectFromThisRowOn("Ignore preceding rows",nullptr); + menu.addAction(&selectFromThisRowOn); + connect(&selectFromThisRowOn,&QAction::triggered,this, + [this](int row){m_firstDataRowSpinBox->setValue(m_tableWidget->verticalHeaderItem(row)->text().toInt());} + ); + + + menu.addSeparator(); + + + //Set column as "Intensity" + QAction setAsIntensity("Set as " + relevantHeaders[_intensity_] + " column", nullptr); + setAsIntensity.setDisabled(m_intensityCol>0 || m_singleCol > 0); + menu.addAction(&setAsIntensity); + connect(&setAsIntensity,&QAction::triggered,this, + [this](int col) { + m_tableWidget->setHorizontalHeaderItem(col, new QTableWidgetItem(relevantHeaders[_intensity_])); + m_intensityCol = unsigned(col+1); + if (m_coordinateCol == m_intensityCol) { + m_coordinateCol = 0; + return; + } + if (m_coordinateCol > 0){ + Reload(); + m_tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem(m_coordinateName)); + m_tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem(relevantHeaders[_intensity_])); + } + } + ); + + QMenu *coordMenu = menu.addMenu("Set as coordinate column"); + coordMenu->setDisabled(m_coordinateCol>0 || m_singleCol > 0); + + + //Set column as "Theta" + QAction setAsTheta("Set as " + relevantHeaders[_theta_],nullptr); + coordMenu->addAction(&setAsTheta); + connect(&setAsTheta,&QAction::triggered,this, + [this](int col){ + m_tableWidget->setHorizontalHeaderItem( col, new QTableWidgetItem( relevantHeaders[_theta_]) ); + m_coordinateCol = unsigned(col+1); + m_coordinateName = m_tableWidget->horizontalHeaderItem(col)->text(); + if(m_coordinateCol == m_intensityCol){ + m_intensityCol=0; + return; + } + if(m_intensityCol > 0){ + Reload(); + m_tableWidget->setHorizontalHeaderItem( 0, new QTableWidgetItem( relevantHeaders[_theta_]) ); + m_tableWidget->setHorizontalHeaderItem( 1, new QTableWidgetItem( relevantHeaders[_intensity_]) ); + } + } + ); + + + //Set column as "2Theta" + QAction setAs2Theta("Set as " + relevantHeaders[_2theta_] + " column",nullptr); + coordMenu->addAction(&setAs2Theta); + connect(&setAs2Theta,&QAction::triggered,this, + [this](int col){ + m_tableWidget->setHorizontalHeaderItem( col, new QTableWidgetItem( relevantHeaders[_2theta_]) ); + m_coordinateCol = unsigned(col+1); + m_coordinateName = m_tableWidget->horizontalHeaderItem(col)->text(); + if(m_coordinateCol == m_intensityCol){ + m_intensityCol=0; + return; + } + if(m_intensityCol > 0){ + Reload(); + m_tableWidget->setHorizontalHeaderItem( 0, new QTableWidgetItem( relevantHeaders[_2theta_]) ); + m_tableWidget->setHorizontalHeaderItem( 1, new QTableWidgetItem( relevantHeaders[_intensity_]) ); + } + } + ); + + + //Set column as "qvector" + QAction setAsQvector("Set as " + relevantHeaders[_q_] + " column",nullptr); + coordMenu->addAction(&setAsQvector); + connect(&setAsQvector,&QAction::triggered,this, + [this](int col){ + m_tableWidget->setHorizontalHeaderItem( col, new QTableWidgetItem( relevantHeaders[_q_]) ); + m_coordinateCol = unsigned(col+1); + m_coordinateName = m_tableWidget->horizontalHeaderItem(col)->text(); + if(m_coordinateCol == m_intensityCol){ + m_intensityCol=0; + return; + } + if(m_intensityCol > 0){ + Reload(); + m_tableWidget->setHorizontalHeaderItem( 0, new QTableWidgetItem( relevantHeaders[_q_]) ); + m_tableWidget->setHorizontalHeaderItem( 1, new QTableWidgetItem( relevantHeaders[_intensity_]) ); + } + } + ); + + + + menu.addSeparator(); + + //Action "reset" + QAction reset("reset",nullptr); + menu.addAction(&reset); + connect(&reset,&QAction::triggered, + [this](){ + m_intensityCol = 0; + m_coordinateCol = 0; + m_coordinateName = ""; + m_singleCol = 0; + m_firstDataRowSpinBox->setValue(0); + m_singleDataColSpinBox->setValue(0); + setHeaders(); + Reload(); + } + ); + + menu.exec(m_tableWidget->mapToGlobal(position)); } -unsigned CsvImportAssistant::singleColumnImport() const{ - return unsigned(m_singleDataColSpinBox->value()); + +bool CsvImportAssistant::hasEqualLengthLines(std::vector<std::vector<std::string>> &dataArray){ + auto tf = all_of( begin(dataArray), end(dataArray), [dataArray](const std::vector<std::string>& x) { + return x.size() == dataArray.front().size(); + }); + return tf; +} + +void CsvImportAssistant::extractDesiredColumns(std::vector<std::vector<std::string>> &dataArray) { + + if (dataArray.empty()) { + m_tableWidget->clearContents(); + m_tableWidget->setRowCount(0); + return; + } + + if ((m_coordinateCol * m_intensityCol < 1) && (m_singleCol < 1)) + return; + + std::vector<std::string> buffer1d; + std::vector<std::vector<std::string>> buffer2d; + auto nRows = dataArray.size(); + auto nCols = dataArray[0].size(); + + if (m_singleCol > 0) { + for (unsigned i = 0; i < nRows; i++) { + buffer1d.clear(); + for (unsigned j = 0; j < nCols; j++) { + if (j + 1 == m_singleCol) + buffer1d.push_back(dataArray[i][j]); + } + buffer2d.push_back(buffer1d); + } + } + else { + for (unsigned i = 0; i < nRows; i++) { + buffer1d.clear(); + //No matter what, we want coordinate column first + for (unsigned j = 0; j < nCols; j++) { + if (j + 1 == m_coordinateCol) + buffer1d.push_back(dataArray[i][j]); + } + //Intensity columns comes next + for (unsigned j = 0; j < nCols; j++) { + if (j + 1 == m_intensityCol) + buffer1d.push_back(dataArray[i][j]); + } + buffer2d.push_back(buffer1d); + } + } + + dataArray.clear(); + swap(buffer2d,dataArray); } diff --git a/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant.h b/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant.h index 5d920fecaf3bacfdce1e2a4738bb213f86378a18..c502046654ef9e2514d30dbd3d84efb3785d9f73 100644 --- a/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant.h +++ b/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant.h @@ -34,22 +34,21 @@ class BA_CORE_API_ CsvImportAssistant : public QDialog Q_OBJECT public: - CsvImportAssistant(QString dir = "./", QString file = "", QWidget* parent = nullptr); - QString filepath() const; - void setFilepath(QString fpath); + CsvImportAssistant(QString& dir, QString& file, QWidget* parent = nullptr); char separator() const; - unsigned headersLine() const; + void setHeaders(); unsigned firstLine() const; unsigned lastLine() const; - unsigned singleColumnImport() const; + void Reload(); std::unique_ptr<OutputData<double>> getData(); + QStringList relevantHeaders = {"Intensity","theta","2theta","q"}; + enum relevantColumns {_intensity_,_theta_,_2theta_,_q_}; public slots: void onImportButton(); - void onReloadButton(); void onRejectButton(); - void onBrowseButton(); - + void OnColumnClicked(int row, int column); + void onColumnRightClick(QPoint position); private: QBoxLayout* createLayout(); @@ -57,24 +56,28 @@ private: char guessSeparator() const; void generate_table(); - void set_table_data(CSVFile *csvFile); - void convert_table(); - void remove_unwanted(); + void set_table_data(std::vector<std::vector<std::string>> dataArray); + void removeBlankColumns(std::vector<std::vector<std::string>> &dataArray); + void extractDesiredColumns(std::vector<std::vector<std::string>> &dataArray); + bool hasEqualLengthLines(std::vector<std::vector<std::string> > &dataArray); void setRowNumbering(); - bool cell_is_blank(int iRow, int jCol); QString m_dirName; QString m_fileName; + unsigned m_lastDataRow; + unsigned m_intensityCol; + unsigned m_coordinateCol; + QString m_coordinateName; + unsigned m_singleCol; QTableWidget* m_tableWidget; - QLineEdit* m_filePathField; QLineEdit* m_separatorField; - //QSpinBox* m_headersRowSpinBox; QSpinBox* m_firstDataRowSpinBox; - QSpinBox* m_lastDataRowSpinBox; QSpinBox* m_singleDataColSpinBox; + QPushButton* m_importButton; + }; -#endif // MATERIALEDITORDIALOG_H +#endif // CSVIMPORTASSISTANT_H diff --git a/GUI/coregui/Views/ImportDataWidgets/CsvReader.cpp b/GUI/coregui/Views/ImportDataWidgets/CsvReader.cpp index d63de6950bd8de4200e5ca14781810d4b4960670..4915aead35bbf497014cec3254f24130d2175d0a 100644 --- a/GUI/coregui/Views/ImportDataWidgets/CsvReader.cpp +++ b/GUI/coregui/Views/ImportDataWidgets/CsvReader.cpp @@ -70,13 +70,15 @@ void CSVFile::EqualizeRowLengths() rows[i].addCell(""); } } - + for(unsigned i = 0; i < NumberOfRows(); i++){ + m_data.push_back(rows[i].dataVector()); + } } -CSVRow const CSVFile::operator[](unsigned index_i) const +std::vector<std::string> const CSVFile::operator[](unsigned index_i) const { - return rows[index_i]; + return m_data[index_i]; } unsigned long CSVFile::NumberOfRows() const diff --git a/GUI/coregui/Views/ImportDataWidgets/CsvReader.h b/GUI/coregui/Views/ImportDataWidgets/CsvReader.h index c6aa4b660b62977f734cc8ad733c97f1df6a121d..1fb2b45ee241d8ce482ff851be19c7fc1fc7ba3a 100644 --- a/GUI/coregui/Views/ImportDataWidgets/CsvReader.h +++ b/GUI/coregui/Views/ImportDataWidgets/CsvReader.h @@ -24,6 +24,8 @@ class CSVRow void addCell(std::string str); + std::vector<std::string> dataVector(){return m_data;} + private: std::vector<std::string> m_data; char separator = '-'; @@ -81,7 +83,7 @@ class CSVFile void EqualizeRowLengths(); - CSVRow const operator[](unsigned index_i) const; + std::vector<std::string> const operator[](unsigned index_i) const; unsigned long NumberOfRows() const; @@ -95,12 +97,15 @@ class CSVFile CSVRow get_row(unsigned i); + std::vector<std::vector<std::string>> asArray(){return m_data;} + private: std::string filepath; char separator = '-'; unsigned headersRow = 0; unsigned numberOfColumns = 0; std::vector<CSVRow> rows; + std::vector<std::vector<std::string>> m_data; }; diff --git a/GUI/coregui/Views/SpecularDataWidgets/SpecularPlot.cpp b/GUI/coregui/Views/SpecularDataWidgets/SpecularPlot.cpp index 970d7ec31370530e1c0a0f3f4f3ab4d20a20821d..83532d9e8d007a048dfcd0b66951e45d32f3ac78 100644 --- a/GUI/coregui/Views/SpecularDataWidgets/SpecularPlot.cpp +++ b/GUI/coregui/Views/SpecularDataWidgets/SpecularPlot.cpp @@ -246,7 +246,6 @@ SpecularDataItem* SpecularPlot::specularItem() const SpecularDataItem* SpecularPlot::specularItem() const { const auto result = dynamic_cast<const SpecularDataItem*>(currentItem()); - Q_ASSERT(result); return result; } diff --git a/Tests/Functional/Core/CoreSpecial/MesoCrystalPerformanceBuilder.cpp b/Tests/Functional/Core/CoreSpecial/MesoCrystalPerformanceBuilder.cpp index 8d52b94dc216f3ec07183d3d74d93636beadac87..bd62c3c099c43b7e49729cd293dcb34051af526d 100644 --- a/Tests/Functional/Core/CoreSpecial/MesoCrystalPerformanceBuilder.cpp +++ b/Tests/Functional/Core/CoreSpecial/MesoCrystalPerformanceBuilder.cpp @@ -136,7 +136,7 @@ namespace Lattice createLattice(double a, double c) { - Lattice result = Lattice::createTrigonalLattice(a, c); + Lattice result = Lattice::createHexagonalLattice(a, c); result.setSelectionRule(SimpleSelectionRule(-1, 1, 1, 3)); return result; } diff --git a/Tests/Functional/Python/PyCore/mesocrystal1.py b/Tests/Functional/Python/PyCore/mesocrystal1.py index 9a7fc15556cb3fd96097490c744e542bff191843..9f42a1e286309eadaab2a4e54d1e6e33f53b5f66 100644 --- a/Tests/Functional/Python/PyCore/mesocrystal1.py +++ b/Tests/Functional/Python/PyCore/mesocrystal1.py @@ -123,7 +123,7 @@ class MySampleBuilder(IMultiLayerBuilder): # create lattice # ------------------------------------------------------------------------- def createLattice(self, stacking_radius_a, stacking_radius_c): - lattice = Lattice.createTrigonalLattice(stacking_radius_a*2.0, stacking_radius_c*2.0*2.3) + lattice = Lattice.createHexagonalLattice(stacking_radius_a*2.0, stacking_radius_c*2.0*2.3) p_result = Lattice(lattice) selection_rule = SimpleSelectionRule(-1, 1, 1, 3) p_result.setSelectionRule( selection_rule ) diff --git a/Tests/UnitTests/Core/Sample/CrystalTest.h b/Tests/UnitTests/Core/Sample/CrystalTest.h index 5e22f442c0e8c5a36ded1e8775085448be1b3f62..dbc87108a57aa30b59ae67c05863e1b6030bc14f 100644 --- a/Tests/UnitTests/Core/Sample/CrystalTest.h +++ b/Tests/UnitTests/Core/Sample/CrystalTest.h @@ -14,7 +14,7 @@ CrystalTest::~CrystalTest() = default; TEST_F(CrystalTest, getChildren) { - Lattice lattice = Lattice::createTrigonalLattice(1.0, 2.0); + Lattice lattice = Lattice::createHexagonalLattice(1.0, 2.0); ParticleComposition composition; Crystal crystal(composition, lattice); diff --git a/Tests/UnitTests/Core/Sample/LatticeTest.h b/Tests/UnitTests/Core/Sample/LatticeTest.h index cc962327b72622d3216d97896020fbc308c0d154..e7ba1fdff5ca44a82c702b4ec9fb517f614ea222 100644 --- a/Tests/UnitTests/Core/Sample/LatticeTest.h +++ b/Tests/UnitTests/Core/Sample/LatticeTest.h @@ -163,10 +163,10 @@ TEST_F(LatticeTest, FCCLatticeTest) EXPECT_EQ(fcc3, l1.getBasisVectorC()); } -// tests trigonal lattice creation -TEST_F(LatticeTest, TrigonalLatticeTest) +// tests hexagonal lattice creation +TEST_F(LatticeTest, HexagonalLatticeTest) { - Lattice l1 = Lattice::createTrigonalLattice(1, 4); + Lattice l1 = Lattice::createHexagonalLattice(1, 4); kvector_t tri1(1, 0.0, 0.0); kvector_t tri2(-1 / 2.0, std::sqrt(3.0) * 1 / 2.0, 0); diff --git a/Tests/UnitTests/Core/Sample/LatticeUtilsTest.h b/Tests/UnitTests/Core/Sample/LatticeUtilsTest.h index b38b2339d6c1918fbd75f57429a7f1f29d383a94..22208c775bf64437bd55d0599dcd86606daf42b8 100644 --- a/Tests/UnitTests/Core/Sample/LatticeUtilsTest.h +++ b/Tests/UnitTests/Core/Sample/LatticeUtilsTest.h @@ -13,38 +13,91 @@ LatticeUtilsTest::~LatticeUtilsTest() = default; // tests the creation of an FCC lattice with the primitive cube aligned along the q-axes TEST_F(LatticeUtilsTest, cubeAlignedFCCTest) { - MillerIndexOrientation cube_aligned(MillerIndexOrientation::QZ, { 0, 0, 1}, - MillerIndexOrientation::QY, { 0, 1, 0}); - auto lattice = LatticeUtils::CreateFCCLattice(2.0, cube_aligned); + MillerIndexOrientation q_aligned(MillerIndexOrientation::QZ, { 0, 0, 1}, + MillerIndexOrientation::QY, { 0, 1, 0}); + auto lattice = LatticeUtils::CreateFCCLattice(2.0, q_aligned); auto a1 = lattice.getBasisVectorA(); auto a2 = lattice.getBasisVectorB(); auto a3 = lattice.getBasisVectorC(); - kvector_t v1 { 1.0, 1.0, 0.0 }; - kvector_t v2 { 0.0, 1.0, 1.0 }; - kvector_t v3 { 1.0, 0.0, 1.0 }; + kvector_t v1 { 0.0, 1.0, 1.0 }; + kvector_t v2 { 1.0, 0.0, 1.0 }; + kvector_t v3 { 1.0, 1.0, 0.0 }; EXPECT_EQ(a1, v1); EXPECT_EQ(a2, v2); EXPECT_EQ(a3, v3); } -// tests the creation of an FCC lattice with the primitive cube aligned along the q-axes +// tests the creation of an FCC lattice with the primitive cube aligned along Miller indices TEST_F(LatticeUtilsTest, diagonalAlignedFCCTest) { - MillerIndexOrientation cube_aligned(MillerIndexOrientation::QZ, { 1, 1, 1}, - MillerIndexOrientation::QX, { 1, 1, 0}); - auto lattice = LatticeUtils::CreateFCCLattice(2.0, cube_aligned); + MillerIndexOrientation diagonal_aligned(MillerIndexOrientation::QZ, { 1, 1, 1}, + MillerIndexOrientation::QX, { 1, 1, 0}); + auto lattice = LatticeUtils::CreateFCCLattice(2.0, diagonal_aligned); + auto a1 = lattice.getBasisVectorA(); + auto a2 = lattice.getBasisVectorB(); + auto a3 = lattice.getBasisVectorC(); + + EXPECT_NEAR(a1.z(), a2.z(), 1e-10); + EXPECT_NEAR(a2.z(), a3.z(), 1e-10); + EXPECT_NEAR(a1.x(), a2.x(), 1e-10); + EXPECT_NEAR(a1.y(), -a2.y(), 1e-10); +} + +// tests the creation of an HCP lattice with a trivial orientation +TEST_F(LatticeUtilsTest, trivialAlignedHCPTest) +{ + MillerIndexOrientation trivial_aligned(MillerIndexOrientation::QZ, { 0, 0, 1}, + MillerIndexOrientation::QX, { 2, -1, 0}); + auto lattice = LatticeUtils::CreateHCPLattice(2.0, 4.0, trivial_aligned); + auto a1 = lattice.getBasisVectorA(); + auto a2 = lattice.getBasisVectorB(); + auto a3 = lattice.getBasisVectorC(); + + kvector_t v1 { 2.0, 0.0, 0.0 }; + kvector_t v2 { -1.0, std::sqrt(3.0), 0.0 }; + kvector_t v3 { 1.0, 1.0/std::sqrt(3.0), 2.0 }; + + EXPECT_EQ(a1, v1); + EXPECT_EQ(a2, v2); + EXPECT_EQ(a3, v3); +} + +// tests the creation of an BCT lattice with the primitive tetragonal aligned along the q-axes +TEST_F(LatticeUtilsTest, tetraAlignedFCCTest) +{ + MillerIndexOrientation q_aligned(MillerIndexOrientation::QZ, { 0, 0, 1}, + MillerIndexOrientation::QY, { 0, 1, 0}); + auto lattice = LatticeUtils::CreateBCTLattice(2.0, 2.0, q_aligned); auto a1 = lattice.getBasisVectorA(); auto a2 = lattice.getBasisVectorB(); auto a3 = lattice.getBasisVectorC(); - kvector_t v1 { 1.0, 1.0, 0.0 }; - kvector_t v2 { 0.0, 1.0, 1.0 }; - kvector_t v3 { 1.0, 0.0, 1.0 }; + kvector_t v1 { 2.0, 0.0, 0.0 }; + kvector_t v2 { 0.0, 2.0, 0.0 }; + kvector_t v3 { 1.0, 1.0, 1.0 }; - EXPECT_EQ(a1.z(), a2.z()); - EXPECT_EQ(a2.z(), a3.z()); - EXPECT_EQ(a2.x(), a3.x()); - EXPECT_EQ(a2.y(), -a3.y()); + EXPECT_EQ(a1, v1); + EXPECT_EQ(a2, v2); + EXPECT_EQ(a3, v3); } + +// tests the creation of an BCT lattice with the primitive tetragonal aligned along Miller indices +TEST_F(LatticeUtilsTest, diagonalAlignedBCTTest) +{ + MillerIndexOrientation diagonal_aligned(MillerIndexOrientation::QZ, { 1, 1, 1}, + MillerIndexOrientation::QX, { 1, 1, 0}); + auto lattice = LatticeUtils::CreateBCTLattice(2.0, 2.0, diagonal_aligned); + auto a1 = lattice.getBasisVectorA(); + auto a2 = lattice.getBasisVectorB(); + auto a3 = lattice.getBasisVectorC(); + + EXPECT_NEAR(a1.z(), a2.z(), 1e-10); + EXPECT_NEAR(a1.x(), a2.x(), 1e-10); + EXPECT_NEAR(a1.y(), -a2.y(), 1e-10); + EXPECT_NEAR(a3.x(), 0.0, 1e-10); + EXPECT_NEAR(a3.y(), 0.0, 1e-10); + EXPECT_NEAR(a3.z(), std::sqrt(3.0), 1e-10); +} + diff --git a/Tests/UnitTests/Core/Sample/MesoCrystalTest.h b/Tests/UnitTests/Core/Sample/MesoCrystalTest.h index 8d678f0cf97d962e1f29355eb5b234e062c8c03c..c367d146b8ac0a9a25849985fa33c3bf6d86f738 100644 --- a/Tests/UnitTests/Core/Sample/MesoCrystalTest.h +++ b/Tests/UnitTests/Core/Sample/MesoCrystalTest.h @@ -16,7 +16,7 @@ MesoCrystalTest::~MesoCrystalTest() = default; TEST_F(MesoCrystalTest, getChildren) { - Lattice lattice = Lattice::createTrigonalLattice(1.0, 2.0); + Lattice lattice = Lattice::createHexagonalLattice(1.0, 2.0); ParticleComposition composition; Crystal crystal(composition, lattice); MesoCrystal meso(crystal, FormFactorFullSphere(1.0)); diff --git a/auto/Wrap/libBornAgainCore.py b/auto/Wrap/libBornAgainCore.py index 65fa2a3444f7e95404e3b62daff20c43ef7a02d4..56198b1052232606d4b2866ffa353efa187c8ad9 100644 --- a/auto/Wrap/libBornAgainCore.py +++ b/auto/Wrap/libBornAgainCore.py @@ -24519,17 +24519,41 @@ class Lattice(INode): return _libBornAgainCore.Lattice_setSelectionRule(self, p_selection_rule) + def createCubicLattice(a): + """createCubicLattice(double a) -> Lattice""" + return _libBornAgainCore.Lattice_createCubicLattice(a) + + createCubicLattice = staticmethod(createCubicLattice) + def createFCCLattice(a): """createFCCLattice(double a) -> Lattice""" return _libBornAgainCore.Lattice_createFCCLattice(a) createFCCLattice = staticmethod(createFCCLattice) - def createTrigonalLattice(a, c): - """createTrigonalLattice(double a, double c) -> Lattice""" - return _libBornAgainCore.Lattice_createTrigonalLattice(a, c) + def createHexagonalLattice(a, c): + """createHexagonalLattice(double a, double c) -> Lattice""" + return _libBornAgainCore.Lattice_createHexagonalLattice(a, c) + + createHexagonalLattice = staticmethod(createHexagonalLattice) + + def createHCPLattice(a, c): + """createHCPLattice(double a, double c) -> Lattice""" + return _libBornAgainCore.Lattice_createHCPLattice(a, c) + + createHCPLattice = staticmethod(createHCPLattice) + + def createTetragonalLattice(a, c): + """createTetragonalLattice(double a, double c) -> Lattice""" + return _libBornAgainCore.Lattice_createTetragonalLattice(a, c) + + createTetragonalLattice = staticmethod(createTetragonalLattice) - createTrigonalLattice = staticmethod(createTrigonalLattice) + def createBCTLattice(a, c): + """createBCTLattice(double a, double c) -> Lattice""" + return _libBornAgainCore.Lattice_createBCTLattice(a, c) + + createBCTLattice = staticmethod(createBCTLattice) def onChange(self): """ @@ -24545,13 +24569,29 @@ class Lattice(INode): Lattice_swigregister = _libBornAgainCore.Lattice_swigregister Lattice_swigregister(Lattice) +def Lattice_createCubicLattice(a): + """Lattice_createCubicLattice(double a) -> Lattice""" + return _libBornAgainCore.Lattice_createCubicLattice(a) + def Lattice_createFCCLattice(a): """Lattice_createFCCLattice(double a) -> Lattice""" return _libBornAgainCore.Lattice_createFCCLattice(a) -def Lattice_createTrigonalLattice(a, c): - """Lattice_createTrigonalLattice(double a, double c) -> Lattice""" - return _libBornAgainCore.Lattice_createTrigonalLattice(a, c) +def Lattice_createHexagonalLattice(a, c): + """Lattice_createHexagonalLattice(double a, double c) -> Lattice""" + return _libBornAgainCore.Lattice_createHexagonalLattice(a, c) + +def Lattice_createHCPLattice(a, c): + """Lattice_createHCPLattice(double a, double c) -> Lattice""" + return _libBornAgainCore.Lattice_createHCPLattice(a, c) + +def Lattice_createTetragonalLattice(a, c): + """Lattice_createTetragonalLattice(double a, double c) -> Lattice""" + return _libBornAgainCore.Lattice_createTetragonalLattice(a, c) + +def Lattice_createBCTLattice(a, c): + """Lattice_createBCTLattice(double a, double c) -> Lattice""" + return _libBornAgainCore.Lattice_createBCTLattice(a, c) def CreateFCCLattice(lattice_constant, orientation): @@ -24562,6 +24602,14 @@ def CreateFCCLattice(lattice_constant, orientation): """ return _libBornAgainCore.CreateFCCLattice(lattice_constant, orientation) + +def CreateHCPLattice(a, c, orientation): + """CreateHCPLattice(double a, double c, ILatticeOrientation orientation) -> Lattice""" + return _libBornAgainCore.CreateHCPLattice(a, c, orientation) + +def CreateBCTLattice(a, c, orientation): + """CreateBCTLattice(double a, double c, ILatticeOrientation orientation) -> Lattice""" + return _libBornAgainCore.CreateBCTLattice(a, c, orientation) class Lattice1DParameters(_object): """ diff --git a/auto/Wrap/libBornAgainCore_wrap.cpp b/auto/Wrap/libBornAgainCore_wrap.cpp index 836d5d27a8b589bb4248d651c855841a80cabf2f..1f9c17cbd2cf7057d091b0b970f5237e00f86b46 100644 --- a/auto/Wrap/libBornAgainCore_wrap.cpp +++ b/auto/Wrap/libBornAgainCore_wrap.cpp @@ -104793,6 +104793,28 @@ fail: } +SWIGINTERN PyObject *_wrap_Lattice_createCubicLattice(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + double arg1 ; + double val1 ; + int ecode1 = 0 ; + PyObject * obj0 = 0 ; + SwigValueWrapper< Lattice > result; + + if (!PyArg_ParseTuple(args,(char *)"O:Lattice_createCubicLattice",&obj0)) SWIG_fail; + ecode1 = SWIG_AsVal_double(obj0, &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "Lattice_createCubicLattice" "', argument " "1"" of type '" "double""'"); + } + arg1 = static_cast< double >(val1); + result = Lattice::createCubicLattice(arg1); + resultobj = SWIG_NewPointerObj((new Lattice(static_cast< const Lattice& >(result))), SWIGTYPE_p_Lattice, SWIG_POINTER_OWN | 0 ); + return resultobj; +fail: + return NULL; +} + + SWIGINTERN PyObject *_wrap_Lattice_createFCCLattice(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; double arg1 ; @@ -104815,7 +104837,100 @@ fail: } -SWIGINTERN PyObject *_wrap_Lattice_createTrigonalLattice(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { +SWIGINTERN PyObject *_wrap_Lattice_createHexagonalLattice(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + double arg1 ; + double arg2 ; + double val1 ; + int ecode1 = 0 ; + double val2 ; + int ecode2 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + SwigValueWrapper< Lattice > result; + + if (!PyArg_ParseTuple(args,(char *)"OO:Lattice_createHexagonalLattice",&obj0,&obj1)) SWIG_fail; + ecode1 = SWIG_AsVal_double(obj0, &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "Lattice_createHexagonalLattice" "', argument " "1"" of type '" "double""'"); + } + arg1 = static_cast< double >(val1); + ecode2 = SWIG_AsVal_double(obj1, &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Lattice_createHexagonalLattice" "', argument " "2"" of type '" "double""'"); + } + arg2 = static_cast< double >(val2); + result = Lattice::createHexagonalLattice(arg1,arg2); + resultobj = SWIG_NewPointerObj((new Lattice(static_cast< const Lattice& >(result))), SWIGTYPE_p_Lattice, SWIG_POINTER_OWN | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Lattice_createHCPLattice(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + double arg1 ; + double arg2 ; + double val1 ; + int ecode1 = 0 ; + double val2 ; + int ecode2 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + SwigValueWrapper< Lattice > result; + + if (!PyArg_ParseTuple(args,(char *)"OO:Lattice_createHCPLattice",&obj0,&obj1)) SWIG_fail; + ecode1 = SWIG_AsVal_double(obj0, &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "Lattice_createHCPLattice" "', argument " "1"" of type '" "double""'"); + } + arg1 = static_cast< double >(val1); + ecode2 = SWIG_AsVal_double(obj1, &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Lattice_createHCPLattice" "', argument " "2"" of type '" "double""'"); + } + arg2 = static_cast< double >(val2); + result = Lattice::createHCPLattice(arg1,arg2); + resultobj = SWIG_NewPointerObj((new Lattice(static_cast< const Lattice& >(result))), SWIGTYPE_p_Lattice, SWIG_POINTER_OWN | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Lattice_createTetragonalLattice(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + double arg1 ; + double arg2 ; + double val1 ; + int ecode1 = 0 ; + double val2 ; + int ecode2 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + SwigValueWrapper< Lattice > result; + + if (!PyArg_ParseTuple(args,(char *)"OO:Lattice_createTetragonalLattice",&obj0,&obj1)) SWIG_fail; + ecode1 = SWIG_AsVal_double(obj0, &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "Lattice_createTetragonalLattice" "', argument " "1"" of type '" "double""'"); + } + arg1 = static_cast< double >(val1); + ecode2 = SWIG_AsVal_double(obj1, &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Lattice_createTetragonalLattice" "', argument " "2"" of type '" "double""'"); + } + arg2 = static_cast< double >(val2); + result = Lattice::createTetragonalLattice(arg1,arg2); + resultobj = SWIG_NewPointerObj((new Lattice(static_cast< const Lattice& >(result))), SWIGTYPE_p_Lattice, SWIG_POINTER_OWN | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_Lattice_createBCTLattice(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; double arg1 ; double arg2 ; @@ -104827,18 +104942,18 @@ SWIGINTERN PyObject *_wrap_Lattice_createTrigonalLattice(PyObject *SWIGUNUSEDPAR PyObject * obj1 = 0 ; SwigValueWrapper< Lattice > result; - if (!PyArg_ParseTuple(args,(char *)"OO:Lattice_createTrigonalLattice",&obj0,&obj1)) SWIG_fail; + if (!PyArg_ParseTuple(args,(char *)"OO:Lattice_createBCTLattice",&obj0,&obj1)) SWIG_fail; ecode1 = SWIG_AsVal_double(obj0, &val1); if (!SWIG_IsOK(ecode1)) { - SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "Lattice_createTrigonalLattice" "', argument " "1"" of type '" "double""'"); + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "Lattice_createBCTLattice" "', argument " "1"" of type '" "double""'"); } arg1 = static_cast< double >(val1); ecode2 = SWIG_AsVal_double(obj1, &val2); if (!SWIG_IsOK(ecode2)) { - SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Lattice_createTrigonalLattice" "', argument " "2"" of type '" "double""'"); + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Lattice_createBCTLattice" "', argument " "2"" of type '" "double""'"); } arg2 = static_cast< double >(val2); - result = Lattice::createTrigonalLattice(arg1,arg2); + result = Lattice::createBCTLattice(arg1,arg2); resultobj = SWIG_NewPointerObj((new Lattice(static_cast< const Lattice& >(result))), SWIGTYPE_p_Lattice, SWIG_POINTER_OWN | 0 ); return resultobj; fail: @@ -104908,6 +105023,92 @@ fail: } +SWIGINTERN PyObject *_wrap_CreateHCPLattice(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + double arg1 ; + double arg2 ; + ILatticeOrientation *arg3 = 0 ; + double val1 ; + int ecode1 = 0 ; + double val2 ; + int ecode2 = 0 ; + void *argp3 = 0 ; + int res3 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; + SwigValueWrapper< Lattice > result; + + if (!PyArg_ParseTuple(args,(char *)"OOO:CreateHCPLattice",&obj0,&obj1,&obj2)) SWIG_fail; + ecode1 = SWIG_AsVal_double(obj0, &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "CreateHCPLattice" "', argument " "1"" of type '" "double""'"); + } + arg1 = static_cast< double >(val1); + ecode2 = SWIG_AsVal_double(obj1, &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "CreateHCPLattice" "', argument " "2"" of type '" "double""'"); + } + arg2 = static_cast< double >(val2); + res3 = SWIG_ConvertPtr(obj2, &argp3, SWIGTYPE_p_ILatticeOrientation, 0 | 0); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "CreateHCPLattice" "', argument " "3"" of type '" "ILatticeOrientation const &""'"); + } + if (!argp3) { + SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "CreateHCPLattice" "', argument " "3"" of type '" "ILatticeOrientation const &""'"); + } + arg3 = reinterpret_cast< ILatticeOrientation * >(argp3); + result = LatticeUtils::CreateHCPLattice(arg1,arg2,(ILatticeOrientation const &)*arg3); + resultobj = SWIG_NewPointerObj((new Lattice(static_cast< const Lattice& >(result))), SWIGTYPE_p_Lattice, SWIG_POINTER_OWN | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_CreateBCTLattice(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + double arg1 ; + double arg2 ; + ILatticeOrientation *arg3 = 0 ; + double val1 ; + int ecode1 = 0 ; + double val2 ; + int ecode2 = 0 ; + void *argp3 = 0 ; + int res3 = 0 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; + SwigValueWrapper< Lattice > result; + + if (!PyArg_ParseTuple(args,(char *)"OOO:CreateBCTLattice",&obj0,&obj1,&obj2)) SWIG_fail; + ecode1 = SWIG_AsVal_double(obj0, &val1); + if (!SWIG_IsOK(ecode1)) { + SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "CreateBCTLattice" "', argument " "1"" of type '" "double""'"); + } + arg1 = static_cast< double >(val1); + ecode2 = SWIG_AsVal_double(obj1, &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "CreateBCTLattice" "', argument " "2"" of type '" "double""'"); + } + arg2 = static_cast< double >(val2); + res3 = SWIG_ConvertPtr(obj2, &argp3, SWIGTYPE_p_ILatticeOrientation, 0 | 0); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "CreateBCTLattice" "', argument " "3"" of type '" "ILatticeOrientation const &""'"); + } + if (!argp3) { + SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "CreateBCTLattice" "', argument " "3"" of type '" "ILatticeOrientation const &""'"); + } + arg3 = reinterpret_cast< ILatticeOrientation * >(argp3); + result = LatticeUtils::CreateBCTLattice(arg1,arg2,(ILatticeOrientation const &)*arg3); + resultobj = SWIG_NewPointerObj((new Lattice(static_cast< const Lattice& >(result))), SWIGTYPE_p_Lattice, SWIG_POINTER_OWN | 0 ); + return resultobj; +fail: + return NULL; +} + + SWIGINTERN PyObject *_wrap_new_Lattice1DParameters__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; Lattice1DParameters *result = 0 ; @@ -136813,8 +137014,12 @@ static PyMethodDef SwigMethods[] = { "Sets a selection rule for the reciprocal vectors. \n" "\n" ""}, + { (char *)"Lattice_createCubicLattice", _wrap_Lattice_createCubicLattice, METH_VARARGS, (char *)"Lattice_createCubicLattice(double a) -> Lattice"}, { (char *)"Lattice_createFCCLattice", _wrap_Lattice_createFCCLattice, METH_VARARGS, (char *)"Lattice_createFCCLattice(double a) -> Lattice"}, - { (char *)"Lattice_createTrigonalLattice", _wrap_Lattice_createTrigonalLattice, METH_VARARGS, (char *)"Lattice_createTrigonalLattice(double a, double c) -> Lattice"}, + { (char *)"Lattice_createHexagonalLattice", _wrap_Lattice_createHexagonalLattice, METH_VARARGS, (char *)"Lattice_createHexagonalLattice(double a, double c) -> Lattice"}, + { (char *)"Lattice_createHCPLattice", _wrap_Lattice_createHCPLattice, METH_VARARGS, (char *)"Lattice_createHCPLattice(double a, double c) -> Lattice"}, + { (char *)"Lattice_createTetragonalLattice", _wrap_Lattice_createTetragonalLattice, METH_VARARGS, (char *)"Lattice_createTetragonalLattice(double a, double c) -> Lattice"}, + { (char *)"Lattice_createBCTLattice", _wrap_Lattice_createBCTLattice, METH_VARARGS, (char *)"Lattice_createBCTLattice(double a, double c) -> Lattice"}, { (char *)"Lattice_onChange", _wrap_Lattice_onChange, METH_VARARGS, (char *)"\n" "Lattice_onChange(Lattice self)\n" "\n" @@ -136830,6 +137035,8 @@ static PyMethodDef SwigMethods[] = { "Lattice LatticeUtils::CreateFCCLattice(double lattice_constant, const ILatticeOrientation &orientation)\n" "\n" ""}, + { (char *)"CreateHCPLattice", _wrap_CreateHCPLattice, METH_VARARGS, (char *)"CreateHCPLattice(double a, double c, ILatticeOrientation orientation) -> Lattice"}, + { (char *)"CreateBCTLattice", _wrap_CreateBCTLattice, METH_VARARGS, (char *)"CreateBCTLattice(double a, double c, ILatticeOrientation orientation) -> Lattice"}, { (char *)"new_Lattice1DParameters", _wrap_new_Lattice1DParameters, METH_VARARGS, (char *)"\n" "Lattice1DParameters()\n" "new_Lattice1DParameters(double length, double xi) -> Lattice1DParameters\n"