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"