diff --git a/CMakeLists.txt b/CMakeLists.txt index ed44d69..bcd64b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -233,6 +233,9 @@ IF (MSVC) ${CMAKE_THREAD_LIBS_INIT} ws2_32.lib ) ELSEIF (UNIX) + #IF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + # set_target_properties(uProbeX PROPERTIES MACOSX_BUNDLE TRUE) + #ENDIF() set_target_properties(uProbeX PROPERTIES COMPILE_FLAGS "-O3") target_link_libraries (uProbeX PRIVATE diff --git a/cmake/FindNetCDF.cmake b/cmake/FindNetCDF.cmake deleted file mode 100644 index ce4f76c..0000000 --- a/cmake/FindNetCDF.cmake +++ /dev/null @@ -1,119 +0,0 @@ -# - Find NetCDF -# Find the native NetCDF includes and library -# -# NETCDF_INCLUDE_DIR - user modifiable choice of where netcdf headers are -# NETCDF_LIBRARY - user modifiable choice of where netcdf libraries are -# -# Your package can require certain interfaces to be FOUND by setting these -# -# NETCDF_CXX - require the C++ interface and link the C++ library -# NETCDF_F77 - require the F77 interface and link the fortran library -# NETCDF_F90 - require the F90 interface and link the fortran library -# -# Or equivalently by calling FindNetCDF with a COMPONENTS argument containing one or -# more of "CXX;F77;F90". -# -# When interfaces are requested the user has access to interface specific hints: -# -# NETCDF_${LANG}_INCLUDE_DIR - where to search for interface header files -# NETCDF_${LANG}_LIBRARY - where to search for interface libraries -# -# This module returns these variables for the rest of the project to use. -# -# NETCDF_FOUND - True if NetCDF found including required interfaces (see below) -# NETCDF_LIBRARIES - All netcdf related libraries. -# NETCDF_INCLUDE_DIRS - All directories to include. -# NETCDF_HAS_INTERFACES - Whether requested interfaces were found or not. -# NETCDF_${LANG}_INCLUDE_DIRS/NETCDF_${LANG}_LIBRARIES - C/C++/F70/F90 only interface -# -# Normal usage would be: -# set (NETCDF_F90 "YES") -# find_package (NetCDF REQUIRED) -# target_link_libraries (uses_everthing ${NETCDF_LIBRARIES}) -# target_link_libraries (only_uses_f90 ${NETCDF_F90_LIBRARIES}) - -#search starting from user editable cache var -if (NETCDF_INCLUDE_DIR AND NETCDF_LIBRARY) - # Already in cache, be silent - set (NETCDF_FIND_QUIETLY TRUE) -endif () - -set(USE_DEFAULT_PATHS "NO_DEFAULT_PATH") -if(NETCDF_USE_DEFAULT_PATHS) - set(USE_DEFAULT_PATHS "") -endif() - -find_path (NETCDF_INCLUDE_DIR netcdf.h - PATHS "${NETCDF_DIR}/include") -mark_as_advanced (NETCDF_INCLUDE_DIR) -set (NETCDF_C_INCLUDE_DIRS ${NETCDF_INCLUDE_DIR}) - -find_library (NETCDF_LIBRARY NAMES netcdf - PATHS "${NETCDF_DIR}/lib" - HINTS "${NETCDF_INCLUDE_DIR}/../lib") -mark_as_advanced (NETCDF_LIBRARY) - -set (NETCDF_C_LIBRARIES ${NETCDF_LIBRARY}) - -#start finding requested language components -set (NetCDF_libs "") -set (NetCDF_includes "${NETCDF_INCLUDE_DIR}") - -get_filename_component (NetCDF_lib_dirs "${NETCDF_LIBRARY}" PATH) -set (NETCDF_HAS_INTERFACES "YES") # will be set to NO if we're missing any interfaces - -macro (NetCDF_check_interface lang header libs) - if (NETCDF_${lang}) - #search starting from user modifiable cache var - find_path (NETCDF_${lang}_INCLUDE_DIR NAMES ${header} - HINTS "${NETCDF_INCLUDE_DIR}" - HINTS "${NETCDF_${lang}_ROOT}/include" - ${USE_DEFAULT_PATHS}) - - find_library (NETCDF_${lang}_LIBRARY NAMES ${libs} - HINTS "${NetCDF_lib_dirs}" - HINTS "${NETCDF_${lang}_ROOT}/lib" - ${USE_DEFAULT_PATHS}) - - mark_as_advanced (NETCDF_${lang}_INCLUDE_DIR NETCDF_${lang}_LIBRARY) - - #export to internal varS that rest of project can use directly - set (NETCDF_${lang}_LIBRARIES ${NETCDF_${lang}_LIBRARY}) - set (NETCDF_${lang}_INCLUDE_DIRS ${NETCDF_${lang}_INCLUDE_DIR}) - - if (NETCDF_${lang}_INCLUDE_DIR AND NETCDF_${lang}_LIBRARY) - list (APPEND NetCDF_libs ${NETCDF_${lang}_LIBRARY}) - list (APPEND NetCDF_includes ${NETCDF_${lang}_INCLUDE_DIR}) - else () - set (NETCDF_HAS_INTERFACES "NO") - message (STATUS "Failed to find NetCDF interface for ${lang}") - endif () - endif () -endmacro () - -list (FIND NetCDF_FIND_COMPONENTS "CXX" _nextcomp) -if (_nextcomp GREATER -1) - set (NETCDF_CXX 1) -endif () -list (FIND NetCDF_FIND_COMPONENTS "F77" _nextcomp) -if (_nextcomp GREATER -1) - set (NETCDF_F77 1) -endif () -list (FIND NetCDF_FIND_COMPONENTS "F90" _nextcomp) -if (_nextcomp GREATER -1) - set (NETCDF_F90 1) -endif () -NetCDF_check_interface (CXX netcdfcpp.h netcdf_c++) -NetCDF_check_interface (F77 netcdf.inc netcdff) -NetCDF_check_interface (F90 netcdf.mod netcdff) - -#export accumulated results to internal varS that rest of project can depend on -list (APPEND NetCDF_libs "${NETCDF_C_LIBRARIES}") -set (NETCDF_LIBRARIES ${NetCDF_libs}) -set (NETCDF_INCLUDE_DIRS ${NetCDF_includes}) - -# handle the QUIETLY and REQUIRED arguments and set NETCDF_FOUND to TRUE if -# all listed variables are TRUE -include (FindPackageHandleStandardArgs) -find_package_handle_standard_args (NetCDF - DEFAULT_MSG NETCDF_LIBRARIES NETCDF_INCLUDE_DIRS NETCDF_HAS_INTERFACES) diff --git a/cmake/linux/FindZeroMQ.cmake b/cmake/linux/FindZeroMQ.cmake deleted file mode 100644 index 091357f..0000000 --- a/cmake/linux/FindZeroMQ.cmake +++ /dev/null @@ -1,137 +0,0 @@ -##============================================================================= -## -## Copyright (c) Kitware, Inc. -## All rights reserved. -## See LICENSE.txt for details. -## -## This software is distributed WITHOUT ANY WARRANTY; without even -## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR -## PURPOSE. See the above copyright notice for more information. -## -##============================================================================= -# - Try to find ZeroMQ headers and libraries -# -# Usage of this module as follows: -# -# find_package(ZeroMQ) -# -# Variables used by this module, they can change the default behaviour and need -# to be set before calling find_package: -# -# ZeroMQ_ROOT_DIR Set this variable to the root installation of -# ZeroMQ if the module has problems finding -# the proper installation path. -# -# Variables defined by this module: -# -# ZeroMQ_FOUND System has ZeroMQ libs/headers -# ZeroMQ_LIBRARIES The ZeroMQ libraries -# ZeroMQ_INCLUDE_DIR The location of ZeroMQ headers -# ZeroMQ_VERSION The version of ZeroMQ - -find_path(ZeroMQ_ROOT_DIR - NAMES include/zmq.h - ) - -if(MSVC) - - set(_zmq_TOOLSET) - list(APPEND _zmq_TOOLSET "-v150") - list(APPEND _zmq_TOOLSET "-v141") - list(APPEND _zmq_TOOLSET "-v140") - - - set(_zmq_versions - "4_2_3" - "4_1_5" "4_1_4" "4_1_3" "4_1_2" "4_1_1" "4_1_0") - - set(_zmq_release_names) - set(_zmq_debug_names) - foreach( toolset ${_zmq_TOOLSET}) - foreach( ver ${_zmq_versions}) - find_library(ZeroMQ_LIBRARY_RELEASE - NAMES "libzmq${toolset}-mt-${ver}" - PATHS ${ZeroMQ_ROOT_DIR}/bin/Release - ${ZeroMQ_ROOT_DIR}/lib/Release - ${ZeroMQ_ROOT_DIR}/build/lib/Release - ) - IF(ZeroMQ_LIBRARY_RELEASE) - break() - ENDIF() - endforeach() - endforeach() - foreach( toolset ${_zmq_TOOLSET}) - foreach( ver ${_zmq_versions}) - find_library(ZeroMQ_LIBRARY_DEBUG - NAMES "libzmq${toolset}-mt-gd-${ver}" - PATHS ${ZeroMQ_ROOT_DIR}/bin/Debug - ${ZeroMQ_ROOT_DIR}/lib/Debug - ${ZeroMQ_ROOT_DIR}/build/lib/Debug - ) - IF(ZeroMQ_LIBRARY_DEBUG) - break() - ENDIF() - endforeach() - endforeach() - - if(ZeroMQ_LIBRARY_RELEASE AND ZeroMQ_LIBRARY_DEBUG) - set(ZeroMQ_LIBRARY - debug ${ZeroMQ_LIBRARY_DEBUG} - optimized ${ZeroMQ_LIBRARY_RELEASE} - ) - elseif(ZeroMQ_LIBRARY_RELEASE) - set(ZeroMQ_LIBRARY ${ZeroMQ_LIBRARY_RELEASE}) - elseif(ZeroMQ_LIBRARY_DEBUG) - set(ZeroMQ_LIBRARY ${ZeroMQ_LIBRARY_DEBUG}) - endif() - -else() - find_library(ZeroMQ_LIBRARY - NAMES zmq libzmq - HINTS ${ZeroMQ_ROOT_DIR}/lib - ) -endif() - -find_path(ZeroMQ_INCLUDE_DIR - NAMES zmq.h - HINTS ${ZeroMQ_ROOT_DIR}/include - ) - -function(extract_version_value value_name file_name value) - file(STRINGS ${file_name} val REGEX "${value_name} .") - string(FIND ${val} " " last REVERSE) - string(SUBSTRING ${val} ${last} -1 val) - string(STRIP ${val} val) - set(${value} ${val} PARENT_SCOPE) -endfunction(extract_version_value) -if(ZeroMQ_INCLUDE_DIR) - extract_version_value("ZMQ_VERSION_MAJOR" ${ZeroMQ_INCLUDE_DIR}/zmq.h MAJOR) - extract_version_value("ZMQ_VERSION_MINOR" ${ZeroMQ_INCLUDE_DIR}/zmq.h MINOR) - extract_version_value("ZMQ_VERSION_PATCH" ${ZeroMQ_INCLUDE_DIR}/zmq.h PATCH) -endif() -set(ZeroMQ_VER "${MAJOR}.${MINOR}.${PATCH}") - -#We are using the 2.8.10 signature of find_package_handle_standard_args, -#as that is the version that ParaView 5.1 && VTK 6/7 ship, and inject -#into the CMake module path. This allows our FindModule to work with -#projects that include VTK/ParaView before searching for Remus -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args( - ZeroMQ - REQUIRED_VARS ZeroMQ_LIBRARY ZeroMQ_INCLUDE_DIR - VERSION_VAR ZeroMQ_VER - ) - -set(ZeroMQ_FOUND ${ZEROMQ_FOUND}) -set(ZeroMQ_INCLUDE_DIRS ${ZeroMQ_INCLUDE_DIR}) -set(ZeroMQ_LIBRARIES ${ZeroMQ_LIBRARY}) -set(ZeroMQ_VERSION ${ZeroMQ_VER}) - -mark_as_advanced( -# ZeroMQ_ROOT_DIR - ZeroMQ_LIBRARY - ZeroMQ_LIBRARY_DEBUG - ZeroMQ_LIBRARY_RELEASE - ZeroMQ_INCLUDE_DIR - ZeroMQ_VERSION - ) diff --git a/src/core/uProbeX.cpp b/src/core/uProbeX.cpp index fc5d5e7..34a0865 100644 --- a/src/core/uProbeX.cpp +++ b/src/core/uProbeX.cpp @@ -230,6 +230,15 @@ void uProbeX::createMenuBar() connect(m_menuFile, SIGNAL(aboutToShow()), this, SLOT(menuBarEnable())); + // Batch menu + //m_menuBatch = new QMenu(tr("Batch Processing")); + //action = m_menuBatch->addAction("Per Pixel Processing"); + //connect(action, SIGNAL(triggered()), this, SLOT(perPixel())); + //action = "Export Images" + //action = "Roi Stats" + //m_menu->addMenu(m_menuBatch); + + // Stream menu m_menuStream = new QMenu(tr("Live Stream")); action = m_menuStream->addAction("Open Live Stream Viewer"); diff --git a/src/core/uProbeX.h b/src/core/uProbeX.h index 95cc709..e226b47 100644 --- a/src/core/uProbeX.h +++ b/src/core/uProbeX.h @@ -280,6 +280,8 @@ private slots: */ QMenu* m_menuStream; + QMenu* m_menuBatch; + /** * @brief Help menu */ diff --git a/src/gstar/Annotation/RoiMaskGraphicsItem.cpp b/src/gstar/Annotation/RoiMaskGraphicsItem.cpp index 2132edb..68b3e6f 100644 --- a/src/gstar/Annotation/RoiMaskGraphicsItem.cpp +++ b/src/gstar/Annotation/RoiMaskGraphicsItem.cpp @@ -104,6 +104,19 @@ RoiMaskGraphicsItem::RoiMaskGraphicsItem(QString name, QColor color, int alpha, { _mask->setPixelColor(itr.first, itr.second, color); } + bool found_name = false; + for (const auto& itr : m_data) + { + if (itr->getName() == DEF_STR_DISPLAY_NAME) + { + itr->setValue(name); + found_name = true; + } + } + if(false == found_name) + { + appendProperty(new AnnotationProperty(DEF_STR_DISPLAY_NAME, name)); + } } diff --git a/src/gstar/CountsStatsTransformer.cpp b/src/gstar/CountsStatsTransformer.cpp index 5ebb484..8c6d2c6 100644 --- a/src/gstar/CountsStatsTransformer.cpp +++ b/src/gstar/CountsStatsTransformer.cpp @@ -73,7 +73,7 @@ void CountsStatsTransformer::setCounts(const data_struct::ArrayXXr& count _stdev += pow((counts(y,x) - _avg), 2); } } - _stdev = sqrtf(_stdev / cnts.size()); + _stdev = sqrtf(_stdev / (float)cnts.size()); std::sort(cnts.begin(), cnts.end(), [](float const& t1, float const& t2) { return t1 < t2; }); int idx = cnts.size() / 2; diff --git a/src/mvc/BatchRoiFitWidget.cpp b/src/mvc/BatchRoiFitWidget.cpp index b83f1f8..83a3d69 100644 --- a/src/mvc/BatchRoiFitWidget.cpp +++ b/src/mvc/BatchRoiFitWidget.cpp @@ -53,9 +53,9 @@ void BatchRoiFitWidget::createLayout() _le_detectors = new QLineEdit("0,1,2,3,4,5,6"); _cb_opt_method = new QComboBox(); + _cb_opt_method->addItem(STR_HYBRID_MP_FIT); _cb_opt_method->addItem(STR_LM_FIT); _cb_opt_method->addItem(STR_MP_FIT); - _cb_opt_method->addItem(STR_HYBRID_MP_FIT); connect(_cb_opt_method, &QComboBox::currentTextChanged, this, &BatchRoiFitWidget::optimizer_changed); _file_list_model = new QStandardItemModel(); diff --git a/src/mvc/FileTabWidget.cpp b/src/mvc/FileTabWidget.cpp index 9739a7c..5db09be 100644 --- a/src/mvc/FileTabWidget.cpp +++ b/src/mvc/FileTabWidget.cpp @@ -12,7 +12,8 @@ #include #include #include - +#include +#include "core/defines.h" /*---------------------------------------------------------------------------*/ FileTabWidget::FileTabWidget(QWidget* parent) : QWidget(parent) @@ -28,13 +29,14 @@ FileTabWidget::FileTabWidget(QWidget* parent) : QWidget(parent) _action_refresh = _contextMenu->addAction("Refresh"); connect(_action_refresh, SIGNAL(triggered()), this, SIGNAL(onRefresh())); - _file_list_model = new QStandardItemModel(); - _file_list_view = new QListView(); + _file_list_model = new FileTableModel(); + _file_list_view = new QTableView(); // _file_list_view->setViewMode(QListView::IconMode); _file_list_view->setModel(_file_list_model); _file_list_view->setEditTriggers(QAbstractItemView::NoEditTriggers); _file_list_view->setContextMenuPolicy(Qt::CustomContextMenu); _file_list_view->setSelectionMode(QAbstractItemView::ExtendedSelection); //MultiSelection + _file_list_view->setSortingEnabled(true); // if preferences saves on select changes loaded dataset connect(_file_list_view->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &FileTabWidget::onFileRowChange); @@ -97,8 +99,8 @@ void FileTabWidget::_gen_visible_list(QStringList *sl) { if(false == _file_list_view->isRowHidden(i)) { - QStandardItem *val = _file_list_model->item(i, 0); - sl->append(val->text()); + auto val = _file_list_model->item(i); + sl->append(val.text); } } } @@ -163,25 +165,78 @@ void FileTabWidget::unload_all() void FileTabWidget::set_file_list(const std::map& fileinfo_list) { + double divisor = 1; + switch(Preferences::inst()->getValue(STR_PRF_FILE_SIZE).toInt()) + { + case 0: + break; + case 1: + divisor = 1024; + break; + case 2: + divisor = 1024*1024; + break; + case 3: + divisor = 1024*1024*1024; + break; + default: + break; + } + _file_list_model->clear(); for(auto & itr : fileinfo_list) { - _file_list_model->appendRow(new QStandardItem(QIcon(":/images/circle_gray.png"), itr.first)); + _file_list_model->appendRow( RowData(QIcon(":/images/circle_gray.png"), itr.first, (double)itr.second.size()/divisor)); } + + _file_list_view->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents); + _file_list_view->horizontalHeader()->resizeSections(QHeaderView::Interactive); } -/*---------------------------------------------------------------------------*/ +//--------------------------------------------------------------------------- + +void FileTabWidget::set_roi_num_list(const std::map& roi_num_map) +{ + _file_list_model->update_roi_num(roi_num_map); +} + +//--------------------------------------------------------------------------- + +void FileTabWidget::set_roi_num(QString name, int val) +{ + _file_list_model->update_single_roi_num(name, val); +} + +//--------------------------------------------------------------------------- void FileTabWidget::update_file_list(const std::map& fileinfo_list) { + double divisor = 1; + switch(Preferences::inst()->getValue(STR_PRF_FILE_SIZE).toInt()) + { + case 0: + break; + case 1: + divisor = 1024; + break; + case 2: + divisor = 1024*1024; + break; + case 3: + divisor = 1024*1024*1024; + break; + default: + break; + } + int rows = _file_list_model->rowCount(); for (const auto& itr : fileinfo_list) { bool found = false; for(int i=0; iitem(i); - if (item->text() == itr.first) + auto item = _file_list_model->item(i); + if (item.text == itr.first) { found = true; break; @@ -190,9 +245,12 @@ void FileTabWidget::update_file_list(const std::map& fileinf if (false == found) { - _file_list_model->appendRow(new QStandardItem(QIcon(":/images/circle_gray.png"), itr.first)); + _file_list_model->appendRow(RowData(QIcon(":/images/circle_gray.png"), itr.first, (double)itr.second.size()/divisor)); } } + + _file_list_view->horizontalHeader()->resizeSections(QHeaderView::ResizeToContents); + _file_list_view->horizontalHeader()->resizeSections(QHeaderView::Interactive); } /*---------------------------------------------------------------------------*/ @@ -209,7 +267,7 @@ void FileTabWidget::onDoubleClickElement(const QModelIndex idx) if (_load_all_btn->isEnabled()) { QStringList sl; - sl.append(idx.data(0).toString()); + sl.append(_file_list_model->getNameAtRow(idx.row())); emit loadList(sl); } } @@ -219,6 +277,7 @@ void FileTabWidget::onDoubleClickElement(const QModelIndex idx) void FileTabWidget::setActionsAndButtonsEnabled(bool val) { _load_all_btn->setEnabled(val); + _file_list_view->setEnabled(val); _unload_all_btn->setEnabled(val); _action_load->setEnabled(val); _action_unload->setEnabled(val); @@ -242,7 +301,7 @@ void FileTabWidget::onLoadFile() for(int i =0; igetNameAtRow(idx.row())); } emit loadList(sl); } @@ -258,7 +317,7 @@ void FileTabWidget::onUnloadFile() for(int i =0; igetNameAtRow(idx.row())); } emit unloadList(sl); @@ -271,13 +330,20 @@ void FileTabWidget::filterTextChanged(const QString &filter_text) _filter_line->setText(filter_text); if(filter_text.length() > 0) { - QRegularExpression re (QRegularExpression::wildcardToRegularExpression(filter_text)); + // if not strict then prepend and append '*' + QString filter_t = filter_text; + if(false == Preferences::inst()->getValue(STR_PRF_STRICT_REGEX).toBool()) + { + filter_t.prepend('*'); + filter_t.append('*'); + } + QRegularExpression re (QRegularExpression::wildcardToRegularExpression(filter_t)); for(int i=0; i < _file_list_model->rowCount(); i++) { _file_list_view->setRowHidden(i, true); - QStandardItem *val = _file_list_model->item(i, 0); - QRegularExpressionMatchIterator j = re.globalMatch(val->text()); + auto val = _file_list_model->item(i); + QRegularExpressionMatchIterator j = re.globalMatch(val.text); if (j.hasNext()) { _file_list_view->setRowHidden(i, false); @@ -297,27 +363,7 @@ void FileTabWidget::filterTextChanged(const QString &filter_text) void FileTabWidget::loaded_file_status_changed(File_Loaded_Status status, const QString& filename) { - for(int i=0; i < _file_list_model->rowCount(); i++) - { - QStandardItem *val = _file_list_model->item(i, 0); - if(filename == val->text()) - { - switch(status) - { - case UNLOADED: - val->setIcon(QIcon(":/images/circle_gray.png")); - break; - case LOADED: - val->setIcon(QIcon(":/images/circle_green.png")); - break; - case FAILED_LOADING: - val->setIcon(QIcon(":/images/circle_red.png")); - break; - } - break; - } - } - + _file_list_model->updateStatus(status, filename); } /*---------------------------------------------------------------------------*/ @@ -351,7 +397,7 @@ void FileTabWidget::onCustomContext() for(int i =0; igetNameAtRow(idx.row())); } QAction *act = qobject_cast(sender()); QVariant v = act->data(); diff --git a/src/mvc/FileTabWidget.h b/src/mvc/FileTabWidget.h index 0c4499b..20be129 100644 --- a/src/mvc/FileTabWidget.h +++ b/src/mvc/FileTabWidget.h @@ -20,11 +20,10 @@ #include #include "FitParamsTableModel.h" #include "mvc/ComboBoxDelegate.h" +#include /*---------------------------------------------------------------------------*/ -enum File_Loaded_Status {UNLOADED, LOADED, FAILED_LOADING}; - /*---------------------------------------------------------------------------*/ class FileTabWidget : public QWidget @@ -39,6 +38,10 @@ class FileTabWidget : public QWidget void set_file_list(const std::map& fileinfo_list); + void set_roi_num_list(const std::map& roi_num_map); + + void set_roi_num(QString name, int val); + void update_file_list(const std::map& fileinfo_list); void unload_all(); @@ -103,9 +106,9 @@ public slots: void _gen_visible_list(QStringList *sl); - QListView* _file_list_view; + QTableView* _file_list_view; - QStandardItemModel* _file_list_model; + FileTableModel* _file_list_model; QMenu *_contextMenu; diff --git a/src/mvc/FileTableModel.h b/src/mvc/FileTableModel.h new file mode 100644 index 0000000..92810a3 --- /dev/null +++ b/src/mvc/FileTableModel.h @@ -0,0 +1,287 @@ +//----------------------------------------------------------------------------- + // Copyright (c) 2024, UChicago Argonne, LLC + // See LICENSE file. + //--------------------------------------------------------------------------- + +#ifndef FileTableModel_H +#define FileTableModel_H + +//--------------------------------------------------------------------------- + +#include +#include + +//--------------------------------------------------------------------------- + +enum File_Loaded_Status {UNLOADED, LOADED, FAILED_LOADING}; + +//--------------------------------------------------------------------------- +struct RowData +{ + RowData(QIcon i, QString s, double n) + { + icon = i; + text = s; + number = n; + status = UNLOADED; + number2 = 0; + } + QIcon icon; + QString text; + double number; + File_Loaded_Status status; + int number2; +}; +//--------------------------------------------------------------------------- + +class FileTableModel : public QAbstractTableModel +{ +public: + FileTableModel(QObject* parent = nullptr) : QAbstractTableModel(parent) + { + QString fs = "Size "; + switch(Preferences::inst()->getValue(STR_PRF_FILE_SIZE).toInt()) + { + case 0: + break; + case 1: + fs += "(Kb)"; + break; + case 2: + fs += "(Mb)"; + break; + case 3: + fs += "(Gb)"; + break; + default: + break; + } + _headers[0] = tr("L"); + _headers[1] = tr("Name"); + _headers[2] = fs; + _headers[3] = tr("# ROI's"); + } + //--------------------------------------------------------------------------- + int rowCount(const QModelIndex& parent = QModelIndex()) const override + { + return _data.size(); + } + + int columnCount(const QModelIndex& parent = QModelIndex()) const override + { + return 4; + } + //--------------------------------------------------------------------------- + void appendRow(const RowData& row) + { + int rown = _data.size(); + QModelIndex gIndex = index(rown, 0, QModelIndex()); + beginInsertRows(gIndex, rown, rown); + _data.append(row); + endInsertRows(); + } + //--------------------------------------------------------------------------- + void update_roi_num(const std::map& roi_num_map) + { + beginResetModel(); + for(auto &itr : _data) + { + itr.number2 = 0; + QStringList sl = itr.text.split('.'); + if(sl.size() > 0) + { + if(roi_num_map.count(sl[0]) > 0) + { + itr.number2 = roi_num_map.at(sl[0]); + } + } + } + endResetModel(); + } + //--------------------------------------------------------------------------- + void update_single_roi_num(QString name, int val) + { + QStringList s0 = name.split("."); + if(s0.size() > 0) + { + beginResetModel(); + for(auto &itr : _data) + { + QStringList sl = itr.text.split('.'); + if(sl.size() > 0) + { + if(s0[0] == sl[0]) + { + itr.number2 = val; + } + } + } + endResetModel(); + } + } + //--------------------------------------------------------------------------- + void clear() + { + _data.clear(); + } + //--------------------------------------------------------------------------- + const RowData& item(int row) + { + return _data.at(row); + } + //--------------------------------------------------------------------------- + const QString& getNameAtRow(int row) + { + if(_data.size() > row) + { + return _data.at(row).text; + } + return ""; + } + //--------------------------------------------------------------------------- + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override + { + if (!index.isValid() || index.row() >= _data.size() || index.column() >= 4) + { + return QVariant(); + } + + const RowData& rowData = _data[index.row()]; + + if (role == Qt::DecorationRole && index.column() == 0) + { + return rowData.icon; + } + else if (role == Qt::DisplayRole) + { + switch(index.column()) + { + case 1: + return rowData.text; + case 2: + return QString::number(rowData.number, 'f', 2); + case 3: + return rowData.number2; + }; + } + return QVariant(); + } + //--------------------------------------------------------------------------- + QVariant headerData(int section, Qt::Orientation orientation, int role) const + { + // Check this is DisplayRole + if (role != Qt::DisplayRole) return QVariant(); + + // Horizontal headers + if (orientation == Qt::Horizontal) + { + if(section > 4) + { + return QVariant(); + } + else + { + return _headers[section]; + } + } + + // Return empty data + return QVariant(); + } + //--------------------------------------------------------------------------- + Qt::ItemFlags flags(const QModelIndex &index) const + { + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + } + //--------------------------------------------------------------------------- + void updateStatus(File_Loaded_Status status, const QString& filename) + { + int i=0; + for(auto &itr : _data) + { + if(filename == itr.text) + { + QModelIndex index = createIndex(i, 0, &itr); + itr.status = status; + switch(status) + { + case UNLOADED: + itr.icon = QIcon(":/images/circle_gray.png"); + emit dataChanged(index, index); + break; + case LOADED: + itr.icon = QIcon(":/images/circle_green.png"); + emit dataChanged(index, index); + break; + case FAILED_LOADING: + itr.icon = QIcon(":/images/circle_red.png"); + emit dataChanged(index, index); + break; + } + break; + } + i++; + } + } + //--------------------------------------------------------------------------- + void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override + { + if(column < 0) + { + return; + } + beginResetModel(); + std::sort(_data.begin(), _data.end(), [&](const RowData& rowA, const RowData& rowB) + { + switch (column) + { + case 0: // icon + switch(order) + { + case Qt::AscendingOrder: + return rowA.status < rowB.status; + case Qt::DescendingOrder: + return rowA.status > rowB.status; + }; + case 1: // file name + switch(order) + { + case Qt::AscendingOrder: + return rowA.text < rowB.text; + case Qt::DescendingOrder: + return rowA.text > rowB.text; + }; + //return (rowA.text.compare(rowB.text, order) == 0); + case 2: // file size + switch(order) + { + case Qt::AscendingOrder: + return rowA.number < rowB.number; + case Qt::DescendingOrder: + return rowA.number > rowB.number; + }; + case 3: // # roi's + switch(order) + { + case Qt::AscendingOrder: + return rowA.number2 < rowB.number2; + case Qt::DescendingOrder: + return rowA.number2 > rowB.number2; + }; + }; + }); + endResetModel(); + } + //--------------------------------------------------------------------------- +private: + QList _data; + + QString _headers[4]; +}; + + +//--------------------------------------------------------------------------- + +#endif /* FileTableModel.h */ + +//--------------------------------------------------------------------------- \ No newline at end of file diff --git a/src/mvc/FitElementsTableModel.cpp b/src/mvc/FitElementsTableModel.cpp index eac2ee7..eb96830 100644 --- a/src/mvc/FitElementsTableModel.cpp +++ b/src/mvc/FitElementsTableModel.cpp @@ -8,7 +8,7 @@ /*---------------------------------------------------------------------------*/ -FitElementsTableModel::FitElementsTableModel(std::string detector_element, QObject* parent) : QAbstractItemModel(parent) +FitElementsTableModel::FitElementsTableModel(std::string detector_element, QObject* parent) : QAbstractTableModel(parent) { // Initialize header data m_headers[HEADERS::SYMBOL] = tr("Symbol"); @@ -113,7 +113,7 @@ data_struct::Fit_Parameters FitElementsTableModel::getAsFitParams() { TreeItem* node = itr.second; data_struct::Fit_Element_Map* element = node->element_data; - fit_params.add_parameter(data_struct::Fit_Param(element->full_name(), node->itemData[1].toDouble(), data_struct::E_Bound_Type::FIT)); + fit_params.add_parameter(data_struct::Fit_Param(element->full_name(), 1.0e-10, 20.0, node->itemData[1].toDouble(), 0.0005, data_struct::E_Bound_Type::LIMITED_LO_HI)); } return fit_params; } diff --git a/src/mvc/FitElementsTableModel.h b/src/mvc/FitElementsTableModel.h index 89ac8ca..b5ec8f5 100644 --- a/src/mvc/FitElementsTableModel.h +++ b/src/mvc/FitElementsTableModel.h @@ -19,7 +19,7 @@ * @brief model to control the solver table */ class FitElementsTableModel -: public QAbstractItemModel +: public QAbstractTableModel { Q_OBJECT diff --git a/src/mvc/FitSpectraWidget.cpp b/src/mvc/FitSpectraWidget.cpp index 4f65874..1305bdd 100644 --- a/src/mvc/FitSpectraWidget.cpp +++ b/src/mvc/FitSpectraWidget.cpp @@ -143,7 +143,7 @@ void FitSpectraWidget::createLayout() _fit_params_table->setItemDelegateForColumn(3, npDelegate); _fit_params_table->setItemDelegateForColumn(4, npDelegate); _fit_params_table->setItemDelegateForColumn(5, npDelegate); - _fit_params_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + _fit_params_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); _fit_params_table->setContextMenuPolicy(Qt::CustomContextMenu); connect(_fit_params_table, SIGNAL(customContextMenuRequested(QPoint)), @@ -218,9 +218,9 @@ void FitSpectraWidget::createLayout() _fit_params_tab_widget->addTab(element_widget, "Fit Elements"); _cb_opttimizer = new QComboBox(); + _cb_opttimizer->addItem(STR_HYBRID_MP_FIT); _cb_opttimizer->addItem(STR_LM_FIT); _cb_opttimizer->addItem(STR_MP_FIT); - _cb_opttimizer->addItem(STR_HYBRID_MP_FIT); connect(_cb_opttimizer, &QComboBox::currentTextChanged, this, &FitSpectraWidget::optimizer_changed); _chk_auto_model = new QCheckBox("Auto Update Model"); @@ -253,6 +253,8 @@ void FitSpectraWidget::createLayout() splitter->setStretchFactor(0, 1); splitter->addWidget(tab_and_buttons_widget); + optimizer_changed(STR_HYBRID_MP_FIT); + QLayout* layout = new QVBoxLayout(); layout->addWidget(splitter); setLayout(layout); diff --git a/src/mvc/FittingDialog.cpp b/src/mvc/FittingDialog.cpp index 46b9013..9a70323 100644 --- a/src/mvc/FittingDialog.cpp +++ b/src/mvc/FittingDialog.cpp @@ -75,13 +75,13 @@ void FittingDialog::_createLayout() _fit_params_table->setItemDelegateForColumn(3, npDelegate); _fit_params_table->setItemDelegateForColumn(4, npDelegate); _fit_params_table->setItemDelegateForColumn(5, npDelegate); - _fit_params_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + _fit_params_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); _new_fit_params_table = new QTableView(); _new_fit_params_table->setModel(_new_fit_params_table_model); _new_fit_params_table->sortByColumn(0, Qt::AscendingOrder); _new_fit_params_table->setItemDelegateForColumn(2, cbDelegate); - _new_fit_params_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); + _new_fit_params_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); connect(_new_fit_params_table->verticalScrollBar(), &QAbstractSlider::valueChanged, _fit_params_table->verticalScrollBar(), &QAbstractSlider::setValue); diff --git a/src/mvc/ImageSegROIDialog.cpp b/src/mvc/ImageSegROIDialog.cpp index 4cb0af2..3206f3b 100644 --- a/src/mvc/ImageSegROIDialog.cpp +++ b/src/mvc/ImageSegROIDialog.cpp @@ -11,9 +11,11 @@ #include #include #include +//#include // out in version 4.10 //--------------------------------------------------------------------------- static const QString STR_KMEANS = QString("KMeans"); +static const QString STR_DBSCAN = QString("DBSCAN"); static const QString STR_MANUAL = QString("Manual"); const int TAB_KMEANS = 0; @@ -47,6 +49,7 @@ ImageSegRoiDialog::ImageSegRoiDialog() : QDialog() _color_map.insert({ 15, QColor(Qt::black) }); _layout_map[STR_KMEANS] = _createKMeansLayout(); + _layout_map[STR_DBSCAN] = _createDBScanLayout(); _layout_map[STR_MANUAL] = _createManualLayout(); _next_color = 0; createLayout(); @@ -293,6 +296,84 @@ QWidget* ImageSegRoiDialog::_createKMeansLayout() //--------------------------------------------------------------------------- +QWidget* ImageSegRoiDialog::_createDBScanLayout() +{ + QVBoxLayout* layout = new QVBoxLayout(); +/* + QLabel* label = new QLabel("Number of Features:"); + _km_nfeatures = new QLineEdit(); + _km_nfeatures->setValidator(new QIntValidator(0, 10, this)); + _km_nfeatures->setText("2"); + + QHBoxLayout* hlayout = new QHBoxLayout(); + hlayout->addWidget(label); + hlayout->addWidget(_km_nfeatures); + layout->addItem(hlayout); + + label = new QLabel("Term Criteria:"); + _km_TermCriteria = new QComboBox(); + _km_TermCriteria->addItem("COUNT"); + _km_TermCriteria->addItem("EPS"); + _km_TermCriteria->addItem("COUNT + EPS"); + _km_TermCriteria->setCurrentIndex(2); // default to EPS + + hlayout = new QHBoxLayout(); + hlayout->addWidget(label); + hlayout->addWidget(_km_TermCriteria); + layout->addItem(hlayout); + + label = new QLabel("Centers:"); + _km_Centers = new QComboBox(); + _km_Centers->addItem("Random"); + _km_Centers->addItem("PP"); + _km_Centers->setCurrentIndex(0); // default to Random + + hlayout = new QHBoxLayout(); + hlayout->addWidget(label); + hlayout->addWidget(_km_Centers); + layout->addItem(hlayout); + + label = new QLabel("Attempts:"); + _km_attempts = new QLineEdit(); + _km_attempts->setValidator(new QIntValidator(0, 100, this)); + _km_attempts->setText("3"); + + hlayout = new QHBoxLayout(); + hlayout->addWidget(label); + hlayout->addWidget(_km_attempts); + layout->addItem(hlayout); + + label = new QLabel("MAX_Iter"); + _km_le_MAX_ITER = new QLineEdit(); + _km_le_MAX_ITER->setValidator(new QIntValidator(0, 10000, this)); + _km_le_MAX_ITER->setText("10"); + + hlayout = new QHBoxLayout(); + hlayout->addWidget(label); + hlayout->addWidget(_km_le_MAX_ITER); + layout->addItem(hlayout); + + label = new QLabel("Epsilon"); + _km_le_epsilon = new QLineEdit(); + _km_le_epsilon->setValidator(new QDoubleValidator()); + _km_le_epsilon->setText("1.0"); + + hlayout = new QHBoxLayout(); + hlayout->addWidget(label); + hlayout->addWidget(_km_le_epsilon); + layout->addItem(hlayout); + + _runBtn = new QPushButton("Run"); + connect(_runBtn, SIGNAL(pressed()), this, SLOT(onRun())); + layout->addWidget(_runBtn); +*/ + QWidget* widget = new QWidget(); + widget->setLayout(layout); + return widget; +} + +//--------------------------------------------------------------------------- + QWidget* ImageSegRoiDialog::_createManualLayout() { QHBoxLayout* hlayout; @@ -349,6 +430,7 @@ void ImageSegRoiDialog::createLayout() { _techTabs = new QTabWidget(); _techTabs->addTab(_layout_map[STR_KMEANS], STR_KMEANS); + _techTabs->addTab(_layout_map[STR_DBSCAN], STR_DBSCAN); _techTabs->addTab(_layout_map[STR_MANUAL], STR_MANUAL); _techTabs->setEnabled(false); connect(_techTabs, &QTabWidget::currentChanged, this, &ImageSegRoiDialog::onTabChanged); @@ -458,7 +540,7 @@ void ImageSegRoiDialog::onRun() } catch (std::exception& e) { - QMessageBox::critical(nullptr, "PythonRegionCaller Error", e.what()); + QMessageBox::critical(nullptr, "ImageSegROIDialog Error", e.what()); _acceptBtn->setEnabled(true); return; } @@ -478,6 +560,14 @@ void ImageSegRoiDialog::onRun() _int_img_widget->addRoiMask(roi); } } + else if(_techTabs->currentIndex() == 1) // DBSCAN + { + /* + int slices=8; + bool merge_small=true; + cv::Ptr< cv::ximgproc::ScanSegment > scanSeg = cv::ximgproc::createScanSegment(int_img.cols(), int_img.rows(), 1, slices=8, merge_small); + */ + } _acceptBtn->setEnabled(true); } diff --git a/src/mvc/ImageSegROIDialog.h b/src/mvc/ImageSegROIDialog.h index cf224fd..2ad6363 100644 --- a/src/mvc/ImageSegROIDialog.h +++ b/src/mvc/ImageSegROIDialog.h @@ -94,6 +94,8 @@ private slots: QWidget* _createKMeansLayout(); + QWidget* _createDBScanLayout(); + QWidget* _createManualLayout(); private: diff --git a/src/mvc/ImageStackControlWidget.cpp b/src/mvc/ImageStackControlWidget.cpp index 37a07ef..0686608 100644 --- a/src/mvc/ImageStackControlWidget.cpp +++ b/src/mvc/ImageStackControlWidget.cpp @@ -16,6 +16,7 @@ ImageStackControlWidget::ImageStackControlWidget(QWidget* parent) : QWidget(parent) { + _model = nullptr; createLayout(); } @@ -64,6 +65,8 @@ void ImageStackControlWidget::createLayout() connect(_mapsFilsWidget, &MapsWorkspaceFilesWidget::unloadList_model, this, &ImageStackControlWidget::onUnloadList_Model); connect(_mapsFilsWidget, &MapsWorkspaceFilesWidget::datasetSelected, this, &ImageStackControlWidget::onChangeDatasetName); + connect(_imageGrid, &MapsElementsWidget::new_rois, _mapsFilsWidget, &MapsWorkspaceFilesWidget::update_roi_num); + _left_btn = new QPushButton(); _left_btn->setIcon(QIcon(":/images/previous.png")); _left_btn->setMaximumWidth(150); @@ -252,6 +255,10 @@ void ImageStackControlWidget::onLoad_Model(const QString name, MODEL_TYPE mt) } _image_name_cb->addItem(name); + if(Preferences::inst()->getValue(STR_PRF_SHOW_DATASET_ON_LOAD).toBool()) + { + _image_name_cb->setCurrentText(name); + } } } diff --git a/src/mvc/MapsElementsWidget.cpp b/src/mvc/MapsElementsWidget.cpp index e99af84..8f2148f 100644 --- a/src/mvc/MapsElementsWidget.cpp +++ b/src/mvc/MapsElementsWidget.cpp @@ -35,6 +35,7 @@ MapsElementsWidget::MapsElementsWidget(int rows, int cols, bool create_image_nav { _model = nullptr; + _roi_stats_diag = nullptr; _normalizer = nullptr; _calib_curve = nullptr; _min_contrast_perc = 0; @@ -426,11 +427,20 @@ void MapsElementsWidget::_appendRoiTab() SLOT(roiTreeDoubleClicked(const QModelIndex&))); */ //infoLayout->addWidget(m_annotationToolbar->getToolBar()); + + QHBoxLayout *roi_button_layout = new QHBoxLayout(); + QVBoxLayout* roiVbox = new QVBoxLayout(); _btn_roi_img_seg = new QPushButton("ROI Dialog"); connect(_btn_roi_img_seg, &QPushButton::released, this, &MapsElementsWidget::openImageSegDialog); - roiVbox->addWidget(_btn_roi_img_seg); + _btn_roi_stats = new QPushButton("ROI Statistics"); + connect(_btn_roi_stats, &QPushButton::released, this, &MapsElementsWidget::openRoiStatsWidget); + + roi_button_layout->addWidget(_btn_roi_img_seg); + roi_button_layout->addWidget(_btn_roi_stats); + + roiVbox->addItem(roi_button_layout); roiVbox->addWidget(m_roiTreeView); m_roiTreeTabWidget = new QWidget(this); @@ -621,6 +631,54 @@ void MapsElementsWidget::openImageSegDialog() //--------------------------------------------------------------------------- +void MapsElementsWidget::openRoiStatsWidget() +{ + if (_model != nullptr) + { + if (_roi_stats_diag == nullptr) + { + _roi_stats_diag = new RoiStatisticsWidget(); + } + _roi_stats_diag->clear_all(); + + std::string analysis_text = _cb_analysis->currentText().toStdString(); + + data_struct::Fit_Count_Dict fit_counts; + _model->getAnalyzedCounts(analysis_text, fit_counts); + std::map>* scalers = _model->getScalers(); + if (scalers != nullptr) + { + for (auto& itr : *scalers) + { + fit_counts.insert(itr); + } + } + // add any roi's that were loaded. + std::vector roi_list; + QImage i; + QColor c; + gstar::RoiMaskGraphicsItem item(i, c, 0); + if (m_treeModel != nullptr) + { + m_roiTreeModel->get_all_of_type(item.classId(), roi_list); + } + + const std::vector x_axis = _model->get_x_axis(); + const std::vector y_axis = _model->get_y_axis(); + + int xidx = x_axis.size() / 2; + int yidx = y_axis.size() / 2; + + float sq_area = ((x_axis[xidx+1] - x_axis[xidx]) * (y_axis[yidx+1] - y_axis[yidx])); + + _roi_stats_diag->setData(_model->getDir(), _model->getDatasetName(), _cb_analysis->currentText(), _cb_normalize->currentText(), sq_area, fit_counts, roi_list, _normalizer, _calib_curve); + + _roi_stats_diag->show(); + } +} + +//--------------------------------------------------------------------------- + void MapsElementsWidget::roiUpdated(gstar::RoiMaskGraphicsItem* ano, bool reload) { if (ano != nullptr && reload) @@ -807,6 +865,8 @@ void MapsElementsWidget::onSelectNormalizer(QString name) } + _scatter_plot_widget->setQuantType(name); + redrawCounts(); } @@ -868,6 +928,7 @@ void MapsElementsWidget::setModel(MapsH5Model* model) { int width = (int)m_imageViewWidget->scene()->width(); int height = (int)m_imageViewWidget->scene()->height(); + logI<< "Loading roi: "<< itr.first<<"\n"; gstar::RoiMaskGraphicsItem* roi = new gstar::RoiMaskGraphicsItem(QString(itr.first.c_str()), itr.second.color, itr.second.color_alpha, width, height, itr.second.pixel_list); insertAndSelectAnnotation(m_roiTreeModel, m_roiTreeView, m_roiSelectionModel, roi); if (itr.second.int_spec.count(_model->getDatasetName().toStdString()) > 0) @@ -1738,16 +1799,16 @@ void MapsElementsWidget::windowChanged(Qt::WindowStates oldState, void MapsElementsWidget::on_add_new_ROIs(std::vector roi_list) { - _model->clearAllMapRois(); - for (auto& itr : roi_list) + if (_model != nullptr) { - insertAndSelectAnnotation(m_roiTreeModel, m_roiTreeView, m_roiSelectionModel, itr->duplicate()); - std::vector> pixel_list; - itr->to_roi_vec(pixel_list); - - data_struct::Spectra* int_spectra = new data_struct::Spectra(); - if (_model != nullptr) + _model->clearAllMapRois(); + + for (auto& itr : roi_list) { + insertAndSelectAnnotation(m_roiTreeModel, m_roiTreeView, m_roiSelectionModel, itr->duplicate()); + std::vector> pixel_list; + itr->to_roi_vec(pixel_list); + data_struct::Spectra* int_spectra = new data_struct::Spectra(); if (io::file::HDF5_IO::inst()->load_integrated_spectra_analyzed_h5_roi(_model->getFilePath().toStdString(), int_spectra, pixel_list)) { struct Map_ROI roi(itr->getName().toStdString(), itr->getColor(), itr->alphaValue(), pixel_list, _model->getDatasetName().toStdString(), *int_spectra); @@ -1756,14 +1817,14 @@ void MapsElementsWidget::on_add_new_ROIs(std::vectorappendROISpectra(itr->getName().toStdString(), int_spectra, itr->getColor()); } } - } - if (_model != nullptr) - { + _model->saveAllRoiMaps(); + + //refresh roi's + _scatter_plot_widget->setModel(_model); + // update num rois in file widget + emit new_rois(_model->getDatasetName(), roi_list.size()); } - //refresh roi's - _scatter_plot_widget->setModel(_model); - _spectra_widget->replot_integrated_spectra(false); annoTabChanged(ROI_TAB); _img_seg_diag.clear_all_rois(); diff --git a/src/mvc/MapsElementsWidget.h b/src/mvc/MapsElementsWidget.h index e419550..9015265 100644 --- a/src/mvc/MapsElementsWidget.h +++ b/src/mvc/MapsElementsWidget.h @@ -27,6 +27,7 @@ #include #include #include +#include using gstar::AbstractGraphicsItem; /*---------------------------------------------------------------------------*/ @@ -59,7 +60,9 @@ class MapsElementsWidget MapsH5Model *getModel(){return _model;} signals: - void loaded_perc(int, int); + void loaded_perc(int, int); + + void new_rois(QString, int); public slots: @@ -81,6 +84,8 @@ public slots: void openImageSegDialog(); + void openRoiStatsWidget(); + void roiUpdated(gstar::RoiMaskGraphicsItem* ano, bool reload); void onGridDialog(); @@ -207,6 +212,8 @@ public slots: ImageSegRoiDialog _img_seg_diag; + RoiStatisticsWidget* _roi_stats_diag; + float _min_contrast_perc; float _max_contrast_perc; @@ -221,6 +228,8 @@ public slots: QPushButton* _btn_roi_img_seg; + QPushButton* _btn_roi_stats; + QDockWidget* _counts_dock; QDockWidget* _intspectra_dock; diff --git a/src/mvc/MapsH5Model.cpp b/src/mvc/MapsH5Model.cpp index 5627862..94aa23c 100644 --- a/src/mvc/MapsH5Model.cpp +++ b/src/mvc/MapsH5Model.cpp @@ -50,7 +50,7 @@ void MapsH5Model::clear_analyzed_counts() /*---------------------------------------------------------------------------*/ -void MapsH5Model::getAnalyzedCounts(std::string analysis_type, data_struct::Fit_Count_Dict& out_counts) +bool MapsH5Model::getAnalyzedCounts(std::string analysis_type, data_struct::Fit_Count_Dict& out_counts) { std::lock_guard lock(_mutex); out_counts.clear(); @@ -61,11 +61,58 @@ void MapsH5Model::getAnalyzedCounts(std::string analysis_type, data_struct::Fit_ { out_counts[itr.first] = itr.second; } + return true; + } + return false; +} + +//--------------------------------------------------------------------------- +bool MapsH5Model::getAnalyzedQuantified(std::string analysis_type, std::string quant_type, data_struct::Fit_Count_Dict& out_counts) +{ + std::lock_guard lock(_mutex); + out_counts.clear(); + std::unordered_map > *calib_map = nullptr; + if(analysis_type.length() > 0 && quant_type.length() > 0 && _analyzed_counts.count(analysis_type) > 0 && _scalers.count(quant_type) > 0) + { + if (analysis_type == STR_FIT_NNLS) + { + calib_map = &_quant_map_nnls; + } + else if(analysis_type == STR_FIT_GAUSS_MATRIX) + { + calib_map = &_quant_map_matrix; + } + else + { + return false; + } + if(calib_map->count(quant_type) > 0) + { + // get scaler quant type + auto calib = calib_map->at(quant_type).calib_curve; + auto quant_scaler = _scalers.at(quant_type); + for (const auto& itr : *(_analyzed_counts[analysis_type])) + { + if(calib.count(itr.first) > 0) + { + out_counts[itr.first] = itr.second / quant_scaler/ calib.at(itr.first); + float min_coef = out_counts.at(itr.first).minCoeff(); + out_counts[itr.first] = out_counts.at(itr.first).unaryExpr([min_coef](float v) { return std::isfinite(v) ? v : min_coef; }); + } + else + { + out_counts[itr.first] = itr.second; + } + } + return true; + } + return false; } + return false; } -/*---------------------------------------------------------------------------*/ +//--------------------------------------------------------------------------- std::vector MapsH5Model::count_names() { @@ -387,6 +434,7 @@ void MapsH5Model::loadAllRoiMaps() } } _map_rois[mroi.name] = mroi; + logI<< "Loading roi: "<< mroi.name<<"\n"; } if (resave) { diff --git a/src/mvc/MapsH5Model.h b/src/mvc/MapsH5Model.h index 64abc55..7ad4949 100644 --- a/src/mvc/MapsH5Model.h +++ b/src/mvc/MapsH5Model.h @@ -122,7 +122,9 @@ class MapsH5Model : public QObject bool is_fully_loaded() { return _is_fully_loaded; } //data_struct::Fit_Count_Dict* getAnalyzedCounts(std::string analysis_type); - void getAnalyzedCounts(std::string analysis_type, data_struct::Fit_Count_Dict& out_counts); + bool getAnalyzedCounts(std::string analysis_type, data_struct::Fit_Count_Dict& out_counts); + + bool getAnalyzedQuantified(std::string analysis_type, std::string quant_type, data_struct::Fit_Count_Dict& out_counts); //const data_struct::Spectra* getIntegratedSpectra() {return &_integrated_spectra;} void getIntegratedSpectra(data_struct::Spectra& out_spectra); diff --git a/src/mvc/MapsWorkspaceFilesWidget.cpp b/src/mvc/MapsWorkspaceFilesWidget.cpp index 5c332f3..3a126d2 100644 --- a/src/mvc/MapsWorkspaceFilesWidget.cpp +++ b/src/mvc/MapsWorkspaceFilesWidget.cpp @@ -91,17 +91,6 @@ void MapsWorkspaceFilesWidget::createLayout() _vlm_tab_widget->appendFilterHelpAction(tiff_file); _vlm_tab_widget->appendFilterHelpAction(tif_file); - _fit_params_table_model = new FitParamsTableModel(); - ComboBoxDelegate *cbDelegate = new ComboBoxDelegate(bound_types); - - /* - _fit_params_table = new QTableView(); - _fit_params_table->setModel(_fit_params_table_model); - //_fit_params_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - //_fit_params_table->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch); - _fit_params_table->sortByColumn(0, Qt::AscendingOrder); - _fit_params_table->setItemDelegateForColumn(2, cbDelegate); - */ QLayout* vlayout = new QVBoxLayout(); _tab_widget->insertTab(0, _h5_tab_widget, "Analyized Data"); @@ -122,7 +111,7 @@ void MapsWorkspaceFilesWidget::setModel(MapsWorkspaceModel *model) disconnect(_model, &MapsWorkspaceModel::doneLoadingVLM, this, &MapsWorkspaceFilesWidget::updatedVLM); disconnect(_model, &MapsWorkspaceModel::doneLoadingImgDat, this, &MapsWorkspaceFilesWidget::updatedHDF); disconnect(_model, &MapsWorkspaceModel::doneUnloading, this, &MapsWorkspaceFilesWidget::clearLists); - disconnect(_model, &MapsWorkspaceModel::newFitParamsFileLoaded, this, &MapsWorkspaceFilesWidget::loadedFitParams); + //disconnect(_model, &MapsWorkspaceModel::newFitParamsFileLoaded, this, &MapsWorkspaceFilesWidget::loadedFitParams); } _model = model; @@ -144,8 +133,9 @@ void MapsWorkspaceFilesWidget::setModel(MapsWorkspaceModel *model) connect(_model, &MapsWorkspaceModel::doneLoadingMDA, this, &MapsWorkspaceFilesWidget::updatedMDA); connect(_model, &MapsWorkspaceModel::doneLoadingVLM, this, &MapsWorkspaceFilesWidget::updatedVLM); connect(_model, &MapsWorkspaceModel::doneLoadingImgDat, this, &MapsWorkspaceFilesWidget::updatedHDF); + connect(_model, &MapsWorkspaceModel::doneLoadingROIS, this, &MapsWorkspaceFilesWidget::updateROIS); connect(_model, &MapsWorkspaceModel::doneUnloading, this, &MapsWorkspaceFilesWidget::clearLists); - connect(_model, &MapsWorkspaceModel::newFitParamsFileLoaded, this, &MapsWorkspaceFilesWidget::loadedFitParams); + //connect(_model, &MapsWorkspaceModel::newFitParamsFileLoaded, this, &MapsWorkspaceFilesWidget::loadedFitParams); connect(_h5_tab_widget, &FileTabWidget::onRefresh, _model, &MapsWorkspaceModel::reload_analyzed); connect(_vlm_tab_widget, &FileTabWidget::onRefresh, _model, &MapsWorkspaceModel::reload_vlm); connect(_mda_tab_widget, &FileTabWidget::onRefresh, _model, &MapsWorkspaceModel::reload_raw); @@ -186,20 +176,23 @@ void MapsWorkspaceFilesWidget::updatedHDF() { _h5_tab_widget->loaded_file_status_changed(File_Loaded_Status::LOADED, itr); } + _h5_tab_widget->set_roi_num_list(_model->get_roi_num_list()); } -/*---------------------------------------------------------------------------*/ +//--------------------------------------------------------------------------- -void MapsWorkspaceFilesWidget::loadedFitParams(int idx) +void MapsWorkspaceFilesWidget::updateROIS() { - if(idx == -1) //avg fit params - { - data_struct::Fit_Parameters* fit_params = _model->getFitParameters(idx); - if(fit_params != nullptr) - { - _fit_params_table_model->setFitParams(*fit_params); - } - } + _h5_tab_widget->set_roi_num_list(_model->get_roi_num_list()); + _mda_tab_widget->set_roi_num_list(_model->get_roi_num_list()); +} + +//--------------------------------------------------------------------------- + +void MapsWorkspaceFilesWidget::update_roi_num(QString name, int val) +{ + _h5_tab_widget->set_roi_num(name, val); + _mda_tab_widget->set_roi_num(name, val); } /*---------------------------------------------------------------------------*/ diff --git a/src/mvc/MapsWorkspaceFilesWidget.h b/src/mvc/MapsWorkspaceFilesWidget.h index 469ff3e..e3c044d 100644 --- a/src/mvc/MapsWorkspaceFilesWidget.h +++ b/src/mvc/MapsWorkspaceFilesWidget.h @@ -67,31 +67,33 @@ class MapsWorkspaceFilesWidget : public QWidget public slots: - void updatedMDA(); + void updatedMDA(); - void updatedVLM(); + void updatedVLM(); - void updatedHDF(); + void updatedHDF(); - void clearLists(); + void updateROIS(); - void loadedFitParams(int idx); - - void onOpenModel(const QStringList& names_list, MODEL_TYPE mt); + void update_roi_num(QString, int); - void onCloseModel(const QStringList& names_list, MODEL_TYPE mt); + void clearLists(); - void onCustomContext(const QString& context_label, const QStringList& file_list); + void onOpenModel(const QStringList& names_list, MODEL_TYPE mt); - void onPerPixelProcessList(const QStringList& file_list); + void onCloseModel(const QStringList& names_list, MODEL_TYPE mt); - void onPerPixelProcessListAnalyzed(const QStringList& file_list); - - void onBatchRoiList(const QStringList& file_list); + void onCustomContext(const QString& context_label, const QStringList& file_list); - void onProcessed_list_update(QStringList file_list); + void onPerPixelProcessList(const QStringList& file_list); - void onDatasetSelected(const QString name); + void onPerPixelProcessListAnalyzed(const QStringList& file_list); + + void onBatchRoiList(const QStringList& file_list); + + void onProcessed_list_update(QStringList file_list); + + void onDatasetSelected(const QString name); protected: @@ -114,10 +116,6 @@ public slots: MapsWorkspaceModel* _model; - QTableView* _fit_params_table; - - FitParamsTableModel* _fit_params_table_model; - PerPixelFitWidget* _per_pixel_fit_widget; BatchRoiFitWidget* _batch_roi_fit_widget; diff --git a/src/mvc/MapsWorkspaceModel.cpp b/src/mvc/MapsWorkspaceModel.cpp index 477d681..e31d3e0 100644 --- a/src/mvc/MapsWorkspaceModel.cpp +++ b/src/mvc/MapsWorkspaceModel.cpp @@ -129,7 +129,7 @@ MapsWorkspaceModel::MapsWorkspaceModel() : QObject() _vlm_suffex.append("tif"); _vlm_suffex.append("tiff"); - _all_roi_suffex.append("roi"); + _all_roi_suffex.append("r0i"); _all_region_links_suffex.append("tif"); } @@ -237,7 +237,6 @@ void MapsWorkspaceModel::load(QString filepath) case 4: _is_rois_loaded = itr.second.get(); to_delete.push_back(itr.first); - //emit doneLoadingImgDat(); break; default: to_delete.push_back(itr.first); @@ -248,9 +247,11 @@ void MapsWorkspaceModel::load(QString filepath) for (const auto& itr : to_delete) { job_queue.erase(itr); - } - + } } + // wait for all datasets to finish loading and then update roi's + _roi_files_to_num(); + emit doneLoadingROIS(); } } catch (std::string& s) @@ -295,7 +296,7 @@ void MapsWorkspaceModel::reload_vlm() void MapsWorkspaceModel::reload_roi() { _roi_fileinfo_list.clear(); - get_filesnames_in_directory(*_dir, "rois", _vlm_suffex, &_roi_fileinfo_list, check_roi, false); + get_filesnames_in_directory(*_dir, "rois", _all_roi_suffex, &_roi_fileinfo_list, check_roi, false); } /*---------------------------------------------------------------------------*/ @@ -660,4 +661,28 @@ data_struct::Fit_Element_Map_Dict* MapsWorkspaceModel::getElementToFit(i return nullptr; } -/*---------------------------------------------------------------------------*/ +//--------------------------------------------------------------------------- + +void MapsWorkspaceModel::_roi_files_to_num() +{ + for(auto itr : _roi_fileinfo_list) + { + _roi_count_map[itr.second.baseName()] = 0; + QFile roiFile(itr.second.absoluteFilePath()); + if (!roiFile.open(QIODevice::ReadOnly)) + { + continue; + } + + QJsonObject rootJson = QJsonDocument::fromJson(roiFile.readAll()).object(); + roiFile.close(); + + if (rootJson.contains(STR_MAPS_ROIS.c_str()) && rootJson[STR_MAPS_ROIS.c_str()].isArray()) + { + QJsonArray rois = rootJson[STR_MAPS_ROIS.c_str()].toArray(); + _roi_count_map[itr.second.baseName()] = rois.size(); + } + } +} + +//--------------------------------------------------------------------------- \ No newline at end of file diff --git a/src/mvc/MapsWorkspaceModel.h b/src/mvc/MapsWorkspaceModel.h index df0e0a7..848ea10 100644 --- a/src/mvc/MapsWorkspaceModel.h +++ b/src/mvc/MapsWorkspaceModel.h @@ -87,6 +87,10 @@ class MapsWorkspaceModel : public QObject const std::map& get_vlm_file_list() { return _vlm_fileinfo_list; } + const std::map& get_roi_file_list() { return _roi_fileinfo_list; } + + const std::map& get_roi_num_list() { return _roi_count_map; } + std::vector get_loaded_raw_names(); std::vector get_loaded_h5_names(); @@ -105,6 +109,8 @@ class MapsWorkspaceModel : public QObject void doneLoadingImgDat(); + void doneLoadingROIS(); + void doneLoading(); void doneUnloading(); @@ -124,6 +130,7 @@ public slots: void reload_region_link(); protected: + void _roi_files_to_num(); bool _load_fit_params(); @@ -152,6 +159,8 @@ public slots: std::map _roi_fileinfo_list; std::map _region_links_fileinfo_list; + std::map _roi_count_map; + QDir* _dir; bool _is_vlm_loaded; diff --git a/src/mvc/PerPixelOptionsWidget.h b/src/mvc/PerPixelOptionsWidget.h index 0601588..29ddc83 100644 --- a/src/mvc/PerPixelOptionsWidget.h +++ b/src/mvc/PerPixelOptionsWidget.h @@ -76,8 +76,6 @@ class PerPixelOptionsWidget : public QWidget if (_proc_matrix->isChecked()) { analysis_job.fitting_routines.push_back(data_struct::Fitting_Routines::GAUSS_MATRIX); - - analysis_job.optimizer()->set_options({ { STR_OPT_STEP, (T_real)0.1 } }); } if (_save_avg->isChecked()) diff --git a/src/mvc/RoiStatisticsWidget.cpp b/src/mvc/RoiStatisticsWidget.cpp new file mode 100644 index 0000000..cab6b69 --- /dev/null +++ b/src/mvc/RoiStatisticsWidget.cpp @@ -0,0 +1,392 @@ +/*----------------------------------------------------------------------------- + * Copyright (c) 2024, UChicago Argonne, LLC + * See LICENSE file. + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include + +//--------------------------------------------------------------------------- +enum HEADER_NAME { ROI_Name=0, MapName=1, SumCnts=2, MeanCts=3, MedianCts=4, StdDevCts=5, SumUgcm2=6, MeanUg=7, MedianUg=8, StdDevUg=9, Area=10, MinCnts=11, MinPixel=12, MaxCnts=13, MaxPixel=14, Min_ugcm2=15, Max_ugcm2=16, Num_Spectra=17, TotalConcentrationCts=18, TotalConcentrationUg=19, TotalContentCts=20, TotalContentUg=21 }; +//--------------------------------------------------------------------------- + +RoiStatisticsWidget::RoiStatisticsWidget() : QWidget() +{ + _base_header = { "ROI Name", "Map Name", "Sum Cnt/s", "Mean Cts/s", "Median Cts/s", "Std Dev Cts/s", "Sum ug/cm2", "Mean ug/cm2", "Median ug/cm2", "Std Dev ug/cm2", "Area", "Min Cnts/s", "Mix Pixel(x|y)", "Max Cnts/s", "Max Pixel (x|y)", "Min ug/cm2", "Max ug/cm2", "Num Spectra", "Total Concentration Cts/s (mean x # of pixels)", "Total Concentration ug/cm2", "Total Content Cts/s(mean x scan area with unit of femtogram 10^-15)", "Total Content ug/cm2" }; + + //create save ordered vector by element Z number with K , L, M lines + for (std::string el_name : data_struct::Element_Symbols) + { + _element_lines_list.push_back(el_name); + } + for (std::string el_name : data_struct::Element_Symbols) + { + _element_lines_list.push_back(el_name + "_L"); + } + for (std::string el_name : data_struct::Element_Symbols) + { + _element_lines_list.push_back(el_name + "_M"); + } + + _final_counts_to_add_before_scalers.push_back(STR_COHERENT_SCT_AMPLITUDE); + _final_counts_to_add_before_scalers.push_back(STR_COMPTON_AMPLITUDE); + _final_counts_to_add_before_scalers.push_back(STR_SUM_ELASTIC_INELASTIC_AMP); + _final_counts_to_add_before_scalers.push_back(STR_TOTAL_FLUORESCENCE_YIELD); + _final_counts_to_add_before_scalers.push_back(STR_NUM_ITR); + _final_counts_to_add_before_scalers.push_back(STR_RESIDUAL); + + _scalers_to_add_first_list.push_back(STR_SR_CURRENT); + _scalers_to_add_first_list.push_back(STR_US_IC); + _scalers_to_add_first_list.push_back(STR_DS_IC); + _scalers_to_add_first_list.push_back(STR_ELT); + _scalers_to_add_first_list.push_back(STR_ELAPSED_LIVE_TIME); + _scalers_to_add_first_list.push_back(STR_ERT); + _scalers_to_add_first_list.push_back(STR_ELAPSED_REAL_TIME); + _scalers_to_add_first_list.push_back(STR_INPUT_COUNTS); + _scalers_to_add_first_list.push_back(STR_ICR); + _scalers_to_add_first_list.push_back("INCNT"); + _scalers_to_add_first_list.push_back(STR_OUTPUT_COUNTS); + _scalers_to_add_first_list.push_back(STR_OCR); + _scalers_to_add_first_list.push_back("OUTCNT"); + _scalers_to_add_first_list.push_back(STR_DEAD_TIME); + _scalers_to_add_first_list.push_back("abs_cfg"); + _scalers_to_add_first_list.push_back("abs_ic"); + _scalers_to_add_first_list.push_back("H_dpc_cfg"); + _scalers_to_add_first_list.push_back("V_dpc_cfg"); + _scalers_to_add_first_list.push_back("DPC1_IC"); + _scalers_to_add_first_list.push_back("DPC2_IC"); + _scalers_to_add_first_list.push_back("dia1_dpc_cfg"); + _scalers_to_add_first_list.push_back("dia2_dpc_cfg"); + _scalers_to_add_first_list.push_back("CFG_1"); + _scalers_to_add_first_list.push_back(STR_CFG_2); + _scalers_to_add_first_list.push_back(STR_CFG_3); + _scalers_to_add_first_list.push_back(STR_CFG_4); + _scalers_to_add_first_list.push_back(STR_CFG_5); + _scalers_to_add_first_list.push_back("CFG_6"); + _scalers_to_add_first_list.push_back("CFG_7"); + _scalers_to_add_first_list.push_back("CFG_8"); + _scalers_to_add_first_list.push_back("CFG_9"); + + + _createLayout(); + +} + +//--------------------------------------------------------------------------- + +RoiStatisticsWidget::~RoiStatisticsWidget() +{ + +} + +//--------------------------------------------------------------------------- + +void RoiStatisticsWidget::_insert_item(QString roiName, + QString imgName, + float sq_area, + const data_struct::ArrayXXr& img, + const std::vector>& roi_pixels, + int i, + data_struct::ArrayXXr* normalizer, + Calibration_curve* calib_curve) +{ + _table_widget->setItem(i, ROI_Name, new QTableWidgetItem(roiName)); + _table_widget->setItem(i, MapName, new QTableWidgetItem(imgName)); + double sum_cts = 0.0; + double min_cts = std::numeric_limits::max(); + double max_cts = std::numeric_limits::min(); + double std_dev_cts = 0.0; + double median_cts = 0.0; + double sum_ugcm2 = 0.0; + double min_ug = std::numeric_limits::max(); + double max_ug = std::numeric_limits::min(); + double std_dev_ug = 0.0; + double median_ug = 0.0; + double area = sq_area * roi_pixels.size(); + std::pair min_pixel; + std::pair max_pixel; + Eigen::ArrayXf cts_arr(roi_pixels.size()); + Eigen::ArrayXf ug_arr(roi_pixels.size()); + int j = 0; + double calib_val = 1.0; + bool hasNorm = false; + if (calib_curve != nullptr && normalizer != nullptr) + { + if( calib_curve->calib_curve.count(imgName.toStdString()) > 0 ) + { + calib_val = static_cast(calib_curve->calib_curve.at(imgName.toStdString())); + hasNorm = true; + } + } + + for(auto pitr : roi_pixels) + { + double val = img(pitr.second, pitr.first); + sum_cts += val; + min_cts = std::min(val,min_cts); + if(min_cts == val) + { + min_pixel = pitr; + } + max_cts = std::max(val,max_cts); + if(max_cts == val) + { + max_pixel = pitr; + } + cts_arr[j] = val; + if(hasNorm) + { + double ug = (val / (*normalizer)(pitr.second, pitr.first) / calib_val); + sum_ugcm2 += ug; + min_ug = std::min(ug,min_ug); + max_ug = std::max(ug,max_ug); + ug_arr[j] = ug; + } + j++; + } + double mean_cts = sum_cts / (double)roi_pixels.size(); + double mean_ug = sum_ugcm2 / (double)roi_pixels.size(); + for(auto pitr : roi_pixels) + { + double val = img(pitr.second, pitr.first); + std_dev_cts += pow((val - mean_cts), 2); + if(hasNorm) + { + double ug = (val / (*normalizer)(pitr.second, pitr.first) / calib_val); + std_dev_ug += pow((ug - mean_ug), 2); + } + } + std_dev_cts = sqrtf(std_dev_cts / (double)roi_pixels.size()); + if(hasNorm) + { + std_dev_ug = sqrtf(std_dev_ug / (double)roi_pixels.size()); + std::sort(ug_arr.begin(), ug_arr.end(), [](float const& t1, float const& t2) { return t1 < t2; }); + int idx = ug_arr.size() / 2; + median_ug = ug_arr(idx); + } + + std::sort(cts_arr.begin(), cts_arr.end(), [](float const& t1, float const& t2) { return t1 < t2; }); + int idx = cts_arr.size() / 2; + median_cts = cts_arr(idx); + + QString str_min_pixel = QString::number(min_pixel.second) + " | " + QString::number(min_pixel.first); + QString str_max_pixel = QString::number(max_pixel.second) + " | " + QString::number(max_pixel.first); + _table_widget->setItem(i, SumCnts, new QTableWidgetItem(QString::number(sum_cts))); + _table_widget->setItem(i, MinCnts, new QTableWidgetItem(QString::number(min_cts))); + _table_widget->setItem(i, MinPixel, new QTableWidgetItem(str_min_pixel)); + _table_widget->setItem(i, MaxCnts, new QTableWidgetItem(QString::number(max_cts))); + _table_widget->setItem(i, MaxPixel, new QTableWidgetItem(str_max_pixel)); + _table_widget->setItem(i, MeanCts, new QTableWidgetItem(QString::number(mean_cts))); + _table_widget->setItem(i, MedianCts, new QTableWidgetItem(QString::number(median_cts))); + _table_widget->setItem(i, StdDevCts, new QTableWidgetItem(QString::number(std_dev_cts))); + _table_widget->setItem(i, Num_Spectra, new QTableWidgetItem(QString::number(roi_pixels.size()))); + + _table_widget->setItem(i, Area, new QTableWidgetItem(QString::number(area))); + _table_widget->setItem(i, TotalContentCts, new QTableWidgetItem(QString::number(area*mean_cts))); + _table_widget->setItem(i, TotalConcentrationCts, new QTableWidgetItem(QString::number(mean_cts * (double)roi_pixels.size()))); + + if(hasNorm) + { + _table_widget->setItem(i, SumUgcm2, new QTableWidgetItem(QString::number(sum_ugcm2))); + _table_widget->setItem(i, Min_ugcm2, new QTableWidgetItem(QString::number(min_ug))); + _table_widget->setItem(i, Max_ugcm2, new QTableWidgetItem(QString::number(max_ug))); + _table_widget->setItem(i, MeanUg, new QTableWidgetItem(QString::number(mean_ug))); + _table_widget->setItem(i, MedianUg, new QTableWidgetItem(QString::number(median_ug))); + _table_widget->setItem(i, StdDevUg, new QTableWidgetItem(QString::number(std_dev_ug))); + _table_widget->setItem(i, TotalContentUg, new QTableWidgetItem(QString::number(area*mean_ug))); + _table_widget->setItem(i, TotalConcentrationUg, new QTableWidgetItem(QString::number(mean_ug * (double)roi_pixels.size()))); + } + else + { + _table_widget->setItem(i, SumUgcm2, new QTableWidgetItem(" ")); + _table_widget->setItem(i, Min_ugcm2, new QTableWidgetItem(" ")); + _table_widget->setItem(i, Max_ugcm2, new QTableWidgetItem(" ")); + _table_widget->setItem(i, MeanUg, new QTableWidgetItem(" ")); + _table_widget->setItem(i, MedianUg, new QTableWidgetItem(" ")); + _table_widget->setItem(i, StdDevUg, new QTableWidgetItem(" ")); + } +} + +//--------------------------------------------------------------------------- + +void RoiStatisticsWidget::setData(QDir model_dir, + QString dataset_name, + QString fitting_name, + QString normalizer_name, + float sq_area, + std::unordered_map>& img_data, + std::vector& roi_list, + data_struct::ArrayXXr* normalizer, + Calibration_curve* calib_curve) +{ + + int total = img_data.size() * roi_list.size(); + _table_widget->setRowCount(total); + + std::unordered_map done_map; + + _export_dir = model_dir; + _export_dir.cdUp(); + _export_dir.cdUp(); + _export_dir.cd("output"); + + + QString filename = "roi_export_" + dataset_name + "_" + fitting_name + "_"; + if(normalizer != nullptr) + { + filename += normalizer_name + "_"; + } + + QDateTime date = QDateTime::currentDateTime(); + QString formattedTime = date.toString("yyyy.MM.dd_hh.mm.ss"); + filename += formattedTime + ".csv"; + + _str_export_filename = _export_dir.absolutePath() + QDir::separator() + filename; + + int i = 0; + for (auto roi_itr : roi_list) + { + std::vector> roi_pixels; + roi_itr->to_roi_vec(roi_pixels); + // insert in z order + for (auto itr : _element_lines_list) + { + if (img_data.count(itr) > 0) + { + _insert_item(roi_itr->getName(), QString::fromLatin1(itr.c_str(), itr.length()), sq_area, img_data.at(itr), roi_pixels, i, normalizer, calib_curve); + done_map[itr] = 1; + i++; + } + + } + // add end of element list that are not elements + for (auto itr : _final_counts_to_add_before_scalers) + { + if (img_data.count(itr) > 0) + { + _insert_item(roi_itr->getName(), QString::fromLatin1(itr.c_str(), itr.length()), sq_area, img_data.at(itr), roi_pixels, i, normalizer, calib_curve); + done_map[itr] = 1; + i++; + } + } + // add scalers in certain order + for (auto itr : _scalers_to_add_first_list) + { + if (img_data.count(itr) > 0) + { + _insert_item(roi_itr->getName(), QString::fromLatin1(itr.c_str(), itr.length()),sq_area, img_data.at(itr), roi_pixels, i, normalizer, calib_curve); + done_map[itr] = 1; + i++; + } + } + // add rest of scalers + for (auto itr : img_data) + { + if(done_map.count(itr.first) == 0) + { + _insert_item(roi_itr->getName(), QString::fromLatin1(itr.first.c_str(), itr.first.length()), sq_area, itr.second, roi_pixels, i, normalizer, calib_curve); + i++; + } + } + } +} + +//--------------------------------------------------------------------------- + +void RoiStatisticsWidget::_createLayout() +{ + + _table_widget = new QTableWidget(1, _base_header.count()); + _table_widget->setHorizontalHeaderLabels(_base_header); + + _btn_export = new QPushButton("Export"); + _btn_close = new QPushButton("Close"); + connect(_btn_export, &QPushButton::pressed, this, &RoiStatisticsWidget::onExport); + connect(_btn_close, &QPushButton::pressed, this, &RoiStatisticsWidget::onClose); + + QVBoxLayout* mainLayout = new QVBoxLayout; + QHBoxLayout* buttonLayout = new QHBoxLayout; + + buttonLayout->addWidget(_btn_export); + buttonLayout->addWidget(_btn_close); + + mainLayout->addWidget(_table_widget); + mainLayout->addItem(buttonLayout); + + setLayout(mainLayout); + + setWindowTitle("ROI Stats"); + + QRect rec = QGuiApplication::screens()[0]->geometry(); + int height1 = rec.height() - 20; + int width1 = rec.width() - 20; + resize(width1,height1); + +} + +//--------------------------------------------------------------------------- + +void RoiStatisticsWidget::onExport() +{ + QFile file(_str_export_filename); + if (!file.open(QIODevice::WriteOnly)) + { + logE<< "Could not open file for writing:"<< _str_export_filename.toStdString()<<"\n"; + return; + } + + QTextStream out(&file); + + // Write header row + QStringList headers = _base_header; + out << headers.join(",") << "\n"; + + // Write data rows + for (int i = 0; i < _table_widget->rowCount(); ++i) + { + QStringList rowData; + for (int j = 0; j < _table_widget->columnCount(); ++j) + { + QTableWidgetItem* item = _table_widget->item(i, j); + if (item) + { + rowData.append(item->text()); + } + else + { + rowData.append(""); + } + } + out << rowData.join(",") << "\n"; + } + + file.close(); + + if (false == QDesktopServices::openUrl(QUrl::fromLocalFile(_export_dir.absolutePath()))) + { + logW << "Failed to open dir " << _export_dir.absolutePath().toStdString() << "\n"; + } + close(); +} + +//--------------------------------------------------------------------------- + +void RoiStatisticsWidget::onClose() +{ + clear_all(); + close(); +} + +//--------------------------------------------------------------------------- + +void RoiStatisticsWidget::clear_all() +{ + _table_widget->setRowCount(0); + _str_export_filename = ""; +} + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- \ No newline at end of file diff --git a/src/mvc/RoiStatisticsWidget.h b/src/mvc/RoiStatisticsWidget.h new file mode 100644 index 0000000..590ba0d --- /dev/null +++ b/src/mvc/RoiStatisticsWidget.h @@ -0,0 +1,100 @@ +/*----------------------------------------------------------------------------- + * Copyright (c) 2024, UChicago Argonne, LLC + * See LICENSE file. + *---------------------------------------------------------------------------*/ + +#ifndef Roi_Statistics_Widget_H +#define Roi_Statistics_Widget_H + +/*---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include "data_struct/fit_parameters.h" +#include "gstar/Annotation/RoiMaskGraphicsItem.h" +#include "core/defines.h" +#include "data_struct/element_info.h" +#include "mvc/MapsH5Model.h" + +/*---------------------------------------------------------------------------*/ + +class RoiStatisticsWidget : public QWidget +{ + + Q_OBJECT + +public: + + /** + * Constructor. + */ + RoiStatisticsWidget(); + + /** + * Destructor. + */ + ~RoiStatisticsWidget(); + + void setData(QDir model_dir, + QString dataset_name, + QString fitting_name, + QString normalizer_name, + float sq_area, + std::unordered_map>& img_data, + std::vector& roi_list, + data_struct::ArrayXXr* normalizer, + Calibration_curve* calib_curve); + + void clear_all(); + + void append_roi(gstar::RoiMaskGraphicsItem* roi); + +public slots: + + void onExport(); + + void onClose(); + +protected: + + void _createLayout(); + +private: + + void _insert_item(QString roiName, + QString imgName, + float sq_area, + const data_struct::ArrayXXr& img, + const std::vector>& roi_pixels, + int i, + data_struct::ArrayXXr* normalizer, + Calibration_curve* calib_curve); + + QString _str_export_filename; + + QDir _export_dir; + + QTableWidget* _table_widget; + + QPushButton* _btn_export; + + QPushButton* _btn_close; + + QStringList _base_header; + + std::vector _element_lines_list; + + std::vector _scalers_to_add_first_list; + + std::vector _final_counts_to_add_before_scalers; +}; + + +/*---------------------------------------------------------------------------*/ + +#endif /* RoiStatisticsWidget.h */ + +/*---------------------------------------------------------------------------*/ + diff --git a/src/mvc/ScatterPlotView.cpp b/src/mvc/ScatterPlotView.cpp index 54d11c6..bf51f3a 100644 --- a/src/mvc/ScatterPlotView.cpp +++ b/src/mvc/ScatterPlotView.cpp @@ -18,6 +18,7 @@ ScatterPlotView::ScatterPlotView(bool display_log10, bool black_background, QWid _model = nullptr; _curAnalysis = QString(STR_FIT_NNLS.c_str()); + _curQuant = QString("1"); _axisXLog10 = new QLogValueAxis(); _axisXLog10->setTitleText(""); @@ -55,6 +56,7 @@ ScatterPlotView::ScatterPlotView(bool display_log10, bool black_background, QWid //setRenderHint(QPainter::Antialiasing); _scatter_series = new QScatterSeries(); + _scatter_series->setColor(QColor(Qt::blue)); QString marker_shape = Preferences::inst()->getValue(STR_PFR_MARKER_SHAPE).toString(); if (marker_shape == "Circle") { @@ -65,7 +67,8 @@ ScatterPlotView::ScatterPlotView(bool display_log10, bool black_background, QWid _scatter_series->setMarkerShape(QScatterSeries::MarkerShapeRectangle); } - _scatter_series->setColor(QColor(Qt::blue)); + setBlackBackground(Preferences::inst()->getValue(STR_PFR_SCATTER_DARK_BACKGROUND).toBool()); + _scatter_series->setBorderColor(Qt::transparent); _scatter_series->setMarkerSize(1.0); //_scatter_series->setUseOpenGL(true); // causes exception when deconstructor called. _chart->addSeries(_scatter_series); @@ -155,11 +158,11 @@ void ScatterPlotView::exportPngCsv() QString apath; if (roi_name.length() > 0) { - apath = dir.absolutePath() + QDir::separator() + finfo.fileName() + QString("_scatter_" + _curAnalysis + "_" + _cb_roi->currentText() + "-" + _cb_x_axis_element->currentText() + "-" + _cb_y_axis_element->currentText() + "_" + formattedTime); + apath = dir.absolutePath() + QDir::separator() + finfo.fileName() + QString("_scatter_" + _curAnalysis + "_" + _curQuant + "_" + roi_name + "-" + _cb_x_axis_element->currentText() + "-" + _cb_y_axis_element->currentText() + "_" + formattedTime); } else { - apath = dir.absolutePath() + QDir::separator() + finfo.fileName() + QString("_scatter_" + _curAnalysis + "_" + _cb_x_axis_element->currentText() + "-" + _cb_y_axis_element->currentText() + "_" + formattedTime); + apath = dir.absolutePath() + QDir::separator() + finfo.fileName() + QString("_scatter_" + _curAnalysis + "_" + _curQuant + "_" + _cb_x_axis_element->currentText() + "-" + _cb_y_axis_element->currentText() + "_" + formattedTime); } QString png_path = QDir::cleanPath(apath + ".png"); if (false == pixmap.save(png_path, "PNG")) @@ -186,8 +189,12 @@ void ScatterPlotView::_exportScatterPlotCSV(QString filePath) { if (_model != nullptr) { + const std::unordered_map rois = _model->get_map_rois(); data_struct::ArrayXXr x_map; data_struct::ArrayXXr y_map; + std::vector x_motor = _model->get_x_axis(); + std::vector y_motor = _model->get_y_axis(); + QString roi_name = _cb_roi->currentText(); if (_getXY_Maps(x_map, y_map)) { std::ofstream out_stream(filePath.toStdString()); @@ -195,16 +202,37 @@ void ScatterPlotView::_exportScatterPlotCSV(QString filePath) { out_stream << "ascii information for file: " << _model->getDatasetName().toStdString() << "\n"; out_stream << "Analysis Type: " << _curAnalysis.toStdString() << "\n"; + out_stream << "Quantification Type: " << _curQuant.toStdString() << "\n"; + if (roi_name.length() > 0) + { + out_stream << "ROI Name: " << roi_name.toStdString() << "\n"; + } out_stream << "X Axis Name: " << _cb_x_axis_element->currentText().toStdString() << "\n"; out_stream << "Y Axis Name: " << _cb_y_axis_element->currentText().toStdString() << "\n"; - out_stream << "Rows: " << x_map.rows() << "\n"; - out_stream << "Cols: " << x_map.cols() << "\n"; - out_stream << "X Index, Y Index, X Value, Y Value \n"; - for (int y = 0; y < x_map.rows(); y++) + out_stream << "Units: Cts/s\n"; + if (rois.count(roi_name.toStdString()) > 0) + { + Map_ROI map_roi = rois.at(roi_name.toStdString()); + out_stream << "Num Points: " << map_roi.pixel_list.size() << "\n"; + out_stream << "X Index, Y Index, X Value, Y Value, X Motor, Y Motor \n"; + + for (auto& itr : map_roi.pixel_list) + { + out_stream << itr.first << "," << itr.second << "," << x_map(itr.second, itr.first) << "," << y_map(itr.second, itr.first) << "," << x_motor[itr.first] << ","<< y_motor[itr.second]<< "\n"; + } + } + else { - for (int x = 0; x < x_map.cols(); x++) + out_stream << "Rows: " << x_map.rows() << "\n"; + out_stream << "Cols: " << x_map.cols() << "\n"; + out_stream << "Num Points: " << x_map.rows() * x_map.cols() << "\n"; + out_stream << "X Index, Y Index, X Value, Y Value, X Motor, Y Motor \n"; + for (int y = 0; y < x_map.rows(); y++) { - out_stream << x << "," << y << "," << x_map(y, x) << "," << y_map(y, x) << "\n"; + for (int x = 0; x < x_map.cols(); x++) + { + out_stream << x << "," << y << "," << x_map(y, x) << "," << y_map(y, x) << x_motor[x] << ","<< y_motor[y]<< "\n"; + } } } } @@ -311,6 +339,13 @@ void ScatterPlotView::setAnalysisType(QString name) //--------------------------------------------------------------------------- +void ScatterPlotView::setQuantType(QString name) +{ + _curQuant = name; +} + +//--------------------------------------------------------------------------- + void ScatterPlotView::_updateNames() { if (_model != nullptr) @@ -319,11 +354,20 @@ void ScatterPlotView::_updateNames() _cb_roi->clear(); _cb_roi->addItem(" "); + int itemAmt = 0; for (auto& itr : rois) { _cb_roi->addItem(QString(itr.first.c_str())); + itemAmt++; + } + if(itemAmt == 0) + { + _cb_roi->setEnabled(false); + } + else + { + _cb_roi->setEnabled(true); } - std::vector map_names; _model->generateNameLists(_curAnalysis, map_names); QString xSavedName = _cb_x_axis_element->currentText(); @@ -394,7 +438,10 @@ bool ScatterPlotView::_getXY_Maps(data_struct::ArrayXXr &x_map, data_stru std::string yName = _cb_y_axis_element->currentText().toStdString(); data_struct::Fit_Count_Dict fit_counts; - _model->getAnalyzedCounts(_curAnalysis.toStdString(), fit_counts); + if(false == _model->getAnalyzedQuantified(_curAnalysis.toStdString(), _curQuant.toStdString(), fit_counts)) + { + _model->getAnalyzedCounts(_curAnalysis.toStdString(), fit_counts); + } std::map>* scalers = _model->getScalers(); int xCnt = fit_counts.count(xName); @@ -503,7 +550,7 @@ void ScatterPlotView::_updatePlot() double corr_coef = find_coefficient(x_arr, y_arr); _lb_corr_coef->setText(QString::number(corr_coef)); - + _scatter_series->setBorderColor(Qt::transparent); _chart->addSeries(_scatter_series); _axisX->setTitleText(_cb_x_axis_element->currentText()); diff --git a/src/mvc/ScatterPlotView.h b/src/mvc/ScatterPlotView.h index bfc9cb0..5a214e3 100644 --- a/src/mvc/ScatterPlotView.h +++ b/src/mvc/ScatterPlotView.h @@ -41,6 +41,8 @@ class ScatterPlotView : public QWidget void setAnalysisType(QString curAnalysis); + void setQuantType(QString curAnalysis); + void updateMarkerSize(qreal val); void setLog10(int val); @@ -64,7 +66,6 @@ public slots: void onNameChange(QString); private: - bool _getXY_Maps(data_struct::ArrayXXr& x_map, data_struct::ArrayXXr& y_map); void _updateNames(); @@ -99,6 +100,8 @@ public slots: QString _curAnalysis; + QString _curQuant; + bool _display_log10; MapsH5Model* _model; diff --git a/src/mvc/ScatterPlotWidget.cpp b/src/mvc/ScatterPlotWidget.cpp index ff35572..6aa661d 100644 --- a/src/mvc/ScatterPlotWidget.cpp +++ b/src/mvc/ScatterPlotWidget.cpp @@ -40,7 +40,7 @@ void ScatterPlotWidget::_createLayout() int num_wins = Preferences::inst()->getValue(STR_PRF_ScatterPlot_NumWindows).toInt(); bool _display_log10 = Preferences::inst()->getValue(STR_PRF_ScatterPlot_Log10).toBool(); bool display_gird_lines = Preferences::inst()->getValue(STR_PRF_ScatterPlot_GridLines).toBool(); - bool dark_theme = Preferences::inst()->getValue(STR_PFR_SPECTRA_BLACK_BG).toBool(); + bool dark_theme = Preferences::inst()->getValue(STR_PFR_SCATTER_DARK_BACKGROUND).toBool(); _ck_display_log10 = new QCheckBox("Display log10"); _ck_display_log10->setChecked(_display_log10); @@ -107,6 +107,13 @@ void ScatterPlotWidget::_createLayout() _mainlayout->addItem(_subPlotLayout); _mainlayout->addItem(_options_layout); + + setGridLinesVisible(Preferences::inst()->getValue(STR_PRF_ScatterPlot_GridLines).toBool()); + setBlackBackground(Preferences::inst()->getValue(STR_PFR_SCATTER_DARK_BACKGROUND).toBool()); + set_log10(Preferences::inst()->getValue(STR_PRF_ScatterPlot_Log10).toBool()); + updateMarkerSize(Preferences::inst()->getValue(STR_PRF_ScatterPlot_Size).toInt()); + onShapeChange(Preferences::inst()->getValue(STR_PFR_MARKER_SHAPE).toString()); + setLayout(_mainlayout); } @@ -117,7 +124,7 @@ void ScatterPlotWidget::onAdd() { bool _display_log10 = Preferences::inst()->getValue(STR_PRF_ScatterPlot_Log10).toBool(); bool display_gird_lines = Preferences::inst()->getValue(STR_PRF_ScatterPlot_GridLines).toBool(); - bool dark_theme = Preferences::inst()->getValue(STR_PFR_SPECTRA_BLACK_BG).toBool(); + bool dark_theme = Preferences::inst()->getValue(STR_PFR_SCATTER_DARK_BACKGROUND).toBool(); _plot_view_list.push_back(new ScatterPlotView(_display_log10, dark_theme, this)); int idx = _plot_view_list.size() - 1; @@ -127,6 +134,11 @@ void ScatterPlotWidget::onAdd() update(); _plot_view_list[idx]->show(); + + + //updateMarkerSize(Preferences::inst()->getValue(STR_PRF_ScatterPlot_Size).toInt()); + //onShapeChange(Preferences::inst()->getValue(STR_PFR_MARKER_SHAPE).toString()); + Preferences::inst()->setValue(STR_PRF_ScatterPlot_NumWindows, (int)_plot_view_list.size()); } @@ -176,16 +188,21 @@ void ScatterPlotWidget::setBlackBackground(int val) { itr->setBlackBackground(val); } + + Preferences::inst()->setValue(STR_PFR_SCATTER_DARK_BACKGROUND, val); } //--------------------------------------------------------------------------- void ScatterPlotWidget::updateMarkerSize(int val) { + val = std::min(val, 1); for (auto& itr : _plot_view_list) { itr->updateMarkerSize(val); } + + Preferences::inst()->setValue(STR_PRF_ScatterPlot_Size, val); } //--------------------------------------------------------------------------- @@ -198,6 +215,15 @@ void ScatterPlotWidget::setAnalysisType(QString name) } } +//--------------------------------------------------------------------------- + +void ScatterPlotWidget::setQuantType(QString name) +{ + for (auto& itr : _plot_view_list) + { + itr->setQuantType(name); + } +} //--------------------------------------------------------------------------- @@ -222,7 +248,8 @@ void ScatterPlotWidget::set_log10(int val) { itr->setLog10(val); } - + + Preferences::inst()->setValue(STR_PRF_ScatterPlot_Log10, val); } //--------------------------------------------------------------------------- diff --git a/src/mvc/ScatterPlotWidget.h b/src/mvc/ScatterPlotWidget.h index 7cbb4a3..69f9e99 100644 --- a/src/mvc/ScatterPlotWidget.h +++ b/src/mvc/ScatterPlotWidget.h @@ -47,6 +47,8 @@ class ScatterPlotWidget : public QWidget void setAnalysisType(QString name); + void setQuantType(QString name); + signals: void updateProgressBar(int, int); diff --git a/src/preferences/Preferences.cpp b/src/preferences/Preferences.cpp index 2172b7c..c346d75 100644 --- a/src/preferences/Preferences.cpp +++ b/src/preferences/Preferences.cpp @@ -32,13 +32,13 @@ Preferences::Preferences() {STR_PRF_PythonCoefficient, QVariant()}, {STR_PRF_PythonOptions, QVariant()}, {STR_PRF_SolverCheckedID, QVariant()}, - {STR_PRF_FontSize, QVariant(14)}, + {STR_PRF_FontSize, QVariant()}, {STR_PRF_RulerUnitLabel, QVariant()}, {STR_PRF_RulerUnitX, QVariant()}, {STR_PRF_RulerUnitY, QVariant()}, {STR_PRF_RegionMenuList, QVariant()}, - {STR_PRF_MainWindowSavedWidth, QVariant(1024)}, - {STR_PRF_MainWindowSavedHeight, QVariant(768)}, + {STR_PRF_MainWindowSavedWidth, QVariant()}, + {STR_PRF_MainWindowSavedHeight, QVariant()}, {STR_PRF_WindowTitle, QVariant()}, {STR_PRF_DecimalPrecision, QVariant()}, {STR_PRF_MicroProbeXPv, QVariant()}, @@ -54,14 +54,43 @@ Preferences::Preferences() {STR_PRF_ExportSelectedXmlOption, QVariant()}, {STR_PRF_LastIP, QVariant()}, {STR_PRF_LastPort, QVariant()}, - {STR_PFR_LOG_10, QVariant(true)}, + {STR_PFR_LOG_10, QVariant()}, {STR_PFR_DETAILED_FIT_SPEC, QVariant()}, + {STR_PFR_SHOW_FIT_INT_MATRIX, QVariant()}, + {STR_PFR_SHOW_FIT_INT_NNLS, QVariant()}, + {STR_PFR_SHOW_MAX_CHAN_SPEC, QVariant()}, {STR_GRID_ROWS, QVariant()}, {STR_GRID_COLS, QVariant()}, + {STR_COLORMAP, QVariant()}, + {STR_COLORMAP_GRAY, QVariant()}, + {STR_COLORMAP_HEAT, QVariant()}, + {STR_RECENT_MAPS_WORKSPACES, QVariant()}, + {STR_LOG_SCALE_COLOR, QVariant()}, + {STR_DISPLAY_COLOR_LEDGEND, QVariant()}, + {STR_INVERT_Y_AXIS, QVariant()}, + {STR_PFR_THEME, QVariant()}, + {STR_PFR_SPECTRA_BLACK_BG, QVariant()}, + {STR_PRF_ScatterPlot_NumWindows, QVariant()}, + {STR_PRF_ScatterPlot_Log10, QVariant()}, + {STR_PFR_MARKER_SHAPE, QVariant()}, + {STR_PFR_SCATTER_DARK_BACKGROUND, QVariant()}, + {STR_PRF_ScatterPlot_Size, QVariant()}, + {STR_PRF_ScatterPlot_GridLines, QVariant()}, + {STR_DEFAULT, QVariant()}, {STR_PRF_SHOW_DATASET_ON_FILE_SELECT, QVariant()}, {STR_SEARCH_SUB_DIR_FOR_DATASETS, QVariant()}, {STR_GEOMETRY, QVariant()}, - {STR_WINDOWSTATE, QVariant()} + {STR_WINDOWSTATE, QVariant()}, + {STR_MAPS_WIDGET_GEOMETRY, QVariant()}, + {STR_COUNTS_DOCK, QVariant()}, + {STR_INTSPEC_DOCK, QVariant()}, + {STR_QUANT_DOCK, QVariant()}, + {STR_COLOR_DOCK, QVariant()}, + {STR_SCATTER_DOCK, QVariant()}, + {STR_EXTRA_DOCK, QVariant()}, + {STR_PRF_STRICT_REGEX, QVariant()}, + {STR_PRF_FILE_SIZE, QVariant()}, + {STR_PRF_SHOW_DATASET_ON_LOAD, QVariant()} }; load(); } diff --git a/src/preferences/Preferences.h b/src/preferences/Preferences.h index adcdca4..259c043 100644 --- a/src/preferences/Preferences.h +++ b/src/preferences/Preferences.h @@ -67,7 +67,9 @@ #define STR_PRF_ScatterPlot_NumWindows "ScatterPlot_NumWindows" #define STR_PRF_ScatterPlot_Log10 "ScatterPlot_Log10" #define STR_PFR_MARKER_SHAPE "ScatterPlotMarkerShape" +#define STR_PFR_SCATTER_DARK_BACKGROUND "ScatterPlotDarkBackground" #define STR_PRF_ScatterPlot_GridLines "ScatterPlotGridLines" +#define STR_PRF_ScatterPlot_Size "ScatterPlotSize" #define STR_DEFAULT "Default" #define STR_PRF_SHOW_DATASET_ON_FILE_SELECT "ShowDatasetOnFileSelect" // if you select file name on left side, it will change the current viewed dataset to that if it is loaded #define STR_SEARCH_SUB_DIR_FOR_DATASETS "SearchSubDirForDatasets" @@ -80,6 +82,9 @@ #define STR_COLOR_DOCK "ColorDock" #define STR_SCATTER_DOCK "ScatterDock" #define STR_EXTRA_DOCK "ExtraDock" +#define STR_PRF_STRICT_REGEX "StrictRegEx" +#define STR_PRF_FILE_SIZE "FileSize" +#define STR_PRF_SHOW_DATASET_ON_LOAD "ShowOnLoad" /** * @brief Read and save preferences between application restarts, the vaule key diff --git a/src/preferences/PreferencesDisplay.cpp b/src/preferences/PreferencesDisplay.cpp index fdee992..dda58d2 100644 --- a/src/preferences/PreferencesDisplay.cpp +++ b/src/preferences/PreferencesDisplay.cpp @@ -59,12 +59,29 @@ PreferencesDisplay::PreferencesDisplay(QWidget* parent) : QWidget(parent) _ck_show_dataset_on_select = new QCheckBox(); _ck_show_dataset_on_select->setChecked(Preferences::inst()->getValue(STR_PRF_SHOW_DATASET_ON_FILE_SELECT).toBool()); + QLabel* lblShowDatasetOnLoad = new QLabel("Show dataset when loading"); + lblShowDatasetOnLoad->setFont(font); + _ck_show_dataset_on_load = new QCheckBox(); + _ck_show_dataset_on_load->setChecked(Preferences::inst()->getValue(STR_PRF_SHOW_DATASET_ON_LOAD).toBool()); QLabel* lblSearchDatasets = new QLabel("Search sub folders for datasets (ESRF datasets)."); lblSearchDatasets->setFont(font); _ck_search_datasets = new QCheckBox(); _ck_search_datasets->setChecked(Preferences::inst()->getValue(STR_SEARCH_SUB_DIR_FOR_DATASETS).toBool()); + QLabel* lblFileSize = new QLabel("Show file size in :"); + _cb_file_size = new QComboBox(); + _cb_file_size->addItem("Bytes"); + _cb_file_size->addItem("Kilobytes (Kb)"); + _cb_file_size->addItem("Megabytes (Mb)"); + _cb_file_size->addItem("Gigabytes (Gb)"); + _cb_file_size->setCurrentIndex(Preferences::inst()->getValue(STR_PRF_FILE_SIZE).toInt()); + + QLabel* lblStrictRegex = new QLabel("Strict Regular Expressions for file filter.\n True: The file filter string is unchanged.\n False: Prepend and append '*' to file filter."); + lblSearchDatasets->setFont(font); + _ck_strict_regex = new QCheckBox(); + _ck_strict_regex->setChecked(Preferences::inst()->getValue(STR_PRF_STRICT_REGEX).toBool()); + QFormLayout* mainLayout = new QFormLayout(); @@ -72,8 +89,11 @@ PreferencesDisplay::PreferencesDisplay(QWidget* parent) : QWidget(parent) mainLayout->addRow(lblTitle, m_windowTitle); mainLayout->addRow(lblDeciPrecision, m_decimalPreci); mainLayout->addRow(lblUseDarkTheme, _cb_themes); + mainLayout->addRow(lblFileSize, _cb_file_size); mainLayout->addRow(lblShowDatasetOnSelect, _ck_show_dataset_on_select); + mainLayout->addRow(lblShowDatasetOnLoad, _ck_show_dataset_on_load); mainLayout->addRow(lblSearchDatasets, _ck_search_datasets); + mainLayout->addRow(lblStrictRegex, _ck_strict_regex); connect(_cb_themes, &QComboBox::currentTextChanged, this, &PreferencesDisplay::themeChanged); @@ -134,7 +154,11 @@ void PreferencesDisplay::acceptChanges() Preferences::inst()->setValue(STR_PRF_WindowTitle, getWindowTitle()); Preferences::inst()->setValue(STR_PRF_DecimalPrecision, getDecimalPrecision()); Preferences::inst()->setValue(STR_PRF_SHOW_DATASET_ON_FILE_SELECT, _ck_show_dataset_on_select->isChecked()); + Preferences::inst()->setValue(STR_PRF_SHOW_DATASET_ON_LOAD, _ck_show_dataset_on_load->isChecked()); Preferences::inst()->setValue(STR_SEARCH_SUB_DIR_FOR_DATASETS, _ck_search_datasets->isChecked()); + Preferences::inst()->setValue(STR_PRF_STRICT_REGEX, _ck_strict_regex->isChecked()); + Preferences::inst()->setValue(STR_PRF_FILE_SIZE, _cb_file_size->currentIndex()); + } /*---------------------------------------------------------------------------*/ diff --git a/src/preferences/PreferencesDisplay.h b/src/preferences/PreferencesDisplay.h index 08dee85..b3598e9 100644 --- a/src/preferences/PreferencesDisplay.h +++ b/src/preferences/PreferencesDisplay.h @@ -105,7 +105,13 @@ public slots: QCheckBox* _ck_show_dataset_on_select; + QCheckBox* _ck_show_dataset_on_load; + QCheckBox* _ck_search_datasets; + + QCheckBox* _ck_strict_regex; + + QComboBox* _cb_file_size; }; /*---------------------------------------------------------------------------*/