├── .gitignore ├── AUTHORS ├── CHANGELOG ├── CMakeLists.txt ├── DEPENDENCIES ├── Dockerfile ├── LICENSE ├── README.md ├── REPLACE_QT_LIBRARIES ├── _clang-format ├── assets ├── README ├── application.qrc.in ├── cssclean │ └── stylesheets.qss ├── images │ ├── DEA.png │ ├── checked-box.png │ ├── cluster.png │ ├── clusterBW.png │ ├── correlation.png │ ├── create-selection.png │ ├── delete.png │ ├── edit.png │ ├── export.png │ ├── export_genes.png │ ├── filesave.png │ ├── flip.png │ ├── histogram.png │ ├── histogram2.png │ ├── import-dataset.png │ ├── import.png │ ├── import_genes.png │ ├── lasso.png │ ├── lasso2.png │ ├── loadGenes.png │ ├── loadSpots.png │ ├── merge.png │ ├── nonvisible.png │ ├── open.png │ ├── pca.png │ ├── print.png │ ├── reg_search.png │ ├── rotateLeft.png │ ├── rotateRight.png │ ├── save.png │ ├── save_selection.png │ ├── scatter.png │ ├── select-all.png │ ├── select-color.png │ ├── selection.png │ ├── selection2.png │ ├── selection_dea.png │ ├── settings.png │ ├── settings2.png │ ├── show_genes.png │ ├── show_spots.png │ ├── st_icon.icns │ ├── st_icon.ico │ ├── st_icon.png │ ├── unchecked-box.png │ ├── unselect-all.png │ ├── visible.png │ ├── warning.png │ ├── zoom_in.png │ └── zoom_out.png └── stviewer.conf ├── cmake ├── CMakeLists.txt ├── FindR.cmake ├── README ├── mac │ ├── CMakeLists.txt │ ├── Info.plist.in │ └── qt.conf ├── options_cmake.h.in └── utils.cmake ├── data ├── HE_Rep6_MOB.jpg └── MOB_REP6.tsv ├── src ├── CMakeLists.txt ├── SettingsStyle.h ├── analysis │ ├── AnalysisClustering.cpp │ ├── AnalysisClustering.h │ ├── AnalysisCorrelation.cpp │ ├── AnalysisCorrelation.h │ ├── AnalysisDEA.cpp │ ├── AnalysisDEA.h │ ├── AnalysisPCA.cpp │ ├── AnalysisPCA.h │ ├── AnalysisPCA.ui │ ├── AnalysisQC.cpp │ ├── AnalysisQC.h │ ├── AnalysisScatter.cpp │ ├── AnalysisScatter.h │ ├── CMakeLists.txt │ ├── ChartView.cpp │ ├── ChartView.h │ ├── analysisClustering.ui │ ├── analysisCorrelation.ui │ ├── analysisDEA.ui │ ├── analysisQC.ui │ └── analysisScatter.ui ├── color │ ├── CMakeLists.txt │ ├── HeatMap.cpp │ └── HeatMap.h ├── config │ ├── CMakeLists.txt │ ├── Configuration.cpp │ ├── Configuration.h │ ├── SettingsFormatXML.cpp │ └── SettingsFormatXML.h ├── data │ ├── CMakeLists.txt │ ├── Dataset.cpp │ ├── Dataset.h │ ├── DatasetImporter.cpp │ ├── DatasetImporter.h │ ├── Gene.cpp │ ├── Gene.h │ ├── STData.cpp │ ├── STData.h │ ├── Spot.cpp │ ├── Spot.h │ ├── UserSelection.cpp │ ├── UserSelection.h │ └── datasetImporter.ui ├── dialogs │ ├── AboutDialog.cpp │ ├── AboutDialog.h │ ├── CMakeLists.txt │ ├── EditDatasetDialog.cpp │ ├── EditDatasetDialog.h │ ├── EditSelectionDialog.cpp │ ├── EditSelectionDialog.h │ ├── SelectionDialog.cpp │ ├── SelectionDialog.h │ ├── aboutdialog.ui │ ├── editDatasetDialog.ui │ ├── editSelectionDialog.ui │ └── selectionConsole.ui ├── main.cpp ├── mainWindow.cpp ├── mainWindow.h ├── math │ ├── CMakeLists.txt │ ├── Common.h │ └── RInterface.h ├── model │ ├── CMakeLists.txt │ ├── DatasetItemModel.cpp │ ├── DatasetItemModel.h │ ├── GeneItemModel.cpp │ ├── GeneItemModel.h │ ├── SpotItemModel.cpp │ ├── SpotItemModel.h │ ├── UserSelectionsItemModel.cpp │ └── UserSelectionsItemModel.h ├── test │ ├── CMakeLists.txt │ ├── controller │ │ ├── tst_widgets.cpp │ │ └── tst_widgets.h │ ├── math │ │ ├── tst_glheatmaptest.cpp │ │ └── tst_glheatmaptest.h │ ├── unit_main.cpp │ ├── utils │ │ ├── tst_mathextendedtest.cpp │ │ └── tst_mathextendedtest.h │ └── viewOpenGL │ │ ├── OpenGLTestWindow.cpp │ │ ├── OpenGLTestWindow.h │ │ ├── test_AssertOpenGL.cpp │ │ └── test_AssertOpenGL.h ├── viewPages │ ├── CMakeLists.txt │ ├── CellViewPage.cpp │ ├── CellViewPage.h │ ├── DatasetPage.cpp │ ├── DatasetPage.h │ ├── GenesWidget.cpp │ ├── GenesWidget.h │ ├── SelectionGenesWidget.cpp │ ├── SelectionGenesWidget.h │ ├── SelectionSpotsWidget.cpp │ ├── SelectionSpotsWidget.h │ ├── SettingsWidget.cpp │ ├── SettingsWidget.h │ ├── SettingsWidget.ui │ ├── SpotsWidget.cpp │ ├── SpotsWidget.h │ ├── UserSelectionsPage.cpp │ ├── UserSelectionsPage.h │ ├── cellviewPage.ui │ ├── datasetsPage.ui │ ├── genesSelectionWidget.ui │ ├── selectionsPage.ui │ └── spotsSelectionWidget.ui ├── viewRenderer │ ├── CMakeLists.txt │ ├── CellGLView.cpp │ ├── CellGLView.h │ ├── GeneRendererGL.cpp │ ├── GeneRendererGL.h │ ├── GraphicItemGL.cpp │ ├── GraphicItemGL.h │ ├── HeatMapLegendGL.cpp │ ├── HeatMapLegendGL.h │ ├── ImageTextureGL.cpp │ ├── ImageTextureGL.h │ └── SelectionEvent.h └── viewTables │ ├── CMakeLists.txt │ ├── DatasetsTableView.cpp │ ├── DatasetsTableView.h │ ├── GenesTableView.cpp │ ├── GenesTableView.h │ ├── SpotsTableView.cpp │ ├── SpotsTableView.h │ ├── UserSelectionTableView.cpp │ └── UserSelectionTableView.h └── ubuntu_dep_and_compile.sh /.gitignore: -------------------------------------------------------------------------------- 1 | local_configuration.cmake 2 | build 3 | .project 4 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Authors: 2 | Jose Carlos Fernandez Navarro 3 | 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(STViewer CXX) 2 | 3 | cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR) 4 | 5 | set(APPLICATION_NAME "Spatial Transcriptomics Research Viewer") 6 | 7 | # Configuration variables 8 | set(PROJECT_VERSION_MAJOR "0") 9 | set(PROJECT_VERSION_MINOR "7") 10 | set(PROJECT_VERSION_PATCH "6") 11 | set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") 12 | set(PROJECT_DESCRIPTION "Visualization tool for Spatial Transcriptomics data") 13 | set(PROJECT_COPYRIGHT "Copyright (C) 2019 Jose Fernandez Navarro, KTH, KI.") 14 | set(PROJECT_CONTACT "jose.fernandez.navarro@scilifelab.se") 15 | set(PROJECT_VENDOR "Jose Fernandez Navarro") 16 | set(CONFIG_FILE "${PROJECT_SOURCE_DIR}/assets/stviewer.conf" CACHE STRING 17 | "The file with the configuration settings") 18 | 19 | # print main variables 20 | message(STATUS) 21 | message(STATUS 22 | "-------------------------------------------------------------------------------" 23 | ) 24 | message(STATUS "Building ${APPLICATION_NAME} .....") 25 | message(STATUS "Change a configuration variable with: cmake -D=") 26 | message(STATUS "CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}") 27 | message(STATUS "CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}") 28 | message(STATUS "CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}") 29 | message(STATUS "CMAKE_CXX_COMPILER = ${CMAKE_CXX_COMPILER}") 30 | message(STATUS "TARGET_ARCH = ${TARGET_ARCH}") 31 | message(STATUS "VERSION = ${PROJECT_VERSION}") 32 | message(STATUS "CONFIGURATION FILE = ${CONFIG_FILE}") 33 | message(STATUS 34 | "-------------------------------------------------------------------------------" 35 | ) 36 | message(STATUS) 37 | 38 | if(WIN32) 39 | SET(CMAKE_FIND_LIBRARY_PREFIXES "") 40 | SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".dll") 41 | endif() 42 | 43 | # Restrict possible builds to the selected build type. 44 | set(CMAKE_CONFIGURATION_TYPES "${CMAKE_BUILD_TYPE}") 45 | 46 | # Some CMake standard settings 47 | if(COMMAND cmake_policy) 48 | cmake_policy(SET CMP0003 NEW) 49 | if(WIN32) 50 | cmake_policy(SET CMP0020 NEW) 51 | cmake_policy(SET CMP0054 NEW) 52 | endif(WIN32) 53 | if(APPLE) 54 | cmake_policy(SET CMP0025 NEW) 55 | endif() 56 | endif(COMMAND cmake_policy) 57 | 58 | # We just need to pass the app the name of the config file so it can be used 59 | get_filename_component(CONFIG_FILE_NAME ${CONFIG_FILE} NAME) 60 | 61 | # Some in-house CMake functions/macros 62 | include(${CMAKE_SOURCE_DIR}/cmake/utils.cmake) 63 | 64 | # Initialize project settings (important to do it first as it defines compilation flags) 65 | initialise_project() 66 | 67 | # Compile RC-file, only for Windows 68 | if(WIN32) 69 | set (RC_FILE ${PROJECT_SOURCE_DIR}/${PROJECT_NAME}.rc) 70 | add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.o 71 | COMMAND windres.exe -I${CMAKE_CURRENT_SOURCE_DIR} -i${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.rc 72 | -o ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.o) 73 | endif (WIN32) 74 | 75 | # Check the the configuration file is present 76 | if(NOT EXISTS ${CONFIG_FILE}) 77 | message(FATAL_ERROR "Configuration file not present!") 78 | endif() 79 | 80 | # Compile CMake generated based files 81 | configure_file(${PROJECT_SOURCE_DIR}/assets/application.qrc.in ${PROJECT_BINARY_DIR}/application.qrc) 82 | configure_file(${PROJECT_SOURCE_DIR}/cmake/options_cmake.h.in ${PROJECT_BINARY_DIR}/options_cmake.h) 83 | 84 | # Include the project binary dir 85 | include_directories(${PROJECT_BINARY_DIR}) 86 | 87 | # Add cutom find.cmake files 88 | set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) 89 | 90 | # Include local configuration file if present 91 | if(EXISTS "${CMAKE_SOURCE_DIR}/local_configuration.cmake") 92 | include("${CMAKE_SOURCE_DIR}/local_configuration.cmake") 93 | endif() 94 | 95 | # Include source code 96 | add_subdirectory(src) 97 | -------------------------------------------------------------------------------- /DEPENDENCIES: -------------------------------------------------------------------------------- 1 | Qt (dynamic linking) with LGPL v3 and v2.1 licenses 2 | QCustomplot (dynamic linking) with a comercial license 3 | Armadillo (dynamic linking) with Apache 2.0 license 4 | R (DESeq2, Rtsne, edgeR and SCRAN) with GNU v2.0 license 5 | RInside with GNU v2.0 license 6 | Rcpp with GNU v2.0 license 7 | RcppArmadillo with GNU v2.0 license 8 | 9 | Links: 10 | http://qcustomplot.com/ 11 | http://arma.sourceforge.net/ 12 | https://www.qt.io/ 13 | https://cran.r-project.org/ 14 | https://cran.r-project.org/web/packages/Rcpp/index.html 15 | https://cran.r-project.org/web/packages/RInside/index.html 16 | https://cran.r-project.org/web/packages/RcppArmadillo/index.html 17 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # To run it locally you need 2 | # 1) Allow local appliaction to use your Xserver 3 | # 4 | # xhost +local:root 5 | # 6 | # 2) mount the display and the temporary directory 7 | # 8 | # 9 | # docker run -d -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix:rw st_viewer 10 | # 11 | 12 | FROM ubuntu:17.10 13 | 14 | RUN apt-get update && apt-get install -y \ 15 | autoconf \ 16 | automake \ 17 | make \ 18 | g++ \ 19 | gcc \ 20 | build-essential \ 21 | git \ 22 | ubuntu-dev-tools \ 23 | libglu1-mesa-dev \ 24 | freeglut3-dev \ 25 | mesa-common-dev \ 26 | wget \ 27 | libfontconfig1 \ 28 | qt5-default \ 29 | qtbase5-dev \ 30 | libqt5charts5-dev \ 31 | libqt5svg5-dev \ 32 | libarmadillo-dev \ 33 | r-base \ 34 | r-cran-rcpparmadillo \ 35 | && rm -rf /var/lib/apt/lists/* 36 | 37 | # Install cmake 38 | RUN wget https://cmake.org/files/v3.7/cmake-3.7.2.tar.gz && \ 39 | tar -xvzf cmake-3.7.2.tar.gz && \ 40 | cd cmake-3.7.2 && \ 41 | ./configure && \ 42 | make -j4 && \ 43 | make install 44 | 45 | 46 | # Install Qt (Faking display) 47 | # Installed via Apt 48 | 49 | # DONWLOAD the QCustomplot 50 | RUN wget http://www.qcustomplot.com/release/1.3.2/QCustomPlot.tar.gz && \ 51 | mkdir /opt/QCustomPlot && tar xf QCustomPlot.tar.gz -C /opt/QCustomPlot 52 | 53 | 54 | # Downlaod Armadillo debs and install 55 | # Installed via apt 56 | 57 | # Install R deps 58 | RUN echo "r <- getOption('repos'); r['CRAN'] <- 'http://cran.us.r-project.org'; options(repos = r);" > ~/.Rprofile 59 | RUN Rscript -e "source('https://bioconductor.org/biocLite.R'); biocLite('DESeq2'); biocLite('scran'); biocLite('Rtsne')" 60 | RUN Rscript -e "install.packages('RInside')" 61 | 62 | # Installed via APT for easier compilation. 63 | #RUN Rscript -e "install.packages('Rcpp')" 64 | #RUN Rscript -e "install.packages('RcppArmadillo')" 65 | 66 | WORKDIR /opt/ 67 | RUN mkdir /opt/st_viewer 68 | WORKDIR /opt/st_viewer 69 | ADD . . 70 | RUN mkdir st_viewer_build 71 | WORKDIR /opt/st_viewer/st_viewer_build 72 | 73 | # Optimize this in one line. 74 | RUN cmake -DCMAKE_BUILD_TYPE="Release" -DCMAKE_PREFIX_PATH="/opt/QCustomPlot/qcustomplot" .. \ 75 | && make -j4 76 | # && make install 77 | 78 | CMD ["/opt/st_viewer/st_viewer_build/STViewer"] 79 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2017 Jose Fernandez Navarro, KTH, KI. 3 | All rights reserved. 4 | 5 | * Jose Fernandez Navarro 6 | * Royal Institute of Technology (KTH) 7 | * Karolisnka Institute (KI) 8 | 9 | This software uses the following third party libraries: 10 | Armadillo, R, QCustomplot and Qt. 11 | Their licenses are listed in the file DEPENDENCIES. 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a 14 | copy of this software and associated documentation files (the "Software"), 15 | to deal in the Software without restriction, including without limitation 16 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 17 | and/or sell copies of the Software, and to permit persons to whom the 18 | Software is furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in all 21 | copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 24 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 25 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 26 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 27 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | -------------------------------------------------------------------------------- /REPLACE_QT_LIBRARIES: -------------------------------------------------------------------------------- 1 | STViewer is an open source application that 2 | uses the open source version of Qt. To comply 3 | the LGPL v3 requirements, instructions on how 4 | to replace the Qt libraries for the end-user must 5 | be given in case you decide to distribute the binaries. 6 | 7 | For OSX: 8 | 9 | Check what Qt frameworks and plugins are in use : 10 | - otool -L /Applications/STViewer.app/Contents/MacOs/STViewer 11 | 12 | Copy the framewors and plugins from your local Qt installation : 13 | - cp -R /path/to/Qt/lib/QtCore.framework STViewer.app/Contents/Frameworks 14 | ... 15 | - cp -R /path/to/Qt/plugin/imageformats/libqjpeg.dylib STViewer.app/Contents/PlugIns 16 | ... 17 | 18 | Set the identification names for the frameworks : 19 | - install_name_tool -id @executable_path/../Frameworks/QtCore.framework/Versions/5.0/QtCore 20 | STViewer.app/Contents/Frameworks/QtCore.framework/Versions/5.0/QtCore 21 | ... 22 | 23 | Ensure STViewer knows where the frameworks are 24 | - install_name_tool -change path/to/Qt/lib/QtCore.framework/Versions/5.0/QtCore 25 | @executable_path/../Frameworks/QtCore.framework/Versions/5.0/QtCore 26 | STViewer.app/Contents/MacOs/plugandpaint 27 | ... 28 | 29 | For Linux: 30 | 31 | The same approach as in OSX (shared libraries are in the folder 32 | lib in the application rool folder and plugins are in the folder 33 | plugins in the application root folder). 34 | 35 | For Windows: 36 | 37 | The QT DDLs present in the ST Viewer installation folder must 38 | be replaced for the DDLs present in the QT installation folder. 39 | Libraries are in the folder lib and plugins are in the folder plugins 40 | inside the application folder. 41 | -------------------------------------------------------------------------------- /_clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: LLVM 4 | AccessModifierOffset: -4 5 | #AlignAfterOpenBracket: true 6 | #AlignConsecutiveAssignments: false 7 | AlignEscapedNewlinesLeft: false 8 | #AlignOperands: true 9 | AlignTrailingComments: true 10 | AllowAllParametersOfDeclarationOnNextLine: true 11 | AllowShortBlocksOnASingleLine: false 12 | # AllowShortBlocksOnASingleLine: false 13 | AllowShortCaseLabelsOnASingleLine: false 14 | AllowShortFunctionsOnASingleLine: Inline 15 | AllowShortIfStatementsOnASingleLine: false 16 | AllowShortLoopsOnASingleLine: false 17 | # AllowShortFunctionsOnASingleLine: All 18 | AlwaysBreakAfterDefinitionReturnType: false 19 | AlwaysBreakBeforeMultilineStrings: false 20 | AlwaysBreakTemplateDeclarations: true 21 | # AlwaysBreakTemplateDeclarations: false 22 | BinPackParameters: false 23 | BinPackArguments: false 24 | BreakBeforeBinaryOperators: All 25 | BreakBeforeBraces: Linux 26 | # BreakBeforeBraces: Attach 27 | # BreakBeforeBinaryOperators: None 28 | # BreakBeforeBinaryOperators: All 29 | BreakBeforeTernaryOperators: true 30 | BreakConstructorInitializersBeforeComma: true 31 | # BreakConstructorInitializersBeforeComma: false 32 | ColumnLimit: 100 33 | CommentPragmas: '^ IWYU pragma:' 34 | # ConstructorInitializerAllOnOneLineOrOnePerLine: true 35 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 36 | ConstructorInitializerIndentWidth: 4 37 | ContinuationIndentWidth: 4 38 | Cpp11BracedListStyle: true 39 | DerivePointerAlignment: false 40 | DisableFormat: false 41 | ExperimentalAutoDetectBinPacking: false 42 | ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] 43 | IndentCaseLabels: false 44 | IndentWidth: 4 45 | IndentWrappedFunctionNames: false 46 | KeepEmptyLinesAtTheStartOfBlocks: true 47 | #MacroBlockBegin: '' 48 | #MacroBlockEnd: '' 49 | MaxEmptyLinesToKeep: 1 50 | NamespaceIndentation: None 51 | #ObjCBlockIndentWidth: 2 52 | ObjCSpaceAfterProperty: false 53 | ObjCSpaceBeforeProtocolList: true 54 | PenaltyBreakBeforeFirstCallParameter: 400 55 | PenaltyBreakComment: 300 56 | PenaltyBreakFirstLessLess: 120 57 | PenaltyBreakString: 1000 58 | PenaltyExcessCharacter: 1000000 59 | PenaltyReturnTypeOnItsOwnLine: 600 60 | PointerAlignment: Right 61 | SpaceAfterCStyleCast: false 62 | SpaceBeforeAssignmentOperators: true 63 | SpaceBeforeParens: ControlStatements 64 | SpaceInEmptyParentheses: false 65 | SpacesBeforeTrailingComments: 1 66 | SpacesInAngles: false 67 | SpacesInContainerLiterals: true 68 | SpacesInCStyleCastParentheses: false 69 | SpacesInParentheses: false 70 | SpacesInSquareBrackets: false 71 | Standard: Cpp11 72 | TabWidth: 8 73 | UseTab: Never 74 | ... 75 | -------------------------------------------------------------------------------- /assets/README: -------------------------------------------------------------------------------- 1 | /images = contains images used in the application (icons,logos..) 2 | /cssclean = contain QSS styles files for the application 3 | application.qrc.in = CMake compilation time generated resource file of Qt 4 | -------------------------------------------------------------------------------- /assets/application.qrc.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | ${PROJECT_SOURCE_DIR}/assets/images/DEA.png 4 | ${PROJECT_SOURCE_DIR}/assets/images/correlation.png 5 | ${PROJECT_SOURCE_DIR}/assets/images/select-color.png 6 | ${PROJECT_SOURCE_DIR}/assets/images/zoom_out.png 7 | ${PROJECT_SOURCE_DIR}/assets/images/zoom_in.png 8 | ${PROJECT_SOURCE_DIR}/assets/images/print.png 9 | ${PROJECT_SOURCE_DIR}/assets/images/selection.png 10 | ${PROJECT_SOURCE_DIR}/assets/images/settings.png 11 | ${PROJECT_SOURCE_DIR}/assets/images/settings2.png 12 | ${PROJECT_SOURCE_DIR}/assets/images/histogram.png 13 | ${PROJECT_SOURCE_DIR}/assets/images/histogram2.png 14 | ${PROJECT_SOURCE_DIR}/assets/images/scatter.png 15 | ${PROJECT_SOURCE_DIR}/assets/images/pca.png 16 | ${PROJECT_SOURCE_DIR}/assets/images/merge.png 17 | ${PROJECT_SOURCE_DIR}/assets/images/reg_search.png 18 | ${PROJECT_SOURCE_DIR}/assets/images/select-all.png 19 | ${PROJECT_SOURCE_DIR}/assets/images/unselect-all.png 20 | ${PROJECT_SOURCE_DIR}/assets/images/visible.png 21 | ${PROJECT_SOURCE_DIR}/assets/images/nonvisible.png 22 | ${PROJECT_SOURCE_DIR}/assets/images/open.png 23 | ${PROJECT_SOURCE_DIR}/assets/images/filesave.png 24 | ${PROJECT_SOURCE_DIR}/assets/images/delete.png 25 | ${PROJECT_SOURCE_DIR}/assets/images/edit.png 26 | ${PROJECT_SOURCE_DIR}/assets/images/warning.png 27 | ${PROJECT_SOURCE_DIR}/assets/images/selection2.png 28 | ${PROJECT_SOURCE_DIR}/assets/images/checked-box.png 29 | ${PROJECT_SOURCE_DIR}/assets/images/unchecked-box.png 30 | ${PROJECT_SOURCE_DIR}/assets/images/clusterBW.png 31 | ${PROJECT_SOURCE_DIR}/assets/images/show_genes.png 32 | ${PROJECT_SOURCE_DIR}/assets/images/show_spots.png 33 | ${PROJECT_SOURCE_DIR}/assets/images/save_selection.png 34 | ${PROJECT_SOURCE_DIR}/assets/images/export.png 35 | ${PROJECT_SOURCE_DIR}/assets/images/import.png 36 | ${PROJECT_SOURCE_DIR}/assets/images/rotateLeft.png 37 | ${PROJECT_SOURCE_DIR}/assets/images/rotateRight.png 38 | ${PROJECT_SOURCE_DIR}/assets/images/flip.png 39 | ${PROJECT_SOURCE_DIR}/assets/images/loadSpots.png 40 | ${PROJECT_SOURCE_DIR}/assets/images/loadGenes.png 41 | ${PROJECT_SOURCE_DIR}/assets/images/lasso.png 42 | ${PROJECT_SOURCE_DIR}/assets/images/lasso2.png 43 | ${PROJECT_SOURCE_DIR}/assets/images/import-dataset.png 44 | ${PROJECT_SOURCE_DIR}/assets/images/export_genes.png 45 | ${PROJECT_SOURCE_DIR}/assets/images/create-selection.png 46 | ${PROJECT_SOURCE_DIR}/assets/cssclean/stylesheets.qss 47 | 48 | 49 | -------------------------------------------------------------------------------- /assets/images/DEA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/DEA.png -------------------------------------------------------------------------------- /assets/images/checked-box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/checked-box.png -------------------------------------------------------------------------------- /assets/images/cluster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/cluster.png -------------------------------------------------------------------------------- /assets/images/clusterBW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/clusterBW.png -------------------------------------------------------------------------------- /assets/images/correlation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/correlation.png -------------------------------------------------------------------------------- /assets/images/create-selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/create-selection.png -------------------------------------------------------------------------------- /assets/images/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/delete.png -------------------------------------------------------------------------------- /assets/images/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/edit.png -------------------------------------------------------------------------------- /assets/images/export.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/export.png -------------------------------------------------------------------------------- /assets/images/export_genes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/export_genes.png -------------------------------------------------------------------------------- /assets/images/filesave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/filesave.png -------------------------------------------------------------------------------- /assets/images/flip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/flip.png -------------------------------------------------------------------------------- /assets/images/histogram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/histogram.png -------------------------------------------------------------------------------- /assets/images/histogram2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/histogram2.png -------------------------------------------------------------------------------- /assets/images/import-dataset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/import-dataset.png -------------------------------------------------------------------------------- /assets/images/import.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/import.png -------------------------------------------------------------------------------- /assets/images/import_genes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/import_genes.png -------------------------------------------------------------------------------- /assets/images/lasso.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/lasso.png -------------------------------------------------------------------------------- /assets/images/lasso2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/lasso2.png -------------------------------------------------------------------------------- /assets/images/loadGenes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/loadGenes.png -------------------------------------------------------------------------------- /assets/images/loadSpots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/loadSpots.png -------------------------------------------------------------------------------- /assets/images/merge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/merge.png -------------------------------------------------------------------------------- /assets/images/nonvisible.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/nonvisible.png -------------------------------------------------------------------------------- /assets/images/open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/open.png -------------------------------------------------------------------------------- /assets/images/pca.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/pca.png -------------------------------------------------------------------------------- /assets/images/print.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/print.png -------------------------------------------------------------------------------- /assets/images/reg_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/reg_search.png -------------------------------------------------------------------------------- /assets/images/rotateLeft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/rotateLeft.png -------------------------------------------------------------------------------- /assets/images/rotateRight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/rotateRight.png -------------------------------------------------------------------------------- /assets/images/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/save.png -------------------------------------------------------------------------------- /assets/images/save_selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/save_selection.png -------------------------------------------------------------------------------- /assets/images/scatter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/scatter.png -------------------------------------------------------------------------------- /assets/images/select-all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/select-all.png -------------------------------------------------------------------------------- /assets/images/select-color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/select-color.png -------------------------------------------------------------------------------- /assets/images/selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/selection.png -------------------------------------------------------------------------------- /assets/images/selection2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/selection2.png -------------------------------------------------------------------------------- /assets/images/selection_dea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/selection_dea.png -------------------------------------------------------------------------------- /assets/images/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/settings.png -------------------------------------------------------------------------------- /assets/images/settings2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/settings2.png -------------------------------------------------------------------------------- /assets/images/show_genes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/show_genes.png -------------------------------------------------------------------------------- /assets/images/show_spots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/show_spots.png -------------------------------------------------------------------------------- /assets/images/st_icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/st_icon.icns -------------------------------------------------------------------------------- /assets/images/st_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/st_icon.ico -------------------------------------------------------------------------------- /assets/images/st_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/st_icon.png -------------------------------------------------------------------------------- /assets/images/unchecked-box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/unchecked-box.png -------------------------------------------------------------------------------- /assets/images/unselect-all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/unselect-all.png -------------------------------------------------------------------------------- /assets/images/visible.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/visible.png -------------------------------------------------------------------------------- /assets/images/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/warning.png -------------------------------------------------------------------------------- /assets/images/zoom_in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/zoom_in.png -------------------------------------------------------------------------------- /assets/images/zoom_out.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/assets/images/zoom_out.png -------------------------------------------------------------------------------- /assets/stviewer.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | STViewer 5 | 0.8.0 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /cmake/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /cmake/README: -------------------------------------------------------------------------------- 1 | options_cmake.h.in = CMake compilation time header were variables can be added 2 | utils.cmake = common CMake functions used in the program, mostly compilation flags 3 | /linux = some files needed to create Linux packages 4 | /mac = some files needed to create MAC packages 5 | /win = some files needed to create Win32 packages 6 | /win64 = some files needed to create Win64 packages 7 | 8 | -------------------------------------------------------------------------------- /cmake/mac/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /cmake/mac/Info.plist.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrincipalClass 6 | NSApplication 7 | NSHighResolutionCapable 8 | True 9 | CFBundleIconFile 10 | ${MACOSX_BUNDLE_ICON_NAME} 11 | CFBundleDocumentTypes 12 | 13 | 14 | CFBundleTypeRole 15 | Editor 16 | CFBundleTypeIconFile 17 | ${MACOSX_BUNDLE_ICON_NAME} 18 | 19 | 20 | NSHumanReadableCopyright 21 | (C) 2012-${YEAR} 22 | CFBundleIconFile 23 | st_icon.icns 24 | CFBundlePackageType 25 | APPL 26 | CFBundleSignature 27 | ???? 28 | CFBundleExecutable 29 | ${PROJECT_NAME} 30 | CFBundleIdentifier 31 | 32 | CFBundleVersion 33 | ${VERSION} 34 | CFBundleShortVersionString 35 | ${VERSION} 36 | 37 | 38 | -------------------------------------------------------------------------------- /cmake/mac/qt.conf: -------------------------------------------------------------------------------- 1 | [Paths] 2 | Plugins = PlugIns 3 | Data = Resources 4 | -------------------------------------------------------------------------------- /cmake/options_cmake.h.in: -------------------------------------------------------------------------------- 1 | // Main solution header file (CMake generated) 2 | #ifndef __COMMON_OPTIONS_CMAKE_H__ 3 | #define __COMMON_OPTIONS_CMAKE_H__ 4 | 5 | #define VERSION_MAJOR @PROJECT_VERSION_MAJOR@ 6 | #define VERSION_MINOR @PROJECT_VERSION_MINOR@ 7 | #define VERSION_REVISION @PROJECT_VERSION_PATCH@ 8 | #define VERSION_BUILD @PROJECT_VERSION_MAJOR@ 9 | #cmakedefine TRANSLATION_FILE "@TRANSLATION_FILE@" 10 | #cmakedefine CONFIG_FILE "@CONFIG_FILE_NAME@" 11 | 12 | // This flag is for unit tests 13 | #cmakedefine01 BUILD_UNIT_TESTS 14 | 15 | static const qulonglong MAJOR = VERSION_MAJOR; 16 | static const qulonglong MINOR = VERSION_MINOR; 17 | static const qulonglong PATCH = VERSION_REVISION; 18 | 19 | #endif // __COMMON_OPTIONS_CMAKE_H__ 20 | -------------------------------------------------------------------------------- /cmake/utils.cmake: -------------------------------------------------------------------------------- 1 | macro(INITIALISE_PROJECT) 2 | set(CMAKE_VERBOSE_MAKEFILE OFF) 3 | 4 | # Required packages 5 | find_package(Qt5Widgets REQUIRED) 6 | # Keep track of some information about Qt 7 | set(QT_BINARY_DIR ${_qt5Widgets_install_prefix}/bin) 8 | set(QT_LIBRARY_DIR ${_qt5Widgets_install_prefix}/lib) 9 | set(QT_PLUGINS_DIR ${_qt5Widgets_install_prefix}/plugins) 10 | set(QT_VERSION_MAJOR ${Qt5Widgets_VERSION_MAJOR}) 11 | set(QT_VERSION_MINOR ${Qt5Widgets_VERSION_MINOR}) 12 | set(QT_VERSION_PATCH ${Qt5Widgets_VERSION_PATCH}) 13 | 14 | string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE_LOWERCASE) 15 | if(BUILD_TYPE_LOWERCASE STREQUAL "debug") 16 | message(STATUS "Building a debug version...") 17 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_DEBUG -DDEBUG") 18 | add_definitions(-DQT_DEBUG) 19 | else() 20 | message(STATUS "Building a release version...") 21 | add_definitions(-DQT_NO_DEBUG_OUTPUT) 22 | add_definitions(-DQT_NO_DEBUG) 23 | endif() 24 | 25 | set(CMAKE_CXX_STANDARD 14) 26 | 27 | # Defining compiler specific settings 28 | if(WIN32) 29 | 30 | else() 31 | 32 | # Adding -std=c++14 flag explicitly 33 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") 34 | 35 | # Enable warning errors 36 | set(WARNING_ERROR "-Werror") 37 | 38 | set(DISABLED_WARNINGS "-Wno-unused-parameter -Wno-unused-function \ 39 | -Wno-sign-compare -Wno-cast-qual -Wno-cast-align -Wno-redundant-decls -Wno-implicit-fallthrough") 40 | 41 | if (APPLE) 42 | set(DISABLED_WARNINGS "${DISABLED_WARNINGS} -Wno-pessimizing-move \ 43 | -Wno-inconsistent-missing-override -Wno-infinite-recursion \ 44 | -Wno-c++1z-extensions -Wno-macro-redefined -Wno-#pragma-messages") 45 | elseif (UNIX) 46 | set(DISABLE_WARNINGS "${DISABLED_WARNINGS} -Wno-unused-but-set-parameter") 47 | endif() 48 | 49 | set(EXTRA_WARNINGS "-Woverloaded-virtual -Wundef -Wall -Wextra \ 50 | -Wformat -Wunused-variable -Wreturn-type -Wempty-body -Wdisabled-optimization \ 51 | -Wredundant-decls -Wpacked -Wuninitialized -Wswitch \ 52 | -pedantic-errors -fuse-cxa-atexit -ffor-scope") 53 | if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") 54 | set(EXTRA_WARNINGS "${EXTRA_WARNINGS} -Wpedantic -Weffc++ -Wnon-virtual-dtor \ 55 | -Wswitch-default -Wint-to-void-pointer-cast") 56 | endif() 57 | endif() 58 | 59 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_WARNINGS} ${DISABLED_WARNINGS} ${WARNING_ERROR}") 60 | 61 | # Check whether the compiler supports position-independent code 62 | include(CheckCXXCompilerFlag) 63 | CHECK_CXX_COMPILER_FLAG("-fPIC" COMPILER_SUPPORTS_PIC) 64 | if(COMPILER_SUPPORTS_PIC) 65 | add_definitions("-fPIC") 66 | endif() 67 | 68 | # Qt 5.X does not include private headers by default 69 | add_definitions(-DNO_QT_PRIVATE_HEADERS) 70 | 71 | endmacro() 72 | 73 | macro(USE_QT5LIB qt5lib) 74 | find_package(${qt5lib} REQUIRED) 75 | include_directories(${${qt5lib}_INCLUDE_DIRS}) 76 | add_definitions(${${qt5lib}_DEFINITIONS}) 77 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${${qt5lib}_EXECUTABLE_COMPILE_FLAGS}") 78 | endmacro() 79 | 80 | function(ST_LIBRARY) 81 | get_filename_component(PARENTDIR ${CMAKE_CURRENT_SOURCE_DIR} NAME) 82 | add_library("${PARENTDIR}" OBJECT ${LIBRARY_ARG_INCLUDES} ${LIBRARY_ARG_SOURCES}) 83 | source_group("${PARENTDIR}" FILES ${LIBRARY_ARG_INCLUDES} ${LIBRARY_ARG_SOURCES}) 84 | endfunction() 85 | -------------------------------------------------------------------------------- /data/HE_Rep6_MOB.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpatialTranscriptomicsResearch/st_viewer/635affa24aa3330f946d36c3a630b44d71931bba/data/HE_Rep6_MOB.jpg -------------------------------------------------------------------------------- /src/SettingsStyle.h: -------------------------------------------------------------------------------- 1 | #ifndef SETTINGSSTYLE_H 2 | #define SETTINGSSTYLE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | // TODO The style configuration could be loaded from a QSS file 9 | namespace Style 10 | { 11 | 12 | /** STYLE VARIABLES **/ 13 | 14 | static const QString BUTTON_STYLE_INIT_PAGE 15 | = "{background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, " 16 | " stop:0 rgba(245, 245, 245, 255), " 17 | " stop:1 rgba(255, 255, 255, 255)); " 18 | " border: 1px solid rgb(209, 209, 209); " 19 | " border-radius: 5px;}"; 20 | 21 | static const QString GENERAL_STYLE 22 | = "QTableView {alternate-background-color: rgb(245,245,245); " 23 | " background-color: transparent; " 24 | " selection-background-color: rgb(215,215,215); " 25 | " selection-color: rgb(238,122,0); " 26 | " gridline-color: rgb(240,240,240);" 27 | " border: 1px solid rgb(240,240,240);} " 28 | "QTableView::indicator:unchecked {image: url(:/images/unchecked-box.png);} " 29 | "QTableView::indicator:checked {image: url(:/images/checked-box.png);} " 30 | "QTableView::indicator {padding-left: 10px; " 31 | " width: 15px; " 32 | " height: 15px; " 33 | " background-color: transparent;} " 34 | "QPushButton:focus:pressed {background-color: transparent; border: none;} " 35 | "QPushButton:pressed {background-color: transparent; border: none;} " 36 | "QPushButton:flat {background-color: transparent; border: none;} " 37 | "QHeaderView::section {height: 35px; " 38 | " padding-left: 4px; " 39 | " padding-right: 2px; " 40 | " spacing: 5px;" 41 | " background-color: rgb(230,230,230); " 42 | " border: 1px solid rgb(240,240,240);} " 43 | "QTableCornerButton::section {background-color: transparent;} " 44 | "QLineEdit {border: 1px solid rgb(209,209,209); " 45 | " border-radius: 5px; " 46 | " background-color: rgb(255,255,255); " 47 | " selection-background-color: darkgray;} " 48 | "QToolButton {border: none;} " 49 | "QRadioButton::indicator::unchecked {border: 1px solid darkgray; " 50 | " border-radius: 6px; " 51 | " background-color: white; " 52 | " width: 10px; " 53 | " height: 10px; " 54 | " margin-left: 5px;}" 55 | "QRadioButton::indicator::checked {border: 1px solid darkgray; " 56 | " border-radius: 6px; " 57 | " background-color: rgb(238,122,0); " 58 | " width: 10px; " 59 | " height: 10px; " 60 | " margin-left: 5px;} " 61 | "QComboBox::item::selected {background: rgb(238,122,0);} " 62 | "QMenu::item:selected {background-color: rgb(238,122,0); }"; 63 | static const QString PAGE_WIDGETS_STYLE = "{background-color: rgb(240,240,240);}"; 64 | 65 | static const QString PAGE_FRAME_STYLE = "{background-color: rgb(230,230,230); " 66 | " border-color: rgb(206,202,202);}"; 67 | 68 | static const int CELL_PAGE_SUB_MENU_BUTTON_SPACE = 15; 69 | static const QSize CELL_PAGE_SUB_MENU_BUTTON_SIZE = QSize(40, 30); 70 | static const QSize CELL_PAGE_SUB_MENU_ICON_SIZE = QSize(40, 30); 71 | static const QSize CELL_PAGE_SUB_MENU_LINE_EDIT_SIZE = QSize(150, 25); 72 | static const QString CELL_PAGE_SUB_MENU_BUTTON_STYLE 73 | = "QPushButton {border: 1px solid rgb(209, 209, 209); " 74 | " border-radius: 5px; " 75 | " background-color: rgb(255, 255, 255);}"; 76 | static const QString CELL_PAGE_SUB_MENU_LINE_EDIT_STYLE 77 | = "QLineEdit {border: 1px solid rgb(209, 209, 209); " 78 | " border-radius: 5px; " 79 | " background-color: rgb(255, 255, 255); " 80 | " selection-background-color: darkgray;}"; 81 | } 82 | #endif // SETTINGSSTYLE_H 83 | -------------------------------------------------------------------------------- /src/analysis/AnalysisClustering.h: -------------------------------------------------------------------------------- 1 | #ifndef ANALYSISCLUSTERING_H 2 | #define ANALYSISCLUSTERING_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "data/STData.h" 9 | 10 | namespace Ui { 11 | class analysisClustering; 12 | } 13 | 14 | QT_CHARTS_USE_NAMESPACE 15 | 16 | // A Widget that is used to classify spots based on gene expression profiles 17 | // using dimensionality reduction and clustering algorithms 18 | // It allows users to interact with the scatter plot and make selections 19 | // based on the clustered spots 20 | class AnalysisClustering : public QWidget 21 | { 22 | Q_OBJECT 23 | 24 | public: 25 | explicit AnalysisClustering(QWidget *parent = nullptr, Qt::WindowFlags f = 0); 26 | virtual ~AnalysisClustering(); 27 | 28 | // One color (color representation of cluster number) for each spot 29 | QHash getSpotClusters() const; 30 | 31 | // List of spots for each cluster 32 | QMultiHash getClustersSpot() const; 33 | 34 | // assigns the dataset 35 | void loadData(const STData::STDataFrame &data); 36 | 37 | // resets to default 38 | void clear(); 39 | 40 | // the user selected spots if any 41 | QList selectedSpots() const; 42 | 43 | public slots: 44 | 45 | signals: 46 | 47 | void signalClusteringUpdated(); 48 | void signalClusteringSpotsSelected(); 49 | void signalClusteringExportSelections(); 50 | 51 | private slots: 52 | 53 | // Performs a dimensionality reduction (t-SNE or PCA) on the data matrix and then 54 | // cluster the reduced coordinates (2D) using KMeans or HClust so to compute classes/colors 55 | // for each spot 56 | void slotRun(); 57 | 58 | // exports the scatter plot to a file 59 | void slotExportPlot(); 60 | 61 | // when the user makes a lasso selection on the scatter plot 62 | void slotLassoSelection(const QPainterPath &path); 63 | 64 | // when the user wants to estimate the number of clusters from the data 65 | void slotComputeClusters(); 66 | 67 | private: 68 | 69 | // helper function to do the heavy computations on a different thread 70 | void computeColorsAsync(); 71 | unsigned computeClustersAsync(); 72 | 73 | // function to udpate the widget once the computation of the spot classes is done 74 | void colorsComputed(); 75 | 76 | // function to update the num clusters field once the estimation of the number of classes is done 77 | void classesComputed(); 78 | 79 | // helper function to filter the matrix of counts 80 | mat filterMatrix(); 81 | 82 | // the data 83 | STData::STDataFrame m_data; 84 | 85 | // the results 86 | std::vector m_colors; 87 | mat m_reduced_coordinates; 88 | QList m_spots; 89 | 90 | // the computational threads 91 | QFutureWatcher m_watcher_colors; 92 | QFutureWatcher m_watcher_classes; 93 | 94 | // the user selected spots 95 | QList m_selected_spots; 96 | 97 | // the splot serie's 98 | QList m_series_vector; 99 | 100 | // The UI object 101 | QScopedPointer m_ui; 102 | }; 103 | 104 | #endif // ANALYSISCLUSTERING_H 105 | -------------------------------------------------------------------------------- /src/analysis/AnalysisCorrelation.h: -------------------------------------------------------------------------------- 1 | #ifndef ANALYSISCORRELATION_H 2 | #define ANALYSISCORRELATION_H 3 | 4 | #include 5 | #include 6 | 7 | #include "data/STData.h" 8 | 9 | namespace Ui { 10 | class analysisCorrelation; 11 | } 12 | 13 | QT_CHARTS_USE_NAMESPACE 14 | 15 | // This Widget takes two datasets (selections) 16 | // and computes correlation value for the common genes 17 | // it allows to chose normalization method and log scale and also to click and 18 | // see the clicked gene 19 | class AnalysisCorrelation : public QWidget 20 | { 21 | Q_OBJECT 22 | 23 | public: 24 | AnalysisCorrelation(const STData::STDataFrame &data1, 25 | const STData::STDataFrame &data2, 26 | const QString &nameA, 27 | const QString &nameB, 28 | QWidget *parent = nullptr, 29 | Qt::WindowFlags f = 0); 30 | virtual ~AnalysisCorrelation(); 31 | 32 | private slots: 33 | 34 | // computes and updates the plot and correlation data 35 | void slotUpdateData(); 36 | 37 | // when the user wants to export the plot to a file 38 | void slotExportPlot(); 39 | 40 | // when the user clicks a point in the plot 41 | void slotClickedPoint(const QPointF point); 42 | 43 | private: 44 | 45 | // GUI object 46 | QScopedPointer m_ui; 47 | 48 | // the two datasets 49 | STData::STDataFrame m_dataA; 50 | STData::STDataFrame m_dataB; 51 | QString m_nameA; 52 | QString m_nameB; 53 | 54 | // cache these to know what gene was clicked 55 | std::vector m_rowsumA; 56 | std::vector m_rowsumB; 57 | QList m_genes; 58 | 59 | // store the plotting series to allow interaction with the plot 60 | QScopedPointer m_series; 61 | 62 | Q_DISABLE_COPY(AnalysisCorrelation) 63 | }; 64 | 65 | #endif // ANALYSISCORRELATION_H 66 | -------------------------------------------------------------------------------- /src/analysis/AnalysisDEA.h: -------------------------------------------------------------------------------- 1 | #ifndef ANALYSISDEA_H 2 | #define ANALYSISDEA_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "data/STData.h" 12 | 13 | namespace Ui 14 | { 15 | class analysisDEA; 16 | } 17 | 18 | // AnalysisDEA is a widget that contains methods to compute 19 | // DEA(Differential Expression Analysis) between two ST data selections 20 | // It shows the results in a volcano plot and a table 21 | // that includes the differently expressed genes at a given FDR 22 | class AnalysisDEA : public QWidget 23 | { 24 | Q_OBJECT 25 | 26 | 27 | public: 28 | 29 | enum Method { 30 | DESEQ2 = 1, 31 | EDGER = 2, 32 | }; 33 | 34 | AnalysisDEA(const QList &datasetsA, 35 | const QList &datasetsB, 36 | const QString &nameA, 37 | const QString &nameB, 38 | QWidget *parent = nullptr, 39 | Qt::WindowFlags f = 0); 40 | virtual ~AnalysisDEA(); 41 | 42 | 43 | 44 | signals: 45 | 46 | private slots: 47 | 48 | // the user wants to export the DE genes 49 | void slotExportTable(); 50 | // the user has selected a DE gene in the table 51 | void slotGeneSelected(QModelIndex index); 52 | // when the DE genes have been computed in the worker thread 53 | void slotDEAComputed(); 54 | // to export the volcano plot to a file 55 | void slotExportPlot(); 56 | // to handle when the user right clicks 57 | void customMenuRequested(const QPoint &pos); 58 | 59 | private: 60 | 61 | // to initialize the data (DE genes and volcano plot) 62 | void run(); 63 | void runDEAAsync(const STData::STDataFrame &data); 64 | void updateTable(); 65 | void updatePlot(); 66 | 67 | // GUI object 68 | QScopedPointer m_ui; 69 | 70 | // the merged data frame and the selections names 71 | STData::STDataFrame m_data; 72 | std::vector m_conditions; 73 | QString m_nameA; 74 | QString m_nameB; 75 | 76 | // cache the settings to not recompute always 77 | Method m_method; 78 | int m_reads_threshold; 79 | int m_genes_threshold; 80 | int m_ind_reads_treshold; 81 | int m_spots_threshold; 82 | 83 | // cache the results to not recompute 84 | mat m_results; 85 | std::vector m_results_cols; 86 | std::vector m_results_rows; 87 | 88 | // the gene to highlight in the volcano plot 89 | QPointF m_gene_highlight; 90 | 91 | // the proxy model 92 | QScopedPointer m_proxy; 93 | 94 | // The computational thread 95 | QFutureWatcher m_watcher; 96 | 97 | Q_DISABLE_COPY(AnalysisDEA) 98 | }; 99 | 100 | #endif // ANALYSISDEA_H 101 | -------------------------------------------------------------------------------- /src/analysis/AnalysisPCA.cpp: -------------------------------------------------------------------------------- 1 | #include "AnalysisPCA.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "color/HeatMap.h" 7 | #include "math/RInterface.h" 8 | 9 | #include "ui_AnalysisPCA.h" 10 | 11 | AnalysisPCA::AnalysisPCA(const QList &datasets, 12 | const QList &names, 13 | QWidget *parent, Qt::WindowFlags f) 14 | : QWidget(parent, f) 15 | , m_ui(new Ui::AnalysisPCA) 16 | { 17 | m_ui->setupUi(this); 18 | 19 | QSet merged_genes; 20 | for (unsigned i = 0; i < datasets.size(); ++i) { 21 | const auto data = datasets.at(i); 22 | merged_genes += data.genes.toSet(); 23 | } 24 | QList genes = merged_genes.toList(); 25 | 26 | const unsigned n_rows = datasets.size(); 27 | const unsigned n_cols = merged_genes.size(); 28 | mat merged(n_rows, n_cols); 29 | merged.fill(0.0); 30 | 31 | for (unsigned d = 0; d < datasets.size(); ++d) { 32 | const auto data = datasets.at(d); 33 | const rowvec colsums = sum(data.counts, 0); 34 | for (uword j = 0; j < n_cols; ++j) { 35 | const auto &gene = genes.at(j); 36 | const int index = data.genes.indexOf(gene); 37 | if (index != -1) { 38 | merged.at(d, j) = colsums.at(index); 39 | } 40 | } 41 | } 42 | 43 | mat results; 44 | RInterface::PCA(merged, false, true, results); 45 | 46 | for (unsigned d = 0; d < datasets.size(); ++d) { 47 | QScatterSeries *series = new QScatterSeries(this); 48 | series->setMarkerShape(QScatterSeries::MarkerShapeCircle); 49 | series->setMarkerSize(10.0); 50 | series->setColor(Color::color_list.at(d)); 51 | series->setUseOpenGL(false); 52 | series->setName(names.at(d)); 53 | const float x = results.at(d,0); 54 | const float y = results.at(d,1); 55 | series->append(x, y); 56 | m_ui->plot->chart()->addSeries(series); 57 | } 58 | 59 | const int min_x = results.col(0).min(); 60 | const int max_x = results.col(0).max(); 61 | const int min_y = results.col(1).min(); 62 | const int max_y = results.col(1).max(); 63 | 64 | m_ui->plot->setRenderHint(QPainter::Antialiasing); 65 | m_ui->plot->chart()->setTitle("PCA selections"); 66 | m_ui->plot->chart()->setDropShadowEnabled(false); 67 | m_ui->plot->chart()->legend()->show(); 68 | m_ui->plot->chart()->createDefaultAxes(); 69 | m_ui->plot->chart()->axes(Qt::Horizontal).back()->setGridLineVisible(false); 70 | m_ui->plot->chart()->axes(Qt::Horizontal).back()->setLabelsVisible(true); 71 | m_ui->plot->chart()->axes(Qt::Horizontal).back()->setRange(min_x - 5, max_x + 5); 72 | m_ui->plot->chart()->axes(Qt::Horizontal).back()->setTitleText(tr("PCA 1")); 73 | m_ui->plot->chart()->axes(Qt::Vertical).back()->setGridLineVisible(false); 74 | m_ui->plot->chart()->axes(Qt::Vertical).back()->setLabelsVisible(true); 75 | m_ui->plot->chart()->axes(Qt::Vertical).back()->setRange(min_y - 5, max_y + 5); 76 | m_ui->plot->chart()->axes(Qt::Vertical).back()->setTitleText(tr("PCA 2")); 77 | 78 | connect(m_ui->exportPlot, &QPushButton::clicked, this, &AnalysisPCA::slotExportPlot); 79 | } 80 | 81 | AnalysisPCA::~AnalysisPCA() 82 | { 83 | } 84 | 85 | void AnalysisPCA::slotExportPlot() 86 | { 87 | m_ui->plot->slotExportPlot(tr("PCA plot")); 88 | } 89 | -------------------------------------------------------------------------------- /src/analysis/AnalysisPCA.h: -------------------------------------------------------------------------------- 1 | #ifndef ANALYSISPCA_H 2 | #define ANALYSISPCA_H 3 | 4 | #include 5 | 6 | #include "data/STData.h" 7 | 8 | namespace Ui { 9 | class AnalysisPCA; 10 | } 11 | 12 | class AnalysisPCA : public QWidget 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | 18 | AnalysisPCA(const QList &datasets, 19 | const QList &names, 20 | QWidget *parent = nullptr, Qt::WindowFlags f = 0); 21 | virtual ~AnalysisPCA(); 22 | 23 | private slots: 24 | 25 | // to save the plot to a file 26 | void slotExportPlot(); 27 | 28 | private: 29 | 30 | // GUI object 31 | QScopedPointer m_ui; 32 | 33 | Q_DISABLE_COPY(AnalysisPCA) 34 | }; 35 | 36 | #endif // ANALYSISPCA_H 37 | -------------------------------------------------------------------------------- /src/analysis/AnalysisPCA.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | AnalysisPCA 4 | 5 | 6 | 7 | 0 8 | 0 9 | 688 10 | 532 11 | 12 | 13 | 14 | PCA Analysis 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | Qt::Horizontal 26 | 27 | 28 | 29 | 17 30 | 20 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | PointingHandCursor 39 | 40 | 41 | Export plot to a file 42 | 43 | 44 | Export plot to a file 45 | 46 | 47 | Export 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | ChartView 58 | QGraphicsView 59 |
analysis/ChartView.h
60 |
61 |
62 | 63 | 64 |
65 | -------------------------------------------------------------------------------- /src/analysis/AnalysisQC.cpp: -------------------------------------------------------------------------------- 1 | #include "AnalysisQC.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "ui_analysisQC.h" 8 | 9 | AnalysisQC::AnalysisQC(const STData::STDataFrame &data, 10 | QWidget *parent, Qt::WindowFlags f) 11 | : QWidget(parent, f) 12 | , m_ui(new Ui::analysisQC) 13 | { 14 | m_ui->setupUi(this); 15 | 16 | Q_ASSERT(data.counts.size() > 0); 17 | 18 | // compute the stats 19 | const colvec rowsums = sum(data.counts, 1); 20 | const ucolvec nonzero_row = STData::computeNonZeroRows(data.counts); 21 | const QString max_transcripts_spot = QString::number(rowsums.max()); 22 | const QString max_genes_spot = QString::number(nonzero_row.max()); 23 | const QString num_genes = QString::number(data.counts.n_cols); 24 | const QString num_spots = QString::number(data.counts.n_rows); 25 | const QString total_transcripts = QString::number(accu(data.counts)); 26 | const QString avg_genes = QString::number(mean(nonzero_row)); 27 | const QString avg_transcritps = QString::number(mean(rowsums)); 28 | const QString std_genes = QString::number(stddev(nonzero_row)); 29 | const QString std_transcripts = QString::number(stddev(rowsums)); 30 | const uvec hist_genes = hist(nonzero_row, 10); 31 | const uvec hist_transcripts = hist(rowsums, 10); 32 | 33 | // populate the line edits 34 | m_ui->maxTranscripts->setText(max_transcripts_spot); 35 | m_ui->maxGenes->setText(max_genes_spot); 36 | m_ui->totalGenes->setText(num_genes); 37 | m_ui->totalSpots->setText(num_spots); 38 | m_ui->totalTranscripts->setText(total_transcripts); 39 | m_ui->medianGenes->setText(avg_genes); 40 | m_ui->medianTranscripts->setText(avg_transcritps); 41 | m_ui->stdGenes->setText(std_genes); 42 | m_ui->stdTranscripts->setText(std_transcripts); 43 | 44 | // populate the plots 45 | QBarSet *genes = new QBarSet("Genes"); 46 | for(const auto &value : hist_genes) { 47 | *genes << value; 48 | } 49 | QBarSeries *series_genes = new QBarSeries(); 50 | series_genes->append(genes); 51 | 52 | QBarSet *transcripts = new QBarSet("Transcripts"); 53 | for (const auto &value : hist_transcripts) { 54 | *transcripts << value; 55 | } 56 | QBarSeries *series_transcripts = new QBarSeries(); 57 | series_transcripts->append(transcripts); 58 | 59 | m_ui->genesPlot->chart()->addSeries(series_genes); 60 | m_ui->genesPlot->chart()->setTitle("Histogram genes"); 61 | m_ui->genesPlot->chart()->setAnimationOptions(QChart::SeriesAnimations); 62 | m_ui->genesPlot->chart()->createDefaultAxes(); 63 | m_ui->genesPlot->chart()->axes(Qt::Horizontal).back()->setTitleText("Spots (binned)"); 64 | m_ui->genesPlot->chart()->axes(Qt::Vertical).back()->setTitleText("#Genes"); 65 | 66 | m_ui->transcriptsPlot->chart()->addSeries(series_transcripts); 67 | m_ui->transcriptsPlot->chart()->setTitle("Histogram transcripts"); 68 | m_ui->transcriptsPlot->chart()->setAnimationOptions(QChart::SeriesAnimations); 69 | m_ui->transcriptsPlot->chart()->createDefaultAxes(); 70 | m_ui->transcriptsPlot->chart()->axes(Qt::Horizontal).back()->setTitleText("Spots (binned)"); 71 | m_ui->transcriptsPlot->chart()->axes(Qt::Vertical).back()->setTitleText("#Transcripts"); 72 | 73 | connect(m_ui->exportGenes, &QPushButton::clicked, [=]() {slotExportPlot(1);}); 74 | connect(m_ui->exportTranscripts, &QPushButton::clicked, [=]() {slotExportPlot(2);}); 75 | } 76 | 77 | AnalysisQC::~AnalysisQC() 78 | { 79 | } 80 | 81 | void AnalysisQC::slotExportPlot(const int type) 82 | { 83 | if (type == 1) { 84 | m_ui->genesPlot->slotExportPlot(tr("QC Histogram (Genes)")); 85 | } else { 86 | m_ui->transcriptsPlot->slotExportPlot(tr("QC Histogram (Reads)")); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/analysis/AnalysisQC.h: -------------------------------------------------------------------------------- 1 | #ifndef ANALYSISQC_H 2 | #define ANALYSISQC_H 3 | 4 | #include 5 | 6 | #include "data/STData.h" 7 | 8 | namespace Ui 9 | { 10 | class analysisQC; 11 | } 12 | 13 | // AnalysisQC is a Widget that is used to show to the users 14 | // the counts/genes distributions of a dataset 15 | class AnalysisQC : public QWidget 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | explicit AnalysisQC(const STData::STDataFrame &data, 21 | QWidget *parent = nullptr, 22 | Qt::WindowFlags f = 0); 23 | virtual ~AnalysisQC(); 24 | 25 | signals: 26 | 27 | public slots: 28 | 29 | private slots: 30 | 31 | // to save the histogram to a file (type 1 genes, type 2 transcripts) 32 | void slotExportPlot(const int type); 33 | 34 | private: 35 | 36 | // GUI object 37 | QScopedPointer m_ui; 38 | 39 | Q_DISABLE_COPY(AnalysisQC) 40 | }; 41 | #endif // ANALYSISQC_H 42 | -------------------------------------------------------------------------------- /src/analysis/AnalysisScatter.cpp: -------------------------------------------------------------------------------- 1 | #include "AnalysisScatter.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "color/HeatMap.h" 8 | 9 | #include "ui_analysisScatter.h" 10 | 11 | AnalysisScatter::AnalysisScatter(const STData::STDataFrame &data, 12 | QWidget *parent, Qt::WindowFlags f) 13 | : QWidget(parent, f) 14 | , m_ui(new Ui::analysisScatter) 15 | { 16 | 17 | // setup UI 18 | m_ui->setupUi(this); 19 | 20 | const unsigned num_spots = data.spots.size(); 21 | const colvec spot_reads = sum(data.counts, 1); 22 | const ucolvec spot_genes = STData::computeNonZeroRows(data.counts); 23 | const float min_reads = spot_reads.min(); 24 | const float max_reads = spot_reads.max(); 25 | const float min_genes = spot_genes.min(); 26 | const float max_genes = spot_genes.max(); 27 | for (unsigned i = 0; i < num_spots; ++i) { 28 | QScatterSeries *series_reads = new QScatterSeries(this); 29 | QScatterSeries *series_genes = new QScatterSeries(this); 30 | series_reads->setMarkerShape(QScatterSeries::MarkerShapeCircle); 31 | series_reads->setMarkerSize(10.0); 32 | series_reads->setUseOpenGL(false); 33 | 34 | series_genes->setMarkerShape(QScatterSeries::MarkerShapeCircle); 35 | series_genes->setMarkerSize(10.0); 36 | series_genes->setUseOpenGL(false); 37 | 38 | const auto &spot = Spot::getCoordinates(data.spots.at(i)); 39 | const float value_reads = spot_reads.at(i); 40 | const float value_genes = spot_genes.at(i); 41 | const QColor color_reads = Color::createCMapColor(value_reads, min_reads, 42 | max_reads, Color::ColorGradients::gpHot); 43 | const QColor color_genes = Color::createCMapColor(value_genes, min_genes, 44 | max_genes, Color::ColorGradients::gpHot); 45 | series_reads->setColor(color_reads); 46 | series_reads->append(spot.first, spot.second * -1); 47 | m_ui->plotReads->chart()->addSeries(series_reads); 48 | 49 | series_genes->setColor(color_genes); 50 | series_genes->append(spot.first, spot.second * -1); 51 | m_ui->plotGenes->chart()->addSeries(series_genes); 52 | } 53 | 54 | m_ui->plotReads->chart()->setTitle(tr("Spots colored by expression (transcripts)")); 55 | m_ui->plotReads->chart()->setDropShadowEnabled(false); 56 | m_ui->plotReads->chart()->legend()->hide(); 57 | m_ui->plotReads->chart()->createDefaultAxes(); 58 | m_ui->plotReads->chart()->axes(Qt::Horizontal).back()->setGridLineVisible(false); 59 | m_ui->plotReads->chart()->axes(Qt::Horizontal).back()->setLabelsVisible(true); 60 | m_ui->plotReads->chart()->axes(Qt::Horizontal).back()->setTitleText(tr("Spot(X)")); 61 | m_ui->plotReads->chart()->axes(Qt::Vertical).back()->setGridLineVisible(false); 62 | m_ui->plotReads->chart()->axes(Qt::Vertical).back()->setLabelsVisible(true); 63 | m_ui->plotReads->chart()->axes(Qt::Vertical).back()->setTitleText(tr("Spot(Y)")); 64 | 65 | m_ui->plotGenes->chart()->setTitle(tr("Spots colored by expression (genes)")); 66 | m_ui->plotGenes->chart()->setDropShadowEnabled(false); 67 | m_ui->plotGenes->chart()->legend()->hide(); 68 | m_ui->plotGenes->chart()->createDefaultAxes(); 69 | m_ui->plotGenes->chart()->axes(Qt::Horizontal).back()->setGridLineVisible(false); 70 | m_ui->plotGenes->chart()->axes(Qt::Horizontal).back()->setLabelsVisible(true); 71 | m_ui->plotGenes->chart()->axes(Qt::Horizontal).back()->setTitleText(tr("Spot(X)")); 72 | m_ui->plotGenes->chart()->axes(Qt::Vertical).back()->setGridLineVisible(false); 73 | m_ui->plotGenes->chart()->axes(Qt::Vertical).back()->setLabelsVisible(true); 74 | m_ui->plotGenes->chart()->axes(Qt::Vertical).back()->setTitleText(tr("Spot(Y)")); 75 | 76 | connect(m_ui->exportReads, &QPushButton::clicked, this, &AnalysisScatter::slotExportPlotReads); 77 | connect(m_ui->exportGenes, &QPushButton::clicked, this, &AnalysisScatter::slotExportPlotGenes); 78 | } 79 | 80 | AnalysisScatter::~AnalysisScatter() 81 | { 82 | 83 | } 84 | 85 | void AnalysisScatter::slotExportPlotReads() 86 | { 87 | m_ui->plotReads->slotExportPlot(tr("Save Scatter Transcripts Plot")); 88 | } 89 | 90 | void AnalysisScatter::slotExportPlotGenes() 91 | { 92 | m_ui->plotGenes->slotExportPlot(tr("Save Scatter Genes Plot")); 93 | } 94 | -------------------------------------------------------------------------------- /src/analysis/AnalysisScatter.h: -------------------------------------------------------------------------------- 1 | #ifndef ANALYSISSCATTER_H 2 | #define ANALYSISSCATTER_H 3 | 4 | #include 5 | 6 | #include "data/STData.h" 7 | 8 | namespace Ui 9 | { 10 | class analysisScatter; 11 | } 12 | 13 | // This widget takes a data frame and shows two 14 | // heatmap scatter plots, one with the accumulate 15 | // counts for each spot and another one with the accumulate 16 | // genes for each spot 17 | class AnalysisScatter : public QWidget 18 | { 19 | Q_OBJECT 20 | 21 | public: 22 | 23 | AnalysisScatter(const STData::STDataFrame &data, 24 | QWidget *parent = nullptr, 25 | Qt::WindowFlags f = 0); 26 | 27 | virtual ~AnalysisScatter(); 28 | 29 | signals: 30 | 31 | public slots: 32 | 33 | private slots: 34 | 35 | // to export the scatter plots to a file 36 | void slotExportPlotGenes(); 37 | void slotExportPlotReads(); 38 | 39 | private: 40 | 41 | // GUI object 42 | QScopedPointer m_ui; 43 | 44 | Q_DISABLE_COPY(AnalysisScatter) 45 | }; 46 | 47 | #endif // ANALYSISSCATTER_H 48 | -------------------------------------------------------------------------------- /src/analysis/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LIBRARY_ARG_INCLUDES 2 | AnalysisDEA.h 3 | AnalysisQC.h 4 | AnalysisCorrelation.h 5 | AnalysisClustering.h 6 | AnalysisScatter.h 7 | AnalysisPCA.h 8 | ChartView.h 9 | ) 10 | 11 | set(LIBRARY_ARG_SOURCES 12 | AnalysisDEA.cpp 13 | AnalysisQC.cpp 14 | AnalysisCorrelation.cpp 15 | AnalysisClustering.cpp 16 | AnalysisScatter.cpp 17 | AnalysisPCA.cpp 18 | ChartView.cpp 19 | ) 20 | 21 | ST_LIBRARY() 22 | -------------------------------------------------------------------------------- /src/analysis/ChartView.h: -------------------------------------------------------------------------------- 1 | #ifndef CHARTVIEW_H 2 | #define CHARTVIEW_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | QT_CHARTS_USE_NAMESPACE 9 | 10 | // A simple wrapper around QChartView to allow zooming and mouse events 11 | class ChartView : public QChartView 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | 17 | explicit ChartView(QWidget *parent = nullptr); 18 | virtual ~ChartView(); 19 | 20 | signals: 21 | 22 | void signalLassoSelection(QPainterPath); 23 | 24 | 25 | public slots: 26 | 27 | void slotExportPlot(const QString &title); 28 | 29 | protected: 30 | 31 | bool viewportEvent(QEvent *event) override; 32 | void mousePressEvent(QMouseEvent *event) override; 33 | void mouseMoveEvent(QMouseEvent *event) override; 34 | void mouseReleaseEvent(QMouseEvent *event) override; 35 | void wheelEvent(QWheelEvent *event) override; 36 | void keyPressEvent(QKeyEvent *event) override; 37 | void drawForeground(QPainter *painter, const QRectF &rect) override; 38 | void paintEvent(QPaintEvent *event) override; 39 | 40 | private: 41 | 42 | bool m_panning; 43 | bool m_lassoSelection; 44 | QPoint m_originPanning; 45 | QPoint m_originLasso; 46 | QPainterPath m_lasso; 47 | }; 48 | 49 | #endif // CHARTVIEW_H 50 | -------------------------------------------------------------------------------- /src/analysis/analysisScatter.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | analysisScatter 4 | 5 | 6 | 7 | 0 8 | 0 9 | 1236 10 | 475 11 | 12 | 13 | 14 | Scatter plots (Transcripts and Genes)) 15 | 16 | 17 | Qt::LeftToRight 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 0 27 | 0 28 | 29 | 30 | 31 | 32 | 600 33 | 400 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 0 43 | 0 44 | 45 | 46 | 47 | 48 | 600 49 | 400 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | Qt::Horizontal 62 | 63 | 64 | 65 | 40 66 | 20 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | Export the scatter plot of genes to a file 75 | 76 | 77 | Export the scatter plot of genes to a file 78 | 79 | 80 | Export Genes 81 | 82 | 83 | 84 | 85 | 86 | 87 | Export the scatter plot of transcripts to a file 88 | 89 | 90 | Export the scatter plot of transcripts to a file 91 | 92 | 93 | Export Transcripts 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | ChartView 104 | QGraphicsView 105 |
analysis/ChartView.h
106 |
107 |
108 | 109 | 110 |
111 | -------------------------------------------------------------------------------- /src/color/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LIBRARY_ARG_INCLUDES 2 | HeatMap.h 3 | ) 4 | 5 | set(LIBRARY_ARG_SOURCES 6 | HeatMap.cpp 7 | ) 8 | 9 | ST_LIBRARY() 10 | 11 | -------------------------------------------------------------------------------- /src/color/HeatMap.h: -------------------------------------------------------------------------------- 1 | #ifndef HEATMAP_H 2 | #define HEATMAP_H 3 | 4 | #include "math/Common.h" 5 | #include "qcustomplot.h" 6 | #include "viewPages/SettingsWidget.h" 7 | 8 | class QImage; 9 | 10 | // Heatmap is a convenience namespace containing functions to generate 11 | // heatmap related images and data. 12 | namespace Color 13 | { 14 | 15 | typedef QCPColorGradient::GradientPreset ColorGradients; 16 | 17 | // Convenience function to generate a heatmap spectrum image given specific 18 | // mapping function 19 | // using the wave lenght spectra or a linear interpolation spectra between two 20 | // colors 21 | // the input image will be transformed with the new colors 22 | void createLegend(QImage &image, const float lowerbound, 23 | const float upperbound, const ColorGradients cmap); 24 | 25 | // Convenience function to generate a QColor color from a real value 26 | QColor createHeatMapWaveLenghtColor(const float value); 27 | 28 | // Convenience function to generate a QColor color from a real value given a 29 | // range 30 | QColor createHeatMapLinearColor(const float value, const float min, const float max); 31 | 32 | // Function that creates a dynamic color (alpha adjusted to the value given and min-max) 33 | QColor createDynamicRangeColor(const float value, const float min, const float max, const QColor color); 34 | 35 | // Functions to create a color mapped in the color range given 36 | QColor createRangeColor(const float value, const float min, const float max, 37 | const QColor init, const QColor end); 38 | 39 | // Functions to create a color from a pre-set color map 40 | QColor createCMapColor(const float value, const float min, const float max, 41 | const ColorGradients cmap); 42 | 43 | // helper fuctions to adjust a spot's color according to the rendering settings 44 | QColor adjustVisualMode(const QColor merged_color, 45 | const float &merged_value, 46 | const float &min_reads, 47 | const float &max_reads, 48 | const SettingsWidget::VisualMode mode); 49 | 50 | static QStringList color_list = (QStringList() << "red" << "green" 51 | << "blue" << "cyan" << "magenta" 52 | << "yellow" << "black" << "grey" 53 | << "darkBlue" << "darkGreen" << "darkRed" 54 | << "darkCyan" << "darkYellow" << "darkMagenta"); 55 | } 56 | 57 | #endif // HEATMAP_H // 58 | -------------------------------------------------------------------------------- /src/config/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LIBRARY_ARG_INCLUDES 2 | Configuration.h 3 | SettingsFormatXML.h 4 | ) 5 | set(LIBRARY_ARG_SOURCES 6 | Configuration.cpp 7 | SettingsFormatXML.cpp 8 | ) 9 | 10 | ST_LIBRARY() 11 | -------------------------------------------------------------------------------- /src/config/Configuration.cpp: -------------------------------------------------------------------------------- 1 | #include "Configuration.h" 2 | #include 3 | #include "SettingsFormatXML.h" 4 | #include "options_cmake.h" 5 | #include 6 | #include 7 | #include 8 | 9 | static const QString SettingsPrefixConfFile = QStringLiteral("configuration"); 10 | 11 | Configuration::Configuration() 12 | : m_settings(nullptr) 13 | { 14 | QSettings::Format format = QSettings::registerFormat("conf", 15 | &SettingsFormatXML::readXMLFile, 16 | &SettingsFormatXML::writeXMLFile); 17 | QDir dir(QApplication::applicationDirPath()); 18 | #if defined Q_OS_MAC 19 | dir.cdUp(); 20 | dir.cd("Resources"); 21 | #endif 22 | const QString config_file = dir.canonicalPath() + QDir::separator() + CONFIG_FILE; 23 | m_settings.reset(new QSettings(config_file, format, nullptr)); 24 | } 25 | 26 | Configuration::~Configuration() 27 | { 28 | } 29 | 30 | const QString Configuration::readSetting(const QString &key) const 31 | { 32 | // early out 33 | if (!is_valid()) { 34 | return QString(); 35 | } 36 | 37 | m_settings->beginGroup(SettingsPrefixConfFile); 38 | const QVariant value = m_settings->value(key); 39 | m_settings->endGroup(); 40 | if (!value.isValid() || !value.canConvert(QVariant::String)) { 41 | qDebug() << "[Configuration] Warning: Invalid configuration key:" 42 | << (SettingsPrefixConfFile + SettingsFormatXML::GROUP_DELIMITER + key); 43 | return QString(); 44 | } 45 | 46 | return value.toString(); 47 | } 48 | 49 | bool Configuration::is_valid() const 50 | { 51 | return !m_settings.isNull() && m_settings->status() == QSettings::NoError; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/config/Configuration.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIGURATION_H 2 | #define CONFIGURATION_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | // Configuration is a convenience class that simplifies the access of 9 | // statically stored configuration data by providing a globally 10 | // accessible instance thanks to the fact that the data 11 | // is stored in QSettings 12 | class Configuration 13 | { 14 | 15 | public: 16 | Configuration(); 17 | ~Configuration(); 18 | 19 | // TODO if more settings are added let each object accessing the 20 | // configurations store the access string literals as static values 21 | // and make readSetting public instead. doesn't make sense to provide 22 | // each setting as a function. 23 | 24 | // True if the QSettings object is initilized and valid 25 | bool is_valid() const; 26 | 27 | private: 28 | // reads the setting stored in the key given and returns 29 | // its value or empty string if there was a problem 30 | const QString readSetting(const QString &key) const; 31 | 32 | QScopedPointer m_settings; 33 | 34 | Q_DISABLE_COPY(Configuration) 35 | }; 36 | 37 | #endif /* CONFIGURATION_H */ 38 | -------------------------------------------------------------------------------- /src/config/SettingsFormatXML.cpp: -------------------------------------------------------------------------------- 1 | #include "SettingsFormatXML.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | // static char defining the delimiting characters when parsing to settings 9 | // format, default '/' 10 | const QChar SettingsFormatXML::GROUP_DELIMITER = QDir::separator(); 11 | 12 | bool SettingsFormatXML::readXMLFile(QIODevice &device, QSettings::SettingsMap &map) 13 | { 14 | Q_UNUSED(device); 15 | 16 | QXmlStreamReader xmlReader(&device); 17 | QStringList elements; 18 | 19 | // read until end is reached or error occurs 20 | while (!xmlReader.atEnd() && !xmlReader.hasError()) { 21 | // get next token 22 | xmlReader.readNext(); 23 | // if node push it to element list 24 | if (xmlReader.isStartElement()) { 25 | elements.append(xmlReader.name().toString()); 26 | // if end node pop 27 | } else if (xmlReader.isEndElement()) { 28 | if (!elements.isEmpty()) { 29 | elements.removeLast(); 30 | } 31 | // if it is some data (excl. whitespaces) parse it 32 | } else if (xmlReader.isCharacters() && !xmlReader.isWhitespace()) { 33 | QString key = elements.join('/'); 34 | map[key] = xmlReader.text().toString(); 35 | } 36 | } 37 | 38 | // show warning on error 39 | if (xmlReader.hasError()) { 40 | qDebug() << xmlReader.errorString(); 41 | return false; 42 | } 43 | 44 | return true; 45 | } 46 | 47 | bool SettingsFormatXML::writeXMLFile(QIODevice &device, const QSettings::SettingsMap &map) 48 | { 49 | Q_UNUSED(device); 50 | Q_UNUSED(map); 51 | 52 | // NOTE: implement if needed 53 | // check "http://www.openshots.de/2011/03/qsettings-mit-xml-format/" for example 54 | return true; 55 | } 56 | -------------------------------------------------------------------------------- /src/config/SettingsFormatXML.h: -------------------------------------------------------------------------------- 1 | #ifndef SETTINGSFORMATXML_H 2 | #define SETTINGSFORMATXML_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | // Import/Export plug-in for saving settings data in an XML format. 9 | 10 | // TODO replace for namespace and remove the class 11 | class SettingsFormatXML 12 | { 13 | 14 | public: 15 | static const QChar GROUP_DELIMITER; 16 | 17 | static bool writeXMLFile(QIODevice &device, const QSettings::SettingsMap &map); 18 | static bool readXMLFile(QIODevice &device, QSettings::SettingsMap &map); 19 | }; 20 | 21 | #endif // SETTINGSFORMATXML_H // 22 | -------------------------------------------------------------------------------- /src/data/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LIBRARY_ARG_INCLUDES 2 | DatasetImporter.h 3 | Dataset.h 4 | Spot.h 5 | Gene.h 6 | UserSelection.h 7 | STData.h 8 | ) 9 | 10 | set(LIBRARY_ARG_SOURCES 11 | DatasetImporter.cpp 12 | Dataset.cpp 13 | Spot.cpp 14 | Gene.cpp 15 | UserSelection.cpp 16 | STData.cpp 17 | ) 18 | 19 | ST_LIBRARY() 20 | 21 | -------------------------------------------------------------------------------- /src/data/Dataset.h: -------------------------------------------------------------------------------- 1 | #ifndef DATASET_H 2 | #define DATASET_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class STData; 9 | class DatasetImporter; 10 | 11 | // Data model class to store datasets. 12 | class Dataset 13 | { 14 | 15 | public: 16 | Dataset(); 17 | explicit Dataset(const DatasetImporter &importer); 18 | explicit Dataset(const Dataset &other); 19 | ~Dataset(); 20 | 21 | Dataset &operator=(const Dataset &other); 22 | bool operator==(const Dataset &other) const; 23 | 24 | // The reference to the ST Data matrix 25 | const QSharedPointer data() const; 26 | 27 | // Getters 28 | const QString name() const; 29 | const QString dataFile() const; 30 | const QTransform imageAlignment() const; 31 | const QString imageAlignmentFile() const; 32 | const QString imageFile() const; 33 | const QString spotsFile() const; 34 | const QString statTissue() const; 35 | const QString statSpecies() const; 36 | const QString statComments() const; 37 | const QRect chip() const; 38 | 39 | // Setters 40 | void name(const QString &name); 41 | void dataFile(const QString &datafile); 42 | void imageAlignment(const QTransform &alignment); 43 | void imageAlignmentFile(const QString &aligment_file); 44 | void imageFile(const QString &image_file); 45 | void spotsFile(const QString &spots_file); 46 | void statTissue(const QString &statTissue); 47 | void statSpecies(const QString &statSpecies); 48 | void statComments(const QString &statComments); 49 | void chip(const QRect &chip); 50 | 51 | // creates the STData object (parse data) 52 | // Parses : matrix of counts, image, size factors (if any), alignment (if any), 53 | // spots-file (if any) and spike-in (if any) 54 | // throws exception if parsing is something went wrong 55 | void load_data(); 56 | 57 | private: 58 | 59 | // Private function to load the image aligment matrix from a file 60 | bool load_imageAligment(); 61 | 62 | QString m_name; 63 | QString m_statTissue; 64 | QString m_statSpecies; 65 | QString m_statComments; 66 | QString m_data_file; 67 | QString m_image_file; 68 | QString m_alignment_file; 69 | QString m_spots_file; 70 | QRect m_chip; 71 | 72 | // generated 73 | QTransform m_alignment; 74 | QSharedPointer m_data; 75 | }; 76 | 77 | #endif // DATASET_H 78 | -------------------------------------------------------------------------------- /src/data/DatasetImporter.h: -------------------------------------------------------------------------------- 1 | #ifndef DATASETIMPORTER_H 2 | #define DATASETIMPORTER_H 3 | 4 | #include 5 | #include 6 | 7 | namespace Ui 8 | { 9 | class DatasetImporter; 10 | } 11 | 12 | class Dataset; 13 | 14 | // This widget allows the user to import a dataset. 15 | // The widget asks the user to introduce the STData (matrix), 16 | // the tissue image and optionally a 3x3 alignment matrix and 17 | // a file mapping coordiantes to new coordinates 18 | class DatasetImporter : public QDialog 19 | { 20 | Q_OBJECT 21 | 22 | public: 23 | explicit DatasetImporter(QWidget *parent = 0); 24 | DatasetImporter(const Dataset &dataset, QWidget *parent = 0); 25 | ~DatasetImporter(); 26 | 27 | const QString datasetName() const; 28 | const QString STDataFile() const; 29 | const QString alignmentMatrix() const; 30 | const QString spotsMapFile() const; 31 | const QString mainImageFile() const; 32 | const QString species() const; 33 | const QString tissue() const; 34 | const QString comments() const; 35 | const QRect chip() const; 36 | 37 | // To import a dataset from a folder 38 | // the function assumes that 39 | // the image is called *.jpg 40 | // the data is called *.tsv 41 | // the aligment is called alignment.txt 42 | // the spots file is called spots.txt 43 | // the metadata is present in a JSON file called info.json 44 | void slotParseFolder(); 45 | 46 | // To import a dataset from a metafile (JSON) 47 | // the file contains the path for each file of the datset 48 | // indentifiable with the key 49 | void slotParseMetaFile(); 50 | 51 | protected: 52 | 53 | void done(int result) override; 54 | 55 | private slots: 56 | 57 | void slotLoadSTDataFile(); 58 | void slotLoadMainImageFile(); 59 | void slotLoadSpotsMapFile(); 60 | void slotLoadAlignmentFile(); 61 | 62 | private: 63 | void init(); 64 | void parseInfoJSON(const QString &filename); 65 | QScopedPointer m_ui; 66 | 67 | }; 68 | 69 | #endif // DATASETIMPORTER_H 70 | -------------------------------------------------------------------------------- /src/data/Gene.cpp: -------------------------------------------------------------------------------- 1 | #include "Gene.h" 2 | 3 | Gene::Gene() 4 | : m_name() 5 | , m_color(Qt::red) 6 | , m_visible(false) 7 | , m_selected(false) 8 | , m_cutoff(0) 9 | , m_totalCount(0) 10 | { 11 | } 12 | 13 | Gene::Gene(const QString &name) 14 | : m_name(name) 15 | , m_color(Qt::red) 16 | , m_visible(false) 17 | , m_selected(false) 18 | , m_cutoff(0) 19 | , m_totalCount(0) 20 | { 21 | } 22 | 23 | Gene::Gene(const Gene &other) 24 | : m_name(other.m_name) 25 | , m_color(other.m_color) 26 | , m_visible(other.m_visible) 27 | , m_selected(other.m_selected) 28 | , m_cutoff(other.m_cutoff) 29 | , m_totalCount(other.m_totalCount) 30 | { 31 | } 32 | 33 | Gene::~Gene() 34 | { 35 | } 36 | 37 | Gene &Gene::operator=(const Gene &other) 38 | { 39 | m_name = other.m_name; 40 | m_visible = other.m_visible; 41 | m_selected = other.m_selected; 42 | m_color = other.m_color; 43 | m_cutoff = other.m_cutoff; 44 | m_totalCount = other.m_totalCount; 45 | return (*this); 46 | } 47 | 48 | bool Gene::operator==(const Gene &other) const 49 | { 50 | return (m_visible == other.m_visible 51 | && m_selected == other.m_selected 52 | && m_name == other.m_name 53 | && m_color == other.m_color 54 | && m_cutoff == other.m_cutoff 55 | && m_totalCount == other.m_totalCount); 56 | } 57 | 58 | const QString Gene::name() const 59 | { 60 | return m_name; 61 | } 62 | 63 | bool Gene::visible() const 64 | { 65 | return m_visible; 66 | } 67 | 68 | bool Gene::selected() const 69 | { 70 | return m_selected; 71 | } 72 | 73 | const QColor Gene::color() const 74 | { 75 | return m_color; 76 | } 77 | 78 | float Gene::cut_off() const 79 | { 80 | return m_cutoff; 81 | } 82 | 83 | float Gene::totalCount() const 84 | { 85 | return m_totalCount; 86 | } 87 | 88 | void Gene::name(const QString &name) 89 | { 90 | m_name = name; 91 | } 92 | 93 | void Gene::visible(const bool visible) 94 | { 95 | m_visible = visible; 96 | } 97 | 98 | void Gene::selected(const bool selected) 99 | { 100 | m_selected = selected; 101 | } 102 | 103 | void Gene::color(const QColor &color) 104 | { 105 | m_color = color; 106 | } 107 | 108 | void Gene::cut_off(const float cutoff) 109 | { 110 | m_cutoff = cutoff; 111 | } 112 | 113 | void Gene::totalCount(const float totalCount) 114 | { 115 | m_totalCount = totalCount; 116 | } 117 | -------------------------------------------------------------------------------- /src/data/Gene.h: -------------------------------------------------------------------------------- 1 | #ifndef GENE_H 2 | #define GENE_H 3 | 4 | #include 5 | #include 6 | 7 | // Data model class to store gene data. 8 | // The genes are part of the ST Data, they are modeled in a class 9 | // to encapculate their status and attributes 10 | class Gene 11 | { 12 | 13 | public: 14 | 15 | Gene(); 16 | explicit Gene(const QString &name); 17 | explicit Gene(const Gene &other); 18 | ~Gene(); 19 | 20 | Gene &operator=(const Gene &other); 21 | bool operator==(const Gene &other) const; 22 | 23 | // the name of the gene 24 | const QString name() const; 25 | // true if gene is visible 26 | bool visible() const; 27 | // true if the gene is selected 28 | bool selected() const; 29 | // the color of the gene 30 | const QColor color() const; 31 | // the threshold (reads) 32 | // the gene cut-off is used to discard genes whose count is below the cut off 33 | float cut_off() const; 34 | // the total number of transcripts for the gene in the dataset 35 | float totalCount() const; 36 | 37 | // Setters 38 | void name(const QString &name); 39 | void visible(const bool visible); 40 | void selected(const bool selected); 41 | void color(const QColor &color); 42 | void cut_off(const float cutoff); 43 | void totalCount(const float totalCount); 44 | 45 | private: 46 | QString m_name; 47 | QColor m_color; 48 | bool m_visible; 49 | bool m_selected; 50 | float m_cutoff; 51 | float m_totalCount; 52 | }; 53 | 54 | #endif // GENE_H // 55 | -------------------------------------------------------------------------------- /src/data/Spot.cpp: -------------------------------------------------------------------------------- 1 | #include "data/Spot.h" 2 | 3 | Spot::Spot() 4 | : m_coordinates(0,0) 5 | , m_visible(false) 6 | , m_selected(false) 7 | , m_color(Qt::black) 8 | , m_name() 9 | , m_totalCount(0) 10 | { 11 | 12 | } 13 | 14 | Spot::Spot(const QString name) 15 | : m_coordinates(0,0) 16 | , m_adj_coordinates(0,0) 17 | , m_visible(false) 18 | , m_selected(false) 19 | , m_color(Qt::white) 20 | , m_name(name) 21 | , m_totalCount(0) 22 | { 23 | 24 | m_coordinates = getCoordinates(name); 25 | m_adj_coordinates = m_coordinates; 26 | } 27 | 28 | Spot::Spot(const Spot &other) 29 | { 30 | m_coordinates = other.m_coordinates; 31 | m_adj_coordinates = other.m_adj_coordinates; 32 | m_color = other.m_color; 33 | m_name = other.m_name; 34 | m_visible = other.m_visible; 35 | m_selected = other.m_selected; 36 | m_totalCount = other.m_totalCount; 37 | } 38 | 39 | Spot::~Spot() 40 | { 41 | } 42 | 43 | Spot &Spot::operator=(const Spot &other) 44 | { 45 | m_coordinates = other.m_coordinates; 46 | m_adj_coordinates = other.m_adj_coordinates; 47 | m_visible = other.m_visible; 48 | m_selected = other.m_selected; 49 | m_color = other.m_color; 50 | m_name = other.m_name; 51 | m_totalCount = other.m_totalCount; 52 | return (*this); 53 | } 54 | 55 | bool Spot::operator==(const Spot &other) const 56 | { 57 | return (m_coordinates == other.m_coordinates 58 | && m_adj_coordinates == other.m_adj_coordinates 59 | && m_visible == other.m_visible 60 | && m_selected == other.m_selected 61 | && m_color == other.m_color 62 | && m_name == other.m_name 63 | && m_totalCount == other.m_totalCount); 64 | } 65 | 66 | Spot::SpotType Spot::coordinates() const 67 | { 68 | return m_coordinates; 69 | } 70 | 71 | Spot::SpotType Spot::adj_coordinates() const 72 | { 73 | return m_adj_coordinates; 74 | } 75 | 76 | QColor Spot::color() const 77 | { 78 | return m_color; 79 | } 80 | 81 | QString Spot::name() const 82 | { 83 | return m_name; 84 | } 85 | 86 | bool Spot::visible() const 87 | { 88 | return m_visible; 89 | } 90 | 91 | bool Spot::selected() const 92 | { 93 | return m_selected; 94 | } 95 | 96 | float Spot::totalCount() const 97 | { 98 | return m_totalCount; 99 | } 100 | 101 | void Spot::coordinates(const SpotType &coordinates) 102 | { 103 | m_coordinates = coordinates; 104 | } 105 | 106 | void Spot::adj_coordinates(const SpotType &adj_coordinates) 107 | { 108 | m_adj_coordinates = adj_coordinates; 109 | } 110 | 111 | void Spot::visible(const bool visible) 112 | { 113 | m_visible = visible; 114 | } 115 | 116 | void Spot::selected(const bool selected) 117 | { 118 | m_selected = selected; 119 | } 120 | 121 | void Spot::color(const QColor color) 122 | { 123 | m_color = color; 124 | } 125 | 126 | void Spot::totalCount(const float totalCount) 127 | { 128 | m_totalCount = totalCount; 129 | } 130 | 131 | 132 | Spot::SpotType Spot::getCoordinates(const QString &spot) 133 | { 134 | const QStringList items = spot.trimmed().split("x"); 135 | Q_ASSERT(items.size() == 2); 136 | const float x = items.at(0).toFloat(); 137 | const float y = items.at(1).toFloat(); 138 | return SpotType(x,y); 139 | } 140 | 141 | QString Spot::getSpot(const Spot::SpotType &spot) 142 | { 143 | return QString::number(spot.first) + "x" + QString::number(spot.second); 144 | } 145 | -------------------------------------------------------------------------------- /src/data/Spot.h: -------------------------------------------------------------------------------- 1 | #ifndef SPOT_H 2 | #define SPOT_H 3 | 4 | #include 5 | #include 6 | 7 | // Data model class to store spot data 8 | // Each spot correspond to a spot in the the array and it is 9 | // defined by two int/float coordinates. 10 | // Extra attributes for the spots are added in this data model 11 | class Spot 12 | { 13 | 14 | public: 15 | typedef QPair SpotType; 16 | 17 | Spot(); 18 | Spot(const QString name); 19 | explicit Spot(const Spot &other); 20 | ~Spot(); 21 | 22 | Spot &operator=(const Spot &other); 23 | bool operator==(const Spot &other) const; 24 | 25 | // the spot's coordinates 26 | SpotType coordinates() const; 27 | // the spot's adjusted coordinates (only useful for plotting) 28 | SpotType adj_coordinates() const; 29 | // the spot's coordinates as a string 30 | QString name() const; 31 | // the spot's color 32 | QColor color() const; 33 | // true if the spot is visible 34 | bool visible() const; 35 | // true if the spot is selected 36 | bool selected() const; 37 | // the total number of transcripts for the spot in the dataset 38 | float totalCount() const; 39 | 40 | // Setters 41 | void coordinates(const SpotType &coordinates); 42 | void adj_coordinates(const SpotType &adj_coordinates); 43 | void color(const QColor color); 44 | void visible(const bool visible); 45 | void selected(const bool selected); 46 | void name(const QString &name); 47 | void totalCount(const float totalCoun); 48 | 49 | // helper method to get coordinates (x,y) from a spot 50 | static SpotType getCoordinates(const QString &spot); 51 | // helper method to get a string representation (XxY) of a spot 52 | static QString getSpot(const SpotType &spot); 53 | 54 | private: 55 | SpotType m_coordinates; 56 | SpotType m_adj_coordinates; 57 | bool m_visible; 58 | bool m_selected; 59 | QColor m_color; 60 | QString m_name; 61 | float m_totalCount; 62 | }; 63 | 64 | #endif // SPOT_H 65 | -------------------------------------------------------------------------------- /src/data/UserSelection.cpp: -------------------------------------------------------------------------------- 1 | #include "UserSelection.h" 2 | 3 | UserSelection::UserSelection() 4 | : m_name() 5 | , m_dataset() 6 | , m_data() 7 | , m_comment() 8 | { 9 | } 10 | 11 | UserSelection::UserSelection(const STData::STDataFrame &data) 12 | : m_name() 13 | , m_dataset() 14 | , m_data(data) 15 | , m_comment() 16 | { 17 | } 18 | 19 | UserSelection::~UserSelection() 20 | { 21 | } 22 | 23 | UserSelection::UserSelection(const UserSelection &other) 24 | { 25 | m_name = other.m_name; 26 | m_dataset = other.m_dataset; 27 | m_data = other.m_data; 28 | m_comment = other.m_comment; 29 | } 30 | 31 | UserSelection &UserSelection::operator=(const UserSelection &other) 32 | { 33 | m_name = other.m_name; 34 | m_dataset = other.m_dataset; 35 | m_data = other.m_data; 36 | m_comment = other.m_comment; 37 | return (*this); 38 | } 39 | 40 | bool UserSelection::operator==(const UserSelection &other) const 41 | { 42 | return (m_name == other.m_name 43 | && m_dataset == other.m_dataset 44 | //TODO gotta fix the == for the Matrix type 45 | //&& m_data.counts == other.m_data.counts 46 | && m_data.genes == other.m_data.genes 47 | && m_data.spots == other.m_data.spots 48 | && m_comment == other.m_comment); 49 | } 50 | 51 | const QString UserSelection::name() const 52 | { 53 | return m_name; 54 | } 55 | 56 | const QString UserSelection::dataset() const 57 | { 58 | return m_dataset; 59 | } 60 | 61 | const STData::STDataFrame &UserSelection::data() const 62 | { 63 | return m_data; 64 | } 65 | 66 | const QString UserSelection::comment() const 67 | { 68 | return m_comment; 69 | } 70 | 71 | int UserSelection::totalGenes() const 72 | { 73 | return m_data.genes.size(); 74 | } 75 | 76 | int UserSelection::totalSpots() const 77 | { 78 | return m_data.spots.size(); 79 | } 80 | 81 | void UserSelection::name(const QString &name) 82 | { 83 | m_name = name; 84 | } 85 | 86 | void UserSelection::dataset(const QString &dataset) 87 | { 88 | m_dataset = dataset; 89 | } 90 | 91 | void UserSelection::comment(const QString &comment) 92 | { 93 | m_comment = comment; 94 | } 95 | 96 | void UserSelection::data(const STData::STDataFrame &data) 97 | { 98 | m_data = data; 99 | } 100 | 101 | -------------------------------------------------------------------------------- /src/data/UserSelection.h: -------------------------------------------------------------------------------- 1 | #ifndef USERSELECTION_H 2 | #define USERSELECTION_H 3 | 4 | #include 5 | #include "STData.h" 6 | 7 | // UserSelection represents a selection of spots made by the user trough the UI. 8 | // Users can select spots manually (lazo, rubberband ..) or by using the selection search 9 | // box with specific gene names (reg-exp). 10 | class UserSelection 11 | { 12 | 13 | public: 14 | 15 | typedef STData::STDataFrame STDataFrame; 16 | 17 | UserSelection(); 18 | explicit UserSelection(const STData::STDataFrame &data); 19 | UserSelection(const UserSelection &other); 20 | ~UserSelection(); 21 | 22 | UserSelection &operator=(const UserSelection &other); 23 | bool operator==(const UserSelection &other) const; 24 | 25 | // the name of the selection 26 | const QString name() const; 27 | // the name of the dataset where the selection has been made 28 | const QString dataset() const; 29 | // the data matrix of counts 30 | const STData::STDataFrame &data() const; 31 | // some meta-data 32 | const QString comment() const; 33 | 34 | // obtained from the data object 35 | int totalGenes() const; 36 | int totalSpots() const; 37 | 38 | // Setters 39 | void name(const QString &name); 40 | void dataset(const QString &dataset); 41 | void comment(const QString &comment); 42 | void data(const STData::STDataFrame &data); 43 | 44 | private: 45 | QString m_name; 46 | QString m_dataset; 47 | STData::STDataFrame m_data; 48 | QString m_comment; 49 | }; 50 | 51 | #endif // USERSELECTION_H 52 | -------------------------------------------------------------------------------- /src/dialogs/AboutDialog.cpp: -------------------------------------------------------------------------------- 1 | #include "AboutDialog.h" 2 | #include "ui_aboutdialog.h" 3 | 4 | AboutDialog::AboutDialog(QWidget *parent, Qt::WindowFlags f) 5 | : QDialog(parent, f) 6 | , m_ui(new Ui::AboutDialog) 7 | { 8 | setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); 9 | 10 | m_ui->setupUi(this); 11 | } 12 | 13 | AboutDialog::~AboutDialog() 14 | { 15 | } 16 | -------------------------------------------------------------------------------- /src/dialogs/AboutDialog.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace Ui 5 | { 6 | class AboutDialog; 7 | } // namespace Ui // 8 | 9 | // Simple about dialog. Contains the application logo as well as some about 10 | // text (so... simple). 11 | class AboutDialog : public QDialog 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | explicit AboutDialog(QWidget *parent = 0, Qt::WindowFlags f = 0); 17 | ~AboutDialog(); 18 | 19 | private: 20 | QScopedPointer m_ui; 21 | 22 | Q_DISABLE_COPY(AboutDialog) 23 | }; 24 | -------------------------------------------------------------------------------- /src/dialogs/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LIBRARY_ARG_INCLUDES 2 | AboutDialog.h 3 | SelectionDialog.h 4 | EditSelectionDialog.h 5 | EditDatasetDialog.h 6 | ) 7 | 8 | set(LIBRARY_ARG_SOURCES 9 | AboutDialog.cpp 10 | SelectionDialog.cpp 11 | EditSelectionDialog.cpp 12 | EditDatasetDialog.cpp 13 | ) 14 | 15 | ST_LIBRARY() 16 | -------------------------------------------------------------------------------- /src/dialogs/EditDatasetDialog.cpp: -------------------------------------------------------------------------------- 1 | #include "EditDatasetDialog.h" 2 | 3 | #include "ui_editDatasetDialog.h" 4 | 5 | EditDatasetDialog::EditDatasetDialog(QWidget *parent, Qt::WindowFlags f) 6 | : QDialog(parent, f) 7 | , m_ui(new Ui::editDatasetDialog) 8 | { 9 | setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); 10 | 11 | m_ui->setupUi(this); 12 | 13 | connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); 14 | connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); 15 | move(parent->window()->mapToGlobal(parent->window()->rect().center()) 16 | - mapToGlobal(rect().center())); 17 | } 18 | 19 | EditDatasetDialog::~EditDatasetDialog() 20 | { 21 | } 22 | 23 | const QString EditDatasetDialog::getName() const 24 | { 25 | return m_ui->name->text(); 26 | } 27 | 28 | const QString EditDatasetDialog::getComment() const 29 | { 30 | return m_ui->comment->toPlainText(); 31 | } 32 | 33 | void EditDatasetDialog::setName(const QString name) 34 | { 35 | return m_ui->name->setText(name); 36 | } 37 | 38 | void EditDatasetDialog::setComment(const QString comment) 39 | { 40 | return m_ui->comment->setText(comment); 41 | } 42 | -------------------------------------------------------------------------------- /src/dialogs/EditDatasetDialog.h: -------------------------------------------------------------------------------- 1 | #ifndef EDITDATASETDIALOG_H 2 | #define EDITDATASETDIALOG_H 3 | 4 | #include 5 | #include 6 | 7 | namespace Ui 8 | { 9 | class editDatasetDialog; 10 | } // namespace Ui // 11 | 12 | // Widget that shows the user the dataset's name and comments fields 13 | class EditDatasetDialog : public QDialog 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit EditDatasetDialog(QWidget *parent = 0, Qt::WindowFlags f = 0); 19 | virtual ~EditDatasetDialog(); 20 | 21 | const QString getName() const; 22 | const QString getComment() const; 23 | 24 | void setName(const QString name); 25 | void setComment(const QString name); 26 | 27 | private: 28 | QScopedPointer m_ui; 29 | 30 | Q_DISABLE_COPY(EditDatasetDialog) 31 | }; 32 | 33 | #endif // EDITDATASETDIALOG_H 34 | -------------------------------------------------------------------------------- /src/dialogs/EditSelectionDialog.cpp: -------------------------------------------------------------------------------- 1 | #include "EditSelectionDialog.h" 2 | 3 | #include 4 | #include 5 | #include "ui_editSelectionDialog.h" 6 | 7 | EditSelectionDialog::EditSelectionDialog(QWidget *parent, Qt::WindowFlags f) 8 | : QDialog(parent, f) 9 | , m_ui(new Ui::editSelectionDialog) 10 | { 11 | setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); 12 | 13 | m_ui->setupUi(this); 14 | 15 | connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); 16 | connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); 17 | move(parent->window()->mapToGlobal(parent->window()->rect().center()) 18 | - mapToGlobal(rect().center())); 19 | } 20 | 21 | EditSelectionDialog::~EditSelectionDialog() 22 | { 23 | } 24 | 25 | const QString EditSelectionDialog::getName() const 26 | { 27 | return m_ui->name->text(); 28 | } 29 | 30 | const QString EditSelectionDialog::getComment() const 31 | { 32 | return m_ui->comment->toPlainText(); 33 | } 34 | 35 | void EditSelectionDialog::setName(const QString name) 36 | { 37 | return m_ui->name->setText(name); 38 | } 39 | 40 | void EditSelectionDialog::setComment(const QString comment) 41 | { 42 | return m_ui->comment->setText(comment); 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/dialogs/EditSelectionDialog.h: -------------------------------------------------------------------------------- 1 | #ifndef EDITSELECTIONDIALOG_H 2 | #define EDITSELECTIONDIALOG_H 3 | 4 | #include 5 | #include 6 | 7 | class QColorDialog; 8 | namespace Ui 9 | { 10 | class editSelectionDialog; 11 | } // namespace Ui // 12 | 13 | // Simple dialog that allows to edit some fields in an UserSelection object 14 | class EditSelectionDialog : public QDialog 15 | { 16 | Q_OBJECT 17 | 18 | public: 19 | explicit EditSelectionDialog(QWidget *parent = 0, Qt::WindowFlags f = 0); 20 | virtual ~EditSelectionDialog(); 21 | 22 | const QString getName() const; 23 | const QString getComment() const; 24 | 25 | void setName(const QString name); 26 | void setComment(const QString comment); 27 | 28 | private: 29 | QScopedPointer m_ui; 30 | 31 | Q_DISABLE_COPY(EditSelectionDialog) 32 | }; 33 | 34 | #endif // EDITSELECTIONDIALOG_H 35 | -------------------------------------------------------------------------------- /src/dialogs/SelectionDialog.cpp: -------------------------------------------------------------------------------- 1 | #include "SelectionDialog.h" 2 | #include "ui_selectionConsole.h" 3 | 4 | SelectionDialog::SelectionDialog(QWidget *parent, 5 | Qt::WindowFlags f) 6 | : QDialog(parent, f) 7 | , m_ui(new Ui::SelectionDialog()) 8 | , m_includeAmbiguous(false) 9 | , m_caseSensitive(false) 10 | , m_regExpValid(false) 11 | , m_selectNonVisible(false) 12 | { 13 | 14 | setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); 15 | 16 | m_ui->setupUi(this); 17 | 18 | // set default state 19 | slotCaseSensitive(false); 20 | slotSelectNonVisible(false); 21 | move(parent->window()->mapToGlobal(parent->window()->rect().center()) 22 | - mapToGlobal(rect().center())); 23 | 24 | // NOTE the connections are made in the UI file 25 | 26 | m_regExp.setPatternSyntax(QRegExp::WildcardUnix); 27 | } 28 | 29 | SelectionDialog::~SelectionDialog() 30 | { 31 | } 32 | 33 | void SelectionDialog::accept() 34 | { 35 | // early out, should "never" happen 36 | if (!m_regExp.isValid()) { 37 | reject(); 38 | return; 39 | } 40 | 41 | // and propagate accept call 42 | QDialog::accept(); 43 | } 44 | 45 | QRegExp SelectionDialog::getRegExp() const 46 | { 47 | return m_regExp; 48 | } 49 | 50 | bool SelectionDialog::isValid() const 51 | { 52 | return m_regExpValid; 53 | } 54 | 55 | bool SelectionDialog::selectNonVisible() const 56 | { 57 | return m_selectNonVisible; 58 | } 59 | 60 | bool SelectionDialog::caseSensitive() const 61 | { 62 | return m_caseSensitive; 63 | } 64 | 65 | void SelectionDialog::slotValidateRegExp(const QString &pattern) 66 | { 67 | m_regExp.setPattern(pattern); 68 | const bool regExpValid = m_regExp.isValid(); 69 | if (regExpValid != m_regExpValid) { 70 | m_regExpValid = regExpValid; 71 | } 72 | } 73 | 74 | void SelectionDialog::slotSelectNonVisible(bool selectNonVisible) 75 | { 76 | m_selectNonVisible = selectNonVisible; 77 | if (m_selectNonVisible != m_ui->checkSelectNonVisible->isChecked()) { 78 | m_ui->checkSelectNonVisible->setChecked(m_selectNonVisible); 79 | } 80 | } 81 | 82 | void SelectionDialog::slotCaseSensitive(bool caseSensitive) 83 | { 84 | // toggle case sensitive 85 | m_regExp.setCaseSensitivity((caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive)); 86 | m_caseSensitive = caseSensitive; 87 | if (m_caseSensitive != m_ui->checkCaseSense->isChecked()) { 88 | m_ui->checkCaseSense->setChecked(m_caseSensitive); 89 | } 90 | } 91 | 92 | void SelectionDialog::slotEnableAcceptAction(bool enableAcceptAction) 93 | { 94 | for (QAbstractButton *button : m_ui->buttonBox->buttons()) { 95 | const QDialogButtonBox::ButtonRole role = m_ui->buttonBox->buttonRole(button); 96 | if (role == QDialogButtonBox::AcceptRole || role == QDialogButtonBox::YesRole 97 | || role == QDialogButtonBox::ApplyRole) { 98 | button->setEnabled(enableAcceptAction); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/dialogs/SelectionDialog.h: -------------------------------------------------------------------------------- 1 | #ifndef SELECTIONDIALOG_H 2 | #define SELECTIONDIALOG_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace Ui 9 | { 10 | class SelectionDialog; 11 | } // namespace Ui // 12 | 13 | // Selection dialog implementing support to select genes by their names 14 | // using regular expressions. 15 | class SelectionDialog : public QDialog 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | 21 | SelectionDialog(QWidget *parent = 0, Qt::WindowFlags f = 0); 22 | virtual ~SelectionDialog(); 23 | 24 | QRegExp getRegExp() const; 25 | bool isValid() const; 26 | bool selectNonVisible() const; 27 | bool caseSensitive() const; 28 | 29 | signals: 30 | 31 | void signalValidRegExp(bool); 32 | 33 | public slots: 34 | 35 | // to get the list of selected genes from the reg-exp 36 | void accept() override; 37 | // to validate or not the reg-exp 38 | void slotValidateRegExp(const QString &pattern); 39 | // to enable/disable case sensitivigy in the reg-exp 40 | void slotCaseSensitive(bool caseSensitive); 41 | // to enable/disable the inclusion of non visible in the selection 42 | void slotSelectNonVisible(bool selectNonVisible); 43 | // disable any "accept/yes/apply" type buttons when regexp is invalid 44 | void slotEnableAcceptAction(bool enableAcceptAction); 45 | 46 | private: 47 | QScopedPointer m_ui; 48 | 49 | // configuration variables 50 | bool m_includeAmbiguous; 51 | bool m_caseSensitive; 52 | bool m_regExpValid; 53 | bool m_selectNonVisible; 54 | QRegExp m_regExp; 55 | 56 | Q_DISABLE_COPY(SelectionDialog) 57 | }; 58 | 59 | #endif // SELECTIONDIALOG_H // 60 | -------------------------------------------------------------------------------- /src/dialogs/aboutdialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | AboutDialog 4 | 5 | 6 | true 7 | 8 | 9 | 10 | 0 11 | 0 12 | 434 13 | 546 14 | 15 | 16 | 17 | 18 | 0 19 | 0 20 | 21 | 22 | 23 | About... 24 | 25 | 26 | 27 | 9 28 | 29 | 30 | 31 | 32 | 6 33 | 34 | 35 | 36 | 37 | 38 | 0 39 | 0 40 | 41 | 42 | 43 | true 44 | 45 | 46 | <html><head/><body><p><span style=" font-size:18pt;">Spatial Transcriptomics Reserch Viewer v</span><span style=" font-size:18pt; font-weight:600;">0.7.6</span></p><p>This tool allows you to visualize, analyse and interact with spatially resolved gene expresions data.</p><p>This a prototype beta version with limited functionalities.</p><p>CopyRight (c) 2012-2019 Jose Fernandez Navarro.</p><p>Read LICENSE for more information about the licensing terms.</p><p>Read DEPENDENCIES for more information about third party</p><p>libraries used in the ST Viewer. </p><p>The ST Viewer uses the following third party libraries :</p><p>- Qt 5.12 (LGPL v3)</p><p>- Armadillo (Apache License 2.0)</p><p>- R (GNU GPL)</p><p>- RInside/Rcpp (GNU GPL)</p><p>- QCustomplot (Commercial dynamic linking license. Link: http://qcustomplot.com/)</p><p>Please report bug, feedback, questions and errors to : <span style=" font-weight:600;">jose.fernandez.navarro@scilifelab.se</span></p></body></html> 47 | 48 | 49 | Qt::AutoText 50 | 51 | 52 | true 53 | 54 | 55 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 56 | 57 | 58 | true 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | Qt::Horizontal 68 | 69 | 70 | QDialogButtonBox::Close 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | buttonBox 80 | accepted() 81 | AboutDialog 82 | accept() 83 | 84 | 85 | 248 86 | 254 87 | 88 | 89 | 157 90 | 274 91 | 92 | 93 | 94 | 95 | buttonBox 96 | rejected() 97 | AboutDialog 98 | reject() 99 | 100 | 101 | 316 102 | 260 103 | 104 | 105 | 286 106 | 274 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /src/dialogs/editDatasetDialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | editDatasetDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | Edit Dataset 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Name: 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | Comment: 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | Qt::Horizontal 44 | 45 | 46 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | buttonBox 56 | accepted() 57 | editDatasetDialog 58 | accept() 59 | 60 | 61 | 248 62 | 254 63 | 64 | 65 | 157 66 | 274 67 | 68 | 69 | 70 | 71 | buttonBox 72 | rejected() 73 | editDatasetDialog 74 | reject() 75 | 76 | 77 | 316 78 | 260 79 | 80 | 81 | 286 82 | 274 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /src/dialogs/editSelectionDialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | editSelectionDialog 4 | 5 | 6 | Qt::ApplicationModal 7 | 8 | 9 | 10 | 0 11 | 0 12 | 400 13 | 294 14 | 15 | 16 | 17 | Edit Selection 18 | 19 | 20 | Gene Selection Creation Dialog 21 | 22 | 23 | Gene Selection Creation Dialog 24 | 25 | 26 | 27 | 28 | 29 | true 30 | 31 | 32 | 33 | 34 | 35 | Name: 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | Comment: 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "mainWindow.h" 12 | #include "options_cmake.h" 13 | 14 | // RcppArmadillo must be included before RInside 15 | #include "RcppArmadillo.h" 16 | #include "RInside.h" 17 | 18 | #include 19 | 20 | namespace 21 | { 22 | 23 | // Application flags must be set before instantiating QApplication 24 | void setApplicationFlags() 25 | { 26 | 27 | #ifdef Q_OS_MAC 28 | QApplication::setAttribute(Qt::AA_MacPluginApplication, false); 29 | QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, false); 30 | // NOTE this is actually pretty important (be false) 31 | QApplication::setAttribute(Qt::AA_NativeWindows, false); 32 | // osx does not show icons on menus 33 | QApplication::setAttribute(Qt::AA_DontShowIconsInMenus, true); 34 | #endif 35 | 36 | // unhandled mouse events will not be translated 37 | QApplication::setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, false); 38 | QApplication::setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false); 39 | // allows to create high-dpi pixmaps 40 | QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true); 41 | // consistent font rendering 42 | QApplication::setAttribute(Qt::AA_Use96Dpi, true); 43 | // force usages of desktop opengl 44 | QApplication::setAttribute(Qt::AA_UseDesktopOpenGL, true); 45 | } 46 | } 47 | 48 | int main(int argc, char **argv) 49 | { 50 | const QString VERSION = QString("%1.%2.%3").arg(MAJOR).arg(MINOR).arg(PATCH); 51 | 52 | // Define some configuration flags 53 | setApplicationFlags(); 54 | 55 | // Creates the application object 56 | QApplication app(argc, argv); 57 | app.setApplicationName(app.translate("main", "STViewer")); 58 | app.setApplicationVersion(VERSION); 59 | 60 | qDebug() << "Application started successfully."; 61 | 62 | // Initialize RInside object here since it is global... 63 | RInside *dummyR = nullptr; 64 | try { 65 | dummyR = new RInside(); 66 | } catch (const std::exception &e) { 67 | QMessageBox::critical(app.desktop()->screen(), 68 | app.tr("Error"), 69 | app.tr("Error initializing R") + "\n" + QString(e.what())); 70 | delete dummyR; 71 | dummyR = nullptr; 72 | return EXIT_FAILURE; 73 | } catch (...) { 74 | QMessageBox::critical(app.desktop()->screen(), 75 | app.tr("Error"), 76 | app.tr("Unknown error initializing R")); 77 | delete dummyR; 78 | dummyR = nullptr; 79 | return EXIT_FAILURE; 80 | } 81 | 82 | // Create main window 83 | MainWindow mainWindow; 84 | app.setActiveWindow(&mainWindow); 85 | // Check for min requirements 86 | if (!mainWindow.checkSystemRequirements()) { 87 | qDebug() << "[Main] Error: Minimum requirements test failed!"; 88 | QMessageBox::critical(app.desktop()->screen(), 89 | app.tr("Error"), 90 | app.tr("Minimum requirements not satisfied")); 91 | delete dummyR; 92 | dummyR = nullptr; 93 | return EXIT_FAILURE; 94 | } 95 | // Initialize graphic components 96 | mainWindow.init(); 97 | // Show main window. 98 | mainWindow.show(); 99 | // launch the app 100 | const int return_code = app.exec(); 101 | delete dummyR; 102 | dummyR = nullptr; 103 | return return_code; 104 | } 105 | -------------------------------------------------------------------------------- /src/mainWindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | 6 | class QSettings; 7 | class QCloseEvent; 8 | class QAction; 9 | class QStatusBar; 10 | class QMenu; 11 | class QVBoxLayout; 12 | class QWidget; 13 | class DatasetPage; 14 | class CellViewPage; 15 | class UserSelectionsPage; 16 | class SpotsWidget; 17 | class GenesWidget; 18 | 19 | // This class represents the main window of the application 20 | // it is composed of a tool bar, the cell main view and the gene tables 21 | // it allows the user to show the datasets and the selections windows as well 22 | class MainWindow : public QMainWindow 23 | { 24 | Q_OBJECT 25 | 26 | public: 27 | explicit MainWindow(QWidget *parent = 0); 28 | ~MainWindow(); 29 | 30 | // Initialize main visual components 31 | void init(); 32 | 33 | // Check that the host has all the required hardware (true yes : false no ) 34 | bool checkSystemRequirements() const; 35 | 36 | // System settings 37 | void loadSettings(); 38 | void saveSettings() const; 39 | 40 | private slots: 41 | 42 | // exit the application 43 | void slotExit(); 44 | 45 | // clear the cache and local stored files 46 | void slotClearCache(); 47 | 48 | // open pop up static widget to show info about the application 49 | void slotShowAbout(); 50 | 51 | // a dataset has been opened 52 | void slotDatasetOpen(const QString &datasetname); 53 | // a dataset has been edited 54 | void slotDatasetUpdated(const QString &datasetname); 55 | // a dataset has been removed (the current open) 56 | void slotDatasetRemoved(const QString &datasetname); 57 | 58 | private: 59 | // create all the widgets 60 | void setupUi(); 61 | // load style sheets 62 | void initStyle(); 63 | // create keyboard shortcuts 64 | void createShorcuts(); 65 | // create some connections 66 | void createConnections(); 67 | 68 | // overloaded close Event function to handle the exit 69 | void closeEvent(QCloseEvent *event) override; 70 | 71 | // reference to some UI elements 72 | QScopedPointer m_actionExit; 73 | QScopedPointer m_actionHelp; 74 | QScopedPointer m_actionVersion; 75 | QScopedPointer m_actionAbout; 76 | QScopedPointer m_actionClear_Cache; 77 | QScopedPointer m_actionDatasets; 78 | QScopedPointer m_actionSelections; 79 | 80 | // different views 81 | QScopedPointer m_datasets; 82 | QScopedPointer m_cellview; 83 | QSharedPointer m_user_selections; 84 | QSharedPointer m_genes; 85 | QSharedPointer m_spots; 86 | }; 87 | 88 | #endif // MAINWINDOW_H 89 | -------------------------------------------------------------------------------- /src/math/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LIBRARY_ARG_INCLUDES 2 | Common.h 3 | RInterface.h 4 | ) 5 | 6 | ST_LIBRARY() 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/model/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LIBRARY_ARG_INCLUDES 2 | DatasetItemModel.h 3 | UserSelectionsItemModel.h 4 | GeneItemModel.h 5 | SpotItemModel.h 6 | ) 7 | 8 | set(LIBRARY_ARG_SOURCES 9 | DatasetItemModel.cpp 10 | UserSelectionsItemModel.cpp 11 | GeneItemModel.cpp 12 | SpotItemModel.cpp 13 | ) 14 | 15 | ST_LIBRARY() 16 | -------------------------------------------------------------------------------- /src/model/DatasetItemModel.cpp: -------------------------------------------------------------------------------- 1 | #include "DatasetItemModel.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "data/Dataset.h" 10 | #include 11 | 12 | static const int COLUMN_NUMBER = 3; 13 | 14 | DatasetItemModel::DatasetItemModel(QObject *parent) 15 | : QAbstractTableModel(parent) 16 | { 17 | } 18 | 19 | DatasetItemModel::~DatasetItemModel() 20 | { 21 | } 22 | 23 | bool DatasetItemModel::setData(const QModelIndex &index, const QVariant &value, int role) 24 | { 25 | return QAbstractItemModel::setData(index, value, role); 26 | } 27 | 28 | QVariant DatasetItemModel::data(const QModelIndex &index, int role) const 29 | { 30 | // early out 31 | if (!index.isValid() || m_datasets_reference.empty()) { 32 | return QVariant(QVariant::Invalid); 33 | } 34 | 35 | if (role == Qt::DisplayRole) { 36 | const Dataset &item = m_datasets_reference.at(index.row()); 37 | switch (index.column()) { 38 | case Name: 39 | return item.name(); 40 | case Tissue: 41 | return item.statTissue(); 42 | case Species: 43 | return item.statSpecies(); 44 | default: 45 | return QVariant(QVariant::Invalid); 46 | } 47 | } 48 | 49 | if (role == Qt::ForegroundRole && index.column() == Name) { 50 | return QColor(0, 155, 60); 51 | } 52 | 53 | return QVariant(QVariant::Invalid); 54 | } 55 | 56 | QVariant DatasetItemModel::headerData(int section, Qt::Orientation orientation, int role) const 57 | { 58 | if (role == Qt::ToolTipRole && orientation == Qt::Horizontal) { 59 | switch (section) { 60 | case Name: 61 | return tr("Dataset name"); 62 | case Tissue: 63 | return tr("Tissue name"); 64 | case Species: 65 | return tr("Species name"); 66 | default: 67 | return QVariant(QVariant::Invalid); 68 | } 69 | } 70 | 71 | if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { 72 | switch (section) { 73 | case Name: 74 | return tr("Name"); 75 | case Tissue: 76 | return tr("Tissue"); 77 | case Species: 78 | return tr("Species"); 79 | default: 80 | return QVariant(QVariant::Invalid); 81 | } 82 | } 83 | 84 | if (role == Qt::TextAlignmentRole) { 85 | switch (section) { 86 | case Name: 87 | case Tissue: 88 | case Species: 89 | return Qt::AlignLeft; 90 | default: 91 | return QVariant(QVariant::Invalid); 92 | } 93 | } 94 | 95 | return QVariant(QVariant::Invalid); 96 | } 97 | 98 | int DatasetItemModel::columnCount(const QModelIndex &parent) const 99 | { 100 | return parent.isValid() ? 0 : COLUMN_NUMBER; 101 | } 102 | 103 | int DatasetItemModel::rowCount(const QModelIndex &parent) const 104 | { 105 | return parent.isValid() ? 0 : m_datasets_reference.size(); 106 | } 107 | 108 | Qt::ItemFlags DatasetItemModel::flags(const QModelIndex &index) const 109 | { 110 | Qt::ItemFlags defaultFlags = QAbstractItemModel::flags(index); 111 | return defaultFlags; 112 | } 113 | 114 | void DatasetItemModel::loadDatasets(const QList &datasetList) 115 | { 116 | beginResetModel(); 117 | m_datasets_reference = datasetList; 118 | endResetModel(); 119 | } 120 | 121 | QList DatasetItemModel::getDatasets(const QItemSelection &selection) 122 | { 123 | // get unique row indexes from the user selection 124 | QSet rows; 125 | for (const auto &index : selection.indexes()) { 126 | rows.insert(index.row()); 127 | } 128 | // get the datasets corresponding to the selection and return them 129 | QList datasetList; 130 | for (const auto &row : rows) { 131 | const Dataset &item = m_datasets_reference.at(row); 132 | datasetList.push_back(item); 133 | } 134 | return datasetList; 135 | } 136 | 137 | void DatasetItemModel::clear() 138 | { 139 | beginResetModel(); 140 | m_datasets_reference.clear(); 141 | endResetModel(); 142 | } 143 | -------------------------------------------------------------------------------- /src/model/DatasetItemModel.h: -------------------------------------------------------------------------------- 1 | #ifndef DATASETITEMMODEL_H 2 | #define DATASETITEMMODEL_H 3 | 4 | #include 5 | 6 | class QModelIndex; 7 | class QStandardItemModel; 8 | class QItemSelection; 9 | class Dataset; 10 | 11 | // Wrapper model class for datasets in the Datasets table. Provides easy 12 | // means of enumerating all the data sets connected to a single user. 13 | // TODO highlight openned dataset 14 | class DatasetItemModel : public QAbstractTableModel 15 | { 16 | Q_OBJECT 17 | Q_ENUMS(Column) 18 | 19 | public: 20 | enum Column { 21 | Name = 0, 22 | Tissue = 1, 23 | Species = 2, 24 | }; 25 | 26 | explicit DatasetItemModel(QObject *parent = 0); 27 | virtual ~DatasetItemModel(); 28 | 29 | // Necessary to override 30 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; 31 | QVariant headerData(int section, Qt::Orientation orientation, int role) const override; 32 | bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; 33 | int columnCount(const QModelIndex &parent = QModelIndex()) const override; 34 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; 35 | Qt::ItemFlags flags(const QModelIndex &index) const override; 36 | 37 | // Updates the data model with the data given as input 38 | void loadDatasets(const QList &datasetList); 39 | 40 | // Returns a list of datasets for the given items selection 41 | QList getDatasets(const QItemSelection &selection); 42 | 43 | // Clear the current model 44 | void clear(); 45 | 46 | private: 47 | QList m_datasets_reference; 48 | 49 | Q_DISABLE_COPY(DatasetItemModel) 50 | }; 51 | 52 | #endif // DATASETITEMMODEL_H 53 | -------------------------------------------------------------------------------- /src/model/GeneItemModel.h: -------------------------------------------------------------------------------- 1 | #ifndef GENEFITEMMODEL_H 2 | #define GENEFITEMMODEL_H 3 | 4 | #include 5 | #include "data/STData.h" 6 | 7 | class QModelIndex; 8 | class QStringList; 9 | class QMimeData; 10 | class QItemSelection; 11 | class Dataset; 12 | 13 | // Wrapper model class for the gene data (specific to a dataset). 14 | // Primarily used to enumerate the genes in the cell view (genes table) 15 | // and allow the user to interact with individual genes. 16 | class GeneItemModel : public QAbstractTableModel 17 | { 18 | Q_OBJECT 19 | Q_ENUMS(Column) 20 | 21 | public: 22 | enum Column { Show = 0, Name = 1, Count = 2, CutOff = 3, Color = 4 }; 23 | 24 | explicit GeneItemModel(QObject *parent = 0); 25 | virtual ~GeneItemModel(); 26 | 27 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; 28 | int columnCount(const QModelIndex &parent = QModelIndex()) const override; 29 | 30 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; 31 | // allows the user to modify the cut off on the table 32 | bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; 33 | QVariant headerData(int section, 34 | Qt::Orientation orientation, 35 | int role = Qt::DisplayRole) const override; 36 | 37 | Qt::ItemFlags flags(const QModelIndex &index) const override; 38 | 39 | // this function will set to visible the genes included in the selection 40 | // and emit a signal with the modified genes 41 | void setVisibility(const QItemSelection &selection, bool visible); 42 | 43 | // this function will modify the color of the genes included in the selection 44 | // and emit a signal with the modified genes 45 | void setColor(const QItemSelection &selection, const QColor &color); 46 | 47 | // reload the model's data from the dataset (genes) 48 | void loadDataset(const Dataset &dataset); 49 | 50 | // clear and reset the model 51 | void clear(); 52 | 53 | public slots: 54 | 55 | signals: 56 | // to notify that the user has changed a gene's cut-off 57 | void signalGeneCutOffChanged(); 58 | 59 | private: 60 | STData::GeneListType m_items_reference; 61 | 62 | Q_DISABLE_COPY(GeneItemModel) 63 | }; 64 | 65 | #endif // GENEFITEMMODEL_H 66 | -------------------------------------------------------------------------------- /src/model/SpotItemModel.h: -------------------------------------------------------------------------------- 1 | #ifndef SPOTITEMMODEL_H 2 | #define SPOTITEMMODEL_H 3 | 4 | #include 5 | #include "data/STData.h" 6 | 7 | class QModelIndex; 8 | class QStringList; 9 | class QMimeData; 10 | class QItemSelection; 11 | class Dataset; 12 | 13 | // Wrapper model class for the spot data (specific to a dataset). 14 | // Primarily used to enumerate the spots in the cell view (spots table) 15 | // and allow the user to interact with individual spots. 16 | class SpotItemModel : public QAbstractTableModel 17 | { 18 | Q_OBJECT 19 | Q_ENUMS(Column) 20 | public: 21 | 22 | enum Column { Show = 0, Name = 1, Count = 2, Color = 3 }; 23 | 24 | explicit SpotItemModel(QObject *parent = 0); 25 | 26 | // Header: 27 | QVariant headerData(int section, Qt::Orientation orientation, 28 | int role = Qt::DisplayRole) const override; 29 | // Basic functionality: 30 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; 31 | int columnCount(const QModelIndex &parent = QModelIndex()) const override; 32 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; 33 | Qt::ItemFlags flags(const QModelIndex& index) const override; 34 | 35 | // this function will set to visible the spots included in the selection 36 | // and emit a signal with the modified spots 37 | void setVisibility(const QItemSelection &selection, bool visible); 38 | 39 | // this function will modify the color of the spots included in the selection 40 | // and emit a signal with the modified spots 41 | void setColor(const QItemSelection &selection, const QColor &color); 42 | 43 | // reload the model's data from the dataset (spots) 44 | void loadDataset(const Dataset &dataset); 45 | 46 | // clear and reset the model 47 | void clear(); 48 | 49 | public slots: 50 | 51 | signals: 52 | 53 | private: 54 | STData::SpotListType m_items_reference; 55 | 56 | Q_DISABLE_COPY(SpotItemModel) 57 | }; 58 | 59 | #endif // SPOTITEMMODEL_H 60 | -------------------------------------------------------------------------------- /src/model/UserSelectionsItemModel.h: -------------------------------------------------------------------------------- 1 | #ifndef USERSELECTIONITEMMODEL_H 2 | #define USERSELECTIONITEMMODEL_H 3 | 4 | #include 5 | #include 6 | 7 | class UserSelection; 8 | class QModelIndex; 9 | class QStringList; 10 | class QItemSelection; 11 | 12 | // Wrapper model for the user selections 13 | class UserSelectionsItemModel : public QAbstractTableModel 14 | { 15 | Q_OBJECT 16 | Q_ENUMS(Column) 17 | 18 | public: 19 | enum Column { 20 | Name = 0, 21 | Dataset = 1, 22 | NGenes = 2, 23 | NSpots = 3, 24 | }; 25 | 26 | explicit UserSelectionsItemModel(QObject *parent = 0); 27 | virtual ~UserSelectionsItemModel(); 28 | 29 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; 30 | int columnCount(const QModelIndex &parent = QModelIndex()) const override; 31 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; 32 | QVariant headerData(int section, 33 | Qt::Orientation orientation, 34 | int role = Qt::DisplayRole) const override; 35 | Qt::ItemFlags flags(const QModelIndex &index) const override; 36 | 37 | // reset current model 38 | void clear(); 39 | 40 | // loads the data of the model from the given input 41 | void loadUserSelections(const QList &selectionList); 42 | 43 | // returns a list of selections items from the indexes given as input 44 | QList getSelections(const QItemSelection &selection); 45 | 46 | private: 47 | QList m_userSelectionList; 48 | 49 | Q_DISABLE_COPY(UserSelectionsItemModel) 50 | }; 51 | 52 | #endif // USERSELECTIONITEMMODEL_H 53 | -------------------------------------------------------------------------------- /src/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Unit Test CMake # 3 | ############################################################################### 4 | 5 | use_qt5lib(Qt5Test) 6 | 7 | include_directories(${PROJECT_SOURCE_DIR}/src 8 | ${PROJECT_SOURCE_DIR} 9 | ${CMAKE_BINARY_DIR}/src 10 | ${CMAKE_BINARY_DIR}) 11 | 12 | # Define source files 13 | set(ST_UNITTEST_SOURCES 14 | ${ST_MAIN} 15 | ${ST_TARGET_OBJECTS} 16 | ) 17 | 18 | find_package(Qt5Test REQUIRED) 19 | 20 | ### TEST CREATION MACRO ####################################################### 21 | # This macro accepts an optional argument 'otherfiles'. This forms an optional list of non test 22 | # files to be added to test executable. It assumes that each entry 'foo' in the list has a 23 | # corresponding .h and .cpp file located in the named sub directory. 24 | macro(add_st_client_test subdir name) 25 | set(srcs ${ST_UNITTEST_SOURCES} ${subdir}/${name}.h ${subdir}/${name}.cpp ) 26 | set (otherfiles ${ARGN}) 27 | foreach(file ${otherfiles}) 28 | set(srcs ${srcs} ${subdir}/${file}.h ${subdir}/${file}.cpp ) 29 | endforeach() 30 | add_executable(${name} ${srcs}) 31 | target_link_libraries(${name} ${QT_TARGET_LINK_LIBS} qcustomplot Qt5::Test 32 | ${ARMADILLO_LIBRARIES} ${LIBR_LIBRARIES} ${LIBRINSIDE_LIBRARIES}) 33 | add_test(NAME ${name} 34 | COMMAND $) 35 | 36 | add_dependencies(${name} ${PROJECT_NAME}) 37 | 38 | if(WIN32) 39 | string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE_LOWERCASE) 40 | if(BUILD_TYPE_LOWERCASE STREQUAL "debug") 41 | get_target_property(ST_QT_LOC "Qt5::Test" LOCATION_DEBUG) 42 | else() 43 | get_target_property(ST_QT_LOC "Qt5::Test" LOCATION) 44 | endif() 45 | #install(FILES ${ST_QT_LOC} DESTINATION .) 46 | #add_custom_command(TARGET ${name} POST_BUILD 47 | # COMMAND ${CMAKE_COMMAND} -E copy ${ST_QT_LOC} 48 | # ${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/) 49 | endif(WIN32) 50 | endmacro() 51 | 52 | 53 | ### ST UNIT TESTS LIST ######################################################## 54 | add_st_client_test(controller tst_widgets) 55 | add_st_client_test(utils tst_mathextendedtest) 56 | add_st_client_test(math tst_glheatmaptest) 57 | -------------------------------------------------------------------------------- /src/test/controller/tst_widgets.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "mainWindow.h" 4 | #include "config/Configuration.h" 5 | #include "tst_widgets.h" 6 | 7 | #include 8 | 9 | namespace unit 10 | { 11 | 12 | WidgetsTest::WidgetsTest(QObject *parent) 13 | : QObject(parent) 14 | { 15 | } 16 | 17 | void WidgetsTest::initTestCase() 18 | { 19 | // init configurations 20 | Configuration *configuration = new Configuration(); 21 | QVERIFY(configuration != 0); 22 | } 23 | 24 | void WidgetsTest::cleanupTestCase() 25 | { 26 | // TODO 27 | } 28 | 29 | void WidgetsTest::testDoesNothing() 30 | { 31 | // This test is a dummy test and always passes. Without it QTest reports use of the 32 | // test-free WidgetsTest as a failure. 33 | QVERIFY(true); 34 | } 35 | 36 | } // namespace unit 37 | 38 | QTEST_MAIN(unit::WidgetsTest) 39 | #include "tst_widgets.moc" 40 | -------------------------------------------------------------------------------- /src/test/controller/tst_widgets.h: -------------------------------------------------------------------------------- 1 | #ifndef TST_WIDGETS_H 2 | #define TST_WIDGETS_H 3 | 4 | #include 5 | 6 | namespace Ui 7 | { 8 | class MainWindow; 9 | } // namespace Ui // 10 | 11 | namespace unit 12 | { 13 | 14 | class WidgetsTest : public QObject 15 | { 16 | Q_OBJECT 17 | 18 | public: 19 | explicit WidgetsTest(QObject *parent = 0); 20 | 21 | private Q_SLOTS: 22 | 23 | void initTestCase(); 24 | void cleanupTestCase(); 25 | 26 | // This test exists because QTest reports test objects with no tests as 27 | // failures. 28 | void testDoesNothing(); 29 | }; 30 | 31 | } // namespace unit // 32 | 33 | #endif // TST_WIDGETS_H 34 | -------------------------------------------------------------------------------- /src/test/math/tst_glheatmaptest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "math/Common.h" 4 | #include "color/HeatMap.h" 5 | 6 | #include "tst_glheatmaptest.h" 7 | 8 | namespace unit 9 | { 10 | 11 | GLHeatMapTest::GLHeatMapTest(QObject *parent) 12 | : QObject(parent) 13 | { 14 | } 15 | 16 | void GLHeatMapTest::initTestCase() 17 | { 18 | QVERIFY2(true, "Empty"); 19 | } 20 | void GLHeatMapTest::cleanupTestCase() 21 | { 22 | QVERIFY2(true, "Empty"); 23 | } 24 | 25 | void GLHeatMapTest::testHeatMap() 26 | { 27 | QVERIFY2(true, "Empty"); 28 | /* 29 | QFETCH(qreal, wavelength); 30 | QFETCH(QColor4ub, color); 31 | QFETCH(bool, expected); 32 | const QColor4ub approximation = Heatmap::createHeatMapWaveLenghtColor(wavelength); 33 | QCOMPARE((approximation == color), expected);*/ 34 | } 35 | void GLHeatMapTest::testHeatMap_data() 36 | { 37 | QVERIFY2(true, "Empty"); 38 | /* 39 | QTest::addColumn("wavelength"); 40 | QTest::addColumn("color"); 41 | QTest::addColumn("expected"); 42 | QTest::newRow("red") << qreal(645.0) << QColor4ub(Qt::red) << true; 43 | QTest::newRow("yellow") << qreal(580.0) << QColor4ub(Qt::yellow) << true; 44 | QTest::newRow("green") << qreal(510.0) << QColor4ub(Qt::green) << true; 45 | QTest::newRow("cyan") << qreal(490.0) << QColor4ub(Qt::cyan) << true; 46 | QTest::newRow("blue") << qreal(440.0) << QColor4ub(Qt::blue) << true;*/ 47 | } 48 | 49 | } // namespace unit // 50 | 51 | QTEST_MAIN(unit::GLHeatMapTest) 52 | #include "tst_glheatmaptest.moc" 53 | -------------------------------------------------------------------------------- /src/test/math/tst_glheatmaptest.h: -------------------------------------------------------------------------------- 1 | #ifndef TST_GLHEATMAP_H 2 | #define TST_GLHEATMAP_H 3 | 4 | #include 5 | 6 | namespace unit 7 | { 8 | 9 | class GLHeatMapTest : public QObject 10 | { 11 | Q_OBJECT 12 | 13 | public: 14 | explicit GLHeatMapTest(QObject *parent = 0); 15 | 16 | private Q_SLOTS: 17 | void initTestCase(); 18 | void cleanupTestCase(); 19 | 20 | void testHeatMap(); 21 | void testHeatMap_data(); 22 | }; 23 | 24 | } // namespace unit // 25 | 26 | #endif // TST_GLHEATMAP_H // 27 | -------------------------------------------------------------------------------- /src/test/unit_main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2012 Spatial Transcriptomics AB, 3 | read LICENSE for licensing terms. 4 | Contact : Jose Fernandez Navarro 5 | 6 | */ 7 | 8 | #include 9 | 10 | // unit test lib 11 | #include "testTools/testsuite.h" 12 | 13 | // unit tests 14 | #include "test/controller/tst_widgets.h" 15 | #include "test/math/tst_glaabbtest.h" 16 | #include "test/math/tst_glquadtreetest.h" 17 | #include "test/math/tst_glheatmaptest.h" 18 | #include "test/model/tst_objectparsertest.h" 19 | #include "test/utils/tst_mathextendedtest.h" 20 | #include "test/network/test_auth.h" 21 | #include "test/network/test_rest.h" 22 | #include "test/viewOpenGL/test_AssertOpenGL.h" 23 | 24 | using namespace unit; 25 | 26 | int main(int argc, char **argv) 27 | { 28 | Q_UNUSED(argc); 29 | Q_UNUSED(argv); 30 | 31 | TestSuite suite; 32 | 33 | // suite.addTest(new WidgetsTest, "Widgets"); 34 | suite.addTest(new GLAABBTest, "GLAABB"); 35 | suite.addTest(new GLQuadTreeTest, "GLQuadTree").dependsOn("GLAABB"); 36 | suite.addTest(new GLHeatMapTest, "GLHeatMap"); 37 | suite.addTest(new ObjectParserTest, "ObjectParser"); 38 | suite.addTest(new MathExtendedTest, "MathExtended"); 39 | suite.addTest(new AuthTest, "Authorization"); 40 | suite.addTest(new RestTest, "REST Services"); 41 | suite.addTest(new OpenGLAssertTest, "OpenGL Assert"); 42 | 43 | return suite.exec(); 44 | } 45 | -------------------------------------------------------------------------------- /src/test/utils/tst_mathextendedtest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "math/Common.h" 4 | #include "tst_mathextendedtest.h" 5 | 6 | namespace unit 7 | { 8 | 9 | MathExtendedTest::MathExtendedTest(QObject *parent) 10 | : QObject(parent) 11 | { 12 | } 13 | 14 | void MathExtendedTest::initTestCase() 15 | { 16 | QVERIFY2(true, "Empty"); 17 | } 18 | 19 | void MathExtendedTest::cleanupTestCase() 20 | { 21 | QVERIFY2(true, "Empty"); 22 | } 23 | 24 | void MathExtendedTest::testFloatMod() 25 | { 26 | QFETCH(qreal, dividend); 27 | QFETCH(qreal, divisor); 28 | QFETCH(qreal, result); 29 | QFETCH(bool, expected); 30 | 31 | QCOMPARE(qFuzzyCompare(STMath::qMod(dividend, divisor), result), expected); 32 | } 33 | void MathExtendedTest::testFloatMod_data() 34 | { 35 | QTest::addColumn("dividend"); 36 | QTest::addColumn("divisor"); 37 | QTest::addColumn("result"); 38 | QTest::addColumn("expected"); 39 | 40 | QTest::newRow("mod_one") << static_cast(42.70) << static_cast(1.00) 41 | << static_cast(0.70) << true; 42 | QTest::newRow("mod_half") << static_cast(1.23) << static_cast(0.50) 43 | << static_cast(0.23) << true; 44 | QTest::newRow("-mod_half") << static_cast(-4.20) << static_cast(0.50) 45 | << static_cast(0.30) << true; 46 | QTest::newRow("mod_-half") << static_cast(1.23) << static_cast(-0.50) 47 | << static_cast(-0.27) << true; 48 | } 49 | 50 | // helper function 51 | bool fuzzyCompare(const QSizeF &s1, const QSizeF &s2) 52 | { 53 | return qFuzzyCompare(s1.width(), s2.width()) && qFuzzyCompare(s1.height(), s2.height()); 54 | } 55 | 56 | void MathExtendedTest::testClamp() 57 | { 58 | QFETCH(QSizeF, size); 59 | QFETCH(QSizeF, min); 60 | QFETCH(QSizeF, max); 61 | QFETCH(QSizeF, result); 62 | QFETCH(uint, mode); 63 | QFETCH(bool, expected); 64 | 65 | QCOMPARE(fuzzyCompare(STMath::clamp(size, min, max, static_cast(mode)), 66 | result), 67 | expected); 68 | } 69 | void MathExtendedTest::testClamp_data() 70 | { 71 | QTest::addColumn("size"); 72 | QTest::addColumn("min"); 73 | QTest::addColumn("max"); 74 | QTest::addColumn("result"); 75 | QTest::addColumn("mode"); 76 | QTest::addColumn("expected"); 77 | 78 | QTest::newRow("shrink_ignore_ratio") << QSizeF(4.0, 6.0) << QSizeF(1.0, 1.0) << QSizeF(4.0, 4.0) 79 | << QSizeF(4.0, 4.0) 80 | << static_cast(Qt::IgnoreAspectRatio) << true; 81 | QTest::newRow("shrink_keep_ratio") << QSizeF(4.0, 6.0) << QSizeF(1.0, 1.0) << QSizeF(4.0, 4.0) 82 | << QSizeF((8.0 / 3.0), 4.0) 83 | << static_cast(Qt::KeepAspectRatio) << true; 84 | QTest::newRow("expand_ignore_ratio") << QSizeF(0.4, 0.6) << QSizeF(1.0, 1.0) << QSizeF(4.0, 4.0) 85 | << QSizeF(1.0, 1.0) 86 | << static_cast(Qt::IgnoreAspectRatio) << true; 87 | QTest::newRow("expand_keep_ratio") << QSizeF(0.4, 0.6) << QSizeF(1.0, 1.0) << QSizeF(4.0, 4.0) 88 | << QSizeF(1.0, 1.5) << static_cast(Qt::KeepAspectRatio) 89 | << true; 90 | } 91 | 92 | } // namespace unit // 93 | 94 | QTEST_MAIN(unit::MathExtendedTest) 95 | #include "tst_mathextendedtest.moc" 96 | -------------------------------------------------------------------------------- /src/test/utils/tst_mathextendedtest.h: -------------------------------------------------------------------------------- 1 | #ifndef TST_MATHEXTENDEDTEST_H 2 | #define TST_MATHEXTENDEDTEST_H 3 | 4 | #include 5 | 6 | namespace unit 7 | { 8 | 9 | class MathExtendedTest : public QObject 10 | { 11 | Q_OBJECT 12 | 13 | public: 14 | explicit MathExtendedTest(QObject *parent = 0); 15 | 16 | private Q_SLOTS: 17 | void initTestCase(); 18 | void cleanupTestCase(); 19 | 20 | void testFloatMod(); 21 | void testFloatMod_data(); 22 | 23 | void testClamp(); 24 | void testClamp_data(); 25 | }; 26 | 27 | } // namespace unit // 28 | 29 | #endif // TST_MATHEXTENDEDTEST_H 30 | -------------------------------------------------------------------------------- /src/test/viewOpenGL/OpenGLTestWindow.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_OPENGLTESTWINDOW_H 2 | #define TEST_OPENGLTESTWINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class QPainter; 9 | class QOpenGLContext; 10 | class QOpenGLPaintDevice; 11 | class QOpenGLShaderProgram; 12 | 13 | // A window used to test OpenGL with. Based on the code from here: 14 | // http://doc.qt.io/qt-5/qtgui-openglwindow-example.html 15 | // By default this window shows a triangle rotating about its central axis. The 16 | // user can limit 17 | // the number of frames the triangle is displayed for, and can also pass in a 18 | // functor object 19 | // which will be called during the render call. 20 | class OpenGLTestWindow : public QWindow, protected QOpenGLFunctions 21 | { 22 | Q_OBJECT 23 | public: 24 | // A self contained call that will create a Qt application and a 25 | // OpenGLTestWindow with the 26 | // params passed in. This call is intended to be used to simplify testing. 27 | // Returns the return code from the exec of the Qt application used to launch 28 | // the window. 29 | static int run(const int maxRenderCount = -1, 30 | std::function renderFunc = &OpenGLTestWindow::doNothing); 31 | 32 | // The window will be displayed for maxRenderCount number of render calls, 33 | // after which it 34 | // will close itself. If maxRenderCount is less than 1 there will be no limit 35 | // and the window 36 | // will not close itself. renderFunc is a functor that will be called inside 37 | // the render loop, 38 | // after the rotating triangle has been setup and before advanceRenderCounter 39 | // is called. 40 | explicit OpenGLTestWindow(const int maxRenderCount, 41 | std::function renderFunc = &OpenGLTestWindow::doNothing, 42 | QWindow *parent = nullptr); 43 | 44 | virtual ~OpenGLTestWindow(); 45 | 46 | virtual void render(QPainter *painter); 47 | 48 | // Call advanceRenderCounter. 49 | virtual void render(); 50 | 51 | virtual void initialize(); 52 | 53 | void setAnimating(bool animating); 54 | 55 | public slots: 56 | void renderLater(); 57 | void renderNow(); 58 | 59 | protected: 60 | bool event(QEvent *event) Q_DECL_OVERRIDE; 61 | 62 | void exposeEvent(QExposeEvent *event) Q_DECL_OVERRIDE; 63 | 64 | // Call this to advance the render count: if a limit on the number of render 65 | // calls has 66 | // been set, this will cause the window to close itself. Called by render, and 67 | // provided 68 | // here to permit overriding of render. 69 | void advanceRenderCounter(); 70 | 71 | private: 72 | GLuint loadShader(GLenum type, const char *source); 73 | 74 | // Default (post)render function, does nothing. 75 | static void doNothing(); 76 | 77 | private: 78 | bool m_update_pending; 79 | bool m_animating; 80 | std::function m_renderFunc; 81 | QOpenGLContext *m_context; 82 | QOpenGLPaintDevice *m_device; 83 | QOpenGLShaderProgram *m_program; 84 | GLuint m_posAttr; 85 | GLuint m_colAttr; 86 | GLuint m_matrixUniform; 87 | int m_frame; 88 | int m_renderCountdown; 89 | }; 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /src/test/viewOpenGL/test_AssertOpenGL.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2015 Spatial Transcriptomics AB, 3 | read LICENSE for licensing terms. 4 | Contact : Jose Fernandez Navarro 5 | */ 6 | #include "test_AssertOpenGL.h" 7 | #include "OpenGLTestWindow.h" 8 | #include "viewOpenGL/AssertOpenGL.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | namespace unit 15 | { 16 | 17 | OpenGLAssertTest::OpenGLAssertTest(QObject *parent) 18 | : QObject(parent) 19 | { 20 | } 21 | 22 | void OpenGLAssertTest::initTestCase() 23 | { 24 | } 25 | 26 | void OpenGLAssertTest::cleanupTestCase() 27 | { 28 | } 29 | 30 | void OpenGLAssertTest::test_checkOpenGLErrorWithNoErrors() 31 | { 32 | const int framesVisible = 4; 33 | 34 | // We expect that the default OpenGL app has no OpenGL errors. 35 | auto test_OpenGL_has_no_error = 36 | [=](void) { QVERIFY2(checkOpenGLError(), "checkOpenGLError returned false."); }; 37 | 38 | OpenGLTestWindow::run(framesVisible, test_OpenGL_has_no_error); 39 | } 40 | 41 | void OpenGLAssertTest::test_checkOpenGLErrorDetectsError() 42 | { 43 | const int framesVisible = 4; 44 | 45 | // Create an error and check that we detect it. 46 | auto test_OpenGL_error_detected = [=](void) { 47 | QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); 48 | QVERIFY2(funcs, "No OpenGL context found."); 49 | 50 | // glEnable does not accept GL_LINE as an argument: causes GL_INVALID_ENUM. 51 | funcs->glEnable(GL_LINE); 52 | QVERIFY2(false == checkOpenGLError(), "checkOpenGLError incorrectly returned true."); 53 | }; 54 | 55 | OpenGLTestWindow::run(framesVisible, test_OpenGL_error_detected); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/viewOpenGL/test_AssertOpenGL.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2015 Spatial Transcriptomics AB, 3 | read LICENSE for licensing terms. 4 | Contact : Jose Fernandez Navarro 5 | */ 6 | 7 | #ifndef TST_ASSERTOPENGL_H 8 | #define TST_ASSERTOPENGL_H 9 | 10 | #include 11 | 12 | namespace unit 13 | { 14 | 15 | // Tests associated with the OpenGLAssert.h file. We cannot test an actual 16 | // assert, so we test 17 | // the components used by the OpenGL assert macro. 18 | class OpenGLAssertTest : public QObject 19 | { 20 | Q_OBJECT 21 | 22 | public: 23 | explicit OpenGLAssertTest(QObject *parent = 0); 24 | 25 | private Q_SLOTS: 26 | 27 | void initTestCase(); 28 | void cleanupTestCase(); 29 | 30 | void test_checkOpenGLErrorWithNoErrors(); 31 | void test_checkOpenGLErrorDetectsError(); 32 | }; 33 | } 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/viewPages/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LIBRARY_ARG_INCLUDES 2 | CellViewPage.h 3 | DatasetPage.h 4 | UserSelectionsPage.h 5 | GenesWidget.h 6 | SpotsWidget.h 7 | SelectionGenesWidget.h 8 | SelectionSpotsWidget.h 9 | SettingsWidget.h 10 | ) 11 | 12 | set(LIBRARY_ARG_SOURCES 13 | CellViewPage.cpp 14 | DatasetPage.cpp 15 | UserSelectionsPage.cpp 16 | GenesWidget.cpp 17 | SpotsWidget.cpp 18 | SelectionGenesWidget.cpp 19 | SelectionSpotsWidget.cpp 20 | SettingsWidget.cpp 21 | ) 22 | 23 | ST_LIBRARY() 24 | 25 | -------------------------------------------------------------------------------- /src/viewPages/CellViewPage.h: -------------------------------------------------------------------------------- 1 | #ifndef CELLVIEWPAGE_H 2 | #define CELLVIEWPAGE_H 3 | 4 | #include 5 | #include 6 | 7 | #include "data/Dataset.h" 8 | #include "data/UserSelection.h" 9 | #include "viewRenderer/ImageTextureGL.h" 10 | #include "viewRenderer/HeatMapLegendGL.h" 11 | #include "viewRenderer/GeneRendererGL.h" 12 | 13 | class SelectionDialog; 14 | class SettingsWidget; 15 | class SpotsWidget; 16 | class GenesWidget; 17 | class UserSelectionsPage; 18 | class AnalysisClustering; 19 | 20 | namespace Ui 21 | { 22 | class CellView; 23 | } // namespace Ui 24 | 25 | // This is the definition of the cell view page visualization widget 26 | // which contains a table of genes/spots and an OpenGL based 27 | // rendering canvas to visualize the cell tissue and the spots (dataset). 28 | // It also contains a toobar. Functionalities in the toolbar are handled by slots. 29 | // We do lazy inizialization of the visual stuff, specially OpenGL based stuff 30 | // It contains a widget with different visualization and data settings 31 | 32 | // TODO add a ruler visual object 33 | // TODO add tissue detection selection (Ludvig's) 34 | // TODO add a visual object to show the coordinates when the user hovers a spot 35 | class CellViewPage : public QWidget 36 | { 37 | Q_OBJECT 38 | 39 | public: 40 | CellViewPage(QSharedPointer spots, 41 | QSharedPointer genes, 42 | QSharedPointer user_selections, 43 | QWidget *parent = 0); 44 | virtual ~CellViewPage(); 45 | 46 | // clear the loaded dataset and reset settings 47 | void clear(); 48 | 49 | // the user has opened/edit a dataset 50 | void loadDataset(const Dataset &dataset); 51 | 52 | // the user has cleared the selections 53 | void clearSelections(); 54 | 55 | signals: 56 | 57 | public slots: 58 | 59 | private slots: 60 | 61 | // the user has updated the genes 62 | void slotGenesUpdate(); 63 | 64 | // the user has updated the spots 65 | void slotSpotsUpdated(); 66 | 67 | // save/esport current view 68 | void slotSaveImage(); 69 | void slotPrintImage(); 70 | 71 | // selection of spots using a the reg-exp dialog that takes gene names as input 72 | void slotSelectByRegExp(); 73 | 74 | // user wants to show the QC widget 75 | void slotShowQC(); 76 | 77 | // user wants to perform spot clustering 78 | void slotClustering(); 79 | 80 | // user wants to load a file with spot colors 81 | void slotLoadSpotColorsFile(); 82 | 83 | // user wants to load a file with genes to select 84 | void slotLoadGenes(); 85 | 86 | // user has performed spot classification 87 | void slotLoadSpotColors(); 88 | 89 | // user has made a selection in the clustering widget 90 | void slotSelectSpotsClustering(); 91 | 92 | // user wants to export the computed clusters as selections 93 | void slotCreateClusteringSelections(); 94 | 95 | // user wants to create a selection 96 | void slotCreateSelection(); 97 | 98 | // when the image has been tiled and loaded 99 | void slotImageLoaded(const bool loaded); 100 | 101 | private: 102 | // create OpenGL graphical elements and view 103 | void initRenderer(); 104 | 105 | // create all the connections 106 | void createConnections(); 107 | 108 | // Reference to other views 109 | QSharedPointer m_spots; 110 | QSharedPointer m_genes; 111 | QSharedPointer m_user_selections; 112 | 113 | // GUI UI object 114 | QScopedPointer m_ui; 115 | 116 | // OpenGL visualization objects 117 | QSharedPointer m_legend; 118 | QSharedPointer m_gene_plotter; 119 | QSharedPointer m_image; 120 | 121 | // different control widgets and views 122 | QScopedPointer m_settings; 123 | 124 | // the spot clustering widget 125 | QScopedPointer m_clustering; 126 | 127 | // the currently opened dataset 128 | Dataset m_dataset; 129 | 130 | // watcher for the image loading 131 | QFutureWatcher m_watcher; 132 | 133 | Q_DISABLE_COPY(CellViewPage) 134 | }; 135 | 136 | #endif // CELLVIEWPAGE_H 137 | -------------------------------------------------------------------------------- /src/viewPages/DatasetPage.h: -------------------------------------------------------------------------------- 1 | #ifndef DATASETPAGE_H 2 | #define DATASETPAGE_H 3 | 4 | #include 5 | #include 6 | #include "data/Dataset.h" 7 | 8 | class QItemSelectionModel; 9 | class QItemSelection; 10 | class DatasetItemModel; 11 | class QSortFilterProxyModel; 12 | class WaitingSpinnerWidget; 13 | class DatasetImporter; 14 | 15 | namespace Ui 16 | { 17 | class DataSets; 18 | } // namespace Ui // 19 | 20 | // This is the definition of the datasets view which contains 21 | // a table with datasets (imported locally) 22 | // It has a toolbar with basic functionalities (such as open, edit, export, import, etc..) 23 | 24 | // TODO add option to highlight the currently opened dataset 25 | // TODO add right click support (copy, open, save, delete...) 26 | class DatasetPage : public QWidget 27 | { 28 | Q_OBJECT 29 | 30 | public: 31 | explicit DatasetPage(QWidget *parent = 0); 32 | virtual ~DatasetPage(); 33 | 34 | // returns the currently opened dataset 35 | QSharedPointer getCurrentDataset() const; 36 | 37 | public slots: 38 | 39 | private slots: 40 | 41 | // changes the selected dataset to index. 42 | void slotDatasetSelected(QModelIndex index); 43 | 44 | // selects the indexed dataset and opens it. 45 | void slotSelectAndOpenDataset(QModelIndex index); 46 | 47 | // update the MVC table model 48 | void slotDatasetsUpdated(); 49 | 50 | // some slots for the actions of the toolbar 51 | void slotOpenDataset(); 52 | void slotOpenDataset(const QModelIndex &index); 53 | void slotRemoveDataset(); 54 | void slotRemoveDataset(const QModelIndex &index); 55 | void slotEditDataset(); 56 | void slotEditDataset(const QModelIndex &index); 57 | void slotImportDataset(); 58 | 59 | signals: 60 | 61 | // to notify about dataset/s action/s 62 | void signalDatasetOpen(const QString dataset); 63 | void signalDatasetRemoved(const QString dataset); 64 | void signalDatasetUpdated(const QString dataset); 65 | 66 | protected: 67 | void showEvent(QShowEvent *event) override; 68 | 69 | private: 70 | // clear focus and resets to default all buttons status 71 | void clearControls(); 72 | // check if a dataset with the same name exists 73 | bool nameExist(const QString &name); 74 | 75 | // Internal function for basic operations 76 | void editDataset(const Dataset &dataset); 77 | void openDataset(const Dataset &dataset); 78 | void removeDatasets(const QList &datasets); 79 | 80 | // to get the data model from the table 81 | QSortFilterProxyModel *datasetsProxyModel(); 82 | DatasetItemModel *datasetsModel(); 83 | 84 | // reference to ui object 85 | QScopedPointer m_ui; 86 | // List of imported datasets (from files) 87 | QList m_importedDatasets; 88 | // Currently open dataset 89 | QSharedPointer m_open_dataset; 90 | 91 | Q_DISABLE_COPY(DatasetPage) 92 | }; 93 | 94 | #endif /* DATASETPAGE_H */ 95 | -------------------------------------------------------------------------------- /src/viewPages/GenesWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef GENESWIDGET_H 2 | #define GENESWIDGET_H 3 | 4 | #include 5 | #include 6 | 7 | class QPushButton; 8 | class QLineEdit; 9 | class GenesTableView; 10 | class Dataset; 11 | class QColorDialog; 12 | 13 | // This widget is componsed of the genes table 14 | // a search field and the select and action menus so the user can 15 | // select/deselect genes and change their color and/or threshold. 16 | // Every action will affect what genes are shown in the cell view. 17 | // Here when a dataset is opened its unique genes will be shown 18 | // so the user can interact with them to visualize them in the cell view 19 | class GenesWidget : public QWidget 20 | { 21 | Q_OBJECT 22 | 23 | public: 24 | explicit GenesWidget(QWidget *parent = 0); 25 | virtual ~GenesWidget(); 26 | 27 | // clear focus/status and selections 28 | void clear(); 29 | 30 | signals: 31 | 32 | // signals emitted when the user selects or change colors of genes 33 | void signalGenesUpdated(); 34 | 35 | public slots: 36 | 37 | // the user has opened a dataset and the genes must be updated 38 | // genes is a reference to the genes of the dataset 39 | void slotLoadDataset(const Dataset &dataset); 40 | 41 | private slots: 42 | 43 | // slots triggered by the show/color controls in the gene table 44 | void slotSetColorAllSelected(const QColor &color); 45 | void slotSetVisibilityForSelectedRows(bool visible); 46 | void slotHideAllSelected(); 47 | void slotShowAllSelected(); 48 | 49 | private: 50 | // internal function to configure created buttons 51 | // to avoid code duplication 52 | // TODO better approach would be to have factories somewhere else 53 | void configureButton(QPushButton *button, const QIcon &icon, const QString &tooltip); 54 | 55 | // some references needed to UI elements 56 | QScopedPointer m_lineEdit; 57 | QScopedPointer m_genes_tableview; 58 | QScopedPointer m_colorList; 59 | 60 | Q_DISABLE_COPY(GenesWidget) 61 | }; 62 | 63 | #endif // GENESWIDGET_H 64 | -------------------------------------------------------------------------------- /src/viewPages/SelectionGenesWidget.cpp: -------------------------------------------------------------------------------- 1 | #include "SelectionGenesWidget.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "SettingsStyle.h" 9 | 10 | #include "ui_genesSelectionWidget.h" 11 | 12 | using namespace Style; 13 | 14 | SelectionGenesWidget::SelectionGenesWidget(const UserSelection::STDataFrame &data, 15 | QWidget *parent, Qt::WindowFlags f) 16 | : QWidget(parent, f) 17 | , m_ui(new Ui::genesSelectionWidget()) 18 | { 19 | m_ui->setupUi(this); 20 | m_ui->searchField->setClearButtonEnabled(true); 21 | m_ui->searchField->setFixedSize(CELL_PAGE_SUB_MENU_LINE_EDIT_SIZE); 22 | m_ui->searchField->setStyleSheet(CELL_PAGE_SUB_MENU_LINE_EDIT_STYLE); 23 | 24 | // data model 25 | const int columns = 2; 26 | const int rows = data.genes.size(); 27 | QStandardItemModel *model = new QStandardItemModel(rows,columns, this); 28 | model->setHorizontalHeaderItem(0, new QStandardItem(QString("Gene"))); 29 | model->setHorizontalHeaderItem(1, new QStandardItem(QString("Count"))); 30 | // populate 31 | for (uword i = 0; i < data.counts.n_cols; ++i) { 32 | const QString gene = data.genes.at(i); 33 | const float count = sum(data.counts.col(i)); 34 | const QString count_str = QString::number(count); 35 | QStandardItem *gene_item = new QStandardItem(gene); 36 | gene_item->setData(gene, Qt::UserRole); 37 | gene_item->setData(gene, Qt::DisplayRole); 38 | model->setItem(i, 0, gene_item); 39 | QStandardItem *count_item = new QStandardItem(count_str); 40 | count_item->setData(count, Qt::UserRole); 41 | count_item->setData(count_str, Qt::DisplayRole); 42 | model->setItem(i, 1, count_item); 43 | } 44 | // sorting model 45 | QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this); 46 | proxy->setSourceModel(model); 47 | proxy->setSortCaseSensitivity(Qt::CaseInsensitive); 48 | proxy->setFilterCaseSensitivity(Qt::CaseInsensitive); 49 | proxy->setSortRole(Qt::UserRole); 50 | m_ui->tableview->setModel(proxy); 51 | 52 | // settings for the table 53 | m_ui->tableview->setSortingEnabled(true); 54 | m_ui->tableview->setShowGrid(true); 55 | m_ui->tableview->setWordWrap(true); 56 | m_ui->tableview->setAlternatingRowColors(true); 57 | m_ui->tableview->sortByColumn(0, Qt::AscendingOrder); 58 | 59 | m_ui->tableview->setFrameShape(QFrame::StyledPanel); 60 | m_ui->tableview->setFrameShadow(QFrame::Sunken); 61 | m_ui->tableview->setGridStyle(Qt::SolidLine); 62 | m_ui->tableview->setCornerButtonEnabled(false); 63 | m_ui->tableview->setLineWidth(1); 64 | 65 | m_ui->tableview->setSelectionBehavior(QAbstractItemView::SelectRows); 66 | m_ui->tableview->setSelectionMode(QAbstractItemView::NoSelection); 67 | m_ui->tableview->setEditTriggers(QAbstractItemView::NoEditTriggers); 68 | 69 | m_ui->tableview->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch); 70 | m_ui->tableview->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch); 71 | m_ui->tableview->horizontalHeader()->setSortIndicatorShown(true); 72 | m_ui->tableview->verticalHeader()->hide(); 73 | 74 | m_ui->tableview->model()->submit(); // support for caching (speed up) 75 | 76 | // Connect the search field signal 77 | connect(m_ui->searchField, 78 | &QLineEdit::textChanged, 79 | proxy, 80 | &QSortFilterProxyModel::setFilterFixedString); 81 | 82 | // allow to copy the content of the table 83 | m_ui->tableview->setContextMenuPolicy(Qt::CustomContextMenu); 84 | connect(m_ui->tableview, &QTableView::customContextMenuRequested, 85 | this, &SelectionGenesWidget::customMenuRequested); 86 | 87 | } 88 | 89 | SelectionGenesWidget::~SelectionGenesWidget() 90 | { 91 | } 92 | 93 | void SelectionGenesWidget::customMenuRequested(const QPoint &pos) 94 | { 95 | const QModelIndex index = m_ui->tableview->indexAt(pos); 96 | if (index.isValid()) { 97 | QMenu *menu = new QMenu(this); 98 | menu->addAction(new QAction(tr("Copy"), this)); 99 | if (menu->exec(m_ui->tableview->viewport()->mapToGlobal(pos))) { 100 | const QString text = index.data().toString(); 101 | QClipboard *clipboard = QApplication::clipboard(); 102 | clipboard->setText(text); 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/viewPages/SelectionGenesWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef SELECTIONGENESWIDGET_H 2 | #define SELECTIONGENESWIDGET_H 3 | 4 | #include 5 | #include 6 | 7 | #include "data/UserSelection.h" 8 | 9 | namespace Ui 10 | { 11 | class genesSelectionWidget; 12 | } // namespace Ui 13 | 14 | // This widgets is part of the UserSelectionsPage. It shows the list of unique 15 | // genes present in a UserSelection and their aggregated counts. 16 | // It contains a search field to search genes by name. 17 | class SelectionGenesWidget : public QWidget 18 | { 19 | Q_OBJECT 20 | 21 | public: 22 | 23 | explicit SelectionGenesWidget(const UserSelection::STDataFrame &data, 24 | QWidget *parent = 0, Qt::WindowFlags f = 0); 25 | virtual ~SelectionGenesWidget(); 26 | 27 | private slots: 28 | 29 | void customMenuRequested(const QPoint &pos); 30 | 31 | signals: 32 | 33 | private: 34 | 35 | // GUI UI object 36 | QScopedPointer m_ui; 37 | 38 | 39 | Q_DISABLE_COPY(SelectionGenesWidget) 40 | }; 41 | 42 | #endif // SELECTIONGENESWIDGET_H 43 | -------------------------------------------------------------------------------- /src/viewPages/SelectionSpotsWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef SELECTIONSPOTSWIDGET_H 2 | #define SELECTIONSPOTSWIDGET_H 3 | 4 | #include 5 | #include "data/UserSelection.h" 6 | 7 | namespace Ui 8 | { 9 | class spotsSelectionWidget; 10 | } // namespace Ui 11 | 12 | 13 | // This widgets is part of the UserSelectionsPage. It shows the list of unique 14 | // spots present in a UserSelection and their aggregated counts. 15 | // It contains a search field to search genes by name. 16 | class SelectionSpotsWidget : public QWidget 17 | { 18 | Q_OBJECT 19 | 20 | public: 21 | 22 | explicit SelectionSpotsWidget(const UserSelection::STDataFrame &data, 23 | QWidget *parent = 0, Qt::WindowFlags f = 0); 24 | virtual ~SelectionSpotsWidget(); 25 | signals: 26 | 27 | private slots: 28 | 29 | void customMenuRequested(const QPoint &pos); 30 | 31 | private: 32 | 33 | // GUI UI object 34 | QScopedPointer m_ui; 35 | 36 | Q_DISABLE_COPY(SelectionSpotsWidget) 37 | }; 38 | 39 | #endif // SELECTIONSPOTSWIDGET_H 40 | -------------------------------------------------------------------------------- /src/viewPages/SettingsWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef SETTINGSWIDGET_H 2 | #define SETTINGSWIDGET_H 3 | 4 | #include 5 | 6 | namespace Ui { 7 | class SettingsWidget; 8 | } 9 | 10 | class SettingsWidget : public QWidget 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | 16 | enum VisualTypeMode { 17 | Reads = 1, 18 | ReadsLog = 2, 19 | Genes = 3, 20 | GenesLog = 4 21 | }; 22 | 23 | enum NormalizationMode { 24 | RAW = 1, 25 | TPM = 2, 26 | REL = 3, 27 | DESEQ = 4, 28 | SCRAN = 5 29 | }; 30 | 31 | enum VisualMode { 32 | Normal = 1, 33 | DynamicRange = 2, 34 | HeatMap = 3, 35 | ColorRange = 4, 36 | ColorRange2 = 5 37 | }; 38 | 39 | struct Rendering { 40 | int reads_threshold; 41 | int genes_threshold; 42 | int spots_threshold; 43 | int ind_reads_threshold; 44 | double legend_min; 45 | double legend_max; 46 | float intensity; 47 | float size; 48 | VisualMode visual_mode; 49 | NormalizationMode normalization_mode; 50 | VisualTypeMode visual_type_mode; 51 | bool gene_cutoff; 52 | }; 53 | 54 | explicit SettingsWidget(QWidget *parent = 0); 55 | ~SettingsWidget(); 56 | 57 | void reset(); 58 | Rendering &renderingSettings(); 59 | 60 | public slots: 61 | 62 | private slots: 63 | 64 | void slotGenesTreshold(int); 65 | void slotSpotsTreshold(int); 66 | void slotReadsTreshold(int); 67 | void slotIndReadsTreshold(int); 68 | void slotIntensity(int); 69 | void slotSize(int); 70 | void slotGeneCutoff(bool); 71 | void slotNormalization(NormalizationMode); 72 | void slotVisualMode(VisualMode); 73 | void slotVisualMode(VisualTypeMode); 74 | 75 | signals: 76 | 77 | void signalShowSpots(bool); 78 | void signalShowLegend(bool); 79 | void signalShowImage(bool); 80 | void signalSpotRendering(); 81 | 82 | private: 83 | QScopedPointer m_ui; 84 | Rendering m_rendering_settings; 85 | }; 86 | 87 | #endif // SETTINGSWIDGET_H 88 | -------------------------------------------------------------------------------- /src/viewPages/SpotsWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef SPOTSWIDGET_H 2 | #define SPOTSWIDGET_H 3 | 4 | #include 5 | #include 6 | 7 | class QPushButton; 8 | class QLineEdit; 9 | class Dataset; 10 | class SpotItemModel; 11 | class SpotsTableView; 12 | class QSortFilterProxyModel; 13 | class QColorDialog; 14 | 15 | // This widget is componsed of the spots table 16 | // a search field and the select and action menus so the user can 17 | // select/deselect spots and change their color. 18 | // Every action will affect what spots are shown in the cell view. 19 | // Here when a dataset is opened its unique spots will be shown 20 | // so the user can interact with them to visualize them in the cell view 21 | class SpotsWidget : public QWidget 22 | { 23 | Q_OBJECT 24 | public: 25 | explicit SpotsWidget(QWidget *parent = 0); 26 | virtual ~SpotsWidget(); 27 | 28 | // clear focus/status and selections 29 | void clear(); 30 | 31 | // forces an update of the table 32 | void updateModelTable(); 33 | 34 | signals: 35 | 36 | // signals emitted when the user selects or change colors of spots 37 | void signalSpotsUpdated(); 38 | 39 | public slots: 40 | // the user has opened a dataset and the spots must be updated 41 | // spots is a reference to the spots of the dataset 42 | void slotLoadDataset(const Dataset &dataset); 43 | 44 | private slots: 45 | 46 | // slots triggered by the show/color controls in the gene table 47 | void slotSetColorAllSelected(const QColor &color); 48 | void slotSetVisibilityForSelectedRows(bool visible); 49 | void slotHideAllSelected(); 50 | void slotShowAllSelected(); 51 | 52 | private: 53 | // internal function to configure created buttons 54 | // to avoid code duplication 55 | // TODO better approach would be to have factories somewhere else 56 | void configureButton(QPushButton *button, const QIcon &icon, const QString &tooltip); 57 | 58 | // some references needed to UI elements 59 | QScopedPointer m_lineEdit; 60 | QScopedPointer m_spots_tableview; 61 | QScopedPointer m_colorList; 62 | 63 | Q_DISABLE_COPY(SpotsWidget) 64 | 65 | }; 66 | 67 | #endif // SPOTSWIDGET_H 68 | -------------------------------------------------------------------------------- /src/viewPages/UserSelectionsPage.h: -------------------------------------------------------------------------------- 1 | #ifndef USERSELECTIONSPAGE_H 2 | #define USERSELECTIONSPAGE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class UserSelectionsItemModel; 9 | class QSortFilterProxyModel; 10 | class UserSelection; 11 | 12 | namespace Ui 13 | { 14 | class UserSelections; 15 | } // namespace Ui // 16 | 17 | // UserSelections page contains a table with the selection made by the user. 18 | // Users can interact here to edit/remove selections and to perform analysis 19 | // like the DEA, PCA, etc.. 20 | 21 | // TODO add option to show right click with mouse in selection (open, copy, edit...) 22 | // TODO implement DEA analysis 23 | class UserSelectionsPage : public QWidget 24 | { 25 | Q_OBJECT 26 | 27 | public: 28 | explicit UserSelectionsPage(QWidget *parent = 0); 29 | virtual ~UserSelectionsPage(); 30 | 31 | // clear the loaded content 32 | void clean(); 33 | 34 | // to add a new selection to the list 35 | void addSelection(const UserSelection& selection); 36 | 37 | signals: 38 | 39 | public slots: 40 | 41 | private slots: 42 | 43 | // slot that handles when the user selects a selection 44 | void slotSelectionSelected(QModelIndex index); 45 | // slots to handle when the user wants to export the selection to a file 46 | void slotExportSelection(); 47 | void slotExportSelection(QModelIndex); 48 | // slot to handle when the user wants to remove a selection 49 | void slotRemoveSelection(); 50 | void slotRemoveSelection(QModelIndex); 51 | // slot to handle when the user wants to edit a selection 52 | void slotEditSelection(); 53 | void slotEditSelection(QModelIndex); 54 | // this slot will init and show the D.E.A. dialog (requires two selected 55 | // selections) 56 | void slotPerformDEA(); 57 | // slot to perform a correlation analysis between two selections 58 | void slotPerformCorrelation(); 59 | // slot to show the aggregated gene counts of the selection in a table 60 | void slotShowGenes(); 61 | // slot to show the aggregated spot counts of the selection in a table 62 | void slotShowSpots(); 63 | // slot to show the QC widget with the selection 64 | void slotQC(); 65 | // slot to show the Scatter plot of genes and reads 66 | void slotScatter(); 67 | // slot to perform a PCA on several selections 68 | void slotPCA(); 69 | // slot to merge several selections into one 70 | void slotMerge(); 71 | // to import a selection from a file 72 | void slotImportSelection(); 73 | 74 | protected: 75 | void showEvent(QShowEvent *event); 76 | 77 | private: 78 | 79 | // internal functions for basic operations 80 | void removeSelections(const QList &selections); 81 | void editSelection(const UserSelection &selection); 82 | void exportSelection(const UserSelection &selection); 83 | 84 | // internal function to check if the name exists 85 | bool nameExist(const QString &name); 86 | 87 | // internal clear focus and default status for the buttons 88 | void clearControls(); 89 | // internal function to update the selections in the model 90 | void selectionsUpdated(); 91 | 92 | // to retrieve the table's model 93 | QSortFilterProxyModel *selectionsProxyModel(); 94 | UserSelectionsItemModel *selectionsModel(); 95 | 96 | // Ui object 97 | QScopedPointer m_ui; 98 | // the list of selections objects 99 | QList m_selections; 100 | 101 | Q_DISABLE_COPY(UserSelectionsPage) 102 | }; 103 | 104 | #endif /* USERSELECTIONSPAGE_H */ 105 | -------------------------------------------------------------------------------- /src/viewPages/genesSelectionWidget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | genesSelectionWidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 300 11 | 12 | 13 | 14 | Genes 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Qt::Horizontal 25 | 26 | 27 | 28 | 40 29 | 20 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 50 39 | 0 40 | 41 | 42 | 43 | false 44 | 45 | 46 | Qt::ClickFocus 47 | 48 | 49 | Qt::DefaultContextMenu 50 | 51 | 52 | false 53 | 54 | 55 | Search for a gene name among the selected genes 56 | 57 | 58 | Search for a gene name among the selected genes 59 | 60 | 61 | Search for a gene name among the selected genes 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 0 72 | 0 73 | 74 | 75 | 76 | 77 | 100 78 | 0 79 | 80 | 81 | 82 | true 83 | 84 | 85 | Qt::ClickFocus 86 | 87 | 88 | Genes 89 | 90 | 91 | QAbstractScrollArea::AdjustIgnored 92 | 93 | 94 | QAbstractItemView::NoEditTriggers 95 | 96 | 97 | false 98 | 99 | 100 | false 101 | 102 | 103 | QAbstractItemView::NoSelection 104 | 105 | 106 | QAbstractItemView::ScrollPerItem 107 | 108 | 109 | QAbstractItemView::ScrollPerPixel 110 | 111 | 112 | false 113 | 114 | 115 | true 116 | 117 | 118 | false 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /src/viewPages/spotsSelectionWidget.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | spotsSelectionWidget 4 | 5 | 6 | 7 | 0 8 | 0 9 | 240 10 | 320 11 | 12 | 13 | 14 | Spots 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Qt::Horizontal 25 | 26 | 27 | 28 | 40 29 | 20 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | Spots Selected 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/viewRenderer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LIBRARY_ARG_INCLUDES 2 | GeneRendererGL.h 3 | CellGLView.h 4 | HeatMapLegendGL.h 5 | ImageTextureGL.h 6 | GraphicItemGL.h 7 | SelectionEvent.h 8 | ) 9 | 10 | set(LIBRARY_ARG_SOURCES 11 | GeneRendererGL.cpp 12 | CellGLView.cpp 13 | HeatMapLegendGL.cpp 14 | ImageTextureGL.cpp 15 | GraphicItemGL.cpp 16 | ) 17 | 18 | ST_LIBRARY() 19 | -------------------------------------------------------------------------------- /src/viewRenderer/GeneRendererGL.cpp: -------------------------------------------------------------------------------- 1 | #include "GeneRendererGL.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "math/RInterface.h" 11 | 12 | #include "color/HeatMap.h" 13 | 14 | // hash function for QColor for use in QSet / QHash 15 | QT_BEGIN_NAMESPACE 16 | uint qHash(const QColor &c) 17 | { 18 | return qHash(c.rgba()); 19 | } 20 | QT_END_NAMESPACE 21 | 22 | GeneRendererGL::GeneRendererGL(SettingsWidget::Rendering &rendering_settings, QObject *parent) 23 | : GraphicItemGL(parent) 24 | , m_rendering_settings(rendering_settings) 25 | , m_initialized(false) 26 | { 27 | setVisualOption(GraphicItemGL::Transformable, true); 28 | setVisualOption(GraphicItemGL::Visible, true); 29 | setVisualOption(GraphicItemGL::Selectable, false); 30 | setVisualOption(GraphicItemGL::Yinverted, false); 31 | setVisualOption(GraphicItemGL::Xinverted, false); 32 | setVisualOption(GraphicItemGL::RubberBandable, true); 33 | setAnchor(GraphicItemGL::Anchor::None); 34 | 35 | // initialize variables 36 | clearData(); 37 | } 38 | 39 | GeneRendererGL::~GeneRendererGL() 40 | { 41 | } 42 | 43 | void GeneRendererGL::clearData() 44 | { 45 | m_initialized = false; 46 | } 47 | 48 | void GeneRendererGL::slotUpdate() 49 | { 50 | if (m_initialized) { 51 | m_geneData->computeRenderingData(m_rendering_settings); 52 | } 53 | } 54 | 55 | void GeneRendererGL::attachData(QSharedPointer data) 56 | { 57 | m_geneData = data; 58 | m_initialized = true; 59 | m_border = m_geneData->getBorder(); 60 | } 61 | 62 | void GeneRendererGL::draw(QOpenGLFunctionsVersion &qopengl_functions, QPainter &painter) 63 | { 64 | Q_UNUSED(qopengl_functions) 65 | 66 | if (!m_initialized) { 67 | return; 68 | } 69 | 70 | const bool is_dynamic = 71 | m_rendering_settings.visual_mode == SettingsWidget::VisualMode::DynamicRange; 72 | const bool do_values = m_rendering_settings.visual_mode != SettingsWidget::VisualMode::Normal; 73 | 74 | const auto &spots = m_geneData->spots(); 75 | const auto &visibles = m_geneData->renderingVisible(); 76 | const auto &colors = m_geneData->renderingColors(); 77 | const auto &selecteds = m_geneData->renderingSelected(); 78 | const auto &values = m_geneData->renderingValues(); 79 | const float size = m_rendering_settings.size / 2; 80 | const float size_selected = size / 4; 81 | const double min_value = m_rendering_settings.legend_min; 82 | const double max_value = m_rendering_settings.legend_max; 83 | const float intensity = m_rendering_settings.intensity; 84 | 85 | QPen pen; 86 | painter.setBrush(Qt::NoBrush); 87 | for (int i = 0; i < spots.size(); ++i) { 88 | const bool visible = visibles.at(i); 89 | const auto spot = spots.at(i)->adj_coordinates(); 90 | const double x = spot.first; 91 | const double y = spot.second; 92 | if (visible) { 93 | const bool selected = selecteds.at(i); 94 | const double value = values.at(i); 95 | QColor color = colors.at(i); 96 | if (do_values && !spots.at(i)->visible()) { 97 | color = Color::adjustVisualMode(color, 98 | value, 99 | min_value, 100 | max_value, 101 | m_rendering_settings.visual_mode); 102 | } 103 | if (!is_dynamic) { 104 | color.setAlphaF(intensity); 105 | } 106 | pen.setColor(color); 107 | pen.setWidthF(size); 108 | painter.setPen(pen); 109 | painter.drawEllipse(QRectF(x, y, size, size)); 110 | if (selected) { 111 | pen.setColor(Qt::white); 112 | pen.setWidthF(size_selected); 113 | painter.setPen(pen); 114 | painter.drawEllipse(QRectF(x, y, size, size)); 115 | } 116 | } 117 | } 118 | } 119 | 120 | const QRectF GeneRendererGL::boundingRect() const 121 | { 122 | return m_border; 123 | } 124 | 125 | void GeneRendererGL::setSelectionArea(const SelectionEvent &event) 126 | { 127 | m_geneData->selectSpots(event); 128 | slotUpdate(); 129 | emit updated(); 130 | } 131 | -------------------------------------------------------------------------------- /src/viewRenderer/GeneRendererGL.h: -------------------------------------------------------------------------------- 1 | #ifndef GENERENDERERGL_H 2 | #define GENERENDERERGL_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "data/STData.h" 9 | #include "viewPages/SettingsWidget.h" 10 | 11 | #include "GraphicItemGL.h" 12 | 13 | // Gene renderer is what renders the data on the CellGLView canvas. 14 | // It uses data arrays (GeneData) to render trough shaders. 15 | // It has some attributes and variables changeable by slots. 16 | // To clarify, by index(spot) we mean the physical spot in the array 17 | // and by feature we mean the gene-index combination 18 | class GeneRendererGL : public GraphicItemGL 19 | { 20 | Q_OBJECT 21 | 22 | public: 23 | 24 | GeneRendererGL(SettingsWidget::Rendering &rendering_settings, QObject *parent = 0); 25 | virtual ~GeneRendererGL(); 26 | 27 | // data builder (create visualization data from the ST data) 28 | void attachData(QSharedPointer data); 29 | 30 | // clears data containers and reset variables to default 31 | void clearData(); 32 | 33 | public slots: 34 | 35 | // update the rendering data 36 | void slotUpdate(); 37 | 38 | signals: 39 | 40 | protected: 41 | // override method that returns the drawing size of this element 42 | const QRectF boundingRect() const override; 43 | void draw(QOpenGLFunctionsVersion &qopengl_functions, QPainter &painter) override; 44 | void setSelectionArea(const SelectionEvent &event); 45 | 46 | private: 47 | 48 | // compiles and loads the shaders 49 | void setupShaders(); 50 | 51 | // bounding rect area 52 | QRectF m_border; 53 | 54 | // rendering settings 55 | SettingsWidget::Rendering &m_rendering_settings; 56 | 57 | // rendering data 58 | QSharedPointer m_geneData; 59 | 60 | // OpenGL rendering shader 61 | QOpenGLShaderProgram m_shader_program; 62 | 63 | // true when the rendering data has been initialized 64 | bool m_initialized; 65 | 66 | Q_DISABLE_COPY(GeneRendererGL) 67 | }; 68 | 69 | #endif // GENERENDERERGL_H 70 | -------------------------------------------------------------------------------- /src/viewRenderer/GraphicItemGL.h: -------------------------------------------------------------------------------- 1 | #ifndef GRAPHICITEMGL_H 2 | #define GRAPHICITEMGL_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class QRectF; 9 | class QMouseEvent; 10 | class SelectionEvent; 11 | 12 | // Base class for rendering nodes used in CellGLView 13 | // it contains some basic functionalities and options 14 | // For any OpenGL/QPainter based graphical object that needs 15 | // to be rendered in the CellGLView, the object 16 | // must has this class as a base class 17 | class GraphicItemGL : public QObject 18 | { 19 | 20 | Q_OBJECT 21 | Q_FLAGS(VisualOptions) 22 | 23 | public: 24 | using QOpenGLFunctionsVersion = QOpenGLFunctions_2_0; 25 | 26 | enum Anchor { 27 | Center = 1, 28 | North = 2, 29 | NorthEast = 3, 30 | East = 4, 31 | SouthEast = 5, 32 | South = 6, 33 | SouthWest = 7, 34 | West = 8, 35 | NorthWest = 9, 36 | None = 10 37 | }; 38 | 39 | enum VisualOption { 40 | Visible = 1, 41 | Selectable = 2, 42 | Transformable = 4, 43 | Yinverted = 8, 44 | Xinverted = 16, 45 | RubberBandable = 32 46 | }; 47 | Q_DECLARE_FLAGS(VisualOptions, VisualOption) 48 | 49 | explicit GraphicItemGL(QObject *parent = 0); 50 | virtual ~GraphicItemGL(); 51 | 52 | // The anchor defines where the object will be placed 53 | // with respect to the rendering canvas 54 | Anchor anchor() const; 55 | void setAnchor(Anchor anchor); 56 | 57 | // transformation matrix of the object 58 | // (local transformation with respect to the rendering canvas) 59 | const QTransform transform() const; 60 | void setTransform(const QTransform &transform); 61 | 62 | // properties stored in the flags 63 | bool visible() const; 64 | bool selectable() const; 65 | bool transformable() const; 66 | bool invertedY() const; 67 | bool invertedX() const; 68 | bool rubberBandable() const; 69 | 70 | // Methods to change the settings/properties 71 | GraphicItemGL::VisualOptions visualOptions() const; 72 | void setVisualOptions(GraphicItemGL::VisualOptions visualOptions); 73 | void setVisualOption(GraphicItemGL::VisualOption visualOption, bool value); 74 | 75 | // The drawing method, must be overriden in every drawing object 76 | virtual void draw(QOpenGLFunctionsVersion &qopengl_functions, QPainter &painter) = 0; 77 | 78 | // geometry of the graphic element 79 | virtual const QRectF boundingRect() const = 0; 80 | 81 | // must be implemented in the node to support selection events (mouse selection) 82 | virtual void setSelectionArea(const SelectionEvent &event) = 0; 83 | 84 | // bounding rect boundaries check 85 | bool contains(const QPointF &point) const; 86 | bool contains(const QRectF &rect) const; 87 | 88 | public slots: 89 | // TODO should prepend "slot" 90 | void setVisible(bool); 91 | 92 | signals: 93 | // TODO should prepend "signal" 94 | // to notify the rendering OpenGL canvas that a render is needed 95 | void updated(); 96 | 97 | protected: 98 | // This is used to adjust the position of the element according to an anchor 99 | // option 100 | // returns the local transformation matrix adjusted for the anchor position 101 | const QTransform adjustForAnchor(const QTransform &transform) const; 102 | 103 | // local transformation matrix (for the object) 104 | QTransform m_transform; 105 | // anchor position of object with respect to the screen 106 | Anchor m_anchor; 107 | // object's rendering settings 108 | GraphicItemGL::VisualOptions m_visualOptions; 109 | 110 | Q_DISABLE_COPY(GraphicItemGL) 111 | }; 112 | 113 | Q_DECLARE_OPERATORS_FOR_FLAGS(GraphicItemGL::VisualOptions) 114 | 115 | #endif // GRAPHICITEMGL_H 116 | -------------------------------------------------------------------------------- /src/viewRenderer/HeatMapLegendGL.cpp: -------------------------------------------------------------------------------- 1 | #include "HeatMapLegendGL.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "math/Common.h" 10 | #include "color/HeatMap.h" 11 | 12 | static const float legend_x = 0.0; 13 | static const float legend_y = 0.0; 14 | static const float legend_width = 30.0; 15 | static const float legend_height = 200.0; 16 | static const float bars_width = 40.0; 17 | 18 | HeatMapLegendGL::HeatMapLegendGL(const SettingsWidget::Rendering &rendering_settings, QObject *parent) 19 | : GraphicItemGL(parent) 20 | , m_image() 21 | , m_rendering_settings(rendering_settings) 22 | , m_initialized(false) 23 | { 24 | setVisualOption(GraphicItemGL::Transformable, false); 25 | setVisualOption(GraphicItemGL::Visible, false); 26 | setVisualOption(GraphicItemGL::Selectable, false); 27 | setVisualOption(GraphicItemGL::Yinverted, false); 28 | setVisualOption(GraphicItemGL::Xinverted, false); 29 | setVisualOption(GraphicItemGL::RubberBandable, false); 30 | setAnchor(Anchor::NorthEast); 31 | } 32 | 33 | HeatMapLegendGL::~HeatMapLegendGL() 34 | { 35 | } 36 | 37 | void HeatMapLegendGL::clearData() 38 | { 39 | m_image = QImage(); 40 | m_initialized = false; 41 | } 42 | 43 | void HeatMapLegendGL::slotUpdate() 44 | { 45 | generateLegend(); 46 | } 47 | 48 | void HeatMapLegendGL::draw(QOpenGLFunctionsVersion &qopengl_functions, QPainter &painter) 49 | { 50 | Q_UNUSED(qopengl_functions) 51 | 52 | if (!m_initialized || m_rendering_settings.visual_mode == SettingsWidget::VisualMode::Normal 53 | || m_rendering_settings.visual_mode == SettingsWidget::VisualMode::DynamicRange) { 54 | return; 55 | } 56 | 57 | // draw the image 58 | painter.drawImage(QPointF(legend_x, legend_y), m_image); 59 | // get the min max values 60 | const double min = m_rendering_settings.legend_min; 61 | const double max = m_rendering_settings.legend_max; 62 | // draw text (add 5 pixels offset to the right) 63 | painter.setBrush(Qt::darkBlue); 64 | painter.drawText(QPointF(legend_x + legend_width + 5, 0), QString::number(max)); 65 | painter.drawText(QPointF(legend_x + legend_width + 5, legend_height), QString::number(min)); 66 | } 67 | 68 | void HeatMapLegendGL::generateLegend() 69 | { 70 | // get the min max values 71 | const float min = m_rendering_settings.legend_min; 72 | const float max = m_rendering_settings.legend_max; 73 | // generate image texture with the size of the legend and then fill it up with the colors 74 | // using the min-max values of the threshold and the color mode 75 | m_image = QImage(legend_width, legend_height, QImage::Format_ARGB32); 76 | Color::ColorGradients cmap = Color::ColorGradients::gpSpectrum; 77 | if (m_rendering_settings.visual_mode == SettingsWidget::VisualMode::ColorRange) { 78 | cmap = Color::ColorGradients::gpHot; 79 | } else if (m_rendering_settings.visual_mode == SettingsWidget::VisualMode::ColorRange2) { 80 | cmap = Color::ColorGradients::gpPolar; 81 | } 82 | Color::createLegend(m_image, min, max, cmap); 83 | m_initialized = true; 84 | } 85 | 86 | const QRectF HeatMapLegendGL::boundingRect() const 87 | { 88 | return QRectF(legend_x, legend_y, legend_width + bars_width, legend_height); 89 | } 90 | 91 | void HeatMapLegendGL::setSelectionArea(const SelectionEvent &event) 92 | { 93 | Q_UNUSED(event) 94 | } 95 | -------------------------------------------------------------------------------- /src/viewRenderer/HeatMapLegendGL.h: -------------------------------------------------------------------------------- 1 | #ifndef HEATMAPLEGEND_H 2 | #define HEATMAPLEGEND_H 3 | 4 | #include 5 | #include "GraphicItemGL.h" 6 | #include "viewPages/SettingsWidget.h" 7 | 8 | class QImage; 9 | 10 | // HeatMapLegend is an visual item that is used to represent the heat map 11 | // spectrum 12 | // in order to give a reference point about the color-value relationship for the 13 | // gene data 14 | // when the user selects heat map mode 15 | class HeatMapLegendGL : public GraphicItemGL 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | 21 | HeatMapLegendGL(const SettingsWidget::Rendering &rendering_settings, QObject *parent = 0); 22 | virtual ~HeatMapLegendGL(); 23 | 24 | // clear up all data 25 | void clearData(); 26 | 27 | public slots: 28 | 29 | // Update the rendering data 30 | void slotUpdate(); 31 | 32 | protected: 33 | const QRectF boundingRect() const override; 34 | void draw(QOpenGLFunctionsVersion &qopengl_functions, QPainter &painter) override; 35 | void setSelectionArea(const SelectionEvent &event); 36 | 37 | private: 38 | 39 | // create the legend 40 | void generateLegend(); 41 | 42 | // legend image 43 | QImage m_image; 44 | // rendering settings 45 | const SettingsWidget::Rendering &m_rendering_settings; 46 | // true when rendering data has been computed 47 | bool m_initialized; 48 | 49 | Q_DISABLE_COPY(HeatMapLegendGL) 50 | }; 51 | 52 | #endif // HEATMAPLEGEND_H // 53 | -------------------------------------------------------------------------------- /src/viewRenderer/ImageTextureGL.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGETEXTUREGL_H 2 | #define IMAGETEXTUREGL_H 3 | 4 | #include "GraphicItemGL.h" 5 | #include 6 | #include 7 | 8 | class QImage; 9 | class QOpenGLTexture; 10 | class QByteArray; 11 | 12 | // This class represents a tiled image to be rendered using textures. This class 13 | // is used to render the cell tissue image which has a high resolution 14 | // The tiling and creation of the textures is performed concurrently 15 | class ImageTextureGL : public GraphicItemGL 16 | { 17 | Q_OBJECT 18 | 19 | public: 20 | explicit ImageTextureGL(QObject *parent = 0); 21 | virtual ~ImageTextureGL(); 22 | 23 | // this function will split the image into small textures of fixed size in an asynchronous way 24 | // using createTiles and returning the future object 25 | QFuture createTextures(const QString &imagefile); 26 | 27 | // will remove and destroy all textures 28 | void clearData(); 29 | 30 | // return the total size of the image as a QRectF 31 | const QRectF boundingRect() const override; 32 | 33 | // will split the image given as input into small textures of fixed size 34 | // returns true if the parsing and creation of tiles was correct 35 | bool createTiles(const QString &imagefile); 36 | 37 | // return a grid of points computed from the image (inside the tissue) 38 | const QList& getGrid() const; 39 | 40 | // true if the image has been scaled down 41 | bool scaled() const; 42 | 43 | public slots: 44 | 45 | protected: 46 | 47 | void draw(QOpenGLFunctionsVersion &qopengl_functions, QPainter &painter) override; 48 | void setSelectionArea(const SelectionEvent &event); 49 | 50 | private: 51 | 52 | // internal function to create a grid of of the image (inside tissue) 53 | void createGrid(const QImage &image, const int offset); 54 | 55 | // internal functions to create a texture from an image and add it to the 56 | // rendering list 57 | void addTexture(const QImage &image, const int x = 0, const int y = 0); 58 | 59 | // internal function to remove and clean textures 60 | void clearTextures(); 61 | void clearNodes(); 62 | 63 | QVector m_textures; 64 | QVector m_textures_indices; 65 | QVector m_texture_coords; 66 | QRectF m_bounds; 67 | bool m_isInitialized; 68 | QList m_grid_points; 69 | bool m_iscaled; 70 | 71 | Q_DISABLE_COPY(ImageTextureGL) 72 | }; 73 | 74 | #endif // IMAGETEXTUREGL_H 75 | -------------------------------------------------------------------------------- /src/viewRenderer/SelectionEvent.h: -------------------------------------------------------------------------------- 1 | #ifndef SELECTIONEVENT_H 2 | #define SELECTIONEVENT_H 3 | 4 | #include 5 | #include 6 | 7 | // Selection event used to propagate selection data to view items. 8 | class SelectionEvent : public QEvent 9 | { 10 | 11 | public: 12 | enum SelectionMode { NewSelection, IncludeSelection, ExcludeSelection }; 13 | 14 | SelectionEvent() 15 | : QEvent(TYPE) 16 | , m_path() 17 | , m_mode(NewSelection) 18 | { 19 | } 20 | 21 | SelectionEvent(const QPainterPath &path, const SelectionMode mode = NewSelection) 22 | : QEvent(TYPE) 23 | , m_path(path) 24 | , m_mode(mode) 25 | { 26 | } 27 | 28 | QPainterPath path() const { return m_path; } 29 | SelectionMode mode() const { return m_mode; } 30 | 31 | static SelectionMode modeFromKeyboardModifiers(Qt::KeyboardModifiers modifiers) 32 | { 33 | return (modifiers.testFlag(Qt::ShiftModifier) 34 | ? (modifiers.testFlag(Qt::ControlModifier) ? SelectionEvent::ExcludeSelection 35 | : SelectionEvent::IncludeSelection) 36 | : SelectionEvent::NewSelection); 37 | } 38 | 39 | private: 40 | static const QEvent::Type TYPE = static_cast(QEvent::User + 42); 41 | 42 | const QPainterPath m_path; 43 | const SelectionMode m_mode; 44 | }; 45 | 46 | #endif // SELECTIONEVENT_H // 47 | -------------------------------------------------------------------------------- /src/viewTables/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(LIBRARY_ARG_INCLUDES 3 | DatasetsTableView.h 4 | GenesTableView.h 5 | SpotsTableView.h 6 | UserSelectionTableView.h 7 | ) 8 | 9 | set(LIBRARY_ARG_SOURCES 10 | DatasetsTableView.cpp 11 | GenesTableView.cpp 12 | SpotsTableView.cpp 13 | UserSelectionTableView.cpp 14 | ) 15 | 16 | ST_LIBRARY() 17 | 18 | -------------------------------------------------------------------------------- /src/viewTables/DatasetsTableView.cpp: -------------------------------------------------------------------------------- 1 | #include "DatasetsTableView.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "model/DatasetItemModel.h" 12 | 13 | DatasetsTableView::DatasetsTableView(QWidget *parent) 14 | : QTableView(parent) 15 | , m_sortDatasetsProxyModel(nullptr) 16 | { 17 | // the data model 18 | DatasetItemModel *data_model = new DatasetItemModel(this); 19 | 20 | // the sorting model 21 | m_sortDatasetsProxyModel.reset(new QSortFilterProxyModel(this)); 22 | m_sortDatasetsProxyModel->setSourceModel(data_model); 23 | m_sortDatasetsProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); 24 | m_sortDatasetsProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); 25 | setModel(m_sortDatasetsProxyModel.data()); 26 | 27 | // settings of the table 28 | setSortingEnabled(true); 29 | setShowGrid(true); 30 | setWordWrap(true); 31 | setAlternatingRowColors(true); 32 | sortByColumn(DatasetItemModel::Name, Qt::AscendingOrder); 33 | setSelectionBehavior(QAbstractItemView::SelectRows); 34 | setEditTriggers(QAbstractItemView::SelectedClicked); 35 | setSelectionMode(QAbstractItemView::MultiSelection); 36 | resizeColumnsToContents(); 37 | resizeRowsToContents(); 38 | 39 | horizontalHeader()->setSortIndicatorShown(true); 40 | horizontalHeader()->setSectionResizeMode(DatasetItemModel::Name, QHeaderView::Stretch); 41 | horizontalHeader()->setSectionResizeMode(DatasetItemModel::Tissue, QHeaderView::Stretch); 42 | horizontalHeader()->setSectionResizeMode(DatasetItemModel::Species, QHeaderView::Stretch); 43 | verticalHeader()->hide(); 44 | 45 | model()->submit(); // support for caching (speed up) 46 | 47 | // allow to copy the dataset name 48 | setContextMenuPolicy(Qt::CustomContextMenu); 49 | connect(this, &DatasetsTableView::customContextMenuRequested, 50 | this, &DatasetsTableView::customMenuRequested); 51 | 52 | } 53 | 54 | DatasetsTableView::~DatasetsTableView() 55 | { 56 | } 57 | 58 | QItemSelection DatasetsTableView::datasetsTableItemSelection() const 59 | { 60 | const auto &selected = selectionModel()->selection(); 61 | return m_sortDatasetsProxyModel->mapSelectionToSource(selected); 62 | } 63 | 64 | void DatasetsTableView::customMenuRequested(const QPoint &pos) 65 | { 66 | const QModelIndex index = indexAt(pos); 67 | if (index.isValid()) { 68 | QMenu *menu = new QMenu(this); 69 | menu->addAction(new QAction(tr("Copy name"), this)); 70 | menu->addAction(new QAction(tr("Open"), this)); 71 | menu->addAction(new QAction(tr("Edit"), this)); 72 | menu->addAction(new QAction(tr("Delete"), this)); 73 | QAction *action = menu->exec(viewport()->mapToGlobal(pos)); 74 | if (action != nullptr) { 75 | const QString action_text = action->text(); 76 | if (action_text == tr("Copy name")) { 77 | const QModelIndex new_index = m_sortDatasetsProxyModel->index(index.row(), DatasetItemModel::Name); 78 | const QString dataset_name = m_sortDatasetsProxyModel->data(new_index, Qt::DisplayRole).toString(); 79 | QClipboard *clipboard = QApplication::clipboard(); 80 | clipboard->setText(dataset_name); 81 | } else if (action_text == tr("Open")) { 82 | emit signalDatasetOpen(index); 83 | } else if (action_text == tr("Edit")) { 84 | emit signalDatasetEdit(index); 85 | } else if (action_text == tr("Delete")) { 86 | emit signalDatasetDelete(index); 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/viewTables/DatasetsTableView.h: -------------------------------------------------------------------------------- 1 | #ifndef DATASETSTABLEVIEW_H 2 | #define DATASETSTABLEVIEW_H 3 | 4 | #include 5 | #include 6 | 7 | class QSortFilterProxyModel; 8 | 9 | // An abstraction of QTableView for the datasets page's table 10 | class DatasetsTableView : public QTableView 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit DatasetsTableView(QWidget *parent = 0); 16 | virtual ~DatasetsTableView(); 17 | 18 | // returns the current selection mapped to the sorting model 19 | QItemSelection datasetsTableItemSelection() const; 20 | 21 | signals: 22 | 23 | void signalDatasetOpen(QModelIndex index); 24 | void signalDatasetEdit(QModelIndex index); 25 | void signalDatasetDelete(QModelIndex index); 26 | 27 | private slots: 28 | 29 | // when the user right clicks 30 | void customMenuRequested(const QPoint &pos); 31 | 32 | private: 33 | // references to proxy model 34 | QScopedPointer m_sortDatasetsProxyModel; 35 | 36 | Q_DISABLE_COPY(DatasetsTableView) 37 | }; 38 | 39 | #endif // DATASETSTABLEVIEW_H // 40 | -------------------------------------------------------------------------------- /src/viewTables/GenesTableView.h: -------------------------------------------------------------------------------- 1 | #ifndef GENESTABLEVIEW_H 2 | #define GENESTABLEVIEW_H 3 | 4 | #include 5 | #include 6 | 7 | class QSortFilterProxyModel; 8 | class GeneItemModel; 9 | 10 | // An abstraction of QTableView for the genes table 11 | class GenesTableView : public QTableView 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | explicit GenesTableView(QWidget *parent = 0); 17 | virtual ~GenesTableView(); 18 | 19 | // returns the current selection mapped to the sorting model 20 | QItemSelection getItemSelection() const; 21 | 22 | // Functions to retrieve the model and the proxy model of the table 23 | QSortFilterProxyModel *getProxyModel(); 24 | GeneItemModel *getModel(); 25 | 26 | signals: 27 | 28 | // signals emitted when the user selects or change colors of genes 29 | void signalGenesUpdated(); 30 | 31 | public slots: 32 | 33 | // slot used to set a search on the table by name 34 | void setNameFilter(const QString &str); 35 | 36 | private slots: 37 | 38 | // slot to handle when the user right clicks 39 | void customMenuRequested(const QPoint &pos); 40 | 41 | private: 42 | 43 | // references to the proxy model 44 | QScopedPointer m_sortProxyModel; 45 | 46 | Q_DISABLE_COPY(GenesTableView) 47 | }; 48 | 49 | #endif // GENESTABLEVIEW_H 50 | -------------------------------------------------------------------------------- /src/viewTables/SpotsTableView.h: -------------------------------------------------------------------------------- 1 | #ifndef SPOTSTABLEVIEW_H 2 | #define SPOTSTABLEVIEW_H 3 | 4 | #include 5 | #include 6 | 7 | class QSortFilterProxyModel; 8 | class SpotItemModel; 9 | 10 | // An abstraction of QTableView for the spots table 11 | class SpotsTableView : public QTableView 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | explicit SpotsTableView(QWidget *parent = 0); 17 | virtual ~SpotsTableView(); 18 | 19 | // returns the current selection mapped to the sorting model 20 | QItemSelection getItemSelection() const; 21 | 22 | // Functions to retrieve the model and the proxy model of the table 23 | QSortFilterProxyModel *getProxyModel(); 24 | SpotItemModel *getModel(); 25 | 26 | signals: 27 | 28 | // signals emitted when the user selects or change colors of spots 29 | void signalSpotsUpdated(); 30 | 31 | public slots: 32 | 33 | // slot used to set a search on the table by name 34 | void setNameFilter(const QString &str); 35 | 36 | private slots: 37 | 38 | // slot to handle when the user right clicks 39 | void customMenuRequested(const QPoint &pos); 40 | 41 | private: 42 | // references to the proxy model 43 | QScopedPointer m_sortProxyModel; 44 | 45 | Q_DISABLE_COPY(SpotsTableView) 46 | 47 | }; 48 | 49 | #endif // SPOTSTABLEVIEW_H 50 | -------------------------------------------------------------------------------- /src/viewTables/UserSelectionTableView.cpp: -------------------------------------------------------------------------------- 1 | #include "UserSelectionTableView.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "model/UserSelectionsItemModel.h" 11 | 12 | UserSelectionTableView::UserSelectionTableView(QWidget *parent) 13 | : QTableView(parent) 14 | , m_sortSelectionsProxyModel(nullptr) 15 | { 16 | // model 17 | UserSelectionsItemModel *data_model = new UserSelectionsItemModel(this); 18 | 19 | // sorting model 20 | m_sortSelectionsProxyModel.reset(new QSortFilterProxyModel(this)); 21 | m_sortSelectionsProxyModel->setSourceModel(data_model); 22 | m_sortSelectionsProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); 23 | m_sortSelectionsProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); 24 | setModel(m_sortSelectionsProxyModel.data()); 25 | 26 | // Configuration of the table 27 | setSortingEnabled(true); 28 | setShowGrid(true); 29 | setWordWrap(true); 30 | setAlternatingRowColors(true); 31 | sortByColumn(UserSelectionsItemModel::Name, Qt::AscendingOrder); 32 | // Selection behavior 33 | setSelectionBehavior(QAbstractItemView::SelectRows); 34 | setEditTriggers(QAbstractItemView::NoEditTriggers); 35 | setSelectionMode(QAbstractItemView::MultiSelection); 36 | // Columns settings 37 | horizontalHeader()->setSectionResizeMode(UserSelectionsItemModel::Name, 38 | QHeaderView::Stretch); 39 | horizontalHeader()->setSectionResizeMode(UserSelectionsItemModel::Dataset, 40 | QHeaderView::Stretch); 41 | horizontalHeader()->setSectionResizeMode(UserSelectionsItemModel::NGenes, 42 | QHeaderView::Stretch); 43 | horizontalHeader()->setSectionResizeMode(UserSelectionsItemModel::NSpots, 44 | QHeaderView::Stretch); 45 | horizontalHeader()->setSortIndicatorShown(true); 46 | verticalHeader()->hide(); 47 | 48 | model()->submit(); // support for caching (speed up) 49 | 50 | // allow to copy the dataset name 51 | setContextMenuPolicy(Qt::CustomContextMenu); 52 | connect(this, &UserSelectionTableView::customContextMenuRequested, 53 | this, &UserSelectionTableView::customMenuRequested); 54 | } 55 | 56 | UserSelectionTableView::~UserSelectionTableView() 57 | { 58 | } 59 | 60 | QItemSelection UserSelectionTableView::userSelecionTableItemSelection() const 61 | { 62 | const auto &selected = selectionModel()->selection(); 63 | return m_sortSelectionsProxyModel->mapSelectionToSource(selected); 64 | } 65 | 66 | void UserSelectionTableView::customMenuRequested(const QPoint &pos) 67 | { 68 | const QModelIndex index = indexAt(pos); 69 | if (index.isValid()) { 70 | QMenu *menu = new QMenu(this); 71 | menu->addAction(new QAction(tr("Copy name"), this)); 72 | menu->addAction(new QAction(tr("Export"), this)); 73 | menu->addAction(new QAction(tr("Edit"), this)); 74 | menu->addAction(new QAction(tr("Delete"), this)); 75 | QAction *action = menu->exec(viewport()->mapToGlobal(pos)); 76 | if (action != nullptr) { 77 | const QString action_text = action->text(); 78 | if (action_text == tr("Copy name")) { 79 | const QModelIndex new_index = m_sortSelectionsProxyModel->index(index.row(), UserSelectionsItemModel::Name); 80 | const QString selection_name = m_sortSelectionsProxyModel->data(new_index, Qt::DisplayRole).toString(); 81 | QClipboard *clipboard = QApplication::clipboard(); 82 | clipboard->setText(selection_name); 83 | } else if (action_text == tr("Export")) { 84 | emit signalSelectionExport(index); 85 | } else if (action_text == tr("Edit")) { 86 | emit signalSelectionEdit(index); 87 | } else if (action_text == tr("Delete")) { 88 | emit signalSelectionDelete(index); 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/viewTables/UserSelectionTableView.h: -------------------------------------------------------------------------------- 1 | #ifndef USERSELECTIONSTABLEVIEW_H 2 | #define USERSELECTIONSTABLEVIEW_H 3 | 4 | #include 5 | #include 6 | 7 | class QSortFilterProxyModel; 8 | 9 | // An abstraction of QTableView for the user selections page's table 10 | class UserSelectionTableView : public QTableView 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | 16 | explicit UserSelectionTableView(QWidget *parent = 0); 17 | virtual ~UserSelectionTableView(); 18 | 19 | // returns the current selection mapped to the sorting model 20 | QItemSelection userSelecionTableItemSelection() const; 21 | 22 | signals: 23 | 24 | void signalSelectionExport(QModelIndex); 25 | void signalSelectionEdit(QModelIndex); 26 | void signalSelectionDelete(QModelIndex); 27 | 28 | private slots: 29 | 30 | // when the user right clicks 31 | void customMenuRequested(const QPoint &pos); 32 | 33 | private: 34 | // references to the proxy model 35 | QScopedPointer m_sortSelectionsProxyModel; 36 | 37 | Q_DISABLE_COPY(UserSelectionTableView) 38 | }; 39 | 40 | #endif // USERSELECTIONSTABLEVIEW_H 41 | -------------------------------------------------------------------------------- /ubuntu_dep_and_compile.sh: -------------------------------------------------------------------------------- 1 | packagelist=( 2 | autoconf 3 | automake 4 | make 5 | g++ 6 | gcc 7 | build-essential 8 | git 9 | ubuntu-dev-tools 10 | libglu1-mesa-dev 11 | freeglut3-dev 12 | mesa-common-dev 13 | wget 14 | libfontconfig1 15 | qt5-default 16 | qtbase5-dev 17 | libqt5charts5-dev 18 | libqt5svg5-dev 19 | libarmadillo-dev 20 | r-base 21 | r-cran-rcpparmadillo 22 | ) 23 | 24 | apt-get update && apt-get install -y ${packagelist[@]} 25 | 26 | 27 | wget https://cmake.org/files/v3.7/cmake-3.7.2.tar.gz && \ 28 | tar -xvzf cmake-3.7.2.tar.gz && \ 29 | cd cmake-3.7.2 && \ 30 | ./configure && \ 31 | make -j4 && \ 32 | make install 33 | 34 | wget http://www.qcustomplot.com/release/1.3.2/QCustomPlot.tar.gz && \ 35 | mkdir /opt/QCustomPlot && tar xf QCustomPlot.tar.gz -C /opt/QCustomPlot 36 | 37 | echo "r <- getOption('repos'); r['CRAN'] <- 'http://cran.us.r-project.org'; options(repos = r);" > ~/.Rprofile 38 | Rscript -e "source('https://bioconductor.org/biocLite.R'); biocLite('DESeq2'); biocLite('scran'); biocLite('Rtsne')" 39 | Rscript -e "install.packages('RInside')" 40 | 41 | mkdir st_viewer_build \ 42 | && cd st_viewer_build\ 43 | && cmake -DCMAKE_BUILD_TYPE="Release" -DCMAKE_PREFIX_PATH="/opt/QCustomPlot/qcustomplot" .. \ 44 | && make -j4 45 | 46 | ln -sv `pwd`/STViewer /usr/local/bin 47 | 48 | --------------------------------------------------------------------------------