From f207c571d82665fa826cae811aa3463a7df24663 Mon Sep 17 00:00:00 2001 From: Jiri Novak Date: Wed, 21 Feb 2018 15:10:29 +0100 Subject: [PATCH] release 1.0.1106 --- CycloBranch/CycloBranch.desktop | 9 + CycloBranch/CycloBranch.pro | 87 ++ CycloBranch/CycloBranch.vcxproj | 334 +++++-- CycloBranch/CycloBranch.vcxproj.filters | 79 +- CycloBranch/CycloBranch.vcxproj.user | 4 +- CycloBranch/core/cAllocator.h | 111 +++ CycloBranch/core/cBrick.cpp | 23 +- CycloBranch/core/cBrick.h | 15 +- CycloBranch/core/cBricksDatabase.cpp | 25 +- CycloBranch/core/cBricksDatabase.h | 11 +- CycloBranch/core/cCandidate.cpp | 252 +++++- CycloBranch/core/cCandidate.h | 112 ++- CycloBranch/core/cDeNovoGraph.cpp | 102 ++- CycloBranch/core/cDeNovoGraph.h | 2 +- CycloBranch/core/cDeNovoGraphNode.cpp | 4 +- CycloBranch/core/cDeNovoGraphNode.h | 8 +- CycloBranch/core/cFragmentIons.cpp | 539 +++++++---- CycloBranch/core/cFragmentIons.h | 203 +++-- CycloBranch/core/cParameters.cpp | 277 ++++-- CycloBranch/core/cParameters.h | 16 +- CycloBranch/core/cPeak.h | 4 +- CycloBranch/core/cPeaksList.cpp | 119 ++- CycloBranch/core/cPeaksList.h | 47 +- CycloBranch/core/cSequence.cpp | 17 +- CycloBranch/core/cSequence.h | 17 +- CycloBranch/core/cSequenceDatabase.cpp | 7 +- CycloBranch/core/cSequenceDatabase.h | 1 + CycloBranch/core/cSummaryFormula.cpp | 4 +- CycloBranch/core/cSummaryFormula.h | 5 +- CycloBranch/core/cTheoreticalSpectrum.cpp | 846 ++++++------------ CycloBranch/core/cTheoreticalSpectrum.h | 135 +-- CycloBranch/core/cTheoreticalSpectrumList.cpp | 50 +- CycloBranch/core/cTheoreticalSpectrumList.h | 6 + CycloBranch/core/utilities.cpp | 177 ++++ CycloBranch/core/utilities.h | 101 +++ CycloBranch/cyclobranch.rc | 1 + CycloBranch/gui/cAboutWidget.cpp | 27 +- CycloBranch/gui/cAboutWidget.h | 10 + CycloBranch/gui/cBranchedWidget.cpp | 465 ++++++---- CycloBranch/gui/cBranchedWidget.h | 24 + CycloBranch/gui/cBricksDatabaseWidget.cpp | 212 +++-- CycloBranch/gui/cBricksDatabaseWidget.h | 27 +- CycloBranch/gui/cCyclicWidget.cpp | 346 +++++-- CycloBranch/gui/cCyclicWidget.h | 32 +- CycloBranch/gui/cDrawPeptideWidget.cpp | 665 ++++++++++++++ CycloBranch/gui/cDrawPeptideWidget.h | 176 ++++ CycloBranch/gui/cEventFilter.cpp | 14 + CycloBranch/gui/cEventFilter.h | 35 + CycloBranch/gui/cGraphWidget.cpp | 12 +- CycloBranch/gui/cGraphWidget.h | 11 + CycloBranch/gui/cLassoWidget.cpp | 332 ++++--- CycloBranch/gui/cLassoWidget.h | 32 +- CycloBranch/gui/cLinearWidget.cpp | 155 +++- CycloBranch/gui/cLinearWidget.h | 26 +- CycloBranch/gui/cMainThread.cpp | 312 ++----- CycloBranch/gui/cMainThread.h | 57 +- CycloBranch/gui/cMainWindow.cpp | 660 +++++++++----- CycloBranch/gui/cMainWindow.h | 51 +- CycloBranch/gui/cModificationsWidget.cpp | 434 +++++++++ CycloBranch/gui/cModificationsWidget.h | 119 +++ CycloBranch/gui/cParametersWidget.cpp | 685 +++++++------- CycloBranch/gui/cParametersWidget.h | 91 +- CycloBranch/gui/cSequenceDatabaseWidget.cpp | 223 +++-- CycloBranch/gui/cSequenceDatabaseWidget.h | 35 +- CycloBranch/gui/cSpectrumDetailWidget.cpp | 598 +++++++++---- CycloBranch/gui/cSpectrumDetailWidget.h | 83 +- CycloBranch/gui/cSpectrumSceneWidget.cpp | 646 +++++++++++++ CycloBranch/gui/cSpectrumSceneWidget.h | 210 +++++ CycloBranch/images.qrc | 32 + CycloBranch/images/cb.cdr | Bin 0 -> 15312 bytes CycloBranch/images/cb.ico | Bin 0 -> 101098 bytes CycloBranch/images/cb.png | Bin 0 -> 2191 bytes CycloBranch/images/icons/2.png | Bin 0 -> 673 bytes CycloBranch/images/icons/20.png | Bin 0 -> 705 bytes CycloBranch/images/icons/22.png | Bin 0 -> 789 bytes CycloBranch/images/icons/26.png | Bin 0 -> 709 bytes CycloBranch/images/icons/3.png | Bin 0 -> 887 bytes CycloBranch/images/icons/32.png | Bin 0 -> 640 bytes CycloBranch/images/icons/33.png | Bin 0 -> 1269 bytes CycloBranch/images/icons/4.png | Bin 0 -> 911 bytes CycloBranch/images/icons/48.png | Bin 0 -> 937 bytes CycloBranch/images/icons/52.png | Bin 0 -> 738 bytes CycloBranch/images/icons/54.png | Bin 0 -> 718 bytes CycloBranch/images/icons/57.png | Bin 0 -> 657 bytes CycloBranch/images/icons/61.png | Bin 0 -> 973 bytes CycloBranch/images/icons/62.png | Bin 0 -> 922 bytes CycloBranch/images/icons/64.png | Bin 0 -> 722 bytes CycloBranch/images/icons/68.png | Bin 0 -> 810 bytes CycloBranch/images/icons/73.png | Bin 0 -> 859 bytes CycloBranch/images/icons/77.png | Bin 0 -> 1269 bytes CycloBranch/images/icons/80.png | Bin 0 -> 614 bytes CycloBranch/images/icons/81.png | Bin 0 -> 788 bytes CycloBranch/images/icons/82.png | Bin 0 -> 883 bytes CycloBranch/images/icons/83.png | Bin 0 -> 917 bytes CycloBranch/images/icons/84.png | Bin 0 -> 984 bytes CycloBranch/images/icons/89.png | Bin 0 -> 814 bytes CycloBranch/images/icons/93.png | Bin 0 -> 980 bytes CycloBranch/images/icons/96.png | Bin 0 -> 1041 bytes CycloBranch/images/splash.cdr | Bin 0 -> 99027 bytes CycloBranch/images/splash.png | Bin 0 -> 52065 bytes CycloBranch/licence.txt | 674 ++++++++++++++ CycloBranch/main.cpp | 29 +- CycloBranch/parallel/cGraphReaderThread.cpp | 45 +- CycloBranch/parallel/cGraphReaderThread.h | 4 +- .../parallel/cSpectrumComparatorThread.cpp | 32 +- .../parallel/cSpectrumComparatorThread.h | 16 +- CycloBranch/readme-linux-compile.txt | 12 + readme.txt | 2 +- 108 files changed, 8313 insertions(+), 3088 deletions(-) create mode 100644 CycloBranch/CycloBranch.desktop create mode 100644 CycloBranch/CycloBranch.pro create mode 100644 CycloBranch/core/cAllocator.h create mode 100644 CycloBranch/cyclobranch.rc create mode 100644 CycloBranch/gui/cDrawPeptideWidget.cpp create mode 100644 CycloBranch/gui/cDrawPeptideWidget.h create mode 100644 CycloBranch/gui/cEventFilter.cpp create mode 100644 CycloBranch/gui/cEventFilter.h create mode 100644 CycloBranch/gui/cModificationsWidget.cpp create mode 100644 CycloBranch/gui/cModificationsWidget.h create mode 100644 CycloBranch/gui/cSpectrumSceneWidget.cpp create mode 100644 CycloBranch/gui/cSpectrumSceneWidget.h create mode 100644 CycloBranch/images.qrc create mode 100644 CycloBranch/images/cb.cdr create mode 100644 CycloBranch/images/cb.ico create mode 100644 CycloBranch/images/cb.png create mode 100644 CycloBranch/images/icons/2.png create mode 100644 CycloBranch/images/icons/20.png create mode 100644 CycloBranch/images/icons/22.png create mode 100644 CycloBranch/images/icons/26.png create mode 100644 CycloBranch/images/icons/3.png create mode 100644 CycloBranch/images/icons/32.png create mode 100644 CycloBranch/images/icons/33.png create mode 100644 CycloBranch/images/icons/4.png create mode 100644 CycloBranch/images/icons/48.png create mode 100644 CycloBranch/images/icons/52.png create mode 100644 CycloBranch/images/icons/54.png create mode 100644 CycloBranch/images/icons/57.png create mode 100644 CycloBranch/images/icons/61.png create mode 100644 CycloBranch/images/icons/62.png create mode 100644 CycloBranch/images/icons/64.png create mode 100644 CycloBranch/images/icons/68.png create mode 100644 CycloBranch/images/icons/73.png create mode 100644 CycloBranch/images/icons/77.png create mode 100644 CycloBranch/images/icons/80.png create mode 100644 CycloBranch/images/icons/81.png create mode 100644 CycloBranch/images/icons/82.png create mode 100644 CycloBranch/images/icons/83.png create mode 100644 CycloBranch/images/icons/84.png create mode 100644 CycloBranch/images/icons/89.png create mode 100644 CycloBranch/images/icons/93.png create mode 100644 CycloBranch/images/icons/96.png create mode 100644 CycloBranch/images/splash.cdr create mode 100644 CycloBranch/images/splash.png create mode 100644 CycloBranch/licence.txt create mode 100644 CycloBranch/readme-linux-compile.txt diff --git a/CycloBranch/CycloBranch.desktop b/CycloBranch/CycloBranch.desktop new file mode 100644 index 0000000..c2b747b --- /dev/null +++ b/CycloBranch/CycloBranch.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Comment=A tool for de novo sequencing of nonribosomal peptides from accurate product ion mass spectra. +Exec=CycloBranch +Icon=/usr/share/cyclobranch/images/cb.png +Name=CycloBranch +NoDisplay=false +StartupNotify=false +Terminal=false +Type=Application diff --git a/CycloBranch/CycloBranch.pro b/CycloBranch/CycloBranch.pro new file mode 100644 index 0000000..6791882 --- /dev/null +++ b/CycloBranch/CycloBranch.pro @@ -0,0 +1,87 @@ +###################################################################### +# Automatically generated by qmake (3.0) Fri Dec 5 03:02:26 2014 +###################################################################### + +TEMPLATE = app +TARGET = CycloBranch +QT += core gui widgets printsupport svg +INCLUDEPATH += . core gui parallel +QMAKE_CXXFLAGS += -std=c++0x -DUNIX -m64 +QMAKE_LIBS += -lboost_regex +OBJECTS_DIR = build/ +MOC_DIR = moc/ + +# Input +RESOURCES = images.qrc +HEADERS += core/cAllocator.h \ + core/cBrick.h \ + core/cBricksDatabase.h \ + core/cCandidate.h \ + core/cCandidateSet.h \ + core/cDeNovoGraph.h \ + core/cDeNovoGraphNode.h \ + core/cFragmentIons.h \ + core/cParameters.h \ + core/cPeak.h \ + core/cPeaksList.h \ + core/cSequence.h \ + core/cSequenceDatabase.h \ + core/cSummaryFormula.h \ + core/cTheoreticalSpectrum.h \ + core/cTheoreticalSpectrumList.h \ + core/utilities.h \ + gui/cAboutWidget.h \ + gui/cBranchedWidget.h \ + gui/cBricksDatabaseWidget.h \ + gui/cCyclicWidget.h \ + gui/cDrawPeptideWidget.h \ + gui/cEventFilter.h \ + gui/cFragmentIonsListWidget.h \ + gui/cGraphWidget.h \ + gui/cLassoWidget.h \ + gui/cLinearWidget.h \ + gui/cMainThread.h \ + gui/cMainWindow.h \ + gui/cModificationsWidget.h \ + gui/cParametersWidget.h \ + gui/cSequenceDatabaseWidget.h \ + gui/cSpectrumDetailWidget.h \ + gui/cSpectrumSceneWidget.h \ + parallel/cGraphReaderThread.h \ + parallel/cSpectrumComparatorThread.h +SOURCES += core/cBrick.cpp \ + core/cBricksDatabase.cpp \ + core/cCandidate.cpp \ + core/cCandidateSet.cpp \ + core/cDeNovoGraph.cpp \ + core/cDeNovoGraphNode.cpp \ + core/cFragmentIons.cpp \ + core/cParameters.cpp \ + core/cPeak.cpp \ + core/cPeaksList.cpp \ + core/cSequence.cpp \ + core/cSequenceDatabase.cpp \ + core/cSummaryFormula.cpp \ + core/cTheoreticalSpectrum.cpp \ + core/cTheoreticalSpectrumList.cpp \ + core/utilities.cpp \ + gui/cAboutWidget.cpp \ + gui/cBranchedWidget.cpp \ + gui/cBricksDatabaseWidget.cpp \ + gui/cCyclicWidget.cpp \ + gui/cDrawPeptideWidget.cpp \ + gui/cEventFilter.cpp \ + gui/cFragmentIonsListWidget.cpp \ + gui/cGraphWidget.cpp \ + gui/cLassoWidget.cpp \ + gui/cLinearWidget.cpp \ + gui/cMainThread.cpp \ + gui/cMainWindow.cpp \ + gui/cModificationsWidget.cpp \ + gui/cParametersWidget.cpp \ + gui/cSequenceDatabaseWidget.cpp \ + gui/cSpectrumDetailWidget.cpp \ + gui/cSpectrumSceneWidget.cpp \ + parallel/cGraphReaderThread.cpp \ + parallel/cSpectrumComparatorThread.cpp \ + main.cpp diff --git a/CycloBranch/CycloBranch.vcxproj b/CycloBranch/CycloBranch.vcxproj index 23c88a4..12d8bf3 100644 --- a/CycloBranch/CycloBranch.vcxproj +++ b/CycloBranch/CycloBranch.vcxproj @@ -74,8 +74,8 @@ - UNICODE;WIN32;WIN64;QT_DLL;QT_CORE_LIB;QT_GUI_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) - .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtWidgets;%(AdditionalIncludeDirectories) + UNICODE;WIN32;WIN64;QT_DLL;QT_CORE_LIB;QT_GUI_LIB;QT_WIDGETS_LIB;QT_PRINTSUPPORT_LIB;QT_SVG_LIB;%(PreprocessorDefinitions) + .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtPrintSupport;$(QTDIR)\include\QtSvg;%(AdditionalIncludeDirectories) Disabled ProgramDatabase MultiThreadedDebugDLL @@ -86,13 +86,13 @@ $(OutDir)\$(ProjectName).exe $(QTDIR)\lib;%(AdditionalLibraryDirectories) true - qtmaind.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;%(AdditionalDependencies) + qtmaind.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5PrintSupportd.lib;Qt5Svgd.lib;%(AdditionalDependencies) - UNICODE;WIN32;WIN64;QT_DLL;QT_CORE_LIB;QT_GUI_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) - .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtWidgets;%(AdditionalIncludeDirectories) + UNICODE;WIN32;WIN64;QT_DLL;QT_CORE_LIB;QT_GUI_LIB;QT_WIDGETS_LIB;QT_PRINTSUPPORT_LIB;QT_SVG_LIB;%(PreprocessorDefinitions) + .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtPrintSupport;$(QTDIR)\include\QtSvg;%(AdditionalIncludeDirectories) Disabled ProgramDatabase MultiThreadedDebugDLL @@ -103,13 +103,13 @@ $(OutDir)\$(ProjectName).exe $(QTDIR)\lib;%(AdditionalLibraryDirectories) true - qtmaind.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;%(AdditionalDependencies) + qtmaind.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5PrintSupportd.lib;Qt5Svgd.lib;%(AdditionalDependencies) - UNICODE;WIN32;WIN64;QT_DLL;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) - .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtWidgets;%(AdditionalIncludeDirectories) + UNICODE;WIN32;WIN64;QT_DLL;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_WIDGETS_LIB;QT_PRINTSUPPORT_LIB;QT_SVG_LIB;%(PreprocessorDefinitions) + .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtPrintSupport;$(QTDIR)\include\QtSvg;%(AdditionalIncludeDirectories) MultiThreadedDLL false @@ -119,13 +119,13 @@ $(OutDir)\$(ProjectName).exe $(QTDIR)\lib;%(AdditionalLibraryDirectories) false - qtmain.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;%(AdditionalDependencies) + qtmain.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5PrintSupport.lib;Qt5Svg.lib;%(AdditionalDependencies) - UNICODE;WIN32;WIN64;QT_DLL;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_WIDGETS_LIB;%(PreprocessorDefinitions) - .\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtWidgets;%(AdditionalIncludeDirectories) + UNICODE;WIN32;WIN64;QT_DLL;QT_NO_DEBUG;NDEBUG;QT_CORE_LIB;QT_GUI_LIB;QT_WIDGETS_LIB;QT_PRINTSUPPORT_LIB;QT_SVG_LIB;%(PreprocessorDefinitions) + .;.\GeneratedFiles;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtPrintSupport;C:\boost_1_57_0\;C:\boost_1_57_0\boost;%(AdditionalIncludeDirectories) ProgramDatabase MultiThreadedDLL true @@ -138,9 +138,9 @@ Windows $(OutDir)\$(ProjectName).exe - $(QTDIR)\lib;%(AdditionalLibraryDirectories) + $(QTDIR)\lib;C:\boost_1_57_0\lib64-msvc-11.0;%(AdditionalLibraryDirectories) true - qtmain.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;%(AdditionalDependencies) + qtmain.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5Svgd.lib;Qt5PrintSupport.lib;libboost_regex-vc110-mt-1_57.lib;%(AdditionalDependencies) true true UseLinkTimeCodeGeneration @@ -179,11 +179,15 @@ true true - + true true - + + true + true + + true true @@ -211,6 +215,10 @@ true true + + true + true + true true @@ -227,6 +235,20 @@ true true + + true + true + + + + + + + + + + + true true @@ -243,11 +265,15 @@ true true - + + true + true + + true true - + true true @@ -275,6 +301,10 @@ true true + + true + true + true true @@ -291,25 +321,33 @@ true true + + true + true + + + - + + + @@ -324,204 +362,283 @@ - + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cSpectrumSceneWidget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cSpectrumSceneWidget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cSpectrumSceneWidget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cSpectrumSceneWidget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cEventFilter.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cEventFilter.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cEventFilter.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cEventFilter.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cDrawPeptideWidget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cDrawPeptideWidget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cDrawPeptideWidget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cDrawPeptideWidget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cModificationsWidget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cModificationsWidget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cModificationsWidget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing cModificationsWidget.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cSequenceDatabaseWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cSequenceDatabaseWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cSequenceDatabaseWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cSequenceDatabaseWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cBricksDatabaseWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cBricksDatabaseWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cBricksDatabaseWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cBricksDatabaseWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cLassoWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cLassoWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cLassoWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cLassoWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cLinearWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cLinearWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cLinearWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cLinearWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cCyclicWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cCyclicWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cCyclicWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cCyclicWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cBranchedWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cBranchedWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cBranchedWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cBranchedWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cFragmentIonsListWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cFragmentIonsListWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cFragmentIonsListWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cFragmentIonsListWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cGraphReaderThread.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cGraphReaderThread.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cGraphReaderThread.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cGraphReaderThread.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" Moc%27ing cSpectrumComparatorThread.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" Moc%27ing cSpectrumComparatorThread.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" Moc%27ing cSpectrumComparatorThread.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" Moc%27ing cSpectrumComparatorThread.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" - $(QTDIR)\bin\moc.exe;%(FullPath) - $(QTDIR)\bin\moc.exe;%(FullPath) - $(QTDIR)\bin\moc.exe;%(FullPath) - $(QTDIR)\bin\moc.exe;%(FullPath) - - + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing cGraphicalSpectrumWidget.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing cGraphicalSpectrumWidget.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing cGraphicalSpectrumWidget.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" $(QTDIR)\bin\moc.exe;%(FullPath) - Moc%27ing cGraphicalSpectrumWidget.h... - .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cSpectrumDetailWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cSpectrumDetailWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cSpectrumDetailWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cSpectrumDetailWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" @@ -553,93 +670,116 @@ $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cMainWindow.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cMainWindow.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cMainWindow.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cMainWindow.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cMainThread.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cMainThread.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cMainThread.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cMainThread.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cParametersWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cParametersWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cParametersWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cParametersWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cGraphWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cGraphWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cGraphWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cGraphWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cAboutWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cAboutWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cAboutWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" $(QTDIR)\bin\moc.exe;%(FullPath) Moc%27ing cAboutWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DWIN64 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -DQT_PRINTSUPPORT_LIB -DQT_SVG_LIB "-I.\GeneratedFiles" "-I." "-I$(QTDIR)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtWidgets" "-IC:\boost_1_57_0" "-IC:\boost_1_57_0\boost" "-I$(QTDIR)\include\QtPrintSupport" "-I$(QTDIR)\include\QtSvg" + + + + + %(FullPath);%(AdditionalInputs) + Rcc%27ing %(Identity)... + .\GeneratedFiles\qrc_%(Filename).cpp;%(Outputs) + "$(QTDIR)\bin\rcc.exe" -name "%(Filename)" -no-compress "%(FullPath)" -o .\GeneratedFiles\qrc_%(Filename).cpp + %(FullPath);%(AdditionalInputs) + Rcc%27ing %(Identity)... + .\GeneratedFiles\qrc_%(Filename).cpp;%(Outputs) + "$(QTDIR)\bin\rcc.exe" -name "%(Filename)" -no-compress "%(FullPath)" -o .\GeneratedFiles\qrc_%(Filename).cpp + %(FullPath);%(AdditionalInputs) + Rcc%27ing %(Identity)... + .\GeneratedFiles\qrc_%(Filename).cpp;%(Outputs) + "$(QTDIR)\bin\rcc.exe" -name "%(Filename)" -no-compress "%(FullPath)" -o .\GeneratedFiles\qrc_%(Filename).cpp + %(FullPath);%(AdditionalInputs) + Rcc%27ing %(Identity)... + .\GeneratedFiles\qrc_%(Filename).cpp;%(Outputs) + "$(QTDIR)\bin\rcc.exe" -name "%(Filename)" -no-compress "%(FullPath)" -o .\GeneratedFiles\qrc_%(Filename).cpp + + + diff --git a/CycloBranch/CycloBranch.vcxproj.filters b/CycloBranch/CycloBranch.vcxproj.filters index a06dc21..f42329c 100644 --- a/CycloBranch/CycloBranch.vcxproj.filters +++ b/CycloBranch/CycloBranch.vcxproj.filters @@ -42,6 +42,9 @@ {ede1a4b0-ffbc-4a56-8e82-02552392966b} + + {3300b581-e947-48ef-9c11-63b4118630d6} + @@ -134,15 +137,6 @@ Generated Files\Release - - Generated Files\Debug - - - Generated Files\Release - - - Source Files\gui - Source Files\core @@ -239,6 +233,45 @@ Generated Files\Release + + Generated Files\Debug + + + Generated Files\Release + + + Source Files\gui + + + Source Files\gui + + + Generated Files\Debug + + + Generated Files\Release + + + Generated Files + + + Generated Files\Debug + + + Generated Files\Release + + + Source Files\gui + + + Source Files\gui + + + Generated Files\Debug + + + Generated Files\Release + @@ -262,9 +295,6 @@ Header Files\gui - - Header Files\gui - Header Files\parallel @@ -292,6 +322,24 @@ Header Files\gui + + Header Files\gui + + + Header Files\gui + + + Resources + + + Header Files\core + + + Header Files\gui + + + Header Files\gui + @@ -336,8 +384,13 @@ Header Files\core - + Header Files\core + + + Resources + + \ No newline at end of file diff --git a/CycloBranch/CycloBranch.vcxproj.user b/CycloBranch/CycloBranch.vcxproj.user index dfe0f79..b65447a 100644 --- a/CycloBranch/CycloBranch.vcxproj.user +++ b/CycloBranch/CycloBranch.vcxproj.user @@ -9,14 +9,14 @@ C:\Qt\5.1.1\msvc2012_64\ - C:\Qt\5.1.1\msvc2012_64 + C:\Qt\Qt5.2.1\5.2.1\msvc2012_64 PATH=$(QTDIR)\bin%3b"$(QTDIR)\bin%3b$(PATH) WindowsLocalDebugger - C:\Qt\5.1.1\msvc2012_64 + C:\Qt\Qt5.2.1\5.2.1\msvc2012_64 PATH=$(QTDIR)\bin%3b%PATH%%3b"$(PATH) WindowsLocalDebugger diff --git a/CycloBranch/core/cAllocator.h b/CycloBranch/core/cAllocator.h new file mode 100644 index 0000000..5fee5b3 --- /dev/null +++ b/CycloBranch/core/cAllocator.h @@ -0,0 +1,111 @@ +/** + \file cAllocator.h + \brief An allocator of objects. +*/ + + +#ifndef _CALLOCATOR_H +#define _CALLOCATOR_H + +#include + +using namespace std; + + +/** + \brief An allocator of objects. +*/ +template +class cAllocator +{ + + vector strips; + int itemsperstrip; + + int currentfreestrip; + int currentfreeitem; + +public: + + + /** + \brief The constructor. + */ + cAllocator(); + + + /** + \brief The destructor. + */ + ~cAllocator(); + + + /** + \brief Remove all allocated items. + */ + void reset(); + + + /** + \brief Get a reference to a new item. + \retval reference to a new item + */ + T* getNewItem(); + +}; + + +template +cAllocator::cAllocator() { + strips.clear(); + itemsperstrip = 500; + currentfreestrip = 0; + currentfreeitem = 0; + + T* newstrip = new T[itemsperstrip]; + strips.push_back(newstrip); +} + + +template +cAllocator::~cAllocator() { + for (int i = 0; i < (int)strips.size(); i++) { + delete [] strips[i]; + } +} + + +template +void cAllocator::reset() { + for (int i = 0; i < (int)strips.size(); i++) { + delete [] strips[i]; + } + + strips.clear(); + itemsperstrip = 500; + currentfreestrip = 0; + currentfreeitem = 0; + + T* newstrip = new T[itemsperstrip]; + strips.push_back(newstrip); +} + + +template +T* cAllocator::getNewItem() { + T* freeitem = &strips[currentfreestrip][currentfreeitem]; + + currentfreeitem++; + if (currentfreeitem == itemsperstrip) { + currentfreestrip++; + currentfreeitem = 0; + T* newstrip = new T[itemsperstrip]; + strips.push_back(newstrip); + } + + return freeitem; +} + + +#endif + diff --git a/CycloBranch/core/cBrick.cpp b/CycloBranch/core/cBrick.cpp index 4b6c764..3737504 100644 --- a/CycloBranch/core/cBrick.cpp +++ b/CycloBranch/core/cBrick.cpp @@ -1,7 +1,7 @@ #include "core/cBrick.h" -int getNumberOfBricks(string& composition) { +int getNumberOfBricks(const string& composition) { if (composition.size() == 0) { return 0; } @@ -64,7 +64,7 @@ string& cBrick::getName() { } -void cBrick::setName(string& name) { +void cBrick::setName(const string& name) { this->name = name; } @@ -103,7 +103,7 @@ string cBrick::getReverseComposition() { } -double cBrick::getMass() { +double cBrick::getMass() const { return mass; } @@ -113,7 +113,7 @@ void cBrick::setMass(double mass) { } -void cBrick::setComposition(string& composition, bool normalize) { +void cBrick::setComposition(const string& composition, bool normalize) { this->composition = composition; if (normalize) { normalizeComposition(); @@ -121,12 +121,12 @@ void cBrick::setComposition(string& composition, bool normalize) { } -void cBrick::setSummary(string& summary) { +void cBrick::setSummary(const string& summary) { this->summary = summary; } -void cBrick::setAcronyms(string& acronyms) { +void cBrick::setAcronyms(const string& acronyms) { this->acronyms.clear(); string s = ""; int i = 0; @@ -148,7 +148,7 @@ void cBrick::setAcronyms(string& acronyms) { } -void cBrick::setReferences(string& references) { +void cBrick::setReferences(const string& references) { this->references.clear(); string s = ""; int i = 0; @@ -194,7 +194,7 @@ void cBrick::explodeToIntComposition(vector& bricks) { int item; int first = 0; int last = (int)composition.find('-'); - while (last != string::npos) { + while (last != (int)string::npos) { item = atoi(composition.substr(first, last - first).c_str()); bricks.push_back(item); first = last+1; @@ -214,7 +214,7 @@ void cBrick::explodeToStringComposition(vector& bricks) { string item; int first = 0; int last = (int)composition.find('-'); - while (last != string::npos) { + while (last != (int)string::npos) { item = composition.substr(first, last - first); bricks.push_back(item); first = last+1; @@ -259,7 +259,7 @@ string cBrick::getFirstAcronymAsString() { string cBrick::getAcronymsWithReferencesAsHTMLString() { if (acronyms.size() != references.size()) { - return ""; + return getAcronymsAsString(); } string s = ""; @@ -339,8 +339,7 @@ string cBrick::getAcronymsWithReferencesAsHTMLString() { } } - catch (std::regex_error& e) { - e; + catch (regex_error& /*e*/) { // nothing to do } diff --git a/CycloBranch/core/cBrick.h b/CycloBranch/core/cBrick.h index fcbfd9d..5a717be 100644 --- a/CycloBranch/core/cBrick.h +++ b/CycloBranch/core/cBrick.h @@ -12,7 +12,6 @@ #include #include #include -#include #include "core/utilities.h" using namespace std; @@ -23,7 +22,7 @@ using namespace std; \param composition string containing ids of bricks separated by '-' \retval number number of bricks */ -int getNumberOfBricks(string& composition); +int getNumberOfBricks(const string& composition); /** @@ -78,7 +77,7 @@ class cBrick { \brief Set a full name of the brick. \param name reference to a string */ - void setName(string& name); + void setName(const string& name); /** @@ -120,7 +119,7 @@ class cBrick { \brief Get the mass of the brick. \retval double mass */ - double getMass(); + double getMass() const; /** @@ -135,28 +134,28 @@ class cBrick { \param composition reference to a string with composition (ids of bricks separated by '-') \param normalize if true then ids of bricks are sorted in ascending order */ - void setComposition(string& composition, bool normalize); + void setComposition(const string& composition, bool normalize); /** \brief Set the summary molecular formula of the brick. \param summary reference to a string */ - void setSummary(string& summary); + void setSummary(const string& summary); /** \brief Set acronyms of all izomers corresponding to the brick. \param acronyms reference to a string where the acronyms are separated by '/' */ - void setAcronyms(string& acronyms); + void setAcronyms(const string& acronyms); /** \brief Set references (e.g., to ChemSpider) of all izomers corresponding to the brick. \param references reference to a string where references to izomers are separated by '/' */ - void setReferences(string& references); + void setReferences(const string& references); /** diff --git a/CycloBranch/core/cBricksDatabase.cpp b/CycloBranch/core/cBricksDatabase.cpp index 6702b0d..810fde9 100644 --- a/CycloBranch/core/cBricksDatabase.cpp +++ b/CycloBranch/core/cBricksDatabase.cpp @@ -4,7 +4,7 @@ #include "gui/cMainThread.h" -bool compareBrickMasses(cBrick& a, cBrick& b) { +bool compareBrickMasses(const cBrick& a, const cBrick& b) { return (a.getMass() < b.getMass()); } @@ -109,7 +109,7 @@ cBricksDatabase::cBricksDatabase() { } -int cBricksDatabase::loadFromPlainTextStream(ifstream &stream, string& errormessage) { +int cBricksDatabase::loadFromPlainTextStream(ifstream &stream, string& errormessage, bool ignoreerrors) { string s; cBrick b; size_t pos; @@ -178,10 +178,15 @@ int cBricksDatabase::loadFromPlainTextStream(ifstream &stream, string& errormess } // load references + #if OS_TYPE == UNX + if ((s.size() > 0) && (s.back() == '\r')) { + s = s.substr(0, s.size() - 1); + } + #endif b.setReferences(s); // store brick - if (!b.empty()) { + if (ignoreerrors || (!ignoreerrors && !b.empty())) { // calculate mass from the summary formula.clear(); @@ -190,11 +195,13 @@ int cBricksDatabase::loadFromPlainTextStream(ifstream &stream, string& errormess b.setMass(formula.getMass()); } else { - error = true; - break; + if (!ignoreerrors) { + error = true; + break; + } } - if (b.getMass() == 0) { + if (!ignoreerrors && (b.getMass() == 0)) { error = true; errormessage = "Invalid brick no. " + to_string(size() + 1) + ".\n\n"; break; @@ -204,7 +211,7 @@ int cBricksDatabase::loadFromPlainTextStream(ifstream &stream, string& errormess } } - if (error) { + if (!ignoreerrors && error) { return -1; } @@ -213,7 +220,7 @@ int cBricksDatabase::loadFromPlainTextStream(ifstream &stream, string& errormess void cBricksDatabase::storeToPlainTextStream(ofstream &stream) { - for (int i = 0; i < bricks.size(); i++) { + for (int i = 0; i < (int)bricks.size(); i++) { stream << bricks[i].getName() << "\t"; stream << bricks[i].getAcronymsAsString() << "\t"; stream << bricks[i].getSummary() << "\t"; @@ -322,7 +329,7 @@ string cBricksDatabase::getTagName(string& composition) { } -string cBricksDatabase::getAcronymNameOfTPeptide(string& tcomposition, bool useHTMLReferences) { +string cBricksDatabase::getAcronymNameOfTPeptide(const string& tcomposition, bool useHTMLReferences) { string comp = tcomposition; int leftbracket = getNumberOfBricks(comp.substr(0, comp.find('('))); diff --git a/CycloBranch/core/cBricksDatabase.h b/CycloBranch/core/cBricksDatabase.h index a9fd148..c2a50de 100644 --- a/CycloBranch/core/cBricksDatabase.h +++ b/CycloBranch/core/cBricksDatabase.h @@ -14,7 +14,7 @@ #include #include - +#include "core/utilities.h" #include "core/cBrick.h" #include "core/cSummaryFormula.h" @@ -31,7 +31,7 @@ class cMainThread; \param b second brick \retval bool true if the mass of \a a is less than the mass of \a b */ -bool compareBrickMasses(cBrick& a, cBrick& b); +bool compareBrickMasses(const cBrick& a, const cBrick& b); /** @@ -90,9 +90,10 @@ class cBricksDatabase { \brief Load the database of bricks from a plain text stream. \param stream reference to an input file stream \param errormessage reference to a string where an error message might be stored + \param ignoreerrors if true errors are ignored \retval int 0 when the database was successfully loaded, -1 when an error occurred (\a errormessage is filled up) */ - int loadFromPlainTextStream(ifstream &stream, string& errormessage); + int loadFromPlainTextStream(ifstream &stream, string& errormessage, bool ignoreerrors); /** @@ -169,7 +170,7 @@ class cBricksDatabase { \param useHTMLReferences if true then each acronym is converted to a link to its reference (e.g., in ChemSpider) \retval string name of the peptide */ - string getAcronymNameOfTPeptide(string& tcomposition, bool useHTMLReferences); + string getAcronymNameOfTPeptide(const string& tcomposition, bool useHTMLReferences); /** @@ -224,4 +225,4 @@ class cBricksDatabase { }; -#endif \ No newline at end of file +#endif diff --git a/CycloBranch/core/cCandidate.cpp b/CycloBranch/core/cCandidate.cpp index 80b391f..b7cdb27 100644 --- a/CycloBranch/core/cCandidate.cpp +++ b/CycloBranch/core/cCandidate.cpp @@ -1,6 +1,7 @@ #include "core/cCandidate.h" #include "core/cCandidateSet.h" +#include "core/cDeNovoGraph.h" void cCandidate::updateInternalComposition() { @@ -96,7 +97,7 @@ void cCandidate::attachAllBranches(cCandidate& candidate, cCandidateSet& result, } -void cCandidate::getPartialRotations(string& composition, vector& rotations) { +void cCandidate::getPartialRotations(const string& composition, vector& rotations) { cBrick b; string s; vector bricks; @@ -134,7 +135,7 @@ void cCandidate::getPartialRotations(string& composition, vector& rotati } -void cCandidate::getPartialLassoRotations(string& composition, vector& lassorotations, int branchstart, int branchend) { +void cCandidate::getPartialLassoRotations(const string& composition, vector& lassorotations, int branchstart, int branchend) { cBrick b; string s; bool leftbracketput; @@ -188,16 +189,20 @@ cCandidate::cCandidate() { cCandidate::cCandidate(vector& composition, vector& path, int startmodifID, int endmodifID, int middlemodifID, int middlepos) { + clear(); setCandidate(composition, path, startmodifID, endmodifID, middlemodifID, middlepos); } cCandidate::cCandidate(vector& composition, vector& path, int startmodifID, int endmodifID, int middlemodifID, int branchstart, int branchend) { + clear(); setCandidate(composition, path, startmodifID, endmodifID, middlemodifID, branchstart, branchend); } void cCandidate::setCandidate(vector& composition, vector& path, int startmodifID, int endmodifID, int middlemodifID, int middlepos) { + clear(); + this->composition = composition; updateInternalComposition(); @@ -222,6 +227,8 @@ void cCandidate::setCandidate(vector& composition, vector& pat void cCandidate::setCandidate(vector& composition, vector& path, int startmodifID, int endmodifID, int middlemodifID, int branchstart, int branchend) { + clear(); + this->composition = composition; updateInternalComposition(); @@ -245,6 +252,13 @@ void cCandidate::clear() { branchend = -1; path.clear(); name = ""; + + realpeptidename = ""; + acronympeptidename = ""; + acronyms.clear(); + backboneacronyms.clear(); + branchacronyms.clear(); + stringpath = ""; } @@ -284,22 +298,53 @@ void cCandidate::revertComposition() { } -void cCandidate::prepareBranchedCandidate(cCandidateSet& result, peptideType peptidetype, bool* terminatecomputation) { +void cCandidate::prepareBranchedCandidates(cCandidateSet& result, peptideType peptidetype, bool* terminatecomputation) { cCandidate c; result.getSet().clear(); - // branching is unknown - if ((branchstart == -1) && (branchend == -1)) { - attachAllBranches(*this, result, peptidetype, terminatecomputation); - } - // branching is determined by a modification of the T-branch - else { - attachSubBranchCandidates(*this, result, peptidetype, terminatecomputation); + if (peptidetype == lasso) { + + // just one from startmodifid and middlemodifid may be > 0 (checked in getCandidatesIter) + // endmodifid is always 0 because precursor_ion is not used in initializeFragmentIonsForDeNovoGraphOfLassoPeptides + // startmodifid is always N-terminal because only b-ions are used in the de novo graph + + if ((startmodifID > 0) && (composition.size() > 0)) { + middlemodifID = startmodifID; + startmodifID = 0; + branchstart = 0; + + cBrick b; + vector intvector; + b.setComposition(composition[0], false); + b.explodeToIntComposition(intvector); + branchend = (int)intvector.size() - 1; + } + + // branch-cyclic series types D,H + if ((branchstart == -1) || (branchstart == 0)) { + for (int i = 1; i < numberofinternalbricks - 1; i++) { + c = *this; + c.branchstart = 0; + c.branchend = i; + result.getSet().insert(c); + } + } + + // branch-cyclic series types B,C,F,G + if ((branchend == -1) || (branchend == numberofinternalbricks - 1)) { + for (int i = 1; i < numberofinternalbricks - 1; i++) { + c = *this; + c.branchstart = i; + c.branchend = numberofinternalbricks - 1; + result.getSet().insert(c); + } + } + } if (peptidetype == branched) { - // below, middlemodifID is always > 0 because branchstart == 0 (or branchend == 0) + // below, middlemodifID is always > 0 because branchstart == 0 (or branchend == numberofinternalbricks - 1) // startmodifID and middlemodifID collide on the first detected combination of bricks if (branchstart == 0) { @@ -339,6 +384,15 @@ void cCandidate::prepareBranchedCandidate(cCandidateSet& result, peptideType pep } + // branching is unknown + if ((branchstart == -1) && (branchend == -1)) { + attachAllBranches(*this, result, peptidetype, terminatecomputation); + } + // branching is determined by a modification of the T-branch + else { + attachSubBranchCandidates(*this, result, peptidetype, terminatecomputation); + } + } @@ -710,7 +764,7 @@ double cCandidate::getPrecursorMass(cBricksDatabase& brickdatabasewithcombinatio mass += brickdatabasewithcombinations[bricks[i] - 1].getMass(); } - return mass; + return (parameters->precursorcharge > 0)?mass:mass-2*Hplus; } @@ -948,6 +1002,13 @@ void cCandidate::store(ofstream& os) { storeString(internalcomposition, os); os.write((char *)&numberofinternalbricks, sizeof(int)); + + storeString(realpeptidename, os); + storeString(acronympeptidename, os); + storeStringVector(acronyms, os); + storeStringVector(backboneacronyms, os); + storeStringVector(branchacronyms, os); + storeString(stringpath, os); } @@ -971,6 +1032,13 @@ void cCandidate::load(ifstream& is) { loadString(internalcomposition, is); is.read((char *)&numberofinternalbricks, sizeof(int)); + + loadString(realpeptidename, is); + loadString(acronympeptidename, is); + loadStringVector(acronyms, is); + loadStringVector(backboneacronyms, is); + loadStringVector(branchacronyms, is); + loadString(stringpath, is); } @@ -984,6 +1052,166 @@ string& cCandidate::getName() { } +void cCandidate::setAcronyms(cBricksDatabase& bricksdatabase) { + vector bricks; + cBrick b; + b.clear(); + b.setComposition(internalcomposition, false); + b.explodeToIntComposition(bricks); + + acronyms.clear(); + for (int i = 0; i < (int)bricks.size(); i++) { + acronyms.push_back(bricksdatabase[bricks[i] - 1].getAcronymsAsString()); + } +} + + +void cCandidate::setBackboneAcronyms(cBricksDatabase& bricksdatabase) { + vector bricks; + cBrick b; + b.clear(); + b.setComposition(internalcomposition, false); + b.explodeToIntComposition(bricks); + + backboneacronyms.clear(); + for (int i = 0; i < (int)bricks.size(); i++) { + if ((branchstart >= 0) && (branchend >= 0) && ((i <= branchstart) || (i > branchend))) { + backboneacronyms.push_back(bricksdatabase[bricks[i] - 1].getAcronymsAsString()); + } + } +} + + +void cCandidate::setBranchAcronyms(cBricksDatabase& bricksdatabase) { + vector bricks; + cBrick b; + b.clear(); + b.setComposition(internalcomposition, false); + b.explodeToIntComposition(bricks); + + branchacronyms.clear(); + for (int i = 0; i < (int)bricks.size(); i++) { + if ((branchstart >= 0) && (branchend >= 0) && (i > branchstart) && (i <= branchend)) { + branchacronyms.push_back(bricksdatabase[bricks[i] - 1].getAcronymsAsString()); + } + } +} + + +vector& cCandidate::getAcronyms() { + return acronyms; +} + + +vector& cCandidate::getBackboneAcronyms() { + return backboneacronyms; +} + + +vector& cCandidate::getBranchAcronyms() { + return branchacronyms; +} + + +void cCandidate::setPath(cDeNovoGraph& graph, cParameters* parameters) { + cDeNovoGraphNode* currentnode; + cDeNovoGraphNode* targetnode; + cEdge* currentedge; + stringpath = ""; + for (int i = 0; i < (int)path.size(); i++) { + currentnode = &graph[path[i].nodeid]; + currentedge = &((*currentnode)[path[i].edgeid]); + targetnode = &graph[currentedge->targetnode]; + + stringpath += to_string(currentnode->getMZRatio()); + stringpath += " -> "; + stringpath += to_string(targetnode->getMZRatio()); + stringpath += " using brick(s): "; + if (currentedge->composition.compare("0") == 0) { + stringpath += "none"; + } + else { + stringpath += graph.getBrickDatabaseWithCombinations()->getAcronymName(currentedge->composition, true); + } + + stringpath += " (mass difference: " + to_string(currentedge->massdifference) + ", "; + stringpath += "source intensity: " + to_string(currentnode->getIntensity()) + ", "; + stringpath += "target intensity: " + to_string(targetnode->getIntensity()) + ", "; + stringpath += "ppm error: " + to_string(currentedge->ppmerror) + ", "; + stringpath += "source charge: " + to_string(currentedge->sourcecharge) + ", "; + stringpath += "target charge: " + to_string(currentedge->targetcharge); + if ((parameters->peptidetype == branched) || (parameters->peptidetype == lasso)) { + if (currentedge->middlemodifID > 0) { + stringpath += ", branch modification: " + parameters->searchedmodifications[currentedge->middlemodifID].name; + } + } + if (currentedge->endmodifID > 0) { + stringpath += ", terminal modification: " + parameters->searchedmodifications[currentedge->endmodifID].name; + } + //path += currentedge->printSourceAnnotation(fragmentdefinitions); + //path += "->"; + //path += currentedge->printTargetAnnotation(fragmentdefinitions); + stringpath += ")
"; + } +} + + +string& cCandidate::getPathAsString() { + return stringpath; +} + + +void cCandidate::setRealPeptideName(cBricksDatabase& bricksdatabase, peptideType peptidetype) { + switch (peptidetype) + { + case linear: + case cyclic: + case linearpolysaccharide: + realpeptidename = bricksdatabase.getRealName(internalcomposition); + break; + case branched: + case lasso: + realpeptidename = getRealNameTComposition(bricksdatabase); + break; + case other: + default: + realpeptidename = ""; + break; + } +} + + +void cCandidate::setAcronymPeptideNameWithHTMLReferences(cBricksDatabase& bricksdatabase, peptideType peptidetype) { + switch (peptidetype) + { + case linear: + case cyclic: + case linearpolysaccharide: + acronympeptidename = bricksdatabase.getAcronymName(internalcomposition, true); + break; + case branched: + case lasso: + acronympeptidename = getAcronymsTComposition(bricksdatabase); + break; + case other: + default: + acronympeptidename = ""; + break; + } +} + + +string& cCandidate::getRealPeptideName() { + return realpeptidename; +} + + +string& cCandidate::getAcronymPeptideNameWithHTMLReferences() { + return acronympeptidename; +} + + bool operator == (cCandidate const& a, cCandidate const& b) { return ((cCandidate &)a).isEqualTo((cCandidate &)b); } + diff --git a/CycloBranch/core/cCandidate.h b/CycloBranch/core/cCandidate.h index 110a3f8..145b90b 100644 --- a/CycloBranch/core/cCandidate.h +++ b/CycloBranch/core/cCandidate.h @@ -17,9 +17,11 @@ #include "core/cSummaryFormula.h" class cCandidateSet; +class cDeNovoGraph; using namespace std; +using namespace boost; /** @@ -140,6 +142,13 @@ class cCandidate { string internalcomposition; int numberofinternalbricks; + string realpeptidename; + string acronympeptidename; + vector acronyms; + vector backboneacronyms; + vector branchacronyms; + string stringpath; + void updateInternalComposition(); void getPermutationsIter(cCandidateSet& permutations, vector& currentcandidate, int position, bool* terminatecomputation); @@ -148,9 +157,9 @@ class cCandidate { void attachAllBranches(cCandidate& candidate, cCandidateSet& result, peptideType peptidetype, bool* terminatecomputation); - void getPartialRotations(string& composition, vector& rotations); + void getPartialRotations(const string& composition, vector& rotations); - void getPartialLassoRotations(string& composition, vector& lassorotations, int branchstart, int branchend); + void getPartialLassoRotations(const string& composition, vector& lassorotations, int branchstart, int branchend); public: @@ -230,12 +239,12 @@ class cCandidate { /** - \brief Prepare candidates of a branched or a lasso peptide. + \brief Prepare candidates of a branched or a branch-cyclic peptide. \param result reference to an output set of possible peptide sequence candidates \param peptidetype a type of an analyzed peptide \param terminatecomputation pointer to a variable determining that the computation must be stopped */ - void prepareBranchedCandidate(cCandidateSet& result, peptideType peptidetype, bool* terminatecomputation); + void prepareBranchedCandidates(cCandidateSet& result, peptideType peptidetype, bool* terminatecomputation); /** @@ -404,9 +413,9 @@ class cCandidate { /** - \brief Get lasso rotations of a lasso peptide sequence. - \param lassorotations reference to an output vector containing lasso rotations of a sequence - \param includerevertedrotations if true then reverted lasso rotations are also included + \brief Get branch-cyclic rotations of a branch-cyclic peptide sequence. + \param lassorotations reference to an output vector containing branch-cyclic rotations of a sequence + \param includerevertedrotations if true then reverted branch-cyclic rotations are also included */ void getLassoRotations(vector& lassorotations, bool includerevertedrotations); @@ -447,6 +456,93 @@ class cCandidate { */ string& getName(); + + /** + \brief Set a vector of acronyms corresponding to a peptide sequence candidate. + \param bricksdatabase a database of building blocks + */ + void setAcronyms(cBricksDatabase& bricksdatabase); + + + /** + \brief Set a vector of acronyms corresponding to a backbone of a peptide sequence candidate. + \param bricksdatabase a database of building blocks + */ + void setBackboneAcronyms(cBricksDatabase& bricksdatabase); + + + /** + \brief Set a vector of acronyms corresponding to a branch of a peptide sequence candidate. + \param bricksdatabase a database of building blocks + */ + void setBranchAcronyms(cBricksDatabase& bricksdatabase); + + + /** + \brief Get a vector of acronyms corresponding to a peptide sequence candidate. + \retval vector a vector of acronyms + */ + vector& getAcronyms(); + + + /** + \brief Get a vector of acronyms corresponding to a backbone of a peptide sequence candidate. + \retval vector a vector of acronyms + */ + vector& getBackboneAcronyms(); + + + /** + \brief Get a vector of acronyms corresponding to a branch of a peptide sequence candidate. + \retval vector a vector of acronyms + */ + vector& getBranchAcronyms(); + + + /** + \brief Set a path in the de novo graph corresponding to the candidate. + \param graph reference to the de novo graph + \param parameters parameters of the application + */ + void setPath(cDeNovoGraph& graph, cParameters* parameters); + + + /** + \brief Get a path in the de novo graph corresponding to the candidate as a string. + \retval string reference to a path corresponding to the spectrum + */ + string& getPathAsString(); + + + /** + \brief Set a real peptide name. + \param bricksdatabase the database of building blocks + \param peptidetype the type of peptide + */ + void setRealPeptideName(cBricksDatabase& bricksdatabase, peptideType peptidetype); + + + /** + \brief Set an acronym peptide name. + \param bricksdatabase the database of building blocks + \param peptidetype the type of peptide + */ + void setAcronymPeptideNameWithHTMLReferences(cBricksDatabase& bricksdatabase, peptideType peptidetype); + + + /** + \brief Get a real peptide name. + \retval string reference to the real peptide name + */ + string& getRealPeptideName(); + + + /** + \brief Get an acronym peptide name. + \retval string reference to the acronym peptide name + */ + string& getAcronymPeptideNameWithHTMLReferences(); + }; @@ -461,7 +557,7 @@ struct hash_cCandidate { \retval size_t hashed candidate */ size_t operator()(const cCandidate& candidate) const { - return hash()(((cCandidate&)candidate).getComposition()); + return std::hash()(((cCandidate&)candidate).getComposition()); } }; diff --git a/CycloBranch/core/cDeNovoGraph.cpp b/CycloBranch/core/cDeNovoGraph.cpp index c9c1039..9c9c1e8 100644 --- a/CycloBranch/core/cDeNovoGraph.cpp +++ b/CycloBranch/core/cDeNovoGraph.cpp @@ -22,11 +22,12 @@ cDeNovoGraph::cDeNovoGraph() { } -bool cDeNovoGraph::findPath(int sourcenodeid, int edgeid, int targetnodeid, string& composition, string brickspath, int maximumbricksincombination, vector& path) { +bool cDeNovoGraph::findPath(int sourcenodeid, int edgeid, int targetnodeid, string& composition, string brickspath, int maximumbricksincombination, vector& path) { string localbrickpath; bool found; bool badpath; int count = getNumberOfBricks(brickspath); + nodeEdge ne; if ((path.size() > 1) && (sourcenodeid == targetnodeid)) { cBrick b; @@ -42,9 +43,15 @@ bool cDeNovoGraph::findPath(int sourcenodeid, int edgeid, int targetnodeid, stri if ((i == edgeid) && (path.size() == 0)) { continue; } + + // target charge of an edge must be equal to the source charge of a following edge + if ((path.size() > 0) && (graph[sourcenodeid][i].sourcecharge != graph[path.back().nodeid][path.back().edgeid].targetcharge)) { + continue; + } + badpath = false; for (int j = 0; j < (int)path.size(); j++) { - if (path[j] == sourcenodeid) { + if (path[j].nodeid == sourcenodeid) { badpath = true; break; } @@ -52,14 +59,21 @@ bool cDeNovoGraph::findPath(int sourcenodeid, int edgeid, int targetnodeid, stri if (badpath) { continue; } + localbrickpath = brickspath; if (localbrickpath.size() > 0) { localbrickpath += '-'; } localbrickpath += graph[sourcenodeid][i].composition; - path.push_back(sourcenodeid); + + ne.nodeid = sourcenodeid; + ne.edgeid = i; + path.push_back(ne); + found = findPath(graph[sourcenodeid][i].targetnode, i, targetnodeid, composition, localbrickpath, maximumbricksincombination, path); + path.pop_back(); + if (found) { //*os << graph[sourcenodeid].getMZRatio() << " "; return true; @@ -118,14 +132,14 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { double termmass; int left, right, middle; cEdge e, e1, e2; - double unchargedprecursormass = uncharge(parameters->precursormass, parameters->precursorcharge); + double unchargedprecursormass = charge(uncharge(parameters->precursormass, parameters->precursorcharge), (parameters->precursorcharge > 0)?1:-1); double unchargedmz; int i; sortedpeaklist = parameters->peaklist; // insert the single charged precursor, if neccessary sortedpeaklist.sortbyMass(); - sortedpeaklist.cropMaximumMZRatio(unchargedprecursormass); + sortedpeaklist.cropMaximumMZRatio(unchargedprecursormass, parameters->precursormasserrortolerance); if ((sortedpeaklist.size() > 0) && (!isInPpmMassErrorTolerance(sortedpeaklist[sortedpeaklist.size() - 1].mzratio, unchargedprecursormass, parameters->precursormasserrortolerance))) { cPeak p; p.mzratio = unchargedprecursormass; @@ -146,12 +160,14 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { sortedpeaklist.removeNeutralLoss(- NH3, parameters->precursorcharge, parameters->fragmentmasserrortolerance); *os << "Number of nodes when deamidated ions are removed: " << sortedpeaklist.size() << endl; + double negativeshift = (parameters->precursorcharge > 0)?0:-2*Hplus; + // insert system nodes switch (parameters->peptidetype) { case cyclic: node.clear(); - node.setMZRatio(parameters->fragmentdefinitions[b_ion].massdifference); + node.setMZRatio(parameters->fragmentdefinitions[b_ion].massdifference + negativeshift); node.setIntensity(0); node.addIonAnnotation(b_ion); graph.push_back(node); @@ -166,13 +182,13 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { graph.push_back(node); node.clear(); - node.setMZRatio(parameters->fragmentdefinitions[b_ion].massdifference); + node.setMZRatio(parameters->fragmentdefinitions[b_ion].massdifference + negativeshift); node.setIntensity(0); node.addIonAnnotation(b_ion); graph.push_back(node); node.clear(); - node.setMZRatio(parameters->fragmentdefinitions[y_ion].massdifference); + node.setMZRatio(parameters->fragmentdefinitions[y_ion].massdifference + negativeshift); node.setIntensity(0); node.addIonAnnotation(y_ion); graph.push_back(node); @@ -195,13 +211,13 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { e.targetnode = i + 2; if (parameters->searchedmodifications[i].nterminal) { - node.setMZRatio(parameters->fragmentdefinitions[b_ion].massdifference + parameters->searchedmodifications[i].massdifference); + node.setMZRatio(parameters->fragmentdefinitions[b_ion].massdifference + parameters->searchedmodifications[i].massdifference + negativeshift); node.setIntensity(0); node.addIonAnnotation(b_ion); } if (parameters->searchedmodifications[i].cterminal) { - node.setMZRatio(parameters->fragmentdefinitions[y_ion].massdifference + parameters->searchedmodifications[i].massdifference); + node.setMZRatio(parameters->fragmentdefinitions[y_ion].massdifference + parameters->searchedmodifications[i].massdifference + negativeshift); node.setIntensity(0); node.addIonAnnotation(y_ion); } @@ -226,13 +242,13 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { graph.push_back(node); node.clear(); - node.setMZRatio(parameters->fragmentdefinitions[b_ion].massdifference); + node.setMZRatio(parameters->fragmentdefinitions[b_ion].massdifference + negativeshift); node.setIntensity(0); node.addIonAnnotation(b_ion); graph.push_back(node); //node.clear(); - //node.setMZRatio(parameters->fragmentdefinitions[y_ion].massdifference); + //node.setMZRatio(parameters->fragmentdefinitions[y_ion].massdifference + negativeshift); //node.setIntensity(0); //node.addIonAnnotation(y_ion); //graph.push_back(node); @@ -256,13 +272,13 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { e.targetnode = i + 2; if (parameters->searchedmodifications[i].nterminal) { - node.setMZRatio(parameters->fragmentdefinitions[b_ion].massdifference + parameters->searchedmodifications[i].massdifference); + node.setMZRatio(parameters->fragmentdefinitions[b_ion].massdifference + parameters->searchedmodifications[i].massdifference + negativeshift); node.setIntensity(0); node.addIonAnnotation(b_ion); } if (parameters->searchedmodifications[i].cterminal) { - node.setMZRatio(parameters->fragmentdefinitions[y_ion].massdifference + parameters->searchedmodifications[i].massdifference); + node.setMZRatio(parameters->fragmentdefinitions[y_ion].massdifference + parameters->searchedmodifications[i].massdifference + negativeshift); node.setIntensity(0); node.addIonAnnotation(y_ion); } @@ -284,13 +300,13 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { graph.push_back(node); node.clear(); - node.setMZRatio(H2O + Hplus); + node.setMZRatio(H2O + Hplus + negativeshift); node.setIntensity(0); node.addIonAnnotation(ms_nterminal_ion_hplus); graph.push_back(node); //node.clear(); - //node.setMZRatio(H2O + Hplus); + //node.setMZRatio(H2O + Hplus + negativeshift); //node.setIntensity(0); //node.addIonAnnotation(ms_cterminal_ion_hplus); //graph.push_back(node); @@ -313,13 +329,13 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { e.targetnode = i + 1;//2; //if (parameters->searchedmodifications[i].nterminal) { - node.setMZRatio(H2O + Hplus + parameters->searchedmodifications[i].massdifference); + node.setMZRatio(H2O + Hplus + parameters->searchedmodifications[i].massdifference + negativeshift); node.setIntensity(0); node.addIonAnnotation(ms_nterminal_ion_hplus); //} //if (parameters->searchedmodifications[i].cterminal) { - // node.setMZRatio(H2O + Hplus +parameters->searchedmodifications[i].massdifference); + // node.setMZRatio(H2O + Hplus + parameters->searchedmodifications[i].massdifference + negativeshift); // node.setIntensity(0); // node.addIonAnnotation(ms_cterminal_ion_hplus); //} @@ -461,7 +477,7 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { continue; } - // middle modifications for branched and lasso peptides + // middle modifications for branched and branch-cyclic peptides for (int p = 0; p < (int)parameters->searchedmodifications.size(); p++) { if ((p > 0) && ((parameters->peptidetype == linear) || (parameters->peptidetype == cyclic) || (parameters->peptidetype == linearpolysaccharide))) { @@ -488,11 +504,11 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { } - for (int z1 = 1; z1 <= parameters->precursorcharge; z1++) { + for (int z1 = 1; z1 <= abs(parameters->precursorcharge); z1++) { - for (int z2 = 1; z2 <= parameters->precursorcharge; z2++) { + for (int z2 = 1; z2 <= abs(parameters->precursorcharge); z2++) { - unchargedmz = uncharge(graph[i].getMZRatio(), z1); + unchargedmz = charge(uncharge(graph[i].getMZRatio(), (parameters->precursorcharge > 0)?z1:-z1), (parameters->precursorcharge > 0)?1:-1); if ((!isInPpmMassErrorTolerance(unchargedmz, unchargedprecursormass, parameters->fragmentmasserrortolerance)) && (unchargedmz > unchargedprecursormass)) { continue; } @@ -521,12 +537,12 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { while (left <= right) { middle = (left + right) / 2; - if (isInPpmMassErrorTolerance(uncharge(graph[middle].getMZRatio(), z2), mass, parameters->fragmentmasserrortolerance)) { + if (isInPpmMassErrorTolerance(charge(uncharge(graph[middle].getMZRatio(), (parameters->precursorcharge > 0)?z2:-z2), (parameters->precursorcharge > 0)?1:-1), mass, parameters->fragmentmasserrortolerance)) { // found - while ((middle > lastsystemnode + 1) && isInPpmMassErrorTolerance(uncharge(graph[middle - 1].getMZRatio(), z2), mass, parameters->fragmentmasserrortolerance)) { + while ((middle > lastsystemnode + 1) && isInPpmMassErrorTolerance(charge(uncharge(graph[middle - 1].getMZRatio(), (parameters->precursorcharge > 0)?z2:-z2), (parameters->precursorcharge > 0)?1:-1), mass, parameters->fragmentmasserrortolerance)) { middle--; } - while ((middle < (int)graph.size()) && (isInPpmMassErrorTolerance(uncharge(graph[middle].getMZRatio(), z2), mass, parameters->fragmentmasserrortolerance))) { + while ((middle < (int)graph.size()) && (isInPpmMassErrorTolerance(charge(uncharge(graph[middle].getMZRatio(), (parameters->precursorcharge > 0)?z2:-z2), (parameters->precursorcharge > 0)?1:-1), mass, parameters->fragmentmasserrortolerance))) { // target node cannot be a system node if (middle <= lastsystemnode) { @@ -541,7 +557,7 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { } // mass corresponding to the target node must be <= uncharged precursor mass - if (uncharge(graph[middle].getMZRatio(), z2) > unchargedprecursormass) { + if (charge(uncharge(graph[middle].getMZRatio(), (parameters->precursorcharge > 0)?z2:-z2), (parameters->precursorcharge > 0)?1:-1) > unchargedprecursormass) { middle++; continue; } @@ -558,10 +574,10 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { if (i == (int)graph.size() - 1) { e.targetnode = i; e.brickid = j; - e.ppmerror = ppmError(uncharge(graph[middle].getMZRatio(), z2), mass); - e.massdifference = abs(unchargedmz - uncharge(graph[middle].getMZRatio(), z2)); - e.sourcecharge = z2; - e.targetcharge = z1; + e.ppmerror = ppmError(charge(uncharge(graph[middle].getMZRatio(), (parameters->precursorcharge > 0)?z2:-z2), (parameters->precursorcharge > 0)?1:-1), mass); + e.massdifference = abs(unchargedmz - charge(uncharge(graph[middle].getMZRatio(), (parameters->precursorcharge > 0)?z2:-z2), (parameters->precursorcharge > 0)?1:-1)); + e.sourcecharge = (parameters->precursorcharge > 0)?z2:-z2; + e.targetcharge = (parameters->precursorcharge > 0)?z1:-z1; e.targetintensity = graph[i].getIntensity(); e.composition = bricksdatabasewithcombinations[j].getComposition(); e.endmodifID = n; @@ -573,10 +589,10 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { else { e.targetnode = middle; e.brickid = j; - e.ppmerror = ppmError(uncharge(graph[middle].getMZRatio(), z2), mass); - e.massdifference = abs(uncharge(graph[middle].getMZRatio(), z2) - unchargedmz); - e.sourcecharge = z1; - e.targetcharge = z2; + e.ppmerror = ppmError(charge(uncharge(graph[middle].getMZRatio(), (parameters->precursorcharge > 0)?z2:-z2), (parameters->precursorcharge > 0)?1:-1), mass); + e.massdifference = abs(charge(uncharge(graph[middle].getMZRatio(), (parameters->precursorcharge > 0)?z2:-z2), (parameters->precursorcharge > 0)?1:-1) - unchargedmz); + e.sourcecharge = (parameters->precursorcharge > 0)?z1:-z1; + e.targetcharge = (parameters->precursorcharge > 0)?z2:-z2; e.targetintensity = graph[middle].getIntensity(); e.composition = bricksdatabasewithcombinations[j].getComposition(); e.endmodifID = n; @@ -593,7 +609,7 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { } break; } - if (mass < uncharge(graph[middle].getMZRatio(), z2)) { + if (mass < charge(uncharge(graph[middle].getMZRatio(), (parameters->precursorcharge > 0)?z2:-z2), (parameters->precursorcharge > 0)?1:-1)) { right = middle - 1; } else { @@ -640,7 +656,7 @@ int cDeNovoGraph::createGraph(bool& terminatecomputation) { int cDeNovoGraph::removeEdgesFormingPathsNotFinishingInPrecursor(bool& terminatecomputation) { *os << "Removing edges forming blind paths (not finishing in the precursor)... "; - double unchargedprecursormass = uncharge(parameters->precursormass, parameters->precursorcharge); + double neutralprecursormass = uncharge(parameters->precursormass, parameters->precursorcharge); bool removed = true; bool isprecursor; int edgesremoved = 0; @@ -658,8 +674,8 @@ int cDeNovoGraph::removeEdgesFormingPathsNotFinishingInPrecursor(bool& terminate // Is the target precursor ? isprecursor = false; - for (int k = 1; k <= parameters->precursorcharge; k++) { - if (isInPpmMassErrorTolerance(graph[graph[i][j].targetnode].getMZRatio(), charge(unchargedprecursormass, k), parameters->precursormasserrortolerance)) { + for (int k = 1; k <= abs(parameters->precursorcharge); k++) { + if (isInPpmMassErrorTolerance(graph[graph[i][j].targetnode].getMZRatio(), charge(neutralprecursormass, (parameters->precursorcharge > 0)?k:-k), parameters->precursormasserrortolerance)) { isprecursor = true; break; } @@ -748,8 +764,8 @@ int cDeNovoGraph::connectEdgesFormingPathsNotFinishingInPrecursor(bool& terminat e.brickid = (int)bricksdatabasewithcombinations.size() + 1; e.ppmerror = 0; e.massdifference = abs(graph[precursorposition].getMZRatio() - graph[i].getMZRatio()); - e.sourcecharge = 1; - e.targetcharge = 1; + e.sourcecharge = (parameters->precursorcharge > 0)?1:-1; + e.targetcharge = (parameters->precursorcharge > 0)?1:-1; e.targetintensity = graph[e.targetnode].getIntensity(); e.composition = to_string(e.brickid); e.endmodifID = 0; @@ -813,8 +829,8 @@ int cDeNovoGraph::connectEdgesFormingPathsNotStartingFromFirstNode(bool& termina e.brickid = (int)bricksdatabasewithcombinations.size() + 1; e.ppmerror = 0; e.massdifference = abs(graph[i].getMZRatio() - graph[j].getMZRatio()); - e.sourcecharge = 1; - e.targetcharge = 1; + e.sourcecharge = (parameters->precursorcharge > 0)?1:-1; + e.targetcharge = (parameters->precursorcharge > 0)?1:-1; e.targetintensity = graph[i].getIntensity(); e.composition = to_string(e.brickid); e.endmodifID = 0; @@ -849,7 +865,7 @@ int cDeNovoGraph::removePathsWhichCanBeSubstitutedByLongerPath(bool& terminateco *os << "Removing edges forming paths which can be substituted by longer paths... "; int edgesremoved = 0; int j; - vector path; + vector path; for (int i = startnode; i < (int)graph.size(); i++) { diff --git a/CycloBranch/core/cDeNovoGraph.h b/CycloBranch/core/cDeNovoGraph.h index 422bf77..c5b49ed 100644 --- a/CycloBranch/core/cDeNovoGraph.h +++ b/CycloBranch/core/cDeNovoGraph.h @@ -55,7 +55,7 @@ class cDeNovoGraph { cGraphReaderThread* graphreaderthread; - bool findPath(int sourcenodeid, int edgeid, int targetnodeid, string& composition, string brickspath, int maximumbricksincombination, vector& path); + bool findPath(int sourcenodeid, int edgeid, int targetnodeid, string& composition, string brickspath, int maximumbricksincombination, vector& path); // create vectors of edges from temporary unordered_sets void createVectorsOfEdges(); diff --git a/CycloBranch/core/cDeNovoGraphNode.cpp b/CycloBranch/core/cDeNovoGraphNode.cpp index 4c3b4d1..453b7e5 100644 --- a/CycloBranch/core/cDeNovoGraphNode.cpp +++ b/CycloBranch/core/cDeNovoGraphNode.cpp @@ -18,12 +18,12 @@ bool operator == (cEdge const& a, cEdge const& b) { } -bool compareEdgesByPPMError(cEdge& a, cEdge& b) { +bool compareEdgesByPPMError(const cEdge& a, const cEdge& b) { return (a.ppmerror < b.ppmerror); } -bool compareEdgesByTargetNodeIntensityDesc(cEdge& a, cEdge& b) { +bool compareEdgesByTargetNodeIntensityDesc(const cEdge& a, const cEdge& b) { return (a.targetintensity > b.targetintensity); } diff --git a/CycloBranch/core/cDeNovoGraphNode.h b/CycloBranch/core/cDeNovoGraphNode.h index 8ee33bd..4dda405 100644 --- a/CycloBranch/core/cDeNovoGraphNode.h +++ b/CycloBranch/core/cDeNovoGraphNode.h @@ -153,7 +153,7 @@ struct hash_cEdge { \retval size_t hashed edge */ size_t operator()(const cEdge& e) const { - return hash()(e.targetnode) ^ hash()(e.brickid); + return std::hash()(e.targetnode) ^ std::hash()(e.brickid); } }; @@ -174,7 +174,7 @@ bool operator == (cEdge const& a, cEdge const& b); \param b second edge \retval bool true when \a a has smaller ppm error than \a b */ -bool compareEdgesByPPMError(cEdge& a, cEdge& b); +bool compareEdgesByPPMError(const cEdge& a, const cEdge& b); /** @@ -183,7 +183,7 @@ bool compareEdgesByPPMError(cEdge& a, cEdge& b); \param b second edge \retval bool true when the target node of \a a has bigger intensity than the target node of \a b */ -bool compareEdgesByTargetNodeIntensityDesc(cEdge& a, cEdge& b); +bool compareEdgesByTargetNodeIntensityDesc(const cEdge& a, const cEdge& b); /** @@ -318,4 +318,4 @@ class cDeNovoGraphNode { }; -#endif \ No newline at end of file +#endif diff --git a/CycloBranch/core/cFragmentIons.cpp b/CycloBranch/core/cFragmentIons.cpp index 9531dbc..c10b320 100644 --- a/CycloBranch/core/cFragmentIons.cpp +++ b/CycloBranch/core/cFragmentIons.cpp @@ -1,4 +1,5 @@ #include "core/cFragmentIons.h" +#include "core/cSummaryFormula.h" cPeriodicTableMap::cPeriodicTableMap() { @@ -47,66 +48,13 @@ int cPeriodicTableMap::count(string& element) { } -peptideType getPeptideTypeFromString(string s) { - if (s.compare("linear") == 0) { - return linear; - } - if (s.compare("cyclic") == 0) { - return cyclic; - } - if (s.compare("branched") == 0) { - return branched; - } - if (s.compare("lasso") == 0) { - return lasso; - } - if (s.compare("linearpolysaccharide") == 0) { - return linearpolysaccharide; - } - if (s.compare("other") == 0) { - return other; - } - - return other; +double charge(double neutralmass, int charge) { + return (neutralmass + (double)charge*Hplus)/(double)abs(charge); } -string getStringFromPeptideType(peptideType peptidetype) { - switch (peptidetype) - { - case linear: - return "linear"; - break; - case cyclic: - return "cyclic"; - break; - case branched: - return "branched"; - break; - case lasso: - return "lasso"; - break; - case linearpolysaccharide: - return "linearpolysaccharide"; - break; - case other: - return "other"; - break; - default: - break; - } - - return "other"; -} - - -double charge(double mass, int charge) { - return (mass + ((double)(charge - 1))*Hplus)/(double)charge; -} - - -double uncharge(double mass, int charge) { - return mass*(double)charge - ((double)(charge - 1))*Hplus; +double uncharge(double mzratio, int charge) { + return mzratio*(double)abs(charge) - (double)charge*Hplus; } @@ -135,12 +83,13 @@ void fragmentDescription::load(ifstream& is) { cFragmentIons::cFragmentIons() { - recalculateFragments(false, false); + string s = ""; + recalculateFragments(false, false, s); } -cFragmentIons::cFragmentIons(bool cyclicnterminus, bool cycliccterminus) { - recalculateFragments(cyclicnterminus, cycliccterminus); +cFragmentIons::cFragmentIons(bool cyclicnterminus, bool cycliccterminus, string& precursoradduct) { + recalculateFragments(cyclicnterminus, cycliccterminus, precursoradduct); } @@ -149,208 +98,299 @@ fragmentDescription &cFragmentIons::operator[](fragmentIonType iontype) { } -void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cycliccterminus) { +void cFragmentIons::recalculateFragments(bool cyclicnterminus, bool cycliccterminus, string& precursoradduct) { fragmentions.clear(); double nterminusshift = cyclicnterminus?-H2O:0; double cterminusshift = cycliccterminus?-H2O:0; - - // initialize B-ion - fragmentions[b_ion].nterminal = true; - fragmentions[b_ion].cterminal = false; - fragmentions[b_ion].name = "B"; - fragmentions[b_ion].massdifference = B_ION + nterminusshift; - fragmentions[b_ion].parent = b_ion; + double adductshift = 0; - // initialize B-H2O ion - fragmentions[b_ion_water_loss].nterminal = true; - fragmentions[b_ion_water_loss].cterminal = false; - fragmentions[b_ion_water_loss].name = "B*"; - fragmentions[b_ion_water_loss].massdifference = B_ION - H2O + nterminusshift; - fragmentions[b_ion_water_loss].parent = b_ion; - - // initialize B-NH3 ion - fragmentions[b_ion_ammonia_loss].nterminal = true; - fragmentions[b_ion_ammonia_loss].cterminal = false; - fragmentions[b_ion_ammonia_loss].name = "Bx"; - fragmentions[b_ion_ammonia_loss].massdifference = B_ION - NH3 + nterminusshift; - fragmentions[b_ion_ammonia_loss].parent = b_ion; - - // initialize B-H2O-NH3 ion - fragmentions[b_ion_water_and_ammonia_loss].nterminal = true; - fragmentions[b_ion_water_and_ammonia_loss].cterminal = false; - fragmentions[b_ion_water_and_ammonia_loss].name = "B*x"; - fragmentions[b_ion_water_and_ammonia_loss].massdifference = B_ION - H2O - NH3 + nterminusshift; - fragmentions[b_ion_water_and_ammonia_loss].parent = b_ion; + if (precursoradduct.compare("") != 0) { + cSummaryFormula formula; + formula.setFormula(precursoradduct); + adductshift = formula.getMass() - H; + } // initialize A-ion fragmentions[a_ion].nterminal = true; fragmentions[a_ion].cterminal = false; fragmentions[a_ion].name = "A"; - fragmentions[a_ion].massdifference = A_ION + nterminusshift; + fragmentions[a_ion].massdifference = A_ION + nterminusshift + adductshift; fragmentions[a_ion].parent = b_ion; // ok // initialize A-H2O ion - fragmentions[a_ion_water_loss].nterminal = true; - fragmentions[a_ion_water_loss].cterminal = false; - fragmentions[a_ion_water_loss].name = "A*"; - fragmentions[a_ion_water_loss].massdifference = A_ION - H2O + nterminusshift; - fragmentions[a_ion_water_loss].parent = a_ion; + fragmentions[a_ion_dehydrated].nterminal = true; + fragmentions[a_ion_dehydrated].cterminal = false; + fragmentions[a_ion_dehydrated].name = "A*"; + fragmentions[a_ion_dehydrated].massdifference = A_ION - H2O + nterminusshift + adductshift; + fragmentions[a_ion_dehydrated].parent = a_ion; // initialize A-NH3 ion - fragmentions[a_ion_ammonia_loss].nterminal = true; - fragmentions[a_ion_ammonia_loss].cterminal = false; - fragmentions[a_ion_ammonia_loss].name = "Ax"; - fragmentions[a_ion_ammonia_loss].massdifference = A_ION - NH3 + nterminusshift; - fragmentions[a_ion_ammonia_loss].parent = a_ion; + fragmentions[a_ion_deamidated].nterminal = true; + fragmentions[a_ion_deamidated].cterminal = false; + fragmentions[a_ion_deamidated].name = "Ax"; + fragmentions[a_ion_deamidated].massdifference = A_ION - NH3 + nterminusshift + adductshift; + fragmentions[a_ion_deamidated].parent = a_ion; // initialize A-H2O-NH3 ion - fragmentions[a_ion_water_and_ammonia_loss].nterminal = true; - fragmentions[a_ion_water_and_ammonia_loss].cterminal = false; - fragmentions[a_ion_water_and_ammonia_loss].name = "A*x"; - fragmentions[a_ion_water_and_ammonia_loss].massdifference = A_ION - H2O - NH3 + nterminusshift; - fragmentions[a_ion_water_and_ammonia_loss].parent = a_ion; + fragmentions[a_ion_dehydrated_and_deamidated].nterminal = true; + fragmentions[a_ion_dehydrated_and_deamidated].cterminal = false; + fragmentions[a_ion_dehydrated_and_deamidated].name = "A*x"; + fragmentions[a_ion_dehydrated_and_deamidated].massdifference = A_ION - H2O - NH3 + nterminusshift + adductshift; + fragmentions[a_ion_dehydrated_and_deamidated].parent = a_ion; + + // initialize B-ion + fragmentions[b_ion].nterminal = true; + fragmentions[b_ion].cterminal = false; + fragmentions[b_ion].name = "B"; + fragmentions[b_ion].massdifference = B_ION + nterminusshift + adductshift; + fragmentions[b_ion].parent = b_ion; + + // initialize B-H2O ion + fragmentions[b_ion_dehydrated].nterminal = true; + fragmentions[b_ion_dehydrated].cterminal = false; + fragmentions[b_ion_dehydrated].name = "B*"; + fragmentions[b_ion_dehydrated].massdifference = B_ION - H2O + nterminusshift + adductshift; + fragmentions[b_ion_dehydrated].parent = b_ion; + + // initialize B-NH3 ion + fragmentions[b_ion_deamidated].nterminal = true; + fragmentions[b_ion_deamidated].cterminal = false; + fragmentions[b_ion_deamidated].name = "Bx"; + fragmentions[b_ion_deamidated].massdifference = B_ION - NH3 + nterminusshift + adductshift; + fragmentions[b_ion_deamidated].parent = b_ion; + + // initialize B-H2O-NH3 ion + fragmentions[b_ion_dehydrated_and_deamidated].nterminal = true; + fragmentions[b_ion_dehydrated_and_deamidated].cterminal = false; + fragmentions[b_ion_dehydrated_and_deamidated].name = "B*x"; + fragmentions[b_ion_dehydrated_and_deamidated].massdifference = B_ION - H2O - NH3 + nterminusshift + adductshift; + fragmentions[b_ion_dehydrated_and_deamidated].parent = b_ion; + + // initialize C-ion + fragmentions[c_ion].nterminal = true; + fragmentions[c_ion].cterminal = false; + fragmentions[c_ion].name = "C"; + fragmentions[c_ion].massdifference = C_ION + nterminusshift + adductshift; + fragmentions[c_ion].parent = c_ion; + + // initialize C-H2O ion + fragmentions[c_ion_dehydrated].nterminal = true; + fragmentions[c_ion_dehydrated].cterminal = false; + fragmentions[c_ion_dehydrated].name = "C*"; + fragmentions[c_ion_dehydrated].massdifference = C_ION - H2O + nterminusshift + adductshift; + fragmentions[c_ion_dehydrated].parent = c_ion; + + // initialize C-NH3 ion + fragmentions[c_ion_deamidated].nterminal = true; + fragmentions[c_ion_deamidated].cterminal = false; + fragmentions[c_ion_deamidated].name = "Cx"; + fragmentions[c_ion_deamidated].massdifference = C_ION - NH3 + nterminusshift + adductshift; + fragmentions[c_ion_deamidated].parent = c_ion; + + // initialize C-H2O-NH3 ion + fragmentions[c_ion_dehydrated_and_deamidated].nterminal = true; + fragmentions[c_ion_dehydrated_and_deamidated].cterminal = false; + fragmentions[c_ion_dehydrated_and_deamidated].name = "C*x"; + fragmentions[c_ion_dehydrated_and_deamidated].massdifference = C_ION - H2O - NH3 + nterminusshift + adductshift; + fragmentions[c_ion_dehydrated_and_deamidated].parent = c_ion; + + // initialize X ion + fragmentions[x_ion].nterminal = false; + fragmentions[x_ion].cterminal = true; + fragmentions[x_ion].name = "X"; + fragmentions[x_ion].massdifference = X_ION + cterminusshift + adductshift; + fragmentions[x_ion].parent = x_ion; + + // initialize X-H2O ion + fragmentions[x_ion_dehydrated].nterminal = false; + fragmentions[x_ion_dehydrated].cterminal = true; + fragmentions[x_ion_dehydrated].name = "X*"; + fragmentions[x_ion_dehydrated].massdifference = X_ION - H2O + cterminusshift + adductshift; + fragmentions[x_ion_dehydrated].parent = x_ion; + + // initialize X-NH3 ion + fragmentions[x_ion_deamidated].nterminal = false; + fragmentions[x_ion_deamidated].cterminal = true; + fragmentions[x_ion_deamidated].name = "Xx"; + fragmentions[x_ion_deamidated].massdifference = X_ION - NH3 + cterminusshift + adductshift; + fragmentions[x_ion_deamidated].parent = x_ion; + + // initialize X-H2O-NH3 ion + fragmentions[x_ion_dehydrated_and_deamidated].nterminal = false; + fragmentions[x_ion_dehydrated_and_deamidated].cterminal = true; + fragmentions[x_ion_dehydrated_and_deamidated].name = "X*x"; + fragmentions[x_ion_dehydrated_and_deamidated].massdifference = X_ION - H2O - NH3 + cterminusshift + adductshift; + fragmentions[x_ion_dehydrated_and_deamidated].parent = x_ion; // initialize Y ion fragmentions[y_ion].nterminal = false; fragmentions[y_ion].cterminal = true; fragmentions[y_ion].name = "Y"; - fragmentions[y_ion].massdifference = Y_ION + cterminusshift; + fragmentions[y_ion].massdifference = Y_ION + cterminusshift + adductshift; fragmentions[y_ion].parent = y_ion; // initialize Y-H2O ion - fragmentions[y_ion_water_loss].nterminal = false; - fragmentions[y_ion_water_loss].cterminal = true; - fragmentions[y_ion_water_loss].name = "Y*"; - fragmentions[y_ion_water_loss].massdifference = Y_ION - H2O + cterminusshift; - fragmentions[y_ion_water_loss].parent = y_ion; + fragmentions[y_ion_dehydrated].nterminal = false; + fragmentions[y_ion_dehydrated].cterminal = true; + fragmentions[y_ion_dehydrated].name = "Y*"; + fragmentions[y_ion_dehydrated].massdifference = Y_ION - H2O + cterminusshift + adductshift; + fragmentions[y_ion_dehydrated].parent = y_ion; // initialize Y-NH3 ion - fragmentions[y_ion_ammonia_loss].nterminal = false; - fragmentions[y_ion_ammonia_loss].cterminal = true; - fragmentions[y_ion_ammonia_loss].name = "Yx"; - fragmentions[y_ion_ammonia_loss].massdifference = Y_ION - NH3 + cterminusshift; - fragmentions[y_ion_ammonia_loss].parent = y_ion; + fragmentions[y_ion_deamidated].nterminal = false; + fragmentions[y_ion_deamidated].cterminal = true; + fragmentions[y_ion_deamidated].name = "Yx"; + fragmentions[y_ion_deamidated].massdifference = Y_ION - NH3 + cterminusshift + adductshift; + fragmentions[y_ion_deamidated].parent = y_ion; // initialize Y-H2O-NH3 ion - fragmentions[y_ion_water_and_ammonia_loss].nterminal = false; - fragmentions[y_ion_water_and_ammonia_loss].cterminal = true; - fragmentions[y_ion_water_and_ammonia_loss].name = "Y*x"; - fragmentions[y_ion_water_and_ammonia_loss].massdifference = Y_ION - H2O - NH3 + cterminusshift; - fragmentions[y_ion_water_and_ammonia_loss].parent = y_ion; + fragmentions[y_ion_dehydrated_and_deamidated].nterminal = false; + fragmentions[y_ion_dehydrated_and_deamidated].cterminal = true; + fragmentions[y_ion_dehydrated_and_deamidated].name = "Y*x"; + fragmentions[y_ion_dehydrated_and_deamidated].massdifference = Y_ION - H2O - NH3 + cterminusshift + adductshift; + fragmentions[y_ion_dehydrated_and_deamidated].parent = y_ion; + + // initialize Z ion + fragmentions[z_ion].nterminal = false; + fragmentions[z_ion].cterminal = true; + fragmentions[z_ion].name = "Z"; + fragmentions[z_ion].massdifference = Z_ION + cterminusshift + adductshift; + fragmentions[z_ion].parent = z_ion; + + // initialize Z-H2O ion + fragmentions[z_ion_dehydrated].nterminal = false; + fragmentions[z_ion_dehydrated].cterminal = true; + fragmentions[z_ion_dehydrated].name = "Z*"; + fragmentions[z_ion_dehydrated].massdifference = Z_ION - H2O + cterminusshift + adductshift; + fragmentions[z_ion_dehydrated].parent = z_ion; + + // initialize Z-NH3 ion + fragmentions[z_ion_deamidated].nterminal = false; + fragmentions[z_ion_deamidated].cterminal = true; + fragmentions[z_ion_deamidated].name = "Zx"; + fragmentions[z_ion_deamidated].massdifference = Z_ION - NH3 + cterminusshift + adductshift; + fragmentions[z_ion_deamidated].parent = z_ion; + + // initialize Z-H2O-NH3 ion + fragmentions[z_ion_dehydrated_and_deamidated].nterminal = false; + fragmentions[z_ion_dehydrated_and_deamidated].cterminal = true; + fragmentions[z_ion_dehydrated_and_deamidated].name = "Z*x"; + fragmentions[z_ion_dehydrated_and_deamidated].massdifference = Z_ION - H2O - NH3 + cterminusshift + adductshift; + fragmentions[z_ion_dehydrated_and_deamidated].parent = z_ion; // initialize precursor ion fragmentions[precursor_ion].nterminal = false; fragmentions[precursor_ion].cterminal = false; fragmentions[precursor_ion].name = "[M+zH]+"; - fragmentions[precursor_ion].massdifference = PRECURSOR_ION + nterminusshift + cterminusshift; + fragmentions[precursor_ion].massdifference = PRECURSOR_ION + nterminusshift + cterminusshift + adductshift; fragmentions[precursor_ion].parent = precursor_ion; // initialize precursor ion - H2O - fragmentions[precursor_ion_water_loss].nterminal = false; - fragmentions[precursor_ion_water_loss].cterminal = false; - fragmentions[precursor_ion_water_loss].name = "[M+zH]+ *"; - fragmentions[precursor_ion_water_loss].massdifference = PRECURSOR_ION - H2O + nterminusshift + cterminusshift; - fragmentions[precursor_ion_water_loss].parent = precursor_ion; + fragmentions[precursor_ion_dehydrated].nterminal = false; + fragmentions[precursor_ion_dehydrated].cterminal = false; + fragmentions[precursor_ion_dehydrated].name = "[M+zH]+ *"; + fragmentions[precursor_ion_dehydrated].massdifference = PRECURSOR_ION - H2O + nterminusshift + cterminusshift + adductshift; + fragmentions[precursor_ion_dehydrated].parent = precursor_ion; // initialize precursor ion - NH3 - fragmentions[precursor_ion_ammonia_loss].nterminal = false; - fragmentions[precursor_ion_ammonia_loss].cterminal = false; - fragmentions[precursor_ion_ammonia_loss].name = "[M+zH]+ x"; - fragmentions[precursor_ion_ammonia_loss].massdifference = PRECURSOR_ION - NH3 + nterminusshift + cterminusshift; - fragmentions[precursor_ion_ammonia_loss].parent = precursor_ion; + fragmentions[precursor_ion_deamidated].nterminal = false; + fragmentions[precursor_ion_deamidated].cterminal = false; + fragmentions[precursor_ion_deamidated].name = "[M+zH]+ x"; + fragmentions[precursor_ion_deamidated].massdifference = PRECURSOR_ION - NH3 + nterminusshift + cterminusshift + adductshift; + fragmentions[precursor_ion_deamidated].parent = precursor_ion; // initialize precursor ion - H2O - NH3 - fragmentions[precursor_ion_water_and_ammonia_loss].nterminal = false; - fragmentions[precursor_ion_water_and_ammonia_loss].cterminal = false; - fragmentions[precursor_ion_water_and_ammonia_loss].name = "[M+zH]+ *x"; - fragmentions[precursor_ion_water_and_ammonia_loss].massdifference = PRECURSOR_ION - H2O - NH3 + nterminusshift + cterminusshift; - fragmentions[precursor_ion_water_and_ammonia_loss].parent = precursor_ion; + fragmentions[precursor_ion_dehydrated_and_deamidated].nterminal = false; + fragmentions[precursor_ion_dehydrated_and_deamidated].cterminal = false; + fragmentions[precursor_ion_dehydrated_and_deamidated].name = "[M+zH]+ *x"; + fragmentions[precursor_ion_dehydrated_and_deamidated].massdifference = PRECURSOR_ION - H2O - NH3 + nterminusshift + cterminusshift + adductshift; + fragmentions[precursor_ion_dehydrated_and_deamidated].parent = precursor_ion; // initialize precursor ion - CO fragmentions[precursor_ion_co_loss].nterminal = false; fragmentions[precursor_ion_co_loss].cterminal = false; fragmentions[precursor_ion_co_loss].name = "[M+zH]+ -CO"; - fragmentions[precursor_ion_co_loss].massdifference = PRECURSOR_ION - CO + nterminusshift + cterminusshift; + fragmentions[precursor_ion_co_loss].massdifference = PRECURSOR_ION - CO + nterminusshift + cterminusshift + adductshift; fragmentions[precursor_ion_co_loss].parent = precursor_ion; // initialize precursor ion - CO - H2O - fragmentions[precursor_ion_co_loss_water_loss].nterminal = false; - fragmentions[precursor_ion_co_loss_water_loss].cterminal = false; - fragmentions[precursor_ion_co_loss_water_loss].name = "[M+zH]+ *-CO"; - fragmentions[precursor_ion_co_loss_water_loss].massdifference = PRECURSOR_ION - CO - H2O + nterminusshift + cterminusshift; - fragmentions[precursor_ion_co_loss_water_loss].parent = precursor_ion_co_loss; + fragmentions[precursor_ion_co_loss_and_dehydrated].nterminal = false; + fragmentions[precursor_ion_co_loss_and_dehydrated].cterminal = false; + fragmentions[precursor_ion_co_loss_and_dehydrated].name = "[M+zH]+ *-CO"; + fragmentions[precursor_ion_co_loss_and_dehydrated].massdifference = PRECURSOR_ION - CO - H2O + nterminusshift + cterminusshift + adductshift; + fragmentions[precursor_ion_co_loss_and_dehydrated].parent = precursor_ion_co_loss; // initialize precursor ion - CO - NH3 - fragmentions[precursor_ion_co_loss_ammonia_loss].nterminal = false; - fragmentions[precursor_ion_co_loss_ammonia_loss].cterminal = false; - fragmentions[precursor_ion_co_loss_ammonia_loss].name = "[M+zH]+ x-CO"; - fragmentions[precursor_ion_co_loss_ammonia_loss].massdifference = PRECURSOR_ION - CO - NH3 + nterminusshift + cterminusshift; - fragmentions[precursor_ion_co_loss_ammonia_loss].parent = precursor_ion_co_loss; + fragmentions[precursor_ion_co_loss_and_deamidated].nterminal = false; + fragmentions[precursor_ion_co_loss_and_deamidated].cterminal = false; + fragmentions[precursor_ion_co_loss_and_deamidated].name = "[M+zH]+ x-CO"; + fragmentions[precursor_ion_co_loss_and_deamidated].massdifference = PRECURSOR_ION - CO - NH3 + nterminusshift + cterminusshift + adductshift; + fragmentions[precursor_ion_co_loss_and_deamidated].parent = precursor_ion_co_loss; // initialize precursor ion - CO - H2O - NH3 - fragmentions[precursor_ion_co_loss_water_and_ammonia_loss].nterminal = false; - fragmentions[precursor_ion_co_loss_water_and_ammonia_loss].cterminal = false; - fragmentions[precursor_ion_co_loss_water_and_ammonia_loss].name = "[M+zH]+ *x-CO"; - fragmentions[precursor_ion_co_loss_water_and_ammonia_loss].massdifference = PRECURSOR_ION - CO - H2O - NH3 + nterminusshift + cterminusshift; - fragmentions[precursor_ion_co_loss_water_and_ammonia_loss].parent = precursor_ion_co_loss; + fragmentions[precursor_ion_co_loss_and_dehydrated_and_deamidated].nterminal = false; + fragmentions[precursor_ion_co_loss_and_dehydrated_and_deamidated].cterminal = false; + fragmentions[precursor_ion_co_loss_and_dehydrated_and_deamidated].name = "[M+zH]+ *x-CO"; + fragmentions[precursor_ion_co_loss_and_dehydrated_and_deamidated].massdifference = PRECURSOR_ION - CO - H2O - NH3 + nterminusshift + cterminusshift + adductshift; + fragmentions[precursor_ion_co_loss_and_dehydrated_and_deamidated].parent = precursor_ion_co_loss; // initialize cyclic precursor ion fragmentions[cyclic_precursor_ion].nterminal = false; fragmentions[cyclic_precursor_ion].cterminal = false; fragmentions[cyclic_precursor_ion].name = "[M+zH]+"; - fragmentions[cyclic_precursor_ion].massdifference = PRECURSOR_ION_CYCLIC; + fragmentions[cyclic_precursor_ion].massdifference = PRECURSOR_ION_CYCLIC + adductshift; fragmentions[cyclic_precursor_ion].parent = cyclic_precursor_ion; // initialize cyclic precursor ion - H2O - fragmentions[cyclic_precursor_ion_water_loss].nterminal = false; - fragmentions[cyclic_precursor_ion_water_loss].cterminal = false; - fragmentions[cyclic_precursor_ion_water_loss].name = "[M+zH]+ *"; - fragmentions[cyclic_precursor_ion_water_loss].massdifference = PRECURSOR_ION_CYCLIC - H2O; - fragmentions[cyclic_precursor_ion_water_loss].parent = cyclic_precursor_ion; + fragmentions[cyclic_precursor_ion_dehydrated].nterminal = false; + fragmentions[cyclic_precursor_ion_dehydrated].cterminal = false; + fragmentions[cyclic_precursor_ion_dehydrated].name = "[M+zH]+ *"; + fragmentions[cyclic_precursor_ion_dehydrated].massdifference = PRECURSOR_ION_CYCLIC - H2O + adductshift; + fragmentions[cyclic_precursor_ion_dehydrated].parent = cyclic_precursor_ion; // initialize cyclic precursor ion - NH3 - fragmentions[cyclic_precursor_ion_ammonia_loss].nterminal = false; - fragmentions[cyclic_precursor_ion_ammonia_loss].cterminal = false; - fragmentions[cyclic_precursor_ion_ammonia_loss].name = "[M+zH]+ x"; - fragmentions[cyclic_precursor_ion_ammonia_loss].massdifference = PRECURSOR_ION_CYCLIC - NH3; - fragmentions[cyclic_precursor_ion_ammonia_loss].parent = cyclic_precursor_ion; + fragmentions[cyclic_precursor_ion_deamidated].nterminal = false; + fragmentions[cyclic_precursor_ion_deamidated].cterminal = false; + fragmentions[cyclic_precursor_ion_deamidated].name = "[M+zH]+ x"; + fragmentions[cyclic_precursor_ion_deamidated].massdifference = PRECURSOR_ION_CYCLIC - NH3 + adductshift; + fragmentions[cyclic_precursor_ion_deamidated].parent = cyclic_precursor_ion; // initialize cyclic precursor ion - H2O - NH3 - fragmentions[cyclic_precursor_ion_water_and_ammonia_loss].nterminal = false; - fragmentions[cyclic_precursor_ion_water_and_ammonia_loss].cterminal = false; - fragmentions[cyclic_precursor_ion_water_and_ammonia_loss].name = "[M+zH]+ *x"; - fragmentions[cyclic_precursor_ion_water_and_ammonia_loss].massdifference = PRECURSOR_ION_CYCLIC - H2O - NH3; - fragmentions[cyclic_precursor_ion_water_and_ammonia_loss].parent = cyclic_precursor_ion; + fragmentions[cyclic_precursor_ion_dehydrated_and_deamidated].nterminal = false; + fragmentions[cyclic_precursor_ion_dehydrated_and_deamidated].cterminal = false; + fragmentions[cyclic_precursor_ion_dehydrated_and_deamidated].name = "[M+zH]+ *x"; + fragmentions[cyclic_precursor_ion_dehydrated_and_deamidated].massdifference = PRECURSOR_ION_CYCLIC - H2O - NH3 + adductshift; + fragmentions[cyclic_precursor_ion_dehydrated_and_deamidated].parent = cyclic_precursor_ion; // initialize cyclic precursor ion - CO fragmentions[cyclic_precursor_ion_co_loss].nterminal = false; fragmentions[cyclic_precursor_ion_co_loss].cterminal = false; fragmentions[cyclic_precursor_ion_co_loss].name = "[M+zH]+ -CO"; - fragmentions[cyclic_precursor_ion_co_loss].massdifference = PRECURSOR_ION_CYCLIC - CO; + fragmentions[cyclic_precursor_ion_co_loss].massdifference = PRECURSOR_ION_CYCLIC - CO + adductshift; fragmentions[cyclic_precursor_ion_co_loss].parent = cyclic_precursor_ion; // initialize cyclic precursor ion - CO - H2O - fragmentions[cyclic_precursor_ion_co_loss_water_loss].nterminal = false; - fragmentions[cyclic_precursor_ion_co_loss_water_loss].cterminal = false; - fragmentions[cyclic_precursor_ion_co_loss_water_loss].name = "[M+zH]+ *-CO"; - fragmentions[cyclic_precursor_ion_co_loss_water_loss].massdifference = PRECURSOR_ION_CYCLIC - CO - H2O; - fragmentions[cyclic_precursor_ion_co_loss_water_loss].parent = cyclic_precursor_ion_co_loss; + fragmentions[cyclic_precursor_ion_co_loss_and_dehydrated].nterminal = false; + fragmentions[cyclic_precursor_ion_co_loss_and_dehydrated].cterminal = false; + fragmentions[cyclic_precursor_ion_co_loss_and_dehydrated].name = "[M+zH]+ *-CO"; + fragmentions[cyclic_precursor_ion_co_loss_and_dehydrated].massdifference = PRECURSOR_ION_CYCLIC - CO - H2O + adductshift; + fragmentions[cyclic_precursor_ion_co_loss_and_dehydrated].parent = cyclic_precursor_ion_co_loss; // initialize cyclic precursor ion - CO - NH3 - fragmentions[cyclic_precursor_ion_co_loss_ammonia_loss].nterminal = false; - fragmentions[cyclic_precursor_ion_co_loss_ammonia_loss].cterminal = false; - fragmentions[cyclic_precursor_ion_co_loss_ammonia_loss].name = "[M+zH]+ x-CO"; - fragmentions[cyclic_precursor_ion_co_loss_ammonia_loss].massdifference = PRECURSOR_ION_CYCLIC - CO - NH3; - fragmentions[cyclic_precursor_ion_co_loss_ammonia_loss].parent = cyclic_precursor_ion_co_loss; + fragmentions[cyclic_precursor_ion_co_loss_and_deamidated].nterminal = false; + fragmentions[cyclic_precursor_ion_co_loss_and_deamidated].cterminal = false; + fragmentions[cyclic_precursor_ion_co_loss_and_deamidated].name = "[M+zH]+ x-CO"; + fragmentions[cyclic_precursor_ion_co_loss_and_deamidated].massdifference = PRECURSOR_ION_CYCLIC - CO - NH3 + adductshift; + fragmentions[cyclic_precursor_ion_co_loss_and_deamidated].parent = cyclic_precursor_ion_co_loss; // initialize cyclic precursor ion - CO - H2O - NH3 - fragmentions[cyclic_precursor_ion_co_loss_water_and_ammonia_loss].nterminal = false; - fragmentions[cyclic_precursor_ion_co_loss_water_and_ammonia_loss].cterminal = false; - fragmentions[cyclic_precursor_ion_co_loss_water_and_ammonia_loss].name = "[M+zH]+ *x-CO"; - fragmentions[cyclic_precursor_ion_co_loss_water_and_ammonia_loss].massdifference = PRECURSOR_ION_CYCLIC - CO - H2O - NH3; - fragmentions[cyclic_precursor_ion_co_loss_water_and_ammonia_loss].parent = cyclic_precursor_ion_co_loss; + fragmentions[cyclic_precursor_ion_co_loss_and_dehydrated_and_deamidated].nterminal = false; + fragmentions[cyclic_precursor_ion_co_loss_and_dehydrated_and_deamidated].cterminal = false; + fragmentions[cyclic_precursor_ion_co_loss_and_dehydrated_and_deamidated].name = "[M+zH]+ *x-CO"; + fragmentions[cyclic_precursor_ion_co_loss_and_dehydrated_and_deamidated].massdifference = PRECURSOR_ION_CYCLIC - CO - H2O - NH3 + adductshift; + fragmentions[cyclic_precursor_ion_co_loss_and_dehydrated_and_deamidated].parent = cyclic_precursor_ion_co_loss; // initialize MS N-terminal ion H+ fragmentions[ms_nterminal_ion_hplus].nterminal = true; @@ -554,7 +594,7 @@ void cFragmentIons::store(ofstream& os) { os.write((char *)&size, sizeof(int)); for (map::iterator it = fragmentions.begin(); it != fragmentions.end(); ++it) { os.write((char *)&it->first, sizeof(fragmentIonType)); - os.write((char *)&it->second, sizeof(fragmentDescription)); + it->second.store(os); } } @@ -568,7 +608,7 @@ void cFragmentIons::load(ifstream& is) { fragmentions.clear(); for (int i = 0; i < size; i++) { is.read((char *)&iontype, sizeof(fragmentIonType)); - is.read((char *)&description, sizeof(fragmentDescription)); + description.load(is); fragmentions[iontype] = description; } } @@ -605,3 +645,130 @@ void initializeFragmentIonsForDeNovoGraphOfLinearPolysaccharide(vector& modifications, string& errormessage, bool ignoreerrors) { + string s; + fragmentDescription modification; + size_t pos; + double mass; + + bool error = false; + errormessage = ""; + cSummaryFormula formula; + + modifications.clear(); + while (stream.good()) { + getline(stream,s); + + // skip a comment + if ((s.length() > 0) && (s[0] == '#')) { + continue; + } + + // replaces commas with dots + pos = s.find(','); + while (pos != string::npos) { + s.replace(pos, 1, "."); + pos = s.find(','); + } + + modification.clear(); + + // load the name + pos = s.find('\t'); + if (pos != string::npos) { + modification.name = s.substr(0, pos); + s = s.substr(pos + 1); + } + else { + break; + } + + // load summary + pos = s.find('\t'); + if (pos != string::npos) { + modification.summary = s.substr(0, pos); + s = s.substr(pos + 1); + } + else { + break; + } + + // load the mass (unused !) + pos = s.find('\t'); + if (pos != string::npos) { + sscanf_s(s.substr(0, pos).c_str(), "%lf", &mass); + s = s.substr(pos + 1); + } + else { + break; + } + + + // load N-terminal flag + pos = s.find('\t'); + if (pos != string::npos) { + modification.nterminal = (s.substr(0, pos).compare("0") == 0)?false:true; + s = s.substr(pos + 1); + } + else { + break; + } + + + // load C-terminal flag + #if OS_TYPE == UNX + if ((s.size() > 0) && (s.back() == '\r')) { + s = s.substr(0, s.size() - 1); + } + #endif + modification.cterminal = (s.compare("0") == 0)?false:true; + + + // calculate mass from the summary + formula.clear(); + formula.setFormula(modification.summary); + if (formula.isValid(errormessage)) { + modification.massdifference = formula.getMass(); + } + else { + if (!ignoreerrors) { + error = true; + break; + } + } + + modifications.push_back(modification); + + } + + if (!ignoreerrors && error) { + return -1; + } + + return 0; +} + + +void storeModificationsToPlainTextStream(ofstream &stream, vector& modifications) { + for (int i = 0; i < (int)modifications.size(); i++) { + stream << removeWhiteSpacesExceptSpaces(modifications[i].name) << "\t"; + stream << removeWhiteSpacesExceptSpaces(modifications[i].summary) << "\t"; + stream << std::fixed << std::setprecision(10) << modifications[i].massdifference << "\t"; + + if (modifications[i].nterminal) { + stream << 1 << "\t"; + } + else { + stream << 0 << "\t"; + } + + if (modifications[i].cterminal) { + stream << 1 << endl; + } + else { + stream << 0 << endl; + } + } +} + diff --git a/CycloBranch/core/cFragmentIons.h b/CycloBranch/core/cFragmentIons.h index 66cda9b..aab7545 100644 --- a/CycloBranch/core/cFragmentIons.h +++ b/CycloBranch/core/cFragmentIons.h @@ -9,8 +9,8 @@ #include #include +#include #include -#include #include #include #include @@ -108,35 +108,6 @@ const double PRECURSOR_ION = Hplus + H2O; const double PRECURSOR_ION_CYCLIC = Hplus; -/** - \brief The types of peptides supported by the application. -*/ -enum peptideType { - linear = 0, - cyclic = 1, - branched = 2, - lasso = 3, - linearpolysaccharide = 4, - other = 5 -}; - - -/** - \brief Convert a string to peptide type. - \param s string - \retval peptideType type of peptide -*/ -peptideType getPeptideTypeFromString(string s); - - -/** - \brief Convert the peptide type to a string. - \param peptidetype type of peptide - \retval string string -*/ -string getStringFromPeptideType(peptideType peptidetype); - - /** \brief Register peptideType by Qt. */ @@ -144,78 +115,90 @@ Q_DECLARE_METATYPE(peptideType); /** - \brief Convert single charged mz ratio to multiple charged mz ratio. - \param mass single charged mz ratio - \param charge new charge - \retval double multiple charged mzratio + \brief Get mzratio from neutral mass. + \param neutralmass neutral mass + \param charge charge + \retval double mzratio */ -double charge(double mass, int charge); +double charge(double neutralmass, int charge); /** - \brief Convert multiple charged mz ratio to single charged mz ratio. - \param mass multiple charged mz ratio - \param charge old charge - \retval double single charged mzratio + \brief Get neutral mass from mzratio. + \param mzratio mzratio + \param charge charge + \retval double neutral mass */ -double uncharge(double mass, int charge); +double uncharge(double mzratio, int charge); /** \brief The types of supported fragment ions. */ enum fragmentIonType { - b_ion = 0, - b_ion_water_loss = 1, - b_ion_ammonia_loss = 2, - b_ion_water_and_ammonia_loss = 3, - a_ion = 4, - a_ion_water_loss = 5, - a_ion_ammonia_loss = 6, - a_ion_water_and_ammonia_loss = 7, - y_ion = 8, - y_ion_water_loss = 9, - y_ion_ammonia_loss = 10, - y_ion_water_and_ammonia_loss = 11, - precursor_ion = 12, - precursor_ion_water_loss = 13, - precursor_ion_ammonia_loss = 14, - precursor_ion_water_and_ammonia_loss = 15, - precursor_ion_co_loss = 16, - precursor_ion_co_loss_water_loss = 17, - precursor_ion_co_loss_ammonia_loss = 18, - precursor_ion_co_loss_water_and_ammonia_loss = 19, - cyclic_precursor_ion = 20, - cyclic_precursor_ion_water_loss = 21, - cyclic_precursor_ion_ammonia_loss = 22, - cyclic_precursor_ion_water_and_ammonia_loss = 23, - cyclic_precursor_ion_co_loss = 24, - cyclic_precursor_ion_co_loss_water_loss = 25, - cyclic_precursor_ion_co_loss_ammonia_loss = 26, - cyclic_precursor_ion_co_loss_water_and_ammonia_loss = 27, - ms_nterminal_ion_hplus = 28, - ms_nterminal_ion_naplus = 29, - ms_nterminal_ion_kplus = 30, - ms_cterminal_ion_hplus = 31, - ms_cterminal_ion_naplus = 32, - ms_cterminal_ion_kplus = 33, - ms_hplus = 34, - ms_naplus = 35, - ms_kplus = 36, - ms_hminus = 37, - ms_3M2Fe5H = 38, - ms_2MFe2H = 39, - ms_3MFe2H = 40, - ms_MFe2H = 41, - ms_3M2Fe6HNa = 42, - ms_2MFe3HNa = 43, - ms_3MFe3HNa = 44, - ms_MFe3HNa = 45, - ms_3M2Fe7H = 46, - ms_2MFe4H = 47, - ms_3MFe4H = 48, - ms_MFe4H = 49, - //b_ion_2H_loss = 34, + a_ion = 1, + a_ion_dehydrated = 2, + a_ion_deamidated = 3, + a_ion_dehydrated_and_deamidated = 4, + b_ion = 5, + b_ion_dehydrated = 6, + b_ion_deamidated = 7, + b_ion_dehydrated_and_deamidated = 8, + c_ion = 9, + c_ion_dehydrated = 10, + c_ion_deamidated = 11, + c_ion_dehydrated_and_deamidated = 12, + x_ion = 13, + x_ion_dehydrated = 14, + x_ion_deamidated = 15, + x_ion_dehydrated_and_deamidated = 16, + y_ion = 17, + y_ion_dehydrated = 18, + y_ion_deamidated = 19, + y_ion_dehydrated_and_deamidated = 20, + z_ion = 21, + z_ion_dehydrated = 22, + z_ion_deamidated = 23, + z_ion_dehydrated_and_deamidated = 24, + precursor_ion = 25, + precursor_ion_dehydrated = 26, + precursor_ion_deamidated = 27, + precursor_ion_dehydrated_and_deamidated = 28, + precursor_ion_co_loss = 29, + precursor_ion_co_loss_and_dehydrated = 30, + precursor_ion_co_loss_and_deamidated = 31, + precursor_ion_co_loss_and_dehydrated_and_deamidated = 32, + cyclic_precursor_ion = 33, + cyclic_precursor_ion_dehydrated = 34, + cyclic_precursor_ion_deamidated = 35, + cyclic_precursor_ion_dehydrated_and_deamidated = 36, + cyclic_precursor_ion_co_loss = 37, + cyclic_precursor_ion_co_loss_and_dehydrated = 38, + cyclic_precursor_ion_co_loss_and_deamidated = 39, + cyclic_precursor_ion_co_loss_and_dehydrated_and_deamidated = 40, + ms_nterminal_ion_hplus = 41, + ms_nterminal_ion_naplus = 42, + ms_nterminal_ion_kplus = 43, + ms_cterminal_ion_hplus = 44, + ms_cterminal_ion_naplus = 45, + ms_cterminal_ion_kplus = 46, + ms_hplus = 47, + ms_naplus = 48, + ms_kplus = 49, + ms_hminus = 50, + ms_3M2Fe5H = 51, + ms_2MFe2H = 52, + ms_3MFe2H = 53, + ms_MFe2H = 54, + ms_3M2Fe6HNa = 55, + ms_2MFe3HNa = 56, + ms_3MFe3HNa = 57, + ms_MFe3HNa = 58, + ms_3M2Fe7H = 59, + ms_2MFe4H = 60, + ms_3MFe4H = 61, + ms_MFe4H = 62, + //b_ion_2H_loss = 63, fragmentIonTypeEnd }; @@ -283,6 +266,14 @@ struct fragmentDescription { \brief The default constructor. */ fragmentDescription() { + clear(); + } + + + /** + \brief Clear the structure. + */ + void clear() { name = ""; summary = ""; massdifference = 0; @@ -359,8 +350,9 @@ class cFragmentIons { \brief The constructor. \param cyclicnterminus true when the N-terminus of a linear peptide is cyclized \param cycliccterminus true when the C-terminus of a linear peptide is cyclized + \param precursoradduct an adduct of a precursor ion */ - cFragmentIons(bool cyclicnterminus, bool cycliccterminus); + cFragmentIons(bool cyclicnterminus, bool cycliccterminus, string& precursoradduct); /** @@ -375,8 +367,9 @@ class cFragmentIons { \brief Recalculate all fragment ion types. \param cyclicnterminus true when the N-terminus of a linear peptide is cyclized \param cycliccterminus true when the C-terminus of a linear peptide is cyclized + \param precursoradduct an adduct of a precursor ion */ - void recalculateFragments(bool cyclicnterminus, bool cycliccterminus); + void recalculateFragments(bool cyclicnterminus, bool cycliccterminus, string& precursoradduct); /** @@ -423,7 +416,7 @@ void initializeFragmentIonsForDeNovoGraphOfTPeptides(vector& fr /** - \brief Initialize fragment ion types for the de novo graph of lasso peptides. + \brief Initialize fragment ion types for the de novo graph of branch-cyclic peptides. \param fragmentions reference to a vector of fragment ion types */ void initializeFragmentIonsForDeNovoGraphOfLassoPeptides(vector& fragmentions); @@ -436,4 +429,24 @@ void initializeFragmentIonsForDeNovoGraphOfLassoPeptides(vector void initializeFragmentIonsForDeNovoGraphOfLinearPolysaccharide(vector& fragmentions); -#endif \ No newline at end of file +/** + \brief Load modifications from a plain text stream. + \param stream reference to an input file stream + \param modifications reference to a vector where modifications will be placed + \param errormessage reference to a string where an error message might be stored + \param ignoreerrors if true errors are ignored + \retval int 0 when modifications were successfully loaded, -1 when an error occurred (\a errormessage is filled up) +*/ +int loadModificationsFromPlainTextStream(ifstream &stream, vector& modifications, string& errormessage, bool ignoreerrors); + + +/** + \brief Store modifications into a plain text stream. + \param stream reference to an output file stream + \param modifications reference to a vector of modifications which will be stored +*/ +void storeModificationsToPlainTextStream(ofstream &stream, vector& modifications); + + +#endif + diff --git a/CycloBranch/core/cParameters.cpp b/CycloBranch/core/cParameters.cpp index a6ee67f..40c8b26 100644 --- a/CycloBranch/core/cParameters.cpp +++ b/CycloBranch/core/cParameters.cpp @@ -9,12 +9,14 @@ cParameters::cParameters() { void cParameters::clear() { + string s = ""; os = 0; - fragmentdefinitions.recalculateFragments(false, false); + fragmentdefinitions.recalculateFragments(false, false, s); peptidetype = linear; peaklistfilename = ""; peaklist.clear(); precursormass = 0; + precursoradduct = ""; precursormasserrortolerance = 5; precursorcharge = 1; fragmentmasserrortolerance = 5; @@ -29,6 +31,8 @@ void cParameters::clear() { maximumbricksincombination = max(max(maximumbricksincombinationbegin, maximumbricksincombinationmiddle), maximumbricksincombinationend); maximumcumulativemass = 0; generatebrickspermutations = true; + modificationsfilename = ""; + searchedmodifications.clear(); maximumnumberofthreads = 1; mode = denovoengine; scoretype = b_ions; @@ -49,9 +53,6 @@ void cParameters::clear() { sequencedatabase.clear(); sequencedatabasefilename = ""; - searchedmodifications.clear(); - searchedmodifications.push_back(fragmentDescription("", 0, "", true, true)); - fragmentionsfordenovograph.clear(); fragmentionsfortheoreticalspectra.clear(); } @@ -63,11 +64,17 @@ int cParameters::checkAndPrepare() { string errormessage = ""; ifstream peakliststream; ifstream bricksdatabasestream; + ifstream modificationsstream; ifstream sequencedatabasestream; regex rx; ePeakListFileFormat peaklistfileformat; string s; + int i; + if (peaklistfilename.empty()) { + error = true; + errormessage = "A peaklist is not specified. Have you configured the engine (Search -> Settings...) ?\n"; + } // peaklist check if (!error) { @@ -94,14 +101,16 @@ int cParameters::checkAndPrepare() { peaklistfileformat = mzXML; } - rx = "\\.[bB][aA][fF]$"; - // Bruker Analysis File - if (regex_search(peaklistfilename, rx)) { - peaklistfileformat = baf; - } + #if OS_TYPE == WIN + rx = "\\.[bB][aA][fF]$"; + // Bruker Analysis File + if (regex_search(peaklistfilename, rx)) { + peaklistfileformat = baf; + } + #endif } - catch (std::regex_error& e) { + catch (regex_error& e) { error = true; errormessage = "cParameters::checkAndPrepare: regex_search failed, error no. " + to_string((int)e.code()) + "\n"; } @@ -118,17 +127,31 @@ int cParameters::checkAndPrepare() { break; case mzML: case mzXML: - *os << "Converting the file " + peaklistfilename + " to .mgf ... "; - s = "External\\any2mgf.bat \"" + peaklistfilename + "\""; - if (system(s.c_str()) != 0) { - error = true; - errormessage = "The file cannot be converted.\n"; - errormessage += "Does the file '" + peaklistfilename + "' exist ?\n"; - errormessage += "Do you have OpenMS installed ?\n"; - errormessage += "Do you have path to the OpenMS/bin/FileConverter.exe in your PATH variable ?\n"; - errormessage += "Is the directory with the file '" + peaklistfilename + "' writable ?\n"; - errormessage += "Do you have 'any2mgf.bat' file located in the 'External' folder ?\n"; - } + *os << "Converting the file " + peaklistfilename + " to mgf ... "; + + #if OS_TYPE == UNX + s = linuxinstalldir.toStdString() + "External/linux/any2mgf.sh " + peaklistfilename; + if (system(s.c_str()) != 0) { + error = true; + errormessage = "The file cannot be converted.\n"; + errormessage += "Does the file '" + peaklistfilename + "' exist ?\n"; + errormessage += "Is the directory with the file '" + peaklistfilename + "' writable ?\n"; + errormessage += "Do you have FileConverter installed (sudo apt-get install topp) ?\n"; + errormessage += "Do you have 'any2mgf.sh' file located in '" + linuxinstalldir.toStdString() + "External/linux' folder ?\n"; + errormessage += "Is the file 'any2mgf.sh' executable (sudo chmod +x " + linuxinstalldir.toStdString() + "External/linux/any2mgf.sh) ? \n"; + } + #else + s = "External\\windows\\any2mgf.bat \"" + peaklistfilename + "\""; + if (system(s.c_str()) != 0) { + error = true; + errormessage = "The file cannot be converted.\n"; + errormessage += "Does the file '" + peaklistfilename + "' exist ?\n"; + errormessage += "Is the directory with the file '" + peaklistfilename + "' writable ?\n"; + errormessage += "Do you have FileConverter installed (OpenMS 1.11) ?\n"; + errormessage += "Do you have a path to FileConverter in your PATH variable (e.g., 'C:/Program Files/OpenMS-1.11/bin') ?\n"; + errormessage += "Do you have 'any2mgf.bat' file located in the '" + appname.toStdString() + "/External/windows' folder ?\n"; + } + #endif if (!error) { *os << "ok" << endl << endl; @@ -136,22 +159,24 @@ int cParameters::checkAndPrepare() { } break; case baf: - *os << "Converting the file " + peaklistfilename + " ... "; - s = "External\\baf2csv.bat \"" + peaklistfilename + "\""; - if (system(s.c_str()) != 0) { - error = true; - errormessage = "The file cannot be converted.\n"; - errormessage += "Does the file '" + peaklistfilename + "' exist ?\n"; - errormessage += "Do you have Bruker Daltonik's CompassXport installed ?\n"; - errormessage += "Do you have path to the CompassXport.exe in your PATH variable ?\n"; - errormessage += "Is the directory with the file '" + peaklistfilename + "' writable ?\n"; - errormessage += "Do you have 'baf2csv.bat' file located in the 'External' folder ?\n"; - } + #if OS_TYPE == WIN + *os << "Converting the file " + peaklistfilename + " ... "; + s = "External\\windows\\baf2csv.bat \"" + peaklistfilename + "\""; + if (system(s.c_str()) != 0) { + error = true; + errormessage = "The file cannot be converted.\n"; + errormessage += "Does the file '" + peaklistfilename + "' exist ?\n"; + errormessage += "Do you have Bruker Daltonik's CompassXport installed ?\n"; + errormessage += "Do you have path to the CompassXport.exe in your PATH variable ?\n"; + errormessage += "Is the directory with the file '" + peaklistfilename + "' writable ?\n"; + errormessage += "Do you have 'baf2csv.bat' file located in the 'External/windows' folder ?\n"; + } - if (!error) { - *os << "ok" << endl << endl; - peakliststream.open(peaklistfilename + ".csv"); - } + if (!error) { + *os << "ok" << endl << endl; + peakliststream.open(peaklistfilename + ".csv"); + } + #endif break; default: break; @@ -179,7 +204,9 @@ int cParameters::checkAndPrepare() { peaklist.loadFromMGFStream(peakliststream); break; case baf: - peaklist.loadFromBAFStream(peakliststream); + #if OS_TYPE == WIN + peaklist.loadFromBAFStream(peakliststream); + #endif break; default: break; @@ -206,7 +233,7 @@ int cParameters::checkAndPrepare() { if (os) { *os << "Loading the database of bricks... "; } - if (bricksdatabase.loadFromPlainTextStream(bricksdatabasestream, errormessage) == -1) { + if (bricksdatabase.loadFromPlainTextStream(bricksdatabasestream, errormessage, false) == -1) { error = true; } else { @@ -245,6 +272,53 @@ int cParameters::checkAndPrepare() { } + // modifications check + if (!error && ((mode == denovoengine) || (mode == singlecomparison) || (mode == databasesearch))) { + + searchedmodifications.clear(); + + if ((peptidetype != cyclic) && (modificationsfilename.compare("") != 0)) { + modificationsstream.open(modificationsfilename); + if (!modificationsstream.good()) { + error = true; + errormessage = "Cannot open the file '" + modificationsfilename + "'."; + } + else { + if (os) { + *os << "Loading modifications... "; + } + if (loadModificationsFromPlainTextStream(modificationsstream, searchedmodifications, errormessage, false) == -1) { + error = true; + } + else { + if (os) { + *os << "ok" << endl << endl; + } + } + } + modificationsstream.close(); + } + + fragmentDescription fd; + fd.nterminal = true; + fd.cterminal = true; + searchedmodifications.insert(searchedmodifications.begin(), fd); + + } + + + // precursor adduct check + if (!error && ((mode == denovoengine) || (mode == singlecomparison) || (mode == databasesearch))) { + cSummaryFormula formula; + formula.clear(); + formula.setFormula(precursoradduct); + if (!formula.isValid(errormessage)) { + error = true; + errormessage = "Precursor Ion Adduct: " + errormessage; + } + } + + // sequencedatabase check if (!error && ((mode == databasesearch) || (mode == dereplication))) { @@ -298,6 +372,20 @@ int cParameters::checkAndPrepare() { } } + + // check theoretical fragments in positive/negative mode + if (!error && (mode == dereplication)) { + i = 0; + while (i < (int)fragmentionsfortheoreticalspectra.size()) { + if (fragmentdefinitions[fragmentionsfortheoreticalspectra[i]].positive != (precursorcharge > 0)) { + fragmentionsfortheoreticalspectra.erase(fragmentionsfortheoreticalspectra.begin() + i); + } + else { + i++; + } + } + } + // report errors and return if (error) { @@ -329,7 +417,7 @@ string cParameters::printToString() { s += "Branched\n"; break; case lasso: - s += "Lasso\n"; + s += "Branch-cyclic\n"; break; case linearpolysaccharide: s += "Linear polysaccharide (beta version)\n"; @@ -342,7 +430,8 @@ string cParameters::printToString() { } s += "Peaklist File: " + peaklistfilename + "\n"; s += "Precursor Mass: " + to_string(precursormass) + "\n"; - s += "Precursor Charge: " + to_string(precursorcharge) + "\n"; + s += "Precursor Ion Adduct: " + precursoradduct + "\n"; + s += "Charge: " + to_string(precursorcharge) + "\n"; s += "Precursor Mass Error Tolerance: " + to_string(precursormasserrortolerance) + "\n"; s += "Fragment Mass Error Tolerance: " + to_string(fragmentmasserrortolerance) + "\n"; s += "Fragment Mass Error Tolerance for Deisotoping: " + to_string(masserrortolerancefordeisotoping) + "\n"; @@ -356,13 +445,35 @@ string cParameters::printToString() { s += generatebrickspermutations ? "on" : "off"; s += "\n"; - s += "N-terminal and C-terminal Modifications:\n"; - for (int i = 1; i < (int)searchedmodifications.size(); i++) { - s += searchedmodifications[i].name + ", " + to_string(searchedmodifications[i].massdifference) + ", "; - s += searchedmodifications[i].nterminal ? "N-terminal, " : "-, "; - s += searchedmodifications[i].cterminal ? "C-terminal" : "-"; - s += "\n"; + s += "N-/C-terminal Modifications File: " + modificationsfilename + "\n"; + + s += "Action with Blind Paths in De Novo Graph: "; + switch (blindedges) { + case 0: + s += "none (you can see a complete de novo graph)"; + break; + case 1: + s += "remove (speed up the search)"; + break; + case 2: + s += "connect (allow detection of sequence tags)"; + break; + default: + break; } + s += "\n"; + + s += "Cyclic N-terminus: "; + s += cyclicnterminus ? "on" : "off"; + s += "\n"; + + s += "Cyclic C-terminus: "; + s += cycliccterminus ? "on" : "off"; + s += "\n"; + + s += "Enable Scrambling: "; + s += enablescrambling ? "on" : "off"; + s += "\n"; s += "Mode: "; switch ((modeType)mode) { @@ -383,6 +494,8 @@ string cParameters::printToString() { } s += "\n"; + s += "Sequence Database File: " + sequencedatabasefilename + "\n"; + s += "Maximum Number of Threads: " + to_string(maximumnumberofthreads) + "\n"; s += "Score Type: "; @@ -390,10 +503,10 @@ string cParameters::printToString() { case b_ions: s += "Number of b-ions"; break; - case b_ions_and_b_water_loss_ions: + case b_ions_and_b_dehydrated_ions: s += "Number of b-ions + dehydrated b-ions"; break; - case b_ions_and_b_ammonia_loss_ions: + case b_ions_and_b_deamidated_ions: s += "Number of b-ions + deamidated b-ions"; break; case y_ions_and_b_ions: @@ -433,36 +546,6 @@ string cParameters::printToString() { s += clearhitswithoutparent ? "on" : "off"; s += "\n"; - s += "Cyclic N-terminus: "; - s += cyclicnterminus ? "on" : "off"; - s += "\n"; - - s += "Cyclic C-terminus: "; - s += cycliccterminus ? "on" : "off"; - s += "\n"; - - s += "Enable Scrambling: "; - s += enablescrambling ? "on" : "off"; - s += "\n"; - - s += "Action with Edges Forming Blind Paths: "; - switch (blindedges) { - case 0: - s += "none (you can see a complete de novo graph)"; - break; - case 1: - s += "remove (speed up the search)"; - break; - case 2: - s += "connect (allow detection of sequence tags)"; - break; - default: - break; - } - s += "\n"; - - s += "Sequence Database File: " + sequencedatabasefilename + "\n"; - s += "Searched Peptide Sequence: " + originalsearchedsequence + "\n"; s += "N-terminal Modification of Searched Peptide Sequence: " + searchedsequenceNtermmodif + "\n"; s += "C-terminal Modification of Searched Peptide Sequence: " + searchedsequenceCtermmodif + "\n"; @@ -481,10 +564,10 @@ void cParameters::setOutputStream(cMainThread& os) { void cParameters::updateFragmentDefinitions() { if (peptidetype == linear) { - fragmentdefinitions.recalculateFragments(cyclicnterminus, cycliccterminus); + fragmentdefinitions.recalculateFragments(cyclicnterminus, cycliccterminus, precursoradduct); } else { - fragmentdefinitions.recalculateFragments(false, false); + fragmentdefinitions.recalculateFragments(false, false, precursoradduct); } } @@ -500,6 +583,9 @@ void cParameters::store(ofstream& os) { peaklist.store(os); os.write((char *)&precursormass, sizeof(double)); + + storeString(precursoradduct, os); + os.write((char *)&precursormasserrortolerance, sizeof(double)); os.write((char *)&precursorcharge, sizeof(int)); os.write((char *)&fragmentmasserrortolerance, sizeof(double)); @@ -516,6 +602,14 @@ void cParameters::store(ofstream& os) { os.write((char *)&maximumbricksincombination, sizeof(int)); os.write((char *)&maximumcumulativemass, sizeof(double)); os.write((char *)&generatebrickspermutations, sizeof(bool)); + storeString(modificationsfilename, os); + + size = (int)searchedmodifications.size(); + os.write((char *)&size, sizeof(int)); + for (int i = 0; i < (int)searchedmodifications.size(); i++) { + searchedmodifications[i].store(os); + } + os.write((char *)&maximumnumberofthreads, sizeof(int)); os.write((char *)&mode, sizeof(modeType)); os.write((char *)&scoretype, sizeof(scoreType)); @@ -539,12 +633,6 @@ void cParameters::store(ofstream& os) { storeString(sequencedatabasefilename, os); sequencedatabase.store(os); - size = (int)searchedmodifications.size(); - os.write((char *)&size, sizeof(int)); - for (int i = 0; i < (int)searchedmodifications.size(); i++) { - searchedmodifications[i].store(os); - } - size = (int)fragmentionsfordenovograph.size(); os.write((char *)&size, sizeof(int)); for (int i = 0; i < (int)fragmentionsfordenovograph.size(); i++) { @@ -572,6 +660,9 @@ void cParameters::load(ifstream& is) { peaklist.load(is); is.read((char *)&precursormass, sizeof(double)); + + loadString(precursoradduct, is); + is.read((char *)&precursormasserrortolerance, sizeof(double)); is.read((char *)&precursorcharge, sizeof(int)); is.read((char *)&fragmentmasserrortolerance, sizeof(double)); @@ -588,6 +679,14 @@ void cParameters::load(ifstream& is) { is.read((char *)&maximumbricksincombination, sizeof(int)); is.read((char *)&maximumcumulativemass, sizeof(double)); is.read((char *)&generatebrickspermutations, sizeof(bool)); + loadString(modificationsfilename, is); + + is.read((char *)&size, sizeof(int)); + searchedmodifications.resize(size); + for (int i = 0; i < (int)searchedmodifications.size(); i++) { + searchedmodifications[i].load(is); + } + is.read((char *)&maximumnumberofthreads, sizeof(int)); is.read((char *)&mode, sizeof(modeType)); is.read((char *)&scoretype, sizeof(scoreType)); @@ -611,12 +710,6 @@ void cParameters::load(ifstream& is) { loadString(sequencedatabasefilename, is); sequencedatabase.load(is); - is.read((char *)&size, sizeof(int)); - searchedmodifications.resize(size); - for (int i = 0; i < (int)searchedmodifications.size(); i++) { - searchedmodifications[i].load(is); - } - is.read((char *)&size, sizeof(int)); fragmentionsfordenovograph.resize(size); for (int i = 0; i < (int)fragmentionsfordenovograph.size(); i++) { diff --git a/CycloBranch/core/cParameters.h b/CycloBranch/core/cParameters.h index 119a10d..923b1d1 100644 --- a/CycloBranch/core/cParameters.h +++ b/CycloBranch/core/cParameters.h @@ -9,6 +9,7 @@ #include #include +#include "core/utilities.h" #include "core/cPeaksList.h" #include "core/cBricksDatabase.h" #include "core/cSequenceDatabase.h" @@ -16,6 +17,7 @@ class cMainThread; using namespace std; +using namespace boost; /** @@ -81,6 +83,12 @@ class cParameters { double precursormass; + /** + \brief An adduct of a precursor ion. + */ + string precursoradduct; + + /** \brief Precursor mass error tolerance (ppm). */ @@ -165,6 +173,12 @@ class cParameters { bool generatebrickspermutations; + /** + \brief A file with modifications. + */ + string modificationsfilename; + + /** \brief Maximum number of threads. */ @@ -331,7 +345,7 @@ class cParameters { /** - \brief Update definitions of fragment ions when \a cyclicnterminus or \a cycliccterminus have been changed. + \brief Update definitions of fragment ions when \a cyclicnterminus, \a cycliccterminus or \a precursoradduct have been changed. */ void updateFragmentDefinitions(); diff --git a/CycloBranch/core/cPeak.h b/CycloBranch/core/cPeak.h index 478e33c..cf38944 100644 --- a/CycloBranch/core/cPeak.h +++ b/CycloBranch/core/cPeak.h @@ -20,8 +20,8 @@ using namespace std; */ enum scoreType { b_ions = 0, - b_ions_and_b_water_loss_ions = 1, - b_ions_and_b_ammonia_loss_ions = 2, + b_ions_and_b_dehydrated_ions = 1, + b_ions_and_b_deamidated_ions = 2, y_ions_and_b_ions = 3, y_ions = 4, weighted_intensity = 5, diff --git a/CycloBranch/core/cPeaksList.cpp b/CycloBranch/core/cPeaksList.cpp index 55431ef..bef1b46 100644 --- a/CycloBranch/core/cPeaksList.cpp +++ b/CycloBranch/core/cPeaksList.cpp @@ -2,16 +2,21 @@ #include "gui/cMainThread.h" -bool comparePeakMasses(cPeak& a, cPeak& b) { +bool comparePeakMasses(const cPeak& a, const cPeak& b) { return (a.mzratio < b.mzratio); } -bool comparePeakIntensitiesDesc(cPeak& a, cPeak& b) { +bool comparePeakIntensitiesDesc(const cPeak& a, const cPeak& b) { return (a.intensity > b.intensity); } +bool comparePeakRemoveMeFlag(const cPeak& a, const cPeak& b) { + return (a.removeme < b.removeme); +} + + bool isInPpmMassErrorTolerance(double experimentalmass, double theoreticalmass, double tolerance) { double errortolerance = experimentalmass*tolerance*0.000001f; return abs(experimentalmass - theoreticalmass) <= errortolerance; @@ -28,6 +33,17 @@ cPeaksList::cPeaksList() { } +cPeaksList::cPeaksList(const cPeaksList& peakslist) { + *this = peakslist; +} + + +cPeaksList& cPeaksList::operator=(const cPeaksList& peakslist) { + peaks = peakslist.peaks; + return *this; +} + + void cPeaksList::clear() { peaks.clear(); } @@ -201,6 +217,11 @@ void cPeaksList::sortbyMass(int limit) { } +void cPeaksList::sortbyIntensityDesc() { + sort(peaks.begin(), peaks.end(), comparePeakIntensitiesDesc); +} + + int cPeaksList::normalizeIntenzity() { double maximum = 0.0f; for (int i = 0; i < (int)peaks.size(); i++) { @@ -234,9 +255,9 @@ void cPeaksList::cropIntenzity(double minimumrelativeintensitythreshold) { } -void cPeaksList::cropMinimumMZRatio(double minimummz) { +void cPeaksList::cropMinimumMZRatio(double minimummz, double errortolerance) { while ((int)peaks.size() > 0) { - if (peaks[0].mzratio < minimummz) { + if ((peaks[0].mzratio < minimummz) && (!isInPpmMassErrorTolerance(peaks[0].mzratio, minimummz, errortolerance))) { peaks.erase(peaks.begin()); } else { @@ -246,9 +267,9 @@ void cPeaksList::cropMinimumMZRatio(double minimummz) { } -void cPeaksList::cropMaximumMZRatio(double maximummz) { +void cPeaksList::cropMaximumMZRatio(double maximummz, double errortolerance) { while ((int)peaks.size() > 0) { - if (peaks.back().mzratio > maximummz) { + if ((peaks.back().mzratio > maximummz) && (!isInPpmMassErrorTolerance(peaks.back().mzratio, maximummz, errortolerance))) { peaks.erase(peaks.begin() + peaks.size() - 1); } else { @@ -269,8 +290,12 @@ void cPeaksList::resize(int size) { double cPeaksList::getMinimumMZRatio() { - double minimum = DBL_MAX; - for (int i = 0; i < (int)peaks.size(); i++) { + if (peaks.size() == 0) { + return 0; + } + + double minimum = peaks[0].mzratio; + for (int i = 1; i < (int)peaks.size(); i++) { if (peaks[i].mzratio < minimum) { minimum = peaks[i].mzratio; } @@ -301,8 +326,8 @@ void cPeaksList::removeIsotopes(int maximumcharge, double fragmentmasserrortoler peaks[i].isotope = false; } for (i = 0; i < (int)peaks.size(); i++) { - for (int j = 1; j <= maximumcharge; j++) { - pos = find(charge(peaks[i].mzratio + Hplus, j), fragmentmasserrortolerance); + for (int j = 1; j <= abs(maximumcharge); j++) { + pos = find(charge(peaks[i].mzratio, (maximumcharge > 0)?j:-j), fragmentmasserrortolerance); if (pos != -1) { if (peaks[pos].intensity < peaks[i].intensity) { peaks[pos].isotope = true; @@ -355,31 +380,31 @@ int cPeaksList::find(double mzratio, double fragmentmasserrortolerance) { } -void cPeaksList::eraseAll(double mzratio) { +void cPeaksList::findObsolete(double mzratio) { int left, right, middle; - for (int i = 0; i < (int)peaks.size(); i++) { - left = 0; - right = (int)peaks.size() - 1; - while (left <= right) { - middle = (left + right) / 2; - if (abs(mzratio - peaks[middle].mzratio) < 0.00000001) { - while ((middle > 0) && (abs(mzratio - peaks[middle - 1].mzratio) < 0.00000001)) { - middle--; - } - while ((peaks.size() > 0) && (middle < (int)peaks.size()) && (abs(mzratio - peaks[middle].mzratio) < 0.00000001)) { - peaks.erase(peaks.begin()+middle); - } - return; - } - if (mzratio < peaks[middle].mzratio) { - right = middle - 1; + + left = 0; + right = (int)peaks.size() - 1; + while (left <= right) { + middle = (left + right) / 2; + if (abs(mzratio - peaks[middle].mzratio) < 0.00000001) { + while ((middle > 0) && (abs(mzratio - peaks[middle - 1].mzratio) < 0.00000001)) { + middle--; } - else { - left = middle + 1; + while ((middle < (int)peaks.size()) && (abs(mzratio - peaks[middle].mzratio) < 0.00000001)) { + peaks[middle].removeme = true; + middle++; } + return; + } + if (mzratio < peaks[middle].mzratio) { + right = middle - 1; + } + else { + left = middle + 1; } } - return; + } @@ -391,22 +416,21 @@ void cPeaksList::remove(int position) { void cPeaksList::removeChargeVariants(int maximumcharge, double fragmentmasserrortolerance) { - if (maximumcharge == 1) { + if (abs(maximumcharge) == 1) { return; } sortbyMass(); - double uncharged, charged; - for (int i = maximumcharge; i > 1; i--) { + double charged; + for (int i = abs(maximumcharge); i > 1; i--) { for (int j = i - 1; j >= 1; j--) { for (int k = 0; k < (int)peaks.size(); k++) { if (peaks[k].removeme) { continue; } - uncharged = uncharge(peaks[k].mzratio, i); - charged = charge(uncharged, j); + charged = charge(uncharge(peaks[k].mzratio, (maximumcharge > 0)?i:-i), (maximumcharge > 0)?j:-j); for (int m = k + 1; m < (int)peaks.size(); m++) { if (peaks[m].removeme) { @@ -428,37 +452,36 @@ void cPeaksList::removeChargeVariants(int maximumcharge, double fragmentmasserro void cPeaksList::removeNeutralLoss(double loss, int maximumcharge, double fragmentmasserrortolerance) { - sortbyMass(); int found = -1; - for (int i = 1; i <= maximumcharge; i++) { + //for (int i = 1; i <= maximumcharge; i++) { for (int j = 0; j < (int)peaks.size(); j++) { found = find(peaks[j].mzratio + loss, fragmentmasserrortolerance); if ((found != -1) && (peaks[found].intensity < peaks[j].intensity)) { peaks[found].removeme = true; } } - } + //} removeObsolete(); - } void cPeaksList::removeObsolete() { + sort(peaks.begin(), peaks.end(), comparePeakRemoveMeFlag); - int i = 0; - while (i < (int)peaks.size()) { - if (peaks[i].removeme) { - //cout << peaks[i].mzratio << endl; - peaks.erase(peaks.begin()+i); - } - else { - i++; - } + int items = 0; + int size = (int)peaks.size(); + while ((items < size) && (peaks[size - items - 1].removeme)) { + items++; } + if (items > 0) { + peaks.erase(peaks.begin() + size - items, peaks.end()); + } + + sortbyMass(); } diff --git a/CycloBranch/core/cPeaksList.h b/CycloBranch/core/cPeaksList.h index 1726347..2fbb41e 100644 --- a/CycloBranch/core/cPeaksList.h +++ b/CycloBranch/core/cPeaksList.h @@ -27,7 +27,7 @@ class cMainThread; \param b second peak \retval bool true when the mz ratio of the peak \a a is lower than the mz ratio of the peak \a b */ -bool comparePeakMasses(cPeak& a, cPeak& b); +bool comparePeakMasses(const cPeak& a, const cPeak& b); /** @@ -36,7 +36,16 @@ bool comparePeakMasses(cPeak& a, cPeak& b); \param b second peak \retval bool true when the intensity of the peak \a a is bigger than the intensity of the peak \a b */ -bool comparePeakIntensitiesDesc(cPeak& a, cPeak& b); +bool comparePeakIntensitiesDesc(const cPeak& a, const cPeak& b); + + +/** + \brief Compare two peaks by \a removeme flag. + \param a first peak + \param b second peak + \retval bool true when the \a removeme flag of the peak \a a is lower than the \a removeme flag of the peak \a b +*/ +bool comparePeakRemoveMeFlag(const cPeak& a, const cPeak& b); /** @@ -74,6 +83,20 @@ class cPeaksList { cPeaksList(); + /** + \brief The copy constructor. + \param peakslist reference to a cPeaksList + */ + cPeaksList(const cPeaksList& peakslist); + + + /** + \brief Overloaded operator=. + \param peakslist reference to a cPeaksList + */ + cPeaksList& operator=(const cPeaksList& peakslist); + + /** \brief Clear the peak list. */ @@ -137,6 +160,12 @@ class cPeaksList { void sortbyMass(int limit = -1); + /** + \brief Sort the peaks by intensity in the descending order. + */ + void sortbyIntensityDesc(); + + /** \brief Normalize intensities of peaks. \retval int 0 == success, -1 == maximum intensity <= 0 @@ -154,15 +183,17 @@ class cPeaksList { /** \brief Crop mz ratio lower than a threshold. \param minimummz minimum threshold of mz ratio + \param errortolerance mz error tolerance in ppm */ - void cropMinimumMZRatio(double minimummz); + void cropMinimumMZRatio(double minimummz, double errortolerance); /** \brief Crop mz ratio bigger than a threshold. \param maximummz maximum threshold of mz ratio + \param errortolerance mz error tolerance in ppm */ - void cropMaximumMZRatio(double maximummz); + void cropMaximumMZRatio(double maximummz, double errortolerance); /** @@ -213,10 +244,10 @@ class cPeaksList { /** - \brief Erase all peaks having specified m/z ratio. - \param mzratio mz ratio of peaks which will be erased + \brief Find all peaks having a specified \a mzratio and mark them with the flag \a removeme == true. + \param mzratio mz ratio of peaks which will be marked */ - void eraseAll(double mzratio); + void findObsolete(double mzratio); /** @@ -282,4 +313,4 @@ class cPeaksList { }; -#endif \ No newline at end of file +#endif diff --git a/CycloBranch/core/cSequence.cpp b/CycloBranch/core/cSequence.cpp index b488a28..26dcbbb 100644 --- a/CycloBranch/core/cSequence.cpp +++ b/CycloBranch/core/cSequence.cpp @@ -67,32 +67,32 @@ void cSequence::setPeptideType(peptideType peptidetype) { } -void cSequence::setSequence(string& sequence) { +void cSequence::setSequence(const string& sequence) { this->sequence = sequence; } -void cSequence::setName(string& name) { +void cSequence::setName(const string& name) { this->name = name; } -void cSequence::setReference(string& reference) { +void cSequence::setReference(const string& reference) { this->reference = reference; } -void cSequence::setNTterminalModification(string& modification) { +void cSequence::setNTterminalModification(const string& modification) { nterminalmodification = modification; } -void cSequence::setCTterminalModification(string& modification) { +void cSequence::setCTterminalModification(const string& modification) { cterminalmodification = modification; } -void cSequence::setBranchModification(string& modification) { +void cSequence::setBranchModification(const string& modification) { branchmodification = modification; } @@ -165,8 +165,7 @@ string cSequence::getNameWithReferenceAsHTMLString() { } } - catch (std::regex_error& e) { - e; + catch (regex_error& /*e*/) { // nothing to do } @@ -178,7 +177,7 @@ string cSequence::getNameWithReferenceAsHTMLString() { } -void cSequence::setSummaryFormula(string& formula) { +void cSequence::setSummaryFormula(const string& formula) { summary.setFormula(formula); } diff --git a/CycloBranch/core/cSequence.h b/CycloBranch/core/cSequence.h index d23d904..bd2d2df 100644 --- a/CycloBranch/core/cSequence.h +++ b/CycloBranch/core/cSequence.h @@ -17,6 +17,7 @@ using namespace std; +using namespace boost; /** @@ -101,42 +102,42 @@ class cSequence { \brief Set sequence. \param sequence sequence */ - void setSequence(string& sequence); + void setSequence(const string& sequence); /** \brief Set name. \param name name */ - void setName(string& name); + void setName(const string& name); /** \brief Set reference. \param reference reference */ - void setReference(string& reference); + void setReference(const string& reference); /** \brief Set N-terminal modification. \param modification name of an N-terminal modification */ - void setNTterminalModification(string& modification); + void setNTterminalModification(const string& modification); /** \brief Set C-terminal modification. \param modification name of a C-terminal modification */ - void setCTterminalModification(string& modification); + void setCTterminalModification(const string& modification); /** \brief Set branch modification. \param modification name of a branch modification */ - void setBranchModification(string& modification); + void setBranchModification(const string& modification); /** @@ -171,7 +172,7 @@ class cSequence { \brief Set the summary formula. \param formula summary formula */ - void setSummaryFormula(string& formula); + void setSummaryFormula(const string& formula); /** @@ -183,4 +184,4 @@ class cSequence { }; -#endif \ No newline at end of file +#endif diff --git a/CycloBranch/core/cSequenceDatabase.cpp b/CycloBranch/core/cSequenceDatabase.cpp index 0f364d1..00a0748 100644 --- a/CycloBranch/core/cSequenceDatabase.cpp +++ b/CycloBranch/core/cSequenceDatabase.cpp @@ -38,7 +38,7 @@ void cSequenceDatabase::loadFromPlainTextStream(ifstream &stream) { if (type.compare("branched") == 0) { sequence.setPeptideType(branched); } - if (type.compare("lasso") == 0) { + if (type.compare("branch-cyclic") == 0) { sequence.setPeptideType(lasso); } if (type.compare("linearpolysaccharide") == 0) { @@ -124,6 +124,11 @@ void cSequenceDatabase::loadFromPlainTextStream(ifstream &stream) { } // load reference + #if OS_TYPE == UNX + if ((s.size() > 0) && (s.back() == '\r')) { + s = s.substr(0, s.size() - 1); + } + #endif sequence.setReference(s); sequences.push_back(sequence); diff --git a/CycloBranch/core/cSequenceDatabase.h b/CycloBranch/core/cSequenceDatabase.h index 6937550..217f1b9 100644 --- a/CycloBranch/core/cSequenceDatabase.h +++ b/CycloBranch/core/cSequenceDatabase.h @@ -11,6 +11,7 @@ #include #include #include +#include "core/utilities.h" #include "core/cSequence.h" diff --git a/CycloBranch/core/cSummaryFormula.cpp b/CycloBranch/core/cSummaryFormula.cpp index fd90ed0..352643e 100644 --- a/CycloBranch/core/cSummaryFormula.cpp +++ b/CycloBranch/core/cSummaryFormula.cpp @@ -94,7 +94,7 @@ void cSummaryFormula::clear() { } -void cSummaryFormula::setFormula(string& formula) { +void cSummaryFormula::setFormula(const string& formula) { this->formula = formula; } @@ -140,7 +140,7 @@ bool cSummaryFormula::isValid(string& errormessage) { return false; } } - catch (std::regex_error& e) { + catch (regex_error& e) { errormessage = "getMassFromResidueSummary: regex_search failed, error no. " + to_string((int)e.code()) + "\n"; return false; } diff --git a/CycloBranch/core/cSummaryFormula.h b/CycloBranch/core/cSummaryFormula.h index 7ac8de4..f6dc553 100644 --- a/CycloBranch/core/cSummaryFormula.h +++ b/CycloBranch/core/cSummaryFormula.h @@ -13,6 +13,7 @@ using namespace std; +using namespace boost; /** @@ -50,7 +51,7 @@ class cSummaryFormula { \brief Set the formula. \param formula a chemical formula */ - void setFormula(string& formula); + void setFormula(const string& formula); /** @@ -98,4 +99,4 @@ class cSummaryFormula { }; -#endif \ No newline at end of file +#endif diff --git a/CycloBranch/core/cTheoreticalSpectrum.cpp b/CycloBranch/core/cTheoreticalSpectrum.cpp index 94432ab..7a53ba6 100644 --- a/CycloBranch/core/cTheoreticalSpectrum.cpp +++ b/CycloBranch/core/cTheoreticalSpectrum.cpp @@ -71,7 +71,7 @@ void cTheoreticalSpectrum::searchForPeakPairs(cPeaksList& theoreticalpeaks, int } -void cTheoreticalSpectrum::computeSomeStatistics(bool writedescription) { +void cTheoreticalSpectrum::computeStatistics(bool writedescription) { experimentalpeaksmatched = 0; scrambledpeaksmatched = 0; if (writedescription) { @@ -103,11 +103,90 @@ void cTheoreticalSpectrum::computeSomeStatistics(bool writedescription) { } +void cTheoreticalSpectrum::generatePrecursorIon(vector& intcomposition, cBricksDatabase& bricksdatabasewithcombinations, int& theoreticalpeaksrealsize, bool writedescription) { + cPeak peak; + int starttype, endtype; + + switch (parameters->peptidetype) + { + case linear: + peak.mzratio = parameters->searchedmodifications[candidate.getStartModifID()].massdifference + parameters->searchedmodifications[candidate.getEndModifID()].massdifference; + peak.seriesid = 0; + starttype = (int)precursor_ion; + endtype = (int)precursor_ion_co_loss_and_dehydrated_and_deamidated; + break; + case cyclic: + peak.mzratio = 0; + peak.seriesid = (int)intcomposition.size() - 1; + starttype = (int)cyclic_precursor_ion; + endtype = (int)cyclic_precursor_ion_co_loss_and_dehydrated_and_deamidated; + break; + case branched: + peak.mzratio = parameters->searchedmodifications[candidate.getStartModifID()].massdifference + parameters->searchedmodifications[candidate.getEndModifID()].massdifference + parameters->searchedmodifications[candidate.getMiddleModifID()].massdifference; + peak.seriesid = 0; + starttype = (int)precursor_ion; + endtype = (int)precursor_ion_co_loss_and_dehydrated_and_deamidated; + break; + case lasso: + peak.mzratio = parameters->searchedmodifications[candidate.getMiddleModifID()].massdifference; + peak.seriesid = 0; + starttype = (int)cyclic_precursor_ion; + endtype = (int)cyclic_precursor_ion_co_loss_and_dehydrated_and_deamidated; + break; + case linearpolysaccharide: + peak.mzratio = parameters->searchedmodifications[candidate.getStartModifID()].massdifference + parameters->searchedmodifications[candidate.getEndModifID()].massdifference; + peak.seriesid = 0; + starttype = (int)precursor_ion; + endtype = (int)precursor_ion_co_loss_and_dehydrated_and_deamidated; + break; + case other: + break; + default: + break; + } + + for (int i = 0; i < (int)intcomposition.size(); i++) { + peak.mzratio += bricksdatabasewithcombinations[intcomposition[i] - 1].getMass(); + } + + double tempratio = peak.mzratio; + for (int i = starttype; i <= endtype; i++) { + for (int j = 1; j <= abs(parameters->precursorcharge); j++) { + peak.mzratio = tempratio + parameters->fragmentdefinitions[(fragmentIonType)i].massdifference; + peak.iontype = (fragmentIonType)i; + + if (writedescription) { + if (parameters->precursorcharge > 0) { + peak.description = to_string(j) + "+ " + parameters->fragmentdefinitions[(fragmentIonType)i].name + ":"; + } + else { + peak.description = to_string(j) + "- " + parameters->fragmentdefinitions[(fragmentIonType)i].name + ":"; + peak.description.replace(peak.description.find("+z"), 2, "-z"); + peak.description.replace(peak.description.find("]+"), 2, "]-"); + } + } + + peak.mzratio = charge(uncharge(peak.mzratio, 1), (parameters->precursorcharge > 0)?j:-j); + peak.charge = (parameters->precursorcharge > 0)?j:-j; + + if (theoreticalpeaks.size() > theoreticalpeaksrealsize) { + theoreticalpeaks[theoreticalpeaksrealsize] = peak; + } + else { + theoreticalpeaks.add(peak); + } + theoreticalpeaksrealsize++; + + } + } +} + + void cTheoreticalSpectrum::generateScrambledIons(cBricksDatabase& bricksdatabase, bool writedescription, int& theoreticalpeaksrealsize) { unordered_set scrambledsequences, commonsequences; vector intcomposition; scrambledsequences.clear(); - int minimumsizeofscrambledsequences = 2; + //int minimumsizeofscrambledsequences = 2; cBrick b; b.setComposition(candidate.getComposition(), false); @@ -122,7 +201,7 @@ void cTheoreticalSpectrum::generateScrambledIons(cBricksDatabase& bricksdatabase int numberofbricks = (int)stringcomposition.size(); string subseq; bool single; - // generate scrambled sequences + // generate all possible combinations of blocks for (int i = 1; i < (int)pow(2, numberofbricks) - 1; i++) { subseq = ""; single = true; @@ -140,14 +219,14 @@ void cTheoreticalSpectrum::generateScrambledIons(cBricksDatabase& bricksdatabase } } - // normalize scrambled sequences - normalizeScrambledSequences(scrambledsequences); + // select and normalize scrambled sequences + selectAndNormalizeScrambledSequences(scrambledsequences); cPeaksList scrambledpeaks; scrambledpeaks.resize(5000); int scrambledspeaksrealsize = 0; - // generate scrambled peaks + // generate scrambled peaks from sequences for (int i = 0; i < (int)parameters->fragmentionsfortheoreticalspectra.size(); i++) { for (unordered_set::iterator it = scrambledsequences.begin(); it != scrambledsequences.end(); ++it) { b.setComposition((string &)*it, false); @@ -161,9 +240,21 @@ void cTheoreticalSpectrum::generateScrambledIons(cBricksDatabase& bricksdatabase for (int i = 0; i < (int)intcomposition.size(); i++) { peak.mzratio += bricksdatabase[intcomposition[i] - 1].getMass(); } + + if (parameters->precursorcharge < 0) { + peak.mzratio = charge(uncharge(peak.mzratio, 1), -1); + } if (writedescription) { - peak.description = "scrambled "; + + if (parameters->precursorcharge < 0) { + peak.description = "1- "; + } + else { + peak.description = "1+ "; + } + + peak.description += "scrambled "; peak.description += parameters->fragmentdefinitions[peak.iontype].name.substr(0, 1) + to_string((int)intcomposition.size()); if (parameters->fragmentdefinitions[peak.iontype].name.size() > 1) { peak.description += parameters->fragmentdefinitions[peak.iontype].name.substr(1, parameters->fragmentdefinitions[peak.iontype].name.length() - 1); @@ -188,12 +279,12 @@ void cTheoreticalSpectrum::generateScrambledIons(cBricksDatabase& bricksdatabase } scrambledpeaks.resize(scrambledspeaksrealsize); - // erase all scrambled peaks whose mz ratios collide with common fragment ions - // eraseAll - time consuming 55.8% - // scrambledpeaks.sortbyMass(); - // for (int i = 0; i < theoreticalpeaksrealsize; i++) { - // scrambledpeaks.eraseAll(theoreticalpeaks[i].mzratio); - // } + // find and erase all scrambled peaks whose mz ratios collide with common fragment ions + scrambledpeaks.sortbyMass(); + for (int i = 0; i < theoreticalpeaksrealsize; i++) { + scrambledpeaks.findObsolete(theoreticalpeaks[i].mzratio); + } + scrambledpeaks.removeObsolete(); // attach scrambled peaks to common peaks for (int i = 0; i < (int)scrambledpeaks.size(); i++) { @@ -209,7 +300,7 @@ void cTheoreticalSpectrum::generateScrambledIons(cBricksDatabase& bricksdatabase } -void cTheoreticalSpectrum::normalizeScrambledSequences(unordered_set& scrambledsequences) { +void cTheoreticalSpectrum::selectAndNormalizeScrambledSequences(unordered_set& scrambledsequences) { unordered_set temp = scrambledsequences; scrambledsequences.clear(); @@ -229,37 +320,69 @@ void cTheoreticalSpectrum::normalizeScrambledSequences(unordered_set& sc } -fragmentIonType cTheoreticalSpectrum::selectHigherPriorityIonType(fragmentIonType experimentalpeakiontype, fragmentIonType theoreticalpeakiontype) { +fragmentIonType cTheoreticalSpectrum::selectHigherPriorityIonTypeCID(fragmentIonType experimentalpeakiontype, fragmentIonType theoreticalpeakiontype) { if (experimentalpeakiontype != fragmentIonTypeEnd) { switch (experimentalpeakiontype) { + case a_ion: + if (theoreticalpeakiontype == b_ion) { + experimentalpeakiontype = theoreticalpeakiontype; + } + break; + case a_ion_dehydrated: + case a_ion_deamidated: + if ((theoreticalpeakiontype == b_ion) || (theoreticalpeakiontype == b_ion_dehydrated) || (theoreticalpeakiontype == b_ion_deamidated) || (theoreticalpeakiontype == a_ion)) { + experimentalpeakiontype = theoreticalpeakiontype; + } + break; + case a_ion_dehydrated_and_deamidated: + if ((theoreticalpeakiontype == b_ion) || (theoreticalpeakiontype == b_ion_dehydrated) || (theoreticalpeakiontype == b_ion_deamidated) || (theoreticalpeakiontype == b_ion_dehydrated_and_deamidated) || (theoreticalpeakiontype == a_ion) || (theoreticalpeakiontype == a_ion_dehydrated) || (theoreticalpeakiontype == a_ion_deamidated)) { + experimentalpeakiontype = theoreticalpeakiontype; + } + break; case b_ion: break; - case b_ion_water_loss: - case b_ion_ammonia_loss: + case b_ion_dehydrated: + case b_ion_deamidated: if (theoreticalpeakiontype == b_ion) { experimentalpeakiontype = theoreticalpeakiontype; } break; - case b_ion_water_and_ammonia_loss: - if ((theoreticalpeakiontype == b_ion) || (theoreticalpeakiontype == b_ion_water_loss) || (theoreticalpeakiontype == b_ion_ammonia_loss)) { + case b_ion_dehydrated_and_deamidated: + if ((theoreticalpeakiontype == b_ion) || (theoreticalpeakiontype == b_ion_dehydrated) || (theoreticalpeakiontype == b_ion_deamidated)) { experimentalpeakiontype = theoreticalpeakiontype; } break; - case a_ion: - if (theoreticalpeakiontype == b_ion) { + case c_ion: + if ((theoreticalpeakiontype == y_ion) || (theoreticalpeakiontype == b_ion) || (theoreticalpeakiontype == a_ion)) { + experimentalpeakiontype = theoreticalpeakiontype; + } + break; + case c_ion_dehydrated: + case c_ion_deamidated: + if ((theoreticalpeakiontype == c_ion) || (theoreticalpeakiontype == y_ion) || (theoreticalpeakiontype == y_ion_dehydrated) || (theoreticalpeakiontype == y_ion_deamidated) || (theoreticalpeakiontype == b_ion) || (theoreticalpeakiontype == b_ion_dehydrated) || (theoreticalpeakiontype == b_ion_deamidated) || (theoreticalpeakiontype == a_ion) || (theoreticalpeakiontype == a_ion_dehydrated) || (theoreticalpeakiontype == a_ion_deamidated)) { experimentalpeakiontype = theoreticalpeakiontype; } break; - case a_ion_water_loss: - case a_ion_ammonia_loss: - if ((theoreticalpeakiontype == b_ion) || (theoreticalpeakiontype == b_ion_water_loss) || (theoreticalpeakiontype == b_ion_ammonia_loss) || (theoreticalpeakiontype == a_ion)) { + case c_ion_dehydrated_and_deamidated: + if ((theoreticalpeakiontype == c_ion) || (theoreticalpeakiontype == c_ion_dehydrated) || (theoreticalpeakiontype == c_ion_deamidated) || (theoreticalpeakiontype == y_ion) || (theoreticalpeakiontype == y_ion_dehydrated) || (theoreticalpeakiontype == y_ion_deamidated) || (theoreticalpeakiontype == y_ion_dehydrated_and_deamidated) || (theoreticalpeakiontype == b_ion) || (theoreticalpeakiontype == b_ion_dehydrated) || (theoreticalpeakiontype == b_ion_deamidated) || (theoreticalpeakiontype == b_ion_dehydrated_and_deamidated) || (theoreticalpeakiontype == a_ion) || (theoreticalpeakiontype == a_ion_dehydrated) || (theoreticalpeakiontype == a_ion_deamidated) || (theoreticalpeakiontype == a_ion_dehydrated_and_deamidated)) { experimentalpeakiontype = theoreticalpeakiontype; } break; - case a_ion_water_and_ammonia_loss: - if ((theoreticalpeakiontype == b_ion) || (theoreticalpeakiontype == b_ion_water_loss) || (theoreticalpeakiontype == b_ion_ammonia_loss) || (theoreticalpeakiontype == a_ion) || (theoreticalpeakiontype == a_ion_water_loss) || (theoreticalpeakiontype == a_ion_ammonia_loss)) { + case x_ion: + if ((theoreticalpeakiontype == y_ion) || (theoreticalpeakiontype == b_ion) || (theoreticalpeakiontype == a_ion)) { + experimentalpeakiontype = theoreticalpeakiontype; + } + break; + case x_ion_dehydrated: + case x_ion_deamidated: + if ((theoreticalpeakiontype == x_ion) || (theoreticalpeakiontype == y_ion) || (theoreticalpeakiontype == y_ion_dehydrated) || (theoreticalpeakiontype == y_ion_deamidated) || (theoreticalpeakiontype == b_ion) || (theoreticalpeakiontype == b_ion_dehydrated) || (theoreticalpeakiontype == b_ion_deamidated) || (theoreticalpeakiontype == a_ion) || (theoreticalpeakiontype == a_ion_dehydrated) || (theoreticalpeakiontype == a_ion_deamidated)) { + experimentalpeakiontype = theoreticalpeakiontype; + } + break; + case x_ion_dehydrated_and_deamidated: + if ((theoreticalpeakiontype == x_ion) || (theoreticalpeakiontype == x_ion_dehydrated) || (theoreticalpeakiontype == x_ion_deamidated) || (theoreticalpeakiontype == y_ion) || (theoreticalpeakiontype == y_ion_dehydrated) || (theoreticalpeakiontype == y_ion_deamidated) || (theoreticalpeakiontype == y_ion_dehydrated_and_deamidated) || (theoreticalpeakiontype == b_ion) || (theoreticalpeakiontype == b_ion_dehydrated) || (theoreticalpeakiontype == b_ion_deamidated) || (theoreticalpeakiontype == b_ion_dehydrated_and_deamidated) || (theoreticalpeakiontype == a_ion) || (theoreticalpeakiontype == a_ion_dehydrated) || (theoreticalpeakiontype == a_ion_deamidated) || (theoreticalpeakiontype == a_ion_dehydrated_and_deamidated)) { experimentalpeakiontype = theoreticalpeakiontype; } break; @@ -268,14 +391,31 @@ fragmentIonType cTheoreticalSpectrum::selectHigherPriorityIonType(fragmentIonTyp experimentalpeakiontype = theoreticalpeakiontype; } break; - case y_ion_water_loss: - case y_ion_ammonia_loss: - if ((theoreticalpeakiontype == y_ion) || (theoreticalpeakiontype == b_ion) || (theoreticalpeakiontype == b_ion_water_loss) || (theoreticalpeakiontype == b_ion_ammonia_loss) || (theoreticalpeakiontype == a_ion) || (theoreticalpeakiontype == a_ion_water_loss) || (theoreticalpeakiontype == a_ion_ammonia_loss)) { + case y_ion_dehydrated: + case y_ion_deamidated: + if ((theoreticalpeakiontype == y_ion) || (theoreticalpeakiontype == b_ion) || (theoreticalpeakiontype == b_ion_dehydrated) || (theoreticalpeakiontype == b_ion_deamidated) || (theoreticalpeakiontype == a_ion) || (theoreticalpeakiontype == a_ion_dehydrated) || (theoreticalpeakiontype == a_ion_deamidated)) { experimentalpeakiontype = theoreticalpeakiontype; } break; - case y_ion_water_and_ammonia_loss: + case y_ion_dehydrated_and_deamidated: experimentalpeakiontype = theoreticalpeakiontype; + break; + case z_ion: + if ((theoreticalpeakiontype == y_ion) || (theoreticalpeakiontype == b_ion) || (theoreticalpeakiontype == a_ion)) { + experimentalpeakiontype = theoreticalpeakiontype; + } + break; + case z_ion_dehydrated: + case z_ion_deamidated: + if ((theoreticalpeakiontype == z_ion) || (theoreticalpeakiontype == y_ion) || (theoreticalpeakiontype == y_ion_dehydrated) || (theoreticalpeakiontype == y_ion_deamidated) || (theoreticalpeakiontype == b_ion) || (theoreticalpeakiontype == b_ion_dehydrated) || (theoreticalpeakiontype == b_ion_deamidated) || (theoreticalpeakiontype == a_ion) || (theoreticalpeakiontype == a_ion_dehydrated) || (theoreticalpeakiontype == a_ion_deamidated)) { + experimentalpeakiontype = theoreticalpeakiontype; + } + break; + case z_ion_dehydrated_and_deamidated: + if ((theoreticalpeakiontype == z_ion) || (theoreticalpeakiontype == z_ion_dehydrated) || (theoreticalpeakiontype == z_ion_deamidated) || (theoreticalpeakiontype == y_ion) || (theoreticalpeakiontype == y_ion_dehydrated) || (theoreticalpeakiontype == y_ion_deamidated) || (theoreticalpeakiontype == y_ion_dehydrated_and_deamidated) || (theoreticalpeakiontype == b_ion) || (theoreticalpeakiontype == b_ion_dehydrated) || (theoreticalpeakiontype == b_ion_deamidated) || (theoreticalpeakiontype == b_ion_dehydrated_and_deamidated) || (theoreticalpeakiontype == a_ion) || (theoreticalpeakiontype == a_ion_dehydrated) || (theoreticalpeakiontype == a_ion_deamidated) || (theoreticalpeakiontype == a_ion_dehydrated_and_deamidated)) { + experimentalpeakiontype = theoreticalpeakiontype; + } + break; default: break; } @@ -328,12 +468,6 @@ void cTheoreticalSpectrum::clear(bool clearpeaklist) { validposition = -1; reversevalidposition = -1; - realpeptidename = ""; - acronympeptidename = ""; - acronyms.clear(); - backboneacronyms.clear(); - branchacronyms.clear(); - path = ""; seriescompleted = 1; } @@ -351,7 +485,6 @@ void cTheoreticalSpectrum::setCandidate(cCandidate& candidate) { int cTheoreticalSpectrum::compareBranched(cPeaksList& sortedpeaklist, cBricksDatabase& bricksdatabasewithcombinations, bool writedescription, regex& sequencetag, regex& searchedsequence) { cBrick brick; - vector stringcomposition; vector splittingsites; int theoreticalpeaksrealsize = 0; @@ -385,75 +518,31 @@ int cTheoreticalSpectrum::compareBranched(cPeaksList& sortedpeaklist, cBricksDat } } } - catch (std::regex_error& e) { - e; + catch (regex_error& /*e*/) { return -2; } for (int i = 0; i < (int)parameters->fragmentionsfortheoreticalspectra.size(); i++) { - for (int j = 0; j < (int)trotations.size(); j++) { - if (writedescription) { - stringcomposition.clear(); - for (int k = 0; k < (int)trotations[j].bricks.size(); k++) { - stringcomposition.push_back(to_string(trotations[j].bricks[k])); - } - } + for (int j = 0; j < (int)trotations.size(); j++) { // we do not know whether the middle branch is n-terminal or c-terminal for an unmodified middle branch - // in this case the modifID is 0, and both n-terminal (*) and c-terminal (**) fragments are generated - - // j == 2 and j == 5 have invalid n-terms - if ((parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].nterminal) && (j != 2) && (j != 5)) { - // if the start modification for j == 1 or j == 4 is nterminal, generate n-terminal ions (*) - if (!(((j == 1) || (j == 4)) && (!parameters->searchedmodifications[trotations[j].startmodifID].nterminal))) { - generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, stringcomposition, trotations[j].bricks, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, branched, &trotations[j]); + // in this case the modifID is 0, and both n-terminal and c-terminal fragments are generated + // j == 2, 4, 5 are invalid + if ((j == 0) || ((j == 1) && (parameters->searchedmodifications[trotations[j].startmodifID].nterminal)) || ((j == 3) && (parameters->searchedmodifications[trotations[j].endmodifID].cterminal))) { + if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].nterminal) { + generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, trotations[j].bricks, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, branched, &trotations[j]); } - } - - // j == 2 and j == 4 have invalid c-terms - if ((parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].cterminal) && (j != 2) && (j != 4)) { - // if the end modification for j == 3 or j == 5 is cterminal, generate c-terminal ions (**) - if (!(((j == 3) || (j == 5)) && (!parameters->searchedmodifications[trotations[j].endmodifID].cterminal))) { - generateCTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, stringcomposition, trotations[j].bricks, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, branched, &trotations[j]); + if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].cterminal) { + generateCTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, trotations[j].bricks, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, branched, &trotations[j]); } } } - } - - // generate the precursor ion - cPeak peak; - peak.mzratio = parameters->searchedmodifications[candidate.getStartModifID()].massdifference + parameters->searchedmodifications[candidate.getEndModifID()].massdifference + parameters->searchedmodifications[candidate.getMiddleModifID()].massdifference; - for (int i = 0; i < (int)trotations[0].bricks.size(); i++) { - peak.mzratio += bricksdatabasewithcombinations[trotations[0].bricks[i] - 1].getMass(); - } - peak.seriesid = 0; - - double tempratio = peak.mzratio; - for (int i = (int)precursor_ion; i <= (int)precursor_ion_co_loss_water_and_ammonia_loss; i++) { - for (int j = 1; j <= parameters->precursorcharge; j++) { - peak.mzratio = tempratio + parameters->fragmentdefinitions[(fragmentIonType)i].massdifference; - peak.iontype = (fragmentIonType)i; - - if (writedescription) { - peak.description = to_string(j) + "+ " + parameters->fragmentdefinitions[(fragmentIonType)i].name + ":"; - } - - peak.mzratio = charge(peak.mzratio, j); - peak.charge = j; - - if (theoreticalpeaks.size() > theoreticalpeaksrealsize) { - theoreticalpeaks[theoreticalpeaksrealsize] = peak; - } - else { - theoreticalpeaks.add(peak); - } - theoreticalpeaksrealsize++; - - } } + + generatePrecursorIon(trotations[0].bricks, bricksdatabasewithcombinations, theoreticalpeaksrealsize, writedescription); // search the theoretical peaks in the experimental peak list @@ -466,7 +555,7 @@ int cTheoreticalSpectrum::compareBranched(cPeaksList& sortedpeaklist, cBricksDat vector > > series; series.resize(trotations.size()); for (int i = 0; i < (int)series.size(); i++) { - for (int j = 0; j < parameters->fragmentionsfortheoreticalspectra.size(); j++) { + for (int j = 0; j < (int)parameters->fragmentionsfortheoreticalspectra.size(); j++) { series[i][parameters->fragmentionsfortheoreticalspectra[j]].resize(trotations[0].bricks.size()); } } @@ -507,7 +596,7 @@ int cTheoreticalSpectrum::compareBranched(cPeaksList& sortedpeaklist, cBricksDat theoreticalpeaks[*it].matchdescription += ", measured mass " + to_string((long double)experimentalpeaks[i].mzratio) + " matched with " + to_string((long double)ppmError(experimentalpeaks[i].mzratio, theoreticalpeaks[*it].mzratio)) + " ppm error"; } - experimentalpeaks[i].iontype = selectHigherPriorityIonType(experimentalpeaks[i].iontype,theoreticalpeaks[*it].iontype); + experimentalpeaks[i].iontype = selectHigherPriorityIonTypeCID(experimentalpeaks[i].iontype,theoreticalpeaks[*it].iontype); } } @@ -529,10 +618,10 @@ int cTheoreticalSpectrum::compareBranched(cPeaksList& sortedpeaklist, cBricksDat tempseries.name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name; coveragebyseries += tempseries.name + " "; tempseries.series.clear(); - for (int k = 0; k < series[i][parameters->fragmentionsfortheoreticalspectra[j]].size() - 1; k++) { + for (int k = 0; k < (int)series[i][parameters->fragmentionsfortheoreticalspectra[j]].size() - 1; k++) { coveragebyseries += to_string(series[i][parameters->fragmentionsfortheoreticalspectra[j]][k]); tempseries.series.push_back(series[i][parameters->fragmentionsfortheoreticalspectra[j]][k]); - if (k < series[i][parameters->fragmentionsfortheoreticalspectra[j]].size() - 2) { + if (k < (int)series[i][parameters->fragmentionsfortheoreticalspectra[j]].size() - 2) { coveragebyseries += " "; } } @@ -543,7 +632,7 @@ int cTheoreticalSpectrum::compareBranched(cPeaksList& sortedpeaklist, cBricksDat } - computeSomeStatistics(writedescription); + computeStatistics(writedescription); return theoreticalpeaksrealsize; } @@ -552,7 +641,6 @@ int cTheoreticalSpectrum::compareBranched(cPeaksList& sortedpeaklist, cBricksDat int cTheoreticalSpectrum::compareLinear(cPeaksList& sortedpeaklist, cBricksDatabase& bricksdatabasewithcombinations, bool writedescription, regex& sequencetag, regex& searchedsequence) { cBrick brick; vector intcomposition; - vector stringcomposition; vector splittingsites; int theoreticalpeaksrealsize = 0; @@ -570,8 +658,7 @@ int cTheoreticalSpectrum::compareLinear(cPeaksList& sortedpeaklist, cBricksDatab } } } - catch (std::regex_error& e) { - e; + catch (regex_error& /*e*/) { return -2; } @@ -580,52 +667,16 @@ int cTheoreticalSpectrum::compareLinear(cPeaksList& sortedpeaklist, cBricksDatab brick.setComposition(candidate.getComposition(), false); brick.explodeToIntComposition(intcomposition); - if (writedescription) { - stringcomposition.clear(); - brick.explodeToStringComposition(stringcomposition); - } - for (int i = 0; i < (int)parameters->fragmentionsfortheoreticalspectra.size(); i++) { if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].nterminal) { - generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, stringcomposition, intcomposition, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, linear); + generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, intcomposition, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, linear); } if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].cterminal) { - generateCTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, stringcomposition, intcomposition, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, linear); + generateCTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, intcomposition, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, linear); } } - - // generate the precursor ion - cPeak peak; - peak.mzratio = parameters->searchedmodifications[candidate.getStartModifID()].massdifference + parameters->searchedmodifications[candidate.getEndModifID()].massdifference; - for (int i = 0; i < (int)intcomposition.size(); i++) { - peak.mzratio += bricksdatabasewithcombinations[intcomposition[i] - 1].getMass(); - } - peak.seriesid = 0; - - double tempratio = peak.mzratio; - for (int i = (int)precursor_ion; i <= (int)precursor_ion_co_loss_water_and_ammonia_loss; i++) { - for (int j = 1; j <= parameters->precursorcharge; j++) { - peak.mzratio = tempratio + parameters->fragmentdefinitions[(fragmentIonType)i].massdifference; - peak.iontype = (fragmentIonType)i; - - if (writedescription) { - peak.description = to_string(j) + "+ " + parameters->fragmentdefinitions[(fragmentIonType)i].name + ":"; - } - - peak.mzratio = charge(peak.mzratio, j); - peak.charge = j; - - if (theoreticalpeaks.size() > theoreticalpeaksrealsize) { - theoreticalpeaks[theoreticalpeaksrealsize] = peak; - } - else { - theoreticalpeaks.add(peak); - } - theoreticalpeaksrealsize++; - - } - } + generatePrecursorIon(intcomposition, bricksdatabasewithcombinations, theoreticalpeaksrealsize, writedescription); // search the theoretical peaks in the experimental peak list @@ -636,7 +687,7 @@ int cTheoreticalSpectrum::compareLinear(cPeaksList& sortedpeaklist, cBricksDatab // coverage of series map > series; - for (int i = 0; i < parameters->fragmentionsfortheoreticalspectra.size(); i++) { + for (int i = 0; i < (int)parameters->fragmentionsfortheoreticalspectra.size(); i++) { series[parameters->fragmentionsfortheoreticalspectra[i]].resize(intcomposition.size()); } @@ -674,7 +725,7 @@ int cTheoreticalSpectrum::compareLinear(cPeaksList& sortedpeaklist, cBricksDatab theoreticalpeaks[*it].matchdescription += ", measured mass " + to_string((long double)experimentalpeaks[i].mzratio) + " matched with " + to_string((long double)ppmError(experimentalpeaks[i].mzratio, theoreticalpeaks[*it].mzratio)) + " ppm error"; } - experimentalpeaks[i].iontype = selectHigherPriorityIonType(experimentalpeaks[i].iontype,theoreticalpeaks[*it].iontype); + experimentalpeaks[i].iontype = selectHigherPriorityIonTypeCID(experimentalpeaks[i].iontype,theoreticalpeaks[*it].iontype); } } @@ -689,10 +740,10 @@ int cTheoreticalSpectrum::compareLinear(cPeaksList& sortedpeaklist, cBricksDatab tempseries.name = parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name; coveragebyseries += tempseries.name + " "; tempseries.series.clear(); - for (int j = 0; j < series[parameters->fragmentionsfortheoreticalspectra[i]].size() - 1; j++) { + for (int j = 0; j < (int)series[parameters->fragmentionsfortheoreticalspectra[i]].size() - 1; j++) { coveragebyseries += to_string(series[parameters->fragmentionsfortheoreticalspectra[i]][j]); tempseries.series.push_back(series[parameters->fragmentionsfortheoreticalspectra[i]][j]); - if (j < series[parameters->fragmentionsfortheoreticalspectra[i]].size() - 2) { + if (j < (int)series[parameters->fragmentionsfortheoreticalspectra[i]].size() - 2) { coveragebyseries += " "; } } @@ -702,7 +753,7 @@ int cTheoreticalSpectrum::compareLinear(cPeaksList& sortedpeaklist, cBricksDatab } - computeSomeStatistics(writedescription); + computeStatistics(writedescription); return theoreticalpeaksrealsize; } @@ -712,7 +763,6 @@ int cTheoreticalSpectrum::compareCyclic(cPeaksList& sortedpeaklist, cBricksDatab cBrick brick; vector intcomposition; - vector stringcomposition; vector splittingsites; int theoreticalpeaksrealsize = 0; @@ -799,8 +849,7 @@ int cTheoreticalSpectrum::compareCyclic(cPeaksList& sortedpeaklist, cBricksDatab } } - catch (std::regex_error& e) { - e; + catch (regex_error& /*e*/) { return -2; } @@ -812,13 +861,8 @@ int cTheoreticalSpectrum::compareCyclic(cPeaksList& sortedpeaklist, cBricksDatab brick.setComposition(rotations[i], false); brick.explodeToIntComposition(intcomposition); - if (writedescription) { - stringcomposition.clear(); - brick.explodeToStringComposition(stringcomposition); - } - for (int j = 0; j < (int)parameters->fragmentionsfortheoreticalspectra.size(); j++) { - generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, stringcomposition, intcomposition, parameters->fragmentionsfortheoreticalspectra[j], bricksdatabasewithcombinations, writedescription, i, splittingsites, parameters->searchedmodifications, cyclic); + generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, intcomposition, parameters->fragmentionsfortheoreticalspectra[j], bricksdatabasewithcombinations, writedescription, i, splittingsites, parameters->searchedmodifications, cyclic); } } @@ -827,38 +871,7 @@ int cTheoreticalSpectrum::compareCyclic(cPeaksList& sortedpeaklist, cBricksDatab generateScrambledIons(bricksdatabasewithcombinations, writedescription, theoreticalpeaksrealsize); } - - // generate the precursor ion - cPeak peak; - peak.mzratio = 0; - for (int i = 0; i < (int)intcomposition.size(); i++) { - peak.mzratio += bricksdatabasewithcombinations[intcomposition[i] - 1].getMass(); - } - peak.seriesid = (int)intcomposition.size() - 1; - - double tempratio = peak.mzratio; - for (int i = (int)cyclic_precursor_ion; i <= (int)cyclic_precursor_ion_co_loss_water_and_ammonia_loss; i++) { - for (int j = 1; j <= parameters->precursorcharge; j++) { - peak.mzratio = tempratio + parameters->fragmentdefinitions[(fragmentIonType)i].massdifference; - peak.iontype = (fragmentIonType)i; - - if (writedescription) { - peak.description = to_string(j) + "+ " + parameters->fragmentdefinitions[(fragmentIonType)i].name + ":"; - } - - peak.mzratio = charge(peak.mzratio, j); - peak.charge = j; - - if (theoreticalpeaks.size() > theoreticalpeaksrealsize) { - theoreticalpeaks[theoreticalpeaksrealsize] = peak; - } - else { - theoreticalpeaks.add(peak); - } - theoreticalpeaksrealsize++; - - } - } + generatePrecursorIon(intcomposition, bricksdatabasewithcombinations, theoreticalpeaksrealsize, writedescription); // search the theoretical peaks in the experimental peak list @@ -871,7 +884,7 @@ int cTheoreticalSpectrum::compareCyclic(cPeaksList& sortedpeaklist, cBricksDatab vector > > series; series.resize(rotations.size()); for (int i = 0; i < (int)series.size(); i++) { - for (int j = 0; j < parameters->fragmentionsfortheoreticalspectra.size(); j++) { + for (int j = 0; j < (int)parameters->fragmentionsfortheoreticalspectra.size(); j++) { series[i][parameters->fragmentionsfortheoreticalspectra[j]].resize(r); } } @@ -967,52 +980,15 @@ int cTheoreticalSpectrum::compareCyclic(cPeaksList& sortedpeaklist, cBricksDatab } if (experimentalpeaks[i].iontype != fragmentIonTypeEnd) { - if (theoreticalpeaks[*it].scrambled == experimentalpeaks[i].scrambled) { - - switch (experimentalpeaks[i].iontype) - { - case b_ion: - break; - case b_ion_water_loss: - case b_ion_ammonia_loss: - if (theoreticalpeaks[*it].iontype == b_ion) { - experimentalpeaks[i].iontype = theoreticalpeaks[*it].iontype; - } - break; - case b_ion_water_and_ammonia_loss: - if ((theoreticalpeaks[*it].iontype == b_ion) || (theoreticalpeaks[*it].iontype == b_ion_water_loss) || (theoreticalpeaks[*it].iontype == b_ion_ammonia_loss)) { - experimentalpeaks[i].iontype = theoreticalpeaks[*it].iontype; - } - break; - case a_ion: - if (theoreticalpeaks[*it].iontype == b_ion) { - experimentalpeaks[i].iontype = theoreticalpeaks[*it].iontype; - } - break; - case a_ion_water_loss: - case a_ion_ammonia_loss: - if ((theoreticalpeaks[*it].iontype == b_ion) || (theoreticalpeaks[*it].iontype == b_ion_water_loss) || (theoreticalpeaks[*it].iontype == b_ion_ammonia_loss) || (theoreticalpeaks[*it].iontype == a_ion)) { - experimentalpeaks[i].iontype = theoreticalpeaks[*it].iontype; - } - break; - case a_ion_water_and_ammonia_loss: - experimentalpeaks[i].iontype = theoreticalpeaks[*it].iontype; - break; - default: - break; - } - + experimentalpeaks[i].iontype = selectHigherPriorityIonTypeCID(experimentalpeaks[i].iontype,theoreticalpeaks[*it].iontype); } else { - if (experimentalpeaks[i].scrambled && !theoreticalpeaks[*it].scrambled) { experimentalpeaks[i].iontype = theoreticalpeaks[*it].iontype; experimentalpeaks[i].scrambled = theoreticalpeaks[*it].scrambled; } - } - } else { experimentalpeaks[i].iontype = theoreticalpeaks[*it].iontype; @@ -1045,10 +1021,10 @@ int cTheoreticalSpectrum::compareCyclic(cPeaksList& sortedpeaklist, cBricksDatab tempseries.name = to_string(splittingsites[i].first + 1) + "-" + to_string(splittingsites[i].second + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name; coveragebyseries += tempseries.name + " "; tempseries.series.clear(); - for (int k = 0; k < series[i][parameters->fragmentionsfortheoreticalspectra[j]].size() - 1; k++) { + for (int k = 0; k < (int)series[i][parameters->fragmentionsfortheoreticalspectra[j]].size() - 1; k++) { coveragebyseries += to_string(series[i][parameters->fragmentionsfortheoreticalspectra[j]][k]); tempseries.series.push_back(series[i][parameters->fragmentionsfortheoreticalspectra[j]][k]); - if (k < series[i][parameters->fragmentionsfortheoreticalspectra[j]].size() - 2) { + if (k < (int)series[i][parameters->fragmentionsfortheoreticalspectra[j]].size() - 2) { coveragebyseries += " "; } } @@ -1113,7 +1089,7 @@ int cTheoreticalSpectrum::compareCyclic(cPeaksList& sortedpeaklist, cBricksDatab maskscore += mask[k]; } - computeSomeStatistics(writedescription); + computeStatistics(writedescription); return theoreticalpeaksrealsize; } @@ -1123,14 +1099,14 @@ int cTheoreticalSpectrum::compareLasso(cPeaksList& sortedpeaklist, cBricksDataba vector splittingsites; int theoreticalpeaksrealsize = 0; - vector stringcomposition; vector lassorotations; // normalize the candidate candidate.getLassoRotations(lassorotations, false); + int numberofbricks = getNumberOfBricks(candidate.getComposition()); for (int i = 0; i < (int)lassorotations.size(); i++) { - if (lassorotations[i].getBranchEnd() == getNumberOfBricks(candidate.getComposition()) - 1) { + if (lassorotations[i].getBranchEnd() == numberofbricks - 1) { vector v; v.push_back(lassorotations[i].getComposition()); candidate.setCandidate(v, candidate.getPath(), candidate.getStartModifID(), candidate.getEndModifID(), candidate.getMiddleModifID(), lassorotations[i].getBranchStart(), lassorotations[i].getBranchEnd()); @@ -1139,10 +1115,10 @@ int cTheoreticalSpectrum::compareLasso(cPeaksList& sortedpeaklist, cBricksDataba } - // get lasso rotations + // get branch-cyclic rotations candidate.getLassoRotations(lassorotations, true); - // get T-permutations of lasso rotations + // get T-permutations of branch-cyclic rotations vector > trotationsoflassorotations; trotationsoflassorotations.resize(lassorotations.size()); for (int i = 0; i < (int)lassorotations.size(); i++) { @@ -1231,8 +1207,7 @@ int cTheoreticalSpectrum::compareLasso(cPeaksList& sortedpeaklist, cBricksDataba } } - catch (std::regex_error& e) { - e; + catch (regex_error& /*e*/) { return -2; } @@ -1243,21 +1218,13 @@ int cTheoreticalSpectrum::compareLasso(cPeaksList& sortedpeaklist, cBricksDataba for (int k = 0; k < (int)trotationsoflassorotations[j].size(); k++) { - if (writedescription) { - // to do - performace issue, generated repeatedly - stringcomposition.clear(); - for (int m = 0; m < (int)trotationsoflassorotations[j][k].bricks.size(); m++) { - stringcomposition.push_back(to_string(trotationsoflassorotations[j][k].bricks[m])); - } - } - // we do not know whether the middle branch is n-terminal or c-terminal for an unmodified middle branch // in this case the modifID is 0, and both n-terminal (*) and c-terminal (**) fragments are generated if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].nterminal) { // if the start modification for k == 1 or k == 4 is nterminal, generate n-terminal ions (*) if (!(((k == 1) || (k == 4)) && (!parameters->searchedmodifications[trotationsoflassorotations[j][k].startmodifID].nterminal))) { - generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, stringcomposition, trotationsoflassorotations[j][k].bricks, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, j, splittingsites, parameters->searchedmodifications, lasso, &trotationsoflassorotations[j][k]); + generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, trotationsoflassorotations[j][k].bricks, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, j, splittingsites, parameters->searchedmodifications, lasso, &trotationsoflassorotations[j][k]); } } @@ -1265,7 +1232,7 @@ int cTheoreticalSpectrum::compareLasso(cPeaksList& sortedpeaklist, cBricksDataba if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].cterminal && ((k == 3) || (k == 5) /*|| ((k == 0) && (trotationsoflassorotations[j][k].endsWithBracket())) || ((k == 2) && (trotationsoflassorotations[j][k].startsWithBracket()))*/)) { // if the end modification is cterminal, generate c-terminal ions (**) if (parameters->searchedmodifications[trotationsoflassorotations[j][k].endmodifID].cterminal) { - generateCTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, stringcomposition, trotationsoflassorotations[j][k].bricks, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, j, splittingsites, parameters->searchedmodifications, lasso, &trotationsoflassorotations[j][k]); + generateCTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, trotationsoflassorotations[j][k].bricks, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, j, splittingsites, parameters->searchedmodifications, lasso, &trotationsoflassorotations[j][k]); } } @@ -1275,44 +1242,7 @@ int cTheoreticalSpectrum::compareLasso(cPeaksList& sortedpeaklist, cBricksDataba } - - // generate the precursor ion - // to do - performance - cBrick b; - b.setComposition(candidate.getComposition(), false); - vector intcomposition; - b.explodeToIntComposition(intcomposition); - - cPeak peak; - peak.mzratio = parameters->searchedmodifications[candidate.getMiddleModifID()].massdifference; - for (int i = 0; i < (int)intcomposition.size(); i++) { - peak.mzratio += bricksdatabasewithcombinations[intcomposition[i] - 1].getMass(); - } - peak.seriesid = 0; - - double tempratio = peak.mzratio; - for (int i = (int)cyclic_precursor_ion; i <= (int)cyclic_precursor_ion_co_loss_water_and_ammonia_loss; i++) { - for (int j = 1; j <= parameters->precursorcharge; j++) { - peak.mzratio = tempratio + parameters->fragmentdefinitions[(fragmentIonType)i].massdifference; - peak.iontype = (fragmentIonType)i; - - if (writedescription) { - peak.description = to_string(j) + "+ " + parameters->fragmentdefinitions[(fragmentIonType)i].name + ":"; - } - - peak.mzratio = charge(peak.mzratio, j); - peak.charge = j; - - if (theoreticalpeaks.size() > theoreticalpeaksrealsize) { - theoreticalpeaks[theoreticalpeaksrealsize] = peak; - } - else { - theoreticalpeaks.add(peak); - } - theoreticalpeaksrealsize++; - - } - } + generatePrecursorIon(trotationsoflassorotations[0][0].bricks, bricksdatabasewithcombinations, theoreticalpeaksrealsize, writedescription); // search the theoretical peaks in the experimental peak list @@ -1329,7 +1259,7 @@ int cTheoreticalSpectrum::compareLasso(cPeaksList& sortedpeaklist, cBricksDataba //series[i].resize(trotationsoflassorotations[i].size()); // to do - potential bug for (int j = 0; j < (int)series[i].size(); j++) { - for (int k = 0; k < parameters->fragmentionsfortheoreticalspectra.size(); k++) { + for (int k = 0; k < (int)parameters->fragmentionsfortheoreticalspectra.size(); k++) { series[i][j][parameters->fragmentionsfortheoreticalspectra[k]].resize(trotationsoflassorotations[i][0].bricks.size()); } } @@ -1375,7 +1305,7 @@ int cTheoreticalSpectrum::compareLasso(cPeaksList& sortedpeaklist, cBricksDataba theoreticalpeaks[*it].matchdescription += ", measured mass " + to_string((long double)experimentalpeaks[i].mzratio) + " matched with " + to_string((long double)ppmError(experimentalpeaks[i].mzratio, theoreticalpeaks[*it].mzratio)) + " ppm error"; } - experimentalpeaks[i].iontype = selectHigherPriorityIonType(experimentalpeaks[i].iontype,theoreticalpeaks[*it].iontype); + experimentalpeaks[i].iontype = selectHigherPriorityIonTypeCID(experimentalpeaks[i].iontype,theoreticalpeaks[*it].iontype); } } @@ -1404,10 +1334,10 @@ int cTheoreticalSpectrum::compareLasso(cPeaksList& sortedpeaklist, cBricksDataba tempseries.name += to_string(j + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[k]].name; coveragebyseries += tempseries.name + " "; tempseries.series.clear(); - for (int m = 0; m < series[i][j][parameters->fragmentionsfortheoreticalspectra[k]].size() - 1; m++) { + for (int m = 0; m < (int)series[i][j][parameters->fragmentionsfortheoreticalspectra[k]].size() - 1; m++) { coveragebyseries += to_string(series[i][j][parameters->fragmentionsfortheoreticalspectra[k]][m]); tempseries.series.push_back(series[i][j][parameters->fragmentionsfortheoreticalspectra[k]][m]); - if (m < series[i][j][parameters->fragmentionsfortheoreticalspectra[k]].size() - 2) { + if (m < (int)series[i][j][parameters->fragmentionsfortheoreticalspectra[k]].size() - 2) { coveragebyseries += " "; } } @@ -1420,7 +1350,7 @@ int cTheoreticalSpectrum::compareLasso(cPeaksList& sortedpeaklist, cBricksDataba } - computeSomeStatistics(writedescription); + computeStatistics(writedescription); return theoreticalpeaksrealsize; } @@ -1429,7 +1359,6 @@ int cTheoreticalSpectrum::compareLasso(cPeaksList& sortedpeaklist, cBricksDataba int cTheoreticalSpectrum::compareLinearPolysaccharide(cPeaksList& sortedpeaklist, cBricksDatabase& bricksdatabasewithcombinations, bool writedescription, regex& sequencetag, regex& searchedsequence) { cBrick brick; vector intcomposition; - vector stringcomposition; vector splittingsites; int theoreticalpeaksrealsize = 0; @@ -1447,8 +1376,7 @@ int cTheoreticalSpectrum::compareLinearPolysaccharide(cPeaksList& sortedpeaklist } } } - catch (std::regex_error& e) { - e; + catch (regex_error& /*e*/) { return -2; } @@ -1457,52 +1385,16 @@ int cTheoreticalSpectrum::compareLinearPolysaccharide(cPeaksList& sortedpeaklist brick.setComposition(candidate.getComposition(), false); brick.explodeToIntComposition(intcomposition); - if (writedescription) { - stringcomposition.clear(); - brick.explodeToStringComposition(stringcomposition); - } - for (int i = 0; i < (int)parameters->fragmentionsfortheoreticalspectra.size(); i++) { if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].nterminal) { - generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, stringcomposition, intcomposition, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, linearpolysaccharide); + generateNTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, intcomposition, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, linearpolysaccharide); } if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].cterminal) { - generateCTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, stringcomposition, intcomposition, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, linearpolysaccharide); + generateCTerminalFragmentIons(parameters->precursorcharge, theoreticalpeaksrealsize, intcomposition, parameters->fragmentionsfortheoreticalspectra[i], bricksdatabasewithcombinations, writedescription, 0, splittingsites, parameters->searchedmodifications, linearpolysaccharide); } } - - // generate the precursor ion - cPeak peak; - peak.mzratio = parameters->searchedmodifications[candidate.getStartModifID()].massdifference + parameters->searchedmodifications[candidate.getEndModifID()].massdifference; - for (int i = 0; i < (int)intcomposition.size(); i++) { - peak.mzratio += bricksdatabasewithcombinations[intcomposition[i] - 1].getMass(); - } - peak.seriesid = 0; - - double tempratio = peak.mzratio; - for (int i = (int)precursor_ion; i <= (int)precursor_ion_co_loss_water_and_ammonia_loss; i++) { - for (int j = 1; j <= parameters->precursorcharge; j++) { - peak.mzratio = tempratio + parameters->fragmentdefinitions[(fragmentIonType)i].massdifference; - peak.iontype = (fragmentIonType)i; - - if (writedescription) { - peak.description = to_string(j) + "+ " + parameters->fragmentdefinitions[(fragmentIonType)i].name + ":"; - } - - peak.mzratio = charge(peak.mzratio, j); - peak.charge = j; - - if (theoreticalpeaks.size() > theoreticalpeaksrealsize) { - theoreticalpeaks[theoreticalpeaksrealsize] = peak; - } - else { - theoreticalpeaks.add(peak); - } - theoreticalpeaksrealsize++; - - } - } + generatePrecursorIon(intcomposition, bricksdatabasewithcombinations, theoreticalpeaksrealsize, writedescription); // search the theoretical peaks in the experimental peak list @@ -1513,7 +1405,7 @@ int cTheoreticalSpectrum::compareLinearPolysaccharide(cPeaksList& sortedpeaklist // coverage of series map > series; - for (int i = 0; i < parameters->fragmentionsfortheoreticalspectra.size(); i++) { + for (int i = 0; i < (int)parameters->fragmentionsfortheoreticalspectra.size(); i++) { series[parameters->fragmentionsfortheoreticalspectra[i]].resize(intcomposition.size()); } @@ -1569,9 +1461,9 @@ int cTheoreticalSpectrum::compareLinearPolysaccharide(cPeaksList& sortedpeaklist coveragebyseries = "Series of matched peaks:
\n"; for (int i = 0; i < (int)parameters->fragmentionsfortheoreticalspectra.size(); i++) { coveragebyseries += parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name + " "; - for (int j = 0; j < series[parameters->fragmentionsfortheoreticalspectra[i]].size() - 1; j++) { + for (int j = 0; j < (int)series[parameters->fragmentionsfortheoreticalspectra[i]].size() - 1; j++) { coveragebyseries += to_string(series[parameters->fragmentionsfortheoreticalspectra[i]][j]); - if (j < series[parameters->fragmentionsfortheoreticalspectra[i]].size() - 2) { + if (j < (int)series[parameters->fragmentionsfortheoreticalspectra[i]].size() - 2) { coveragebyseries += " "; } } @@ -1580,7 +1472,7 @@ int cTheoreticalSpectrum::compareLinearPolysaccharide(cPeaksList& sortedpeaklist } - computeSomeStatistics(writedescription); + computeStatistics(writedescription); return theoreticalpeaksrealsize; } @@ -1592,7 +1484,7 @@ void cTheoreticalSpectrum::compareMSSpectrum(cParameters* parameters) { cPeak peak; cSummaryFormula formula; - theoreticalpeaks.resize((int)parameters->fragmentionsfortheoreticalspectra.size()*parameters->sequencedatabase.size()*parameters->precursorcharge); + theoreticalpeaks.resize((int)parameters->fragmentionsfortheoreticalspectra.size()*parameters->sequencedatabase.size()*abs(parameters->precursorcharge)); for (int i = 0; i < parameters->sequencedatabase.size(); i++) { peak.clear(); formula.clear(); @@ -1600,7 +1492,8 @@ void cTheoreticalSpectrum::compareMSSpectrum(cParameters* parameters) { formula.setFormula(parameters->sequencedatabase[i].getSummaryFormula()); for (int j = 0; j < (int)parameters->fragmentionsfortheoreticalspectra.size(); j++) { - for (int k = 0; k < parameters->precursorcharge; k++) { + + for (int k = 0; k < abs(parameters->precursorcharge); k++) { peak.mzratio = (double)parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].multiplier*formula.getMass() + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].massdifference; if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].positive) { peak.mzratio += (double)k*Hplus; @@ -1617,10 +1510,12 @@ void cTheoreticalSpectrum::compareMSSpectrum(cParameters* parameters) { else { peak.description += "-"; } - peak.description += " " + parameters->sequencedatabase[i].getName() + " (" + parameters->sequencedatabase[i].getSummaryFormula() + "): "; + //peak.description += " " + parameters->sequencedatabase[i].getName() + " (" + parameters->sequencedatabase[i].getSummaryFormula() + "): "; + peak.description += " " + parameters->sequencedatabase[i].getNameWithReferenceAsHTMLString() + " (" + parameters->sequencedatabase[i].getSummaryFormula() + "): "; - theoreticalpeaks[(i*(int)parameters->fragmentionsfortheoreticalspectra.size() + j)*parameters->precursorcharge + k] = peak; + theoreticalpeaks[(i*(int)parameters->fragmentionsfortheoreticalspectra.size() + j)*abs(parameters->precursorcharge) + k] = peak; } + } } theoreticalpeaks.sortbyMass(); @@ -1635,12 +1530,12 @@ void cTheoreticalSpectrum::compareMSSpectrum(cParameters* parameters) { if (experimentalpeaks[i].description.compare("") != 0) { experimentalpeaks[i].description += ","; } - experimentalpeaks[i].description += theoreticalpeaks[*it].description.substr(0,theoreticalpeaks[*it].description.find(':')); + experimentalpeaks[i].description += theoreticalpeaks[*it].description.substr(0,theoreticalpeaks[*it].description.rfind(':')); theoreticalpeaks[*it].matchdescription += ", measured mass " + to_string((long double)experimentalpeaks[i].mzratio) + " matched with " + to_string((long double)ppmError(experimentalpeaks[i].mzratio, theoreticalpeaks[*it].mzratio)) + " ppm error"; } } - computeSomeStatistics(true); + computeStatistics(true); } @@ -1649,7 +1544,7 @@ int cTheoreticalSpectrum::getNumberOfPeaks() { } -int cTheoreticalSpectrum::getNumberOfMatchedPeaks() { +int cTheoreticalSpectrum::getNumberOfMatchedPeaks() const { return experimentalpeaksmatched; } @@ -1659,25 +1554,25 @@ int cTheoreticalSpectrum::getNumberOfScrambledPeaks() { } -int cTheoreticalSpectrum::getNumberOfMatchedPeaks(fragmentIonType iontype) { - return matchedions[iontype]; +int cTheoreticalSpectrum::getNumberOfMatchedPeaks(fragmentIonType iontype) const { + return matchedions.at(iontype); } -double cTheoreticalSpectrum::getRatioOfMatchedPeaks() { - return experimentalpeaksmatchedratio; +int cTheoreticalSpectrum::getNumberOfMatchedPeaksYB() const { + return matchedions.at(y_ion)+matchedions.at(b_ion); } -int cTheoreticalSpectrum::getNumberOfMatchedPeaksYB() { - return matchedions[y_ion]+matchedions[b_ion]; +double cTheoreticalSpectrum::getRatioOfMatchedPeaks() { + return experimentalpeaksmatchedratio; } void cTheoreticalSpectrum::printMatch(ofstream& os, peptideType peptidetype) { vector rotations; - os << endl << "Peptide: " << realpeptidename << endl; + os << endl << "Peptide: " << candidate.getRealPeptideName() << endl; switch (peptidetype) { @@ -1728,48 +1623,48 @@ void cTheoreticalSpectrum::printMatch(ofstream& os, peptideType peptidetype) { os << "Matched y-ions: " << matchedions[y_ion] << endl; os << "Matched b-ions: " << matchedions[b_ion] << endl; os << "Matched a-ions: " << matchedions[a_ion] << endl; - os << "Matched y*-ions: " << matchedions[y_ion_water_loss] << endl; - os << "Matched b*-ions: " << matchedions[b_ion_water_loss] << endl; - os << "Matched a*-ions: " << matchedions[a_ion_water_loss] << endl; - os << "Matched yx-ions: " << matchedions[y_ion_ammonia_loss] << endl; - os << "Matched bx-ions: " << matchedions[b_ion_ammonia_loss] << endl; - os << "Matched ax-ions: " << matchedions[a_ion_ammonia_loss] << endl; + os << "Matched y*-ions: " << matchedions[y_ion_dehydrated] << endl; + os << "Matched b*-ions: " << matchedions[b_ion_dehydrated] << endl; + os << "Matched a*-ions: " << matchedions[a_ion_dehydrated] << endl; + os << "Matched yx-ions: " << matchedions[y_ion_deamidated] << endl; + os << "Matched bx-ions: " << matchedions[b_ion_deamidated] << endl; + os << "Matched ax-ions: " << matchedions[a_ion_deamidated] << endl; break; case cyclic: os << "Matched b-ions: " << matchedions[b_ion] << endl; os << "Matched a-ions: " << matchedions[a_ion] << endl; - os << "Matched b*-ions: " << matchedions[b_ion_water_loss] << endl; - os << "Matched a*-ions: " << matchedions[a_ion_water_loss] << endl; - os << "Matched bx-ions: " << matchedions[b_ion_ammonia_loss] << endl; - os << "Matched ax-ions: " << matchedions[a_ion_ammonia_loss] << endl; - os << "Matched b*x-ions: " << matchedions[b_ion_water_and_ammonia_loss] << endl; - os << "Matched a*x-ions: " << matchedions[a_ion_water_and_ammonia_loss] << endl; - os << "Matched b-ions and b*-ions: " << matchedions[b_ion] + matchedions[b_ion_water_loss] << endl; - os << "Matched b-ions and bx-ions: " << matchedions[b_ion] + matchedions[b_ion_ammonia_loss] << endl << endl; + os << "Matched b*-ions: " << matchedions[b_ion_dehydrated] << endl; + os << "Matched a*-ions: " << matchedions[a_ion_dehydrated] << endl; + os << "Matched bx-ions: " << matchedions[b_ion_deamidated] << endl; + os << "Matched ax-ions: " << matchedions[a_ion_deamidated] << endl; + os << "Matched b*x-ions: " << matchedions[b_ion_dehydrated_and_deamidated] << endl; + os << "Matched a*x-ions: " << matchedions[a_ion_dehydrated_and_deamidated] << endl; + os << "Matched b-ions and b*-ions: " << matchedions[b_ion] + matchedions[b_ion_dehydrated] << endl; + os << "Matched b-ions and bx-ions: " << matchedions[b_ion] + matchedions[b_ion_deamidated] << endl << endl; break; case branched: os << "Matched y-ions and b-ions: " << matchedions[y_ion] + matchedions[b_ion] << endl; os << "Matched y-ions: " << matchedions[y_ion] << endl; os << "Matched b-ions: " << matchedions[b_ion] << endl; os << "Matched a-ions: " << matchedions[a_ion] << endl; - os << "Matched y*-ions: " << matchedions[y_ion_water_loss] << endl; - os << "Matched b*-ions: " << matchedions[b_ion_water_loss] << endl; - os << "Matched a*-ions: " << matchedions[a_ion_water_loss] << endl; - os << "Matched yx-ions: " << matchedions[y_ion_ammonia_loss] << endl; - os << "Matched bx-ions: " << matchedions[b_ion_ammonia_loss] << endl; - os << "Matched ax-ions: " << matchedions[a_ion_ammonia_loss] << endl; + os << "Matched y*-ions: " << matchedions[y_ion_dehydrated] << endl; + os << "Matched b*-ions: " << matchedions[b_ion_dehydrated] << endl; + os << "Matched a*-ions: " << matchedions[a_ion_dehydrated] << endl; + os << "Matched yx-ions: " << matchedions[y_ion_deamidated] << endl; + os << "Matched bx-ions: " << matchedions[b_ion_deamidated] << endl; + os << "Matched ax-ions: " << matchedions[a_ion_deamidated] << endl; break; case lasso: os << "Matched y-ions and b-ions: " << matchedions[y_ion] + matchedions[b_ion] << endl; os << "Matched y-ions: " << matchedions[y_ion] << endl; os << "Matched b-ions: " << matchedions[b_ion] << endl; os << "Matched a-ions: " << matchedions[a_ion] << endl; - os << "Matched y*-ions: " << matchedions[y_ion_water_loss] << endl; - os << "Matched b*-ions: " << matchedions[b_ion_water_loss] << endl; - os << "Matched a*-ions: " << matchedions[a_ion_water_loss] << endl; - os << "Matched yx-ions: " << matchedions[y_ion_ammonia_loss] << endl; - os << "Matched bx-ions: " << matchedions[b_ion_ammonia_loss] << endl; - os << "Matched ax-ions: " << matchedions[a_ion_ammonia_loss] << endl; + os << "Matched y*-ions: " << matchedions[y_ion_dehydrated] << endl; + os << "Matched b*-ions: " << matchedions[b_ion_dehydrated] << endl; + os << "Matched a*-ions: " << matchedions[a_ion_dehydrated] << endl; + os << "Matched yx-ions: " << matchedions[y_ion_deamidated] << endl; + os << "Matched bx-ions: " << matchedions[b_ion_deamidated] << endl; + os << "Matched ax-ions: " << matchedions[a_ion_deamidated] << endl; break; case linearpolysaccharide: break; @@ -1791,7 +1686,7 @@ void cTheoreticalSpectrum::printMatch(ofstream& os, peptideType peptidetype) { } -void cTheoreticalSpectrum::generateNTerminalFragmentIons(int maxcharge, int& peaklistrealsize, vector& stringcomposition, vector& intcomposition, fragmentIonType fragmentiontype, cBricksDatabase& bricksdatabase, bool writedescription, int rotationid, vector& splittingsites, vector& searchedmodifications, peptideType peptidetype, TRotationInfo* trotation) { +void cTheoreticalSpectrum::generateNTerminalFragmentIons(int maxcharge, int& peaklistrealsize, vector& intcomposition, fragmentIonType fragmentiontype, cBricksDatabase& bricksdatabase, bool writedescription, int rotationid, vector& splittingsites, vector& searchedmodifications, peptideType peptidetype, TRotationInfo* trotation) { cPeak peak; double tempratio; string tempdescription; @@ -1889,12 +1784,17 @@ void cTheoreticalSpectrum::generateNTerminalFragmentIons(int maxcharge, int& pea if (writedescription) { tempdescription = peak.description; } - for (int j = 1; j <= maxcharge; j++) { + for (int j = 1; j <= abs(maxcharge); j++) { - peak.mzratio = charge(tempratio, j); - peak.charge = j; + peak.mzratio = charge(uncharge(tempratio, 1), (parameters->precursorcharge > 0)?j:-j); + peak.charge = (parameters->precursorcharge > 0)?j:-j; if (writedescription) { - peak.description = to_string(j) + "+ " + tempdescription; + if (parameters->precursorcharge > 0) { + peak.description = to_string(j) + "+ " + tempdescription; + } + else { + peak.description = to_string(j) + "- " + tempdescription; + } } if (theoreticalpeaks.size() > peaklistrealsize) { @@ -1918,7 +1818,7 @@ void cTheoreticalSpectrum::generateNTerminalFragmentIons(int maxcharge, int& pea } -void cTheoreticalSpectrum::generateCTerminalFragmentIons(int maxcharge, int& peaklistrealsize, vector& stringcomposition, vector& intcomposition, fragmentIonType fragmentiontype, cBricksDatabase& bricksdatabase, bool writedescription, int rotationid, vector& splittingsites, vector& searchedmodifications, peptideType peptidetype, TRotationInfo* trotation) { +void cTheoreticalSpectrum::generateCTerminalFragmentIons(int maxcharge, int& peaklistrealsize, vector& intcomposition, fragmentIonType fragmentiontype, cBricksDatabase& bricksdatabase, bool writedescription, int rotationid, vector& splittingsites, vector& searchedmodifications, peptideType peptidetype, TRotationInfo* trotation) { cPeak peak; double tempratio; string tempdescription; @@ -2016,12 +1916,17 @@ void cTheoreticalSpectrum::generateCTerminalFragmentIons(int maxcharge, int& pea if (writedescription) { tempdescription = peak.description; } - for (int j = 1; j <= maxcharge; j++) { + for (int j = 1; j <= abs(maxcharge); j++) { - peak.mzratio = charge(tempratio, j); - peak.charge = j; + peak.mzratio = charge(uncharge(tempratio, 1), (parameters->precursorcharge > 0)?j:-j); + peak.charge = (parameters->precursorcharge > 0)?j:-j; if (writedescription) { - peak.description = to_string(j) + "+ " + tempdescription; + if (parameters->precursorcharge > 0) { + peak.description = to_string(j) + "+ " + tempdescription; + } + else { + peak.description = to_string(j) + "- " + tempdescription; + } } if (theoreticalpeaks.size() > peaklistrealsize) { @@ -2060,61 +1965,11 @@ double cTheoreticalSpectrum::getPrecursorMass(cBricksDatabase& brickdatabasewith } -double cTheoreticalSpectrum::getWeightedIntensityScore() { +double cTheoreticalSpectrum::getWeightedIntensityScore() const { return intensityweightedscore; } -void cTheoreticalSpectrum::setRealPeptideName(cBricksDatabase& bricksdatabase, peptideType peptidetype) { - switch (peptidetype) - { - case linear: - case cyclic: - case linearpolysaccharide: - realpeptidename = bricksdatabase.getRealName(candidate.getComposition()); - break; - case branched: - case lasso: - realpeptidename = candidate.getRealNameTComposition(bricksdatabase); - break; - case other: - default: - realpeptidename = ""; - break; - } -} - - -void cTheoreticalSpectrum::setAcronymPeptideNameWithHTMLReferences(cBricksDatabase& bricksdatabase, peptideType peptidetype) { - switch (peptidetype) - { - case linear: - case cyclic: - case linearpolysaccharide: - acronympeptidename = bricksdatabase.getAcronymName(candidate.getComposition(), true); - break; - case branched: - case lasso: - acronympeptidename = candidate.getAcronymsTComposition(bricksdatabase); - break; - case other: - default: - acronympeptidename = ""; - break; - } -} - - -string& cTheoreticalSpectrum::getRealPeptideName() { - return realpeptidename; -} - - -string& cTheoreticalSpectrum::getAcronymPeptideNameWithHTMLReferences() { - return acronympeptidename; -} - - cPeak& cTheoreticalSpectrum::operator[](int position) { return theoreticalpeaks[position]; } @@ -2155,7 +2010,7 @@ int cTheoreticalSpectrum::getReverseValidPosition() { } -int cTheoreticalSpectrum::getNumberOfMatchedBricks() { +int cTheoreticalSpectrum::getNumberOfMatchedBricks() const { return maskscore; } @@ -2165,115 +2020,6 @@ vector& cTheoreticalSpectrum::getVisualCoverage() { } -void cTheoreticalSpectrum::setAcronyms(cBricksDatabase& bricksdatabase) { - vector bricks; - cBrick b; - b.clear(); - b.setComposition(candidate.getComposition(), false); - b.explodeToIntComposition(bricks); - - acronyms.clear(); - for (int i = 0; i < (int)bricks.size(); i++) { - acronyms.push_back(bricksdatabase[bricks[i] - 1].getAcronymsAsString()); - } -} - - -void cTheoreticalSpectrum::setBackboneAcronyms(cBricksDatabase& bricksdatabase) { - vector bricks; - cBrick b; - b.clear(); - b.setComposition(candidate.getComposition(), false); - b.explodeToIntComposition(bricks); - - backboneacronyms.clear(); - for (int i = 0; i < (int)bricks.size(); i++) { - if ((candidate.getBranchStart() >= 0) && (candidate.getBranchEnd() >= 0) && ((i <= candidate.getBranchStart()) || (i > candidate.getBranchEnd()))) { - backboneacronyms.push_back(bricksdatabase[bricks[i] - 1].getAcronymsAsString()); - } - } -} - - -void cTheoreticalSpectrum::setBranchAcronyms(cBricksDatabase& bricksdatabase) { - vector bricks; - cBrick b; - b.clear(); - b.setComposition(candidate.getComposition(), false); - b.explodeToIntComposition(bricks); - - branchacronyms.clear(); - for (int i = 0; i < (int)bricks.size(); i++) { - if ((candidate.getBranchStart() >= 0) && (candidate.getBranchEnd() >= 0) && (i > candidate.getBranchStart()) && (i <= candidate.getBranchEnd())) { - branchacronyms.push_back(bricksdatabase[bricks[i] - 1].getAcronymsAsString()); - } - } -} - - -vector& cTheoreticalSpectrum::getAcronyms() { - return acronyms; -} - - -vector& cTheoreticalSpectrum::getBackboneAcronyms() { - return backboneacronyms; -} - - -vector& cTheoreticalSpectrum::getBranchAcronyms() { - return branchacronyms; -} - - -void cTheoreticalSpectrum::setPath(cDeNovoGraph& graph) { - cDeNovoGraphNode* currentnode; - cDeNovoGraphNode* targetnode; - cEdge* currentedge; - path = ""; - for (int i = 0; i < (int)candidate.getPath().size(); i++) { - currentnode = &graph[candidate.getPath()[i].nodeid]; - currentedge = &((*currentnode)[candidate.getPath()[i].edgeid]); - targetnode = &graph[currentedge->targetnode]; - - path += to_string(currentnode->getMZRatio()); - path += " -> "; - path += to_string(targetnode->getMZRatio()); - path += " using brick(s): "; - if (currentedge->composition.compare("0") == 0) { - path += "none"; - } - else { - path += graph.getBrickDatabaseWithCombinations()->getAcronymName(currentedge->composition, true); - } - - path += " (mass difference: " + to_string(currentedge->massdifference) + ", "; - path += "source intensity: " + to_string(currentnode->getIntensity()) + ", "; - path += "target intensity: " + to_string(targetnode->getIntensity()) + ", "; - path += "ppm error: " + to_string(currentedge->ppmerror) + ", "; - path += "source charge: " + to_string(currentedge->sourcecharge) + ", "; - path += "target charge: " + to_string(currentedge->targetcharge); - if ((parameters->peptidetype == branched) || (parameters->peptidetype == lasso)) { - if (currentedge->middlemodifID > 0) { - path += ", branch modification: " + parameters->searchedmodifications[currentedge->middlemodifID].name; - } - } - if (currentedge->endmodifID > 0) { - path += ", terminal modification: " + parameters->searchedmodifications[currentedge->endmodifID].name; - } - //path += currentedge->printSourceAnnotation(fragmentdefinitions); - //path += "->"; - //path += currentedge->printTargetAnnotation(fragmentdefinitions); - path += ")
"; - } -} - - -string& cTheoreticalSpectrum::getPath() { - return path; -} - - int cTheoreticalSpectrum::getNumberOfCompletedSeries() { return seriescompleted; } @@ -2325,13 +2071,6 @@ void cTheoreticalSpectrum::store(ofstream& os) { os.write((char *)&validposition, sizeof(int)); os.write((char *)&reversevalidposition, sizeof(int)); os.write((char *)&seriescompleted, sizeof(int)); - - storeString(realpeptidename, os); - storeString(acronympeptidename, os); - storeStringVector(acronyms, os); - storeStringVector(backboneacronyms, os); - storeStringVector(branchacronyms, os); - storeString(path, os); } @@ -2376,12 +2115,5 @@ void cTheoreticalSpectrum::load(ifstream& is) { is.read((char *)&validposition, sizeof(int)); is.read((char *)&reversevalidposition, sizeof(int)); is.read((char *)&seriescompleted, sizeof(int)); - - loadString(realpeptidename, is); - loadString(acronympeptidename, is); - loadStringVector(acronyms, is); - loadStringVector(backboneacronyms, is); - loadStringVector(branchacronyms, is); - loadString(path, is); } diff --git a/CycloBranch/core/cTheoreticalSpectrum.h b/CycloBranch/core/cTheoreticalSpectrum.h index 3c3100f..3f69e6e 100644 --- a/CycloBranch/core/cTheoreticalSpectrum.h +++ b/CycloBranch/core/cTheoreticalSpectrum.h @@ -11,7 +11,6 @@ #include #include #include -#include #include #include "core/cParameters.h" @@ -113,30 +112,26 @@ class cTheoreticalSpectrum { int reversevalidposition; int seriescompleted; - string realpeptidename; - string acronympeptidename; - vector acronyms; - vector backboneacronyms; - vector branchacronyms; - string path; - // remove false hits, i.e., b-H2O without existing b-ion void clearFalseHits(map >& series, vector& fragmentions); // search for matches of experimental and theoretical peaks void searchForPeakPairs(cPeaksList& theoreticalpeaks, int theoreticalpeaksrealsize, cPeaksList& experimentalpeaks, vector >& experimentalpeakmatches, double fragmentmasserrortolerance); - // compute some scores, etc. - void computeSomeStatistics(bool writedescription); + // compute additional scores + void computeStatistics(bool writedescription); + + // generate precursor ion and its variants + void generatePrecursorIon(vector& intcomposition, cBricksDatabase& bricksdatabasewithcombinations, int& theoreticalpeaksrealsize, bool writedescription); // generate scrambled sequences void generateScrambledIons(cBricksDatabase& bricksdatabase, bool writedescription, int& theoreticalpeaksrealsize); - // normalize scrambled sequences - void normalizeScrambledSequences(unordered_set& scrambledsequences); + // select and normalize scrambled sequences + void selectAndNormalizeScrambledSequences(unordered_set& scrambledsequences); // select a proper fragment ion type for an experimental peak when masses of more theoretical fragment ions collide - fragmentIonType selectHigherPriorityIonType(fragmentIonType experimentalpeakiontype, fragmentIonType theoreticalpeakiontype); + fragmentIonType selectHigherPriorityIonTypeCID(fragmentIonType experimentalpeakiontype, fragmentIonType theoreticalpeakiontype); public: @@ -166,14 +161,14 @@ class cTheoreticalSpectrum { \brief Get the peptide spectrum candidate. \retval cCandidate reference to the peptide sequence candidate */ - cCandidate& cTheoreticalSpectrum::getCandidate(); + cCandidate& getCandidate(); /** \brief Set a peptide spectrum candidate. \param candidate reference to the peptide sequence candidate */ - void cTheoreticalSpectrum::setCandidate(cCandidate& candidate); + void setCandidate(cCandidate& candidate); /** @@ -220,7 +215,7 @@ class cTheoreticalSpectrum { /** - \brief Compare the theoretical spectrum of a lasso peptide with an experimental spectrum. + \brief Compare the theoretical spectrum of a branch-cyclic peptide with an experimental spectrum. \param sortedpeaklist reference to a peak list of an experimental spectrum \param bricksdatabasewithcombinations reference to a database of bricks with combinations of bricks \param writedescription if true then string descriptions of peaks are filled @@ -254,7 +249,7 @@ class cTheoreticalSpectrum { \brief Get the number of matched peaks between an experimental and a theoretical spectrum. \retval int number of matched peaks */ - int getNumberOfMatchedPeaks(); + int getNumberOfMatchedPeaks() const; /** @@ -269,14 +264,14 @@ class cTheoreticalSpectrum { \param iontype a fragment ion type \retval int number of matched peaks */ - int getNumberOfMatchedPeaks(fragmentIonType iontype); + int getNumberOfMatchedPeaks(fragmentIonType iontype) const; /** \brief Get the number of matched Y and B ions between an experimental and a theoretical spectrum. \retval int number of matched peaks */ - int getNumberOfMatchedPeaksYB(); + int getNumberOfMatchedPeaksYB() const; /** @@ -298,7 +293,6 @@ class cTheoreticalSpectrum { \brief Generate a N-terminal fragment ion series. \param maxcharge a charge of precursor ion \param peaklistrealsize real size of the peak list - \param stringcomposition reference to a vector of ids of bricks as strings \param intcomposition reference to a vector of ids of bricks as integers \param fragmentiontype fragment ion type which will be generated \param bricksdatabase reference to a database of building blocks @@ -309,14 +303,13 @@ class cTheoreticalSpectrum { \param peptidetype the type of searched peptide \param trotation a pointer to a T-permutation of a branched peptide */ - void generateNTerminalFragmentIons(int maxcharge, int& peaklistrealsize, vector& stringcomposition, vector& intcomposition, fragmentIonType fragmentiontype, cBricksDatabase& bricksdatabase, bool writedescription, int rotationid, vector& splittingsites, vector& searchedmodifications, peptideType peptidetype, TRotationInfo* trotation = 0); + void generateNTerminalFragmentIons(int maxcharge, int& peaklistrealsize, vector& intcomposition, fragmentIonType fragmentiontype, cBricksDatabase& bricksdatabase, bool writedescription, int rotationid, vector& splittingsites, vector& searchedmodifications, peptideType peptidetype, TRotationInfo* trotation = 0); /** \brief Generate a C-terminal fragment ion series. \param maxcharge a charge of precursor ion \param peaklistrealsize real size of the peak list - \param stringcomposition reference to a vector of ids of bricks as strings \param intcomposition reference to a vector of ids of bricks as integers \param fragmentiontype fragment ion type which will be generated \param bricksdatabase reference to a database of building blocks @@ -327,7 +320,7 @@ class cTheoreticalSpectrum { \param peptidetype the type of searched peptide \param trotation a pointer to a T-permutation of a branched peptide */ - void generateCTerminalFragmentIons(int maxcharge, int& peaklistrealsize, vector& stringcomposition, vector& intcomposition, fragmentIonType fragmentiontype, cBricksDatabase& bricksdatabase, bool writedescription, int rotationid, vector& splittingsites, vector& searchedmodifications, peptideType peptidetype, TRotationInfo* trotation = 0); + void generateCTerminalFragmentIons(int maxcharge, int& peaklistrealsize, vector& intcomposition, fragmentIonType fragmentiontype, cBricksDatabase& bricksdatabase, bool writedescription, int rotationid, vector& splittingsites, vector& searchedmodifications, peptideType peptidetype, TRotationInfo* trotation = 0); /** @@ -356,37 +349,7 @@ class cTheoreticalSpectrum { \brief Get the sum of relative intensities of matched peaks. \retval double sum of relative intensities of matched peaks */ - double getWeightedIntensityScore(); - - - /** - \brief Set a real peptide name. - \param bricksdatabase the database of building blocks - \param peptidetype the type of peptide - */ - void setRealPeptideName(cBricksDatabase& bricksdatabase, peptideType peptidetype); - - - /** - \brief Set an acronym peptide name. - \param bricksdatabase the database of building blocks - \param peptidetype the type of peptide - */ - void setAcronymPeptideNameWithHTMLReferences(cBricksDatabase& bricksdatabase, peptideType peptidetype); - - - /** - \brief Get a real peptide name. - \retval string reference to the real peptide name - */ - string& getRealPeptideName(); - - - /** - \brief Get an acronym peptide name. - \retval string reference to the acronym peptide name - */ - string& getAcronymPeptideNameWithHTMLReferences(); + double getWeightedIntensityScore() const; /** @@ -450,7 +413,7 @@ class cTheoreticalSpectrum { \brief Get the number of matched bricks. \retval int number of matched bricks */ - int getNumberOfMatchedBricks(); + int getNumberOfMatchedBricks() const; /** @@ -460,62 +423,6 @@ class cTheoreticalSpectrum { vector& getVisualCoverage(); - /** - \brief Set a vector of acronyms corresponding to a peptide sequence candidate. - \param bricksdatabase a database of building blocks - */ - void setAcronyms(cBricksDatabase& bricksdatabase); - - - /** - \brief Set a vector of acronyms corresponding to a backbone of a peptide sequence candidate. - \param bricksdatabase a database of building blocks - */ - void setBackboneAcronyms(cBricksDatabase& bricksdatabase); - - - /** - \brief Set a vector of acronyms corresponding to a branch of a peptide sequence candidate. - \param bricksdatabase a database of building blocks - */ - void setBranchAcronyms(cBricksDatabase& bricksdatabase); - - - /** - \brief Get a vector of acronyms corresponding to a peptide sequence candidate. - \retval vector a vector of acronyms - */ - vector& getAcronyms(); - - - /** - \brief Get a vector of acronyms corresponding to a backbone of a peptide sequence candidate. - \retval vector a vector of acronyms - */ - vector& getBackboneAcronyms(); - - - /** - \brief Get a vector of acronyms corresponding to a branch of a peptide sequence candidate. - \retval vector a vector of acronyms - */ - vector& getBranchAcronyms(); - - - /** - \brief Set a path in the de novo graph corresponding to the spectrum. - \param graph reference to the de novo graph - */ - void setPath(cDeNovoGraph& graph); - - - /** - \brief Get a path in the de novo graph corresponding to the spectrum. - \retval string reference to a path corresponding to the spectrum - */ - string& getPath(); - - /** \brief Get a number of series which identify the peptide. \retval int number of completed series @@ -553,11 +460,5 @@ class cTheoreticalSpectrum { }; -/** - \brief Register cTheoreticalSpectrum by Qt. -*/ -Q_DECLARE_METATYPE(cTheoreticalSpectrum); - - #endif diff --git a/CycloBranch/core/cTheoreticalSpectrumList.cpp b/CycloBranch/core/cTheoreticalSpectrumList.cpp index ad3a3ea..1addb34 100644 --- a/CycloBranch/core/cTheoreticalSpectrumList.cpp +++ b/CycloBranch/core/cTheoreticalSpectrumList.cpp @@ -48,6 +48,11 @@ void cTheoreticalSpectrumList::fixRegularExpression(string& s) { cTheoreticalSpectrumList::cTheoreticalSpectrumList() { + clear(); +} + + +void cTheoreticalSpectrumList::clear() { theoreticalspectra.clear(); os = 0; parameters = 0; @@ -55,6 +60,7 @@ cTheoreticalSpectrumList::cTheoreticalSpectrumList() { worstScore = 0; worstNumberOfMatchedPeaks = 0; + refreshlimit = 0; } @@ -132,7 +138,7 @@ int cTheoreticalSpectrumList::parallelCompareAndStore(cCandidateSet& candidates, try { rxsequencetag = stmp; } - catch (const std::regex_error& e) { + catch (regex_error& e) { *os << endl << endl << "Error: Bad Regular Expression in Peptide Sequence Tag." << endl << e.what() << endl; return -1; } @@ -154,7 +160,7 @@ int cTheoreticalSpectrumList::parallelCompareAndStore(cCandidateSet& candidates, try { rxsearchedsequence = stmp; } - catch (const std::regex_error& e) { + catch (regex_error& e) { *os << endl << endl << "Error: Bad Regular Expression in Searched Peptide Sequence." << endl << e.what() << endl; return -1; } @@ -273,15 +279,15 @@ int cTheoreticalSpectrumList::parallelCompareAndStore(cCandidateSet& candidates, // sort peaks in theoretical spectra by mass and set real names of peptides for (int i = 0; i < (int)theoreticalspectra.size(); i++) { theoreticalspectra[i].sortByMass(); - theoreticalspectra[i].setRealPeptideName(*bricksdb, parameters->peptidetype); - theoreticalspectra[i].setAcronymPeptideNameWithHTMLReferences(*bricksdb, parameters->peptidetype); - theoreticalspectra[i].setAcronyms(*bricksdb); + theoreticalspectra[i].getCandidate().setRealPeptideName(*bricksdb, parameters->peptidetype); + theoreticalspectra[i].getCandidate().setAcronymPeptideNameWithHTMLReferences(*bricksdb, parameters->peptidetype); + theoreticalspectra[i].getCandidate().setAcronyms(*bricksdb); if ((parameters->peptidetype == branched) || (parameters->peptidetype == lasso)) { - theoreticalspectra[i].setBackboneAcronyms(*bricksdb); - theoreticalspectra[i].setBranchAcronyms(*bricksdb); + theoreticalspectra[i].getCandidate().setBackboneAcronyms(*bricksdb); + theoreticalspectra[i].getCandidate().setBranchAcronyms(*bricksdb); } if (parameters->mode == denovoengine) { - theoreticalspectra[i].setPath(*graph); + theoreticalspectra[i].getCandidate().setPath(*graph, parameters); } // parameters must not be used by viewer, they are not stored/loaded theoreticalspectra[i].setParameters(0); @@ -316,13 +322,13 @@ void cTheoreticalSpectrumList::addButDoNotFitSize(cTheoreticalSpectrum& theoreti sort(theoreticalspectra.begin(), theoreticalspectra.end(), compareBandAllIonsDesc); worstScore = theoreticalspectra.back().getNumberOfMatchedPeaks(b_ion); break; - case b_ions_and_b_water_loss_ions: + case b_ions_and_b_dehydrated_ions: sort(theoreticalspectra.begin(), theoreticalspectra.end(), compareBBwaterLossAndAllIonsDesc); - worstScore = theoreticalspectra.back().getNumberOfMatchedPeaks(b_ion) + theoreticalspectra.back().getNumberOfMatchedPeaks(b_ion_water_loss); + worstScore = theoreticalspectra.back().getNumberOfMatchedPeaks(b_ion) + theoreticalspectra.back().getNumberOfMatchedPeaks(b_ion_dehydrated); break; - case b_ions_and_b_ammonia_loss_ions: + case b_ions_and_b_deamidated_ions: sort(theoreticalspectra.begin(), theoreticalspectra.end(), compareBBammoniaLossAndAllIonsDesc); - worstScore = theoreticalspectra.back().getNumberOfMatchedPeaks(b_ion) + theoreticalspectra.back().getNumberOfMatchedPeaks(b_ion_ammonia_loss); + worstScore = theoreticalspectra.back().getNumberOfMatchedPeaks(b_ion) + theoreticalspectra.back().getNumberOfMatchedPeaks(b_ion_deamidated); break; case y_ions_and_b_ions: sort(theoreticalspectra.begin(), theoreticalspectra.end(), compareYBandAllIonsDesc); @@ -358,14 +364,14 @@ void cTheoreticalSpectrumList::addButDoNotFitSize(cTheoreticalSpectrum& theoreti theoreticalspectra.back().resizePeakList(theoreticalpeaksrealsize); } break; - case b_ions_and_b_water_loss_ions: - if ((worstScore < theoreticalspectrum.getNumberOfMatchedPeaks(b_ion) + theoreticalspectrum.getNumberOfMatchedPeaks(b_ion_water_loss)) || ((worstScore == theoreticalspectrum.getNumberOfMatchedPeaks(b_ion) + theoreticalspectrum.getNumberOfMatchedPeaks(b_ion_water_loss)) && (worstNumberOfMatchedPeaks < theoreticalspectrum.getNumberOfMatchedPeaks()))) { + case b_ions_and_b_dehydrated_ions: + if ((worstScore < theoreticalspectrum.getNumberOfMatchedPeaks(b_ion) + theoreticalspectrum.getNumberOfMatchedPeaks(b_ion_dehydrated)) || ((worstScore == theoreticalspectrum.getNumberOfMatchedPeaks(b_ion) + theoreticalspectrum.getNumberOfMatchedPeaks(b_ion_dehydrated)) && (worstNumberOfMatchedPeaks < theoreticalspectrum.getNumberOfMatchedPeaks()))) { theoreticalspectra.push_back(theoreticalspectrum); theoreticalspectra.back().resizePeakList(theoreticalpeaksrealsize); } break; - case b_ions_and_b_ammonia_loss_ions: - if ((worstScore < theoreticalspectrum.getNumberOfMatchedPeaks(b_ion) + theoreticalspectrum.getNumberOfMatchedPeaks(b_ion_ammonia_loss)) || ((worstScore == theoreticalspectrum.getNumberOfMatchedPeaks(b_ion) + theoreticalspectrum.getNumberOfMatchedPeaks(b_ion_ammonia_loss)) && (worstNumberOfMatchedPeaks < theoreticalspectrum.getNumberOfMatchedPeaks()))) { + case b_ions_and_b_deamidated_ions: + if ((worstScore < theoreticalspectrum.getNumberOfMatchedPeaks(b_ion) + theoreticalspectrum.getNumberOfMatchedPeaks(b_ion_deamidated)) || ((worstScore == theoreticalspectrum.getNumberOfMatchedPeaks(b_ion) + theoreticalspectrum.getNumberOfMatchedPeaks(b_ion_deamidated)) && (worstNumberOfMatchedPeaks < theoreticalspectrum.getNumberOfMatchedPeaks()))) { theoreticalspectra.push_back(theoreticalspectrum); theoreticalspectra.back().resizePeakList(theoreticalpeaksrealsize); } @@ -410,15 +416,15 @@ void cTheoreticalSpectrumList::addButDoNotFitSize(cTheoreticalSpectrum& theoreti theoreticalspectra.resize(parameters->hitsreported); worstScore = theoreticalspectra.back().getNumberOfMatchedPeaks(b_ion); break; - case b_ions_and_b_water_loss_ions: + case b_ions_and_b_dehydrated_ions: sort(theoreticalspectra.begin(), theoreticalspectra.end(), compareBBwaterLossAndAllIonsDesc); theoreticalspectra.resize(parameters->hitsreported); - worstScore = theoreticalspectra.back().getNumberOfMatchedPeaks(b_ion) + theoreticalspectra.back().getNumberOfMatchedPeaks(b_ion_water_loss); + worstScore = theoreticalspectra.back().getNumberOfMatchedPeaks(b_ion) + theoreticalspectra.back().getNumberOfMatchedPeaks(b_ion_dehydrated); break; - case b_ions_and_b_ammonia_loss_ions: + case b_ions_and_b_deamidated_ions: sort(theoreticalspectra.begin(), theoreticalspectra.end(), compareBBammoniaLossAndAllIonsDesc); theoreticalspectra.resize(parameters->hitsreported); - worstScore = theoreticalspectra.back().getNumberOfMatchedPeaks(b_ion) + theoreticalspectra.back().getNumberOfMatchedPeaks(b_ion_ammonia_loss); + worstScore = theoreticalspectra.back().getNumberOfMatchedPeaks(b_ion) + theoreticalspectra.back().getNumberOfMatchedPeaks(b_ion_deamidated); break; case y_ions_and_b_ions: sort(theoreticalspectra.begin(), theoreticalspectra.end(), compareYBandAllIonsDesc); @@ -461,10 +467,10 @@ void cTheoreticalSpectrumList::sortAndFitSize() { case b_ions: sort(theoreticalspectra.begin(), theoreticalspectra.end(), compareBandAllIonsDesc); break; - case b_ions_and_b_water_loss_ions: + case b_ions_and_b_dehydrated_ions: sort(theoreticalspectra.begin(), theoreticalspectra.end(), compareBBwaterLossAndAllIonsDesc); break; - case b_ions_and_b_ammonia_loss_ions: + case b_ions_and_b_deamidated_ions: sort(theoreticalspectra.begin(), theoreticalspectra.end(), compareBBammoniaLossAndAllIonsDesc); break; case y_ions_and_b_ions: diff --git a/CycloBranch/core/cTheoreticalSpectrumList.h b/CycloBranch/core/cTheoreticalSpectrumList.h index 5d881a0..f0129ab 100644 --- a/CycloBranch/core/cTheoreticalSpectrumList.h +++ b/CycloBranch/core/cTheoreticalSpectrumList.h @@ -46,6 +46,12 @@ class cTheoreticalSpectrumList { cTheoreticalSpectrumList(); + /** + \brief Clear the class. + */ + void clear(); + + /** \brief Initialize the list. \param os reference to the main thread of the application diff --git a/CycloBranch/core/utilities.cpp b/CycloBranch/core/utilities.cpp index 9bf5d8f..f8868c3 100644 --- a/CycloBranch/core/utilities.cpp +++ b/CycloBranch/core/utilities.cpp @@ -1,5 +1,12 @@ #include "core/utilities.h" +#include "core/cBrick.h" + + +QString appname = "CycloBranch"; +QString appversion = "v. 1.0.1106 (64-bit)"; +QString linuxinstalldir = "/usr/share/cyclobranch/"; + void storeString(string& s, ofstream& os) { int size = (int)s.size(); @@ -34,3 +41,173 @@ void loadStringVector(vector& v, ifstream& is) { } } + +bool isWhiteSpaceExceptSpace(char c) { + return isspace(c) && (c != ' '); +} + + +string& removeWhiteSpacesExceptSpaces(string& s) { + s.erase(remove_if(begin(s), end(s), isWhiteSpaceExceptSpace), end(s)); + return s; +} + + +bool checkRegex(peptideType peptidetype, string& sequence, string& errormessage) { + errormessage = ""; + + if (sequence.compare("") == 0) { + errormessage = "The sequence is empty."; + return false; + } + + regex rx; + // [^\\[\\]]+ is used instead of .+ to prevent from a too complex regex error + switch (peptidetype) + { + case linear: + case linearpolysaccharide: + rx = "^\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*$"; + break; + case cyclic: + rx = "^\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])+$"; + break; + case branched: + rx = "^\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*\\\\\\(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])+\\\\\\)\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*$"; + break; + case lasso: + rx = "(^(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*)?\\\\\\(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])+\\\\\\)\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*$|^\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*\\\\\\(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])+\\\\\\)(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*)?$)"; + break; + case other: + default: + rx = ".*"; + break; + } + + try { + if (!(regex_search(sequence, rx))) { + errormessage = "The format of sequence '" + sequence + "' does not correspond to the sequence type '" + getStringFromPeptideType(peptidetype) + "'."; + return false; + } + } + catch (regex_error& e) { + errormessage = "checkRegex: regex_search failed, error no. " + to_string(e.code()); + return false; + } + + return true; +} + + +void parseBranch(peptideType peptidetype, string& composition, vector& vectorcomposition, int& branchstart, int& branchend) { + string s = composition; + cBrick b; + branchstart = -1; + branchend = -1; + + if ((peptidetype == branched) || (peptidetype == lasso)) { + int i = 0; + while (i < (int)s.size()) { + if (s[i] == '\\') { + s.erase(s.begin() + i); + } + else { + i++; + } + } + + for (int i = 0; i < (int)s.size(); i++) { + if (s[i] == '(') { + if (i > 0) { + b.clear(); + b.setComposition(s.substr(0, i - 1), false); + branchstart = getNumberOfBricks(b.getComposition()); + s[i] = '-'; + } + else { + s.erase(s.begin()); + branchstart = 0; + } + break; + } + } + + for (int i = 0; i < (int)s.size(); i++) { + if (s[i] == ')') { + b.clear(); + b.setComposition(s.substr(0, i - 1), false); + branchend = getNumberOfBricks(b.getComposition()) - 1; + if (i < (int)s.size() - 1) { + s[i] = '-'; + } + else { + s.erase(s.begin() + i); + } + break; + } + } + + if (branchend <= branchstart) { + branchstart = -1; + branchend = -1; + } + } + + b.clear(); + b.setComposition(s, false); + b.explodeToStringComposition(vectorcomposition); +} + + +peptideType getPeptideTypeFromString(string s) { + if (s.compare("linear") == 0) { + return linear; + } + if (s.compare("cyclic") == 0) { + return cyclic; + } + if (s.compare("branched") == 0) { + return branched; + } + if (s.compare("branch-cyclic") == 0) { + return lasso; + } + if (s.compare("linearpolysaccharide") == 0) { + return linearpolysaccharide; + } + if (s.compare("other") == 0) { + return other; + } + + return other; +} + + +string getStringFromPeptideType(peptideType peptidetype) { + switch (peptidetype) + { + case linear: + return "linear"; + break; + case cyclic: + return "cyclic"; + break; + case branched: + return "branched"; + break; + case lasso: + return "branch-cyclic"; + break; + case linearpolysaccharide: + return "linearpolysaccharide"; + break; + case other: + return "other"; + break; + default: + break; + } + + return "other"; +} + diff --git a/CycloBranch/core/utilities.h b/CycloBranch/core/utilities.h index 21a3272..bdff4c4 100644 --- a/CycloBranch/core/utilities.h +++ b/CycloBranch/core/utilities.h @@ -10,9 +10,57 @@ #include #include #include +#include +#include + +class cBrick; + + +#define WIN 0 // Windows +#define UNX 1 // Linux/UNIX + +#ifdef UNIX + #define OS_TYPE UNX + #define sscanf_s sscanf + #define sprintf_s sprintf +#else + #define OS_TYPE WIN +#endif using namespace std; +using namespace boost; + + +/** + \brief The types of peptides supported by the application. +*/ +enum peptideType { + linear = 0, + cyclic = 1, + branched = 2, + lasso = 3, + linearpolysaccharide = 4, + other = 5 +}; + + +/** + \brief The name of the application. +*/ +extern QString appname; + + +/** + \brief The version of the application. +*/ +extern QString appversion; + + +/** + \brief A directory where the application is installed in Linux. +*/ +extern QString linuxinstalldir; /** @@ -47,5 +95,58 @@ void storeStringVector(vector& v, ofstream& os); void loadStringVector(vector& v, ifstream& is); +/** + \brief Check if \a c is a white space (except normal space). + \param c char + \retval bool true if \a c is a white space (except normal space); false otherwise. +*/ +bool isWhiteSpaceExceptSpace(char c); + + +/** + \brief Remove white spaces except normal spaces from a string. + \param s reference to a string + \retval string reference to the input string +*/ +string& removeWhiteSpacesExceptSpaces(string& s); + + +/** + \brief Check the syntax of a peptide sequence. + \param peptidetype peptide type + \param sequence peptide sequence + \param errormessage an error message if false is returned + \retval bool true when the syntax is correct, false otherwise +*/ +bool checkRegex(peptideType peptidetype, string& sequence, string& errormessage); + + +/** + \brief Parse a position of a branch from a peptide sequence. + \param peptidetype peptide type + \param composition a peptide sequence where all blocks "[blockX]-[blockY]" were replaced by ids "1-2"; but "\(" and "\)" are still included + \param vectorcomposition an output vector with ids of blocks represented as strings + \param branchstart start position of a branch (an output value) + \param branchend end position of a branch (an output value) +*/ +void parseBranch(peptideType peptidetype, string& composition, vector& vectorcomposition, int& branchstart, int& branchend); + + +/** + \brief Convert a string to peptide type. + \param s string + \retval peptideType type of peptide +*/ +peptideType getPeptideTypeFromString(string s); + + +/** + \brief Convert the peptide type to a string. + \param peptidetype type of peptide + \retval string string +*/ +string getStringFromPeptideType(peptideType peptidetype); + + #endif diff --git a/CycloBranch/cyclobranch.rc b/CycloBranch/cyclobranch.rc new file mode 100644 index 0000000..4fe2776 --- /dev/null +++ b/CycloBranch/cyclobranch.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "images/cb.ico" \ No newline at end of file diff --git a/CycloBranch/gui/cAboutWidget.cpp b/CycloBranch/gui/cAboutWidget.cpp index 75401aa..0fc521d 100644 --- a/CycloBranch/gui/cAboutWidget.cpp +++ b/CycloBranch/gui/cAboutWidget.cpp @@ -4,21 +4,35 @@ #include #include #include - +#include +#include cAboutWidget::cAboutWidget(QWidget* parent) { this->parent = parent; setWindowTitle("About..."); + setWindowIcon(QIcon(":/images/icons/48.png")); layout = new QVBoxLayout(); + QString title = "A tool for de novo sequencing of nonribosomal peptides from accurate product ion mass spectra.


"; + + QString licence = "Licence:

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

"; + licence += "This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

"; + licence += "You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.


"; + + QString developers = "Developers:

Jiri Novak
Laboratory of Molecular Structure Characterization
Institute of Microbiology
Academy of Sciences of the Czech Republic
Videnska 1083
142 20 Prague
Czech Republic
jiri.novak@biomed.cas.cz
http://ms.biomed.cas.cz/cyclobranch/
http://ms.biomed.cas.cz/staff-novak_jiri.php
https://cas-cz.academia.edu/JiriNovak

(C) 2013 - 2015


"; + + QString splash = "



"; + + QString acknowledgement = "Acknowledgements:

http://www.aha-soft.com/


"; + message = new QTextBrowser(); message->setReadOnly(true); message->setAcceptRichText(true); message->setOpenExternalLinks(true); - message->setHtml(appname + " " + appversion + "

Developers:

Jiri Novak
Laboratory of Molecular Structure Characterization
Institute of Microbiology
Academy of Sciences of the Czech Republic
Videnska 1083
142 20 Prague
Czech Republic
jiri.novak@biomed.cas.cz
http://ms.biomed.cas.cz/cyclobranch/
http://ms.biomed.cas.cz/staff-novak_jiri.php
https://cas-cz.academia.edu/JiriNovak

(C) 2013-2014"); + message->setHtml("
" + splash + "" + appname + " " + appversion + "

" + title + developers /*+ licence*/ + acknowledgement); buttonbox = new QDialogButtonBox(QDialogButtonBox::Ok); //buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); @@ -31,7 +45,7 @@ cAboutWidget::cAboutWidget(QWidget* parent) { setLayout(layout); - resize(600, 400); + resize(800, 600); } @@ -47,6 +61,13 @@ void cAboutWidget::closeEvent(QCloseEvent *event) { } +void cAboutWidget::keyPressEvent(QKeyEvent *event) { + if(event->key() == Qt::Key_Escape) { + hide(); + } +} + + void cAboutWidget::accept() { hide(); //parent->setEnabled(true); diff --git a/CycloBranch/gui/cAboutWidget.h b/CycloBranch/gui/cAboutWidget.h index f787147..e8ef446 100644 --- a/CycloBranch/gui/cAboutWidget.h +++ b/CycloBranch/gui/cAboutWidget.h @@ -46,6 +46,16 @@ class cAboutWidget : public QWidget void closeEvent(QCloseEvent *event); +protected: + + + /** + \brief Handle a key press event. + \param event pointer to QKeyEvent + */ + void keyPressEvent(QKeyEvent *event); + + private: QWidget* parent; QVBoxLayout* layout; diff --git a/CycloBranch/gui/cBranchedWidget.cpp b/CycloBranch/gui/cBranchedWidget.cpp index 324f9d5..ea01478 100644 --- a/CycloBranch/gui/cBranchedWidget.cpp +++ b/CycloBranch/gui/cBranchedWidget.cpp @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include cBranchedWidget::cBranchedWidget() { @@ -19,18 +22,97 @@ void cBranchedWidget::initialize(cParameters* parameters, cTheoreticalSpectrum* } +void cBranchedWidget::exportToPDF(QString filename, bool postscript) { + QPrinter printer; + if (postscript) { + printer.setPaperSize(QSizeF(width() + 100, height() + 100), QPrinter::DevicePixel); + printer.setPageMargins (50, 50, 50, 50, QPrinter::DevicePixel); + } + else { + printer.setPaperSize(QSizeF(width(), height()), QPrinter::DevicePixel); + printer.setPageMargins (0, 0, 0, 0, QPrinter::DevicePixel); + } + printer.setOutputFormat(QPrinter::NativeFormat); + printer.setOutputFileName(filename); + + QPainter painter; + if (!painter.begin(&printer)) { + QMessageBox msgBox; + QString errstr = "The file cannot be created."; + #if OS_TYPE == UNX + errstr += "\nDo you have a properly configured print server (sudo apt-get install cups-pdf) ?"; + errstr += "\nIf you cannot create a ps file, you can create a pdf file and then use pdf2ps tool."; + #endif + msgBox.setText(errstr); + msgBox.exec(); + return; + } + + painter.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing|QPainter::SmoothPixmapTransform); + paint(painter); + painter.end(); +} + + +void cBranchedWidget::exportToPNG(QString filename) { + QImage image(width(), height(), QImage::Format_ARGB32); + image.fill(Qt::white); + + QPainter painter; + if (!painter.begin(&image)) { + QMessageBox msgBox; + QString errstr = "The file cannot be created."; + msgBox.setText(errstr); + msgBox.exec(); + return; + } + + painter.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing|QPainter::SmoothPixmapTransform); + paint(painter); + painter.end(); + image.save(filename); +} + + +void cBranchedWidget::exportToSVG(QString filename) { + QSvgGenerator generator; + generator.setFileName(filename); + generator.setSize(QSize(width(), height())); + generator.setViewBox(QRect(0, 0, width(), height())); + + QPainter painter; + if (!painter.begin(&generator)) { + QMessageBox msgBox; + QString errstr = "The file cannot be created."; + msgBox.setText(errstr); + msgBox.exec(); + return; + } + + paint(painter); + painter.end(); +} + + void cBranchedWidget::paintEvent(QPaintEvent *event) { + QPainter painter; + painter.begin(this); + paint(painter); + painter.end(); +} + - if (theoreticalspectrum->getVisualCoverage().size() == 0) { +void cBranchedWidget::paint(QPainter& painter) { + + if (!theoreticalspectrum) { return; } vector backboneacronyms; vector branchacronyms; - backboneacronyms = theoreticalspectrum->getBackboneAcronyms(); - branchacronyms = theoreticalspectrum->getBranchAcronyms(); + backboneacronyms = theoreticalspectrum->getCandidate().getBackboneAcronyms(); + branchacronyms = theoreticalspectrum->getCandidate().getBranchAcronyms(); - QPainter painter(this); const int topmargin = 20; const int leftmargin = 20; const int bottommargin = 80; @@ -46,11 +128,17 @@ void cBranchedWidget::paintEvent(QPaintEvent *event) { const int verticalstep = (height() - topmargin - bottommargin)/std::max(branchsize, 1); QFont myFont("Courier", 9); + QFontMetrics fm(myFont); painter.setFont(myFont); for (int i = 0; i < backbonesize; i++) { painter.setPen(QPen(Qt::blue, 2, Qt::SolidLine)); - painter.drawText(leftmargin + horizontalstep/4 + horizontalstep*i, topmargin + verticalstep*branchsize, horizontalstep/2, 20, Qt::AlignCenter, backboneacronyms[i].c_str()); + if (fm.width(backboneacronyms[i].c_str()) > horizontalstep/2) { + painter.drawText(leftmargin + horizontalstep/4 + horizontalstep*i + 2, topmargin + verticalstep*branchsize, horizontalstep/2 - 2, 20, Qt::AlignLeft|Qt::AlignVCenter, backboneacronyms[i].c_str()); + } + else { + painter.drawText(leftmargin + horizontalstep/4 + horizontalstep*i, topmargin + verticalstep*branchsize, horizontalstep/2, 20, Qt::AlignCenter, backboneacronyms[i].c_str()); + } painter.setPen(QPen(Qt::black, 2, Qt::SolidLine)); painter.drawRect(leftmargin + horizontalstep/4 + horizontalstep*i, topmargin + verticalstep*branchsize, horizontalstep/2, 20); @@ -58,231 +146,244 @@ void cBranchedWidget::paintEvent(QPaintEvent *event) { if (i < backbonesize - 1) { painter.setPen(QPen(Qt::black, 2, Qt::SolidLine)); painter.drawLine(leftmargin + horizontalstep/4 + horizontalstep*i + horizontalstep/2, topmargin + verticalstep*branchsize + 11, leftmargin + horizontalstep/4 + horizontalstep*(i + 1), topmargin + verticalstep*branchsize + 11); - painter.setPen(QPen(Qt::black, 2, Qt::DashLine)); - painter.drawLine(leftmargin + horizontalstep*(i + 1), topmargin + verticalstep*branchsize - 10, leftmargin + horizontalstep*(i + 1), topmargin + verticalstep*branchsize + 30); - painter.drawLine(leftmargin + horizontalstep/4 + horizontalstep/8 + horizontalstep*i + horizontalstep/2, topmargin + verticalstep*branchsize - 10, leftmargin + horizontalstep*(i + 1), topmargin + verticalstep*branchsize - 10); - painter.drawLine(leftmargin + horizontalstep*(i + 1), topmargin + verticalstep*branchsize + 30, leftmargin + horizontalstep*(i + 1) + horizontalstep/8, topmargin + verticalstep*branchsize + 30); + if (theoreticalspectrum->getVisualCoverage().size() > 0) { + painter.setPen(QPen(Qt::black, 2, Qt::DashLine)); + painter.drawLine(leftmargin + horizontalstep*(i + 1), topmargin + verticalstep*branchsize - 10, leftmargin + horizontalstep*(i + 1), topmargin + verticalstep*branchsize + 30); + painter.drawLine(leftmargin + horizontalstep/4 + horizontalstep/8 + horizontalstep*i + horizontalstep/2, topmargin + verticalstep*branchsize - 10, leftmargin + horizontalstep*(i + 1), topmargin + verticalstep*branchsize - 10); + painter.drawLine(leftmargin + horizontalstep*(i + 1), topmargin + verticalstep*branchsize + 30, leftmargin + horizontalstep*(i + 1) + horizontalstep/8, topmargin + verticalstep*branchsize + 30); + } } } for (int i = 0; i < branchsize; i++) { painter.setPen(QPen(Qt::blue, 2, Qt::SolidLine)); - painter.drawText(leftmargin + horizontalstep/4 + horizontalstep*tpermutations[0].middlebranchstart, topmargin + verticalstep*i, horizontalstep/2, 20, Qt::AlignCenter, branchacronyms[branchsize - i - 1].c_str()); + if (fm.width(branchacronyms[branchsize - i - 1].c_str()) > horizontalstep/2) { + painter.drawText(leftmargin + horizontalstep/4 + horizontalstep*tpermutations[0].middlebranchstart + 2, topmargin + verticalstep*i, horizontalstep/2 - 2, 20, Qt::AlignLeft|Qt::AlignVCenter, branchacronyms[branchsize - i - 1].c_str()); + } + else { + painter.drawText(leftmargin + horizontalstep/4 + horizontalstep*tpermutations[0].middlebranchstart, topmargin + verticalstep*i, horizontalstep/2, 20, Qt::AlignCenter, branchacronyms[branchsize - i - 1].c_str()); + } painter.setPen(QPen(Qt::black, 2, Qt::SolidLine)); painter.drawRect(leftmargin + horizontalstep/4 + horizontalstep*tpermutations[0].middlebranchstart, topmargin + verticalstep*i, horizontalstep/2, 20); painter.setPen(QPen(Qt::black, 2, Qt::SolidLine)); painter.drawLine(leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart, topmargin + verticalstep*i + 20, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart, topmargin + verticalstep*i + verticalstep); - painter.setPen(QPen(Qt::black, 2, Qt::DashLine)); - painter.drawLine(leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart - 20, topmargin + verticalstep*i + (verticalstep + 10)/2, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart + 20, topmargin + verticalstep*i + (verticalstep + 10)/2); - painter.drawLine(leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart - 20, topmargin + verticalstep*i + (verticalstep + 10)/2, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart - 20, topmargin + verticalstep*i + (verticalstep + 10)/2 + verticalstep/8); - painter.drawLine(leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart + 20, topmargin + verticalstep*i + (verticalstep + 10)/2 - verticalstep/8, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart + 20, topmargin + verticalstep*i + (verticalstep + 10)/2); + if (theoreticalspectrum->getVisualCoverage().size() > 0) { + painter.setPen(QPen(Qt::black, 2, Qt::DashLine)); + painter.drawLine(leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart - 20, topmargin + verticalstep*i + (verticalstep + 10)/2, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart + 20, topmargin + verticalstep*i + (verticalstep + 10)/2); + painter.drawLine(leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart - 20, topmargin + verticalstep*i + (verticalstep + 10)/2, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart - 20, topmargin + verticalstep*i + (verticalstep + 10)/2 + verticalstep/8); + painter.drawLine(leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart + 20, topmargin + verticalstep*i + (verticalstep + 10)/2 - verticalstep/8, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart + 20, topmargin + verticalstep*i + (verticalstep + 10)/2); + } } - unordered_set labels; - labels.clear(); + if (parameters && (theoreticalspectrum->getVisualCoverage().size() > 0)) { + + unordered_set labels; + labels.clear(); - int position; - string name; - int len = (int)theoreticalspectrum->getVisualCoverage()[0].series.size(); - for (int i = 0; i < 6; i++) { + int position; + string name; + int len = (int)theoreticalspectrum->getVisualCoverage()[0].series.size(); + for (int i = 0; i < 6; i++) { - if ((visibletrotationid != -1) && (visibletrotationid != i)) { - continue; - } + if ((visibletrotationid != -1) && (visibletrotationid != i)) { + continue; + } - for (int j = 0; j < (int)parameters->fragmentionsfortheoreticalspectra.size(); j++) { + for (int j = 0; j < (int)parameters->fragmentionsfortheoreticalspectra.size(); j++) { - position = 0; - if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].nterminal) { - for (int k = 0; k < len; k++) { - switch (i) - { - case 0: - if ((k < tpermutations[i].middlebranchstart) || (k >= tpermutations[i].middlebranchend)) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep/4 + horizontalstep/8 + horizontalstep*position + horizontalstep/2, topmargin + verticalstep*branchsize - 35, name, false); + position = 0; + if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].nterminal) { + for (int k = 0; k < len; k++) { + switch (i) + { + case 0: + if ((k < tpermutations[i].middlebranchstart) || (k >= tpermutations[i].middlebranchend)) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep/4 + horizontalstep/8 + horizontalstep*position + horizontalstep/2, topmargin + verticalstep*branchsize - 35, name, false); + } + position++; } - position++; - } - break; - case 1: - if (k < tpermutations[i].middlebranchstart) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart + 25, topmargin + verticalstep*k + verticalstep/2 - verticalstep/8, name, false); + break; + case 1: + if (k < tpermutations[i].middlebranchstart) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart + 25, topmargin + verticalstep*k + verticalstep/2 - verticalstep/8, name, false); + } } - } - if (k >= tpermutations[i].middlebranchend) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep/4 + horizontalstep/8 + horizontalstep*(position + tpermutations[i].middlebranchend - tpermutations[i].middlebranchstart) + horizontalstep/2, topmargin + verticalstep*branchsize - 35, name, false); + if (k >= tpermutations[i].middlebranchend) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep/4 + horizontalstep/8 + horizontalstep*(position + tpermutations[i].middlebranchend - tpermutations[i].middlebranchstart) + horizontalstep/2, topmargin + verticalstep*branchsize - 35, name, false); + } + position++; } - position++; - } - break; - case 2: - if ((k < tpermutations[i].middlebranchstart) || (k >= tpermutations[i].middlebranchend)) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep*(backbonesize - position - 2 + 1), topmargin + verticalstep*branchsize + 35, name, false); + break; + case 2: + if ((k < tpermutations[i].middlebranchstart) || (k >= tpermutations[i].middlebranchend)) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep*(backbonesize - position - 2 + 1), topmargin + verticalstep*branchsize + 35, name, false); + } + position++; } - position++; - } - break; - case 3: - if (k < tpermutations[i].middlebranchstart) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep/4 + horizontalstep/8 + horizontalstep*position + horizontalstep/2, topmargin + verticalstep*branchsize - 35, name, false); + break; + case 3: + if (k < tpermutations[i].middlebranchstart) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep/4 + horizontalstep/8 + horizontalstep*position + horizontalstep/2, topmargin + verticalstep*branchsize - 35, name, false); + } + position++; } - position++; - } - if (k >= tpermutations[i].middlebranchend) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart - 25, topmargin + verticalstep*(branchsize - k - 2 + backbonesize) + verticalstep/2, name, true); + if (k >= tpermutations[i].middlebranchend) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart - 25, topmargin + verticalstep*(branchsize - k - 2 + backbonesize) + verticalstep/2, name, true); + } } - } - break; - case 4: - if (k < tpermutations[i].middlebranchstart) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart + 25, topmargin + verticalstep*k + verticalstep/2 - verticalstep/8, name, false); + break; + case 4: + if (k < tpermutations[i].middlebranchstart) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart + 25, topmargin + verticalstep*k + verticalstep/2 - verticalstep/8, name, false); + } } - } - if (k >= tpermutations[i].middlebranchend) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep*(backbonesize - tpermutations[i].middlebranchend + tpermutations[i].middlebranchstart - position - 2 + 1), topmargin + verticalstep*branchsize + 35, name, false); + if (k >= tpermutations[i].middlebranchend) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep*(backbonesize - tpermutations[i].middlebranchend + tpermutations[i].middlebranchstart - position - 2 + 1), topmargin + verticalstep*branchsize + 35, name, false); + } + position++; } - position++; - } - break; - case 5: - if (k < tpermutations[i].middlebranchstart) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep*(backbonesize - position - 2 + 1), topmargin + verticalstep*branchsize + 35, name, false); + break; + case 5: + if (k < tpermutations[i].middlebranchstart) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep*(backbonesize - position - 2 + 1), topmargin + verticalstep*branchsize + 35, name, false); + } + position++; } - position++; - } - if (k >= tpermutations[i].middlebranchend) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart - 25, topmargin + verticalstep*(branchsize - k - 2 + backbonesize) + verticalstep/2, name, true); + if (k >= tpermutations[i].middlebranchend) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[k] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(k + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart - 25, topmargin + verticalstep*(branchsize - k - 2 + backbonesize) + verticalstep/2, name, true); + } } + break; + default: + break; } - break; - default: - break; } } - } - position = 0; - if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].cterminal) { - for (int k = len - 1; k >= 0; k--) { - switch (i) - { - case 0: - if ((k < tpermutations[i].middlebranchstart) || (k >= tpermutations[i].middlebranchend)) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep*(backbonesize - position - 1), topmargin + verticalstep*branchsize + 35, name, false); + position = 0; + if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].cterminal) { + for (int k = len - 1; k >= 0; k--) { + switch (i) + { + case 0: + if ((k < tpermutations[i].middlebranchstart) || (k >= tpermutations[i].middlebranchend)) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep*(backbonesize - position - 1), topmargin + verticalstep*branchsize + 35, name, false); + } + position++; } - position++; - } - break; - case 1: - if (k < tpermutations[i].middlebranchstart) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart - 25, topmargin + verticalstep*k + verticalstep/2, name, true); + break; + case 1: + if (k < tpermutations[i].middlebranchstart) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart - 25, topmargin + verticalstep*k + verticalstep/2, name, true); + } } - } - if (k >= tpermutations[i].middlebranchend) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep*(backbonesize - position - 1), topmargin + verticalstep*branchsize + 35, name, false); + if (k >= tpermutations[i].middlebranchend) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep*(backbonesize - position - 1), topmargin + verticalstep*branchsize + 35, name, false); + } + position++; } - position++; - } - break; - case 2: - if ((k < tpermutations[i].middlebranchstart) || (k >= tpermutations[i].middlebranchend)) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep*position + horizontalstep/2 + horizontalstep/4 + horizontalstep/8, topmargin + verticalstep*branchsize - 35, name, false); + break; + case 2: + if ((k < tpermutations[i].middlebranchstart) || (k >= tpermutations[i].middlebranchend)) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep*position + horizontalstep/2 + horizontalstep/4 + horizontalstep/8, topmargin + verticalstep*branchsize - 35, name, false); + } + position++; } - position++; - } - break; - case 3: - if (k < tpermutations[i].middlebranchstart) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep*(backbonesize - position - tpermutations[i].middlebranchend + tpermutations[i].middlebranchstart - 1), topmargin + verticalstep*branchsize + 35, name, false); + break; + case 3: + if (k < tpermutations[i].middlebranchstart) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep*(backbonesize - position - tpermutations[i].middlebranchend + tpermutations[i].middlebranchstart - 1), topmargin + verticalstep*branchsize + 35, name, false); + } + position++; } - position++; - } - if (k >= tpermutations[i].middlebranchend) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart + 25, topmargin + verticalstep*(branchsize - k - 2 + backbonesize) + verticalstep/2 - verticalstep/8, name, false); + if (k >= tpermutations[i].middlebranchend) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart + 25, topmargin + verticalstep*(branchsize - k - 2 + backbonesize) + verticalstep/2 - verticalstep/8, name, false); + } } - } - break; - case 4: - if (k < tpermutations[i].middlebranchstart) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart - 25, topmargin + verticalstep*k + verticalstep/2, name, true); + break; + case 4: + if (k < tpermutations[i].middlebranchstart) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart - 25, topmargin + verticalstep*k + verticalstep/2, name, true); + } } - } - if (k >= tpermutations[i].middlebranchend) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep*position + horizontalstep/2 + horizontalstep/4 + horizontalstep/8, topmargin + verticalstep*branchsize - 35, name, false); + if (k >= tpermutations[i].middlebranchend) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep*position + horizontalstep/2 + horizontalstep/4 + horizontalstep/8, topmargin + verticalstep*branchsize - 35, name, false); + } + position++; } - position++; - } - break; - case 5: - if (k < tpermutations[i].middlebranchstart) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep*(position + tpermutations[i].middlebranchend - tpermutations[i].middlebranchstart) + horizontalstep/2 + horizontalstep/4 + horizontalstep/8, topmargin + verticalstep*branchsize - 35, name, false); + break; + case 5: + if (k < tpermutations[i].middlebranchstart) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep*(position + tpermutations[i].middlebranchend - tpermutations[i].middlebranchstart) + horizontalstep/2 + horizontalstep/4 + horizontalstep/8, topmargin + verticalstep*branchsize - 35, name, false); + } + position++; } - position++; - } - if (k >= tpermutations[i].middlebranchend) { - if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { - name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart + 25, topmargin + verticalstep*(branchsize - k - 2 + backbonesize) + verticalstep/2 - verticalstep/8, name, false); + if (k >= tpermutations[i].middlebranchend) { + if (theoreticalspectrum->getVisualCoverage()[i*parameters->fragmentionsfortheoreticalspectra.size() + j].series[len - k - 1] > 0) { + name = to_string(i + 1) + "_" + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name[0] + to_string(len - k) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[j]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep/2 + horizontalstep*tpermutations[0].middlebranchstart + 25, topmargin + verticalstep*(branchsize - k - 2 + backbonesize) + verticalstep/2 - verticalstep/8, name, false); + } } + break; + default: + break; } - break; - default: - break; } } - } + } } - } - painter.setPen(QPen(Qt::red, 2, Qt::SolidLine)); - for (auto it = labels.begin(); it != labels.end(); ++it) { - if (it->alignright) { - painter.drawText(it->x - (int)it->label.size()*7, it->y, (int)it->label.size()*7, 20, Qt::AlignLeft, it->label.c_str()); - } - else { - painter.drawText(it->x, it->y, width(), 20, Qt::AlignLeft, it->label.c_str()); + painter.setPen(QPen(Qt::red, 2, Qt::SolidLine)); + for (auto it = labels.begin(); it != labels.end(); ++it) { + if (it->alignright) { + painter.drawText(it->x - fm.width(it->label.c_str()), it->y, fm.width(it->label.c_str()), 20, Qt::AlignLeft, it->label.c_str()); + } + else { + painter.drawText(it->x, it->y, width(), 20, Qt::AlignLeft, it->label.c_str()); + } } + } } diff --git a/CycloBranch/gui/cBranchedWidget.h b/CycloBranch/gui/cBranchedWidget.h index 1f8b9f2..74f27ae 100644 --- a/CycloBranch/gui/cBranchedWidget.h +++ b/CycloBranch/gui/cBranchedWidget.h @@ -40,6 +40,28 @@ class cBranchedWidget : public QWidget void initialize(cParameters* parameters, cTheoreticalSpectrum* theoreticalspectrum); + /** + \brief Export peptide into a PDF or a PS file. + \param filename filename + \param postscript if true then PS file is generated instead of PDF + */ + void exportToPDF(QString filename, bool postscript); + + + /** + \brief Export peptide scene into a PNG file. + \param filename filename + */ + void exportToPNG(QString filename); + + + /** + \brief Export peptide scene into a SVG file. + \param filename filename + */ + void exportToSVG(QString filename); + + protected: @@ -52,6 +74,8 @@ class cBranchedWidget : public QWidget private: + void paint(QPainter& painter); + cParameters* parameters; cTheoreticalSpectrum* theoreticalspectrum; int visibletrotationid; diff --git a/CycloBranch/gui/cBricksDatabaseWidget.cpp b/CycloBranch/gui/cBricksDatabaseWidget.cpp index bae78d0..81dec94 100644 --- a/CycloBranch/gui/cBricksDatabaseWidget.cpp +++ b/CycloBranch/gui/cBricksDatabaseWidget.cpp @@ -1,5 +1,6 @@ #include "gui/cBricksDatabaseWidget.h" #include "gui/cMainThread.h" +#include "gui/cEventFilter.h" #include #include @@ -12,9 +13,11 @@ #include #include #include +#include +#include -int numberOfOccurrences(string& s, char c) { +int numberOfOccurrences(const string& s, char c) { int count = 0; for (int i = 0; i < (int)s.size(); i++) { if (s[i] == c) { @@ -29,6 +32,7 @@ cBricksDatabaseWidget::cBricksDatabaseWidget(QWidget* parent) { this->parent = parent; setWindowTitle("Building Blocks Editor"); + setWindowIcon(QIcon(":/images/icons/68.png")); insertrow = new QPushButton(tr("Add Row")); insertrow->setToolTip("Add a new row."); @@ -56,13 +60,20 @@ cBricksDatabaseWidget::cBricksDatabaseWidget(QWidget* parent) { database = new QTableWidget(0, 0, this); database->setColumnCount(7); - database->setHorizontalHeaderItem(0, new QTableWidgetItem("")); - database->setHorizontalHeaderItem(1, new QTableWidgetItem("Name(s)")); - database->setHorizontalHeaderItem(2, new QTableWidgetItem("Acronym(s)")); - database->setHorizontalHeaderItem(3, new QTableWidgetItem("Residue Summary")); - database->setHorizontalHeaderItem(4, new QTableWidgetItem("Monoisotopic Residue Mass")); - database->setHorizontalHeaderItem(5, new QTableWidgetItem("Reference(s)")); - database->setHorizontalHeaderItem(6, new QTableWidgetItem("Preview")); + database->setHorizontalHeaderItem(0, new QTableWidgetItem()); + database->setHorizontalHeaderItem(1, new QTableWidgetItem()); + database->horizontalHeaderItem(1)->setText("Name(s)"); + database->setHorizontalHeaderItem(2, new QTableWidgetItem()); + database->horizontalHeaderItem(2)->setText("Acronym(s)"); + database->setHorizontalHeaderItem(3, new QTableWidgetItem()); + database->horizontalHeaderItem(3)->setText("Residue Summary"); + database->setHorizontalHeaderItem(4, new QTableWidgetItem()); + database->horizontalHeaderItem(4)->setText("Monoisotopic Residue Mass"); + database->setHorizontalHeaderItem(5, new QTableWidgetItem()); + database->horizontalHeaderItem(5)->setText("Reference(s)"); + database->setHorizontalHeaderItem(6, new QTableWidgetItem()); + database->horizontalHeaderItem(6)->setText("Preview"); + database->horizontalHeader()->setStretchLastSection(true); for (int i = 0; i < database->columnCount(); i++) { database->resizeColumnToContents(i); @@ -77,11 +88,6 @@ cBricksDatabaseWidget::cBricksDatabaseWidget(QWidget* parent) { mainlayout->addWidget(database); mainlayout->addLayout(buttons); - progress = new QProgressDialog(this); - progress->setCancelButton(0); - progress->setMinimumDuration(1000); - progress->setWindowModality(Qt::WindowModal); - connect(database->horizontalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(headerItemDoubleClicked(int))); connect(database, SIGNAL(itemChanged(QTableWidgetItem *)), this, SLOT(itemChanged(QTableWidgetItem *))); connect(insertrow, SIGNAL(released()), this, SLOT(addRow())); @@ -96,7 +102,13 @@ cBricksDatabaseWidget::cBricksDatabaseWidget(QWidget* parent) { resize(1280, 700); databasefile = ""; - lastdir = "./BrickDatabases/"; + + #if OS_TYPE == WIN + lastdir = "./BrickDatabases/"; + #else + lastdir = linuxinstalldir + "BrickDatabases/"; + #endif + bricks.clear(); } @@ -119,7 +131,6 @@ cBricksDatabaseWidget::~cBricksDatabaseWidget() { delete database; delete buttons; delete mainlayout; - delete progress; } @@ -129,47 +140,51 @@ void cBricksDatabaseWidget::closeEvent(QCloseEvent *event) { void cBricksDatabaseWidget::deleteTable(bool enableprogress) { + QProgressDialog* progress; + cEventFilter filter; + int rowcount = database->rowCount(); + if (enableprogress) { - progress->setLabelText("Clearing the table..."); - progress->setMinimum(0); - progress->setValue(1); - progress->setMaximum(database->rowCount()); - progress->show(); + progress = new QProgressDialog("Clearing the table...", /*"Cancel"*/0, 0, rowcount, this); + progress->installEventFilter(&filter); + progress->setMinimumDuration(0); + progress->setWindowModality(Qt::WindowModal); + progress->setValue(0); } - for (int i = 0; i < database->rowCount(); i++) { - for (int j = 0; j < database->columnCount(); j++) { - if ((j == 0) || (j == 6)) { - delete database->cellWidget(i, j); - } - else { - delete database->item(i, j); - } - } + widgetitemallocator.reset(); - if (enableprogress && ((i == 0) || ((i - 1)/100 != i/100))) { - progress->setValue(i); - } - } + for (int i = 0; i < rowcount; i++) { + delete database->cellWidget(rowcount - i - 1, 0); + delete database->cellWidget(rowcount - i - 1, 6); + + if (enableprogress) { + progress->setValue(i); + //if (progress->wasCanceled()) { + // break; + //} + } + } + + database->setRowCount(0); if (enableprogress) { - progress->setValue(database->rowCount()); - progress->hide(); + progress->setValue(rowcount); + delete progress; } - database->setRowCount(0); } void cBricksDatabaseWidget::removeRow(int row) { - for (int i = 0; i < database->columnCount(); i++) { - if ((i == 0) || (i == 6)) { - delete database->cellWidget(row, i); - } - else { - delete database->item(row, i); - } - } - database->removeRow(row); + for (int i = 0; i < database->columnCount(); i++) { + if ((i == 0) || (i == 6)) { + delete database->cellWidget(row, i); + } + else { + database->takeItem(row, i); + } + } + database->removeRow(row); } @@ -200,7 +215,7 @@ bool cBricksDatabaseWidget::checkTable() { } -bool cBricksDatabaseWidget::checkFormula(int row, string& summary) { +bool cBricksDatabaseWidget::checkFormula(int row, const string& summary) { cSummaryFormula formula; string errmsg; formula.setFormula(summary); @@ -221,6 +236,13 @@ bool cBricksDatabaseWidget::checkFormula(int row, string& summary) { } +void cBricksDatabaseWidget::keyPressEvent(QKeyEvent *event) { + if(event->key() == Qt::Key_Escape) { + hide(); + } +} + + void cBricksDatabaseWidget::closeWindow() { hide(); } @@ -228,11 +250,11 @@ void cBricksDatabaseWidget::closeWindow() { void cBricksDatabaseWidget::loadDatabase() { QString filename = QFileDialog::getOpenFileName(this, tr("Load the Database of Building Blocks"), lastdir, tr("Database of Building Blocks (*.txt)")); - lastdir = filename; - string errormessage; - - if (filename.toStdString().compare("") != 0) { + if (!filename.isEmpty()) { + lastdir = filename; + string errormessage; + databasefile = filename; save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); @@ -246,46 +268,52 @@ void cBricksDatabaseWidget::loadDatabase() { else { bricks.clear(); - bricks.loadFromPlainTextStream(inputstream, errormessage); + bricks.loadFromPlainTextStream(inputstream, errormessage, true); deleteTable(true); - progress->setLabelText("Loading the Databatase of Building Blocks..."); - progress->setMinimum(0); - progress->setValue(1); - progress->setMaximum(bricks.size()); - progress->show(); + QProgressDialog progress("Loading the Databatase of Building Blocks...", /*"Cancel"*/0, 0, bricks.size(), this); + cEventFilter filter; + progress.installEventFilter(&filter); + progress.setMinimumDuration(0); + progress.setWindowModality(Qt::WindowModal); database->setRowCount(bricks.size()); for (int i = 0; i < bricks.size(); i++) { QCheckBox* checkbox = new QCheckBox(); database->setCellWidget(i, 0, checkbox); - database->setItem(i, 1, new QTableWidgetItem(bricks[i].getName().c_str())); - database->setItem(i, 2, new QTableWidgetItem(bricks[i].getAcronymsAsString().c_str())); - database->setItem(i, 3, new QTableWidgetItem(bricks[i].getSummary().c_str())); + database->setItem(i, 1, widgetitemallocator.getNewItem()); + database->item(i, 1)->setText(bricks[i].getName().c_str()); + + database->setItem(i, 2, widgetitemallocator.getNewItem()); + database->item(i, 2)->setText(bricks[i].getAcronymsAsString().c_str()); + + database->setItem(i, 3, widgetitemallocator.getNewItem()); + database->item(i, 3)->setText(bricks[i].getSummary().c_str()); - database->setItem(i, 4, new QTableWidgetItem()); + database->setItem(i, 4, widgetitemallocator.getNewItem()); database->item(i, 4)->setData(Qt::DisplayRole, bricks[i].getMass()); - database->setItem(i, 5, new QTableWidgetItem(bricks[i].getReferencesAsString().c_str())); + database->setItem(i, 5, widgetitemallocator.getNewItem()); + database->item(i, 5)->setText(bricks[i].getReferencesAsString().c_str()); database->setCellWidget(i, 6, new QLabel(bricks[i].getAcronymsWithReferencesAsHTMLString().c_str())); ((QLabel *)database->cellWidget(i, 6))->setTextFormat(Qt::RichText); ((QLabel *)database->cellWidget(i, 6))->setTextInteractionFlags(Qt::TextBrowserInteraction); ((QLabel *)database->cellWidget(i, 6))->setOpenExternalLinks(true); - if ((i == 0) || ((i - 1)/100 != i/100)) { - progress->setValue(i); - } + progress.setValue(i); + //if (progress.wasCanceled()) { + // break; + //} } for (int i = 0; i < database->columnCount(); i++) { database->resizeColumnToContents(i); } - progress->setValue(bricks.size()); - progress->hide(); + progress.setValue(bricks.size()); } @@ -314,19 +342,18 @@ void cBricksDatabaseWidget::saveDatabase() { } else { - progress->setLabelText("Saving the Databatase of Building Blocks..."); - progress->setMinimum(0); - progress->setMaximum(100); - progress->setValue(1); - progress->show(); + QProgressDialog progress("Saving the Databatase of Building Blocks...", /*"Cancel"*/0, 0, database->rowCount(), this); + cEventFilter filter; + progress.installEventFilter(&filter); + progress.setMinimumDuration(0); + progress.setWindowModality(Qt::WindowModal); cBrick b; bricks.clear(); + string s; removeEmptyRows(); - progress->setMaximum(database->rowCount()); - for (int i = 0; i < database->rowCount(); i++) { b.clear(); for (int j = 0; j < database->columnCount(); j++) { @@ -336,19 +363,23 @@ void cBricksDatabaseWidget::saveDatabase() { // nothing to do break; case 1: - b.setName(database->item(i,j)->text().toStdString()); + s = database->item(i,j)->text().toStdString(); + b.setName(removeWhiteSpacesExceptSpaces(s)); break; case 2: - b.setAcronyms(database->item(i,j)->text().toStdString()); + s = database->item(i,j)->text().toStdString(); + b.setAcronyms(removeWhiteSpacesExceptSpaces(s)); break; case 3: - b.setSummary(database->item(i,j)->text().toStdString()); + s = database->item(i,j)->text().toStdString(); + b.setSummary(removeWhiteSpacesExceptSpaces(s)); break; case 4: b.setMass(database->item(i,j)->data(Qt::DisplayRole).toDouble()); break; case 5: - b.setReferences(database->item(i,j)->text().toStdString()); + s = database->item(i,j)->text().toStdString(); + b.setReferences(removeWhiteSpacesExceptSpaces(s)); break; default: break; @@ -356,15 +387,15 @@ void cBricksDatabaseWidget::saveDatabase() { } bricks.push_back(b); - if ((i == 0) || ((i - 1)/100 != i/100)) { - progress->setValue(i); - } + progress.setValue(i); + //if (progress.wasCanceled()) { + // break; + //} } bricks.storeToPlainTextStream(outputstream); - progress->setValue(database->rowCount()); - progress->hide(); + progress.setValue(progress.maximum()); } outputstream.close(); @@ -377,10 +408,11 @@ void cBricksDatabaseWidget::saveDatabaseAs() { return; } - QString filename = QFileDialog::getSaveFileName(this, tr("Save Settings As..."), lastdir, tr("Database of Building Blocks (*.txt)")); - lastdir = filename; + QString filename = QFileDialog::getSaveFileName(this, tr("Save the Database of Building Blocks As..."), lastdir, tr("Database of Building Blocks (*.txt)")); - if (filename.toStdString().compare("") != 0) { + if (!filename.isEmpty()) { + lastdir = filename; + databasefile = filename; save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); saveDatabase(); @@ -395,11 +427,11 @@ void cBricksDatabaseWidget::addRow() { QCheckBox* checkbox = new QCheckBox(); database->setCellWidget(row, 0, checkbox); - database->setItem(row, 1, new QTableWidgetItem()); - database->setItem(row, 2, new QTableWidgetItem()); - database->setItem(row, 3, new QTableWidgetItem()); - database->setItem(row, 4, new QTableWidgetItem()); - database->setItem(row, 5, new QTableWidgetItem()); + database->setItem(row, 1, widgetitemallocator.getNewItem()); + database->setItem(row, 2, widgetitemallocator.getNewItem()); + database->setItem(row, 3, widgetitemallocator.getNewItem()); + database->setItem(row, 4, widgetitemallocator.getNewItem()); + database->setItem(row, 5, widgetitemallocator.getNewItem()); database->setCellWidget(row, 6, new QLabel()); ((QLabel *)database->cellWidget(row, 6))->setTextFormat(Qt::RichText); diff --git a/CycloBranch/gui/cBricksDatabaseWidget.h b/CycloBranch/gui/cBricksDatabaseWidget.h index ade57cc..673abe1 100644 --- a/CycloBranch/gui/cBricksDatabaseWidget.h +++ b/CycloBranch/gui/cBricksDatabaseWidget.h @@ -9,7 +9,9 @@ #include #include +#include "core/utilities.h" #include "core/cBricksDatabase.h" +#include "core/cAllocator.h" using namespace std; @@ -19,10 +21,7 @@ class QHBoxLayout; class QVBoxLayout; class QTableWidget; class QTableWidgetItem; -class QDialogButtonBox; class QPushButton; -class QLabel; -class QProgressDialog; /** @@ -31,11 +30,11 @@ class QProgressDialog; \param c char \retval int number of occurrences of \a c in \a s */ -int numberOfOccurrences(string& s, char c); +int numberOfOccurrences(const string& s, char c); /** - \brief The widget representing the dialog 'About'. + \brief Visualization of the database of building blocks. */ class cBricksDatabaseWidget : public QWidget { @@ -75,7 +74,6 @@ class cBricksDatabaseWidget : public QWidget QTableWidget* database; QHBoxLayout* buttons; QVBoxLayout* mainlayout; - QProgressDialog* progress; QString databasefile; QString lastdir; @@ -85,13 +83,26 @@ class cBricksDatabaseWidget : public QWidget vector headersort; + cAllocator widgetitemallocator; + void deleteTable(bool enableprogress); void removeRow(int row); bool checkTable(); - bool checkFormula(int row, string& summary); + bool checkFormula(int row, const string& summary); + + +protected: + + + /** + \brief Handle a key press event. + \param event pointer to QKeyEvent + */ + void keyPressEvent(QKeyEvent *event); + private slots: @@ -113,4 +124,4 @@ private slots: }; -#endif \ No newline at end of file +#endif diff --git a/CycloBranch/gui/cCyclicWidget.cpp b/CycloBranch/gui/cCyclicWidget.cpp index db7eede..491397e 100644 --- a/CycloBranch/gui/cCyclicWidget.cpp +++ b/CycloBranch/gui/cCyclicWidget.cpp @@ -4,11 +4,20 @@ #include #include #include +#include +#include +#include -void paintCircle(QPainter& painter, QColor& brushcolor, vector& acronymsofblocks, int centerx, int centery, int radius, double angle, int horizontalstep, int linesize, int cornerlinesize) { +void paintCircle(QPainter& painter, vector& acronymsofblocks, int centerx, int centery, int radius, double angle, int horizontalstep, int linesize, int cornerlinesize, bool drawdashlines, int visiblerotationid, unordered_set& labels) { double cumulativeangle; + QFont myFont("Courier", 9); + QFontMetrics fm(myFont); + + string nterm = "N-term"; + string cterm = "C-term"; + painter.setPen(QPen(Qt::black, 2, Qt::SolidLine)); painter.drawEllipse(QPointF(centerx,centery), radius, radius); @@ -18,86 +27,180 @@ void paintCircle(QPainter& painter, QColor& brushcolor, vector& acronyms cumulativeangle = angle*(double)(i + 1); blockid = to_string(i + 1); if (cumulativeangle < pi/2) { - painter.setBrush(QBrush(brushcolor, Qt::SolidPattern)); - painter.drawRect(centerx + sin(cumulativeangle)*radius - xsize/2, centery - sin(pi/2 - cumulativeangle)*radius - 10, xsize, 20); - painter.setBrush(QBrush(brushcolor, Qt::NoBrush)); + painter.eraseRect(centerx + sin(cumulativeangle)*radius - xsize/2, centery - sin(pi/2 - cumulativeangle)*radius - 10, xsize, 20); painter.setPen(QPen(Qt::blue, 2, Qt::SolidLine)); - painter.drawText(centerx + sin(cumulativeangle)*radius - xsize/2, centery - sin(pi/2 - cumulativeangle)*radius - 10, xsize, 20, Qt::AlignCenter, acronymsofblocks[i].c_str()); - painter.drawText(centerx + sin(cumulativeangle)*radius - xsize/2, centery - sin(pi/2 - cumulativeangle)*radius - 30, xsize, 20, Qt::AlignLeft, blockid.c_str()); + + if (fm.width(acronymsofblocks[i].c_str()) > xsize) { + painter.drawText(centerx + sin(cumulativeangle)*radius - xsize/2 + 2, centery - sin(pi/2 - cumulativeangle)*radius - 10, xsize - 2, 20, Qt::AlignLeft|Qt::AlignVCenter, acronymsofblocks[i].c_str()); + } + else { + painter.drawText(centerx + sin(cumulativeangle)*radius - xsize/2, centery - sin(pi/2 - cumulativeangle)*radius - 10, xsize, 20, Qt::AlignCenter, acronymsofblocks[i].c_str()); + } + + if (drawdashlines) { + painter.drawText(centerx + sin(cumulativeangle)*radius - xsize/2, centery - sin(pi/2 - cumulativeangle)*radius - 30, xsize, 20, Qt::AlignLeft, blockid.c_str()); + } + painter.setPen(QPen(Qt::black, 2, Qt::SolidLine)); painter.drawRect(centerx + sin(cumulativeangle)*radius - xsize/2, centery - sin(pi/2 - cumulativeangle)*radius - 10, xsize, 20); } else if ((cumulativeangle >= pi/2) && (cumulativeangle <= pi)) { - painter.setBrush(QBrush(brushcolor, Qt::SolidPattern)); - painter.drawRect(centerx + sin(pi - cumulativeangle)*radius - xsize/2, centery + sin(cumulativeangle - pi/2)*radius - 10, xsize, 20); - painter.setBrush(QBrush(brushcolor, Qt::NoBrush)); + painter.eraseRect(centerx + sin(pi - cumulativeangle)*radius - xsize/2, centery + sin(cumulativeangle - pi/2)*radius - 10, xsize, 20); painter.setPen(QPen(Qt::blue, 2, Qt::SolidLine)); - painter.drawText(centerx + sin(pi - cumulativeangle)*radius - xsize/2, centery + sin(cumulativeangle - pi/2)*radius - 10, xsize, 20, Qt::AlignCenter, acronymsofblocks[i].c_str()); - painter.drawText(centerx + sin(pi - cumulativeangle)*radius - xsize/2, centery + sin(cumulativeangle - pi/2)*radius - 30, xsize, 20, Qt::AlignLeft, blockid.c_str()); + + if (fm.width(acronymsofblocks[i].c_str()) > xsize) { + painter.drawText(centerx + sin(pi - cumulativeangle)*radius - xsize/2 + 2, centery + sin(cumulativeangle - pi/2)*radius - 10, xsize - 2, 20, Qt::AlignLeft|Qt::AlignVCenter, acronymsofblocks[i].c_str()); + } + else { + painter.drawText(centerx + sin(pi - cumulativeangle)*radius - xsize/2, centery + sin(cumulativeangle - pi/2)*radius - 10, xsize, 20, Qt::AlignCenter, acronymsofblocks[i].c_str()); + } + + if (drawdashlines) { + painter.drawText(centerx + sin(pi - cumulativeangle)*radius - xsize/2, centery + sin(cumulativeangle - pi/2)*radius - 30, xsize, 20, Qt::AlignLeft, blockid.c_str()); + } + painter.setPen(QPen(Qt::black, 2, Qt::SolidLine)); painter.drawRect(centerx + sin(pi - cumulativeangle)*radius - xsize/2, centery + sin(cumulativeangle - pi/2)*radius - 10, xsize, 20); } else if ((cumulativeangle >= pi) && (cumulativeangle <= 3*pi/2)) { - painter.setBrush(QBrush(brushcolor, Qt::SolidPattern)); - painter.drawRect(centerx - sin(cumulativeangle - pi)*radius - xsize/2, centery + sin(3*pi/2 - cumulativeangle)*radius - 10, xsize, 20); - painter.setBrush(QBrush(brushcolor, Qt::NoBrush)); + painter.eraseRect(centerx - sin(cumulativeangle - pi)*radius - xsize/2, centery + sin(3*pi/2 - cumulativeangle)*radius - 10, xsize, 20); painter.setPen(QPen(Qt::blue, 2, Qt::SolidLine)); - painter.drawText(centerx - sin(cumulativeangle - pi)*radius - xsize/2, centery + sin(3*pi/2 - cumulativeangle)*radius - 10, xsize, 20, Qt::AlignCenter, acronymsofblocks[i].c_str()); - painter.drawText(centerx - sin(cumulativeangle - pi)*radius - xsize/2, centery + sin(3*pi/2 - cumulativeangle)*radius - 30, xsize, 20, Qt::AlignLeft, blockid.c_str()); + + if (fm.width(acronymsofblocks[i].c_str()) > xsize) { + painter.drawText(centerx - sin(cumulativeangle - pi)*radius - xsize/2 + 2, centery + sin(3*pi/2 - cumulativeangle)*radius - 10, xsize - 2, 20, Qt::AlignLeft|Qt::AlignVCenter, acronymsofblocks[i].c_str()); + } + else { + painter.drawText(centerx - sin(cumulativeangle - pi)*radius - xsize/2, centery + sin(3*pi/2 - cumulativeangle)*radius - 10, xsize, 20, Qt::AlignCenter, acronymsofblocks[i].c_str()); + } + + if (drawdashlines) { + painter.drawText(centerx - sin(cumulativeangle - pi)*radius - xsize/2, centery + sin(3*pi/2 - cumulativeangle)*radius - 30, xsize, 20, Qt::AlignLeft, blockid.c_str()); + } + painter.setPen(QPen(Qt::black, 2, Qt::SolidLine)); painter.drawRect(centerx - sin(cumulativeangle - pi)*radius - xsize/2, centery + sin(3*pi/2 - cumulativeangle)*radius - 10, xsize, 20); } else { - painter.setBrush(QBrush(brushcolor, Qt::SolidPattern)); - painter.drawRect(centerx - sin(2*pi - cumulativeangle)*radius - xsize/2, centery - sin(cumulativeangle - 3*pi/2)*radius - 10, xsize, 20); - painter.setBrush(QBrush(brushcolor, Qt::NoBrush)); + painter.eraseRect(centerx - sin(2*pi - cumulativeangle)*radius - xsize/2, centery - sin(cumulativeangle - 3*pi/2)*radius - 10, xsize, 20); painter.setPen(QPen(Qt::blue, 2, Qt::SolidLine)); - painter.drawText(centerx - sin(2*pi - cumulativeangle)*radius - xsize/2, centery - sin(cumulativeangle - 3*pi/2)*radius - 10, xsize, 20, Qt::AlignCenter, acronymsofblocks[i].c_str()); - painter.drawText(centerx - sin(2*pi - cumulativeangle)*radius - xsize/2, centery - sin(cumulativeangle - 3*pi/2)*radius - 30, xsize, 20, Qt::AlignLeft, blockid.c_str()); + + if (fm.width(acronymsofblocks[i].c_str()) > xsize) { + painter.drawText(centerx - sin(2*pi - cumulativeangle)*radius - xsize/2 + 2, centery - sin(cumulativeangle - 3*pi/2)*radius - 10, xsize - 2, 20, Qt::AlignLeft|Qt::AlignVCenter, acronymsofblocks[i].c_str()); + } + else { + painter.drawText(centerx - sin(2*pi - cumulativeangle)*radius - xsize/2, centery - sin(cumulativeangle - 3*pi/2)*radius - 10, xsize, 20, Qt::AlignCenter, acronymsofblocks[i].c_str()); + } + + if (drawdashlines) { + painter.drawText(centerx - sin(2*pi - cumulativeangle)*radius - xsize/2, centery - sin(cumulativeangle - 3*pi/2)*radius - 30, xsize, 20, Qt::AlignLeft, blockid.c_str()); + } + painter.setPen(QPen(Qt::black, 2, Qt::SolidLine)); painter.drawRect(centerx - sin(2*pi - cumulativeangle)*radius - xsize/2, centery - sin(cumulativeangle - 3*pi/2)*radius - 10, xsize, 20); } } - painter.setPen(QPen(Qt::black, 2, Qt::DashLine)); - for (int i = 0; i < (int)acronymsofblocks.size(); i++) { - cumulativeangle = angle*(double)i + angle/(double)2; - if (cumulativeangle < pi/2) { - QPoint p1(centerx + sin(cumulativeangle)*(radius - linesize), centery - sin(pi/2 - cumulativeangle)*(radius - linesize)); - QPoint p2(centerx + sin(cumulativeangle)*(radius + linesize), centery - sin(pi/2 - cumulativeangle)*(radius + linesize)); - QPoint p3(centerx + sin(cumulativeangle)*(radius + linesize) - sin(pi/2 - cumulativeangle)*cornerlinesize, centery - sin(pi/2 - cumulativeangle)*(radius + linesize) - sin(cumulativeangle)*cornerlinesize); - QPoint p4(centerx + sin(cumulativeangle)*(radius - linesize) + sin(pi/2 - cumulativeangle)*cornerlinesize, centery - sin(pi/2 - cumulativeangle)*(radius - linesize) + sin(cumulativeangle)*cornerlinesize); - painter.drawLine(p1, p2); - painter.drawLine(p3, p2); - painter.drawLine(p1, p4); - } - else if ((cumulativeangle >= pi/2) && (cumulativeangle <= pi)) { - QPoint p1(centerx + sin(pi - cumulativeangle)*(radius - linesize), centery + sin(cumulativeangle - pi/2)*(radius - linesize)); - QPoint p2(centerx + sin(pi - cumulativeangle)*(radius + linesize), centery + sin(cumulativeangle - pi/2)*(radius + linesize)); - QPoint p3(centerx + sin(pi - cumulativeangle)*(radius + linesize) + sin(cumulativeangle - pi/2)*cornerlinesize, centery + sin(cumulativeangle - pi/2)*(radius + linesize) - sin(pi - cumulativeangle)*cornerlinesize); - QPoint p4(centerx + sin(pi - cumulativeangle)*(radius - linesize) - sin(cumulativeangle - pi/2)*cornerlinesize, centery + sin(cumulativeangle - pi/2)*(radius - linesize) + sin(pi - cumulativeangle)*cornerlinesize); - painter.drawLine(p1, p2); - painter.drawLine(p3, p2); - painter.drawLine(p1, p4); - } - else if ((cumulativeangle >= pi) && (cumulativeangle <= 3*pi/2)) { - QPoint p1(centerx - sin(cumulativeangle - pi)*(radius - linesize), centery + sin(3*pi/2 - cumulativeangle)*(radius - linesize)); - QPoint p2(centerx - sin(cumulativeangle - pi)*(radius + linesize), centery + sin(3*pi/2 - cumulativeangle)*(radius + linesize)); - QPoint p3(centerx - sin(cumulativeangle - pi)*(radius + linesize) + sin(3*pi/2 - cumulativeangle)*cornerlinesize, centery + sin(3*pi/2 - cumulativeangle)*(radius + linesize) + sin(cumulativeangle - pi)*cornerlinesize); - QPoint p4(centerx - sin(cumulativeangle - pi)*(radius - linesize) - sin(3*pi/2 - cumulativeangle)*cornerlinesize, centery + sin(3*pi/2 - cumulativeangle)*(radius - linesize) - sin(cumulativeangle - pi)*cornerlinesize); - painter.drawLine(p1, p2); - painter.drawLine(p3, p2); - painter.drawLine(p1, p4); + int reddashid = visiblerotationid; + if (visiblerotationid >= (int)acronymsofblocks.size()) { + reddashid = (2*(int)acronymsofblocks.size() - visiblerotationid)%(int)acronymsofblocks.size(); + } + + if (drawdashlines) { + for (int i = 0; i < (int)acronymsofblocks.size(); i++) { + cumulativeangle = angle*(double)i + angle/(double)2; + if (cumulativeangle < pi/2) { + QPoint p1(centerx + sin(cumulativeangle)*(radius - linesize), centery - sin(pi/2 - cumulativeangle)*(radius - linesize)); + QPoint p2(centerx + sin(cumulativeangle)*(radius + linesize), centery - sin(pi/2 - cumulativeangle)*(radius + linesize)); + QPoint p3(centerx + sin(cumulativeangle)*(radius + linesize) - sin(pi/2 - cumulativeangle)*cornerlinesize, centery - sin(pi/2 - cumulativeangle)*(radius + linesize) - sin(cumulativeangle)*cornerlinesize); + QPoint p4(centerx + sin(cumulativeangle)*(radius - linesize) + sin(pi/2 - cumulativeangle)*cornerlinesize, centery - sin(pi/2 - cumulativeangle)*(radius - linesize) + sin(cumulativeangle)*cornerlinesize); + if (reddashid == i) { + painter.setPen(QPen(Qt::red, 2, Qt::DashLine)); + if (visiblerotationid < (int)acronymsofblocks.size()) { + insertLabel(labels, p3.x() + 10, p3.y() - 10, cterm, false); + insertLabel(labels, p4.x() - 5, p4.y() - 5, nterm, true); + } + else { + insertLabel(labels, p3.x() + 10, p3.y() - 10, nterm, false); + insertLabel(labels, p4.x() - 5, p4.y() - 5, cterm, true); + } + } + else { + painter.setPen(QPen(Qt::black, 2, Qt::DashLine)); + } + painter.drawLine(p1, p2); + painter.drawLine(p3, p2); + painter.drawLine(p1, p4); + } + else if ((cumulativeangle >= pi/2) && (cumulativeangle <= pi)) { + QPoint p1(centerx + sin(pi - cumulativeangle)*(radius - linesize), centery + sin(cumulativeangle - pi/2)*(radius - linesize)); + QPoint p2(centerx + sin(pi - cumulativeangle)*(radius + linesize), centery + sin(cumulativeangle - pi/2)*(radius + linesize)); + QPoint p3(centerx + sin(pi - cumulativeangle)*(radius + linesize) + sin(cumulativeangle - pi/2)*cornerlinesize, centery + sin(cumulativeangle - pi/2)*(radius + linesize) - sin(pi - cumulativeangle)*cornerlinesize); + QPoint p4(centerx + sin(pi - cumulativeangle)*(radius - linesize) - sin(cumulativeangle - pi/2)*cornerlinesize, centery + sin(cumulativeangle - pi/2)*(radius - linesize) + sin(pi - cumulativeangle)*cornerlinesize); + if (reddashid == i) { + painter.setPen(QPen(Qt::red, 2, Qt::DashLine)); + if (visiblerotationid < (int)acronymsofblocks.size()) { + insertLabel(labels, p3.x() + 10, p3.y() - 10, cterm, false); + insertLabel(labels, p4.x() - 5, p4.y() - 5, nterm, true); + } + else { + insertLabel(labels, p3.x() + 10, p3.y() - 10, nterm, false); + insertLabel(labels, p4.x() - 5, p4.y() - 5, cterm, true); + } + } + else { + painter.setPen(QPen(Qt::black, 2, Qt::DashLine)); + } + painter.drawLine(p1, p2); + painter.drawLine(p3, p2); + painter.drawLine(p1, p4); + } + else if ((cumulativeangle >= pi) && (cumulativeangle <= 3*pi/2)) { + QPoint p1(centerx - sin(cumulativeangle - pi)*(radius - linesize), centery + sin(3*pi/2 - cumulativeangle)*(radius - linesize)); + QPoint p2(centerx - sin(cumulativeangle - pi)*(radius + linesize), centery + sin(3*pi/2 - cumulativeangle)*(radius + linesize)); + QPoint p3(centerx - sin(cumulativeangle - pi)*(radius + linesize) + sin(3*pi/2 - cumulativeangle)*cornerlinesize, centery + sin(3*pi/2 - cumulativeangle)*(radius + linesize) + sin(cumulativeangle - pi)*cornerlinesize); + QPoint p4(centerx - sin(cumulativeangle - pi)*(radius - linesize) - sin(3*pi/2 - cumulativeangle)*cornerlinesize, centery + sin(3*pi/2 - cumulativeangle)*(radius - linesize) - sin(cumulativeangle - pi)*cornerlinesize); + if (reddashid == i) { + painter.setPen(QPen(Qt::red, 2, Qt::DashLine)); + if (visiblerotationid < (int)acronymsofblocks.size()) { + insertLabel(labels, p3.x() - 10, p3.y() - 10, cterm, true); + insertLabel(labels, p4.x() + 10, p4.y() - 10, nterm, false); + } + else { + insertLabel(labels, p3.x() - 10, p3.y() - 10, nterm, true); + insertLabel(labels, p4.x() + 10, p4.y() - 10, cterm, false); + } + } + else { + painter.setPen(QPen(Qt::black, 2, Qt::DashLine)); + } + painter.drawLine(p1, p2); + painter.drawLine(p3, p2); + painter.drawLine(p1, p4); + } + else { + QPoint p1(centerx - sin(2*pi - cumulativeangle)*(radius - linesize), centery - sin(cumulativeangle - 3*pi/2)*(radius - linesize)); + QPoint p2(centerx - sin(2*pi - cumulativeangle)*(radius + linesize), centery - sin(cumulativeangle - 3*pi/2)*(radius + linesize)); + QPoint p3(centerx - sin(2*pi - cumulativeangle)*(radius + linesize) - sin(cumulativeangle - 3*pi/2)*cornerlinesize, centery - sin(cumulativeangle - 3*pi/2)*(radius + linesize) + sin(2*pi - cumulativeangle)*cornerlinesize); + QPoint p4(centerx - sin(2*pi - cumulativeangle)*(radius - linesize) + sin(cumulativeangle - 3*pi/2)*cornerlinesize, centery - sin(cumulativeangle - 3*pi/2)*(radius - linesize) - sin(2*pi - cumulativeangle)*cornerlinesize); + if (reddashid == i) { + painter.setPen(QPen(Qt::red, 2, Qt::DashLine)); + if (visiblerotationid < (int)acronymsofblocks.size()) { + insertLabel(labels, p3.x() - 10, p3.y() - 10, cterm, true); + insertLabel(labels, p4.x() + 10, p4.y() - 10, nterm, false); + } + else { + insertLabel(labels, p3.x() - 10, p3.y() - 10, nterm, true); + insertLabel(labels, p4.x() + 10, p4.y() - 10, cterm, false); + } + } + else { + painter.setPen(QPen(Qt::black, 2, Qt::DashLine)); + } + painter.drawLine(p1, p2); + painter.drawLine(p3, p2); + painter.drawLine(p1, p4); + } } - else { - QPoint p1(centerx - sin(2*pi - cumulativeangle)*(radius - linesize), centery - sin(cumulativeangle - 3*pi/2)*(radius - linesize)); - QPoint p2(centerx - sin(2*pi - cumulativeangle)*(radius + linesize), centery - sin(cumulativeangle - 3*pi/2)*(radius + linesize)); - QPoint p3(centerx - sin(2*pi - cumulativeangle)*(radius + linesize) - sin(cumulativeangle - 3*pi/2)*cornerlinesize, centery - sin(cumulativeangle - 3*pi/2)*(radius + linesize) + sin(2*pi - cumulativeangle)*cornerlinesize); - QPoint p4(centerx - sin(2*pi - cumulativeangle)*(radius - linesize) + sin(cumulativeangle - 3*pi/2)*cornerlinesize, centery - sin(cumulativeangle - 3*pi/2)*(radius - linesize) - sin(2*pi - cumulativeangle)*cornerlinesize); - painter.drawLine(p1, p2); - painter.drawLine(p3, p2); - painter.drawLine(p1, p4); - } } } @@ -195,19 +298,98 @@ void cCyclicWidget::initialize(cParameters* parameters, cTheoreticalSpectrum* th } +void cCyclicWidget::exportToPDF(QString filename, bool postscript) { + QPrinter printer; + if (postscript) { + printer.setPaperSize(QSizeF(width() + 100, height() + 100), QPrinter::DevicePixel); + printer.setPageMargins (50, 50, 50, 50, QPrinter::DevicePixel); + } + else { + printer.setPaperSize(QSizeF(width(), height()), QPrinter::DevicePixel); + printer.setPageMargins (0, 0, 0, 0, QPrinter::DevicePixel); + } + printer.setOutputFormat(QPrinter::NativeFormat); + printer.setOutputFileName(filename); + + QPainter painter; + if (!painter.begin(&printer)) { + QMessageBox msgBox; + QString errstr = "The file cannot be created."; + #if OS_TYPE == UNX + errstr += "\nDo you have a properly configured print server (sudo apt-get install cups-pdf) ?"; + errstr += "\nIf you cannot create a ps file, you can create a pdf file and then use pdf2ps tool."; + #endif + msgBox.setText(errstr); + msgBox.exec(); + return; + } + + painter.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing|QPainter::SmoothPixmapTransform); + paint(painter); + painter.end(); +} + + +void cCyclicWidget::exportToPNG(QString filename) { + QImage image(width(), height(), QImage::Format_ARGB32); + image.fill(Qt::white); + + QPainter painter; + if (!painter.begin(&image)) { + QMessageBox msgBox; + QString errstr = "The file cannot be created."; + msgBox.setText(errstr); + msgBox.exec(); + return; + } + + painter.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing|QPainter::SmoothPixmapTransform); + paint(painter); + painter.end(); + image.save(filename); +} + + +void cCyclicWidget::exportToSVG(QString filename) { + QSvgGenerator generator; + generator.setFileName(filename); + generator.setSize(QSize(width(), height())); + generator.setViewBox(QRect(0, 0, width(), height())); + + QPainter painter; + if (!painter.begin(&generator)) { + QMessageBox msgBox; + QString errstr = "The file cannot be created."; + msgBox.setText(errstr); + msgBox.exec(); + return; + } + + paint(painter); + painter.end(); +} + + void cCyclicWidget::paintEvent(QPaintEvent *event) { + QPainter painter; + painter.begin(this); + paint(painter); + painter.end(); +} - if (theoreticalspectrum->getVisualCoverage().size() == 0) { + +void cCyclicWidget::paint(QPainter& painter) { + + if (!theoreticalspectrum) { return; } - QPainter painter(this); const int topmargin = 20;//max(20,(height() - 80)/2); const int leftmargin = 20; const int bottommargin = 80; const int rightmargin = 20; - int size = (int)theoreticalspectrum->getAcronyms().size(); + int size = (int)theoreticalspectrum->getCandidate().getAcronyms().size(); double angle = 2*pi/(double)size; int centerx = width()/2; int centery = height()/2; @@ -216,31 +398,37 @@ void cCyclicWidget::paintEvent(QPaintEvent *event) { const int horizontalstep = (width() - leftmargin - rightmargin)/std::max(size, 1); QFont myFont("Courier", 9); + QFontMetrics fm(myFont); painter.setFont(myFont); + unordered_set labels; + labels.clear(); + int linesize = 20; int cornerlinesize = horizontalstep/8; - paintCircle(painter, (QColor &)(palette().color(QPalette::Background)), theoreticalspectrum->getAcronyms(), centerx, centery, radius, angle, horizontalstep, linesize, cornerlinesize); + + paintCircle(painter, theoreticalspectrum->getCandidate().getAcronyms(), centerx, centery, radius, angle, horizontalstep, linesize, cornerlinesize, theoreticalspectrum->getVisualCoverage().size() > 0, visiblerotationid, labels); - unordered_set labels; - labels.clear(); + if (parameters && (theoreticalspectrum->getVisualCoverage().size() > 0)) { - int half = (int)theoreticalspectrum->getVisualCoverage().size()/(int)parameters->fragmentionsfortheoreticalspectra.size()/2; - for (int i = 0; i < half; i++) { - generateCyclicLabelsToRight(true, i, i, 0, size - 1, size, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, -1, -1); - } - for (int i = half; i < 2*half; i++) { - generateCyclicLabelsToLeft(true, i, i, 0, size - 1, size, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, -1, -1); - } - - painter.setPen(QPen(Qt::red, 2, Qt::SolidLine)); - for (auto it = labels.begin(); it != labels.end(); ++it) { - if (it->alignright) { - painter.drawText(it->x - (int)it->label.size()*7, it->y, (int)it->label.size()*7, 20, Qt::AlignLeft, it->label.c_str()); + int half = (int)theoreticalspectrum->getVisualCoverage().size()/(int)parameters->fragmentionsfortheoreticalspectra.size()/2; + for (int i = 0; i < half; i++) { + generateCyclicLabelsToRight(true, i, i, 0, size - 1, size, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, -1, -1); } - else { - painter.drawText(it->x, it->y, width(), 20, Qt::AlignLeft, it->label.c_str()); + for (int i = half; i < 2*half; i++) { + generateCyclicLabelsToLeft(true, i, i, 0, size - 1, size, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, -1, -1); } + + painter.setPen(QPen(Qt::red, 2, Qt::SolidLine)); + for (auto it = labels.begin(); it != labels.end(); ++it) { + if (it->alignright) { + painter.drawText(it->x - fm.width(it->label.c_str()), it->y, fm.width(it->label.c_str()), 20, Qt::AlignLeft, it->label.c_str()); + } + else { + painter.drawText(it->x, it->y, width(), 20, Qt::AlignLeft, it->label.c_str()); + } + } + } } diff --git a/CycloBranch/gui/cCyclicWidget.h b/CycloBranch/gui/cCyclicWidget.h index 03cac46..b7db166 100644 --- a/CycloBranch/gui/cCyclicWidget.h +++ b/CycloBranch/gui/cCyclicWidget.h @@ -23,9 +23,8 @@ const double pi = 3.141592653589793; /** - \brief Paint the circle of a cyclic or a lasso peptide. + \brief Paint the circle of a cyclic or a branch-cyclic peptide. \param painter a reference to current QPainter - \param brushcolor a background color for rectangles with the acronyms of building blocks \param acronymsofblocks acronyms of building blocks \param centerx x coordinate of a center of the ring \param centery y coordinate of a center of the ring @@ -34,8 +33,11 @@ const double pi = 3.141592653589793; \param horizontalstep determine width of rectangles with the acronyms of building blocks \param linesize length of separators between building blocks \param cornerlinesize length of endings of separators between building blocks + \param drawdashlines true when dashed lines between blocks and numbers of blocks are painted, false otherwise + \param visiblerotationid an identifier of a rotation of a cyclic peptide + \param labels labels of fragment ions */ -void paintCircle(QPainter& painter, QColor& brushcolor, vector& acronymsofblocks, int centerx, int centery, int radius, double angle, int horizontalstep, int linesize, int cornerlinesize); +void paintCircle(QPainter& painter, vector& acronymsofblocks, int centerx, int centery, int radius, double angle, int horizontalstep, int linesize, int cornerlinesize, bool drawdashlines, int visiblerotationid, unordered_set& labels); /** @@ -110,6 +112,28 @@ class cCyclicWidget : public QWidget void initialize(cParameters* parameters, cTheoreticalSpectrum* theoreticalspectrum); + /** + \brief Export peptide into a PDF or a PS file. + \param filename filename + \param postscript if true then PS file is generated instead of PDF + */ + void exportToPDF(QString filename, bool postscript); + + + /** + \brief Export peptide scene into a PNG file. + \param filename filename + */ + void exportToPNG(QString filename); + + + /** + \brief Export peptide scene into a SVG file. + \param filename filename + */ + void exportToSVG(QString filename); + + protected: @@ -122,6 +146,8 @@ class cCyclicWidget : public QWidget private: + void paint(QPainter& painter); + cParameters* parameters; cTheoreticalSpectrum* theoreticalspectrum; int visiblerotationid; diff --git a/CycloBranch/gui/cDrawPeptideWidget.cpp b/CycloBranch/gui/cDrawPeptideWidget.cpp new file mode 100644 index 0000000..9744319 --- /dev/null +++ b/CycloBranch/gui/cDrawPeptideWidget.cpp @@ -0,0 +1,665 @@ +#include "gui/cDrawPeptideWidget.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +cDrawPeptideWidget::cDrawPeptideWidget(QWidget* parent) { + this->parent = parent; + + setWindowTitle("Draw Peptide"); + setWindowIcon(QIcon(":/images/icons/96.png")); + + drawpeptideformlayout = new QFormLayout(); + + peptidetypecombobox = new QComboBox(); + peptidetypecombobox->setToolTip("Select the type of peptide."); + peptidetypecombobox->setMaximumWidth(150); + peptidetypecombobox->addItem(tr("Linear")); + peptidetypecombobox->addItem(tr("Cyclic")); + peptidetypecombobox->addItem(tr("Branched")); + peptidetypecombobox->addItem(tr("Branch-cyclic")); + //peptidetypecombobox->addItem(tr("Linear polysaccharide (beta version)")); + //peptidetypecombobox->addItem(tr("Other")); + drawpeptideformlayout->addRow(tr("Peptide Type: "), peptidetypecombobox); + + sequenceline = new QLineEdit(); + sequenceline->setToolTip("A peptide sequence to be drawn.\nThe tool automatically checks if the syntax of an entered sequence corresponds to the selected peptide type.\nIf the syntax is correct then a green message \"correct\" is shown else a red message \"incorrect\" is shown at the end of the input line."); + + sequencestatuslabel = new QLabel(""); + sequencestatuslabel->setMinimumWidth(50); + + sequenceactioncopy = new QAction("Copy to &Clipboard", this); + sequenceactionsetsequence = new QAction("Set as Searched &Sequence", this); + sequenceactionsettag = new QAction("Set as Sequence &Tag", this); + sequenceactioninsert = new QAction("Insert into Sequence &Database", this); + + sequencemenu = new QMenu(); + sequencemenu->addAction(sequenceactioncopy); + sequencemenu->addSeparator(); + sequencemenu->addAction(sequenceactionsetsequence); + sequencemenu->addAction(sequenceactionsettag); + sequencemenu->addAction(sequenceactioninsert); + + sequencetoolbutton = new QToolButton(); + sequencetoolbutton->setMenu(sequencemenu); + sequencetoolbutton->setPopupMode(QToolButton::MenuButtonPopup); + sequencetoolbutton->setDefaultAction(sequenceactioncopy); + + sequencetoolbar = new QToolBar(); + sequencetoolbar->addWidget(sequencetoolbutton); + + sequencelayout = new QHBoxLayout(); + sequencelayout->addWidget(sequenceline); + sequencelayout->addWidget(sequencestatuslabel); + sequencelayout->addWidget(sequencetoolbar); + drawpeptideformlayout->addRow(tr("Sequence: "), sequencelayout); + + separateblocks = new QCheckBox(); + separateblocks->setToolTip("If the box is checked, the sequence to be drawn is specified by the fields \"Number of Blocks at Backbone\", \"Number of Blocks at Branch\", \"Branch Connection Block No.\", \"Backbone Blocks\" and \"Branch Blocks\".\nIf the box is unchecked, the sequence to be drawn is specified in the field \"Sequence\"."); + drawpeptideformlayout->addRow(tr("Define Blocks Separately: "), separateblocks); + + numberofblocksbackbone = new QSpinBox(); + numberofblocksbackbone->setToolTip("A number of blocks forming a backbone of a peptide."); + numberofblocksbackbone->setMaximumWidth(150); + numberofblocksbackbone->setSingleStep(1); + drawpeptideformlayout->addRow(tr("Number of Blocks at Backbone: "), numberofblocksbackbone); + + numberofblocksbranch = new QSpinBox(); + numberofblocksbranch->setToolTip("A number of blocks forming a branch of a branched or a branch-cyclic peptide."); + numberofblocksbranch->setMaximumWidth(150); + numberofblocksbranch->setRange(1, 100); + numberofblocksbranch->setSingleStep(1); + drawpeptideformlayout->addRow(tr("Number of Blocks at Branch: "), numberofblocksbranch); + + branchposition = new QSpinBox(); + branchposition->setToolTip("A number of a block where a backbone of a branched or a branch-cyclic peptide is connected to a branch."); + branchposition->setMaximumWidth(150); + branchposition->setSingleStep(1); + drawpeptideformlayout->addRow(tr("Branch Connection Block No.:"), branchposition); + + backboneblocks = new QHBoxLayout(); + backboneblocks->setContentsMargins(0, 0, 0, 0); + backboneblockswidget = new QWidget(); + backboneblockswidget->setContentsMargins(0, 0, 0, 0); + backboneblockswidget->setLayout(backboneblocks); + backboneblockswidget->setToolTip("Names of building blocks forming a backbone of a peptide.\nThe number of fields is updated when the value of \"Number of Blocks at Backbone\" is changed.\nOne name of a building block per field must be entered."); + drawpeptideformlayout->addRow(tr("Backbone Blocks: "), backboneblockswidget); + + branchblocks = new QHBoxLayout(); + branchblocks->setContentsMargins(0, 0, 0, 0); + branchblockswidget = new QWidget(); + branchblockswidget->setContentsMargins(0, 0, 0, 0); + branchblockswidget->setLayout(branchblocks); + branchblockswidget->setToolTip("Names of building blocks forming a branch of a branched or a branch-cyclic peptide.\nThe number of fields is updated when the value of \"Number of Blocks at Branch\" is changed.\nOne name of a building block per field must be entered."); + drawpeptideformlayout->addRow(tr("Branch Blocks: "), branchblockswidget); + + drawpeptideformwidget = new QWidget(); + drawpeptideformwidget->setLayout(drawpeptideformlayout); + + + linearwidget = new cLinearWidget(); + linearwidget->initialize(0, 0); + + cyclicwidget = new cCyclicWidget(); + cyclicwidget->initialize(0, 0); + + branchedwidget = new cBranchedWidget(); + branchedwidget->initialize(0, 0); + + lassowidget = new cLassoWidget(); + lassowidget->initialize(0, 0); + + vbox = new QVBoxLayout(); + vbox->addWidget(drawpeptideformwidget); + vbox->addWidget(linearwidget); + vbox->addWidget(cyclicwidget); + vbox->addWidget(branchedwidget); + vbox->addWidget(lassowidget); + + vbox->setStretchFactor(drawpeptideformwidget, 1); + vbox->setStretchFactor(linearwidget, 5); + vbox->setStretchFactor(cyclicwidget, 5); + vbox->setStretchFactor(branchedwidget, 5); + vbox->setStretchFactor(lassowidget, 5); + + mainbox = new QHBoxLayout(); + mainbox->addLayout(vbox); + setLayout(mainbox); + + resize(1280, 700); + + connect(sequenceline, SIGNAL(textEdited(const QString&)), this, SLOT(sequenceChanged())); + connect(sequenceactioncopy, SIGNAL(triggered()), this, SLOT(sequenceCopy())); + connect(sequenceactionsetsequence, SIGNAL(triggered()), this, SLOT(sequenceSetSequence())); + connect(sequenceactionsettag, SIGNAL(triggered()), this, SLOT(sequenceSetTag())); + connect(sequenceactioninsert, SIGNAL(triggered()), this, SLOT(sequenceInsert())); + connect(peptidetypecombobox, SIGNAL(currentIndexChanged(int)), this, SLOT(peptideTypeChanged(int))); + connect(separateblocks, SIGNAL(stateChanged(int)), this, SLOT(separateBlocksChanged(int))); + connect(numberofblocksbackbone, SIGNAL(valueChanged(int)), this, SLOT(numberOfBackboneBlocksChanged(int))); + connect(numberofblocksbranch, SIGNAL(valueChanged(int)), this, SLOT(numberOfBranchBlocksChanged(int))); + connect(branchposition, SIGNAL(valueChanged(int)), this, SLOT(blocksChanged())); + numberOfBackboneBlocksChanged(numberofblocksbackbone->value()); + numberOfBranchBlocksChanged(numberofblocksbranch->value()); + peptideTypeChanged(peptidetypecombobox->currentIndex()); + + connect(this, SIGNAL(sendSequence(int, QString)), parent, SLOT(setSequence(int, QString))); + connect(this, SIGNAL(sendTag(int, QString)), parent, SLOT(setTag(int, QString))); + connect(this, SIGNAL(sendInsert(int, QString)), parent, SLOT(insertSequence(int, QString))); +} + + +cDrawPeptideWidget::~cDrawPeptideWidget() { + delete linearwidget; + delete cyclicwidget; + delete branchedwidget; + delete lassowidget; + + delete peptidetypecombobox; + + delete sequenceline; + delete sequencestatuslabel; + delete sequenceactioncopy; + delete sequenceactionsetsequence; + delete sequenceactionsettag; + delete sequenceactioninsert; + delete sequencemenu; + delete sequencetoolbutton; + delete sequencetoolbar; + delete sequencelayout; + + delete separateblocks; + + delete numberofblocksbackbone; + delete numberofblocksbranch; + delete branchposition; + + QLayoutItem* item; + + while (backboneblocks->count() > 0) { + item = backboneblocks->takeAt(0); + delete item->widget(); + } + + while (branchblocks->count() > 0) { + item = branchblocks->takeAt(0); + delete item->widget(); + } + + delete backboneblocks; + delete branchblocks; + + delete backboneblockswidget; + delete branchblockswidget; + + delete drawpeptideformlayout; + delete drawpeptideformwidget; + + delete vbox; + + delete mainbox; +} + + +void cDrawPeptideWidget::closeEvent(QCloseEvent *event) { + hide(); +} + + +void cDrawPeptideWidget::setSequence(int peptidetypeindex, QString sequence) { + separateblocks->setChecked(false); + peptidetypecombobox->setCurrentIndex(peptidetypeindex); + sequenceline->setText(sequence); + sequenceChanged(); + separateblocks->setChecked(true); +} + + +void cDrawPeptideWidget::keyPressEvent(QKeyEvent *event) { + if(event->key() == Qt::Key_Escape) { + hide(); + } +} + + +void cDrawPeptideWidget::separateBlocksChanged(int state) { + if (state == Qt::Checked) { + sequenceline->setDisabled(true); + numberofblocksbackbone->setDisabled(false); + backboneblockswidget->setDisabled(false); + if (((peptideType)(peptidetypecombobox->currentIndex()) == branched) || ((peptideType)(peptidetypecombobox->currentIndex()) == lasso)) { + numberofblocksbranch->setDisabled(false); + branchblockswidget->setDisabled(false); + branchposition->setDisabled(false); + } + else { + numberofblocksbranch->setDisabled(true); + branchblockswidget->setDisabled(true); + branchposition->setDisabled(true); + } + } + else { + sequenceline->setDisabled(false); + numberofblocksbackbone->setDisabled(true); + backboneblockswidget->setDisabled(true); + numberofblocksbranch->setDisabled(true); + branchblockswidget->setDisabled(true); + branchposition->setDisabled(true); + } + + blocksChanged(); + sequenceChanged(); +} + + +void cDrawPeptideWidget::numberOfBackboneBlocksChanged(int numberofblocks) { + switch ((peptideType)peptidetypecombobox->currentIndex()) { + case linear: + numberofblocksbackbone->setRange(1, 100); + branchposition->setRange(1, 1); + break; + case cyclic: + numberofblocksbackbone->setRange(2, 100); + branchposition->setRange(1, 1); + break; + case branched: + numberofblocksbackbone->setRange(3, 100); + branchposition->setRange(2, numberofblocks - 1); + break; + case lasso: + numberofblocksbackbone->setRange(2, 100); + branchposition->setRange(1, numberofblocks); + break; + case linearpolysaccharide: + break; + case other: + break; + default: + break; + } + + if (numberofblocks > backboneblocks->count()) { + int itemscount = numberofblocks - backboneblocks->count(); + QLineEdit* line; + for (int i = 0; i < itemscount; i++) { + line = new QLineEdit(); + connect(line, SIGNAL(textEdited(const QString&)), this, SLOT(blocksChanged())); + backboneblocks->addWidget(line); + } + } + else if (numberofblocks < backboneblocks->count()) { + QLayoutItem* item; + while (numberofblocks < backboneblocks->count()) { + item = backboneblocks->takeAt(backboneblocks->count() - 1); + delete item->widget(); + } + } + + blocksChanged(); +} + + +void cDrawPeptideWidget::numberOfBranchBlocksChanged(int numberofblocks) { + if (numberofblocks > branchblocks->count()) { + int itemscount = numberofblocks - branchblocks->count(); + QLineEdit* line; + for (int i = 0; i < itemscount; i++) { + line = new QLineEdit(); + connect(line, SIGNAL(textEdited(const QString&)), this, SLOT(blocksChanged())); + branchblocks->addWidget(line); + } + } + else if (numberofblocks < branchblocks->count()) { + QLayoutItem* item; + while (numberofblocks < branchblocks->count()) { + item = branchblocks->takeAt(branchblocks->count() - 1); + delete item->widget(); + } + } + + blocksChanged(); +} + + +void cDrawPeptideWidget::peptideTypeChanged(int index) { + + linearwidget->hide(); + cyclicwidget->hide(); + branchedwidget->hide(); + lassowidget->hide(); + + switch ((peptideType)index) { + case linear: + linearwidget->show(); + numberOfBackboneBlocksChanged(max(backboneblocks->count(), 1)); + break; + case cyclic: + cyclicwidget->show(); + numberOfBackboneBlocksChanged(max(backboneblocks->count(), 2)); + break; + case branched: + branchedwidget->show(); + numberOfBackboneBlocksChanged(max(backboneblocks->count(), 3)); + break; + case lasso: + lassowidget->show(); + numberOfBackboneBlocksChanged(max(backboneblocks->count(), 2)); + break; + case linearpolysaccharide: + break; + case other: + break; + default: + break; + } + + separateBlocksChanged(separateblocks->checkState()); +} + + +void cDrawPeptideWidget::sequenceCopy() { + QApplication::clipboard()->setText(sequenceline->text()); +} + + +void cDrawPeptideWidget::sequenceSetSequence() { + emit sendSequence(peptidetypecombobox->currentIndex(), sequenceline->text()); +} + + +void cDrawPeptideWidget::sequenceSetTag() { + emit sendTag(peptidetypecombobox->currentIndex(), sequenceline->text()); +} + + +void cDrawPeptideWidget::sequenceInsert() { + emit sendInsert(peptidetypecombobox->currentIndex(), sequenceline->text()); +} + + +void cDrawPeptideWidget::blocksChanged() { + if (!separateblocks->isChecked()) { + return; + } + + QString s = ""; + string composition = ""; + int compositioncount = 0; + cBricksDatabase bricksdb; + cBrick b; + + int backbonecount = backboneblocks->count(); + while ((backbonecount > 0) && (((QLineEdit *)(backboneblocks->itemAt(backbonecount - 1)->widget()))->text().toStdString().compare("") == 0)) { + backbonecount--; + } + + int branchcount = branchblocks->count(); + while ((branchcount > 1) && (((QLineEdit *)(branchblocks->itemAt(branchcount - 1)->widget()))->text().toStdString().compare("") == 0)) { + branchcount--; + } + + peptideType peptidetype = (peptideType)peptidetypecombobox->currentIndex(); + + if ((peptidetype == linear) || (peptidetype == linearpolysaccharide) || ((backbonecount > 1) && (peptidetype == cyclic))) { + for (int i = 0; i < backbonecount; i++) { + if (i > 0) { + s += "-"; + composition += "-"; + } + s += "["; + s += ((QLineEdit *)(backboneblocks->itemAt(i)->widget()))->text(); + s += "]"; + composition += to_string(++compositioncount); + b.clear(); + b.setAcronyms(((QLineEdit *)(backboneblocks->itemAt(i)->widget()))->text().toStdString()); + bricksdb.push_back(b); + } + } + + if (((backbonecount > branchposition->value()) && (peptidetype == branched)) || ((backbonecount >= branchposition->value()) && (peptidetype == lasso))) { + for (int i = 0; i < backbonecount; i++) { + if (i == branchposition->value() - 1) { + s += "\\(["; + s += ((QLineEdit *)(backboneblocks->itemAt(i)->widget()))->text(); + s += "]"; + if (composition.size() > 0) { + composition += "-"; + } + composition += to_string(++compositioncount); + b.clear(); + b.setAcronyms(((QLineEdit *)(backboneblocks->itemAt(i)->widget()))->text().toStdString()); + bricksdb.push_back(b); + + for (int j = 0; j < branchcount; j++) { + s += "-["; + s += ((QLineEdit *)(branchblocks->itemAt(j)->widget()))->text(); + s += "]"; + if (composition.size() > 0) { + composition += "-"; + } + composition += to_string(++compositioncount); + b.clear(); + b.setAcronyms(((QLineEdit *)(branchblocks->itemAt(j)->widget()))->text().toStdString()); + bricksdb.push_back(b); + + } + + s += "\\)"; + } + else { + if ((i > 0) && (i != branchposition->value())) { + s += "-"; + } + s += "["; + s += ((QLineEdit *)(backboneblocks->itemAt(i)->widget()))->text(); + s += "]"; + if (composition.size() > 0) { + composition += "-"; + } + composition += to_string(++compositioncount); + b.clear(); + b.setAcronyms(((QLineEdit *)(backboneblocks->itemAt(i)->widget()))->text().toStdString()); + bricksdb.push_back(b); + } + } + } + + sequenceline->setText(s); + + string errormessage = ""; + string sequence = sequenceline->text().toStdString(); + if (checkRegex(peptidetype, sequence, errormessage)) { + sequencestatuslabel->setText("correct"); + vector compositionvector; + compositionvector.push_back(composition); + drawPeptide(compositionvector, bricksdb, branchposition->value() - 1, branchposition->value() - 1 + branchcount); + } + else { + sequencestatuslabel->setText("incorrect"); + } +} + + +void cDrawPeptideWidget::sequenceChanged() { + if (separateblocks->isChecked()) { + return; + } + + string errormessage = ""; + peptideType peptidetype = (peptideType)peptidetypecombobox->currentIndex(); + string sequence = sequenceline->text().toStdString(); + int start1, start2; + + if (checkRegex(peptidetype, sequence, errormessage)) { + + cBricksDatabase bricksdb; + cBrick b; + string s = ""; + string acronym; + bool insidebrick = false; + bool found = false; + + for (int i = 0; i < (int)sequence.size(); i++) { + if (sequence[i] == '[') { + acronym = ""; + insidebrick = true; + continue; + } + + if (sequence[i] == ']') { + b.clear(); + b.setAcronyms(acronym); + bricksdb.push_back(b); + s += to_string(bricksdb.size()); + insidebrick = false; + continue; + } + + if (insidebrick) { + acronym += sequence[i]; + } + else { + s += sequence[i]; + } + } + sequence = s; + + int branchstart, branchend; + vector v; + parseBranch(peptidetype, sequence, v, branchstart, branchend); + + sequencestatuslabel->setText("correct"); + // the candidate is also initialized + drawPeptide(v, bricksdb, branchstart, branchend); + + vector intcomposition; + b.clear(); + b.setComposition(theoreticalspectrum.getCandidate().getComposition(), false); + b.explodeToIntComposition(intcomposition); + + if ((peptidetype == linear) || (peptidetype == linearpolysaccharide) || (peptidetype == cyclic)) { + numberofblocksbackbone->setValue((int)v.size()); + for (int i = 0; i < backboneblocks->count(); i++) { + if (i < (int)v.size()) { + ((QLineEdit *)(backboneblocks->itemAt(i)->widget()))->setText(bricksdb[intcomposition[i] - 1].getAcronymsAsString().c_str()); + + } + else { + ((QLineEdit *)(backboneblocks->itemAt(i)->widget()))->setText(""); + } + } + } + + if ((peptidetype == branched) || (peptidetype == lasso)) { + numberofblocksbackbone->setValue((int)v.size() - branchend + branchstart); + numberofblocksbranch->setValue(branchend - branchstart); + branchposition->setValue(branchstart + 1); + + start1 = 0; + start2 = 0; + for (int i = 0; i < (int)v.size(); i++) { + if ((i > branchstart) && (i <= branchend)) { + ((QLineEdit *)(branchblocks->itemAt(start1)->widget()))->setText(bricksdb[intcomposition[i] - 1].getAcronymsAsString().c_str()); + start1++; + } + else { + ((QLineEdit *)(backboneblocks->itemAt(start2)->widget()))->setText(bricksdb[intcomposition[i] - 1].getAcronymsAsString().c_str()); + start2++; + } + } + + while (start1 < branchblocks->count()) { + ((QLineEdit *)(branchblocks->itemAt(start1)->widget()))->setText(""); + start1++; + } + + while (start2 < backboneblocks->count()) { + ((QLineEdit *)(backboneblocks->itemAt(start2)->widget()))->setText(""); + start2++; + } + } + + } + else { + sequencestatuslabel->setText("incorrect"); + } +} + + +void cDrawPeptideWidget::drawPeptide(vector& composition, cBricksDatabase& bricksdb, int branchstart, int branchend) { + vector netmp; + vector lassorotations; + int numberofbricks; + + switch ((peptideType)peptidetypecombobox->currentIndex()) { + case linear: + theoreticalspectrum.getCandidate().setCandidate(composition, netmp, 0, 0, 0, -1, -1); + theoreticalspectrum.getCandidate().setAcronyms(bricksdb); + linearwidget->initialize(0, &theoreticalspectrum); + linearwidget->repaint(); + break; + case cyclic: + theoreticalspectrum.getCandidate().setCandidate(composition, netmp, 0, 0, 0, -1, -1); + theoreticalspectrum.getCandidate().setAcronyms(bricksdb); + cyclicwidget->initialize(0, &theoreticalspectrum); + cyclicwidget->repaint(); + break; + case branched: + theoreticalspectrum.getCandidate().setCandidate(composition, netmp, 0, 0, 0, branchstart, branchend); + theoreticalspectrum.getCandidate().setBackboneAcronyms(bricksdb); + theoreticalspectrum.getCandidate().setBranchAcronyms(bricksdb); + branchedwidget->initialize(0, &theoreticalspectrum); + branchedwidget->repaint(); + break; + case lasso: + theoreticalspectrum.getCandidate().setCandidate(composition, netmp, 0, 0, 0, branchstart, branchend); + + // normalize the candidate + theoreticalspectrum.getCandidate().getLassoRotations(lassorotations, false); + numberofbricks = getNumberOfBricks(theoreticalspectrum.getCandidate().getComposition()); + for (int i = 0; i < (int)lassorotations.size(); i++) { + if (lassorotations[i].getBranchEnd() == numberofbricks - 1) { + vector v; + v.push_back(lassorotations[i].getComposition()); + theoreticalspectrum.getCandidate().setCandidate(v, theoreticalspectrum.getCandidate().getPath(), theoreticalspectrum.getCandidate().getStartModifID(), theoreticalspectrum.getCandidate().getEndModifID(), theoreticalspectrum.getCandidate().getMiddleModifID(), lassorotations[i].getBranchStart(), lassorotations[i].getBranchEnd()); + break; + } + } + + theoreticalspectrum.getCandidate().setBackboneAcronyms(bricksdb); + theoreticalspectrum.getCandidate().setBranchAcronyms(bricksdb); + lassowidget->initialize(0, &theoreticalspectrum); + lassowidget->repaint(); + break; + case linearpolysaccharide: + break; + case other: + break; + default: + break; + } +} + diff --git a/CycloBranch/gui/cDrawPeptideWidget.h b/CycloBranch/gui/cDrawPeptideWidget.h new file mode 100644 index 0000000..e44ea87 --- /dev/null +++ b/CycloBranch/gui/cDrawPeptideWidget.h @@ -0,0 +1,176 @@ +/** + \file cDrawPeptideWidget.h + \brief Draw a peptide from a sequence of building blocks. +*/ + + +#ifndef _CDRAWPEPTIDEWIDGET_H +#define _CDRAWPEPTIDEWIDGET_H + +#include +#include "gui/cLinearWidget.h" +#include "gui/cCyclicWidget.h" +#include "gui/cBranchedWidget.h" +#include "gui/cLassoWidget.h" + + +// forward declaration +class QTextEdit; +class QTextBrowser; +class QHBoxLayout; +class QVBoxLayout; +class QFormLayout; +class QScrollArea; +class QCheckBox; +class QPushButton; +class QComboBox; +class QDoubleSpinBox; +class QLineEdit; +class QSpinBox; +class QLabel; +class QAction; +class QMenu; +class QToolButton; +class QToolBar; + + +/** + \brief Draw a peptide from a sequence of building blocks. +*/ +class cDrawPeptideWidget : public QWidget +{ + Q_OBJECT + +public: + + + /** + \brief The constructor. + \param parent pointer to a parent widget + */ + cDrawPeptideWidget(QWidget* parent = (QWidget *)0); + + + /** + \brief The destructor. + */ + ~cDrawPeptideWidget(); + + + /** + \brief Handle the window close event. + \param event pointer to QCloseEvent + */ + void closeEvent(QCloseEvent *event); + + + /** + \brief Set peptide sequence. + \param peptidetypeindex an index of current peptide type + \param sequence searched sequence + */ + void setSequence(int peptidetypeindex, QString sequence); + + +protected: + + + /** + \brief Handle a key press event. + \param event pointer to QKeyEvent + */ + void keyPressEvent(QKeyEvent *event); + + +private: + + QWidget* parent; + + QWidget* drawpeptideformwidget; + QFormLayout* drawpeptideformlayout; + QComboBox* peptidetypecombobox; + + QLineEdit* sequenceline; + QLabel* sequencestatuslabel; + QAction *sequenceactioncopy; + QAction *sequenceactionsetsequence; + QAction *sequenceactionsettag; + QAction *sequenceactioninsert; + QMenu *sequencemenu; + QToolButton* sequencetoolbutton; + QToolBar *sequencetoolbar; + QHBoxLayout* sequencelayout; + + QCheckBox* separateblocks; + QSpinBox* numberofblocksbackbone; + QSpinBox* numberofblocksbranch; + QSpinBox* branchposition; + QHBoxLayout* backboneblocks; + QWidget* backboneblockswidget; + QHBoxLayout* branchblocks; + QWidget* branchblockswidget; + + cTheoreticalSpectrum theoreticalspectrum; + cLinearWidget* linearwidget; + cCyclicWidget* cyclicwidget; + cBranchedWidget* branchedwidget; + cLassoWidget* lassowidget; + + QVBoxLayout* vbox; + QHBoxLayout* mainbox; + + + void drawPeptide(vector& composition, cBricksDatabase& bricksdb, int branchstart, int branchend); + + +private slots: + + void separateBlocksChanged(int state); + + void numberOfBackboneBlocksChanged(int numberofblocks); + + void numberOfBranchBlocksChanged(int numberofblocks); + + void peptideTypeChanged(int index); + + void sequenceCopy(); + + void sequenceSetSequence(); + + void sequenceSetTag(); + + void sequenceInsert(); + + void blocksChanged(); + + void sequenceChanged(); + + +signals: + + /** + \brief Send index of peptide type and searched sequence (a request for cParametersWidget). + \param peptidetypeindex an index of current peptide type + \param sequence searched sequence + */ + void sendSequence(int peptidetypeindex, QString sequence); + + + /** + \brief Send index of peptide type and sequence tag (a request for cParametersWidget). + \param peptidetypeindex an index of current peptide type + \param tag sequence tag + */ + void sendTag(int peptidetypeindex, QString tag); + + + /** + \brief Send index of peptide type and sequence (a request for cSequenceDatabaseWidget). + \param peptidetypeindex an index of current peptide type + \param sequence sequence + */ + void sendInsert(int peptidetypeindex, QString sequence); + +}; + +#endif \ No newline at end of file diff --git a/CycloBranch/gui/cEventFilter.cpp b/CycloBranch/gui/cEventFilter.cpp new file mode 100644 index 0000000..84a193c --- /dev/null +++ b/CycloBranch/gui/cEventFilter.cpp @@ -0,0 +1,14 @@ +#include "gui/cEventFilter.h" + + +bool cEventFilter::eventFilter(QObject *obj, QEvent *event) { + if (event->type() == QEvent::KeyPress) { + //QKeyEvent *keyEvent = static_cast(event); + //qDebug("Ate key press %d", keyEvent->key()); + return true; + } + else { + return QObject::eventFilter(obj, event); + } +} + diff --git a/CycloBranch/gui/cEventFilter.h b/CycloBranch/gui/cEventFilter.h new file mode 100644 index 0000000..e357b9a --- /dev/null +++ b/CycloBranch/gui/cEventFilter.h @@ -0,0 +1,35 @@ +/** + \file cEventFilter.h + \brief An event filter. +*/ + + +#ifndef _CEVENTFILTER_H +#define _CEVENTFILTER_H + +#include +#include +#include + + +/** + \brief An event filter. +*/ +class cEventFilter : public QObject { + + Q_OBJECT + + protected: + + /** + \brief Filter events. + \param obj pointer to QObject + \param event pointer to QKeyEvent + */ + bool eventFilter(QObject *obj, QEvent *event); + +}; + + +#endif + diff --git a/CycloBranch/gui/cGraphWidget.cpp b/CycloBranch/gui/cGraphWidget.cpp index ba9ccfc..dde3d75 100644 --- a/CycloBranch/gui/cGraphWidget.cpp +++ b/CycloBranch/gui/cGraphWidget.cpp @@ -2,12 +2,15 @@ #include #include +#include +#include cGraphWidget::cGraphWidget() { htmlstring = ""; - setWindowTitle("Graph"); + setWindowTitle("De Novo Graph"); + setWindowIcon(QIcon(":/images/icons/32.png")); layout = new QVBoxLayout(); @@ -59,3 +62,10 @@ void cGraphWidget::load(ifstream& is) { textbrowser->setHtml(htmlstring.c_str()); } + +void cGraphWidget::keyPressEvent(QKeyEvent *event) { + if(event->key() == Qt::Key_Escape) { + hide(); + } +} + diff --git a/CycloBranch/gui/cGraphWidget.h b/CycloBranch/gui/cGraphWidget.h index 4809917..08a04ba 100644 --- a/CycloBranch/gui/cGraphWidget.h +++ b/CycloBranch/gui/cGraphWidget.h @@ -83,6 +83,17 @@ class cGraphWidget : public QWidget QTextBrowser* textbrowser; string htmlstring; + +protected: + + + /** + \brief Handle a key press event. + \param event pointer to QKeyEvent + */ + void keyPressEvent(QKeyEvent *event); + + }; #endif \ No newline at end of file diff --git a/CycloBranch/gui/cLassoWidget.cpp b/CycloBranch/gui/cLassoWidget.cpp index 20874c1..3806b29 100644 --- a/CycloBranch/gui/cLassoWidget.cpp +++ b/CycloBranch/gui/cLassoWidget.cpp @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include void generateBranchLabelsDown(bool nterminal, int rotationid, unordered_set& labels, cParameters* parameters, cTheoreticalSpectrum* theoreticalspectrum, int centerx, int topmargin, int horizontalstep, int verticalstep, int visiblerotationid, int branchstart) { @@ -64,18 +67,97 @@ void cLassoWidget::initialize(cParameters* parameters, cTheoreticalSpectrum* the } +void cLassoWidget::exportToPDF(QString filename, bool postscript) { + QPrinter printer; + if (postscript) { + printer.setPaperSize(QSizeF(width() + 100, height() + 100), QPrinter::DevicePixel); + printer.setPageMargins (50, 50, 50, 50, QPrinter::DevicePixel); + } + else { + printer.setPaperSize(QSizeF(width(), height()), QPrinter::DevicePixel); + printer.setPageMargins (0, 0, 0, 0, QPrinter::DevicePixel); + } + printer.setOutputFormat(QPrinter::NativeFormat); + printer.setOutputFileName(filename); + + QPainter painter; + if (!painter.begin(&printer)) { + QMessageBox msgBox; + QString errstr = "The file cannot be created."; + #if OS_TYPE == UNX + errstr += "\nDo you have a properly configured print server (sudo apt-get install cups-pdf) ?"; + errstr += "\nIf you cannot create a ps file, you can create a pdf file and then use pdf2ps tool."; + #endif + msgBox.setText(errstr); + msgBox.exec(); + return; + } + + painter.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing|QPainter::SmoothPixmapTransform); + paint(painter); + painter.end(); +} + + +void cLassoWidget::exportToPNG(QString filename) { + QImage image(width(), height(), QImage::Format_ARGB32); + image.fill(Qt::white); + + QPainter painter; + if (!painter.begin(&image)) { + QMessageBox msgBox; + QString errstr = "The file cannot be created."; + msgBox.setText(errstr); + msgBox.exec(); + return; + } + + painter.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing|QPainter::SmoothPixmapTransform); + paint(painter); + painter.end(); + image.save(filename); +} + + +void cLassoWidget::exportToSVG(QString filename) { + QSvgGenerator generator; + generator.setFileName(filename); + generator.setSize(QSize(width(), height())); + generator.setViewBox(QRect(0, 0, width(), height())); + + QPainter painter; + if (!painter.begin(&generator)) { + QMessageBox msgBox; + QString errstr = "The file cannot be created."; + msgBox.setText(errstr); + msgBox.exec(); + return; + } + + paint(painter); + painter.end(); +} + + void cLassoWidget::paintEvent(QPaintEvent *event) { + QPainter painter; + painter.begin(this); + paint(painter); + painter.end(); +} + - if (theoreticalspectrum->getVisualCoverage().size() == 0) { +void cLassoWidget::paint(QPainter& painter) { + + if (!theoreticalspectrum) { return; } vector backboneacronyms; vector branchacronyms; - backboneacronyms = theoreticalspectrum->getBackboneAcronyms(); - branchacronyms = theoreticalspectrum->getBranchAcronyms(); + backboneacronyms = theoreticalspectrum->getCandidate().getBackboneAcronyms(); + branchacronyms = theoreticalspectrum->getCandidate().getBranchAcronyms(); - QPainter painter(this); const int topmargin = 20; const int leftmargin = 20; const int bottommargin = 80; @@ -83,6 +165,11 @@ void cLassoWidget::paintEvent(QPaintEvent *event) { int backbonesize = (int)backboneacronyms.size(); int branchsize = (int)branchacronyms.size(); + + if (branchsize < 1) { + return; + } + double angle = 2*pi/(double)backbonesize; int centerx = width()/2; int centery = height()*3/4; @@ -92,28 +179,44 @@ void cLassoWidget::paintEvent(QPaintEvent *event) { const int verticalstep = (centery - radius - topmargin - 10)/std::max(branchsize, 1); QFont myFont("Courier", 9); + QFontMetrics fm(myFont); painter.setFont(myFont); + unordered_set labels; + labels.clear(); + int linesize = 20; int cornerlinesize = horizontalstep/8; - paintCircle(painter, (QColor &)(palette().color(QPalette::Background)), backboneacronyms, centerx, centery, radius, angle, horizontalstep, linesize, cornerlinesize); + + paintCircle(painter, backboneacronyms, centerx, centery, radius, angle, horizontalstep, linesize, cornerlinesize, theoreticalspectrum->getVisualCoverage().size() > 0, visiblerotationid, labels); // paint the branch for (int i = 0; i < branchsize; i++) { painter.setPen(QPen(Qt::blue, 2, Qt::SolidLine)); - painter.drawText(centerx - horizontalstep/3, topmargin + verticalstep*i, horizontalstep*2/3, 20, Qt::AlignCenter, branchacronyms[branchsize - i - 1].c_str()); - painter.drawText(centerx - horizontalstep/3, topmargin + verticalstep*i - 20, horizontalstep*2/3, 20, Qt::AlignLeft, to_string(backbonesize + branchsize - i).c_str()); + if (fm.width(branchacronyms[branchsize - i - 1].c_str()) > horizontalstep*2/3) { + painter.drawText(centerx - horizontalstep/3 + 2, topmargin + verticalstep*i, horizontalstep*2/3 - 2, 20, Qt::AlignLeft|Qt::AlignVCenter, branchacronyms[branchsize - i - 1].c_str()); + } + else { + painter.drawText(centerx - horizontalstep/3, topmargin + verticalstep*i, horizontalstep*2/3, 20, Qt::AlignCenter, branchacronyms[branchsize - i - 1].c_str()); + } + + if (theoreticalspectrum->getVisualCoverage().size() > 0) { + painter.drawText(centerx - horizontalstep/3, topmargin + verticalstep*i - 20, horizontalstep*2/3, 20, Qt::AlignLeft, to_string(backbonesize + branchsize - i).c_str()); + } painter.setPen(QPen(Qt::black, 2, Qt::SolidLine)); painter.drawRect(centerx - horizontalstep/3, topmargin + verticalstep*i, horizontalstep*2/3, 20); painter.setPen(QPen(Qt::black, 2, Qt::SolidLine)); painter.drawLine(centerx, topmargin + verticalstep*i + 20, centerx, topmargin + verticalstep*i + verticalstep); - painter.setPen(QPen(Qt::black, 2, Qt::DashLine)); - painter.drawLine(centerx - 20, topmargin + verticalstep*i + (verticalstep + 10)/2, centerx + 20, topmargin + verticalstep*i + (verticalstep + 10)/2); - painter.drawLine(centerx - 20, topmargin + verticalstep*i + (verticalstep + 10)/2, centerx - 20, topmargin + verticalstep*i + (verticalstep + 10)/2 + verticalstep/8); - painter.drawLine(centerx + 20, topmargin + verticalstep*i + (verticalstep + 10)/2 - verticalstep/8, centerx + 20, topmargin + verticalstep*i + (verticalstep + 10)/2); + + if (theoreticalspectrum->getVisualCoverage().size() > 0) { + painter.setPen(QPen(Qt::black, 2, Qt::DashLine)); + painter.drawLine(centerx - 20, topmargin + verticalstep*i + (verticalstep + 10)/2, centerx + 20, topmargin + verticalstep*i + (verticalstep + 10)/2); + painter.drawLine(centerx - 20, topmargin + verticalstep*i + (verticalstep + 10)/2, centerx - 20, topmargin + verticalstep*i + (verticalstep + 10)/2 + verticalstep/8); + painter.drawLine(centerx + 20, topmargin + verticalstep*i + (verticalstep + 10)/2 - verticalstep/8, centerx + 20, topmargin + verticalstep*i + (verticalstep + 10)/2); + } if (i == branchsize - 1) { painter.setPen(QPen(Qt::black, 2, Qt::SolidLine)); @@ -122,124 +225,125 @@ void cLassoWidget::paintEvent(QPaintEvent *event) { } - // get lasso rotations - vector lassorotations; - theoreticalspectrum->getCandidate().getLassoRotations(lassorotations, true); + if (parameters && (theoreticalspectrum->getVisualCoverage().size() > 0)) { - // get T-permutations of lasso rotations - vector > trotationsoflassorotations; - trotationsoflassorotations.resize(lassorotations.size()); - for (int i = 0; i < (int)lassorotations.size(); i++) { - lassorotations[i].getPermutationsOfBranches(trotationsoflassorotations[i]); - } + // get branch-cyclic rotations + vector lassorotations; + theoreticalspectrum->getCandidate().getLassoRotations(lassorotations, true); - unordered_set labels; - labels.clear(); + // get T-permutations of branch-cyclic rotations + vector > trotationsoflassorotations; + trotationsoflassorotations.resize(lassorotations.size()); + for (int i = 0; i < (int)lassorotations.size(); i++) { + lassorotations[i].getPermutationsOfBranches(trotationsoflassorotations[i]); + } - int rotationid; - int half = (int)theoreticalspectrum->getVisualCoverage().size()/(int)parameters->fragmentionsfortheoreticalspectra.size()/2; - for (int i = 0; i < half; i++) { + int rotationid; + int half = (int)theoreticalspectrum->getVisualCoverage().size()/(int)parameters->fragmentionsfortheoreticalspectra.size()/2; + for (int i = 0; i < half; i++) { - if ((visibletrotationid != -1) && (visibletrotationid != i % 6)) { - continue; - } + if ((visibletrotationid != -1) && (visibletrotationid != i % 6)) { + continue; + } - if (i/6 == 0) { - rotationid = half/6; - } - else { - rotationid = 2*half/6 - i/6; - } + if (i/6 == 0) { + rotationid = half/6; + } + else { + rotationid = 2*half/6 - i/6; + } - switch (i % 6) - { - case 0: - generateCyclicLabelsToRight(true, i, i/6, 0, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][0].middlebranchstart, trotationsoflassorotations[i/6][0].middlebranchend); - break; - case 1: - generateBranchLabelsDown(true, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][1].middlebranchstart); - generateCyclicLabelsToRight(true, i, -1, trotationsoflassorotations[i/6][1].middlebranchend, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][1].middlebranchstart, trotationsoflassorotations[i/6][1].middlebranchend); - break; - case 2: - generateCyclicLabelsToRight(true, rotationid*6 + 2, i/6, 0, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[rotationid][2].middlebranchstart, trotationsoflassorotations[rotationid][2].middlebranchend); - break; - case 3: - generateCyclicLabelsToRight(true, i, i/6, 0, trotationsoflassorotations[i/6][3].middlebranchstart, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][3].middlebranchstart, trotationsoflassorotations[i/6][3].middlebranchend); - generateBranchLabelsUp(true, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][3].middlebranchend); - generateBranchLabelsDown(false, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][4].middlebranchstart); - generateCyclicLabelsToLeft(false, i, 0, trotationsoflassorotations[i/6][4].middlebranchend, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][4].middlebranchstart, trotationsoflassorotations[i/6][4].middlebranchend); - break; - case 4: - generateBranchLabelsDown(true, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][4].middlebranchstart); - generateCyclicLabelsToLeft(true, i, 0, trotationsoflassorotations[i/6][4].middlebranchend, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][4].middlebranchstart, trotationsoflassorotations[i/6][4].middlebranchend); - break; - case 5: - generateCyclicLabelsToRight(true, rotationid*6 + 5, i/6, 0, trotationsoflassorotations[rotationid][5].middlebranchstart, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[rotationid][5].middlebranchstart, trotationsoflassorotations[rotationid][5].middlebranchend); - generateBranchLabelsUp(true, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][5].middlebranchend); - generateBranchLabelsDown(false, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][1].middlebranchstart); - generateCyclicLabelsToRight(false, i, -1, trotationsoflassorotations[i/6][1].middlebranchend, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][1].middlebranchstart, trotationsoflassorotations[i/6][1].middlebranchend); - break; - default: - break; + switch (i % 6) + { + case 0: + generateCyclicLabelsToRight(true, i, i/6, 0, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][0].middlebranchstart, trotationsoflassorotations[i/6][0].middlebranchend); + break; + case 1: + generateBranchLabelsDown(true, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][1].middlebranchstart); + generateCyclicLabelsToRight(true, i, -1, trotationsoflassorotations[i/6][1].middlebranchend, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][1].middlebranchstart, trotationsoflassorotations[i/6][1].middlebranchend); + break; + case 2: + generateCyclicLabelsToRight(true, rotationid*6 + 2, i/6, 0, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[rotationid][2].middlebranchstart, trotationsoflassorotations[rotationid][2].middlebranchend); + break; + case 3: + generateCyclicLabelsToRight(true, i, i/6, 0, trotationsoflassorotations[i/6][3].middlebranchstart, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][3].middlebranchstart, trotationsoflassorotations[i/6][3].middlebranchend); + generateBranchLabelsUp(true, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][3].middlebranchend); + generateBranchLabelsDown(false, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][4].middlebranchstart); + generateCyclicLabelsToLeft(false, i, 0, trotationsoflassorotations[i/6][4].middlebranchend, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][4].middlebranchstart, trotationsoflassorotations[i/6][4].middlebranchend); + break; + case 4: + generateBranchLabelsDown(true, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][4].middlebranchstart); + generateCyclicLabelsToLeft(true, i, 0, trotationsoflassorotations[i/6][4].middlebranchend, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][4].middlebranchstart, trotationsoflassorotations[i/6][4].middlebranchend); + break; + case 5: + generateCyclicLabelsToRight(true, rotationid*6 + 5, i/6, 0, trotationsoflassorotations[rotationid][5].middlebranchstart, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[rotationid][5].middlebranchstart, trotationsoflassorotations[rotationid][5].middlebranchend); + generateBranchLabelsUp(true, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][5].middlebranchend); + generateBranchLabelsDown(false, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][1].middlebranchstart); + generateCyclicLabelsToRight(false, i, -1, trotationsoflassorotations[i/6][1].middlebranchend, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][1].middlebranchstart, trotationsoflassorotations[i/6][1].middlebranchend); + break; + default: + break; + } + } - } + for (int i = half; i < 2*half; i++) { - for (int i = half; i < 2*half; i++) { + if ((visibletrotationid != -1) && (visibletrotationid != i % 6)) { + continue; + } - if ((visibletrotationid != -1) && (visibletrotationid != i % 6)) { - continue; - } + if (i/6 == half/6) { + rotationid = 0; + } + else { + rotationid = 2*half/6 - i/6; + } - if (i/6 == half/6) { - rotationid = 0; - } - else { - rotationid = 2*half/6 - i/6; - } + switch (i % 6) + { + case 0: + generateCyclicLabelsToLeft(true, i, i/6, 0, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][0].middlebranchstart, trotationsoflassorotations[i/6][0].middlebranchend); + break; + case 1: + generateBranchLabelsDown(true, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][1].middlebranchstart); + generateCyclicLabelsToLeft(true, i, 0, trotationsoflassorotations[i/6][1].middlebranchend, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][1].middlebranchstart, trotationsoflassorotations[i/6][1].middlebranchend); + break; + case 2: + generateCyclicLabelsToLeft(true, rotationid*6 + 2, i/6, 0, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[rotationid][2].middlebranchstart, trotationsoflassorotations[rotationid][2].middlebranchend); + break; + case 3: + generateCyclicLabelsToLeft(true, i, i/6, 0, trotationsoflassorotations[i/6][3].middlebranchstart, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][3].middlebranchstart, trotationsoflassorotations[i/6][3].middlebranchend); + generateBranchLabelsUp(true, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][3].middlebranchend); + generateBranchLabelsDown(false, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][4].middlebranchstart); + generateCyclicLabelsToRight(false, i, -1, trotationsoflassorotations[i/6][4].middlebranchend, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][4].middlebranchstart, trotationsoflassorotations[i/6][4].middlebranchend); + break; + case 4: + generateBranchLabelsDown(true, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][4].middlebranchstart); + generateCyclicLabelsToRight(true, i, -1, trotationsoflassorotations[i/6][4].middlebranchend, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][4].middlebranchstart, trotationsoflassorotations[i/6][4].middlebranchend); + break; + case 5: + generateCyclicLabelsToLeft(true, rotationid*6 + 5, i/6, 0, trotationsoflassorotations[rotationid][5].middlebranchstart, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[rotationid][5].middlebranchstart, trotationsoflassorotations[rotationid][5].middlebranchend); + generateBranchLabelsUp(true, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][5].middlebranchend); + generateBranchLabelsDown(false, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][1].middlebranchstart); + generateCyclicLabelsToLeft(false, i, 0, trotationsoflassorotations[i/6][1].middlebranchend, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][1].middlebranchstart, trotationsoflassorotations[i/6][1].middlebranchend); + break; + default: + break; + } - switch (i % 6) - { - case 0: - generateCyclicLabelsToLeft(true, i, i/6, 0, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][0].middlebranchstart, trotationsoflassorotations[i/6][0].middlebranchend); - break; - case 1: - generateBranchLabelsDown(true, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][1].middlebranchstart); - generateCyclicLabelsToLeft(true, i, 0, trotationsoflassorotations[i/6][1].middlebranchend, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][1].middlebranchstart, trotationsoflassorotations[i/6][1].middlebranchend); - break; - case 2: - generateCyclicLabelsToLeft(true, rotationid*6 + 2, i/6, 0, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[rotationid][2].middlebranchstart, trotationsoflassorotations[rotationid][2].middlebranchend); - break; - case 3: - generateCyclicLabelsToLeft(true, i, i/6, 0, trotationsoflassorotations[i/6][3].middlebranchstart, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][3].middlebranchstart, trotationsoflassorotations[i/6][3].middlebranchend); - generateBranchLabelsUp(true, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][3].middlebranchend); - generateBranchLabelsDown(false, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][4].middlebranchstart); - generateCyclicLabelsToRight(false, i, -1, trotationsoflassorotations[i/6][4].middlebranchend, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][4].middlebranchstart, trotationsoflassorotations[i/6][4].middlebranchend); - break; - case 4: - generateBranchLabelsDown(true, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][4].middlebranchstart); - generateCyclicLabelsToRight(true, i, -1, trotationsoflassorotations[i/6][4].middlebranchend, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][4].middlebranchstart, trotationsoflassorotations[i/6][4].middlebranchend); - break; - case 5: - generateCyclicLabelsToLeft(true, rotationid*6 + 5, i/6, 0, trotationsoflassorotations[rotationid][5].middlebranchstart, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[rotationid][5].middlebranchstart, trotationsoflassorotations[rotationid][5].middlebranchend); - generateBranchLabelsUp(true, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][5].middlebranchend); - generateBranchLabelsDown(false, i, labels, parameters, theoreticalspectrum, centerx, topmargin, horizontalstep, verticalstep, visiblerotationid, trotationsoflassorotations[i/6][1].middlebranchstart); - generateCyclicLabelsToLeft(false, i, 0, trotationsoflassorotations[i/6][1].middlebranchend, backbonesize + branchsize - 1, backbonesize, labels, parameters, theoreticalspectrum, centerx, centery, radius, angle, linesize, cornerlinesize, visiblerotationid, trotationsoflassorotations[i/6][1].middlebranchstart, trotationsoflassorotations[i/6][1].middlebranchend); - break; - default: - break; } - } - - painter.setPen(QPen(Qt::red, 2, Qt::SolidLine)); - for (auto it = labels.begin(); it != labels.end(); ++it) { - if (it->alignright) { - painter.drawText(it->x - (int)it->label.size()*7, it->y, (int)it->label.size()*7, 20, Qt::AlignLeft, it->label.c_str()); - } - else { - painter.drawText(it->x, it->y, width(), 20, Qt::AlignLeft, it->label.c_str()); + painter.setPen(QPen(Qt::red, 2, Qt::SolidLine)); + for (auto it = labels.begin(); it != labels.end(); ++it) { + if (it->alignright) { + painter.drawText(it->x - fm.width(it->label.c_str()), it->y, fm.width(it->label.c_str()), 20, Qt::AlignLeft, it->label.c_str()); + } + else { + painter.drawText(it->x, it->y, width(), 20, Qt::AlignLeft, it->label.c_str()); + } } + } } diff --git a/CycloBranch/gui/cLassoWidget.h b/CycloBranch/gui/cLassoWidget.h index ee21684..5417ce6 100644 --- a/CycloBranch/gui/cLassoWidget.h +++ b/CycloBranch/gui/cLassoWidget.h @@ -1,6 +1,6 @@ /** \file cLassoWidget.h - \brief Visualization of a lasso peptide. + \brief Visualization of a branch-cyclic peptide. */ @@ -21,7 +21,7 @@ class QPaintEvent; /** - \brief Generate labels of fragment ions on a branch of a lasso peptide (direction down). + \brief Generate labels of fragment ions on a branch of a branch-cyclic peptide (direction down). \param nterminal if true only nterminal fragment ions are drawn, if false only cterminal fragment ions are drawn \param rotationid id of a sequence rotation \param labels labels of fragment ions @@ -38,7 +38,7 @@ void generateBranchLabelsDown(bool nterminal, int rotationid, unordered_set #include #include +#include +#include +#include bool operator == (cIonLabel const& a, cIonLabel const& b) { @@ -40,28 +43,113 @@ void cLinearWidget::initialize(cParameters* parameters, cTheoreticalSpectrum* th } +void cLinearWidget::exportToPDF(QString filename, bool postscript) { + QPrinter printer; + if (postscript) { + printer.setPaperSize(QSizeF(width() + 100, height() + 100), QPrinter::DevicePixel); + printer.setPageMargins (50, 50, 50, 50, QPrinter::DevicePixel); + } + else { + printer.setPaperSize(QSizeF(width(), height()), QPrinter::DevicePixel); + printer.setPageMargins (0, 0, 0, 0, QPrinter::DevicePixel); + } + printer.setOutputFormat(QPrinter::NativeFormat); + printer.setOutputFileName(filename); + + QPainter painter; + if (!painter.begin(&printer)) { + QMessageBox msgBox; + QString errstr = "The file cannot be created."; + #if OS_TYPE == UNX + errstr += "\nDo you have a properly configured print server (sudo apt-get install cups-pdf) ?"; + errstr += "\nIf you cannot create a ps file, you can create a pdf file and then use pdf2ps tool."; + #endif + msgBox.setText(errstr); + msgBox.exec(); + return; + } + + painter.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing|QPainter::SmoothPixmapTransform); + paint(painter); + painter.end(); +} + + +void cLinearWidget::exportToPNG(QString filename) { + QImage image(width(), height(), QImage::Format_ARGB32); + image.fill(Qt::white); + + QPainter painter; + if (!painter.begin(&image)) { + QMessageBox msgBox; + QString errstr = "The file cannot be created."; + msgBox.setText(errstr); + msgBox.exec(); + return; + } + + painter.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing|QPainter::SmoothPixmapTransform); + paint(painter); + painter.end(); + image.save(filename); +} + + +void cLinearWidget::exportToSVG(QString filename) { + QSvgGenerator generator; + generator.setFileName(filename); + generator.setSize(QSize(width(), height())); + generator.setViewBox(QRect(0, 0, width(), height())); + + QPainter painter; + if (!painter.begin(&generator)) { + QMessageBox msgBox; + QString errstr = "The file cannot be created."; + msgBox.setText(errstr); + msgBox.exec(); + return; + } + + paint(painter); + painter.end(); +} + + void cLinearWidget::paintEvent(QPaintEvent *event) { + QPainter painter; + painter.begin(this); + paint(painter); + painter.end(); +} - if (theoreticalspectrum->getVisualCoverage().size() == 0) { + +void cLinearWidget::paint(QPainter& painter) { + + if (!theoreticalspectrum) { return; } - QPainter painter(this); const int topmargin = max(20,(height() - 80)/2); const int leftmargin = 20; const int bottommargin = 80; const int rightmargin = 20; - int size = (int)theoreticalspectrum->getAcronyms().size(); + int size = (int)theoreticalspectrum->getCandidate().getAcronyms().size(); const int horizontalstep = (width() - leftmargin - rightmargin)/std::max(size, 1); QFont myFont("Courier", 9); + QFontMetrics fm(myFont); painter.setFont(myFont); for (int i = 0; i < size; i++) { painter.setPen(QPen(Qt::blue, 2, Qt::SolidLine)); - painter.drawText(leftmargin + horizontalstep/4 + horizontalstep*i, topmargin, horizontalstep/2, 20, Qt::AlignCenter, theoreticalspectrum->getAcronyms()[i].c_str()); + if (fm.width(theoreticalspectrum->getCandidate().getAcronyms()[i].c_str()) > horizontalstep/2) { + painter.drawText(leftmargin + horizontalstep/4 + horizontalstep*i + 2, topmargin, horizontalstep/2 - 2, 20, Qt::AlignLeft|Qt::AlignVCenter, theoreticalspectrum->getCandidate().getAcronyms()[i].c_str()); + } + else { + painter.drawText(leftmargin + horizontalstep/4 + horizontalstep*i, topmargin, horizontalstep/2, 20, Qt::AlignCenter, theoreticalspectrum->getCandidate().getAcronyms()[i].c_str()); + } painter.setPen(QPen(Qt::black, 2, Qt::SolidLine)); painter.drawRect(leftmargin + horizontalstep/4 + horizontalstep*i, topmargin, horizontalstep/2, 20); @@ -69,41 +157,48 @@ void cLinearWidget::paintEvent(QPaintEvent *event) { if (i < size - 1) { painter.setPen(QPen(Qt::black, 2, Qt::SolidLine)); painter.drawLine(leftmargin + horizontalstep/4 + horizontalstep*i + horizontalstep/2, topmargin + 11, leftmargin + horizontalstep/4 + horizontalstep*(i + 1), topmargin + 11); - painter.setPen(QPen(Qt::black, 2, Qt::DashLine)); - painter.drawLine(leftmargin + horizontalstep*(i + 1), topmargin - 10, leftmargin + horizontalstep*(i + 1), topmargin + 30); - painter.drawLine(leftmargin + horizontalstep/4 + horizontalstep/8 + horizontalstep*i + horizontalstep/2, topmargin - 10, leftmargin + horizontalstep*(i + 1), topmargin + - 10); - painter.drawLine(leftmargin + horizontalstep*(i + 1), topmargin + 30, leftmargin + horizontalstep*(i + 1) + horizontalstep/8, topmargin + 30); + + if (theoreticalspectrum->getVisualCoverage().size() > 0) { + painter.setPen(QPen(Qt::black, 2, Qt::DashLine)); + painter.drawLine(leftmargin + horizontalstep*(i + 1), topmargin - 10, leftmargin + horizontalstep*(i + 1), topmargin + 30); + painter.drawLine(leftmargin + horizontalstep/4 + horizontalstep/8 + horizontalstep*i + horizontalstep/2, topmargin - 10, leftmargin + horizontalstep*(i + 1), topmargin + - 10); + painter.drawLine(leftmargin + horizontalstep*(i + 1), topmargin + 30, leftmargin + horizontalstep*(i + 1) + horizontalstep/8, topmargin + 30); + } } } - unordered_set labels; - labels.clear(); - - string name; - int len = (int)theoreticalspectrum->getVisualCoverage()[0].series.size(); - - for (int i = 0; i < (int)parameters->fragmentionsfortheoreticalspectra.size(); i++) { - if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].nterminal) { - for (int j = 0; j < len; j++) { - if (theoreticalspectrum->getVisualCoverage()[i].series[j] > 0) { - name = parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name[0] + to_string(j + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep/4 + horizontalstep/8 + horizontalstep*j + horizontalstep/2, topmargin - 35, name, false); + if (parameters && (theoreticalspectrum->getVisualCoverage().size() > 0)) { + + unordered_set labels; + labels.clear(); + + string name; + int len = (int)theoreticalspectrum->getVisualCoverage()[0].series.size(); + + for (int i = 0; i < (int)parameters->fragmentionsfortheoreticalspectra.size(); i++) { + if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].nterminal) { + for (int j = 0; j < len; j++) { + if (theoreticalspectrum->getVisualCoverage()[i].series[j] > 0) { + name = parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name[0] + to_string(j + 1) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep/4 + horizontalstep/8 + horizontalstep*j + horizontalstep/2, topmargin - 35, name, false); + } } } - } - if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].cterminal) { - for (int j = len - 1; j >= 0; j--) { - if (theoreticalspectrum->getVisualCoverage()[i].series[len - j - 1] > 0) { - name = parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name[0] + to_string(len - j) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name.substr(1); - insertLabel(labels, leftmargin + horizontalstep*(j + 1), topmargin + 35, name, false); + if (parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].cterminal) { + for (int j = len - 1; j >= 0; j--) { + if (theoreticalspectrum->getVisualCoverage()[i].series[len - j - 1] > 0) { + name = parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name[0] + to_string(len - j) + parameters->fragmentdefinitions[parameters->fragmentionsfortheoreticalspectra[i]].name.substr(1); + insertLabel(labels, leftmargin + horizontalstep*(j + 1), topmargin + 35, name, false); + } } } } - } - painter.setPen(QPen(Qt::red, 2, Qt::SolidLine)); - for (auto it = labels.begin(); it != labels.end(); ++it) { - painter.drawText(it->x, it->y, width(), 20, Qt::AlignLeft, it->label.c_str()); + painter.setPen(QPen(Qt::red, 2, Qt::SolidLine)); + for (auto it = labels.begin(); it != labels.end(); ++it) { + painter.drawText(it->x, it->y, width(), 20, Qt::AlignLeft, it->label.c_str()); + } + } } diff --git a/CycloBranch/gui/cLinearWidget.h b/CycloBranch/gui/cLinearWidget.h index 092d3cc..e14d1a6 100644 --- a/CycloBranch/gui/cLinearWidget.h +++ b/CycloBranch/gui/cLinearWidget.h @@ -77,7 +77,7 @@ struct hash_cIonLabel { \retval size_t hashed ion label */ size_t operator()(const cIonLabel& label) const { - return hash()(to_string(label.x) + to_string(label.y)); + return std::hash()(to_string(label.x) + to_string(label.y)); } }; @@ -127,6 +127,28 @@ class cLinearWidget : public QWidget void initialize(cParameters* parameters, cTheoreticalSpectrum* theoreticalspectrum); + /** + \brief Export peptide into a PDF or a PS file. + \param filename filename + \param postscript if true then PS file is generated instead of PDF + */ + void exportToPDF(QString filename, bool postscript); + + + /** + \brief Export peptide scene into a PNG file. + \param filename filename + */ + void exportToPNG(QString filename); + + + /** + \brief Export peptide scene into a SVG file. + \param filename filename + */ + void exportToSVG(QString filename); + + protected: @@ -139,6 +161,8 @@ class cLinearWidget : public QWidget private: + void paint(QPainter& painter); + cParameters* parameters; cTheoreticalSpectrum* theoreticalspectrum; diff --git a/CycloBranch/gui/cMainThread.cpp b/CycloBranch/gui/cMainThread.cpp index e7464a0..d5da33b 100644 --- a/CycloBranch/gui/cMainThread.cpp +++ b/CycloBranch/gui/cMainThread.cpp @@ -1,30 +1,26 @@ #include "gui/cMainThread.h" -QString appname = "CycloBranch"; -QString appversion = "v. 1.0.850 (64-bit)"; - - bool cMainThread::checkModifications(cParameters& parameters, cSequence& sequence, int& startmodifid, int& endmodifid, int& middlemodifid, string& errormessage) { startmodifid = 0; endmodifid = 0; middlemodifid = 0; errormessage = ""; - if ((parameters.peptidetype == linear) || (parameters.peptidetype == branched) || (parameters.peptidetype == lasso) || (parameters.peptidetype == linearpolysaccharide)) { + if ((sequence.getPeptideType() == linear) || (sequence.getPeptideType() == branched) || (sequence.getPeptideType() == lasso) || (sequence.getPeptideType() == linearpolysaccharide)) { - if ((parameters.peptidetype == linear) || (parameters.peptidetype == branched) || (parameters.peptidetype == linearpolysaccharide)) { + if ((sequence.getPeptideType() == linear) || (sequence.getPeptideType() == branched) || (sequence.getPeptideType() == linearpolysaccharide)) { startmodifid = -1; endmodifid = -1; } - if ((parameters.peptidetype == branched) || (parameters.peptidetype == lasso)) { + if ((sequence.getPeptideType() == branched) || (sequence.getPeptideType() == lasso)) { middlemodifid = -1; } for (int i = 0; i < (int)parameters.searchedmodifications.size(); i++) { - if ((parameters.peptidetype == linear) || (parameters.peptidetype == branched) || (parameters.peptidetype == linearpolysaccharide)) { + if ((sequence.getPeptideType() == linear) || (sequence.getPeptideType() == branched) || (sequence.getPeptideType() == linearpolysaccharide)) { if (parameters.searchedmodifications[i].name.compare(sequence.getNTterminalModification()) == 0) { startmodifid = i; } @@ -34,7 +30,7 @@ bool cMainThread::checkModifications(cParameters& parameters, cSequence& sequenc } } - if ((parameters.peptidetype == branched) || (parameters.peptidetype == lasso)) { + if ((sequence.getPeptideType() == branched) || (sequence.getPeptideType() == lasso)) { if (parameters.searchedmodifications[i].name.compare(sequence.getBranchModification()) == 0) { middlemodifid = i; } @@ -43,18 +39,17 @@ bool cMainThread::checkModifications(cParameters& parameters, cSequence& sequenc } if (startmodifid == -1) { - errormessage = "The N-terminal modification in the sequence " + sequence.getSequence() + " is not listed in the field 'N-terminal and C-terminal modifications': " + sequence.getNTterminalModification(); - + errormessage = "The N-terminal modification in the sequence " + sequence.getSequence() + " is not defined: " + sequence.getNTterminalModification(); return false; } if (endmodifid == -1) { - errormessage = "The C-terminal modification in the sequence " + sequence.getSequence() + " is not listed in the field 'N-terminal and C-terminal modifications': " + sequence.getCTterminalModification(); + errormessage = "The C-terminal modification in the sequence " + sequence.getSequence() + " is not defined: " + sequence.getCTterminalModification(); return false; } if (middlemodifid == -1) { - errormessage = "The branch modification in the sequence " + sequence.getSequence() + " is not listed in the field 'N-terminal and C-terminal modifications': " + sequence.getBranchModification(); + errormessage = "The branch modification in the sequence " + sequence.getSequence() + " is not defined: " + sequence.getBranchModification(); return false; } @@ -64,112 +59,9 @@ bool cMainThread::checkModifications(cParameters& parameters, cSequence& sequenc } -void cMainThread::parseBranch(peptideType peptidetype, string& composition, vector& vectorcomposition, int& branchstart, int& branchend) { - string s = composition; - cBrick b; - branchstart = -1; - branchend = -1; - - if ((peptidetype == branched) || (peptidetype == lasso)) { - int i = 0; - while (i < (int)s.size()) { - if (s[i] == '\\') { - s.erase(s.begin() + i); - } - else { - i++; - } - } - - for (int i = 0; i < (int)s.size(); i++) { - if (s[i] == '(') { - if (i > 0) { - b.clear(); - b.setComposition(s.substr(0, i - 1), false); - branchstart = getNumberOfBricks(b.getComposition()); - s[i] = '-'; - } - else { - s.erase(s.begin()); - branchstart = 0; - } - break; - } - } - - for (int i = 0; i < (int)s.size(); i++) { - if (s[i] == ')') { - b.clear(); - b.setComposition(s.substr(0, i - 1), false); - branchend = getNumberOfBricks(b.getComposition()) - 1; - if (i < (int)s.size() - 1) { - s[i] = '-'; - } - else { - s.erase(s.begin() + i); - } - break; - } - } - - if (branchend <= branchstart) { - branchstart = -1; - branchend = -1; - } - } - - b.clear(); - b.setComposition(s, false); - b.explodeToStringComposition(vectorcomposition); -} - - -bool cMainThread::checkRegex(cParameters& parameters, string& sequence, string& errormessage) { - errormessage = ""; - - if (sequence.compare("") == 0) { - errormessage = "The sequence is empty."; - return false; - } - - regex rx; - // [^\\[\\]]+ is used instead of .+ to prevent from a too complex regex error - switch (parameters.peptidetype) - { - case linear: - case cyclic: - case linearpolysaccharide: - rx = "^\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*$"; - break; - case branched: - rx = "^\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*\\\\\\(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*\\\\\\)\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*$"; - break; - case lasso: - rx = "(^(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*)?\\\\\\(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*\\\\\\)\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*$|^\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*\\\\\\(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*\\\\\\)(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*)?$)"; - break; - case other: - default: - rx = ".*"; - break; - } - - try { - if (!(regex_search(sequence, rx))) { - errormessage = "The format of sequence is invalid: " + sequence + "."; - return false; - } - } - catch (std::regex_error& e) { - errormessage = "cMainThread::checkRegex: regex_search failed, error no. " + to_string(e.code()); - return false; - } - - return true; -} - - -cMainThread::cMainThread(cParameters& parameters, bool enablelogwindow, bool enablestdout) { +cMainThread::cMainThread(cParameters& parameters, cTheoreticalSpectrumList& theoreticalspectrumlist, bool enablelogwindow, bool enablestdout) { this->parameters = parameters; + this->theoreticalspectrumlist = &theoreticalspectrumlist; this->enablelogwindow = enablelogwindow; this->enablestdout = enablestdout; @@ -234,7 +126,9 @@ cMainThread& cMainThread::operator<<(StandardEndLine manip) { void cMainThread::run() { - emitStartSignals(); + if (parameters.mode != denovoengine) { + emit setGraph(""); + } cMainThread* os = this; string errormessage; @@ -242,6 +136,8 @@ void cMainThread::run() { cCandidateSet candidates; candidates.getSet().clear(); + theoreticalspectrumlist->clear(); + QTime time; time.start(); @@ -251,24 +147,15 @@ void cMainThread::run() { parameters.setOutputStream(*os); if (parameters.checkAndPrepare() == -1) { - emit safeExit(); + emitEndSignals(); return; } *os << parameters.printToString(); - if ((parameters.mode == denovoengine) || (parameters.mode == singlecomparison) || (parameters.mode == databasesearch)) { - if (!parameters.bricksdatabase.replaceAcronymsByIDs(parameters.sequencetag, errormessage)) { - *os << "Error: " << errormessage << endl; - emit safeExit(); - return; - } - } - if (parameters.mode == singlecomparison) { - errormessage = ""; - if (!checkRegex(parameters, parameters.searchedsequence, errormessage)) { + if (!checkRegex(parameters.peptidetype, parameters.searchedsequence, errormessage)) { *os << "Error: " << errormessage << endl; - emit safeExit(); + emitEndSignals(); return; } } @@ -276,41 +163,27 @@ void cMainThread::run() { if ((parameters.mode == denovoengine) || (parameters.mode == singlecomparison) || (parameters.mode == databasesearch)) { if (!parameters.bricksdatabase.replaceAcronymsByIDs(parameters.searchedsequence, errormessage)) { *os << "Error: " << errormessage << endl; - emit safeExit(); + emitEndSignals(); return; } - } - if ((parameters.mode == denovoengine) || (parameters.mode == singlecomparison) || (parameters.mode == databasesearch)) { - if (parameters.peptidetype != cyclic) { - // check summary formulas of modifications - errormessage = ""; - cSummaryFormula formula; - for (int i = 0; i < (int)parameters.searchedmodifications.size(); i++) { - formula.clear(); - formula.setFormula(parameters.searchedmodifications[i].summary); - if (formula.isValid(errormessage)) { - parameters.searchedmodifications[i].massdifference = formula.getMass(); - } - else { - *os << errormessage << endl; - emit safeExit(); - return; - } - } + if (!parameters.bricksdatabase.replaceAcronymsByIDs(parameters.sequencetag, errormessage)) { + *os << "Error: " << errormessage << endl; + emitEndSignals(); + return; } } parameters.peaklist.sortbyMass(); - parameters.peaklist.cropMinimumMZRatio(parameters.minimummz); + parameters.peaklist.cropMinimumMZRatio(parameters.minimummz, parameters.fragmentmasserrortolerance); if ((parameters.mode == denovoengine) || (parameters.mode == singlecomparison) || (parameters.mode == databasesearch)) { - parameters.peaklist.cropMaximumMZRatio(uncharge(parameters.precursormass, parameters.precursorcharge)); + parameters.peaklist.cropMaximumMZRatio(charge(uncharge(parameters.precursormass, parameters.precursorcharge), (parameters.precursorcharge > 0)?1:-1), parameters.precursormasserrortolerance); } if (parameters.peaklist.normalizeIntenzity() == -1) { - *os << "Error: the spectrum cannot be normalized; the maximum intensity is <= 0." << endl; - emit safeExit(); + *os << "Error: the spectrum cannot be normalized because the maximum intensity is <= 0. The format of peaklist is likely incorrect." << endl; + emitEndSignals(); return; } parameters.peaklist.cropIntenzity(parameters.minimumrelativeintensitythreshold); @@ -323,13 +196,47 @@ void cMainThread::run() { } + if ((parameters.mode == denovoengine) || (parameters.mode == singlecomparison) || (parameters.mode == databasesearch)) { + int startmodifid, endmodifid, middlemodifid; + + cSequence sequence; + sequence.setNTterminalModification(parameters.searchedsequenceNtermmodif); + sequence.setCTterminalModification(parameters.searchedsequenceCtermmodif); + sequence.setBranchModification(parameters.searchedsequenceTmodif); + sequence.setPeptideType(parameters.peptidetype); + + // check for names of modifications which are used with the searched sequence + errormessage = ""; + if (!checkModifications(parameters, sequence, startmodifid, endmodifid, middlemodifid, errormessage)) { + *os << endl << "Error: " << errormessage << endl; + emitEndSignals(); + return; + } + + // single comparison of a peaklist with a theoretical spectrum + if (parameters.mode == singlecomparison) { + int branchstart, branchend; + vector v; + cCandidate c; + vector netmp; + + parseBranch(parameters.peptidetype, parameters.searchedsequence, v, branchstart, branchend); + // startmodifid, endmodifid and middlemodifid were filled up by checkModifications + c.setCandidate(v, netmp, startmodifid, endmodifid, middlemodifid, branchstart, branchend); + candidates.getSet().insert(c); + + graphreaderisworking = false; + } + } + + // de novo search engine if (parameters.mode == denovoengine) { // create the de novo graph graph.initialize(*os, parameters); if (graph.createGraph(terminatecomputation) == -1) { - endNow(); + emitEndSignals(); return; } @@ -339,12 +246,12 @@ void cMainThread::run() { // note: paths finishing in precursor minus X are removed, however, precursor peak is always present thus any candidate should not be lost if (parameters.blindedges == 1) { if (graph.removeEdgesFormingPathsNotStartingFromFirstNode(terminatecomputation) == -1) { - endNow(); + emitEndSignals(); return; } if (graph.removeEdgesFormingPathsNotFinishingInPrecursor(terminatecomputation) == -1) { - endNow(); + emitEndSignals(); return; } } @@ -352,12 +259,12 @@ void cMainThread::run() { // blind paths are connected if (parameters.blindedges == 2) { if (graph.connectEdgesFormingPathsNotStartingFromFirstNode(terminatecomputation) == -1) { - endNow(); + emitEndSignals(); return; } if (graph.connectEdgesFormingPathsNotFinishingInPrecursor(terminatecomputation) == -1) { - endNow(); + emitEndSignals(); return; } } @@ -366,7 +273,7 @@ void cMainThread::run() { emit setGraph(graph.printGraph()); if (graph.removePathsWhichCanBeSubstitutedByLongerPath(terminatecomputation) == -1) { - endNow(); + emitEndSignals(); return; } @@ -395,7 +302,6 @@ void cMainThread::run() { *os << "The number of sequence candidates is too high. The identification would be very time-consuming. Please, change the settings and search again." << endl << endl; *os << "Aborted." << endl; emitEndSignals(); - endNow(); return; } @@ -405,35 +311,6 @@ void cMainThread::run() { } - // single comparison of a peaklist with a theoretical spectrum - if (parameters.mode == singlecomparison) { - vector v; - cCandidate c; - int startmodifid, endmodifid, middlemodifid, branchstart, branchend; - - cSequence sequence; - sequence.setNTterminalModification(parameters.searchedsequenceNtermmodif); - sequence.setCTterminalModification(parameters.searchedsequenceCtermmodif); - sequence.setBranchModification(parameters.searchedsequenceTmodif); - - errormessage = ""; - if (!checkModifications(parameters, sequence, startmodifid, endmodifid, middlemodifid, errormessage)) { - *os << endl << "Error: " << errormessage << endl; - emitEndSignals(); - endNow(); - return; - } - - parseBranch(parameters.peptidetype, parameters.searchedsequence, v, branchstart, branchend); - - vector netmp; - c.setCandidate(v, netmp, startmodifid, endmodifid, middlemodifid, branchstart, branchend); - candidates.getSet().insert(c); - - graphreaderisworking = false; - } - - // database search - MS/MS mode if (parameters.mode == databasesearch) { string composition; @@ -457,7 +334,7 @@ void cMainThread::run() { } // check format of sequence - if (!calculatesummaries && !checkRegex(parameters, parameters.sequencedatabase[i].getSequence(), errormessage)) { + if (!calculatesummaries && !checkRegex(parameters.sequencedatabase[i].getPeptideType(), parameters.sequencedatabase[i].getSequence(), errormessage)) { *os << "Ignored sequence: " << errormessage << endl; continue; } @@ -475,12 +352,12 @@ void cMainThread::run() { continue; } - // parse branch of a branched or a lasso peptide + // parse branch of a branched or a branch-cyclic peptide parseBranch(parameters.sequencedatabase[i].getPeptideType(), composition, v, branchstart, branchend); // set candidate and check precursor mass error c.setCandidate(v, netmp, startmodifid, endmodifid, middlemodifid, branchstart, branchend); - if (!calculatesummaries && !isInPpmMassErrorTolerance(uncharge(parameters.precursormass, parameters.precursorcharge), c.getPrecursorMass(parameters.bricksdatabase, ¶meters), parameters.precursormasserrortolerance)) { + if (!calculatesummaries && !isInPpmMassErrorTolerance(charge(uncharge(parameters.precursormass, parameters.precursorcharge), (parameters.precursorcharge > 0)?1:-1), c.getPrecursorMass(parameters.bricksdatabase, ¶meters), parameters.precursormasserrortolerance)) { continue; } @@ -494,7 +371,7 @@ void cMainThread::run() { if (calculatesummaries) { *os << endl << "done." << endl; - emit safeExit(); + emitEndSignals(); return; } @@ -510,18 +387,17 @@ void cMainThread::run() { *os << "Comparing theoretical peaks with the peak list... " << endl; cTheoreticalSpectrum ts; ts.compareMSSpectrum(¶meters); - theoreticalspectra.initialize(*os, parameters, &graph); - theoreticalspectra.add(ts); + theoreticalspectrumlist->initialize(*os, parameters, &graph); + theoreticalspectrumlist->add(ts); *os << " ok" << endl; } if ((parameters.mode == denovoengine) || (parameters.mode == singlecomparison) || (parameters.mode == databasesearch)) { *os << "Comparing theoretical spectra of candidates with the peak list... " << endl; - theoreticalspectra.initialize(*os, parameters, &graph); - if (theoreticalspectra.parallelCompareAndStore(candidates, terminatecomputation) == -1) { + theoreticalspectrumlist->initialize(*os, parameters, &graph); + if (theoreticalspectrumlist->parallelCompareAndStore(candidates, terminatecomputation) == -1) { emitEndSignals(); - endNow(); return; } *os << " ok" << endl; @@ -561,8 +437,6 @@ void cMainThread::run() { } */ - emitEndSignals(); - int secs = time.elapsed() / 1000; int mins = (secs / 60) % 60; int hrs = (secs / 3600); @@ -573,49 +447,31 @@ void cMainThread::run() { *os << "====================================================================================================" << endl; -} - - -void cMainThread::emitStartSignals() { - emit enableRunButtonAndSettings(false); - emit enableStopButton(true); - emit enableButtonsHandlingResults(false); + emitEndSignals(); - if (parameters.mode != denovoengine) { - emit setGraph(""); - } } void cMainThread::emitEndSignals() { - emit sendParameters(parameters); + emit setGraph(graph.printGraph()); - emit prepareColumns(); + emit sendParameters(parameters); + emit reportSpectra(); - for (int i = 0; i < theoreticalspectra.size(); i++) { - emit sendTheoreticalSpectrum(theoreticalspectra[i]); - theoreticalspectra[i].clear(); + if (terminatecomputation) { + *this << endl << "Aborted by user. Partial results have been reported if they are available." << endl; } - emit fitColumns(); - emit enableRunButtonAndSettings(true); emit enableStopButton(false); emit enableButtonsHandlingResults(true); } -void cMainThread::endNow() { - emit setGraph(graph.printGraph()); - emit safeExit(); - if (terminatecomputation) { - *this << endl << "Aborted by user." << endl; - } -} - - void cMainThread::stopComputation() { - *this << endl << endl << "Please wait while stopping threads and generating partial results..." << endl; + if (!terminatecomputation) { + *this << endl << endl << "Stopping..." << endl; + } terminatecomputation = true; } diff --git a/CycloBranch/gui/cMainThread.h b/CycloBranch/gui/cMainThread.h index 3d7c680..a52e15d 100644 --- a/CycloBranch/gui/cMainThread.h +++ b/CycloBranch/gui/cMainThread.h @@ -12,6 +12,7 @@ #include #include +#include "core/utilities.h" #include "core/cParameters.h" #include "core/cDeNovoGraph.h" #include "core/cTheoreticalSpectrum.h" @@ -19,18 +20,6 @@ using namespace std; -/** - \brief The name of the application. -*/ -extern QString appname; - - -/** - \brief The version of the application. -*/ -extern QString appversion; - - /** \brief The class representing a thread launched by the command 'Search->Run'. */ @@ -46,25 +35,22 @@ class cMainThread : public QThread { bool graphreaderisworking; cDeNovoGraph graph; - cTheoreticalSpectrumList theoreticalspectra; + cTheoreticalSpectrumList* theoreticalspectrumlist; cParameters parameters; bool checkModifications(cParameters& parameters, cSequence& sequence, int& startmodifid, int& endmodifid, int& middlemodifid, string& errormessage); - void parseBranch(peptideType peptidetype, string& composition, vector& vectorcomposition, int& branchstart, int& branchend); - - bool checkRegex(cParameters& parameters, string& sequence, string& errormessage); - public: /** \brief The constructor. \param parameters reference to input paramaters + \param theoreticalspectrumlist a list of theoretical spectra \param enablelogwindow if true then messages are logged into the log window \param enablestdout if true then messages are logged into the standard output */ - cMainThread(cParameters& parameters, bool enablelogwindow = true, bool enablestdout = true); + cMainThread(cParameters& parameters, cTheoreticalSpectrumList& theoreticalspectrumlist, bool enablelogwindow = true, bool enablestdout = true); /** @@ -136,24 +122,12 @@ class cMainThread : public QThread { void run(); - /** - \brief The signals emitted when the thread has launched. - */ - void emitStartSignals(); - - /** \brief The signals emitted when the thread has successfully finished. */ void emitEndSignals(); - /** - \brief The signals emitted when the thread was forced to stop. - */ - void endNow(); - - signals: @@ -185,13 +159,6 @@ class cMainThread : public QThread { void enableButtonsHandlingResults(bool enable); - /** - \brief Send a theoretical spectrum to cMainWindow when the thread has finished. - \param theoreticalspectrum a theoretical spectrum - */ - void sendTheoreticalSpectrum(cTheoreticalSpectrum theoreticalspectrum); - - /** \brief Send parameters to cMainWindow when the thread has finished. \param parameters parameters @@ -200,15 +167,9 @@ class cMainThread : public QThread { /** - \brief Prepare columns in cMainWindow when the thread has finished. + \brief Report results. */ - void prepareColumns(); - - - /** - \brief Fit the width of columns in cMainWindow. - */ - void fitColumns(); + void reportSpectra(); /** @@ -218,12 +179,6 @@ class cMainThread : public QThread { void setGraph(string s); - /** - \brief Safely exit when the thread was forced to stop. - */ - void safeExit(); - - private slots: void stopComputation(); diff --git a/CycloBranch/gui/cMainWindow.cpp b/CycloBranch/gui/cMainWindow.cpp index d4c954f..c8bd9e3 100644 --- a/CycloBranch/gui/cMainWindow.cpp +++ b/CycloBranch/gui/cMainWindow.cpp @@ -1,4 +1,5 @@ #include "gui/cMainWindow.h" +#include "gui/cEventFilter.h" #include #include @@ -13,38 +14,113 @@ #include #include #include +#include +#include cMainWindow::cMainWindow() { + setWindowTitle(appname); + setWindowIcon(QIcon(":/images/cb.png")); + // main menu menuBar = new QMenuBar(this); + menuBar->setNativeMenuBar(false); + // items in the menu menuFile = new QMenu(tr("&File"), this); menuSearch = new QMenu(tr("&Search"), this); menuTools = new QMenu(tr("&Tools"), this); menuView = new QMenu(tr("&View"), this); menuHelp = new QMenu(tr("&Help"), this); - + + // subitems in the menu - // actionOpen = new QAction(tr("&Open"), this); - actionOpenResults = new QAction(tr("&Open Results..."), this); - actionSaveResults = new QAction(tr("&Save Results..."), this); - actionExportToCsv = new QAction(tr("&Export to CSV"), this); - actionExportToHTML = new QAction(tr("&Export to HTML"), this); - actionQuit = new QAction(tr("&Quit"), this); - actionRun = new QAction(tr("&Run"), this); - actionStop = new QAction(tr("&Stop"), this); + actionOpenResults = new QAction(QIcon(":/images/icons/52.png"), tr("&Open Results..."), this); + actionOpenResults->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_O)); + + actionSaveResults = new QAction(QIcon(":/images/icons/22.png"), tr("&Save Results..."), this); + actionSaveResults->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); + + actionExportToCsv = new QAction(QIcon(":/images/icons/62.png"), tr("&Export to CSV"), this); + actionExportToCsv->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_E)); + + actionExportToHTML = new QAction(QIcon(":/images/icons/77.png"), tr("Export to &HTML"), this); + actionExportToHTML->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_H)); + + actionQuit = new QAction(QIcon(":/images/icons/33.png"), tr("&Quit"), this); + actionQuit->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q)); + + + actionRun = new QAction(QIcon(":/images/icons/93.png"), tr("&Run"), this); + actionRun->setShortcut(QKeySequence(Qt::Key_F5)); + + actionStop = new QAction(QIcon(":/images/icons/89.png"), tr("S&top"), this); + actionStop->setShortcut(QKeySequence(Qt::Key_F6)); actionStop->setEnabled(false); - actionProperties = new QAction(tr("&Settings..."), this); - actionBricksDatabase = new QAction(tr("&Building Blocks Editor"), this); - actionSequenceDatabase = new QAction(tr("&Sequence Database Editor"), this); - actionGraph = new QAction(tr("&Graph"), this); - actionLog = new QAction(tr("&Log Window"), this); - actionHTMLDocumentation = new QAction(tr("&HTML Documentation"), this); - actionPDFManual = new QAction(tr("&PDF Manual"), this); - actionAbout = new QAction(tr("&About"), this); + + actionProperties = new QAction(QIcon(":/images/icons/73.png"), tr("&Settings..."), this); + actionProperties->setShortcut(QKeySequence(Qt::Key_F7)); + + + actionBricksDatabase = new QAction(QIcon(":/images/icons/68.png"), tr("&Building Blocks Editor"), this); + actionBricksDatabase->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_B)); + + actionSequenceDatabase = new QAction(QIcon(":/images/icons/26.png"), tr("Sequence &Database Editor"), this); + actionSequenceDatabase->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_D)); + + actionModifications = new QAction(QIcon(":/images/icons/61.png"), tr("&Modifications Editor"), this); + actionModifications->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M)); + + actionDrawPeptide = new QAction(QIcon(":/images/icons/96.png"), tr("Draw &Peptide"), this); + actionDrawPeptide->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_P)); + + + actionGraph = new QAction(QIcon(":/images/icons/32.png"), tr("De Novo &Graph"), this); + actionGraph->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_G)); + + actionLog = new QAction(QIcon(":/images/icons/2.png"), tr("&Log Window"), this); + actionLog->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L)); + + + actionHTMLDocumentation = new QAction(QIcon(":/images/icons/3.png"), tr("&HTML Documentation"), this); + actionHTMLDocumentation->setShortcut(QKeySequence(Qt::Key_F1)); + + actionPDFManual = new QAction(QIcon(":/images/icons/4.png"), tr("&PDF Manual"), this); + actionPDFManual->setShortcut(QKeySequence(Qt::Key_F2)); + + actionAbout = new QAction(QIcon(":/images/icons/48.png"), tr("&About"), this); + actionAbout->setShortcut(QKeySequence(Qt::Key_F3)); + + + toolbarFile = addToolBar(tr("File")); + toolbarFile->addAction(actionOpenResults); + toolbarFile->addAction(actionSaveResults); + toolbarFile->addAction(actionExportToCsv); + toolbarFile->addAction(actionExportToHTML); + toolbarFile->addAction(actionQuit); + + toolbarSearch = addToolBar(tr("Search")); + toolbarSearch->addAction(actionRun); + toolbarSearch->addAction(actionStop); + toolbarSearch->addAction(actionProperties); + + toolbarTools = addToolBar(tr("Tools")); + toolbarTools->addAction(actionBricksDatabase); + toolbarTools->addAction(actionSequenceDatabase); + toolbarTools->addAction(actionModifications); + toolbarTools->addAction(actionDrawPeptide); + + toolbarView = addToolBar(tr("View")); + toolbarView->addAction(actionGraph); + toolbarView->addAction(actionLog); + + toolbarHelp = addToolBar(tr("Help")); + toolbarHelp->addAction(actionHTMLDocumentation); + toolbarHelp->addAction(actionPDFManual); + toolbarHelp->addAction(actionAbout); + // widgets results = new QTableWidget(0, 0, this); @@ -55,8 +131,10 @@ cMainWindow::cMainWindow() { graph = new cGraphWidget(); bricksdatabasewidget = new cBricksDatabaseWidget(); - sequencedatabasewidget = new cSequenceDatabaseWidget(); - parameterswidget = new cParametersWidget(); + sequencedatabasewidget = new cSequenceDatabaseWidget(this); + modificationswidget = new cModificationsWidget(); + drawpeptidewidget = new cDrawPeptideWidget(this); + parameterswidget = new cParametersWidget(this); // additional key shortcuts // actionOpen->setShortcut(QKeySequence("Ctrl+O")); @@ -67,13 +145,14 @@ cMainWindow::cMainWindow() { connect(actionSaveResults, SIGNAL(triggered()), this, SLOT(saveResultsFile())); connect(actionExportToCsv, SIGNAL(triggered()), this, SLOT(exportToCsv())); connect(actionExportToHTML, SIGNAL(triggered()), this, SLOT(exportToHTML())); - connect(actionQuit, SIGNAL(triggered()), this, SLOT(stop())); - connect(actionQuit, SIGNAL(triggered()), qApp, SLOT(quit())); + connect(actionQuit, SIGNAL(triggered()), this, SLOT(quitApplication())); connect(actionRun, SIGNAL(triggered()), this, SLOT(run())); connect(actionStop, SIGNAL(triggered()), this, SLOT(stop())); connect(actionProperties, SIGNAL(triggered()), this, SLOT(showProperties())); connect(actionBricksDatabase, SIGNAL(triggered()), this, SLOT(showBricksDatabase())); connect(actionSequenceDatabase, SIGNAL(triggered()), this, SLOT(showSequenceDatabase())); + connect(actionModifications, SIGNAL(triggered()), this, SLOT(showModifications())); + connect(actionDrawPeptide, SIGNAL(triggered()), this, SLOT(showDrawPeptideWidget())); connect(actionGraph, SIGNAL(triggered()), this, SLOT(showGraph())); connect(actionLog, SIGNAL(triggered()), this, SLOT(showHideLog())); connect(actionHTMLDocumentation, SIGNAL(triggered()), this, SLOT(showHTMLDocumentation())); @@ -95,6 +174,9 @@ cMainWindow::cMainWindow() { menuSearch->addAction(actionProperties); menuTools->addAction(actionBricksDatabase); menuTools->addAction(actionSequenceDatabase); + menuTools->addAction(actionModifications); + menuTools->addSeparator(); + menuTools->addAction(actionDrawPeptide); menuView->addAction(actionGraph); menuView->addSeparator(); menuView->addAction(actionLog); @@ -125,6 +207,8 @@ cMainWindow::cMainWindow() { graph->hide(); bricksdatabasewidget->hide(); sequencedatabasewidget->hide(); + modificationswidget->hide(); + drawpeptidewidget->hide(); parameterswidget->hide(); splitter->setOrientation(Qt::Vertical); @@ -138,24 +222,131 @@ cMainWindow::cMainWindow() { // set the size of main window resize(1280, 700); - setWindowTitle(appname); - resultsbasecolumncount = 8; resultsspecificcolumncount = 0; dbsearchspecificcolumncount = 0; - resultsDetails.clear(); + theoreticalspectrumlist.clear(); + spectradetails.clear(); lastdirexporttocsv = "./"; lastdirexporttohtml = "./"; lastdirsaveresults = "./"; lastdiropenresults = "./"; + + quitapp = false; } void cMainWindow::closeEvent(QCloseEvent *event) { - emit stopComputation(); - qApp->quit(); + quitApplication(); + event->ignore(); +} + + +void cMainWindow::reportSpectrum(int id, cTheoreticalSpectrum& theoreticalspectrum) { + int row = results->rowCount(); + results->insertRow(row); + + results->setItem(row, 0, widgetitemallocator.getNewItem()); + + results->setItem(row, 1, widgetitemallocator.getNewItem()); + results->item(row, 1)->setData(Qt::DisplayRole, results->rowCount()); + + if ((parameters.mode == denovoengine) || (parameters.mode == singlecomparison) || (parameters.mode == databasesearch)) { + + if (parameters.mode == databasesearch) { + results->setItem(row, 2, widgetitemallocator.getNewItem()); + results->item(row, 2)->setText(theoreticalspectrum.getCandidate().getName().c_str()); + } + + results->setItem(row, 2 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 2 + dbsearchspecificcolumncount)->setText(stripHTML(theoreticalspectrum.getCandidate().getAcronymPeptideNameWithHTMLReferences()).c_str()); + + results->setItem(row, 3 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 3 + dbsearchspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getCandidate().getSummaryFormula(parameters, parameters.peptidetype).c_str()); + + results->setItem(row, 4 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 4 + dbsearchspecificcolumncount)->setData(Qt::DisplayRole, getNumberOfBricks(theoreticalspectrum.getCandidate().getComposition())); + + switch (parameters.peptidetype) + { + case linear: + results->setItem(row, 5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 5 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getStartModifID()].name.c_str()); + results->setItem(row, 6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 6 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getEndModifID()].name.c_str()); + break; + case branched: + results->setItem(row, 5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 5 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getStartModifID()].name.c_str()); + results->setItem(row, 6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 6 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getMiddleModifID()].name.c_str()); + results->setItem(row, 7 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 7 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getEndModifID()].name.c_str()); + break; + case cyclic: + results->setItem(row, 5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 5 + dbsearchspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfMatchedBricks()); + break; + case lasso: + results->setItem(row, 5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 5 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getMiddleModifID()].name.c_str()); + break; + case linearpolysaccharide: + results->setItem(row, 5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 5 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getStartModifID()].name.c_str()); + results->setItem(row, 6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 6 + dbsearchspecificcolumncount)->setText(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getEndModifID()].name.c_str()); + break; + case other: + default: + break; + } + + results->setItem(row, 5 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 5 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfMatchedPeaks()); + + results->setItem(row, 6 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 6 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getRatioOfMatchedPeaks()*100); + + results->setItem(row, 7 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); + results->item(row, 7 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getWeightedIntensityScore()); + + for (int i = 0; i < (int)parameters.fragmentionsfortheoreticalspectra.size(); i++) { + results->setItem(row, resultsbasecolumncount + dbsearchspecificcolumncount + resultsspecificcolumncount + i, widgetitemallocator.getNewItem()); + results->item(row, resultsbasecolumncount + dbsearchspecificcolumncount + resultsspecificcolumncount + i)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfMatchedPeaks(parameters.fragmentionsfortheoreticalspectra[i])); + } + + if ((parameters.peptidetype == cyclic) && parameters.enablescrambling) { + results->setItem(row, results->columnCount() - 1, widgetitemallocator.getNewItem()); + results->item(row, results->columnCount() - 1)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfScrambledPeaks()); + } + + if (theoreticalspectrum.isValid()) { + results->item(row, 0)->setData(Qt::DisplayRole, "*"); + for (int i = 0; i < results->columnCount(); i++) { + results->item(row, i)->setBackground(Qt::yellow); + } + } + + } + + + if (parameters.mode == dereplication) { + results->setItem(row, 2, widgetitemallocator.getNewItem()); + results->item(row, 2)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfMatchedPeaks()); + + results->setItem(row, 3, widgetitemallocator.getNewItem()); + results->item(row, 3)->setData(Qt::DisplayRole, theoreticalspectrum.getRatioOfMatchedPeaks()*100); + + results->setItem(row, 4, widgetitemallocator.getNewItem()); + results->item(row, 4)->setData(Qt::DisplayRole, theoreticalspectrum.getWeightedIntensityScore()); + } + + + spectradetails[id].initialize(¶meters, theoreticalspectrum); + spectradetails[id].setWindowTitle(("Theoretical Spectrum No. " + to_string(row+1)).c_str()); } @@ -189,6 +380,24 @@ void cMainWindow::showSequenceDatabase() { } +void cMainWindow::showModifications() { + modificationswidget->show(); + modificationswidget->activateWindow(); +} + + +void cMainWindow::showDrawPeptideWidget() { + drawpeptidewidget->show(); + drawpeptidewidget->activateWindow(); +} + + +void cMainWindow::setAndShowDrawPeptideWidget(int peptidetypeindex, QString sequence) { + drawpeptidewidget->setSequence(peptidetypeindex, sequence); + showDrawPeptideWidget(); +} + + void cMainWindow::showGraph() { graph->show(); graph->activateWindow(); @@ -202,22 +411,26 @@ void cMainWindow::showProperties() { void cMainWindow::run() { + enableRunButtonAndSettings(false); + enableStopButton(true); + enableButtonsHandlingResults(false); + logWindow->clear(); + deleteResults(); - resultsDetails.clear(); + + theoreticalspectrumlist.clear(); + spectradetails.clear(); - cMainThread* thread = new cMainThread(parameterswidget->getParameters(), true, false); + cMainThread* thread = new cMainThread(parameterswidget->getParameters(), theoreticalspectrumlist, true, false); connect(thread, SIGNAL(message(QString)), this, SLOT(updateLog(QString))); connect(thread, SIGNAL(enableRunButtonAndSettings(bool)), this, SLOT(enableRunButtonAndSettings(bool))); connect(thread, SIGNAL(enableStopButton(bool)), this, SLOT(enableStopButton(bool))); connect(thread, SIGNAL(enableButtonsHandlingResults(bool)), this, SLOT(enableButtonsHandlingResults(bool))); - connect(thread, SIGNAL(sendTheoreticalSpectrum(cTheoreticalSpectrum)), this, SLOT(sendTheoreticalSpectrum(cTheoreticalSpectrum))); connect(thread, SIGNAL(sendParameters(cParameters)), this, SLOT(sendParameters(cParameters))); - connect(thread, SIGNAL(prepareColumns()), this, SLOT(prepareColumns())); - connect(thread, SIGNAL(fitColumns()), this, SLOT(fitColumns())); + connect(thread, SIGNAL(reportSpectra()), this, SLOT(reportSpectra())); connect(thread, SIGNAL(setGraph(string)), this, SLOT(setGraph(string))); connect(this, SIGNAL(stopComputation()), thread, SLOT(stopComputation())); - connect(thread, SIGNAL(safeExit()), this, SLOT(safeExit())); thread->start(); } @@ -239,6 +452,11 @@ void cMainWindow::updateLog(QString qstr) { void cMainWindow::enableRunButtonAndSettings(bool enable) { + + if (enable && quitapp) { + qApp->quit(); + } + actionRun->setEnabled(enable); actionProperties->setEnabled(enable); @@ -259,111 +477,16 @@ void cMainWindow::enableButtonsHandlingResults(bool enable) { } -void cMainWindow::sendTheoreticalSpectrum(cTheoreticalSpectrum theoreticalspectrum) { - int row = results->rowCount(); - results->insertRow(row); - - results->setItem(row, 0, new QTableWidgetItem("")); - - results->setItem(row, 1, new QTableWidgetItem()); - results->item(row, 1)->setData(Qt::DisplayRole, results->rowCount()); - - - if ((parameters.mode == denovoengine) || (parameters.mode == singlecomparison) || (parameters.mode == databasesearch)) { - - if (parameters.mode == databasesearch) { - results->setItem(row, 2, new QTableWidgetItem(theoreticalspectrum.getCandidate().getName().c_str())); - } - - results->setItem(row, 2 + dbsearchspecificcolumncount, new QTableWidgetItem(stripHTML(theoreticalspectrum.getAcronymPeptideNameWithHTMLReferences()).c_str())); - - results->setItem(row, 3 + dbsearchspecificcolumncount, new QTableWidgetItem()); - results->item(row, 3 + dbsearchspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getCandidate().getSummaryFormula(parameters, parameters.peptidetype).c_str()); - - results->setItem(row, 4 + dbsearchspecificcolumncount, new QTableWidgetItem()); - results->item(row, 4 + dbsearchspecificcolumncount)->setData(Qt::DisplayRole, getNumberOfBricks(theoreticalspectrum.getCandidate().getComposition())); - - switch (parameters.peptidetype) - { - case linear: - results->setItem(row, 5 + dbsearchspecificcolumncount, new QTableWidgetItem(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getStartModifID()].name.c_str())); - results->setItem(row, 6 + dbsearchspecificcolumncount, new QTableWidgetItem(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getEndModifID()].name.c_str())); - break; - case branched: - results->setItem(row, 5 + dbsearchspecificcolumncount, new QTableWidgetItem(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getStartModifID()].name.c_str())); - results->setItem(row, 6 + dbsearchspecificcolumncount, new QTableWidgetItem(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getMiddleModifID()].name.c_str())); - results->setItem(row, 7 + dbsearchspecificcolumncount, new QTableWidgetItem(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getEndModifID()].name.c_str())); - break; - case cyclic: - results->setItem(row, 5 + dbsearchspecificcolumncount, new QTableWidgetItem()); - results->item(row, 5 + dbsearchspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfMatchedBricks()); - break; - case lasso: - results->setItem(row, 5 + dbsearchspecificcolumncount, new QTableWidgetItem(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getMiddleModifID()].name.c_str())); - break; - case linearpolysaccharide: - results->setItem(row, 5 + dbsearchspecificcolumncount, new QTableWidgetItem(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getStartModifID()].name.c_str())); - results->setItem(row, 6 + dbsearchspecificcolumncount, new QTableWidgetItem(parameters.searchedmodifications[theoreticalspectrum.getCandidate().getEndModifID()].name.c_str())); - break; - case other: - default: - break; - } - - results->setItem(row, 5 + dbsearchspecificcolumncount + resultsspecificcolumncount, new QTableWidgetItem()); - results->item(row, 5 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfMatchedPeaks()); - - results->setItem(row, 6 + dbsearchspecificcolumncount + resultsspecificcolumncount, new QTableWidgetItem()); - results->item(row, 6 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getRatioOfMatchedPeaks()*100); - - results->setItem(row, 7 + dbsearchspecificcolumncount + resultsspecificcolumncount, new QTableWidgetItem()); - results->item(row, 7 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setData(Qt::DisplayRole, theoreticalspectrum.getWeightedIntensityScore()); - - for (int i = 0; i < (int)parameters.fragmentionsfortheoreticalspectra.size(); i++) { - results->setItem(row, resultsbasecolumncount + dbsearchspecificcolumncount + resultsspecificcolumncount + i, new QTableWidgetItem()); - results->item(row, resultsbasecolumncount + dbsearchspecificcolumncount + resultsspecificcolumncount + i)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfMatchedPeaks(parameters.fragmentionsfortheoreticalspectra[i])); - } - - if ((parameters.peptidetype == cyclic) && parameters.enablescrambling) { - results->setItem(row, results->columnCount() - 1, new QTableWidgetItem()); - results->item(row, results->columnCount() - 1)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfScrambledPeaks()); - } - - if (theoreticalspectrum.isValid()) { - results->item(row, 0)->setData(Qt::DisplayRole, "*"); - for (int i = 0; i < results->columnCount(); i++) { - results->item(row, i)->setBackground(Qt::yellow); - } - } - - } - - - if (parameters.mode == dereplication) { - results->setItem(row, 2, new QTableWidgetItem()); - results->item(row, 2)->setData(Qt::DisplayRole, theoreticalspectrum.getNumberOfMatchedPeaks()); - - results->setItem(row, 3, new QTableWidgetItem()); - results->item(row, 3)->setData(Qt::DisplayRole, theoreticalspectrum.getRatioOfMatchedPeaks()*100); - - results->setItem(row, 4, new QTableWidgetItem()); - results->item(row, 4)->setData(Qt::DisplayRole, theoreticalspectrum.getWeightedIntensityScore()); - } - - - cSpectrumDetailWidget sd; - sd.initialize(¶meters, theoreticalspectrum); - sd.setWindowTitle(("Theoretical Spectrum No. " + to_string(row+1)).c_str()); - resultsDetails.push_back(sd); -} - - void cMainWindow::sendParameters(cParameters parameters) { this->parameters = parameters; } -void cMainWindow::prepareColumns() { +void cMainWindow::reportSpectra() { + + if (quitapp) { + return; + } switch (parameters.peptidetype) { @@ -404,51 +527,75 @@ void cMainWindow::prepareColumns() { results->setColumnCount(results->columnCount() + 1); } - results->setHorizontalHeaderItem(0, new QTableWidgetItem("*")); - results->setHorizontalHeaderItem(1, new QTableWidgetItem("Result ID")); + results->setHorizontalHeaderItem(0, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(0)->setText("*"); + + results->setHorizontalHeaderItem(1, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(1)->setText("Result ID"); + if (parameters.mode == databasesearch) { - results->setHorizontalHeaderItem(2, new QTableWidgetItem("Name")); + results->setHorizontalHeaderItem(2, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(2)->setText("Name"); } - results->setHorizontalHeaderItem(2 + dbsearchspecificcolumncount, new QTableWidgetItem("Peptide Sequence")); - results->setHorizontalHeaderItem(3 + dbsearchspecificcolumncount, new QTableWidgetItem("Summary Formula")); - results->setHorizontalHeaderItem(4 + dbsearchspecificcolumncount, new QTableWidgetItem("Number of Bricks")); + results->setHorizontalHeaderItem(2 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(2 + dbsearchspecificcolumncount)->setText("Peptide Sequence"); + results->setHorizontalHeaderItem(3 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(3 + dbsearchspecificcolumncount)->setText("Summary Formula"); + results->setHorizontalHeaderItem(4 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(4 + dbsearchspecificcolumncount)->setText("Number of Bricks"); switch (parameters.peptidetype) { case linear: - results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount, new QTableWidgetItem("N-terminal Modification")); - results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount, new QTableWidgetItem("C-terminal Modification")); + results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(5 + dbsearchspecificcolumncount)->setText("N-terminal Modification"); + results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(6 + dbsearchspecificcolumncount)->setText("C-terminal Modification"); break; case branched: - results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount, new QTableWidgetItem("N-terminal Modification")); - results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount, new QTableWidgetItem("Branch Modification")); - results->setHorizontalHeaderItem(7 + dbsearchspecificcolumncount, new QTableWidgetItem("C-terminal Modification")); + results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(5 + dbsearchspecificcolumncount)->setText("N-terminal Modification"); + results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(6 + dbsearchspecificcolumncount)->setText("Branch Modification"); + results->setHorizontalHeaderItem(7 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(7 + dbsearchspecificcolumncount)->setText("C-terminal Modification"); break; case cyclic: - results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount, new QTableWidgetItem("Matched Bricks")); + results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(5 + dbsearchspecificcolumncount)->setText("Matched Bricks"); break; case lasso: - results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount, new QTableWidgetItem("Branch Modification")); + results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(5 + dbsearchspecificcolumncount)->setText("Branch Modification"); break; case linearpolysaccharide: - results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount, new QTableWidgetItem("N-terminal Modification")); - results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount, new QTableWidgetItem("C-terminal Modification")); + results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(5 + dbsearchspecificcolumncount)->setText("N-terminal Modification"); + results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(6 + dbsearchspecificcolumncount)->setText("C-terminal Modification"); break; case other: default: break; } - results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount + resultsspecificcolumncount, new QTableWidgetItem("Matched Peaks")); - results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount + resultsspecificcolumncount, new QTableWidgetItem("Ratio of Matched Peaks [%]")); - results->setHorizontalHeaderItem(7 + dbsearchspecificcolumncount + resultsspecificcolumncount, new QTableWidgetItem("Sum of Relative Intensities")); + results->setHorizontalHeaderItem(5 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(5 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setText("Matched Peaks"); + + results->setHorizontalHeaderItem(6 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(6 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setText("Ratio of Matched Peaks [%]"); + + results->setHorizontalHeaderItem(7 + dbsearchspecificcolumncount + resultsspecificcolumncount, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(7 + dbsearchspecificcolumncount + resultsspecificcolumncount)->setText("Sum of Relative Intensities"); for (int i = 0; i < (int)parameters.fragmentionsfortheoreticalspectra.size(); i++) { - results->setHorizontalHeaderItem(resultsbasecolumncount + dbsearchspecificcolumncount + resultsspecificcolumncount + i, new QTableWidgetItem(parameters.fragmentdefinitions[(fragmentIonType)parameters.fragmentionsfortheoreticalspectra[i]].name.c_str())); + results->setHorizontalHeaderItem(resultsbasecolumncount + dbsearchspecificcolumncount + resultsspecificcolumncount + i, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(resultsbasecolumncount + dbsearchspecificcolumncount + resultsspecificcolumncount + i)->setText(parameters.fragmentdefinitions[(fragmentIonType)parameters.fragmentionsfortheoreticalspectra[i]].name.c_str()); } if ((parameters.peptidetype == cyclic) && parameters.enablescrambling) { - results->setHorizontalHeaderItem(results->columnCount() - 1, new QTableWidgetItem("Scrambled Peaks")); + results->setHorizontalHeaderItem(results->columnCount() - 1, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(results->columnCount() - 1)->setText("Scrambled Peaks"); } } @@ -456,11 +603,16 @@ void cMainWindow::prepareColumns() { if (parameters.mode == dereplication) { results->setColumnCount(5); - results->setHorizontalHeaderItem(0, new QTableWidgetItem("*")); - results->setHorizontalHeaderItem(1, new QTableWidgetItem("Result ID")); - results->setHorizontalHeaderItem(2, new QTableWidgetItem("Matched Peaks")); - results->setHorizontalHeaderItem(3, new QTableWidgetItem("Ratio of Matched Peaks [%]")); - results->setHorizontalHeaderItem(4, new QTableWidgetItem("Sum of Relative Intensities")); + results->setHorizontalHeaderItem(0, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(0)->setText("*"); + results->setHorizontalHeaderItem(1, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(1)->setText("Result ID"); + results->setHorizontalHeaderItem(2, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(2)->setText("Matched Peaks"); + results->setHorizontalHeaderItem(3, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(3)->setText("Ratio of Matched Peaks [%]"); + results->setHorizontalHeaderItem(4, widgetitemallocator.getNewItem()); + results->horizontalHeaderItem(4)->setText("Sum of Relative Intensities"); } @@ -471,35 +623,43 @@ void cMainWindow::prepareColumns() { resultsheadersort[i] = -1; } -} + QProgressDialog progress("Preparing the report...", /*"Cancel"*/0, 0, theoreticalspectrumlist.size(), this); + cEventFilter filter; + progress.installEventFilter(&filter); + progress.setMinimumDuration(0); + progress.setWindowModality(Qt::WindowModal); + + spectradetails.clear(); + spectradetails.resize(theoreticalspectrumlist.size()); + for (int i = 0; i < theoreticalspectrumlist.size(); i++) { + reportSpectrum(i, theoreticalspectrumlist[i]); + progress.setValue(i); + //if (progress.wasCanceled()) { + // break; + //} + } -void cMainWindow::fitColumns() { for (int i = 0; i < results->columnCount(); i++) { results->resizeColumnToContents(i); } + + progress.setValue(theoreticalspectrumlist.size()); + } void cMainWindow::deleteResults() { - while (results->rowCount() > 0) { - for (int i = 0; i < results->columnCount(); i++) { - delete results->item(results->rowCount() - 1, i); - } - results->removeRow(results->rowCount() - 1); - } - - for (int i = 0; i < results->columnCount(); i++) { - delete results->horizontalHeaderItem(i); - } + widgetitemallocator.reset(); results->setColumnCount(0); + results->setRowCount(0); } void cMainWindow::resultsCellClicked(int row, int column) { - resultsDetails[results->item(row, 1)->data(Qt::DisplayRole).toInt() - 1].prepareToShow(parameters.peptidetype); - resultsDetails[results->item(row, 1)->data(Qt::DisplayRole).toInt() - 1].show(); - resultsDetails[results->item(row, 1)->data(Qt::DisplayRole).toInt() - 1].activateWindow(); + spectradetails[results->item(row, 1)->data(Qt::DisplayRole).toInt() - 1].prepareToShow(parameters.peptidetype); + spectradetails[results->item(row, 1)->data(Qt::DisplayRole).toInt() - 1].show(); + spectradetails[results->item(row, 1)->data(Qt::DisplayRole).toInt() - 1].activateWindow(); } @@ -526,18 +686,17 @@ void cMainWindow::headerItemDoubleClicked(int index) { } -void cMainWindow::safeExit() { - enableRunButtonAndSettings(true); - enableStopButton(false); - enableButtonsHandlingResults(true); -} - - void cMainWindow::exportToCsv() { QString filename = QFileDialog::getSaveFileName(this, tr("Export to CSV"), lastdirexporttocsv, tr("Files (*.csv)")); - lastdirexporttocsv = filename; - if (filename.toStdString().compare("") != 0) { + if (!filename.isEmpty()) { + lastdirexporttocsv = filename; + + QProgressDialog progress("Exporting the CSV file...", /*"Cancel"*/0, 0, results->rowCount(), this); + cEventFilter filter; + progress.installEventFilter(&filter); + progress.setMinimumDuration(0); + progress.setWindowModality(Qt::WindowModal); QFile file(filename); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { @@ -562,19 +721,34 @@ void cMainWindow::exportToCsv() { } } out << endl; + + progress.setValue(i); + //if (progress.wasCanceled()) { + // break; + //} } file.close(); + + progress.setValue(results->rowCount()); } + } void cMainWindow::exportToHTML() { + QString filename = QFileDialog::getSaveFileName(this, tr("Export to HTML"), lastdirexporttohtml, tr("HTML Files (*.htm *.html)")); - lastdirexporttohtml = filename; - if (filename.toStdString().compare("") != 0) { + if (!filename.isEmpty()) { + lastdirexporttohtml = filename; + QProgressDialog progress("Exporting the HTML report...", /*"Cancel"*/0, 0, results->rowCount(), this); + cEventFilter filter; + progress.installEventFilter(&filter); + progress.setMinimumDuration(0); + progress.setWindowModality(Qt::WindowModal); + QFile file(filename); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { return; @@ -637,10 +811,15 @@ void cMainWindow::exportToHTML() { out << results->columnCount(); out << "\">\n"; - out << "

" << resultsDetails[i].getTheoreticalSpectrum().getCoverageBySeries().c_str(); - out << "
" << resultsDetails[i].getDetailsAsHTMLString().c_str() << "

\n"; + out << "

" << spectradetails[i].getTheoreticalSpectrum().getCoverageBySeries().c_str(); + out << "
" << spectradetails[i].getDetailsAsHTMLString().c_str() << "

\n"; out << "\n"; + + progress.setValue(i); + //if (progress.wasCanceled()) { + // break; + //} } out << "

\n"; @@ -663,28 +842,49 @@ void cMainWindow::exportToHTML() { file.close(); + progress.setValue(results->rowCount()); + } } void cMainWindow::showHTMLDocumentation() { - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/userguide.html").absoluteFilePath())); + #if OS_TYPE == WIN + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/html/userguide.html").absoluteFilePath())); + #else + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(linuxinstalldir + "docs/html/userguide.html").absoluteFilePath())); + #endif } void cMainWindow::showPDFManual() { - QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/refman.pdf").absoluteFilePath())); + #if OS_TYPE == WIN + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo("docs/refman.pdf").absoluteFilePath())); + #else + QDesktopServices::openUrl(QUrl::fromLocalFile(QFileInfo(linuxinstalldir + "docs/refman.pdf").absoluteFilePath())); + #endif } void cMainWindow::saveResultsFile() { + + #if OS_TYPE == WIN + string filetypes = appname.toStdString() + " " + appversion.toStdString() + " Results Files (*.res)"; + #else + string filetypes = "Results Files (*.res)"; + #endif - string filetypes = appname.toStdString() + " " + appversion.toStdString() + " Results Files (*.res)"; QString filename = QFileDialog::getSaveFileName(this, tr("Save Results..."), lastdirsaveresults, tr(filetypes.c_str())); - lastdirsaveresults = filename; - if (filename.toStdString().compare("") != 0) { + if (!filename.isEmpty()) { + lastdirsaveresults = filename; + + QProgressDialog progress("Saving the report...", /*"Cancel"*/0, 0, theoreticalspectrumlist.size(), this); + cEventFilter filter; + progress.installEventFilter(&filter); + progress.setMinimumDuration(0); + progress.setWindowModality(Qt::WindowModal); ofstream outfile; outfile.open(filename.toStdString().c_str(), ios::out | ios::binary | ios::trunc); @@ -710,28 +910,39 @@ void cMainWindow::saveResultsFile() { parameters.store(outfile); // store theoretical spectra - size = (int)resultsDetails.size(); + size = theoreticalspectrumlist.size(); outfile.write((char *)&size, sizeof(int)); - for (int i = 0; i < (int)resultsDetails.size(); i++) { - resultsDetails[i].getTheoreticalSpectrum().store(outfile); + for (int i = 0; i < theoreticalspectrumlist.size(); i++) { + theoreticalspectrumlist[i].store(outfile); + progress.setValue(i); + //if (progress.wasCanceled()) { + // break; + //} } // close file outfile.close(); } + progress.setValue(theoreticalspectrumlist.size()); + } } void cMainWindow::openResultsFile() { - - string filetypes = appname.toStdString() + " " + appversion.toStdString() + " Results Files (*.res)"; + + #if OS_TYPE == WIN + string filetypes = appname.toStdString() + " " + appversion.toStdString() + " Results Files (*.res)"; + #else + string filetypes = "Results Files (*.res)"; + #endif + QString filename = QFileDialog::getOpenFileName(this, tr("Open Results..."), lastdiropenresults, tr(filetypes.c_str())); - lastdiropenresults = filename; - if (filename.toStdString().compare("") != 0) { + if (!filename.isEmpty()) { + lastdiropenresults = filename; ifstream infile; infile.open(filename.toStdString().c_str(), ios::in | ios::binary); @@ -759,7 +970,9 @@ void cMainWindow::openResultsFile() { } deleteResults(); - resultsDetails.clear(); + + theoreticalspectrumlist.clear(); + spectradetails.clear(); // load graph window graph->load(infile); @@ -777,13 +990,26 @@ void cMainWindow::openResultsFile() { parameterswidget->setAndRestoreParameters(parameters); // load theoretical spectra - prepareColumns(); infile.read((char *)&size, sizeof(int)); + + QProgressDialog progress("Loading the report...", /*"Cancel"*/0, 0, size, this); + cEventFilter filter; + progress.installEventFilter(&filter); + progress.setMinimumDuration(0); + progress.setWindowModality(Qt::WindowModal); + for (int i = 0; i < size; i++) { theoreticalspectrum.load(infile); - sendTheoreticalSpectrum(theoreticalspectrum); + theoreticalspectrumlist.add(theoreticalspectrum); + progress.setValue(i); + //if (progress.wasCanceled()) { + // break; + //} } - fitColumns(); + + progress.setValue(size); + + reportSpectra(); // close file infile.close(); @@ -794,6 +1020,34 @@ void cMainWindow::openResultsFile() { } +void cMainWindow::setSequence(int peptidetypeindex, QString sequence) { + showProperties(); + parameterswidget->setSequence(peptidetypeindex, sequence); +} + + +void cMainWindow::setTag(int peptidetypeindex, QString tag) { + showProperties(); + parameterswidget->setTag(peptidetypeindex, tag); +} + + +void cMainWindow::insertSequence(int peptidetypeindex, QString sequence) { + showSequenceDatabase(); + sequencedatabasewidget->insertRow(peptidetypeindex, sequence); +} + + +void cMainWindow::quitApplication() { + emit stopComputation(); + quitapp = true; + + if (actionRun->isEnabled()) { + qApp->quit(); + } +} + + /* void cMainWindow::showContextMenu(const QPoint &pt) { QMenu *menu = logWindow->createStandardContextMenu(); @@ -824,6 +1078,8 @@ cMainWindow::~cMainWindow() { delete actionRun; delete actionBricksDatabase; delete actionSequenceDatabase; + delete actionModifications; + delete actionDrawPeptide; delete actionGraph; delete actionLog; delete actionHTMLDocumentation; @@ -838,6 +1094,8 @@ cMainWindow::~cMainWindow() { delete graph; delete bricksdatabasewidget; delete sequencedatabasewidget; + delete modificationswidget; + delete drawpeptidewidget; delete parameterswidget; } diff --git a/CycloBranch/gui/cMainWindow.h b/CycloBranch/gui/cMainWindow.h index 6a780ee..d95dcd3 100644 --- a/CycloBranch/gui/cMainWindow.h +++ b/CycloBranch/gui/cMainWindow.h @@ -11,6 +11,7 @@ #include #include #include +#include "core/utilities.h" #include "core/cTheoreticalSpectrum.h" #include "gui/cAboutWidget.h" #include "gui/cGraphWidget.h" @@ -18,7 +19,11 @@ #include "gui/cSpectrumDetailWidget.h" #include "gui/cBricksDatabaseWidget.h" #include "gui/cSequenceDatabaseWidget.h" +#include "gui/cModificationsWidget.h" +#include "gui/cDrawPeptideWidget.h" #include "gui/cMainThread.h" +#include "core/cAllocator.h" + // forward declaration class QTextEdit; @@ -60,6 +65,13 @@ class cMainWindow : public QMainWindow QMenu* menuView; QMenu* menuHelp; + // toolbars + QToolBar* toolbarFile; + QToolBar* toolbarSearch; + QToolBar* toolbarTools; + QToolBar* toolbarView; + QToolBar* toolbarHelp; + // subitems in the menu QAction* actionOpenResults; QAction* actionSaveResults; @@ -71,6 +83,8 @@ class cMainWindow : public QMainWindow QAction* actionProperties; QAction* actionBricksDatabase; QAction* actionSequenceDatabase; + QAction* actionModifications; + QAction *actionDrawPeptide; QAction* actionGraph; QAction* actionLog; QAction* actionHTMLDocumentation; @@ -78,8 +92,9 @@ class cMainWindow : public QMainWindow QAction* actionAbout; QTableWidget* results; + cTheoreticalSpectrumList theoreticalspectrumlist; + vector spectradetails; - vector resultsDetails; cParameters parameters; QTextEdit* logWindow; @@ -89,6 +104,8 @@ class cMainWindow : public QMainWindow cGraphWidget* graph; cBricksDatabaseWidget* bricksdatabasewidget; cSequenceDatabaseWidget* sequencedatabasewidget; + cModificationsWidget* modificationswidget; + cDrawPeptideWidget* drawpeptidewidget; cParametersWidget* parameterswidget; int resultsbasecolumncount; @@ -102,9 +119,17 @@ class cMainWindow : public QMainWindow QString lastdirsaveresults; QString lastdiropenresults; + cAllocator widgetitemallocator; + + bool quitapp; + void closeEvent(QCloseEvent *event); + void reportSpectrum(int id, cTheoreticalSpectrum& theoreticalspectrum); + + void deleteResults(); + private slots: void showHideLog(); @@ -115,6 +140,12 @@ private slots: void showSequenceDatabase(); + void showModifications(); + + void showDrawPeptideWidget(); + + void setAndShowDrawPeptideWidget(int peptidetypeindex, QString sequence); + void showGraph(); void showProperties(); @@ -131,15 +162,9 @@ private slots: void enableButtonsHandlingResults(bool enable); - void sendTheoreticalSpectrum(cTheoreticalSpectrum theoreticalspectrum); - void sendParameters(cParameters parameters); - void prepareColumns(); - - void fitColumns(); - - void deleteResults(); + void reportSpectra(); void resultsCellClicked(int row, int column); @@ -147,8 +172,6 @@ private slots: void headerItemDoubleClicked(int); - void safeExit(); - void exportToCsv(); void exportToHTML(); @@ -161,6 +184,14 @@ private slots: void openResultsFile(); + void setSequence(int peptidetypeindex, QString sequence); + + void setTag(int peptidetypeindex, QString tag); + + void insertSequence(int peptidetypeindex, QString tag); + + void quitApplication(); + //void showContextMenu(const QPoint &pt); signals: diff --git a/CycloBranch/gui/cModificationsWidget.cpp b/CycloBranch/gui/cModificationsWidget.cpp new file mode 100644 index 0000000..cc175be --- /dev/null +++ b/CycloBranch/gui/cModificationsWidget.cpp @@ -0,0 +1,434 @@ +#include "gui/cModificationsWidget.h" +#include "gui/cEventFilter.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +cModificationsWidget::cModificationsWidget(QWidget* parent) { + this->parent = parent; + + setWindowTitle("Modifications Editor"); + setWindowIcon(QIcon(":/images/icons/61.png")); + + insertrow = new QPushButton(tr("Add Row")); + insertrow->setToolTip("Add a new row."); + removechecked = new QPushButton(tr(" Remove Rows ")); + removechecked->setToolTip("Remove selected rows."); + + close = new QPushButton(tr("Close")); + close->setToolTip("Close the window."); + load = new QPushButton(tr("Load")); + load->setToolTip("Load modifications."); + save = new QPushButton(QString("Save")); + save->setToolTip("Save modifications in the current file. When a file has not been loaded yet, the \"Save As ...\" file dialog is opened."); + saveas = new QPushButton(tr("Save As...")); + saveas->setToolTip("Save modifications into a file."); + + buttons = new QHBoxLayout(); + buttons->addWidget(close); + buttons->addStretch(1); + buttons->addWidget(insertrow); + buttons->addWidget(removechecked); + buttons->addStretch(10); + buttons->addWidget(load); + buttons->addWidget(save); + buttons->addWidget(saveas); + + database = new QTableWidget(0, 0, this); + database->setColumnCount(6); + database->setHorizontalHeaderItem(0, new QTableWidgetItem("")); + database->setHorizontalHeaderItem(1, new QTableWidgetItem("Name")); + database->setHorizontalHeaderItem(2, new QTableWidgetItem("Summary Formula")); + database->setHorizontalHeaderItem(3, new QTableWidgetItem("Monoisotopic Mass")); + database->setHorizontalHeaderItem(4, new QTableWidgetItem("N-terminal")); + database->setHorizontalHeaderItem(5, new QTableWidgetItem("C-terminal")); + database->horizontalHeader()->setStretchLastSection(true); + for (int i = 0; i < database->columnCount(); i++) { + database->resizeColumnToContents(i); + } + + headersort.resize(database->columnCount()); + for (int i = 0; i < database->columnCount(); i++) { + headersort[i] = -1; + } + + mainlayout = new QVBoxLayout(); + mainlayout->addWidget(database); + mainlayout->addLayout(buttons); + + connect(database->horizontalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(headerItemDoubleClicked(int))); + connect(database, SIGNAL(itemChanged(QTableWidgetItem *)), this, SLOT(itemChanged(QTableWidgetItem *))); + connect(insertrow, SIGNAL(released()), this, SLOT(addRow())); + connect(removechecked, SIGNAL(released()), this, SLOT(removeEmptyRows())); + connect(close, SIGNAL(released()), this, SLOT(closeWindow())); + connect(load, SIGNAL(released()), this, SLOT(loadDatabase())); + connect(save, SIGNAL(released()), this, SLOT(saveDatabase())); + connect(saveas, SIGNAL(released()), this, SLOT(saveDatabaseAs())); + + setLayout(mainlayout); + + resize(1280, 700); + + databasefile = ""; + + #if OS_TYPE == WIN + lastdir = "./Modifications/"; + #else + lastdir = linuxinstalldir + "Modifications/"; + #endif + + modifications.clear(); +} + + +cModificationsWidget::~cModificationsWidget() { + deleteTable(false); + + for (int i = 0; i < database->columnCount(); i++) { + delete database->horizontalHeaderItem(i); + } + + database->setColumnCount(0); + + delete insertrow; + delete removechecked; + delete close; + delete load; + delete save; + delete saveas; + delete database; + delete buttons; + delete mainlayout; +} + + +void cModificationsWidget::closeEvent(QCloseEvent *event) { + closeWindow(); +} + + +void cModificationsWidget::deleteTable(bool enableprogress) { + QProgressDialog* progress; + cEventFilter filter; + int rowcount = database->rowCount(); + + if (enableprogress) { + progress = new QProgressDialog("Clearing the table...", /*"Cancel"*/0, 0, rowcount, this); + progress->installEventFilter(&filter); + progress->setMinimumDuration(0); + progress->setWindowModality(Qt::WindowModal); + progress->setValue(0); + } + + widgetitemallocator.reset(); + + for (int i = 0; i < rowcount; i++) { + delete database->cellWidget(rowcount - i - 1, 4); + delete database->cellWidget(rowcount - i - 1, 5); + + if (enableprogress) { + progress->setValue(i); + //if (progress->wasCanceled()) { + // break; + //} + } + } + + database->setRowCount(0); + + if (enableprogress) { + progress->setValue(rowcount); + delete progress; + } +} + + +void cModificationsWidget::removeRow(int row) { + for (int i = 0; i < database->columnCount(); i++) { + if ((i == 4) || (i == 5)) { + delete database->cellWidget(row, i); + } + else { + database->takeItem(row, i); + } + } + database->removeRow(row); +} + + +bool cModificationsWidget::checkTable() { + // check summary formulas + for (int i = 0; i < database->rowCount(); i++) { + if (!checkFormula(i, database->item(i, 2)->text().toStdString())) { + return false; + } + } + + return true; +} + + +bool cModificationsWidget::checkFormula(int row, const string& summary) { + cSummaryFormula formula; + string errmsg; + formula.setFormula(summary); + if (!formula.isValid(errmsg)) { + QMessageBox msgBox; + QString errstr = "Syntax error in the row no. "; + errstr += to_string(row + 1).c_str(); + errstr += ": "; + errstr += errmsg.c_str(); + msgBox.setText(errstr); + msgBox.exec(); + return false; + } + if (database->item(row, 3)) { + database->item(row, 3)->setData(Qt::DisplayRole, formula.getMass()); + } + return true; +} + + +void cModificationsWidget::keyPressEvent(QKeyEvent *event) { + if(event->key() == Qt::Key_Escape) { + hide(); + } +} + + +void cModificationsWidget::closeWindow() { + hide(); +} + + +void cModificationsWidget::loadDatabase() { + QString filename = QFileDialog::getOpenFileName(this, tr("Load Modifications"), lastdir, tr("Modifications (*.txt)")); + + if (!filename.isEmpty()) { + lastdir = filename; + string errormessage; + + databasefile = filename; + save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); + + inputstream.open(filename.toStdString().c_str()); + + if (!inputstream.good()) { + QMessageBox msgBox; + msgBox.setText("Cannot open the file '" + databasefile + "'."); + msgBox.exec(); + } + else { + + modifications.clear(); + loadModificationsFromPlainTextStream(inputstream, modifications, errormessage, true); + + deleteTable(true); + + QProgressDialog progress("Loading Modifications...", /*"Cancel"*/0, 0, (int)modifications.size(), this); + cEventFilter filter; + progress.installEventFilter(&filter); + progress.setMinimumDuration(0); + progress.setWindowModality(Qt::WindowModal); + + database->setRowCount((int)modifications.size()); + for (int i = 0; i < (int)modifications.size(); i++) { + QCheckBox* checkbox = new QCheckBox(); + database->setCellWidget(i, 0, checkbox); + + database->setItem(i, 1, widgetitemallocator.getNewItem()); + database->item(i, 1)->setText(modifications[i].name.c_str()); + + database->setItem(i, 2, widgetitemallocator.getNewItem()); + database->item(i, 2)->setText(modifications[i].summary.c_str()); + + database->setItem(i, 3, widgetitemallocator.getNewItem()); + database->item(i, 3)->setData(Qt::DisplayRole, modifications[i].massdifference); + + checkbox = new QCheckBox(); + if (modifications[i].nterminal) { + checkbox->setChecked(true); + } + database->setCellWidget(i, 4, checkbox); + + checkbox = new QCheckBox(); + if (modifications[i].cterminal) { + checkbox->setChecked(true); + } + database->setCellWidget(i, 5, checkbox); + + progress.setValue(i); + //if (progress.wasCanceled()) { + // break; + //} + } + + for (int i = 0; i < database->columnCount(); i++) { + database->resizeColumnToContents(i); + } + + progress.setValue((int)modifications.size()); + + } + + inputstream.close(); + + } +} + + +void cModificationsWidget::saveDatabase() { + + if (!checkTable()) { + return; + } + + if (databasefile.compare("") == 0) { + saveDatabaseAs(); + return; + } + + outputstream.open(databasefile.toStdString().c_str()); + if (!outputstream.good()) { + QMessageBox msgBox; + msgBox.setText("Cannot open the file '" + databasefile + "'."); + msgBox.exec(); + } + else { + + QProgressDialog progress("Saving Modifications...", /*"Cancel"*/0, 0, database->rowCount(), this); + cEventFilter filter; + progress.installEventFilter(&filter); + progress.setMinimumDuration(0); + progress.setWindowModality(Qt::WindowModal); + + fragmentDescription modification; + modifications.clear(); + + removeEmptyRows(); + + for (int i = 0; i < database->rowCount(); i++) { + modification.clear(); + for (int j = 0; j < database->columnCount(); j++) { + switch (j) + { + case 0: + // nothing to do + break; + case 1: + modification.name = database->item(i,j)->text().toStdString(); + break; + case 2: + modification.summary = database->item(i,j)->text().toStdString(); + break; + case 3: + modification.massdifference = database->item(i,j)->data(Qt::DisplayRole).toDouble(); + break; + case 4: + modification.nterminal = ((QCheckBox *)database->cellWidget(i, j))->isChecked(); + break; + case 5: + modification.cterminal = ((QCheckBox *)database->cellWidget(i, j))->isChecked(); + break; + default: + break; + } + } + modifications.push_back(modification); + + progress.setValue(i); + //if (progress.wasCanceled()) { + // break; + //} + } + + storeModificationsToPlainTextStream(outputstream, modifications); + + progress.setValue(progress.maximum()); + + } + outputstream.close(); +} + + +void cModificationsWidget::saveDatabaseAs() { + + if (!checkTable()) { + return; + } + + QString filename = QFileDialog::getSaveFileName(this, tr("Save Modifications As..."), lastdir, tr("Modifications (*.txt)")); + + if (!filename.isEmpty()) { + lastdir = filename; + + databasefile = filename; + save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); + saveDatabase(); + } +} + + +void cModificationsWidget::addRow() { + int row = database->rowCount(); + database->insertRow(row); + + database->setCellWidget(row, 0, new QCheckBox()); + database->setItem(row, 1, widgetitemallocator.getNewItem()); + database->setItem(row, 2, widgetitemallocator.getNewItem()); + database->setItem(row, 3, widgetitemallocator.getNewItem()); + database->setCellWidget(row, 4, new QCheckBox()); + database->setCellWidget(row, 5, new QCheckBox()); +} + + +void cModificationsWidget::removeEmptyRows() { + int i = 0; + while (i < database->rowCount()) { + if (((QCheckBox *)(database->cellWidget(i, 0)))->isChecked()) { + removeRow(i); + } + else { + i++; + } + } +} + + +void cModificationsWidget::itemChanged(QTableWidgetItem* item) { + // recalculate mass when formula is changed + if (item->column() == 2) { + checkFormula(item->row(), item->text().toStdString()); + } +} + + +void cModificationsWidget::headerItemDoubleClicked(int index) { + if (headersort[index] == -1) { + database->sortByColumn(index, Qt::AscendingOrder); + headersort[index] = 1; + return; + } + + if (headersort[index] == 0) { + database->sortByColumn(index, Qt::AscendingOrder); + headersort[index] = 1; + } + else { + database->sortByColumn(index, Qt::DescendingOrder); + headersort[index] = 0; + } +} + diff --git a/CycloBranch/gui/cModificationsWidget.h b/CycloBranch/gui/cModificationsWidget.h new file mode 100644 index 0000000..3deb65f --- /dev/null +++ b/CycloBranch/gui/cModificationsWidget.h @@ -0,0 +1,119 @@ +/** + \file cModificationsWidget.h + \brief Editor of N-terminal and C-terminal modifications. +*/ + + +#ifndef _CMODIFICATIONSWIDGET_H +#define _CMODIFICATIONSWIDGET_H + +#include +#include +#include "core/utilities.h" +#include "core/cFragmentIons.h" +#include "core/cSummaryFormula.h" +#include "core/cAllocator.h" + +using namespace std; + + +// forward declaration +class QHBoxLayout; +class QVBoxLayout; +class QTableWidget; +class QTableWidgetItem; +class QPushButton; + + +/** + \brief Editor of N-terminal and C-terminal modifications. +*/ +class cModificationsWidget : public QWidget +{ + Q_OBJECT + +public: + + + /** + \brief The constructor. + \param parent pointer to a parent widget + */ + cModificationsWidget(QWidget* parent = (QWidget *)0); + + + /** + \brief The destructor. + */ + ~cModificationsWidget(); + + + /** + \brief Handle the window close event. + \param event pointer to QCloseEvent + */ + void closeEvent(QCloseEvent *event); + + +private: + QWidget* parent; + QPushButton* insertrow; + QPushButton* removechecked; + QPushButton* close; + QPushButton* load; + QPushButton* save; + QPushButton* saveas; + QTableWidget* database; + QHBoxLayout* buttons; + QVBoxLayout* mainlayout; + + QString databasefile; + QString lastdir; + ifstream inputstream; + ofstream outputstream; + vector modifications; + + vector headersort; + + cAllocator widgetitemallocator; + + void deleteTable(bool enableprogress); + + void removeRow(int row); + + bool checkTable(); + + bool checkFormula(int row, const string& summary); + + +protected: + + + /** + \brief Handle a key press event. + \param event pointer to QKeyEvent + */ + void keyPressEvent(QKeyEvent *event); + + +private slots: + + void closeWindow(); + + void loadDatabase(); + + void saveDatabase(); + + void saveDatabaseAs(); + + void addRow(); + + void removeEmptyRows(); + + void itemChanged(QTableWidgetItem* item); + + void headerItemDoubleClicked(int index); + +}; + +#endif diff --git a/CycloBranch/gui/cParametersWidget.cpp b/CycloBranch/gui/cParametersWidget.cpp index 6848117..bd2a3f3 100644 --- a/CycloBranch/gui/cParametersWidget.cpp +++ b/CycloBranch/gui/cParametersWidget.cpp @@ -17,16 +17,18 @@ #include #include #include +#include +#include -cParametersWidget::cParametersWidget() { +cParametersWidget::cParametersWidget(QWidget* parent) { + this->parent = parent; + setWindowTitle("Settings..."); + setWindowIcon(QIcon(":/images/icons/73.png")); settingsfile = ""; oldsettingsfile = ""; - peaklistfilename = ""; - brickdatabasefilename = ""; - sequencedatabasefilename = ""; stdbuttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel); stdbuttons->button(QDialogButtonBox::Ok)->setToolTip("Accept changes and hide window."); @@ -54,15 +56,20 @@ cParametersWidget::cParametersWidget() { peptidetype->addItem(tr("Linear")); peptidetype->addItem(tr("Cyclic")); peptidetype->addItem(tr("Branched")); - peptidetype->addItem(tr("Lasso")); + peptidetype->addItem(tr("Branch-cyclic")); peptidetype->addItem(tr("Linear polysaccharide (beta version)")); //peptidetype->addItem(tr("Other")); peaklistformlayout->addRow(tr("Peptide Type: "), peptidetype); peaklistline = new QLineEdit(); - peaklistline->setToolTip("Select the peaklist. Following formats are supported: txt, mgf, mzML, mzXML, baf."); peaklistbutton = new QPushButton("Select"); - peaklistbutton->setToolTip("Select the peaklist. Following formats are supported: txt, mgf, mzML, mzXML, baf."); + #if OS_TYPE == UNX + peaklistline->setToolTip("Select the peaklist. Following formats are supported: txt, mgf, mzML, mzXML."); + peaklistbutton->setToolTip("Select the peaklist. Following formats are supported: txt, mgf, mzML, mzXML."); + #else + peaklistline->setToolTip("Select the peaklist. Following formats are supported: txt, mgf, mzML, mzXML, baf."); + peaklistbutton->setToolTip("Select the peaklist. Following formats are supported: txt, mgf, mzML, mzXML, baf."); + #endif peaklistlayout = new QHBoxLayout(); peaklistlayout->addWidget(peaklistline); peaklistlayout->addWidget(peaklistbutton); @@ -75,11 +82,15 @@ cParametersWidget::cParametersWidget() { precursormass->setSingleStep(1); peaklistformlayout->addRow(tr("Precursor m/z Ratio: "), precursormass); + precursoradduct = new QLineEdit(); + precursoradduct->setToolTip("Enter the formula of a precursor ion adduct (e.g., Na, K, Li). H is used by default when empty."); + peaklistformlayout->addRow(tr("Precursor Ion Adduct: "), precursoradduct); + precursorcharge = new QSpinBox(); - precursorcharge->setToolTip("Enter the precursor charge (a precursor charge in the peaklist file is ignored)."); - precursorcharge->setRange(1, 100); + precursorcharge->setToolTip("Enter the precursor charge (a precursor charge in the peaklist file is ignored). Negative values are allowed.\nWhen mode is set up to \"Compare Peaklist with Database - MS data\", the value determines the maximum charge of generated peaks."); + precursorcharge->setRange(-100, 100); precursorcharge->setSingleStep(1); - peaklistformlayout->addRow(tr("Precursor Charge: "), precursorcharge); + peaklistformlayout->addRow(tr("Charge: "), precursorcharge); precursormasserrortolerance = new QDoubleSpinBox(); precursormasserrortolerance->setToolTip("Enter the precursor m/z error tolerance in ppm."); @@ -163,54 +174,63 @@ cParametersWidget::cParametersWidget() { generatebrickspermutations->setToolTip("Permutations of combined blocks are generated when checked (e.g., when an edge corresponds to a combination of blocks leucine, proline and valine, the order of blocks can be LPV, LVP, PVL, PLV, VLP or VPL).\nIt is recommended to enable this option by default."); brickdatabaseformlayout->addRow(tr("Generate Permutations of Combined Blocks: "), generatebrickspermutations); + modificationsline = new QLineEdit(); + modificationsline->setToolTip("Select the txt file containing a list of modifications."); + modificationsbutton = new QPushButton("Select"); + modificationsbutton->setToolTip("Select the txt file containing a list of modifications."); + modificationslayout = new QHBoxLayout(); + modificationslayout->addWidget(modificationsline); + modificationslayout->addWidget(modificationsbutton); + brickdatabaseformlayout->addRow(tr("N-/C-terminal Modifications File: "), modificationslayout); + brickdatabasegroupbox = new QGroupBox("Database of Building Blocks"); brickdatabasegroupbox->setLayout(brickdatabaseformlayout); - modificationslayout = new QVBoxLayout(); - - modificationstable = new QTableWidget(); - modificationstable->setColumnCount(4); - modificationstable->setHorizontalHeaderItem(0, new QTableWidgetItem("Name")); - modificationstable->horizontalHeaderItem(0)->setToolTip("A name of a modification."); - modificationstable->setHorizontalHeaderItem(1, new QTableWidgetItem("Summary")); - modificationstable->horizontalHeaderItem(1)->setToolTip("A residue summary formula of a modification (e.g., H2C2O for acetylation or HNO-1 for amidation). Negative numbers of atoms are supported (e.g., H-2O3N-5 means remove two hydrogens, add three oxygens and remove five nitrogens)."); - modificationstable->setHorizontalHeaderItem(2, new QTableWidgetItem("N-terminal")); - modificationstable->horizontalHeaderItem(2)->setToolTip("When checked, the modification is considered to be N-terminal."); - modificationstable->setHorizontalHeaderItem(3, new QTableWidgetItem("C-terminal")); - modificationstable->horizontalHeaderItem(3)->setToolTip("When checked, the modification is considered to be C-terminal."); - modificationstable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - //modificationstable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Interactive); - - modificationsbuttoninsert = new QPushButton("Insert Modification"); - modificationsbuttoninsert->setToolTip("Insert a new row for a modification."); - modificationsbuttoninsert->setMinimumWidth(120); - modificationsbuttoninsert->setMaximumWidth(120); - modificationsbuttonremove = new QPushButton("Remove Empty Rows"); - modificationsbuttonremove->setToolTip("Remove rows having empty column \"Name\"."); - modificationsbuttonremove->setMinimumWidth(120); - modificationsbuttonremove->setMaximumWidth(120); - modificationsbuttonslayout = new QHBoxLayout(); - modificationsbuttonslayout->addWidget(modificationsbuttoninsert); - modificationsbuttonslayout->addWidget(modificationsbuttonremove); - modificationsbuttonslayout->addStretch(1); - modificationslayout->addWidget(modificationstable); - modificationslayout->addLayout(modificationsbuttonslayout); - - modificationsgroupbox = new QGroupBox("N-terminal and C-terminal Modifications"); - modificationsgroupbox->setLayout(modificationslayout); + miscformlayout = new QFormLayout(); + + blindedges = new QComboBox(); + blindedges->setToolTip("An operation which is performed with edges in the de novo graph forming exclusively blind paths:\nnone (edges are kept - useful when you would like to see the whole de novo graph in 'View -> Graph');\nremove (edges are removed - speeds up the search);\nconnect (edges are connected - useful when you are looking for sequence tags)."); + blindedges->addItem(tr("none (you can see a complete de novo graph)")); + blindedges->addItem(tr("remove (speed up the search)")); + blindedges->addItem(tr("connect (allow detection of sequence tags)")); + miscformlayout->addRow(tr("Action with Blind Paths in De Novo Graph: "), blindedges); + + cyclicnterminus = new QCheckBox(); + cyclicnterminus->setToolTip("N-terminal cyclization of a linear peptide is assumed when checked. H2O is subtracted from all theoretical N-terminal fragment ions and the theoretical precursor mass."); + miscformlayout->addRow(tr("Cyclic N-terminus: "), cyclicnterminus); + + cycliccterminus = new QCheckBox(); + cycliccterminus->setToolTip("C-terminal cyclization of a linear peptide is assumed when checked. H2O is subtracted from all theoretical C-terminal fragment ions and the theoretical precursor mass."); + miscformlayout->addRow(tr("Cyclic C-terminus: "), cycliccterminus); + + enablescrambling = new QCheckBox(); + enablescrambling->setToolTip("When checked, scrambled fragment ions of cyclic peptides are generated in theoretical spectra."); + miscformlayout->addRow(tr("Enable Scrambling: "), enablescrambling); + + miscgroupbox = new QGroupBox("Miscellaneous"); + miscgroupbox->setLayout(miscformlayout); applicationformlayout = new QFormLayout(); mode = new QComboBox(); - mode->setToolTip("De Novo Search Engine (identification mode) - the default mode of the application.\nCompare Peaklist with Spectrum of Searched Sequence (annotation mode) - a theoretical spectrum is generated for an input \"Searched Peptide Sequence\" and it is compared with the peaklist.\nCompare Peaklist with Database - MS/MS data (identification mode) - the peaklist is compared with theoretical spectra generated from a database of sequences.\nCompare Peaklist with Database - MS data (identification mode) - the peaklist is compared with theoretical peaks generated from a database of sequences."); + mode->setToolTip("De Novo Search Engine (identification mode) - the default mode of the application.\nCompare Peaklist with Spectrum of Searched Sequence (annotation mode) - a theoretical spectrum is generated for an input \"Searched Peptide Sequence\" and it is compared with the peaklist.\nCompare Peaklist with Database - MS/MS data (identification mode) - a peaklist is compared with theoretical spectra generated from a database of sequences.\nCompare Peaklist with Database - MS data (identification mode) - a peaklist is compared with theoretical peaks generated from a database of compounds/sequences."); mode->addItem(tr("De Novo Search Engine")); mode->addItem(tr("Compare Peaklist with Spectrum of Searched Sequence")); mode->addItem(tr("Compare Peaklist with Database - MS/MS data")); mode->addItem(tr("Compare Peaklist with Database - MS data")); applicationformlayout->addRow(tr("Mode: "), mode); + sequencedatabaseline = new QLineEdit(); + sequencedatabaseline->setToolTip("Select the txt file containing a database of sequences."); + sequencedatabasebutton = new QPushButton("Select"); + sequencedatabasebutton->setToolTip("Select the txt file containing a database of sequences."); + sequencedatabaselayout = new QHBoxLayout(); + sequencedatabaselayout->addWidget(sequencedatabaseline); + sequencedatabaselayout->addWidget(sequencedatabasebutton); + applicationformlayout->addRow(tr("Sequence Database File: "), sequencedatabaselayout); + maximumnumberofthreads = new QSpinBox(); maximumnumberofthreads->setToolTip("A maximum number of threads used when the peaklist is compared with theoretical spectra of peptide sequence candidates."); maximumnumberofthreads->setRange(1, 1024); @@ -237,7 +257,7 @@ cParametersWidget::cParametersWidget() { sequencetag = new QLineEdit(); sequencetag->setToolTip("Each peptide sequence candidate generated from a de novo graph must fulfil the peptide sequence tag. Otherwise, its theoretical spectrum is not generated and the peptide sequence candidate is excluded from the search.\nSee the syntax of tags in the documentation."); - sequencetag->setMaxLength(1024*1024); + sequencetag->setMaxLength(5000); applicationformlayout->addRow(tr("Peptide Sequence Tag: "), sequencetag); fragmentiontypes = new cFragmentIonsListWidget(this); @@ -248,67 +268,33 @@ cParametersWidget::cParametersWidget() { clearhitswithoutparent->setToolTip("When checked, a hit of a peak is not considered when corresponding parent peak is not hit (e.g., a hit of a dehydrated b-ion is not considered as a hit when corresponding b-ion has not been hit)."); applicationformlayout->addRow(tr("Remove Hits of Fragments without Hits of Parent Fragments: "), clearhitswithoutparent); - cyclicnterminus = new QCheckBox(); - cyclicnterminus->setToolTip("N-terminal cyclization of a linear peptide is assumed when checked. H2O is subtracted from all theoretical N-terminal fragment ions and the theoretical precursor mass."); - applicationformlayout->addRow(tr("Cyclic N-terminus: "), cyclicnterminus); - - cycliccterminus = new QCheckBox(); - cycliccterminus->setToolTip("C-terminal cyclization of a linear peptide is assumed when checked. H2O is subtracted from all theoretical C-terminal fragment ions and the theoretical precursor mass."); - applicationformlayout->addRow(tr("Cyclic C-terminus: "), cycliccterminus); - - enablescrambling = new QCheckBox(); - enablescrambling->setToolTip("When checked, scrambled fragment ions of cyclic peptides are generated in theoretical spectra."); - applicationformlayout->addRow(tr("Enable Scrambling: "), enablescrambling); - applicationgroupbox = new QGroupBox("Application"); applicationgroupbox->setLayout(applicationformlayout); - denovographformlayout = new QFormLayout(); - - blindedges = new QComboBox(); - blindedges->setToolTip("An operation with edges in the de novo graph forming exclusively blind paths:\nnone (edges are kept - useful when you would like to see the whole de novo graph in 'View -> Graph');\nremove (edges are removed - speeds up the search);\nconnect (edges are connected - useful when you are looking for sequence tags)."); - blindedges->addItem(tr("none (you can see a complete de novo graph)")); - blindedges->addItem(tr("remove (speed up the search)")); - blindedges->addItem(tr("connect (allow detection of sequence tags)")); - denovographformlayout->addRow(tr("Action with Edges Forming Blind Paths: "), blindedges); - - denovographgroupbox = new QGroupBox("De Novo Graph"); - denovographgroupbox->setLayout(denovographformlayout); - - - databasesearchformlayout = new QFormLayout(); - - sequencedatabaseline = new QLineEdit(); - sequencedatabaseline->setToolTip("Select the txt file containing a database of sequences."); - sequencedatabasebutton = new QPushButton("Select"); - sequencedatabasebutton->setToolTip("Select the txt file containing a database of sequences."); - sequencedatabaselayout = new QHBoxLayout(); - sequencedatabaselayout->addWidget(sequencedatabaseline); - sequencedatabaselayout->addWidget(sequencedatabasebutton); - databasesearchformlayout->addRow(tr("Sequence Database File: "), sequencedatabaselayout); - - databasesearchgroupbox = new QGroupBox("Database Search"); - databasesearchgroupbox->setLayout(databasesearchformlayout); - - searchedsequenceformlayout = new QFormLayout(); - searchedsequence = new QLineEdit(); - searchedsequence->setToolTip("A peptide sequence which you are searching for or a peptide sequence tag.\nA peptide sequence must be entered when \"Mode\" is set up to \"Compare Peaklist with Spectrum of Searched Sequence\".\nOtherwise, it is similar to the option \"Peptide Sequence Tag\" with a difference that a peptide sequence candidate is not removed from the search but it is just highlighted in an output report of peptide sequence candidates."); - searchedsequence->setMaxLength(1024*1024); - searchedsequenceformlayout->addRow(tr("Sequence: "), searchedsequence); + searchedsequenceline = new QLineEdit(); + searchedsequenceline->setToolTip("A peptide sequence which you are searching for or a peptide sequence tag.\nA peptide sequence must be entered when \"Mode\" is set up to \"Compare Peaklist with Spectrum of Searched Sequence\".\nOtherwise, it is similar to the option \"Peptide Sequence Tag\" with a difference that a peptide sequence candidate is not removed from the search but it is just highlighted in an output report of peptide sequence candidates."); + searchedsequenceline->setMaxLength(5000); + searchedsequencebutton = new QPushButton("Edit"); + searchedsequencebutton->setMinimumWidth(50); + searchedsequencebutton->setToolTip("Edit the sequence using the 'Draw Peptide' tool."); + searchedsequencelayout = new QHBoxLayout(); + searchedsequencelayout->addWidget(searchedsequenceline); + searchedsequencelayout->addWidget(searchedsequencebutton); + searchedsequenceformlayout->addRow(tr("Sequence: "), searchedsequencelayout); searchedsequenceNtermmodif = new QLineEdit(); - searchedsequenceNtermmodif->setToolTip("A name of an N-terminal modification as defined in the window \"N-terminal and C-terminal Modifications\" which belongs to the searched peptide."); + searchedsequenceNtermmodif->setToolTip("A name of an N-terminal modification which belongs to the searched peptide. The name must be defined in \"N-/C-terminal Modifications File\"."); searchedsequenceformlayout->addRow(tr("N-terminal Modification: "), searchedsequenceNtermmodif); searchedsequenceCtermmodif = new QLineEdit(); - searchedsequenceCtermmodif->setToolTip("A name of a C-terminal modification as defined in the window \"N-terminal and C-terminal Modifications\" which belongs to the searched peptide."); + searchedsequenceCtermmodif->setToolTip("A name of a C-terminal modification which belongs to the searched peptide. The name must be defined in \"N-/C-terminal Modifications File\"."); searchedsequenceformlayout->addRow(tr("C-terminal Modification: "), searchedsequenceCtermmodif); searchedsequenceTmodif = new QLineEdit(); - searchedsequenceTmodif->setToolTip("A name of an N-terminal or C-terminal modification as defined in the window \"N-terminal and C-terminal Modifications\" which belongs to a branch of a searched peptide (branched and lasso peptides only)."); + searchedsequenceTmodif->setToolTip("A name of an N-terminal or C-terminal modification which belongs to a branch of a searched peptide (branched and branch-cyclic peptides only). The name must be defined in \"N-/C-terminal Modifications File\"."); searchedsequenceformlayout->addRow(tr("Branch Modification: "), searchedsequenceTmodif); searchedsequencegroupbox = new QGroupBox("Searched Peptide Sequence"); @@ -318,14 +304,11 @@ cParametersWidget::cParametersWidget() { vlayout1 = new QVBoxLayout(); vlayout1->addWidget(peaklistgroupbox); vlayout1->addWidget(brickdatabasegroupbox); - vlayout1->addWidget(modificationsgroupbox); + vlayout1->addWidget(miscgroupbox); vlayout2 = new QVBoxLayout(); vlayout2->addWidget(applicationgroupbox); - vlayout2->addWidget(denovographgroupbox); - vlayout2->addWidget(databasesearchgroupbox); vlayout2->addWidget(searchedsequencegroupbox); - vlayout2->addStretch(1); hlayout = new QHBoxLayout(); @@ -350,12 +333,13 @@ cParametersWidget::cParametersWidget() { connect(stdbuttons, SIGNAL(rejected()), this, SLOT(restoreParameters())); connect(peaklistbutton, SIGNAL(released()), this, SLOT(peaklistButtonReleased())); connect(brickdatabasebutton, SIGNAL(released()), this, SLOT(brickDatabaseButtonReleased())); - connect(modificationsbuttoninsert, SIGNAL(released()), this, SLOT(modificationsInsertButtonReleased())); - connect(modificationsbuttonremove, SIGNAL(released()), this, SLOT(modificationsRemoveButtonReleased())); + connect(modificationsbutton, SIGNAL(released()), this, SLOT(modificationsButtonReleased())); connect(peptidetype, SIGNAL(currentIndexChanged(int)), this, SLOT(updateSettingsWhenPeptideTypeChanged(int))); connect(mode, SIGNAL(currentIndexChanged(int)), this, SLOT(updateSettingsWhenModeChanged(int))); connect(fragmentiontypes, SIGNAL(resetReleased()), this, SLOT(resetFragmentIonTypes())); connect(sequencedatabasebutton, SIGNAL(released()), this, SLOT(sequenceDatabaseButtonReleased())); + connect(searchedsequencebutton, SIGNAL(released()), this, SLOT(drawPeptideButtonReleased())); + connect(this, SIGNAL(sendSequenceLine(int, QString)), parent, SLOT(setAndShowDrawPeptideWidget(int, QString))); updateSettingsWhenPeptideTypeChanged(peptidetype->currentIndex()); @@ -363,12 +347,22 @@ cParametersWidget::cParametersWidget() { restoreParameters(); - - lastdirloadsettings = "./Settings/"; - lastdirsavesettings = "./Settings/"; - lastdirselectpeaklist = "./PeakLists/"; - lastdirselectbricksdatabase = "./BrickDatabases/"; - lastdirselectsequencedatabase = "./SequenceDatabases/"; + #if OS_TYPE == WIN + lastdirloadsettings = "./Settings/"; + lastdirsavesettings = "./Settings/"; + lastdirselectpeaklist = "./PeakLists/"; + lastdirselectbricksdatabase = "./BrickDatabases/"; + lastdirselectmodifications = "./Modifications/"; + lastdirselectsequencedatabase = "./SequenceDatabases/"; + #else + lastdirloadsettings = linuxinstalldir + "Settings/"; + lastdirsavesettings = linuxinstalldir + "Settings/"; + lastdirselectpeaklist = linuxinstalldir + "PeakLists/"; + lastdirselectbricksdatabase = linuxinstalldir + "BrickDatabases/"; + lastdirselectmodifications = linuxinstalldir + "Modifications/"; + lastdirselectsequencedatabase = linuxinstalldir + "SequenceDatabases/"; + #endif + } @@ -385,6 +379,7 @@ cParametersWidget::~cParametersWidget() { delete peaklistbutton; delete peaklistlayout; delete precursormass; + delete precursoradduct; delete precursorcharge; delete precursormasserrortolerance; delete fragmentmasserrortolerance; @@ -402,46 +397,35 @@ cParametersWidget::~cParametersWidget() { delete maximumbricksincombinationend; delete maximumcumulativemass; delete generatebrickspermutations; + delete modificationsline; + delete modificationsbutton; + delete modificationslayout; delete brickdatabaseformlayout; delete brickdatabasegroupbox; - deleteModificationsTableBody(); - - for (int i = 0; i < modificationstable->columnCount(); i++) { - delete modificationstable->horizontalHeaderItem(i); - } - - delete modificationsbuttoninsert; - delete modificationsbuttonremove; - delete modificationsbuttonslayout; - delete modificationstable; - delete modificationslayout; - delete modificationsgroupbox; + delete blindedges; + delete cyclicnterminus; + delete cycliccterminus; + delete enablescrambling; + delete miscformlayout; + delete miscgroupbox; delete mode; + delete sequencedatabaseline; + delete sequencedatabasebutton; + delete sequencedatabaselayout; delete maximumnumberofthreads; delete scoretype; delete hitsreported; delete sequencetag; delete fragmentiontypes; delete clearhitswithoutparent; - delete cyclicnterminus; - delete cycliccterminus; - delete enablescrambling; delete applicationformlayout; delete applicationgroupbox; - delete blindedges; - delete denovographformlayout; - delete denovographgroupbox; - - delete sequencedatabaseline; - delete sequencedatabasebutton; - delete sequencedatabaselayout; - delete databasesearchformlayout; - delete databasesearchgroupbox; - - delete searchedsequence; + delete searchedsequenceline; + delete searchedsequencebutton; + delete searchedsequencelayout; delete searchedsequenceNtermmodif; delete searchedsequenceCtermmodif; delete searchedsequenceTmodif; @@ -480,64 +464,32 @@ void cParametersWidget::closeEvent(QCloseEvent *event) { } -void cParametersWidget::deleteRow(int number) { - for (int i = 0; i < modificationstable->columnCount(); i++) { - if ((i == 0) || (i == 1)) { - delete modificationstable->item(number, i); - } - else { - delete modificationstable->cellWidget(number, i); - } - } - modificationstable->removeRow(number); +void cParametersWidget::setSequence(int peptidetypeindex, QString sequence) { + peptidetype->setCurrentIndex(peptidetypeindex); + searchedsequenceline->setText(sequence); } -void cParametersWidget::deleteModificationsTableBody() { - while (modificationstable->rowCount() > 0) { - deleteRow(modificationstable->rowCount() - 1); - } +void cParametersWidget::setTag(int peptidetypeindex, QString tag) { + peptidetype->setCurrentIndex(peptidetypeindex); + sequencetag->setText(tag); } -void cParametersWidget::modificationsTableInsertRow() { - int row = modificationstable->rowCount(); - - modificationstable->insertRow(row); - - modificationstable->setItem(row, 0, new QTableWidgetItem()); - modificationstable->item(row, 0)->setData(Qt::DisplayRole, ""); - - modificationstable->setItem(row, 1, new QTableWidgetItem()); - modificationstable->item(row, 1)->setData(Qt::DisplayRole, ""); - - modificationstable->setCellWidget(row, 2, new QCheckBox()); - - modificationstable->setCellWidget(row, 3, new QCheckBox()); -} - - -void cParametersWidget::modificationsTableRemoveEmptyRows() { - int i = 0; - while (i < modificationstable->rowCount()) { - if (modificationstable->item(i, 0)->text().toStdString().compare("") == 0) { - deleteRow(i); - } - else { - i++; - } - } +void cParametersWidget::keyPressEvent(QKeyEvent *event) { + if(event->key() == Qt::Key_Escape) { + restoreParameters(); + } } void cParametersWidget::loadSettings() { QString filename = QFileDialog::getOpenFileName(this, tr("Load Settings"), lastdirloadsettings, tr("Settings Files (*.ini)")); - lastdirloadsettings = filename; - if (filename.toStdString().compare("") != 0) { - int loadedrows = 0; + if (!filename.isEmpty()) { + lastdirloadsettings = filename; + QString qloadstring; - QCheckBox* tmpcheckbox; settingsfile = filename; save->setText(QString(" Save '") + QString(settingsfile.toStdString().substr(settingsfile.toStdString().rfind('/') + 1, settingsfile.toStdString().size()).c_str()) + QString("' ")); @@ -546,6 +498,7 @@ void cParametersWidget::loadSettings() { peptidetype->setCurrentIndex(settings.value("peptidetype", 0).toInt()); peaklistline->setText(settings.value("peaklist", "").toString()); precursormass->setValue(settings.value("precursormass", 0.0).toDouble()); + precursoradduct->setText(settings.value("precursoradduct", "").toString()); precursormasserrortolerance->setValue(settings.value("precursormasserrortolerance", 5.0).toDouble()); precursorcharge->setValue(settings.value("precursorcharge", 1).toInt()); fragmentmasserrortolerance->setValue(settings.value("fragmentmasserrortolerance", 5.0).toDouble()); @@ -559,31 +512,15 @@ void cParametersWidget::loadSettings() { maximumbricksincombinationend->setValue(settings.value("maximumbricksincombinationend", 3).toInt()); maximumcumulativemass->setValue(settings.value("maximumcumulativemass", 0).toDouble()); settings.value("generatebrickspermutations", 1).toInt() == 0 ? generatebrickspermutations->setChecked(false) : generatebrickspermutations->setChecked(true); + modificationsline->setText(settings.value("modificationsfile", "").toString()); - deleteModificationsTableBody(); - - qloadstring = ("modification_" + to_string(loadedrows) + "_0").c_str(); - while (settings.value(qloadstring, "").toString().toStdString().compare("") != 0) { - modificationsTableInsertRow(); - - modificationstable->item(loadedrows, 0)->setText(settings.value(qloadstring, "").toString()); - - qloadstring = ("modification_" + to_string(loadedrows) + "_1").c_str(); - modificationstable->item(loadedrows, 1)->setText(settings.value(qloadstring, "").toString()); - - tmpcheckbox = (QCheckBox *)(modificationstable->cellWidget(loadedrows, 2)); - qloadstring = ("modification_" + to_string(loadedrows) + "_2").c_str(); - settings.value(qloadstring, 0).toInt() == 0 ? tmpcheckbox->setChecked(false) : tmpcheckbox->setChecked(true); - - tmpcheckbox = (QCheckBox *)(modificationstable->cellWidget(loadedrows, 3)); - qloadstring = ("modification_" + to_string(loadedrows) + "_3").c_str(); - settings.value(qloadstring, 0).toInt() == 0 ? tmpcheckbox->setChecked(false) : tmpcheckbox->setChecked(true); - - loadedrows++; - qloadstring = ("modification_" + to_string(loadedrows) + "_0").c_str(); - } + blindedges->setCurrentIndex(settings.value("blindedges", 2).toInt()); + settings.value("cyclicnterminus", 0).toInt() == 0 ? cyclicnterminus->setChecked(false) : cyclicnterminus->setChecked(true); + settings.value("cycliccterminus", 0).toInt() == 0 ? cycliccterminus->setChecked(false) : cycliccterminus->setChecked(true); + settings.value("enablescrambling", 0).toInt() == 0 ? enablescrambling->setChecked(false) : enablescrambling->setChecked(true); mode->setCurrentIndex(settings.value("mode", 0).toInt()); + sequencedatabaseline->setText(settings.value("sequencedatabase", "").toString()); maximumnumberofthreads->setValue(settings.value("maximumnumberofthreads", 1).toInt()); scoretype->setCurrentIndex(settings.value("scoretype", 0).toInt()); hitsreported->setValue(settings.value("hitsreported", 1000).toInt()); @@ -595,15 +532,8 @@ void cParametersWidget::loadSettings() { } settings.value("clearhitswithoutparent", 0).toInt() == 0 ? clearhitswithoutparent->setChecked(false) : clearhitswithoutparent->setChecked(true); - settings.value("cyclicnterminus", 0).toInt() == 0 ? cyclicnterminus->setChecked(false) : cyclicnterminus->setChecked(true); - settings.value("cycliccterminus", 0).toInt() == 0 ? cycliccterminus->setChecked(false) : cycliccterminus->setChecked(true); - settings.value("enablescrambling", 0).toInt() == 0 ? enablescrambling->setChecked(false) : enablescrambling->setChecked(true); - - blindedges->setCurrentIndex(settings.value("blindedges", 2).toInt()); - - sequencedatabaseline->setText(settings.value("sequencedatabase", "").toString()); - searchedsequence->setText(settings.value("searchedsequence", "").toString()); + searchedsequenceline->setText(settings.value("searchedsequence", "").toString()); searchedsequenceNtermmodif->setText(settings.value("searchedsequenceNtermmodif", "").toString()); searchedsequenceCtermmodif->setText(settings.value("searchedsequenceCtermmodif", "").toString()); searchedsequenceTmodif->setText(settings.value("searchedsequenceTmodif", "").toString()); @@ -620,9 +550,7 @@ void cParametersWidget::saveSettings() { return; } - int savedrows = 0; QString qsavestring; - QCheckBox* tmpcheckbox; QSettings settings(settingsfile, QSettings::IniFormat); settings.clear(); @@ -630,6 +558,7 @@ void cParametersWidget::saveSettings() { settings.setValue("peptidetype", peptidetype->currentIndex()); settings.setValue("peaklist", peaklistline->text()); settings.setValue("precursormass", precursormass->value()); + settings.setValue("precursoradduct", precursoradduct->text()); settings.setValue("precursormasserrortolerance", precursormasserrortolerance->value()); settings.setValue("precursorcharge", precursorcharge->value()); settings.setValue("fragmentmasserrortolerance", fragmentmasserrortolerance->value()); @@ -643,28 +572,15 @@ void cParametersWidget::saveSettings() { settings.setValue("maximumbricksincombinationend", maximumbricksincombinationend->value()); settings.setValue("maximumcumulativemass", maximumcumulativemass->value()); generatebrickspermutations->isChecked() ? settings.setValue("generatebrickspermutations", 1) : settings.setValue("generatebrickspermutations", 0); + settings.setValue("modificationsfile", modificationsline->text()); - modificationsTableRemoveEmptyRows(); - - for (int i = 0; i < modificationstable->rowCount(); i++) { - qsavestring = ("modification_" + to_string(savedrows) + "_0").c_str(); - settings.setValue(qsavestring, modificationstable->item(i, 0)->text()); - - qsavestring = ("modification_" + to_string(savedrows) + "_1").c_str(); - settings.setValue(qsavestring, modificationstable->item(i, 1)->text()); - - qsavestring = ("modification_" + to_string(savedrows) + "_2").c_str(); - tmpcheckbox = (QCheckBox *)(modificationstable->cellWidget(i, 2)); - tmpcheckbox->isChecked() ? settings.setValue(qsavestring, 1) : settings.setValue(qsavestring, 0); - - qsavestring = ("modification_" + to_string(savedrows) + "_3").c_str(); - tmpcheckbox = (QCheckBox *)(modificationstable->cellWidget(i, 3)); - tmpcheckbox->isChecked() ? settings.setValue(qsavestring, 1) : settings.setValue(qsavestring, 0); - - savedrows++; - } + settings.setValue("blindedges", blindedges->currentIndex()); + cyclicnterminus->isChecked() ? settings.setValue("cyclicnterminus", 1) : settings.setValue("cyclicnterminus", 0); + cycliccterminus->isChecked() ? settings.setValue("cycliccterminus", 1) : settings.setValue("cycliccterminus", 0); + enablescrambling->isChecked() ? settings.setValue("enablescrambling", 1) : settings.setValue("enablescrambling", 0); settings.setValue("mode", mode->currentIndex()); + settings.setValue("sequencedatabase", sequencedatabaseline->text()); settings.setValue("maximumnumberofthreads", maximumnumberofthreads->value()); settings.setValue("scoretype", scoretype->currentIndex()); settings.setValue("hitsreported", hitsreported->value()); @@ -676,15 +592,8 @@ void cParametersWidget::saveSettings() { } clearhitswithoutparent->isChecked() ? settings.setValue("clearhitswithoutparent", 1) : settings.setValue("clearhitswithoutparent", 0); - cyclicnterminus->isChecked() ? settings.setValue("cyclicnterminus", 1) : settings.setValue("cyclicnterminus", 0); - cycliccterminus->isChecked() ? settings.setValue("cycliccterminus", 1) : settings.setValue("cycliccterminus", 0); - enablescrambling->isChecked() ? settings.setValue("enablescrambling", 1) : settings.setValue("enablescrambling", 0); - - settings.setValue("blindedges", blindedges->currentIndex()); - - settings.setValue("sequencedatabase", sequencedatabaseline->text()); - settings.setValue("searchedsequence", searchedsequence->text()); + settings.setValue("searchedsequence", searchedsequenceline->text()); settings.setValue("searchedsequenceNtermmodif", searchedsequenceNtermmodif->text()); settings.setValue("searchedsequenceCtermmodif", searchedsequenceCtermmodif->text()); settings.setValue("searchedsequenceTmodif", searchedsequenceTmodif->text()); @@ -694,9 +603,10 @@ void cParametersWidget::saveSettings() { void cParametersWidget::saveSettingsAs() { QString filename = QFileDialog::getSaveFileName(this, tr("Save Settings As..."), lastdirsavesettings, tr("Files (*.ini)")); - lastdirsavesettings = filename; - if (filename.toStdString().compare("") != 0) { + if (!filename.isEmpty()) { + lastdirsavesettings = filename; + settingsfile = filename; save->setText(QString(" Save '") + QString(settingsfile.toStdString().substr(settingsfile.toStdString().rfind('/') + 1, settingsfile.toStdString().size()).c_str()) + QString("' ")); saveSettings(); @@ -705,11 +615,14 @@ void cParametersWidget::saveSettingsAs() { void cParametersWidget::peaklistButtonReleased() { - QString filename = QFileDialog::getOpenFileName(this, tr("Select Peaklist..."), lastdirselectpeaklist, tr("Peak Lists (*.txt *.mgf *.mzML *.mzXML *.baf)")); - lastdirselectpeaklist = filename; - - if (filename.toStdString().compare("") != 0) { - peaklistfilename = filename.toStdString(); + #if OS_TYPE == UNX + QString filename = QFileDialog::getOpenFileName(this, tr("Select Peaklist..."), lastdirselectpeaklist, tr("Peak Lists (*.txt *.mgf *.mzML *.mzXML)")); + #else + QString filename = QFileDialog::getOpenFileName(this, tr("Select Peaklist..."), lastdirselectpeaklist, tr("Peak Lists (*.txt *.mgf *.mzML *.mzXML *.baf)")); + #endif + + if (!filename.isEmpty()) { + lastdirselectpeaklist = filename; peaklistline->setText(filename); } } @@ -717,33 +630,31 @@ void cParametersWidget::peaklistButtonReleased() { void cParametersWidget::brickDatabaseButtonReleased() { QString filename = QFileDialog::getOpenFileName(this, tr("Select Building Blocks Database..."), lastdirselectbricksdatabase, tr("Text Files (*.txt)")); - lastdirselectbricksdatabase = filename; - - if (filename.toStdString().compare("") != 0) { - brickdatabasefilename = filename.toStdString(); + + if (!filename.isEmpty()) { + lastdirselectbricksdatabase = filename; brickdatabaseline->setText(filename); } } -void cParametersWidget::sequenceDatabaseButtonReleased() { - QString filename = QFileDialog::getOpenFileName(this, tr("Select Sequence Database..."), lastdirselectsequencedatabase, tr("Text Files (*.txt)")); - lastdirselectsequencedatabase = filename; - - if (filename.toStdString().compare("") != 0) { - sequencedatabasefilename = filename.toStdString(); - sequencedatabaseline->setText(filename); +void cParametersWidget::modificationsButtonReleased() { + QString filename = QFileDialog::getOpenFileName(this, tr("Select Modifications File..."), lastdirselectmodifications, tr("Text Files (*.txt)")); + + if (!filename.isEmpty()) { + lastdirselectmodifications = filename; + modificationsline->setText(filename); } } -void cParametersWidget::modificationsInsertButtonReleased() { - modificationsTableInsertRow(); -} - +void cParametersWidget::sequenceDatabaseButtonReleased() { + QString filename = QFileDialog::getOpenFileName(this, tr("Select Sequence Database..."), lastdirselectsequencedatabase, tr("Text Files (*.txt)")); -void cParametersWidget::modificationsRemoveButtonReleased() { - modificationsTableRemoveEmptyRows(); + if (!filename.isEmpty()) { + lastdirselectsequencedatabase = filename; + sequencedatabaseline->setText(filename); + } } @@ -752,29 +663,46 @@ bool cParametersWidget::updateParameters() { QString errstr; if (peaklistline->text().toStdString().compare("") == 0) { - errstr = "A peaklist must be specified."; + errstr = "A peaklist must be specified!"; msgBox.setText(errstr); msgBox.exec(); return false; } if ((brickdatabaseline->text().toStdString().compare("") == 0) && (((modeType)mode->currentIndex() == denovoengine) || ((modeType)mode->currentIndex() == singlecomparison) || ((modeType)mode->currentIndex() == databasesearch))) { - errstr = "A database of building blocks must be specified."; + errstr = "A database of building blocks must be specified!"; msgBox.setText(errstr); msgBox.exec(); return false; } if ((sequencedatabaseline->text().toStdString().compare("") == 0) && (((modeType)mode->currentIndex() == databasesearch) || ((modeType)mode->currentIndex() == dereplication))) { - errstr = "A sequence database must be specified."; + errstr = "A sequence database must be specified!"; + msgBox.setText(errstr); + msgBox.exec(); + return false; + } + + if (precursorcharge->value() == 0) { + errstr = "The charge cannot be zero!"; msgBox.setText(errstr); msgBox.exec(); return false; } + /* + if ((maximumbricksincombinationmiddle->value() < 2) && ((modeType)mode->currentIndex() == denovoengine) && (((peptideType)peptidetype->currentIndex() == branched) || ((peptideType)peptidetype->currentIndex() == lasso))) { + errstr = "'Maximum Number of Combined Blocks (middle)' must be at least 2 when a branched or a branch-cyclic peptide is searched! (One block represents a branched residue, the other block(s) corresponds to a branch.)"; + msgBox.setText(errstr); + msgBox.exec(); + return false; + } + */ + parameters.peptidetype = (peptideType)peptidetype->currentIndex(); parameters.peaklistfilename = peaklistline->text().toStdString(); parameters.precursormass = precursormass->value(); + parameters.precursoradduct = precursoradduct->text().toStdString(); parameters.precursormasserrortolerance = precursormasserrortolerance->value(); parameters.precursorcharge = precursorcharge->value(); parameters.fragmentmasserrortolerance = fragmentmasserrortolerance->value(); @@ -789,26 +717,15 @@ bool cParametersWidget::updateParameters() { parameters.maximumcumulativemass = maximumcumulativemass->value(); parameters.maximumbricksincombination = max(max(parameters.maximumbricksincombinationbegin, parameters.maximumbricksincombinationmiddle), parameters.maximumbricksincombinationend); parameters.generatebrickspermutations = generatebrickspermutations->isChecked(); + parameters.modificationsfilename = modificationsline->text().toStdString(); - QCheckBox* tmpcheckbox1; - QCheckBox* tmpcheckbox2; - - parameters.searchedmodifications.clear(); - parameters.searchedmodifications.push_back(fragmentDescription("", 0, "", true, true)); - - modificationsTableRemoveEmptyRows(); - - int i = 0; - while (i < modificationstable->rowCount()) { - tmpcheckbox1 = (QCheckBox *)(modificationstable->cellWidget(i, 2)); - tmpcheckbox2 = (QCheckBox *)(modificationstable->cellWidget(i, 3)); - - parameters.searchedmodifications.push_back(fragmentDescription(modificationstable->item(i, 0)->text().toStdString(), 0, modificationstable->item(i, 1)->text().toStdString(), tmpcheckbox1->isChecked(), tmpcheckbox2->isChecked())); - - i++; - } + parameters.blindedges = blindedges->currentIndex(); + parameters.cyclicnterminus = cyclicnterminus->isChecked(); + parameters.cycliccterminus = cycliccterminus->isChecked(); + parameters.enablescrambling = enablescrambling->isChecked(); parameters.mode = (modeType)mode->currentIndex(); + parameters.sequencedatabasefilename = sequencedatabaseline->text().toStdString(); parameters.maximumnumberofthreads = maximumnumberofthreads->value(); parameters.scoretype = (scoreType)scoretype->currentIndex(); parameters.hitsreported = hitsreported->value(); @@ -826,13 +743,13 @@ bool cParametersWidget::updateParameters() { { case linear: case branched: - start = b_ion; + start = a_ion; break; case cyclic: - start = b_ion; + start = a_ion; break; case lasso: - start = b_ion; + start = a_ion; break; case linearpolysaccharide: start = ms_nterminal_ion_hplus; @@ -850,22 +767,15 @@ bool cParametersWidget::updateParameters() { } parameters.clearhitswithoutparent = clearhitswithoutparent->isChecked(); - parameters.cyclicnterminus = cyclicnterminus->isChecked(); - parameters.cycliccterminus = cycliccterminus->isChecked(); - parameters.updateFragmentDefinitions(); - - parameters.enablescrambling = enablescrambling->isChecked(); - - parameters.blindedges = blindedges->currentIndex(); - parameters.sequencedatabasefilename = sequencedatabaseline->text().toStdString(); - - parameters.searchedsequence = searchedsequence->text().toStdString(); + parameters.searchedsequence = searchedsequenceline->text().toStdString(); parameters.originalsearchedsequence = parameters.searchedsequence; parameters.searchedsequenceNtermmodif = searchedsequenceNtermmodif->text().toStdString(); parameters.searchedsequenceCtermmodif = searchedsequenceCtermmodif->text().toStdString(); parameters.searchedsequenceTmodif = searchedsequenceTmodif->text().toStdString(); + parameters.updateFragmentDefinitions(); + oldsettingsfile = settingsfile; return true; @@ -883,6 +793,7 @@ void cParametersWidget::restoreParameters() { peptidetype->setCurrentIndex(parameters.peptidetype); peaklistline->setText(parameters.peaklistfilename.c_str()); precursormass->setValue(parameters.precursormass); + precursoradduct->setText(parameters.precursoradduct.c_str()); precursormasserrortolerance->setValue(parameters.precursormasserrortolerance); precursorcharge->setValue(parameters.precursorcharge); fragmentmasserrortolerance->setValue(parameters.fragmentmasserrortolerance); @@ -896,29 +807,15 @@ void cParametersWidget::restoreParameters() { maximumbricksincombinationend->setValue(parameters.maximumbricksincombinationend); maximumcumulativemass->setValue(parameters.maximumcumulativemass); generatebrickspermutations->setChecked(parameters.generatebrickspermutations); + modificationsline->setText(parameters.modificationsfilename.c_str()); - QCheckBox* tmpcheckbox; - - deleteModificationsTableBody(); - - int i = 1; - while (i < (int)parameters.searchedmodifications.size()) { - modificationsTableInsertRow(); - - modificationstable->item(i - 1, 0)->setText(parameters.searchedmodifications[i].name.c_str()); - - modificationstable->item(i - 1, 1)->setText(parameters.searchedmodifications[i].summary.c_str()); - - tmpcheckbox = (QCheckBox *)(modificationstable->cellWidget(i - 1, 2)); - tmpcheckbox->setChecked(parameters.searchedmodifications[i].nterminal); - - tmpcheckbox = (QCheckBox *)(modificationstable->cellWidget(i - 1, 3)); - tmpcheckbox->setChecked(parameters.searchedmodifications[i].cterminal); - - i++; - } + blindedges->setCurrentIndex(parameters.blindedges); + cyclicnterminus->setChecked(parameters.cyclicnterminus); + cycliccterminus->setChecked(parameters.cycliccterminus); + enablescrambling->setChecked(parameters.enablescrambling); mode->setCurrentIndex(parameters.mode); + sequencedatabaseline->setText(parameters.sequencedatabasefilename.c_str()); maximumnumberofthreads->setValue(parameters.maximumnumberofthreads); scoretype->setCurrentIndex(parameters.scoretype); hitsreported->setValue(parameters.hitsreported); @@ -933,13 +830,13 @@ void cParametersWidget::restoreParameters() { { case linear: case branched: - start = b_ion; + start = a_ion; break; case cyclic: - start = b_ion; + start = a_ion; break; case lasso: - start = b_ion; + start = a_ion; break; case linearpolysaccharide: start = ms_nterminal_ion_hplus; @@ -955,15 +852,8 @@ void cParametersWidget::restoreParameters() { } clearhitswithoutparent->setChecked(parameters.clearhitswithoutparent); - cyclicnterminus->setChecked(parameters.cyclicnterminus); - cycliccterminus->setChecked(parameters.cycliccterminus); - enablescrambling->setChecked(parameters.enablescrambling); - blindedges->setCurrentIndex(parameters.blindedges); - - sequencedatabaseline->setText(parameters.sequencedatabasefilename.c_str()); - - searchedsequence->setText(parameters.searchedsequence.c_str()); + searchedsequenceline->setText(parameters.searchedsequence.c_str()); searchedsequenceNtermmodif->setText(parameters.searchedsequenceNtermmodif.c_str()); searchedsequenceCtermmodif->setText(parameters.searchedsequenceCtermmodif.c_str()); searchedsequenceTmodif->setText(parameters.searchedsequenceTmodif.c_str()); @@ -987,49 +877,54 @@ void cParametersWidget::updateSettingsWhenPeptideTypeChanged(int index) { switch ((peptideType)index) { case linear: - modificationsgroupbox->setDisabled(false); - searchedsequenceNtermmodif->setDisabled(false); - searchedsequenceCtermmodif->setDisabled(false); - searchedsequenceTmodif->setDisabled(true); + modificationsline->setDisabled(false); + modificationsbutton->setDisabled(false); cyclicnterminus->setDisabled(false); cycliccterminus->setDisabled(false); enablescrambling->setDisabled(true); + searchedsequenceNtermmodif->setDisabled(false); + searchedsequenceCtermmodif->setDisabled(false); + searchedsequenceTmodif->setDisabled(true); break; case cyclic: - modificationsgroupbox->setDisabled(true); - searchedsequenceNtermmodif->setDisabled(true); - searchedsequenceCtermmodif->setDisabled(true); - searchedsequenceTmodif->setDisabled(true); + modificationsline->setDisabled(true); + modificationsbutton->setDisabled(true); cyclicnterminus->setDisabled(true); cycliccterminus->setDisabled(true); enablescrambling->setDisabled(false); + searchedsequenceNtermmodif->setDisabled(true); + searchedsequenceCtermmodif->setDisabled(true); + searchedsequenceTmodif->setDisabled(true); break; case branched: - modificationsgroupbox->setDisabled(false); + modificationsline->setDisabled(false); + modificationsbutton->setDisabled(false); + cyclicnterminus->setDisabled(true); + cycliccterminus->setDisabled(true); + enablescrambling->setDisabled(true); searchedsequenceNtermmodif->setDisabled(false); searchedsequenceCtermmodif->setDisabled(false); searchedsequenceTmodif->setDisabled(false); + break; + case lasso: + modificationsline->setDisabled(false); + modificationsbutton->setDisabled(false); cyclicnterminus->setDisabled(true); cycliccterminus->setDisabled(true); enablescrambling->setDisabled(true); - break; - case lasso: - modificationsgroupbox->setDisabled(false); searchedsequenceNtermmodif->setDisabled(true); searchedsequenceCtermmodif->setDisabled(true); searchedsequenceTmodif->setDisabled(false); + break; + case linearpolysaccharide: + modificationsline->setDisabled(false); + modificationsbutton->setDisabled(false); cyclicnterminus->setDisabled(true); cycliccterminus->setDisabled(true); enablescrambling->setDisabled(true); - break; - case linearpolysaccharide: - modificationsgroupbox->setDisabled(false); searchedsequenceNtermmodif->setDisabled(false); searchedsequenceCtermmodif->setDisabled(false); searchedsequenceTmodif->setDisabled(true); - cyclicnterminus->setDisabled(true); - cycliccterminus->setDisabled(true); - enablescrambling->setDisabled(true); break; case other: default: @@ -1045,6 +940,7 @@ void cParametersWidget::updateSettingsWhenModeChanged(int index) { case denovoengine: peptidetype->setDisabled(false); precursormass->setDisabled(false); + precursoradduct->setDisabled(false); precursorcharge->setDisabled(false); precursormasserrortolerance->setDisabled(false); brickdatabaseline->setDisabled(false); @@ -1054,23 +950,28 @@ void cParametersWidget::updateSettingsWhenModeChanged(int index) { maximumbricksincombinationend->setDisabled(false); maximumcumulativemass->setDisabled(false); generatebrickspermutations->setDisabled(false); + modificationsline->setDisabled(false); + modificationsbutton->setDisabled(false); + sequencedatabaseline->setDisabled(true); + sequencedatabasebutton->setDisabled(true); + blindedges->setDisabled(false); maximumnumberofthreads->setDisabled(false); scoretype->setDisabled(false); hitsreported->setDisabled(false); sequencetag->setDisabled(false); fragmentiontypes->setDisabled(false); clearhitswithoutparent->setDisabled(false); - denovographgroupbox->setDisabled(false); - databasesearchgroupbox->setDisabled(true); - searchedsequence->setDisabled(false); + searchedsequenceline->setDisabled(false); + searchedsequencebutton->setDisabled(false); updateSettingsWhenPeptideTypeChanged(peptidetype->currentIndex()); break; case singlecomparison: peptidetype->setDisabled(false); - precursormass->setDisabled(true); + precursormass->setDisabled(false); + precursoradduct->setDisabled(false); precursorcharge->setDisabled(false); - precursormasserrortolerance->setDisabled(true); + precursormasserrortolerance->setDisabled(false); brickdatabaseline->setDisabled(false); brickdatabasebutton->setDisabled(false); maximumbricksincombinationbegin->setDisabled(true); @@ -1078,21 +979,26 @@ void cParametersWidget::updateSettingsWhenModeChanged(int index) { maximumbricksincombinationend->setDisabled(true); maximumcumulativemass->setDisabled(true); generatebrickspermutations->setDisabled(true); + modificationsline->setDisabled(false); + modificationsbutton->setDisabled(false); + sequencedatabaseline->setDisabled(true); + sequencedatabasebutton->setDisabled(true); + blindedges->setDisabled(true); maximumnumberofthreads->setDisabled(true); scoretype->setDisabled(true); hitsreported->setDisabled(true); sequencetag->setDisabled(true); fragmentiontypes->setDisabled(false); clearhitswithoutparent->setDisabled(false); - denovographgroupbox->setDisabled(true); - databasesearchgroupbox->setDisabled(true); - searchedsequence->setDisabled(false); + searchedsequenceline->setDisabled(false); + searchedsequencebutton->setDisabled(false); updateSettingsWhenPeptideTypeChanged(peptidetype->currentIndex()); break; case databasesearch: peptidetype->setDisabled(false); precursormass->setDisabled(false); + precursoradduct->setDisabled(false); precursorcharge->setDisabled(false); precursormasserrortolerance->setDisabled(false); brickdatabaseline->setDisabled(false); @@ -1102,21 +1008,26 @@ void cParametersWidget::updateSettingsWhenModeChanged(int index) { maximumbricksincombinationend->setDisabled(true); maximumcumulativemass->setDisabled(true); generatebrickspermutations->setDisabled(true); + modificationsline->setDisabled(false); + modificationsbutton->setDisabled(false); + blindedges->setDisabled(true); + sequencedatabaseline->setDisabled(false); + sequencedatabasebutton->setDisabled(false); maximumnumberofthreads->setDisabled(false); scoretype->setDisabled(false); hitsreported->setDisabled(false); sequencetag->setDisabled(false); fragmentiontypes->setDisabled(false); clearhitswithoutparent->setDisabled(false); - denovographgroupbox->setDisabled(true); - databasesearchgroupbox->setDisabled(false); - searchedsequence->setDisabled(false); + searchedsequenceline->setDisabled(false); + searchedsequencebutton->setDisabled(false); updateSettingsWhenPeptideTypeChanged(peptidetype->currentIndex()); break; case dereplication: peptidetype->setDisabled(true); precursormass->setDisabled(true); + precursoradduct->setDisabled(true); precursorcharge->setDisabled(false); precursormasserrortolerance->setDisabled(true); brickdatabaseline->setDisabled(true); @@ -1126,25 +1037,30 @@ void cParametersWidget::updateSettingsWhenModeChanged(int index) { maximumbricksincombinationend->setDisabled(true); maximumcumulativemass->setDisabled(true); generatebrickspermutations->setDisabled(true); + modificationsline->setDisabled(true); + modificationsbutton->setDisabled(true); + blindedges->setDisabled(true); + sequencedatabaseline->setDisabled(false); + sequencedatabasebutton->setDisabled(false); maximumnumberofthreads->setDisabled(true); scoretype->setDisabled(true); hitsreported->setDisabled(true); sequencetag->setDisabled(true); fragmentiontypes->setDisabled(false); clearhitswithoutparent->setDisabled(true); - denovographgroupbox->setDisabled(true); - databasesearchgroupbox->setDisabled(false); - searchedsequence->setDisabled(true); + searchedsequenceline->setDisabled(true); + searchedsequencebutton->setDisabled(true); resetFragmentIonTypes(); - modificationsgroupbox->setDisabled(true); - searchedsequenceNtermmodif->setDisabled(true); - searchedsequenceCtermmodif->setDisabled(true); - searchedsequenceTmodif->setDisabled(true); + modificationsline->setDisabled(true); + modificationsbutton->setDisabled(true); cyclicnterminus->setDisabled(true); cycliccterminus->setDisabled(true); enablescrambling->setDisabled(true); + searchedsequenceNtermmodif->setDisabled(true); + searchedsequenceCtermmodif->setDisabled(true); + searchedsequenceTmodif->setDisabled(true); break; default: break; @@ -1166,16 +1082,16 @@ void cParametersWidget::resetFragmentIonTypes() { switch ((peptideType)peptidetype->currentIndex()) { case linear: case branched: - start = b_ion; - end = y_ion_water_and_ammonia_loss; + start = a_ion; + end = z_ion_dehydrated_and_deamidated; break; case cyclic: - start = b_ion; - end = a_ion_water_and_ammonia_loss; + start = a_ion; + end = c_ion_dehydrated_and_deamidated; break; case lasso: - start = b_ion; - end = y_ion_water_and_ammonia_loss; + start = a_ion; + end = z_ion_dehydrated_and_deamidated; break; case linearpolysaccharide: start = ms_nterminal_ion_hplus; @@ -1187,13 +1103,50 @@ void cParametersWidget::resetFragmentIonTypes() { } } - for (int i = start; i <= end; i++) { + for (int i = (int)start; i <= (int)end; i++) { + fragmentiontypes->getList()->addItem(tr(parameters.fragmentdefinitions[(fragmentIonType)i].name.c_str())); - if (parameters.fragmentdefinitions[(fragmentIonType)i].parent == (fragmentIonType)i) { - fragmentiontypes->getList()->item(i-start)->setSelected(true); + if ((modeType)mode->currentIndex() == dereplication) { + if ((fragmentIonType)i == ms_hplus) { + fragmentiontypes->getList()->item(i-start)->setSelected(true); + } + } + else { + switch ((peptideType)peptidetype->currentIndex()) { + case linear: + case branched: + if (((fragmentIonType)i == b_ion) || ((fragmentIonType)i == y_ion)) { + fragmentiontypes->getList()->item(i-start)->setSelected(true); + } + break; + case cyclic: + if ((fragmentIonType)i == b_ion) { + fragmentiontypes->getList()->item(i-start)->setSelected(true); + } + break; + case lasso: + if (((fragmentIonType)i == b_ion) || ((fragmentIonType)i == y_ion)) { + fragmentiontypes->getList()->item(i-start)->setSelected(true); + } + break; + case linearpolysaccharide: + if (((fragmentIonType)i == ms_nterminal_ion_hplus) || ((fragmentIonType)i == ms_cterminal_ion_hplus)) { + fragmentiontypes->getList()->item(i-start)->setSelected(true); + } + break; + case other: + default: + break; + } } + } } + +void cParametersWidget::drawPeptideButtonReleased() { + emit sendSequenceLine(peptidetype->currentIndex(), searchedsequenceline->text()); +} + diff --git a/CycloBranch/gui/cParametersWidget.h b/CycloBranch/gui/cParametersWidget.h index b5661da..a3bf011 100644 --- a/CycloBranch/gui/cParametersWidget.h +++ b/CycloBranch/gui/cParametersWidget.h @@ -14,6 +14,7 @@ #include #include +#include "core/utilities.h" #include "core/cSummaryFormula.h" #include "core/cParameters.h" #include "gui/cFragmentIonsListWidget.h" @@ -50,8 +51,9 @@ class cParametersWidget : public QWidget /** \brief The constructor. + \param parent pointer to a parent widget */ - cParametersWidget(); + cParametersWidget(QWidget* parent = (QWidget *)0); /** @@ -81,7 +83,26 @@ class cParametersWidget : public QWidget void closeEvent(QCloseEvent *event); + /** + \brief Set peptide type and searched sequence. + \param peptidetypeindex an index of current peptide type + \param sequence searched sequence + */ + void setSequence(int peptidetypeindex, QString sequence); + + + /** + \brief Set peptide type and sequence tag. + \param peptidetypeindex an index of current peptide type + \param tag sequence tag + */ + void setTag(int peptidetypeindex, QString tag); + + private: + + QWidget* parent; + cParameters parameters; QVBoxLayout* vlayout1; @@ -104,8 +125,8 @@ class cParametersWidget : public QWidget QLineEdit* peaklistline; QPushButton* peaklistbutton; QHBoxLayout* peaklistlayout; - string peaklistfilename; QDoubleSpinBox* precursormass; + QLineEdit* precursoradduct; QSpinBox* precursorcharge; QDoubleSpinBox* precursormasserrortolerance; QDoubleSpinBox* fragmentmasserrortolerance; @@ -118,47 +139,40 @@ class cParametersWidget : public QWidget QLineEdit* brickdatabaseline; QPushButton* brickdatabasebutton; QHBoxLayout* brickdatabaselayout; - string brickdatabasefilename; QSpinBox* maximumbricksincombinationbegin; QSpinBox* maximumbricksincombinationmiddle; QSpinBox* maximumbricksincombinationend; QDoubleSpinBox* maximumcumulativemass; QCheckBox* generatebrickspermutations; + QLineEdit* modificationsline; + QPushButton* modificationsbutton; + QHBoxLayout* modificationslayout; - QGroupBox* modificationsgroupbox; - QVBoxLayout* modificationslayout; - QTableWidget* modificationstable; - QHBoxLayout* modificationsbuttonslayout; - QPushButton* modificationsbuttoninsert; - QPushButton* modificationsbuttonremove; + QGroupBox* miscgroupbox; + QFormLayout* miscformlayout; + QComboBox* blindedges; + QCheckBox* cyclicnterminus; + QCheckBox* cycliccterminus; + QCheckBox* enablescrambling; QFormLayout* applicationformlayout; QGroupBox* applicationgroupbox; QComboBox* mode; + QLineEdit* sequencedatabaseline; + QPushButton* sequencedatabasebutton; + QHBoxLayout* sequencedatabaselayout; QSpinBox* maximumnumberofthreads; QComboBox* scoretype; QSpinBox* hitsreported; QLineEdit* sequencetag; cFragmentIonsListWidget* fragmentiontypes; QCheckBox* clearhitswithoutparent; - QCheckBox* cyclicnterminus; - QCheckBox* cycliccterminus; - QCheckBox* enablescrambling; - - QGroupBox* denovographgroupbox; - QFormLayout* denovographformlayout; - QComboBox* blindedges; - QGroupBox* databasesearchgroupbox; - QFormLayout* databasesearchformlayout; - QLineEdit* sequencedatabaseline; - QPushButton* sequencedatabasebutton; - QHBoxLayout* sequencedatabaselayout; - string sequencedatabasefilename; - QGroupBox* searchedsequencegroupbox; QFormLayout* searchedsequenceformlayout; - QLineEdit* searchedsequence; + QLineEdit* searchedsequenceline; + QPushButton* searchedsequencebutton; + QHBoxLayout* searchedsequencelayout; QLineEdit* searchedsequenceNtermmodif; QLineEdit* searchedsequenceCtermmodif; QLineEdit* searchedsequenceTmodif; @@ -167,15 +181,18 @@ class cParametersWidget : public QWidget QString lastdirsavesettings; QString lastdirselectpeaklist; QString lastdirselectbricksdatabase; + QString lastdirselectmodifications; QString lastdirselectsequencedatabase; - void deleteRow(int number); - void deleteModificationsTableBody(); +protected: - void modificationsTableInsertRow(); - void modificationsTableRemoveEmptyRows(); + /** + \brief Handle a key press event. + \param event pointer to QKeyEvent + */ + void keyPressEvent(QKeyEvent *event); private slots: @@ -190,11 +207,9 @@ private slots: void brickDatabaseButtonReleased(); - void sequenceDatabaseButtonReleased(); - - void modificationsInsertButtonReleased(); + void modificationsButtonReleased(); - void modificationsRemoveButtonReleased(); + void sequenceDatabaseButtonReleased(); bool updateParameters(); @@ -208,6 +223,18 @@ private slots: void resetFragmentIonTypes(); + void drawPeptideButtonReleased(); + + +signals: + + /** + \brief Send index of peptide type and searched sequence. + \param peptidetypeindex an index of current peptide type + \param sequence searched sequence + */ + void sendSequenceLine(int peptidetypeindex, QString sequence); + }; #endif \ No newline at end of file diff --git a/CycloBranch/gui/cSequenceDatabaseWidget.cpp b/CycloBranch/gui/cSequenceDatabaseWidget.cpp index 819b1ea..7d70122 100644 --- a/CycloBranch/gui/cSequenceDatabaseWidget.cpp +++ b/CycloBranch/gui/cSequenceDatabaseWidget.cpp @@ -1,5 +1,6 @@ #include "gui/cSequenceDatabaseWidget.h" #include "gui/cMainThread.h" +#include "gui/cEventFilter.h" #include #include @@ -13,12 +14,15 @@ #include #include #include +#include +#include cSequenceDatabaseWidget::cSequenceDatabaseWidget(QWidget* parent) { this->parent = parent; setWindowTitle("Sequence Database Editor"); + setWindowIcon(QIcon(":/images/icons/26.png")); insertrow = new QPushButton(tr("Add Row")); insertrow->setToolTip("Add a new row."); @@ -71,11 +75,6 @@ cSequenceDatabaseWidget::cSequenceDatabaseWidget(QWidget* parent) { mainlayout->addWidget(database); mainlayout->addLayout(buttons); - progress = new QProgressDialog(this); - progress->setCancelButton(0); - progress->setMinimumDuration(1000); - progress->setWindowModality(Qt::WindowModal); - connect(database->horizontalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(headerItemDoubleClicked(int))); connect(database, SIGNAL(itemChanged(QTableWidgetItem *)), this, SLOT(itemChanged(QTableWidgetItem *))); connect(insertrow, SIGNAL(released()), this, SLOT(addRow())); @@ -90,7 +89,13 @@ cSequenceDatabaseWidget::cSequenceDatabaseWidget(QWidget* parent) { resize(1280, 700); databasefile = ""; - lastdir = "./SequenceDatabases/"; + + #if OS_TYPE == WIN + lastdir = "./SequenceDatabases/"; + #else + lastdir = linuxinstalldir + "SequenceDatabases/"; + #endif + sequences.clear(); } @@ -113,7 +118,6 @@ cSequenceDatabaseWidget::~cSequenceDatabaseWidget() { delete database; delete buttons; delete mainlayout; - delete progress; } @@ -122,35 +126,51 @@ void cSequenceDatabaseWidget::closeEvent(QCloseEvent *event) { } +void cSequenceDatabaseWidget::insertRow(int peptidetypeindex, QString sequence) { + addRow(); + ((QComboBox *)(database->cellWidget(database->rowCount() - 1, 1)))->setCurrentIndex(peptidetypeindex); + database->item(database->rowCount() - 1, 5)->setText(sequence); + + for (int i = 0; i < database->columnCount(); i++) { + database->resizeColumnToContents(i); + } +} + + void cSequenceDatabaseWidget::deleteTable(bool enableprogress) { + QProgressDialog* progress; + cEventFilter filter; + int rowcount = database->rowCount(); + if (enableprogress) { - progress->setLabelText("Clearing the table..."); - progress->setMinimum(0); - progress->setValue(1); - progress->setMaximum(database->rowCount()); - progress->show(); + progress = new QProgressDialog("Clearing the table...", /*"Cancel"*/0, 0, rowcount, this); + progress->installEventFilter(&filter); + progress->setMinimumDuration(0); + progress->setWindowModality(Qt::WindowModal); + progress->setValue(0); } - for (int i = 0; i < database->rowCount(); i++) { - for (int j = 0; j < database->columnCount(); j++) { - if ((j == 0) || (j == 1) || (j == 10)) { - delete database->cellWidget(i, j); - } - else { - delete database->item(i, j); - } - } + widgetitemallocator.reset(); + + for (int i = 0; i < rowcount; i++) { + delete database->cellWidget(rowcount - i - 1, 0); + delete database->cellWidget(rowcount - i - 1, 1); + delete database->cellWidget(rowcount - i - 1, 10); - if (enableprogress && ((i == 0) || ((i - 1)/100 != i/100))) { + if (enableprogress) { progress->setValue(i); + //if (progress->wasCanceled()) { + // break; + //} } } + database->setRowCount(0); + if (enableprogress) { - progress->setValue(database->rowCount()); - progress->hide(); + progress->setValue(rowcount); + delete progress; } - database->setRowCount(0); } @@ -160,7 +180,7 @@ void cSequenceDatabaseWidget::removeRow(int row) { delete database->cellWidget(row, i); } else { - delete database->item(row, i); + database->takeItem(row, i); } } database->removeRow(row); @@ -187,7 +207,7 @@ bool cSequenceDatabaseWidget::checkTable() { } -bool cSequenceDatabaseWidget::checkFormula(int row, string& summary) { +bool cSequenceDatabaseWidget::checkFormula(int row, const string& summary) { cSummaryFormula formula; string errmsg; formula.setFormula(summary); @@ -209,20 +229,27 @@ bool cSequenceDatabaseWidget::checkFormula(int row, string& summary) { bool cSequenceDatabaseWidget::checkSequence(int row) { + + if (database->item(row, 5)->text().toStdString().compare("") == 0) { + return true; + } + regex rx; // [^\\[\\]]+ is used instead of .+ to prevent from a too complex regex error switch ((peptideType)((QComboBox *)database->cellWidget(row, 1))->currentIndex()) { case linear: - case cyclic: case linearpolysaccharide: rx = "^\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*$"; break; + case cyclic: + rx = "^\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])+$"; + break; case branched: - rx = "^\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*\\\\\\(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*\\\\\\)\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*$"; + rx = "^\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*\\\\\\(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])+\\\\\\)\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*$"; break; case lasso: - rx = "(^(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*)?\\\\\\(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*\\\\\\)\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*$|^\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*\\\\\\(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*\\\\\\)(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*)?$)"; + rx = "(^(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*)?\\\\\\(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])+\\\\\\)\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*$|^\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*\\\\\\(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])+\\\\\\)(\\[[^\\[\\]]+\\](-\\[[^\\[\\]]+\\])*)?$)"; break; case other: default: @@ -245,7 +272,7 @@ bool cSequenceDatabaseWidget::checkSequence(int row) { return false; } } - catch (std::regex_error& e) { + catch (regex_error& e) { QMessageBox msgBox; QString errstr = "Row no. "; errstr += to_string(row + 1).c_str(); @@ -263,6 +290,13 @@ bool cSequenceDatabaseWidget::checkSequence(int row) { } +void cSequenceDatabaseWidget::keyPressEvent(QKeyEvent *event) { + if(event->key() == Qt::Key_Escape) { + hide(); + } +} + + void cSequenceDatabaseWidget::closeWindow() { hide(); } @@ -270,9 +304,9 @@ void cSequenceDatabaseWidget::closeWindow() { void cSequenceDatabaseWidget::loadDatabase() { QString filename = QFileDialog::getOpenFileName(this, tr("Load the Database of Sequences"), lastdir, tr("Database of Sequences (*.txt)")); - lastdir = filename; - if (filename.toStdString().compare("") != 0) { + if (!filename.isEmpty()) { + lastdir = filename; databasefile = filename; save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); @@ -291,11 +325,11 @@ void cSequenceDatabaseWidget::loadDatabase() { sequences.clear(); sequences.loadFromPlainTextStream(inputstream); - progress->setLabelText("Loading the Sequence Databatase..."); - progress->setMinimum(0); - progress->setValue(1); - progress->setMaximum(sequences.size()); - progress->show(); + QProgressDialog progress("Loading the Sequence Databatase...", /*"Cancel"*/0, 0, sequences.size(), this); + cEventFilter filter; + progress.installEventFilter(&filter); + progress.setMinimumDuration(0); + progress.setWindowModality(Qt::WindowModal); cSummaryFormula formula; database->setRowCount(sequences.size()); @@ -310,34 +344,48 @@ void cSequenceDatabaseWidget::loadDatabase() { combo->setCurrentIndex((int)sequences[i].getPeptideType()); database->setCellWidget(i, 1, combo); - database->setItem(i, 2, new QTableWidgetItem(sequences[i].getName().c_str())); - database->setItem(i, 3, new QTableWidgetItem(sequences[i].getSummaryFormula().c_str())); - formula.setFormula(sequences[i].getSummaryFormula()); - database->setItem(i, 4, new QTableWidgetItem()); + database->setItem(i, 2, widgetitemallocator.getNewItem()); + database->item(i, 2)->setText(sequences[i].getName().c_str()); + + database->setItem(i, 3, widgetitemallocator.getNewItem()); + database->item(i, 3)->setText(sequences[i].getSummaryFormula().c_str()); + + formula.setFormula(sequences[i].getSummaryFormula()); + database->setItem(i, 4, widgetitemallocator.getNewItem()); database->item(i, 4)->setData(Qt::DisplayRole, formula.getMass()); - database->setItem(i, 5, new QTableWidgetItem(sequences[i].getSequence().c_str())); - database->setItem(i, 6, new QTableWidgetItem(sequences[i].getNTterminalModification().c_str())); - database->setItem(i, 7, new QTableWidgetItem(sequences[i].getCTterminalModification().c_str())); - database->setItem(i, 8, new QTableWidgetItem(sequences[i].getBranchModification().c_str())); - database->setItem(i, 9, new QTableWidgetItem(sequences[i].getReference().c_str())); + + database->setItem(i, 5, widgetitemallocator.getNewItem()); + database->item(i, 5)->setText(sequences[i].getSequence().c_str()); + + database->setItem(i, 6, widgetitemallocator.getNewItem()); + database->item(i, 6)->setText(sequences[i].getNTterminalModification().c_str()); + + database->setItem(i, 7, widgetitemallocator.getNewItem()); + database->item(i, 7)->setText(sequences[i].getCTterminalModification().c_str()); + + database->setItem(i, 8, widgetitemallocator.getNewItem()); + database->item(i, 8)->setText(sequences[i].getBranchModification().c_str()); + + database->setItem(i, 9, widgetitemallocator.getNewItem()); + database->item(i, 9)->setText(sequences[i].getReference().c_str()); database->setCellWidget(i, 10, new QLabel(sequences[i].getNameWithReferenceAsHTMLString().c_str())); ((QLabel *)database->cellWidget(i, 10))->setTextFormat(Qt::RichText); ((QLabel *)database->cellWidget(i, 10))->setTextInteractionFlags(Qt::TextBrowserInteraction); ((QLabel *)database->cellWidget(i, 10))->setOpenExternalLinks(true); - if ((i == 0) || ((i - 1)/100 != i/100)) { - progress->setValue(i); - } - } + progress.setValue(i); + //if (progress.wasCanceled()) { + // break; + //} + } for (int i = 0; i < database->columnCount(); i++) { database->resizeColumnToContents(i); } - progress->setValue(sequences.size()); - progress->hide(); - + progress.setValue(sequences.size()); + } inputstream.close(); @@ -365,19 +413,18 @@ void cSequenceDatabaseWidget::saveDatabase() { } else { - progress->setLabelText("Saving the Sequence Databatase..."); - progress->setMinimum(0); - progress->setMaximum(100); - progress->setValue(1); - progress->show(); + QProgressDialog progress("Saving the Sequence Databatase...", /*"Cancel"*/0, 0, database->rowCount(), this); + cEventFilter filter; + progress.installEventFilter(&filter); + progress.setMinimumDuration(0); + progress.setWindowModality(Qt::WindowModal); cSequence seq; sequences.clear(); + string s; removeEmptyRows(); - progress->setMaximum(database->rowCount()); - for (int i = 0; i < database->rowCount(); i++) { seq.clear(); for (int j = 0; j < database->columnCount(); j++) { @@ -390,28 +437,35 @@ void cSequenceDatabaseWidget::saveDatabase() { seq.setPeptideType((peptideType)(((QComboBox *)database->cellWidget(i,j))->currentIndex())); break; case 2: - seq.setName(database->item(i,j)->text().toStdString()); + s = database->item(i,j)->text().toStdString(); + seq.setName(removeWhiteSpacesExceptSpaces(s)); break; case 3: - seq.setSummaryFormula(database->item(i,j)->text().toStdString()); + s = database->item(i,j)->text().toStdString(); + seq.setSummaryFormula(removeWhiteSpacesExceptSpaces(s)); break; case 4: // nothing to do break; case 5: - seq.setSequence(database->item(i,j)->text().toStdString()); + s = database->item(i,j)->text().toStdString(); + seq.setSequence(removeWhiteSpacesExceptSpaces(s)); break; case 6: - seq.setNTterminalModification(database->item(i,j)->text().toStdString()); + s = database->item(i,j)->text().toStdString(); + seq.setNTterminalModification(removeWhiteSpacesExceptSpaces(s)); break; case 7: - seq.setCTterminalModification(database->item(i,j)->text().toStdString()); + s = database->item(i,j)->text().toStdString(); + seq.setCTterminalModification(removeWhiteSpacesExceptSpaces(s)); break; case 8: - seq.setBranchModification(database->item(i,j)->text().toStdString()); + s = database->item(i,j)->text().toStdString(); + seq.setBranchModification(removeWhiteSpacesExceptSpaces(s)); break; case 9: - seq.setReference(database->item(i,j)->text().toStdString()); + s = database->item(i,j)->text().toStdString(); + seq.setReference(removeWhiteSpacesExceptSpaces(s)); break; default: break; @@ -419,15 +473,15 @@ void cSequenceDatabaseWidget::saveDatabase() { } sequences.push_back(seq); - if ((i == 0) || ((i - 1)/100 != i/100)) { - progress->setValue(i); - } + progress.setValue(i); + //if (progress.wasCanceled()) { + // break; + //} } sequences.storeToPlainTextStream(outputstream); - progress->setValue(database->rowCount()); - progress->hide(); + progress.setValue(progress.maximum()); } outputstream.close(); @@ -440,10 +494,11 @@ void cSequenceDatabaseWidget::saveDatabaseAs() { return; } - QString filename = QFileDialog::getSaveFileName(this, tr("Save Settings As..."), lastdir, tr("Database of Sequences (*.txt)")); - lastdir = filename; + QString filename = QFileDialog::getSaveFileName(this, tr("Save the Database of Sequences As..."), lastdir, tr("Database of Sequences (*.txt)")); - if (filename.toStdString().compare("") != 0) { + if (!filename.isEmpty()) { + lastdir = filename; + databasefile = filename; save->setText(QString(" Save '") + QString(databasefile.toStdString().substr(databasefile.toStdString().rfind('/') + 1, databasefile.toStdString().size()).c_str()) + QString("' ")); saveDatabase(); @@ -465,14 +520,14 @@ void cSequenceDatabaseWidget::addRow() { combo->setCurrentIndex((int)other); database->setCellWidget(row, 1, combo); - database->setItem(row, 2, new QTableWidgetItem()); - database->setItem(row, 3, new QTableWidgetItem()); - database->setItem(row, 4, new QTableWidgetItem()); - database->setItem(row, 5, new QTableWidgetItem()); - database->setItem(row, 6, new QTableWidgetItem()); - database->setItem(row, 7, new QTableWidgetItem()); - database->setItem(row, 8, new QTableWidgetItem()); - database->setItem(row, 9, new QTableWidgetItem()); + database->setItem(row, 2, widgetitemallocator.getNewItem()); + database->setItem(row, 3, widgetitemallocator.getNewItem()); + database->setItem(row, 4, widgetitemallocator.getNewItem()); + database->setItem(row, 5, widgetitemallocator.getNewItem()); + database->setItem(row, 6, widgetitemallocator.getNewItem()); + database->setItem(row, 7, widgetitemallocator.getNewItem()); + database->setItem(row, 8, widgetitemallocator.getNewItem()); + database->setItem(row, 9, widgetitemallocator.getNewItem()); database->setCellWidget(row, 10, new QLabel()); ((QLabel *)database->cellWidget(row, 10))->setTextFormat(Qt::RichText); diff --git a/CycloBranch/gui/cSequenceDatabaseWidget.h b/CycloBranch/gui/cSequenceDatabaseWidget.h index d568f39..204c984 100644 --- a/CycloBranch/gui/cSequenceDatabaseWidget.h +++ b/CycloBranch/gui/cSequenceDatabaseWidget.h @@ -9,9 +9,12 @@ #include #include +#include "core/utilities.h" #include "core/cSequenceDatabase.h" +#include "core/cAllocator.h" using namespace std; +using namespace boost; // forward declaration @@ -19,15 +22,11 @@ class QHBoxLayout; class QVBoxLayout; class QTableWidget; class QTableWidgetItem; -class QDialogButtonBox; class QPushButton; -class QLabel; -class QComboBox; -class QProgressDialog; /** - \brief The widget representing the dialog 'About'. + \brief Visualization of the database of sequences. */ class cSequenceDatabaseWidget : public QWidget { @@ -56,6 +55,14 @@ class cSequenceDatabaseWidget : public QWidget void closeEvent(QCloseEvent *event); + /** + \brief Insert a new row, set its peptide type and sequence. + \param peptidetypeindex an index of current peptide type + \param sequence sequence + */ + void insertRow(int peptidetypeindex, QString sequence); + + private: QWidget* parent; QPushButton* insertrow; @@ -67,7 +74,6 @@ class cSequenceDatabaseWidget : public QWidget QTableWidget* database; QHBoxLayout* buttons; QVBoxLayout* mainlayout; - QProgressDialog* progress; QString databasefile; QString lastdir; @@ -77,16 +83,29 @@ class cSequenceDatabaseWidget : public QWidget vector headersort; + cAllocator widgetitemallocator; + void deleteTable(bool enableprogress); void removeRow(int row); bool checkTable(); - bool checkFormula(int row, string& summary); + bool checkFormula(int row, const string& summary); bool checkSequence(int row); + +protected: + + + /** + \brief Handle a key press event. + \param event pointer to QKeyEvent + */ + void keyPressEvent(QKeyEvent *event); + + private slots: void closeWindow(); @@ -107,4 +126,4 @@ private slots: }; -#endif \ No newline at end of file +#endif diff --git a/CycloBranch/gui/cSpectrumDetailWidget.cpp b/CycloBranch/gui/cSpectrumDetailWidget.cpp index a3b82b3..6327cd4 100644 --- a/CycloBranch/gui/cSpectrumDetailWidget.cpp +++ b/CycloBranch/gui/cSpectrumDetailWidget.cpp @@ -5,28 +5,34 @@ #include #include #include -#include #include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include cSpectrumDetailWidget::cSpectrumDetailWidget() { - rotation = 0; - trotation = 0; parameters = 0; - preparedToShow = false; theoreticalspectrum = new cTheoreticalSpectrum(); } cSpectrumDetailWidget::cSpectrumDetailWidget(const cSpectrumDetailWidget& sd) { - rotation = 0; - trotation = 0; + *this = sd; +} + + +cSpectrumDetailWidget& cSpectrumDetailWidget::operator=(const cSpectrumDetailWidget& sd) { parameters = sd.parameters; preparedToShow = false; @@ -41,6 +47,8 @@ cSpectrumDetailWidget::cSpectrumDetailWidget(const cSpectrumDetailWidget& sd) { } setWindowTitle(sd.windowTitle()); + + return *this; } @@ -63,15 +71,15 @@ string cSpectrumDetailWidget::getDetailsAsHTMLString() { if (parameters && ((parameters->mode == denovoengine) || (parameters->mode == singlecomparison) || (parameters->mode == databasesearch))) { s += "Acronym Peptide Name:
"; - s += theoreticalspectrum->getAcronymPeptideNameWithHTMLReferences(); + s += theoreticalspectrum->getCandidate().getAcronymPeptideNameWithHTMLReferences(); s += "

"; s += "Full Peptide Name:
"; - s += theoreticalspectrum->getRealPeptideName() + "
"; + s += theoreticalspectrum->getCandidate().getRealPeptideName() + "
"; - if ((int)theoreticalspectrum->getPath().size() > 0) { + if ((int)theoreticalspectrum->getCandidate().getPathAsString().size() > 0) { s += "
"; s += "Path in the De Novo Graph:
"; - s += theoreticalspectrum->getPath(); + s += theoreticalspectrum->getCandidate().getPathAsString(); } s += "
"; @@ -80,6 +88,7 @@ string cSpectrumDetailWidget::getDetailsAsHTMLString() { s += "Unmatched Measured Peaks:
" + theoreticalspectrum->getUnmatchedPeaks() + "

"; s += "Theoretical Peaks:
" + theoreticalspectrum->getTheoreticalPeaks()->print(true); + } return s; @@ -92,39 +101,28 @@ cSpectrumDetailWidget::~cSpectrumDetailWidget() { if (preparedToShow) { - delete graphicalspectrum; - delete graphicalspectrumscroll; - - if (parameters && ((parameters->mode == denovoengine) || (parameters->mode == singlecomparison) || (parameters->mode == databasesearch))) { - delete textedit; - } + delete spectrumscene; + delete textedit; delete textbrowser; - delete zoomin; - delete zoomout; - delete normalsize; - delete zoom; - + delete labelmz; delete minmz; delete maxmz; delete setmzinterval; delete resetmzinterval; - delete mzinterval; - - delete hideunmatched; - delete hidematched; - - if (rotation) { - delete rotation; - } + delete hboxmz; + delete widgetmz; - if (trotation) { - delete trotation; - } + delete labelrotation; + delete rotation; + delete hboxrotation; + delete widgetrotation; - delete formlayout; - delete formwidget; + delete labeltrotation; + delete trotation; + delete hboxtrotation; + delete widgettrotation; if (parameters && ((parameters->mode == denovoengine) || (parameters->mode == singlecomparison) || (parameters->mode == databasesearch))) { @@ -150,14 +148,24 @@ cSpectrumDetailWidget::~cSpectrumDetailWidget() { break; } + delete actionExportPeptide; + } - delete vsplitter1; - delete vsplitter2; + delete hsplitter1; + delete hsplitter2; + + delete vsplitter; - delete hsplitter; + delete actionExportSpectrum; + delete actionZoomIn; + delete actionZoomOut; + delete actionZoomReset; + delete actionHideMatched; + delete actionHideUnmatched; + delete actionHideScrambled; + delete actionMouseMzSelection; - delete mainbox; } } @@ -171,14 +179,15 @@ void cSpectrumDetailWidget::prepareToShow(peptideType peptidetype) { if (!preparedToShow) { - hsplitter = new QSplitter(); - hsplitter->setOrientation(Qt::Horizontal); + vsplitter = new QSplitter(); + vsplitter->setOrientation(Qt::Vertical); - vsplitter1 = new QSplitter(); - vsplitter1->setOrientation(Qt::Vertical); + hsplitter1 = new QSplitter(); + hsplitter1->setOrientation(Qt::Horizontal); + + hsplitter2 = new QSplitter(); + hsplitter2->setOrientation(Qt::Horizontal); - vsplitter2 = new QSplitter(); - vsplitter2->setOrientation(Qt::Vertical); if (parameters && ((parameters->mode == denovoengine) || (parameters->mode == singlecomparison) || (parameters->mode == databasesearch))) { switch (peptidetype) @@ -204,18 +213,89 @@ void cSpectrumDetailWidget::prepareToShow(peptideType peptidetype) { } } - graphicalspectrumscroll = new QScrollArea(); - graphicalspectrum = new cGraphicalSpectrumWidget(graphicalspectrumscroll); - graphicalspectrumscroll->setWidget(graphicalspectrum); - //graphicalspectrumscroll->setWidgetResizable(true); + spectrumscene = new cSpectrumSceneWidget(this); + + toolbarExport = addToolBar(tr("Export")); + toolbarExport->setMovable(false); + toolbarExport->setFloatable(false); + + actionExportSpectrum = new QAction(QIcon(":/images/icons/54.png"), tr("Export Spectrum"), this); + actionExportSpectrum->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_E)); + actionExportSpectrum->setToolTip("Export Spectrum (Ctrl + E)"); + toolbarExport->addAction(actionExportSpectrum); + connect(actionExportSpectrum, SIGNAL(triggered()), this, SLOT(exportSpectrum())); if (parameters && ((parameters->mode == denovoengine) || (parameters->mode == singlecomparison) || (parameters->mode == databasesearch))) { - textedit = new QTextEdit(); - textedit->setReadOnly(true); - textedit->setFont(QFont("Courier", 9)); - textedit->setLineWrapMode(QTextEdit::NoWrap); + actionExportPeptide = new QAction(QIcon(":/images/icons/57.png"), tr("Export Peptide"), this); + actionExportPeptide->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_P)); + actionExportPeptide->setToolTip("Export Peptide (Ctrl + P)"); + toolbarExport->addAction(actionExportPeptide); + connect(actionExportPeptide, SIGNAL(triggered()), this, SLOT(exportPeptide())); } + toolbarZoom = addToolBar(tr("Zoom")); + toolbarZoom->setMovable(false); + toolbarZoom->setFloatable(false); + + actionZoomIn = new QAction(QIcon(":/images/icons/83.png"), tr("Zoom In"), this); + actionZoomIn->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Plus)); + actionZoomIn->setToolTip("Zoom In (Ctrl +)"); + toolbarZoom->addAction(actionZoomIn); + connect(actionZoomIn, SIGNAL(triggered()), spectrumscene, SLOT(zoomIn())); + + actionZoomOut = new QAction(QIcon(":/images/icons/82.png"), tr("Zoom Out"), this); + actionZoomOut->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Minus)); + actionZoomOut->setToolTip("Zoom Out (Ctrl -)"); + toolbarZoom->addAction(actionZoomOut); + connect(actionZoomOut, SIGNAL(triggered()), spectrumscene, SLOT(zoomOut())); + + actionZoomReset = new QAction(QIcon(":/images/icons/84.png"), tr("Reset Zoom"), this); + actionZoomReset->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_R)); + actionZoomReset->setToolTip("Zoom Reset (Ctrl + R)"); + toolbarZoom->addAction(actionZoomReset); + connect(actionZoomReset, SIGNAL(triggered()), spectrumscene, SLOT(normalSize())); + + + toolbarHide = addToolBar(tr("Show/Hide Peaks")); + toolbarHide->setMovable(false); + toolbarHide->setFloatable(false); + + actionHideMatched = new QAction(QIcon(":/images/icons/20.png"), tr("Hide Matched Peaks"), this); + actionHideMatched->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M)); + actionHideMatched->setToolTip("Hide Matched Peaks (Ctrl + M)"); + actionHideMatched->setCheckable(true); + toolbarHide->addAction(actionHideMatched); + connect(actionHideMatched, SIGNAL(toggled(bool)), spectrumscene, SLOT(hideMatchedPeaks(bool))); + + actionHideUnmatched = new QAction(QIcon(":/images/icons/81.png"), tr("Hide Unmatched Peaks"), this); + actionHideUnmatched->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_U)); + actionHideUnmatched->setToolTip("Hide Unmatched Peaks (Ctrl + U)"); + actionHideUnmatched->setCheckable(true); + toolbarHide->addAction(actionHideUnmatched); + connect(actionHideUnmatched, SIGNAL(toggled(bool)), spectrumscene, SLOT(hideUnmatchedPeaks(bool))); + + actionHideScrambled = new QAction(QIcon(":/images/icons/80.png"), tr("Hide Scrambled Peaks"), this); + actionHideScrambled->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); + actionHideScrambled->setToolTip("Hide Scrambled Peaks (Ctrl + S)"); + actionHideScrambled->setCheckable(true); + actionHideScrambled->setEnabled(false); + toolbarHide->addAction(actionHideScrambled); + + + if (parameters && ((parameters->mode == denovoengine) || (parameters->mode == singlecomparison) || (parameters->mode == databasesearch))) { + + if ((parameters->peptidetype == cyclic) && parameters->enablescrambling) { + actionHideScrambled->setEnabled(true); + connect(actionHideScrambled, SIGNAL(toggled(bool)), spectrumscene, SLOT(hideScrambledPeaks(bool))); + } + + } + + textedit = new QTextEdit(); + textedit->setReadOnly(true); + textedit->setFont(QFont("Courier", 9)); + textedit->setLineWrapMode(QTextEdit::NoWrap); + textbrowser = new QTextBrowser(); textbrowser->setReadOnly(true); textbrowser->setFont(QFont("Courier", 9)); @@ -223,22 +303,8 @@ void cSpectrumDetailWidget::prepareToShow(peptideType peptidetype) { textbrowser->setAcceptRichText(true); textbrowser->setOpenExternalLinks(true); - zoomin = new QPushButton("In"); - zoomin->setMaximumWidth(50); - connect(zoomin, SIGNAL(released()), graphicalspectrum, SLOT(zoomIn())); - zoomout = new QPushButton("Out"); - zoomout->setMaximumWidth(50); - connect(zoomout, SIGNAL(released()), graphicalspectrum, SLOT(zoomOut())); - - normalsize = new QPushButton("Reset"); - normalsize->setMaximumWidth(50); - connect(normalsize, SIGNAL(released()), graphicalspectrum, SLOT(normalSize())); - - zoom = new QHBoxLayout(); - zoom->addWidget(zoomin); - zoom->addWidget(zoomout); - zoom->addWidget(normalsize); + labelmz = new QLabel(tr("View m/z (from - to): ")); minmz = new QDoubleSpinBox(); minmz->setDecimals(6); @@ -253,39 +319,80 @@ void cSpectrumDetailWidget::prepareToShow(peptideType peptidetype) { setmzinterval = new QPushButton("Set"); setmzinterval->setMaximumWidth(50); connect(setmzinterval, SIGNAL(released()), this, SLOT(setMZInterval())); - connect(this, SIGNAL(emitMZInterval(double, double)), graphicalspectrum, SLOT(setMZInterval(double, double))); + connect(this, SIGNAL(emitMZInterval(double, double)), spectrumscene, SLOT(setMZInterval(double, double))); resetmzinterval = new QPushButton("Reset"); resetmzinterval->setMaximumWidth(50); - connect(resetmzinterval, SIGNAL(released()), graphicalspectrum, SLOT(resetMZInterval())); + connect(resetmzinterval, SIGNAL(released()), spectrumscene, SLOT(resetMZInterval())); + connect(spectrumscene, SIGNAL(updateMZInterval(double, double)), this, SLOT(updateMZInterval(double, double))); + + hboxmz = new QHBoxLayout(); + hboxmz->addSpacing(1); + hboxmz->addWidget(labelmz); + hboxmz->addSpacing(1); + hboxmz->addWidget(minmz); + hboxmz->addSpacing(1); + hboxmz->addWidget(maxmz); + hboxmz->addSpacing(1); + hboxmz->addWidget(setmzinterval); + hboxmz->addSpacing(1); + hboxmz->addWidget(resetmzinterval); + hboxmz->addSpacing(1); - mzinterval = new QHBoxLayout(); - mzinterval->addWidget(minmz); - mzinterval->addWidget(maxmz); - mzinterval->addWidget(setmzinterval); - mzinterval->addWidget(resetmzinterval); - connect(graphicalspectrum, SIGNAL(updateMZInterval(double, double)), this, SLOT(updateMZInterval(double, double))); + widgetmz = new QWidget(); + widgetmz->setLayout(hboxmz); - hideunmatched = new QCheckBox(); - connect(hideunmatched, SIGNAL(stateChanged(int)), graphicalspectrum, SLOT(hideUnmatchedPeaks(int))); + toolbarMz = addToolBar(tr("Range of m/z")); + toolbarMz->setMovable(false); + toolbarMz->setFloatable(false); - hidematched = new QCheckBox(); - connect(hidematched, SIGNAL(stateChanged(int)), graphicalspectrum, SLOT(hideMatchedPeaks(int))); + actionMouseMzSelection = new QAction(QIcon(":/images/icons/64.png"), tr("Mouse m/z Selection Tool"), this); + actionMouseMzSelection->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_T)); + actionMouseMzSelection->setToolTip("Mouse m/z Selection Tool (Ctrl + T)"); + actionMouseMzSelection->setCheckable(true); + actionMouseMzSelection->setChecked(true); + actionMouseMzSelection->setEnabled(true); + toolbarMz->addAction(actionMouseMzSelection); + connect(actionMouseMzSelection, SIGNAL(toggled(bool)), spectrumscene, SLOT(enableMouseMzSelectionTool(bool))); + + toolbarMz->addWidget(widgetmz); + + + labelrotation = new QLabel(tr("Ring break up point: ")); + rotation = new QComboBox(); + + hboxrotation = new QHBoxLayout(); + hboxrotation->addSpacing(1); + hboxrotation->addWidget(labelrotation); + hboxrotation->addSpacing(1); + hboxrotation->addWidget(rotation); + hboxrotation->addSpacing(1); + + widgetrotation = new QWidget(); + widgetrotation->setLayout(hboxrotation); + + + labeltrotation = new QLabel(tr("Linearized sequence: ")); + trotation = new QComboBox(); + + hboxtrotation = new QHBoxLayout(); + hboxtrotation->addSpacing(1); + hboxtrotation->addWidget(labeltrotation); + hboxtrotation->addSpacing(1); + hboxtrotation->addWidget(trotation); + hboxtrotation->addSpacing(1); + + widgettrotation = new QWidget(); + widgettrotation->setLayout(hboxtrotation); - formlayout = new QFormLayout(); - formlayout->addRow(tr("Zoom: "), zoom); - formlayout->addRow(tr("View m/z (from - to): "), mzinterval); - formlayout->addRow(tr("Hide matched peaks: "), hidematched); - formlayout->addRow(tr("Hide unmatched peaks: "), hideunmatched); if (parameters && ((parameters->mode == denovoengine) || (parameters->mode == singlecomparison) || (parameters->mode == databasesearch))) { // cyclic - if (parameters && theoreticalspectrum && (parameters->peptidetype == cyclic)) { - int r = (int)theoreticalspectrum->getAcronyms().size(); + if (theoreticalspectrum && (parameters->peptidetype == cyclic)) { + int r = (int)theoreticalspectrum->getCandidate().getAcronyms().size(); int hint = (int)theoreticalspectrum->getVisualCoverage().size()/(2*r); - - rotation = new QComboBox(); + rotation->addItem(tr("all")); string s; @@ -296,15 +403,18 @@ void cSpectrumDetailWidget::prepareToShow(peptideType peptidetype) { } } - connect(rotation, SIGNAL(currentIndexChanged(int)), graphicalspectrum, SLOT(rotationChanged(int))); - connect(rotation, SIGNAL(currentIndexChanged(QString)), graphicalspectrum, SLOT(rotationChanged(QString))); + connect(rotation, SIGNAL(currentIndexChanged(int)), spectrumscene, SLOT(rotationChanged(int))); + connect(rotation, SIGNAL(currentIndexChanged(QString)), spectrumscene, SLOT(rotationChanged(QString))); connect(rotation, SIGNAL(currentIndexChanged(int)), cyclicwidget, SLOT(rotationChanged(int))); - formlayout->addRow(tr("Ring break up point: "), rotation); + + toolbarRotation = addToolBar(tr("Ring break up point")); + toolbarRotation->addWidget(widgetrotation); + toolbarRotation->setMovable(false); + toolbarRotation->setFloatable(false); } // branched - if (parameters && (parameters->peptidetype == branched)) { - trotation = new QComboBox(); + if (parameters->peptidetype == branched) { trotation->addItem(tr("all")); trotation->addItem(tr("1 (left-to-right)")); trotation->addItem(tr("2 (top-to-right)")); @@ -313,17 +423,20 @@ void cSpectrumDetailWidget::prepareToShow(peptideType peptidetype) { trotation->addItem(tr("5 (top-to-left)")); trotation->addItem(tr("6 (right-to-top)")); - connect(trotation, SIGNAL(currentIndexChanged(int)), graphicalspectrum, SLOT(trotationChanged(int))); + connect(trotation, SIGNAL(currentIndexChanged(int)), spectrumscene, SLOT(trotationChanged(int))); connect(trotation, SIGNAL(currentIndexChanged(int)), branchedwidget, SLOT(trotationChanged(int))); - formlayout->addRow(tr("Linearized sequence: "), trotation); + + toolbarTrotation = addToolBar(tr("Linearized sequence")); + toolbarTrotation->addWidget(widgettrotation); + toolbarTrotation->setMovable(false); + toolbarTrotation->setFloatable(false); } - // lasso + // branch-cyclic if (parameters && theoreticalspectrum && (parameters->peptidetype == lasso)) { - int r = (int)theoreticalspectrum->getAcronyms().size() - (int)theoreticalspectrum->getCandidate().getBranchSize(); + int r = (int)theoreticalspectrum->getCandidate().getAcronyms().size() - (int)theoreticalspectrum->getCandidate().getBranchSize(); int hint = (int)theoreticalspectrum->getVisualCoverage().size()/(2*r); - rotation = new QComboBox(); rotation->addItem(tr("all")); string s; @@ -334,12 +447,15 @@ void cSpectrumDetailWidget::prepareToShow(peptideType peptidetype) { } } - connect(rotation, SIGNAL(currentIndexChanged(int)), graphicalspectrum, SLOT(rotationChanged(int))); - connect(rotation, SIGNAL(currentIndexChanged(QString)), graphicalspectrum, SLOT(rotationChanged(QString))); + connect(rotation, SIGNAL(currentIndexChanged(int)), spectrumscene, SLOT(rotationChanged(int))); + connect(rotation, SIGNAL(currentIndexChanged(QString)), spectrumscene, SLOT(rotationChanged(QString))); connect(rotation, SIGNAL(currentIndexChanged(int)), lassowidget, SLOT(rotationChanged(int))); - formlayout->addRow(tr("Ring break up point: "), rotation); - trotation = new QComboBox(); + toolbarRotation = addToolBar(tr("Ring break up point")); + toolbarRotation->addWidget(widgetrotation); + toolbarRotation->setMovable(false); + toolbarRotation->setFloatable(false); + trotation->addItem(tr("all")); trotation->addItem(tr("1 (left-to-right)")); trotation->addItem(tr("2 (top-to-right)")); @@ -348,62 +464,41 @@ void cSpectrumDetailWidget::prepareToShow(peptideType peptidetype) { trotation->addItem(tr("5 (top-to-left)")); trotation->addItem(tr("6 (right-to-top)")); - connect(trotation, SIGNAL(currentIndexChanged(int)), graphicalspectrum, SLOT(trotationChanged(int))); + connect(trotation, SIGNAL(currentIndexChanged(int)), spectrumscene, SLOT(trotationChanged(int))); connect(trotation, SIGNAL(currentIndexChanged(int)), lassowidget, SLOT(trotationChanged(int))); - formlayout->addRow(tr("Linearized sequence: "), trotation); + + toolbarTrotation = addToolBar(tr("Linearized sequence")); + toolbarTrotation->addWidget(widgettrotation); + toolbarTrotation->setMovable(false); + toolbarTrotation->setFloatable(false); } } - formwidget = new QWidget(); - formwidget->setLayout(formlayout); + hsplitter1->addWidget(spectrumscene); + hsplitter2->addWidget(textbrowser); - vsplitter1->addWidget(graphicalspectrumscroll); - vsplitter1->addWidget(textbrowser); - vsplitter1->setStretchFactor(0, 7); - vsplitter1->setStretchFactor(1, 3); + QList sizes; + sizes.push_back(100); + sizes.push_back(100); - if (parameters && ((parameters->mode == denovoengine) || (parameters->mode == singlecomparison) || (parameters->mode == databasesearch))) { + if ((parameters->mode == denovoengine) || (parameters->mode == singlecomparison) || (parameters->mode == databasesearch)) { switch (peptidetype) { case linear: - vsplitter2->addWidget(formwidget); - vsplitter2->addWidget(linearwidget); - vsplitter2->addWidget(textedit); - vsplitter2->setStretchFactor(0, 2); - vsplitter2->setStretchFactor(1, 3); - vsplitter2->setStretchFactor(2, 5); + hsplitter1->addWidget(linearwidget); break; case cyclic: - vsplitter2->addWidget(formwidget); - vsplitter2->addWidget(cyclicwidget); - vsplitter2->addWidget(textedit); - vsplitter2->setStretchFactor(0, 2); - vsplitter2->setStretchFactor(1, 3); - vsplitter2->setStretchFactor(2, 5); + hsplitter1->addWidget(cyclicwidget); break; case branched: - vsplitter2->addWidget(formwidget); - vsplitter2->addWidget(branchedwidget); - vsplitter2->addWidget(textedit); - vsplitter2->setStretchFactor(0, 2); - vsplitter2->setStretchFactor(1, 3); - vsplitter2->setStretchFactor(2, 5); + hsplitter1->addWidget(branchedwidget); break; case lasso: - vsplitter2->addWidget(formwidget); - vsplitter2->addWidget(lassowidget); - vsplitter2->addWidget(textedit); - vsplitter2->setStretchFactor(0, 2); - vsplitter2->setStretchFactor(1, 3); - vsplitter2->setStretchFactor(2, 5); + hsplitter1->addWidget(lassowidget); break; case linearpolysaccharide: - vsplitter2->addWidget(formwidget); - vsplitter2->addWidget(textedit); - vsplitter2->setStretchFactor(0, 2); - vsplitter2->setStretchFactor(1, 8); break; case other: break; @@ -411,20 +506,20 @@ void cSpectrumDetailWidget::prepareToShow(peptideType peptidetype) { break; } - } + hsplitter2->addWidget(textedit); + + hsplitter1->setSizes(sizes); + hsplitter2->setSizes(sizes); - if (parameters && (parameters->mode == dereplication)) { - vsplitter2->addWidget(formwidget); } - hsplitter->addWidget(vsplitter1); - hsplitter->addWidget(vsplitter2); - hsplitter->setStretchFactor(0, 6); - hsplitter->setStretchFactor(1, 4); - - mainbox = new QHBoxLayout(); - mainbox->addWidget(hsplitter); - setLayout(mainbox); + vsplitter->addWidget(hsplitter1); + vsplitter->addWidget(hsplitter2); + + vsplitter->setSizes(sizes); + + setCentralWidget(vsplitter); + centralWidget()->setContentsMargins(10, 10, 10, 10); resize(1280, 700); @@ -453,12 +548,12 @@ void cSpectrumDetailWidget::prepareToShow(peptideType peptidetype) { default: break; } - - textedit->setHtml(theoreticalspectrum->getCoverageBySeries().c_str()); + textedit->setHtml(theoreticalspectrum->getCoverageBySeries().c_str()); + } - graphicalspectrum->initialize(parameters, theoreticalspectrum); + spectrumscene->initialize(parameters, theoreticalspectrum); textbrowser->setHtml(getDetailsAsHTMLString().c_str()); } @@ -468,6 +563,17 @@ void cSpectrumDetailWidget::prepareToShow(peptideType peptidetype) { } +void cSpectrumDetailWidget::keyPressEvent(QKeyEvent *event) { + if(event->key() == Qt::Key_Escape) { + hide(); + } + + if(event->key() == Qt::Key_Enter) { + setMZInterval(); + } +} + + void cSpectrumDetailWidget::updateMZInterval(double minmz, double maxmz) { this->minmz->setValue(minmz); this->maxmz->setValue(maxmz); @@ -478,3 +584,189 @@ void cSpectrumDetailWidget::setMZInterval() { emit emitMZInterval(minmz->value(), maxmz->value()); } + +void cSpectrumDetailWidget::exportSpectrum() { + #if OS_TYPE == UNX + QString filename = QFileDialog::getSaveFileName(this, tr("Export Spectrum..."), "./", "PDF Files (*.pdf);; PS Files (*.ps);; PNG Files (*.png);; SVG Files (*.svg)"); + #else + QString filename = QFileDialog::getSaveFileName(this, tr("Export Spectrum..."), "./", "PDF Files (*.pdf);; PS Files (*.ps);; PNG Files (*.png)"); + #endif + if (!filename.isEmpty()) { + regex rx; + bool selected = false; + + rx = ".+\\.pdf$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + spectrumscene->exportToPDF(filename, false); + selected = true; + } + + rx = ".+\\.ps$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + spectrumscene->exportToPDF(filename, true); + selected = true; + } + + rx = ".+\\.png$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + spectrumscene->exportToPNG(filename); + selected = true; + } + + #if OS_TYPE == UNX + rx = ".+\\.svg$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + spectrumscene->exportToSVG(filename); + selected = true; + } + #endif + + if (!selected) { + QMessageBox msgBox; + QString errstr = "Unsupported file format."; + msgBox.setText(errstr); + msgBox.exec(); + } + } +} + + +void cSpectrumDetailWidget::exportPeptide() { + #if OS_TYPE == UNX + QString filename = QFileDialog::getSaveFileName(this, tr("Export Peptide..."), "./", "PDF Files (*.pdf);; PS Files (*.ps);; PNG Files (*.png);; SVG Files (*.svg)"); + #else + QString filename = QFileDialog::getSaveFileName(this, tr("Export Peptide..."), "./", "PDF Files (*.pdf);; PS Files (*.ps);; PNG Files (*.png)"); + #endif + if (!filename.isEmpty() && parameters) { + regex rx; + bool selected = false; + + switch ((peptideType)parameters->peptidetype) { + case linear: + rx = ".+\\.pdf$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + linearwidget->exportToPDF(filename, false); + selected = true; + } + + rx = ".+\\.ps$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + linearwidget->exportToPDF(filename, true); + selected = true; + } + + rx = ".+\\.png$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + linearwidget->exportToPNG(filename); + selected = true; + } + + #if OS_TYPE == UNX + rx = ".+\\.svg$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + linearwidget->exportToSVG(filename); + selected = true; + } + #endif + break; + case cyclic: + rx = ".+\\.pdf$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + cyclicwidget->exportToPDF(filename, false); + selected = true; + } + + rx = ".+\\.ps$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + cyclicwidget->exportToPDF(filename, true); + selected = true; + } + + + rx = ".+\\.png$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + cyclicwidget->exportToPNG(filename); + selected = true; + } + + #if OS_TYPE == UNX + rx = ".+\\.svg$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + cyclicwidget->exportToSVG(filename); + selected = true; + } + #endif + break; + case branched: + rx = ".+\\.pdf$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + branchedwidget->exportToPDF(filename, false); + selected = true; + } + + rx = ".+\\.ps$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + branchedwidget->exportToPDF(filename, true); + selected = true; + } + + + rx = ".+\\.png$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + branchedwidget->exportToPNG(filename); + selected = true; + } + + #if OS_TYPE == UNX + rx = ".+\\.svg$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + branchedwidget->exportToSVG(filename); + selected = true; + } + #endif + break; + case lasso: + rx = ".+\\.pdf$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + lassowidget->exportToPDF(filename, false); + selected = true; + } + + rx = ".+\\.ps$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + lassowidget->exportToPDF(filename, true); + selected = true; + } + + + rx = ".+\\.png$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + lassowidget->exportToPNG(filename); + selected = true; + } + + #if OS_TYPE == UNX + rx = ".+\\.svg$"; + if (!selected && (regex_search(filename.toStdString(), rx))) { + lassowidget->exportToSVG(filename); + selected = true; + } + #endif + break; + case linearpolysaccharide: + break; + case other: + break; + default: + break; + } + + if (!selected) { + QMessageBox msgBox; + QString errstr = "Unsupported file format."; + msgBox.setText(errstr); + msgBox.exec(); + } + } +} + diff --git a/CycloBranch/gui/cSpectrumDetailWidget.h b/CycloBranch/gui/cSpectrumDetailWidget.h index 01c528f..6c0063c 100644 --- a/CycloBranch/gui/cSpectrumDetailWidget.h +++ b/CycloBranch/gui/cSpectrumDetailWidget.h @@ -8,12 +8,13 @@ #define _CSPECTRUMDETAILWIDGET_H #include +#include #include "core/cTheoreticalSpectrum.h" #include "gui/cLinearWidget.h" #include "gui/cCyclicWidget.h" #include "gui/cBranchedWidget.h" #include "gui/cLassoWidget.h" -#include "gui/cGraphicalSpectrumWidget.h" +#include "gui/cSpectrumSceneWidget.h" // forward declaration @@ -22,18 +23,20 @@ class QTextBrowser; class QHBoxLayout; class QVBoxLayout; class QFormLayout; -class QScrollArea; class QCheckBox; class QPushButton; class QSplitter; class QComboBox; class QDoubleSpinBox; +class QToolBar; +class QAction; +class QLabel; /** \brief The class representing a widget for visualisation of a detail of a spectrum (opened after doubleclick on a row when results are reported). */ -class cSpectrumDetailWidget : public QWidget +class cSpectrumDetailWidget : public QMainWindow { Q_OBJECT @@ -53,6 +56,13 @@ class cSpectrumDetailWidget : public QWidget cSpectrumDetailWidget(const cSpectrumDetailWidget& sd); + /** + \brief Overloaded operator=. + \param sd reference to a cSpectrumDetailWidget + */ + cSpectrumDetailWidget& operator=(const cSpectrumDetailWidget& sd); + + /** \brief The destructor. */ @@ -95,26 +105,54 @@ class cSpectrumDetailWidget : public QWidget void prepareToShow(peptideType peptidetype); +protected: + + + /** + \brief Handle a key press event. + \param event pointer to QKeyEvent + */ + void keyPressEvent(QKeyEvent *event); + + private: - QHBoxLayout* zoom; - QHBoxLayout* mzinterval; - - QSplitter* hsplitter; - QSplitter* vsplitter1; - QSplitter* vsplitter2; - - QWidget* formwidget; - QFormLayout* formlayout; - QPushButton* zoomin; - QPushButton* zoomout; - QPushButton* normalsize; + QToolBar* toolbarExport; + QToolBar* toolbarZoom; + QToolBar* toolbarHide; + QToolBar* toolbarMz; + QToolBar* toolbarRotation; + QToolBar* toolbarTrotation; + + QAction* actionExportSpectrum; + QAction* actionExportPeptide; + QAction* actionZoomIn; + QAction* actionZoomOut; + QAction* actionZoomReset; + QAction* actionHideMatched; + QAction* actionHideUnmatched; + QAction* actionHideScrambled; + QAction* actionMouseMzSelection; + + QSplitter* hsplitter1; + QSplitter* hsplitter2; + QSplitter* vsplitter; + + QWidget* widgetmz; + QHBoxLayout* hboxmz; + QLabel* labelmz; QDoubleSpinBox* minmz; QDoubleSpinBox* maxmz; QPushButton* setmzinterval; QPushButton* resetmzinterval; - QCheckBox* hideunmatched; - QCheckBox* hidematched; + + QWidget* widgetrotation; + QHBoxLayout* hboxrotation; + QLabel* labelrotation; QComboBox* rotation; + + QWidget* widgettrotation; + QHBoxLayout* hboxtrotation; + QLabel* labeltrotation; QComboBox* trotation; QTextEdit* textedit; @@ -124,16 +162,14 @@ class cSpectrumDetailWidget : public QWidget cBranchedWidget* branchedwidget; cLassoWidget* lassowidget; - QScrollArea* graphicalspectrumscroll; - cGraphicalSpectrumWidget* graphicalspectrum; + cSpectrumSceneWidget* spectrumscene; cTheoreticalSpectrum* theoreticalspectrum; - QHBoxLayout* mainbox; - bool preparedToShow; cParameters* parameters; + signals: /** @@ -143,12 +179,17 @@ class cSpectrumDetailWidget : public QWidget */ void emitMZInterval(double minmz, double maxmz); + private slots: void updateMZInterval(double minmz, double maxmz); void setMZInterval(); + void exportSpectrum(); + + void exportPeptide(); + }; #endif \ No newline at end of file diff --git a/CycloBranch/gui/cSpectrumSceneWidget.cpp b/CycloBranch/gui/cSpectrumSceneWidget.cpp new file mode 100644 index 0000000..eaa1420 --- /dev/null +++ b/CycloBranch/gui/cSpectrumSceneWidget.cpp @@ -0,0 +1,646 @@ +#include "gui/cSpectrumSceneWidget.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +cSpectrumSceneWidget::cSpectrumSceneWidget(QWidget* parent) { + this->parent = parent; + parameters = 0; + theoreticalspectrum = 0; + origwidth = 500; + origheight = 200; + currentscale = 1; + hideunmatched = false; + hidematched = false; + hidescrambled = false; + factor = 0.2; + coloredrotationid = -1; + coloredrotationstring = ""; + coloredtrotationid = -1; + pressedx = -1; + pressedy = -1; + currentx = 0; + currenty = 0; + minmzratio = 0; + maxmzratio = 0; + + topmargin = 0; + bottommargin = 0; + leftmargin = 0; + rightmargin = 0; + + firstshow = true; + enablemousemzselection = true; + + scene = new QGraphicsScene(this); + + zoomgroup = new QGraphicsItemGroup(); + zoomrect = new QGraphicsRectItem(); + zoomgroup->addToGroup(zoomrect); + zoomsimpletextitem = new QGraphicsSimpleTextItem(); + zoomgroup->addToGroup(zoomsimpletextitem); + scene->addItem(zoomgroup); +} + + +cSpectrumSceneWidget::~cSpectrumSceneWidget() { + delete scene; +} + + +void cSpectrumSceneWidget::initialize(cParameters* parameters, cTheoreticalSpectrum* theoreticalspectrum) { + this->parameters = parameters; + this->theoreticalspectrum = theoreticalspectrum; + + if (parameters->mode == dereplication) { + origwidth = 800; + } + + minmzratio = 0; + maxmzratio = theoreticalspectrum->getExperimentalSpectrum().getMaximumMZRatio(); + emit updateMZInterval(minmzratio, maxmzratio); + + setScene(scene); + redrawScene(); + originalmatrix = matrix(); +} + + +void cSpectrumSceneWidget::exportToPDF(QString filename, bool postscript) { + QPrinter printer; + if (postscript) { + printer.setPaperSize(QSizeF(scene->width() + 100, scene->height() + 100), QPrinter::DevicePixel); + printer.setPageMargins (50, 50, 50, 50, QPrinter::DevicePixel); + } + else { + printer.setPaperSize(QSizeF(scene->width(), scene->height()), QPrinter::DevicePixel); + printer.setPageMargins (0, 0, 0, 0, QPrinter::DevicePixel); + } + printer.setOutputFormat(QPrinter::NativeFormat); + printer.setOutputFileName(filename); + + QPainter painter; + if (!painter.begin(&printer)) { + QMessageBox msgBox; + QString errstr = "The file cannot be created."; + #if OS_TYPE == UNX + errstr += "\nDo you have a properly configured print server (sudo apt-get install cups-pdf) ?"; + errstr += "\nIf you cannot create a ps file, you can create a pdf file and then use pdf2ps tool."; + #endif + msgBox.setText(errstr); + msgBox.exec(); + return; + } + + painter.setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing|QPainter::SmoothPixmapTransform); + scene->render(&painter); + painter.end(); +} + + +void cSpectrumSceneWidget::exportToSVG(QString filename) { + QSvgGenerator generator; + generator.setFileName(filename); + generator.setSize(QSize(scene->width(), scene->height())); + generator.setViewBox(QRect(0, 0, scene->width(), scene->height())); + + QPainter painter; + if (!painter.begin(&generator)) { + QMessageBox msgBox; + QString errstr = "The file cannot be created."; + msgBox.setText(errstr); + msgBox.exec(); + return; + } + + scene->render(&painter); + painter.end(); +} + + +void cSpectrumSceneWidget::exportToPNG(QString filename) { + QImage image(scene->width(), scene->height(), QImage::Format_ARGB32); + image.fill(Qt::white); + + QPainter painter; + if (!painter.begin(&image)) { + QMessageBox msgBox; + QString errstr = "The file cannot be created."; + msgBox.setText(errstr); + msgBox.exec(); + return; + } + + scene->render(&painter); + painter.end(); + image.save(filename); +} + + +void cSpectrumSceneWidget::wheelEvent(QWheelEvent *event) { + if (event->delta() > 0) { + zoomIn(); + } + else { + zoomOut(); + } +} + + +void cSpectrumSceneWidget::mouseMoveEvent(QMouseEvent *event) { + QGraphicsView::mouseMoveEvent(event); + + if (enablemousemzselection && (pressedx != -1) && (pressedy != -1)) { + QPointF p = mapToScene(event->x(), event->y()); + currentx = (int)p.x(); + currenty = (int)p.y(); + + updateZoomGroup(); + } +} + + +void cSpectrumSceneWidget::mouseReleaseEvent(QMouseEvent *event) { + QGraphicsView::mouseReleaseEvent(event); + + if (enablemousemzselection) { + if (pressedx == currentx) { + pressedx = -1; + currentx = -1; + + redrawScene(); + } + + if ((event->button() == Qt::LeftButton) && (pressedx != -1) && (pressedy != -1)) { + if (pressedx < leftmargin) { + pressedx = leftmargin; + } + + if (pressedx > origwidth - rightmargin) { + pressedx = origwidth - rightmargin; + } + + if (currentx < leftmargin) { + currentx = leftmargin; + } + + if (currentx > origwidth - rightmargin) { + currentx = origwidth - rightmargin; + } + + double tmpminmzratio = getMZRatioFromXPosition((pressedx < currentx)?pressedx:currentx, origwidth); + double tmpmaxmzratio = getMZRatioFromXPosition((pressedx < currentx)?currentx:pressedx, origwidth); + + minmzratio = tmpminmzratio; + maxmzratio = tmpmaxmzratio; + + emit updateMZInterval(minmzratio, maxmzratio); + + pressedx = -1; + pressedy = -1; + + redrawScene(); + } + } +} + + +void cSpectrumSceneWidget::mousePressEvent(QMouseEvent *event) { + QGraphicsView::mousePressEvent(event); + + if (enablemousemzselection) { + if (event->button() == Qt::LeftButton) { + QPointF p = mapToScene(event->x(), event->y()); + pressedx = (int)p.x(); + pressedy = (int)p.y(); + + currentx = pressedx; + currenty = pressedy; + + updateZoomGroup(); + } + + if (event->button() == Qt::RightButton) { + pressedx = -1; + pressedy = -1; + + redrawScene(); + } + + if (event->button() == Qt::MiddleButton) { + pressedx = -1; + pressedy = -1; + + resetMZInterval(); + + redrawScene(); + } + } +} + + +void cSpectrumSceneWidget::showEvent(QShowEvent *event) { + if (firstshow) { + normalSize(); + firstshow = false; + } +} + + +double cSpectrumSceneWidget::getMZRatioFromXPosition(int x, int w) { + return (double)(x - leftmargin)/(double)(w - leftmargin - rightmargin)*(maxmzratio - minmzratio) + minmzratio; +} + + +int cSpectrumSceneWidget::getXPositionFromMZRatio(double mzratio, int w) { + double val = mzratio - minmzratio; + val /= maxmzratio - minmzratio; + val *= double(w - leftmargin - rightmargin); + return (int)val + leftmargin; +} + + +void cSpectrumSceneWidget::redrawScene() { + + QGraphicsSimpleTextItem* simpletext; + QGraphicsTextItem* text; + + int x; + double y; + qreal tx, ty, tw, th, sumh; + + char tmpbuf[30]; + string s; + + int w = origwidth; + int h = origheight; + + cPeaksList visiblepeaks; + visiblepeaks.clear(); + + QList hiddenitems; + + vector hits; + + QFont myFont("Arial", 8); + QFontMetrics fm(myFont); + + // maximum intensity in the interval + double maxintensity = theoreticalspectrum->getExperimentalSpectrum().getMaximumIntensityFromMZInterval(minmzratio, maxmzratio); + + scene->removeItem(zoomgroup); + scene->clear(); + zoomgroup->setVisible(false); + scene->addItem(zoomgroup); + + // x axis + scene->addLine(leftmargin, h - bottommargin, w - rightmargin, h - bottommargin, QPen(Qt::black, 2, Qt::SolidLine)); + + // x axis ruler + scene->addLine(leftmargin, h - bottommargin, leftmargin, h - bottommargin + 10, QPen(Qt::black, 2, Qt::SolidLine)); + scene->addLine(w - rightmargin, h - bottommargin, w - rightmargin, h - bottommargin + 10, QPen(Qt::black, 2, Qt::SolidLine)); + + simpletext = scene->addSimpleText(QString::number(minmzratio), myFont); + simpletext->setPos(QPointF(leftmargin - 2, h - bottommargin + 12)); + + simpletext = scene->addSimpleText(QString::number(maxmzratio), myFont); + simpletext->setPos(QPointF(w - rightmargin - 2, h - bottommargin + 12)); + + // y axis + scene->addLine(leftmargin, h - bottommargin, leftmargin, h - bottommargin - std::max(h - topmargin - bottommargin, 5), QPen(Qt::black, 2, Qt::SolidLine)); + + // y axis ruler + scene->addLine(leftmargin - 10, h - bottommargin - std::max(h - topmargin - bottommargin, 5), leftmargin, h - bottommargin - std::max(h - topmargin - bottommargin, 5), QPen(Qt::black, 2, Qt::SolidLine)); + scene->addLine(leftmargin - 10, h - bottommargin, leftmargin, h - bottommargin, QPen(Qt::black, 2, Qt::SolidLine)); + + simpletext = scene->addSimpleText(QString::number(0), myFont); + simpletext->setPos(QPointF(leftmargin - 25, h - bottommargin + 2)); + simpletext->setRotation(-90); + + simpletext = scene->addSimpleText(QString::number(maxintensity), myFont); + simpletext->setPos(QPointF(leftmargin - 25, h - bottommargin - std::max(h - topmargin - bottommargin, 5) + 2)); + simpletext->setRotation(-90); + + // all experimental peaks + for (int i = 0; i < (int)theoreticalspectrum->getExperimentalSpectrum().size(); i++) { + + // skip peaks which are out of range + if ((theoreticalspectrum->getExperimentalSpectrum()[i].mzratio < minmzratio) || (theoreticalspectrum->getExperimentalSpectrum()[i].mzratio > maxmzratio)) { + continue; + } + + // hide unmatched peaks + if (hideunmatched && (theoreticalspectrum->getExperimentalSpectrum()[i].matched <= 0)) { + continue; + } + + // hide matched peaks + if (hidematched && (theoreticalspectrum->getExperimentalSpectrum()[i].matched > 0)) { + continue; + } + + visiblepeaks.add(theoreticalspectrum->getExperimentalSpectrum()[i]); + + } + + visiblepeaks.sortbyIntensityDesc(); + + // visible peaks only + for (int i = 0; i < (int)visiblepeaks.size(); i++) { + + x = getXPositionFromMZRatio(visiblepeaks[i].mzratio, origwidth); + + y = visiblepeaks[i].intensity/maxintensity * (h - topmargin - bottommargin); + + string coloredtrotationstring; + if (coloredtrotationid != -1) { + if (parameters->peptidetype == branched) { + coloredtrotationstring = " " + to_string(coloredtrotationid + 1) + "_"; + } + if (parameters->peptidetype == lasso) { + coloredtrotationstring = "_" + to_string(coloredtrotationid + 1) + "_"; + } + } + + hits.clear(); + + s = visiblepeaks[i].description; + int position = (int)s.find(','); + while (position != (int)string::npos) { + hits.push_back(s.substr(0, position)); + s = s.substr(position + 1); + + if (parameters->peptidetype == cyclic) { + if (visiblepeaks[i].scrambled) { + if (hidescrambled) { + hits.pop_back(); + } + } + else { + if ((coloredrotationid != -1) && (hits.back().find(coloredrotationstring) == string::npos)) { + hits.pop_back(); + } + } + } + + if ((parameters->peptidetype == branched) && (coloredtrotationid != -1) && (hits.back().find(coloredtrotationstring) == string::npos)) { + hits.pop_back(); + } + + if ((parameters->peptidetype == lasso) && (((coloredrotationid != -1) && (hits.back().find(coloredrotationstring) == string::npos)) || ((coloredtrotationid != -1) && (hits.back().find(coloredtrotationstring) == string::npos)))) { + hits.pop_back(); + } + + position = (int)s.find(','); + } + + if (s.size() > 0) { + hits.push_back(s); + + if (parameters->peptidetype == cyclic) { + if (visiblepeaks[i].scrambled) { + if (hidescrambled) { + hits.pop_back(); + } + } + else { + if ((coloredrotationid != -1) && (hits.back().find(coloredrotationstring) == string::npos)) { + hits.pop_back(); + } + } + } + + if ((parameters->peptidetype == branched) && (coloredtrotationid != -1) && (hits.back().find(coloredtrotationstring) == string::npos)) { + hits.pop_back(); + } + + if ((parameters->peptidetype == lasso) && (((coloredrotationid != -1) && (hits.back().find(coloredrotationstring) == string::npos)) || ((coloredtrotationid != -1) && (hits.back().find(coloredtrotationstring) == string::npos)))) { + hits.pop_back(); + } + } + + sprintf_s(tmpbuf,"%.3f\0",visiblepeaks[i].mzratio); + s = tmpbuf; + hits.push_back(s); + + if (hits.size() > 1) { + scene->addLine(x, h - bottommargin - 2, x, h - bottommargin - std::max((int)y, 5), QPen(Qt::red, 2, Qt::SolidLine)); + + hiddenitems.clear(); + sumh = 0; + for (vector::reverse_iterator rit = hits.rbegin(); rit != hits.rend(); ++rit) { + text = scene->addText(""); + text->setDefaultTextColor(QColor(Qt::red)); + text->setFont(myFont); + if (parameters->mode == dereplication) { + text->setTextInteractionFlags(Qt::TextBrowserInteraction); + text->setOpenExternalLinks(true); + } + text->setHtml(rit->c_str()); + tw = text->boundingRect().width(); + th = text->boundingRect().height(); + sumh += th + 1; + tx = x - 2 - 4; + ty = h - bottommargin - std::max((int)y, 5) - sumh - 4; + text->setPos(tx, ty); + + hiddenitems.append(text); + + if (scene->items(tx, ty, tw, th, Qt::IntersectsItemBoundingRect, Qt::AscendingOrder).size() > 1) { + for (int k = 0; k < (int)hiddenitems.size(); k++) { + scene->removeItem(hiddenitems[k]); + } + break; + } + } + } + else { + scene->addLine(x, h - bottommargin - 2, x, h - bottommargin - std::max((int)y, 5), QPen(Qt::black, 2, Qt::SolidLine)); + + simpletext = scene->addSimpleText(hits[0].c_str(), myFont); + tw = simpletext->boundingRect().width(); + th = simpletext->boundingRect().height(); + tx = x - 2; + ty = h - bottommargin - std::max((int)y, 5) - th - 1 - 4; + simpletext->setPos(tx, ty); + simpletext->setBrush(Qt::black); + + if (scene->items(tx, ty, tw, th, Qt::IntersectsItemBoundingRect, Qt::AscendingOrder).size() > 1) { + scene->removeItem(simpletext); + } + } + + } + + // fix the scene rectangle + scene->setSceneRect(scene->itemsBoundingRect()); + +} + + +void cSpectrumSceneWidget::updateZoomGroup() { + qreal rx1, rx2, ry1, ry2; + QFont myFont("Arial", 8); + + if (currentx < pressedx) { + rx1 = currentx; + rx2 = pressedx; + } + else { + rx1 = pressedx; + rx2 = currentx; + } + + if (currenty < pressedy) { + ry1 = currenty; + ry2 = pressedy; + } + else { + ry1 = pressedy; + ry2 = currenty; + } + + zoomrect->setPen(QPen(Qt::black, 1, Qt::DashLine)); + zoomrect->setRect(QRectF(QPointF(rx1, ry1), QPointF(rx2, ry2))); + + QString qstr = "m/z: "; + qstr += QString::number(getMZRatioFromXPosition((pressedx < currentx)?pressedx:currentx, origwidth)); + qstr += "-"; + qstr += QString::number(getMZRatioFromXPosition((pressedx < currentx)?currentx:pressedx, origwidth)); + + zoomsimpletextitem->setFont(myFont); + zoomsimpletextitem->setText(qstr); + zoomsimpletextitem->setPos(QPointF(pressedx, pressedy - 2)); + + zoomgroup->setVisible(true); +} + + +void cSpectrumSceneWidget::hideUnmatchedPeaks(bool state) { + if (state == false) { + hideunmatched = false; + } + else { + hideunmatched = true; + } + + redrawScene(); +} + + +void cSpectrumSceneWidget::hideMatchedPeaks(bool state) { + if (state == false) { + hidematched = false; + } + else { + hidematched = true; + } + + redrawScene(); +} + + +void cSpectrumSceneWidget::hideScrambledPeaks(bool state) { + if (state == false) { + hidescrambled = false; + } + else { + hidescrambled = true; + } + + redrawScene(); +} + + +void cSpectrumSceneWidget::zoomIn() { + if (currentscale < 32) { + currentscale += factor; + setMatrix(originalmatrix); + scale(currentscale, currentscale); + verticalScrollBar()->setSliderPosition(verticalScrollBar()->maximum()); + } +} + + +void cSpectrumSceneWidget::zoomOut() { + if (currentscale > 1) { + currentscale -= factor; + setMatrix(originalmatrix); + scale(currentscale, currentscale); + verticalScrollBar()->setSliderPosition(verticalScrollBar()->maximum()); + } +} + + +void cSpectrumSceneWidget::normalSize() { + currentscale = 1; + setMatrix(originalmatrix); + verticalScrollBar()->setSliderPosition(verticalScrollBar()->maximum()); +} + + +void cSpectrumSceneWidget::setMZInterval(double minmz, double maxmz) { + if (maxmz < minmz) { + double tmp = maxmz; + maxmz = minmz; + minmz = tmp; + } + + minmzratio = std::max(0.0, minmz); + maxmzratio = std::min(maxmz, theoreticalspectrum->getExperimentalSpectrum().getMaximumMZRatio()); + emit updateMZInterval(minmzratio, maxmzratio); + + redrawScene(); +} + + +void cSpectrumSceneWidget::resetMZInterval() { + minmzratio = 0; + maxmzratio = theoreticalspectrum->getExperimentalSpectrum().getMaximumMZRatio(); + emit updateMZInterval(minmzratio, maxmzratio); + + redrawScene(); +} + + +void cSpectrumSceneWidget::rotationChanged(int index) { + coloredrotationid = index - 1; + redrawScene(); +} + + +void cSpectrumSceneWidget::trotationChanged(int index) { + coloredtrotationid = index - 1; + redrawScene(); +} + + +void cSpectrumSceneWidget::rotationChanged(QString text) { + coloredrotationstring = " " + text.toStdString() + "_"; + redrawScene(); +} + + +void cSpectrumSceneWidget::enableMouseMzSelectionTool(bool enable) { + enablemousemzselection = enable; + pressedx = -1; + pressedy = -1; + + redrawScene(); +} + diff --git a/CycloBranch/gui/cSpectrumSceneWidget.h b/CycloBranch/gui/cSpectrumSceneWidget.h new file mode 100644 index 0000000..83fc912 --- /dev/null +++ b/CycloBranch/gui/cSpectrumSceneWidget.h @@ -0,0 +1,210 @@ +/** + \file cSpectrumSceneWidget.h + \brief The implementation of a widget painting a 2D mass spectrum. +*/ + + +#ifndef _CSPECTRUMSCENEWIDGET_H +#define _CSPECTRUMSCENEWIDGET_H + +#include +#include +#include + +#include "core/cTheoreticalSpectrum.h" + + +using namespace std; + + +// forward declaration +class QPaintEvent; +class QGraphicsScene; +class QMatrix; +class QGraphicsItemGroup; +class QGraphicsRectItem; +class QGraphicsSimpleTextItem; + + +/** + \brief The widget representing a 2D mass spectrum. +*/ +class cSpectrumSceneWidget : public QGraphicsView +{ + Q_OBJECT + +public: + + + /** + \brief The constructor. + \param parent pointer to a parent widget + */ + cSpectrumSceneWidget(QWidget* parent = 0); + + + /** + \brief The destructor. + */ + ~cSpectrumSceneWidget(); + + + /** + \brief Initialize the widget. + \param parameters a pointer to parameters + \param theoreticalspectrum a pointer to a theoretical spectrum + */ + void initialize(cParameters* parameters, cTheoreticalSpectrum* theoreticalspectrum); + + + /** + \brief Export spectrum scene into a PDF or a PS file. + \param filename filename + \param postscript if true then PS file is generated instead of PDF + */ + void exportToPDF(QString filename, bool postscript); + + + /** + \brief Export spectrum scene into a SVG file. + \param filename filename + */ + void exportToSVG(QString filename); + + + /** + \brief Export spectrum scene into a PNG file. + \param filename filename + */ + void exportToPNG(QString filename); + + +protected: + + + /** + \brief Handle the mouse wheel event. + \param event pointer to QWheelEvent + */ + void wheelEvent(QWheelEvent *event); + + + /** + \brief Handle the mouse move event. + \param event pointer to QMouseEvent + */ + void mouseMoveEvent(QMouseEvent *event); + + + /** + \brief Handle the mouse release event. + \param event pointer to QMouseEvent + */ + void mouseReleaseEvent(QMouseEvent *event); + + + /** + \brief Handle the mouse press event. + \param event pointer to QMouseEvent + */ + void mousePressEvent(QMouseEvent *event); + + + /** + \brief Handle the widget show event. + \param event pointer to QShowEvent + */ + void showEvent(QShowEvent *event); + + +private: + QWidget* parent; + QGraphicsScene* scene; + QMatrix originalmatrix; + + QGraphicsItemGroup* zoomgroup; + QGraphicsRectItem* zoomrect; + QGraphicsSimpleTextItem* zoomsimpletextitem; + + cParameters* parameters; + cTheoreticalSpectrum* theoreticalspectrum; + + qreal currentscale; + qreal factor; + + int origwidth; + int origheight; + + int coloredrotationid; + string coloredrotationstring; + int coloredtrotationid; + + bool hideunmatched; + bool hidematched; + bool hidescrambled; + + int pressedx; + int pressedy; + + int currentx; + int currenty; + + double minmzratio; + double maxmzratio; + + int topmargin; + int bottommargin; + int leftmargin; + int rightmargin; + + bool firstshow; + bool enablemousemzselection; + + + double getMZRatioFromXPosition(int x, int w); + + int getXPositionFromMZRatio(double mzratio, int w); + + void redrawScene(); + + void updateZoomGroup(); + + +signals: + + /** + \brief The signal is emitted when the range of m/z ratios has been changed. + \param minmz a minimum threshold of m/z ratio + \param maxmz a maximum threshold of m/z ratio + */ + void updateMZInterval(double minmz, double maxmz); + +private slots: + + void hideUnmatchedPeaks(bool state); + + void hideMatchedPeaks(bool state); + + void hideScrambledPeaks(bool state); + + void zoomIn(); + + void zoomOut(); + + void normalSize(); + + void setMZInterval(double minmz, double maxmz); + + void resetMZInterval(); + + void rotationChanged(int index); + + void trotationChanged(int index); + + void rotationChanged(QString text); + + void enableMouseMzSelectionTool(bool enable); + +}; + +#endif diff --git a/CycloBranch/images.qrc b/CycloBranch/images.qrc new file mode 100644 index 0000000..74aa3b2 --- /dev/null +++ b/CycloBranch/images.qrc @@ -0,0 +1,32 @@ + + + images/icons/2.png + images/icons/3.png + images/icons/4.png + images/icons/22.png + images/icons/26.png + images/icons/32.png + images/icons/33.png + images/icons/48.png + images/icons/52.png + images/icons/61.png + images/icons/62.png + images/icons/68.png + images/icons/73.png + images/icons/77.png + images/icons/89.png + images/icons/93.png + images/icons/96.png + images/splash.png + images/cb.png + images/icons/20.png + images/icons/81.png + images/icons/82.png + images/icons/83.png + images/icons/84.png + images/icons/80.png + images/icons/57.png + images/icons/54.png + images/icons/64.png + + diff --git a/CycloBranch/images/cb.cdr b/CycloBranch/images/cb.cdr new file mode 100644 index 0000000000000000000000000000000000000000..6efd8530fb072565eef570aeebdcb4734e4b862b GIT binary patch literal 15312 zcmeIZV|XP`zb+ix&cwEDYvN2WvCRorY)+g^Y-5s4Y)x$2w$1gf|Ji4sXYc3Q=iB@7 z^tyUA>#pwVU;T7fsmMb@VS$0cfq_}Ma7#0y2`&^Mfr0(Ag3f}OIy$(TJGinqTU%I2 z8oL@Zo0>VR$w^CRfUZkOs!6#!yEs6A?gKz8$bD1i{HKJylQSA<`_J;9TL~2hOK>nK zFhCaMKc~U}{rI1zm&RnubB+xAB|=EO32hsVJOf3jP;0laUd_ zppWgPZLnu-0Q5PucaMV#vLCn~%3~mIFYLDOHL(?#Kde8bKlD+LVb9w3R36HFut%@J zHX{J@9lZlwDX_T*|C+|>O9x795JetN78Fg-4=1E`2*V(j9>r}~j~@GL>=u|$#Ofev zCrCZm+~BF6?q2h27AJTggilCeaIGHbYqDopUer%`VHlFYpLrt3u&+S?ClNfjT~Smt zL=#bxX@YwQAu&rdWV;@OwqS=mhGPiw0Q@wtK-y_|NeIL=n35nmQh458q-(S^6pUU# zJQ$%7dm0pV5WEo<9=vqGju9aq;$XncHaIID5`;S|k|11I5SbD5FjQRdfe|(U!YuF? zDI_Dr2`Mroq&%iPwa?Qx-~?pqhx6e8Wu-0`2|+eByY-58>b)*}Qhehso2r8TH4BD+ z8+lXDUy6b;#dHR4a$-J7i89MAIj#rSZGz3$99 zYfM*?ViSLCs`%g%uyCWhv$A~Y%Er%16U`=^c!oimmMy;xJZrZMTf^jO_L#}Trt>9b z10&Bq{4(5OQTbtLi*^TkoF5;V?*SOyb zeh1T!ZbB_~9)>!zmnPo3B&YnfMj;SR{8_-R$#KdB1pS4?(f^bP1m`LPqT)rKWjWXq8+ z?gL2@vE@*Q5$Ht5{jR~bX*>#Kc3$UHcK~kWeqUar32Wfa)4!{2$D!_jGgz(?k#I@I zd5*M`3E6Yw5j-t(>L{S}H~6);(3&(bZjw%?sJ23MdQ{n8W%f-eyi_1otEcd#p+%x9 zl!cI`a#xvs;{vdeeIx7YI4~Ag1xrkY318#K80?t!(mL8i8@)J@ES7nbkP+-zy0^zR zU&z(~rzK8&u@Z3zGz4764K8+0?wNMh|E_^)eMbl@CprV_06Ls8e@b*LeO(=hf_Ch8+`J5{Gd_r|?&Zb0xq`Gn1tK=Si^=Oug zD~H>x;MDT$;%Q*6H7-ZS3#Iah$!BFYiZuy|>^7!3SP|{cQU6+fDJy=JAm4@}+-es9#9*Oo=D< zyQah1TRz8g-#KjDufSy-5To52~%_FIgrs9$C*ecszz{1oMAhQcBc8bRI^4p-}!15;-Jr* z+N2v3+F>}eQPNoY)%mLja!R5-WVw4i%<0OUy^a8G#pScdCw1Od^D36}`*ZSI zM%UdQbJ3}Mw!R#bGA85@tfu?Iy+J1h*N2{8k>=+>QsCa23sd5xrOjMnG58F$w`pi4 z!4@7KQS2RhhHxqKHQ8B3%(|XOPMr~L+ zx4!hd;+MzP0L5R2c8fh0bw(Ua3Yq2?f6@tU>ruidLaTR5iE^bnl2)c)k=Zjbx|sa_CrE`~KJQ|} zvEsyz4v(yl!TXM8K5@ZUU$0YZDOq91DPEYdQd>jh4Z{K1Lv{6kqKPE`Ayh`J=J6D~RHQ2U^_q(z(QyJE0>2%tMzhnv3>Z6Ub%tko8- zH69P4OfXOAwE(7Wn&r8+#JlDvQ#w`y7|wrrjTl7ZbnH1or&F)A*9Lj)eMh~mu8;K~ zCc65{@KcTXW4oVXYmNQ+HM7v!5Fv6sp-^UF82f8N(uXsgb`q&MvYd9`UH&Vj{CI|B z_FnJX`Xv;ZEj5B~E~VLoS^m}fkV4`S#N`_rl`UbNazwe0aEG0-?Kdcv5`-5v#cPwc zSlrqwz|3QZku55`!FarhSR$@cFJcqcCERL;NqXnD-Q#=3UdnB{7IW45BIIKZ*L9^L&+}YXk2N} z05RW=tU`1gj-v+HotL8ba++c|i<-tsvY#&;NdtOwOv;gOn*1cKQnRRk!;n{ei@F61 zQw^Q`+THbPx$HxRMkBLXTi29S!neAjJ3&pH1i_{2_e3(97|!l%m!<6|0f3)&!9Tt6 zD7Bb&XzE~jkR4&1MKCTI+<@O%kEVHBQQ--FCd-Jm0Ex|HwfI7m*q z4C6TTExuzSLuSelqo?p>U6r)=F4NpP?T|LW0Fp zsU<>%3?`mdz=4VA6g|VQ2ER!E3x-|^z6(K`19Pwh{sSFNIpCHdfEPA`h*xz2&B$QH8y^tFajM&L2R?s4 z&8V&Y=*=5BI5=4P`Ex3_JHRU6_?VAVz!vk_=^f#n{GI<@?cK(Yc3EAAmry!9I_KqP zkLI}HBB||%3KABKlz6X-pbcv6!LO>CnwsCgNm0aVDkHb+g;8kf5u!~BujfBa$K)hr zqQD?ODynXxH}bB_An5;IK{x#l+r&WU61VMN-k)tGR7cQ|fPN|NNwJ&mb9CIAoSHgv z)p8_M$NVMr>qU&#Nx~A2YF|>_5w?uC0+mLk88TDtrzANdA|f=yTQVvHAw;uEGg4*@ zPMixXG38QbQx6{@?m=!MDVN7HOkm+QGjB}W#`5@=%@fdT(#8i?HTGCL5y49F z*;H0uRA#ier zloMW*krAWcw1{Hr8X6jY|88_p>5s7OoR3pZd22vpPye&M`Zf% zymY`-NaNs!pF=MTL?t8fMG_A!1$Z2s0_bBL%H?FiObne3I5#yk^d|{=f_*_(l&dPy zWAEVfEX%aa6XU~SH<__YHqGgPniyR2IxA@KOG(8N$(0@Nu%GDq+?*S2ByrwZikne z!G_+W(Qlm@d+LRvf85$h(_%#adB!IrO?&^28zEiTF+3m(wzB_vdj0y!@91b$6bNwk zibHd>GgW|qSFQX$3y|k9g>P-qetp;_Z{14kAZv~tzb0ofW#Vh#jAj#c}WWg z43?ZS9dVbBL>hB`3c9MgYww?3QmFwt3P9t}83Z`B^yjS(PYDCVuoWn?a?y9ebMt%2 z2~mKtabQOYQW8eQoaW6PwX(G3`R13=%FgJ+tDkkM>ncq zKck%a8M@qv=r4I6eV58fylvth7P5(-%Pp=~L-Tc01wCqF=C_DD{T(}sf6OijZk*gd zxV^x5`R3&JJby>ixbu|g%~KWWg9uy}aP>jT-M%>c3#-&1Fi7}Ni0pCQeob)W4O_GL zXej*C-pDe?10fz&p^rNMvILrgvFuVo-==YwHc( zAQ?czjqQt52xu>a@G*XVkEr0_MXG7ljwD@DT~3JyKqoI8HC1ft~aKzX-s4V_##A z5YScnSQfuVW^|&M-`(kJTk{MlCMlpOrStTHpSfqMr7_d9;KG5bUtiM6=JST&8RHBg zbAoF+fjmfrh(C4$1R09QNdIxwt=mrbA6=Y^18X;Gcx~D=oe=@m0UbE4;(M3&zHX&R zk9_g9AXe=SaG%(avA9pp=yZ+AYEk@P9=w%^{j>RVfgTsfT1=92W5r@! zB#v0fS<^?};5@5um;#IqF>>p*-$B@MD8YBXOATogLVS#;D{%ABS77*OwhNvoRLE?< zw)f;14`%>IqIYD8HOjk&RTs*Xys#o7ZQ;eXN4geGOfF)*`|8%(S(90z#pSHqY2I=B ztnV(EXRS-@WD+)hhm8+e&tGexb#s0BGl%n3JjY=fu3PreW#hU&e!j`|YbX*kR|}ev z#x=*x<+P7TFnh*WS2C{^sC#XHmyH1RThe8vBV`IQv`zFBJHVa0$o3^e`sbJ>)p~?+ zwlIZB$7uT$QTnM>3{lz5n*_(4@YJ+=I7kFzDl24@gw`gb93^_^VQomyf0M;i^`fq; zZL2->+4fdNHLNOYtNd_eo63SvB2fpG)6a)1vJ7f=5Ed=mHXi0vTd2 z7R|X=eAB6T4{Gxj_9AJ|&K4`_cZ!GR5$F=W2(x`3+p}Kac!S2fVoOi2k?qS;Lp5=W z7qj^a>8{#T-6uaYv69Rf8KOrmia>9nt86`{|nOXZ+NJ94Sa2Sc^^%1a&&+zofaS zy;ckd;-aJHdCuO#H2M<_Zde1Vb)9?1pIvR=K)TQevXiV^U(vz8RZ%@5{m(fv0jxzC5nx z6P!7eZRVq7=;{@YhFW8I+V(ZBV|}KLgix`kyNQeW>K)y&F?SKV+<-vpQCxm>$#sih zF`#|J)aG^fB8LG*O=F@hrv;OE(u7;5UeL`{Tk16g}eKfc=*>&3N2Xs`FR+#OEWb@!{#cChVOFgO@ zeg2F`zaZw-zrrGra}Jhoaa;H-nd8ou~nS$sA zZ-NpC$+_n-y|%bWN)Tg2P;lr}!%_BYDQ-VeZv4;noGR+5Py-8R%B&WoueK;^biNYj zlozy}GNg3o+gTp&Zfw1kOWOSA?ZYZ$k~u-K4j*@&nF1Egi3FVQy`~Pkn`~WB&T?LE zQg1ZsNIBWmeGDmhKfvxkV%V|H9I9L`9QxkAE|F!w1ydBCM5PW#khfjT@oG0;T@Bd0)75WhoF_8}9KP@3Y zU2)keDcu$2GBBto#Sx&3kL^Yn9%>fp-q<(TnmZ&vgmtYy;^w!=Q(>h;@tqw+A2E`0 zUlra8-D^Jt=QGqJUx&Zx0M#oOM*0(LEEp;KSzOOU&EQgEb5`d|32yNoaQFGXHpwS* zuyTL(dq#9!BAnDyiZG$hM-=}U{A%| zHPq2zH>jCBB>~+?<4(ZR_+>%DIb7UG&#t+G8vbmS=<_SgE-wG0Y|i}dQ^hZT#m139 zoWxI=<4bEpLtJrc=TNY?zz3BGL!+bmt(uVwDUdoDE|!HD!I=hG2lCzK+q^8!T4Qfk z?`4=9f+=_5jq-tUkxkoB_ML9%#10$9fn4(`?fs{RERpKIG@e+H10?+pe?wsSzF>CE zkR3~biuW9O7`uH~$0Bp;Sc(S+D}iYbdh^0qwU}Ao_BayOW90~c2ZzaRo~MOu>KYx} z7iMR44DmGRGUGi)1^E>vEe%zW19KsA>97L)g~HI0*;Dw1vx5@h26%f`1Jm7l=1S#x zG3>!Rx7+HG)B*1b1HN2TInW|P=C=ouw!VCSvoyVskZ8WskxWtDFHd#^)-4SC$`M=7 zhdf89{pCvRSqF4zCHy)g<|Q=Fu%e`Xdo=zdS0)5)KN9o;8vt~%J;$hCeyu;TL04W& zHy%mk3D~*hszr6+>Pc(MN6Bcc(sEriJ)F5rN*_k=UiG3iB`-7~shHdLNJWu#mh;l2Yt%H}Bu*Nq( z&?}!AhTy&l^Ja1XRLvLjYpnJHxn!=#7TH9Z#G#A+8w=R##PMBxLcl+74quRK9gkse z2)2MQ=xUy#4sH}IbPbh@CUnAfF4X;wK0uB^B6X!{&s$i?JCMp~vqf}!> zb(bk0l-uUI%8xl7EWs`WZoqE{M1Zn@?7-$X@YYoxw#9WYHatcVe)~%C7Lb=Q|F-41 zoq3ZIwk^#}hxf^T;r_Ugt?BYc@QUVWm`W4_cY~Pi?~#nbOOjVgh3mr(z~;V0?}DxY zxr=u@D)LPXFuzj`Phyd-YG%R&5Tf>JU&!6HOBXIcho_htm^1)BUtQd(p z0sPq_$A&N2wkvnho|ajUTNB~UJ>wFojf(J~`@2uOeNv=>b*U*jlZ7&I3e~}`ISQEx zn{cOEJIDtjHl*+^zmb0F_yZpo z8I;dP44&&|3J&VxzzaKCNp>K$FLZq)6!l;7b}K-Fo1LO;Z>VY-6zV7B#b zd&siTZWq72)x8Wjfj|ij55EBf3ubV@?kB~}+tqxyD99bPdT<;ve+ph=kxlN`D84_` zR{bbc8y%%S>Vb-UyOO*T$+pt+MZXB{qe^~#dOHVHjX~E&)w4#P8XjbK*S5DRDn!#< ziePsFzd*tcG?Q{+JMy@=RLj|o@-w7P%HCju6}-x*l-2FqzOE%fG zKj}2c<1P6DGF_3;p9=;|l)wEOX_8H~^NX0lLbpXISN4XKB}MXqQL}pM6Xu2$-FL;M zi<_C3RI8JJx!@!maJzx3H%ws8WN1*izx@MsjWC`&;Kno-)o&P&(+W2)p?xD=z%zz` zWCt{yrrH7h1h_%Ui@;1CM@nJI8#knC38~S3kqdWvtD(Ft79CbCjfAhcKTrKNJ;M-M zt)bwAwShZM-=%4K^LC3`4z)g_w+W6l>L=t()DS1CW_SL6bWc^*0gwp2adL+9^z0W&2M%UJfiI5Lgt%K4Ub93sX;+2L$$N=g=%GT9I4OqBlZLC z(x{>y?Ie(*19-vMi##Ci;TOss+iAA|e0^<87lMg8Di&Kh`FeNsw?pU>6d0doBK6<4 zMB(t_sb~2~ssp3?>UqVFg2WM$5xM~ep$!mfj(o-iC88mqZy zOy0s_7rd7NH+d2m$_N9%OwF!DMOTXB!&8sOgmtjX3i{ZIpI=%L$ndgGogNMOCA?F` z`UVeSBS(NYDKG~ISZVqV-mQW}H~o?@a&~X)Hi?yBa?7>Kn=J+Wu_?#~RS)kzrUer_ z7gvwS$O`S*rm z0^-%o9|;1$O27>RN{D@toqj1wB0$aRgXhN~TXtj)^cuo=m3y2CGx?7K|F&;ZK?zj~ z4VKDXU!OOpa&j0V`_pS&sgqF{m;&>5?de-X>vwfkQ%(Nl@!m-UgCK99cgctt|&^qEIK;S7^8=1%@Ma=@+^c|lo8!HqZH zM+V-U{Sl_uED_CJ^F|j3;$u_fSwEZ??G!XK4mq(MQ-?!xjr&|I>Yd0)i7@R^-Y|Zj zfZ14Hf09Bq>=!TK_rGs`I>5)^gA9ue4hvKf1>Tn~H@YK>ch;PVj>|az3t3aqss zs=Zo6@mo@B!u;Z{fxW|k;enH6ceO+a^3ge#pi2Z#9o82YHyIQKFQ1SN1eBczJS{+e zQ1D;$s+BY3+-9Sr@MdTKtI}FY615FKLQWhgJ82-vZ(ej#1=izM7mcJ&7XaQ26M-P4 z32{ivX!Z0g4piTD>x-nNw#OSmtt_Ru+f#@?An(b9Yvc@Uru|IiMz&A?L9P_iv@k>P zEy|jHbJOkAh;i%(=@@-0I;l>p^;Fg4{R#)h$547q_M5}`?@zIbL~w}boVy|49J0Uk z!3nRrl%+%(vn_9?fHhFMAZW83#d2|iOkA`fC4!_0l!wzqiiGW5+XKa>Z`)3hjouXK zHp0Am{D6xfe?WXk#)uJGjLM(4^@Lc{H@4q{n1Ldy>hCQ4A)xMatqjod2Kr%uO8|d; z;e~C)>vFRO=`JJ!p(lq}&UJj3`M73IqigmPn{;=9{Dw&Pp^$ob!y!b6qEGj8fh#?t zHaF|*S7_NE+oc(xL<8IS&=@W{K>1<@KQ(XN<3IM!VTcIES*lThQ_)OjT`y9Z7O=hR~M=qkIm*?G;(%uI?JmOjb=(qEClzQI^HVmOWrFgl&~wcdzMz)NDs zE)pat@4E}^fi#vzO-A-^&LFbh#gm4c>33NCQUk{kvfQ?6+Yb^|7p(qxu$^>Jn6as; zsR>|?P(`9lz5U{WvDZo}%|_`We1Zh&WPom(3|^}`@lwR`mlIt<%-Glj*4EzII&z&) zVG}Z4l|iWL#+BBTVIMOmJq8vc+Sdy2(Xr8rvx3}~^P7>Vx_jP{uz|AZCPsl*UF1kw9$MikhUBGKM44I+ZJ7go|;?tZWv*AHgP}r0{IU9lhci z4B{Hhk{B?B)0r?LucK)xpr8tmsA2gK!~5RhSYZOy&&PJ;%t7qQGrCb7L_(SJVcy_# z5mFLRjB5n3FgdUTeBc>! z;kJ>tv(Hj_9P1Yhf1V=(O2Zl;CVFSOzUu1x4tEzO0Y70E6n5d?_Y>+6pS8hC%AC_P>Zp#vAerF z=r_{5-7-J2B0Y;Sqnnm8rwY0Ttf_^)!ab}UUe^n)WjlGp5YV5?)1qdU^xudPiBaPJ39%krq1Dt>SBa2 zIhZF8W(*Djp5}x}9Cn@9)4fI;#WP9ShnjjGmaLcStpw|2#zZd{)<1sC9G$Km{Xy&# zMMXOM>!|F$!V*0awt#;eXsrKyI>P+$ZOXOwS@dbZ>DxxnKrDbUB}1N(I4%UX5Hk3t z#Wz#WS*q~nvuj^^%3;x}M<(3vZXt=uV;!!bQ>f|yw!))JOZ&Qsqe6IX)w$*Tt7+9- zl$&O!OXb_?%HIj@&n>=W!|s~A4?runMGTBDV3^%dC?+ z>d~P3WjDC=VlQ^EE?&{py%+BuojgO>o8!7M{;9GTpG-@?RSZ-hk+pThK+9A3yXSr0 zMQck-TIimn`|r)U<>j=G8ZBJMyOQZ2yWy5w1{EK-g_bo987P-ca|IV8bBwM1SMU3b zaqBxdOY7)AL*7<(H?}Ub8CJT?;162OwNb{Fan)yEYp4y{anv2)^Bq8cxDr z#$7$}>YhGfw+H|Y?kA00|7mCsva5Ay^N(cHcY`hciuZxFZ^{q&j>?L#^6Q?%v$aey z=K0AF0Dq6vCmPoebz_3ot}!;hE0LARae;&Rs}D|Mc!AQ^#aqZtUC2qPT>bXqdo1f} zLod&kDQ+btB^dwc;T+D(I2mu2rOVf87o4$XsbAS+DVu8a3QAJ;6OR=hH?GCC)CU$~ zx&vfuF7A)U(=riuw+l&cPJvWzpOw3%`gIzix4G|OE%i3mW@9q9?h=%Of`S#R$C zg=+8};IlV4;c8kJdC@zc{0?@lH}ZamXeV~z66!EFyT4D_{j>qM`1(Sxx$xZIA7v>z zc6?Z+8z~v2{CAnxEEi~|<=@nhk(1Mulp)2pJA_I4ZJ6~FEAqIKRe=xw?ALA)8-av@;B+t9qM}+*xTg~59F?I7N^9G ztzWxP@~|w8cFYPqYg6(+MhX`ay`Pm}obJLc_1`Z{reJdV;*!p;r;BQc zLR1J>3XgDY-NRdQE#iDg=22uxhEc};`^#&_0QpD4?w?HqCGSvfdwJ{P{_cG!)v1w2 zo_sA<{|-+Q_sQ=;t!`4P*Jr*$Ib^Er+SWXJx;pZ=S+TT$t!v{UK-z20wJf(<7PoK668W;yFpSZo}-lA2E>NkXULP!j>a}NfVmnvCc$y5r&bJ z4O=ckrRt|?y2(*(0>4tizdoL%pM7WFm@E3Pau=&z4uJe(^yj_eI| zOX_8A^Fh!&h(J4MVM3+XxtyOHVvd|Aao(4-PTs>rsEd2(#IZ~9#xeGGV~kz_s^9#< zbnD}F<8@sF2oKZrtc&3Ig_Bh5K6Z@GAI(qW6zz|-em`zsuM_=R?x;dGh=&_u$1WEU zBGUD?W&I=jTR_9^B3AwuRnwJ2}SwU5Ey+8aw~Ea%Q3AFfxHXL#|I5s8F51 zIt}e>EpC`Gu2ZwtKZ7DZjrk`5ge@jzA1pFdllFHY&q{mPemSV#tTj~ElO_|a5d}kY4ta;N+(_?-RM=e^mxHQlqR?J?{)Q2RDoHFgQvqV=tqW=TN{8^Tm#7H1a(w5Jcz*;wS+`G@TIAQ*xeKoRD2QUa zudG6Lu2_gOSQkEL9?1gDl+sbMI;_FWd&nBXw!JFwooq2?wn*Tn(1tF>$Q|7u>lX(s zzWDoz_?n$uRKffq7@fGWUkO?SB^fM+BiNa*Gx{aV`ZRCb3o-=O`{}Ui zz%{Q6O`O_o4X)s?uvr$GYh%V!f15ljc36}gm{&qYR<(_MZAET3C2QgPHDF_P|0J-Q znx^IeSlW^4`o&L}9BQb=d6&5EtN?y~Tz33mWN>%|dvUBs2oW|g!s*6%0sf<5hjyhx zy+WXSb^6i?-qMm@Rz)SRq9h+*`sb6D(=Uvfu(j7`$OGU>DGG`$e z4s7ZoH34G0nbnWfOdop4M~Xus1vjXBq-;fpe0!nvY?Q|^`p`0u+wD2Oxgzk3{ExiB z?T)htq;TZXvOitJgz?+HEE@&idI{y*9s{*%M%ye_AFwS_ynKMy`qAOPrW?WNC#DU}mHFIjV65ZtJc2r*xON7YItbAFH3Qp9D#{2cm zeRu?pwhX&IVBOvMz~%F9*{<{N{(3@ilz_Zw-seR&o zjB7u4I}MJbDt9HAc{-|g;Bd4b#SYE+Z8bs3TRd+67Ri=X{NROIl=CmR$Hokj;#eaZ zD{b4jm-@_0HsUq>p~H33sr^Eyndy4Bx4SBGlXd%K4BR*T?^eS6ZdZ{PG@B0`Gy(9x zSqWEjfUC8Gh2uX~;#cC7Loh4S;FWI_tw6B6x3+4Yn(hOq{kJ8d0Pwh4F;Oz2`-{{D zxCd0LFR&q|{vvBTm}5=DE2!oC4CXyT9;5gpEeh=EFz>$IZp3`LVVEMuqWu&$M>7)bK0zci<}7k};5WyE34?zKBiLnsyg z8dF7a79KmB#H~I=U)hizyMkAEn+G{L^-RoEo7eU?ZM{W3Inx9DOfoQ=Q7i^`8S|Cu zwcxvm?t)v1W5?g*-WUXF^IiD3qR;IO%U8RcP#TCkDAyYy7#Kc?L9d@$3MX3vu@U__ zI-P7bQ{%rmNAQ3QF&Ais2d#G24z@1;G;e)v&G3XOtvnO`kgDVXUXt*V;>osbAOS;Sut7_> znFJFI6p1Zc23s~pzG4G5Mwi9d#ul<=*)oJ`+tZixo$s8}(=*f4GaCd;f;R{6ct?QW%HWDO2Ek?6yXc~B{`x-%g6B}S za%DGvH`@K<+k@beOQQT=1i{S3L9l97H~-$h34*&m6a;J5bo1|iO0y5%Zj ztR3FFdt!3KmsQ!!O_ztqo_aVubnrkp^78ZH1++hO@L()IwsUJZ_TtlVe*DP?J4c@z zni0Jd_kL~GcF0jSA^*Zt;n};_M7k~u55vae&pZ;#AA9;|vHZxc=fmk+Kc0}EUVBwY zj?_2$yJx%pdFAQS6@WC%fgwps}u6%KY9N*l>GVI|DA33f#10DAN)bw z3qQPCrQD}aN1xpi=jlK3^W?o>r#$=V?aBDv5FUAMNZCf)?eTj?#XIWj?}2=7zoia+ zL!Y~i{U;2=B}Mx$`rM1se~G~#^T4M)2|Z?>$CxQgdGbJ8+CqPfW1Ge{6Kxahr|j!I zUf5oKXIBJ4XIT&oEe(RfCEZQx=A=nLq$2M%63S?BkA8(4{yB_kVfg_k{=^6O;PHcZoSpzPSrLTc`CAJQ5 z>E|@eL^)zG4ViuW_wPq%58+MgZwWY*8P5{Bz-gVSW81cEZ-VYCUHRsDo-q86934NBYy%u>#-&LJ-+$QaD2;;!r|9Glap8nbQLX7XH_wC#F zKInM>TX^)hkA>4WueQo`^;{mF`o*o`v8|7)@l&v=|J26YmENgaKdIz77N2@-9mcZV zSA+W)d7oSV`2_ZvpL{z!f-!XL#iuYXZo&AuIz036cfvyl4q$x$MBH}z<}1`#&2z%J z=o~@a=huHO9DQ}?rh^9$oImmSy$PGoV7wpR`+CyvJm>7&tFRLI@P~}Y#1y+O;5;z$ z+RHN|ukV^U{qz5g%W3cNU*D%>=(l*&&TBfpYX6&`h76;Tz+&_mu@uzRTGSMf-H?I$e_q@`@IIwR<_s{t|u2JV6o%h6j z-E-fWhi{yN&;ByJ_qA|*=*O`S7>C0+4+Dea;G`MfQ;*%M`Xc*2`^*etNWUulIq~hD zi%&fHV2nR~%g4iG&pZ-hTta*gzD}-3fBVb$97`;o)9F)*7yUpV4ZpfGq`Y2!YU2;X z$$P#QmrdbX=g9UU;$IEy@6H}y&svVJ%TYEMo_X+wkk=09pkg@Tn0OG zuQMF{#Or74IgIBWoM$+m?lt3)gF6jw9iF4ibC>u?QrgAyJ7X^WDhr!!fX(y!Dw|IP z*G$>3fXlwi<6{z=TvM@coX0kXvImf^<~hogmwfo8FqjGkg0sPjpc5=p+fcAH7=#PC zrMNN@@7A*&WkjA>#GDC2bse@6tyf`-ufteS^2h5$*mNyyPI}O-xDbn&E*zlq z!@l%da6X*HfgCL|ravp?)BL~~(N7KNKZ$W+PJe*zZ`G|^@G<7ypvM7Y+NDxwro6A` z7F~B#^1Y5to#X&6??idx_#S!nh474ajUnfHUeAnee>}m3_wzjeOPj1zUAso}6!7;( z>c<%IL7mt5F=3(`*hW%4wq}#~-xc|dXX5ERWexk6^_j$c|g7~)M zkN4`aZs1Ja_HPL+C;h-S^+$c5*qbo^zAQRyxcY3%v~ z_WiP}b@p#`z0G-QFZQM3z|NCt*W;+`+4ZM*0)3&j>u+LSH9^F=)8Ap0o)J+{5b--9@Rkk{3M zk(Gwy%foPRNjQT?##2Esa5e~5j0eH;P7o{`3WBBF1~G-eE$D7YGJmS=AleQ^@*Q9i zli1WjUDO$NmW6y?bP2YPVTzr%+Q|1o^?9*ld}AzcSw+2$~0>|x!ysO@_w z>zR%d9OqFG%a4HTXTj%bY{IW-`ZO_!<#TQ(%Lw$@e*j+|H%GClYpe?VX)ov3j$zwK z>@3|?>i8@basM{-O;zNZ6(eHbXqyM9!X5GbXZUAJjl4~pwoqpk&LRumoF7*Af(`QL zbr{FZ)xx7_%IBTnds~y7Q*_;?KYMkx1Lui0a990`TwHmx9gfp0QhZ_d)5h|yeJMIt z8}ILV{^IeFcT98K0?y_bWxj<#a~@%ejjuk+mG#LvNhQ{b97 zPeX?Dog33+hj+h(x#n$ZZ5`(W&)<1%yd8aZQ^|K2{HKy>W}GdxIgmx%W7@H*lWCXOx7wGUI6t2v1^2$~&7aV&pC`Vs8mb!75d40FVstKu3I z*Ljo~w4GY_ub4~wO3Z%(cG-9pEhC5Xm^;Ec8Dh_jjEsCH8tdN={)uZ~tP@GBO(?31 z?ayIdhML1e|8bei=e#rh#q}Jr_Rywx3Tq>|egiiAX3w5I?*jKPORSl4UgsS8w@tQ4 z8Rsdvrb1!EhRJA6i4B8%$96o~ZHsy7lUOTdYbRx=AGt}j1^2%M{zEZ;$a2kxYkxV8 zIlZILZdTh_%qt5%Q(~NX_`6+B@XN8Sk0t8$wtViO^=-^M?n!M+xeIsvhiZ@G_FC8w z&vSB3la6cKpT6Z2;pmIcpl{3`qp|%cJO0E2@iBAyk^h_JzineGHjmE)f7ol&EoD<& zlZ0mj(0eO3HBU?qvc6W@nd$jEKacfY@f>H&E#?ml?sM(W?;l+o&tbFdSONaSdtPTKzGtnZ_Z5xyEXPhbt2t*w;t zxe3Q5ol}v0K9>_LGo|0gux6X<*G{1S<@u3ZHQi49C-_{hz;h=JU+K!?Z`zZVr(F{d zep9VU)bO47AIF+MO~$@Y`|!+9ZAPD}%Kset%(1P%K#V%3ZYTa@FKspD=Hy3q?^J6+ z`CM1l&Gvz z2W8!>j>qeg<4@xGn(=%R*wc|6nd9flO?RZ(kC^U<>{q<-=QA@thts*sKF@R7xWhRL zJ}2BS{IkwqllNV3?bqzjAansi& z3%;K6+F5+V>mx=0pU-vKMar&p|JNwl5&pB&#|H6A1-isk`xqsY+`^Wpk?)_tTEx+y$*;n_EKl^?- zj`irWNsO!9KQb;HOL@F@XQ)?feP(^9S2nKYs;3KiXwG_b=z>P`^15|76_keWbZIoA>VB z%SV%`KXCsi*f1~WZ^bAa%dML~Cnw?OlH$C~Yl~j@7p1@G^9$OyVZ#PKKkB&+HyZi!E{OjdJHPi?YPv^`rhg!i9s6HoW!*-;d(><~`7MaN)fu z@26){wi9T>`PPS!ei>u>`>XO$i-kh2my9+pCgOevi;I{JVX+a@L98P}iZw=9Wfb6j zDEtOyQ;0zj@2WFh9^l<6{Fcq8L(JoSb~7DhIafgOXQtg!e}6UnL82l*#MHv8!*Y$k z*d=zF_KRP{PqE(sr2Hs;g%7*F=0dIRd;P1RY7kqzPK%j_f9OwN;D)|+JvP^4=z5WB zn64Lfu=8^TY<2a?=e&@s2?Xbsi!g5dPYre_{6ihoRg)QoVKK)3DQxb={oRe!U6`;( z0oeVWy5sGD{~eDeIYEKb#SXj@{kDPj7dw%!*l1*AnQp$JaR?)mnaoF8j+qIZ@ z_W}I6Qo}D5o2KQ-IWw4!mGjYd@wE>h2-bW}9m8yG2Ak)@@t$`)mKqNhi0$H=LOy`) zZ9Kn=EoD>Z>x21vtmpBz9^^(L?l0PKOb$3R;mkF%{0^u*ttePOouou_Wy513o~mTA9UZ|-xAnJ-RU z6Jg@}!p_1uwdwYRUfq81Nu94dseR8c3%^L+4Ayn)K5$vbUIag_Ex)&?>Ai+Nz%zlR_5!{gVrye7oj#+`0Y!bEBE=04!up*zR1#kjC)^|yrlRhqcfJNhu^$TY#D3bM4zNw8*Ad( z@*LYmMo(>RZDq8Nau^4%!#3ynu}vncjIoq&r09I~ecReUy`K9`*+2gHhS+|@e@N%S zb!u6*nsv5*tmB#cvX0Q!hkIcE*TIj^MC1OXf4|kV)yx;QUDspVuVg>Ik81Ku%S-$t z4hj3yWNhW~y?C1~Wy;tmY+UubFS!e%{;YoYU_ATyjJoVUGz??1?9voozsbm?hYTfN*o{#~#A&G<+2AJ+LFa;kIw zi}vVtbKmv;PyJu9=-4YV_Z5BLBGya$@x8(~LU*I{pR`@S4l46aSiL{E?4R1SKDImZ zyPE%`5BM`?!__ zpYFG5V%st9e|y&Q?p|Hbzf4Y<}!tB4my|@In4}NuGIIn+-`oKb1`zQV^ zwEj(c2l~K5@IfitH6Mr%=VdB(luZ}=`e*uWKKj7N+HbSZ%#-n;((!KEZ06zD){cqf zX7a5g-_q-YLg#lMet{p_aIKuVrq_p^Ss2khQ{nqY_^#^twCC?X>V8?Q@4xCkkbT59 zbw05|+*|$rv)Im*bE>$H=DhNU_lB)l4-UVm%NBnW|3@aHlKQ{U0^V52)`N zAU(?*zUZJ}@I?nnJE}NXCh1V1e*Awn{Ke^@%Bufw!#(ZG3#vl$-B$Je6+QglIsC=x zkjl>Tm3*gLzD!cFTT=0h_(@Xbeg>c`KkMfq7QpWvrU;knzaTS^~iT3-f~vVL*WAc;aIGC4w@ssfZa83O{*i$u9)-IY4eo0Yg~HKZl1cd z^|X5t%d$FK@635Xu&nRfBsUM-+$xG~ik&Ymt#WV+$@ubfn{is`_MTE|bFAv()>DVK zKzUt$olm$e2t(r(=2Lv?=GwUPd!(>#Kh9_T9)+Y4wevYHO>u7|5DhA6%5MuvPlMs9 zP1Qn*N7J^{7L*2noA%X0)Ym|mysKDO+_oKo=wg~j&RDYc6^06hH zg^KFp)yJ*BPZbKZ(YPO<`r}i#kByKzXY1zG$FIL{IR{&7*i>BdzOAj-H^ph8>CwXK zv|E?`dMvB#x1C=V+tOsq+UykYs8LxRX>w_{_$p7+Tcq3YnrETeOb0iolEScZI#rwZDsLXZ77T1Hn}`|^WvW;pH<&BUkINp&a9Jm3n9(2 zwXWE=-EUbwX*>6#{L*aAihY_)UU^Y&y=tFjN3S^5r8mviwD_mB&nmBrdtJB-$(B4H z*=)7N-qtR!EKheE>w9gJO@Ez!vgtG9Z)=lPRwv)Ov9s)AU0wQnq1UFfO6=?MO;flw zf9Pd(@z8ao?bo5()Kxb2b#Utirs)qe@0*i}pO*Knmw2WwJ@#f@R=y5yy}-<}k#)W~ z<>}Mwo6s%s*Y#%Y`{v|=m&HfwTyV@bBAb?)?W^X~^w`R)>axk3dWyu}hF4da$+Jk_ zl~W$3D~@ZsJbik-D`t^)IzIQ?7JHLlm3*FG^04#di`M7q)9Z_3yR_Hwx$hc#7woES zOm4pNHeN2+Hn}QgE;^-66+LOPf-NayFZ)?(8lJE6EZsipbe^twx{Qx~SG{cKL!XIJ zM8DqF#PONe^|WcMfD5UI(P`C=xAdq9DSv(Hu}0f`t^1q>pRtTv~}O7%`P_j)Td*)=r-Hv@;>)XJ#Ec5X|qpVCRQ2$ zni#(FWw`W0#+SWh3o-Nbwxzx<`&rSgmgUk5xjO7`60?fW z>fl+0Pt&q>*xwXpRbSP?vnr=1XTa&SibGA z3$G4e_~u#%M;oS%x2;`XnGL6HWqCG~t@mwbSsq2?@;Lj%%G1?EeGz+#wDrxsi0(3N zUHQ6VyW+XFv*~q}&1z@E^--3kvuK?UK4}$336*176-X;+p* zo}7zrvrQf*>rI&|`8<79uthdcN6~u0^^q3U?b^O9w>==ZOT{SqRXanDO#>$mfg?OSr*qOm#2&MHo3B8dHQ-0 zd)ku6E3dw+KTNr%^tjq=@~e{1v#m(%iB*M*DVxVFt=`0`l26ki$jyu_ZVS(ldg!OO%*)5UVL zt*?BRPO0;yi#URrmip9{r%#W2k=T>FZ=SutON)VC?vs~}Yuop!i&!=tQdTAQ#PH3v zX*}^mTI!omnx49RnWe94?Cav}+vjO`S-z>uHdALBx2ol)9y4#ozUa6wcvX4!LSDGr z(q8cKt{PJQw7jZ?+WB5|)X z_NEQ4J~HL{dH4UTSTy!c#=jp&_c#{yRhhW=V_#o9ipH->`?9g`$A5muze?Quv0vP= z@5g_B#=q(@ugh0C=k#Tp?>~C%s_ysW*L?iS`n+naZSrNg^yQlCH@3L>D(lCwxi}W} zwXYbb;S}Z5Z{J*BNsF1!@_syIrvea1Hr%av2VUH$zeFIIKb_v2cBT=RTfM_gSo z^SJfv>+2t`F{-OwKeqM7HqW;#Y|Nc=VK6SV4$Jc*+(|lTYEX&}haqXA; z>lbC>(v(a;&i>+T`m(7QR@Gzj?&r(*iK?;ag?vBW<>M{B>qXpr=@c9KY4LvGD+ay9 z>BoI>#$E4o{XUT22XucewEcek)8oI;Vx4ABzYomzfixd2rBiKA(`ngSc8{d9e zeIDp#?CZ0tk6hLRb@Yd_T-q!bs^8fl7*IPwH$MZ)OS`-3?+{H`6Bn>rBv{x{`Q>rF z$_C3M4|M)wz#)|lmPGYkG?XE)^hfPg0oz3FV+LJu{9VJ^Fm4{%(245@RQ+HwAFGQj z7>}!i6-xh*UI2vIEE{k*Ct1IAFqsdQ8u>RH`L`MQi;VnABj3+f^S~Pn@jU-uVzmF5k?$n) zONWyAVA)`@V0khdtT6IlH1bA&Uz$8TgJov_H}b)N(P7sl^Gm``LZNv)E;o+H6-Iu| zoa28`$6IO+5E#StdJb@jyfGeONKZHbLw+KUQ$!+<;VqHp_^TK2l%abNbQ1X$Mt)5) zug)-JP&x g=4(_2f4ZF{K7U3g3`ljCK@5lD4j5?F6o|*Qc zE(nw2CP7PzQ4_A;e-}`sXw}yG`+FcsxDDl67nGYn3V=WK3cAfkialuAf|~@b+IxnD zJ)O%mZc4x{L~IY<2Bq9Aum!)~64b*JP8Rrob}a-v#vS0Yuuw5#8CWd1%-7suws~ z%oa%2f^;o%%fwNx!+`fT7igoxFjLX8e)ZpLOK{cOUEpb2+Y+Lt`$TCKSgs$LDM}Z1 zr(v&>QRVQOUNM9!%xj88@68UlpVYyl@AibPMRgMba^@>h*)xsOnyq-%1p}e4y#sF6kcmDu|s4=9)Y!-T( z52^oSgjfMHjCQYncMnyo;w(@dQZ*z6WNkDCB@PPW<|53%$UAu9?xLK{XljJGNHfqH z4WTaD*_gP9B`?TQFOCIu-Axa1ukl&|sctF{Fc*s0L+wTDYdGb4>OHla<|AwayO@G@ zXj6Sh6gi}wb@R}3Dy3W#HHsvl?rCd*dww=)@57O!`9O3L=995Dc$|*vO*OFstmbbN zEr+^l1XwFUV|+QED?fbWSjdvq@M>KT>#{;(aGQ@oi4s<27)$QeILTrLUdvrPwdx(l zfqN)I(|GAUb)D?UL5a|uPh4K>4-9b}KD7b~QIFK&$EjJL=^`LGMBs%_QH1K-*y>6U zJ4NdPR#SvoQl(1|#Oo8&fzr`a$VO+yt>PoW0 z9R+6F^s>NFz~cg-E~pB4Z19sR@TnAFD^e_?eWB$>ACY3|DPYP5h%9Uo?zVlX+c3;+ zH>Pg`kHl;TxaBuJYI#(s^|JQgOLrsogz@-f-V2<#1vYXE)ChwKm&T>s} zkxcpIH3`2}`8piA9j}#Vxt3 zbhpDyq;jX)q7sdI*h{ykWKbHKw@Tu!;_lYWFltQpT5!$Z2evStWz5v{zg8!Pi0 z8FyQ1i>|@*QoxMONLan3omkm+VQK4S`R%nsY^GHwz0y()pEhek@0zI3RVLr+R^5IE z2~W&8lkDEl7kC(rqU#cqJHEVk0p`lUyKd3whN3 zc`s%f-N-}-9xU@#o8ie?(~@bGL6NfaGj=ow%achxNzwVMcQ%EnY$zP2b^Z<=-oq;! z42RIp-@U_I%o+&poqsxP31h80-eR+v_ZiDs zH{7=1v^z9sY@{MBEXQgcf5A;l>6$Y)y8<(%y6`~KK6TFE?44eNrTUN_teTNtDwAf; zWNyc=tfZcTyiNd)eC$vM0NdJ$~wOGyg#M^M`l-&a*%IP^pow zr{q=MaR7`C)w+n*^)$1eeE`gO(}|vJ!_N0~qC|aTw>+uIn@Fb>=^zDffjkC5OWvmk zbx>h_*oiu{6{}Zr-(k$~ED6XAKl*MR8xb!d4(52m*EH@aPZmf{m$Ja@ED@~G)ds=L zsG(?GVQp=mr6NfqyviWR7%JvPtF3OK+ZiKZcU#eO+v{?iO!NU^7NKET1}q0oyQdwe zV`XwZXY!M+1p7FlsAB}4tn>_Qd!o?pn4G9|{d)$%I&6EW((Y_~sMPLkd8pRzOgU8S z`u7Zic}&Z|2?aO5crcW>vqBGP`%w*BHupbSOY!Fp0rUo)_}*O&e(yR zfq=8c=~|H82g26p>OnMz4zEIn&aO$(`8AlLRvHi)I~pTp=VP=KdQQ=n^DnNI`#CGp RcPjt@002ovPDHLkV1i$>Cfxu4 literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/2.png b/CycloBranch/images/icons/2.png new file mode 100644 index 0000000000000000000000000000000000000000..10bf7bb5d5ff61517a33eb1190304e734fd09dbe GIT binary patch literal 673 zcmV;S0$%-zP)DnJt@cxGI~kF z2P^_HiEKqBvlh!T7l50a1IAwsSRTU0xD_- zVCS((DGP6!YMk?jvw9~vEsqdlqV>DmtuuRa&&VU1f`a9597L5C3EkjCqYi%JxhAVs>mD10H;0A=h%^VEi2%{P@d_!T`{Z9&a9o z(?i79bK+f-;J$_dQk|E8&(>+CJmi_oVf0OoUb%@Plr|3F*4DWk)8Ve#ALQ;12~0LY z3+*lQD1l-QhuyVi+$);Tg4=5Ph-ObBy6wWjVY=!oXK^UF(+5q-0v6nSqnl{UlJU&} zH0UjYz^v3b$SAm_st4Kw$t<|xl8H1QSpu_Dc!%R95d#}9f5p?IDJ-a{>?ALg%P{B) z4NRb$OQG(>%Tvo)a8AR{9=qscwC_P~y#&auR<7a`ozE=>Y%uhl% z6&9AYq4#DQ3(hNfMa;L;y;~`i5>Y|2_ci)!(pfOBSVt`PGeXmR6~9x5p$C~P7`^>D zu|CTBFEFN{6*kRU78K__3z)1wa!mX?=DQ&T#K*WA*Ll+)%}nnVjH&fk00000NkvXX Hu0mjfipM&8 literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/20.png b/CycloBranch/images/icons/20.png new file mode 100644 index 0000000000000000000000000000000000000000..468a26b43ae7560c3f8edfeef81494b9101363f5 GIT binary patch literal 705 zcmV;y0zUnTP)Q zx>>Cf-C*#^F5t;+@T=AB6WyaDM?@+K5syPe!k~Nsl+EJfquETpP*fR=?E=njgXBFi z3^9;|r1e82;(!fqZi3cwpv4uuem=J)6CPeLalI9`5|n2=wc6NUpwKi(iI@X|6Iz^* z7FUsZ`yLzl!de%QkGoF$GeDn8G}#un7%-d=^q^l)Y31oGoig*J0&L+5!Fq&?trwk!gY>spvF74|2M!7 z5B54i?CbiS2TkB{PMFdfXkyLa_)kixQ_C2l`#+9>uq0SEF zT~wh@5rL}DUZfB?YY z|HhdAGAQlDVrd?2o>&t!CElUBL7JbmedNI7ZCH>NLBW!g5NQ7TYf`X8lRq4->!)?O z)y07&Ex6wtNx{RbL)0{wkj&(K#2S?q>Y2)0$DVn3ObMP7z#~nV$APFCk)LdWFW%uv zDV#ms7tT1`Wa0&jlh2Clao2_@ex>4WR(uFV1pA3I3>B4{8d;sO2E7Bnp}O5e!Ak;| zZ^vA76dj8Vn*j;o0T3DNufqs|q|U`*t)GUV+x?U3d(HBmfA6zljyYNps3p$*6OJJ> z+NsaAt57%$Y9esM@{X_f*5GDy3H$W-OxLWV@VV|~l_cHYH|v=~EU zYL+lv2^pxvKs`gI@FVvvZ+Im4Hm*yHol-MTG#=Z!IdI!eTqVVlQ5kWwASZDStc?8k zi)rW`gzL?HaKFm~OjTKLm4REUaGA6iv<9inUIIz;gP`hZ5A4XR5(m8v2i2-*rYbf( zcMiawTkYiMOIs(8Zn}zb9H{x!a3DoMsvSDe<0zU?Y0}v`DqEMegHtju;sPn2Zgu3R zir;&UI?!b=1g)u<*4=7Zl21P&xYO3gBjyU6D=npz>_zJpgI_oa_`0@Gmt^d5K2I&H zRr-n7;Ir)&uxZly;eZvJvyk9^D+h+AS2(?< znc=V~!dFh`VNtr+Z14C$KzmKWXjz7_vGf5wp&!;3Ug~ TrF~_J00000NkvXXu0mjfkDPmu literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/26.png b/CycloBranch/images/icons/26.png new file mode 100644 index 0000000000000000000000000000000000000000..1a7765a7d221541e095b5cd265e7ba608beaeffc GIT binary patch literal 709 zcmV;$0y_PPP)LQ$fvR+d^V zN1r0F7sZ-MVw18&Gk<=nq>opWCg1w2a_3pmK%YUYgc zsRe-rJQmQX+rpW(1<&Qvvy6)0!QPcqRpUxkmMLLW?|&XGSKkD zRL-vOgTq7ObPmFT#Ka(Jk5s@Mhg2w;Z20P44jOD;$}9H_gMaqRXCjK?L@JqLWQ#SK zR%7U~4K&bX<($0(h|KsjkSLaNqROfr|Dzj+;~?@lHc zRC&Qao+oAxje6~xQnuscgJMvxa|IV3=m3BBB!bgu*FOxUmcw^{6R4*?n~M&$Au`#b zhRF{w-@8h4R$Qg*Q(7f@?`;Eh*V%ae;b-89+v+iicaGK~yrx&CbAg;K$!f=Y*A7tE zja9tC{uGgkn=*@q72;F~AhYUIt+~lsgKpPO(A(=dTzte09>1*EL$X6miJ}Fvve~4e zv6s5;nu{9Xbyk2nujX+{brb#s&kM)P##YLgeHQyuhx}exHg<`{bQe0El}JuDIH==F zK9?SCL?m!l1w_G83t28t?w7{QGeMsKPQO7%!$BB~Mn}oBJ|rF<_g7Vy@ZTM3yucD$~uhGCJxvH9eOTE(et r7uIlGS(tw(cFe-gm7VH6t=;IP)~>(-N}5vop0tF1tu|HGh0T> z2GVj;9;t`aLTWIr7ViITk3t5NPD_Q7Rc+z4dJW6)7Dn=`MTIdUh@6`b1;Q~QT1PQX z0uTKY=xJilvPt?)y7aku%9P~{baMd421NUSU^_%_s~Gll^hCqH`Y9#RW0L~EH>k=O zPIV?Zca>e4wUYrig}fp#9swkYM4w9f4nG%z-FIB$UjK2++VT6cz;E@cDr1_pRA1=G zgfU*ixx{M){BJ2b4rBnW1yJjO{_Fkj&yO3^N_=}|fxUM%owk{Ib}qX_4a4Q1&X^By zR}ze;qiX;Y{X~^b$8U}dy}9JFmbeRLfn7C8(HTn@a4@F!uOECVFFRV ztm_GErJA;(@7XCnd);@HEU@F2uCt(Mp`Ep+r~wuTi1;!x3w$I1g%Zfmq9DsgdKdxk z(@0m7(^as|BcI{BDnnIfeom=n-uz4mBKn33ki|7qc2OWH<7ajg*ON!^!=e7}*N+ala<$v8fDKP)s2Wc_;64g6C!=pKfv{)?;JjlWmYU;0*C7Y2`42*9{{YHPJtSjZzbgO$ N002ovPDHLkV1mY8o_GKN literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/32.png b/CycloBranch/images/icons/32.png new file mode 100644 index 0000000000000000000000000000000000000000..fdc09e9e36d037aef9459f15dd53c364b75147db GIT binary patch literal 640 zcmV-`0)PF9P)6W#!W>}a7snJy}N)n=x+ErxH%pxc#h#EPV2}aUI z1$h%PO{qZ)DlbwKm-|4HQE9oB`*3sbJJ))7FVtn_T6WR7Jm-0SJm+wD7-wI2W7msU zV5x%f|A1`+9oU|=0dldFE)Y%!99xu#kz~S{(nrjJPLB&a+O!y|dxW%49=t0rLvEiH zOo1Tzmd65a6dE;XziUUyzzCQ;-rvnI^5H#R?J9ysn~&GE_pv%nk~|n0AA?h^Lf)Va zlgj}`vj)A|dyooOCI{LTa>y*bV5N)b!sN6cira@^Id%ux>8t3RH%KBJ`G!m(X8{x- zLJ*{+&VjLL6bu$C?vS4dqM-R8%+)Q(;AA5AR406)2u2M1utuCZd(P$_MPbWfys3S- z_#RG?A>=hxVQRPvJ&mPcP`Q#zW(?~qkR#!vf836u)}!dJc>twEwm9es5Rg$Xq!3?XzR~E%=4P)}QXe+nW{Ob3wOdI&up#aTfYUC$PD} zjOUk&u~RPn`P%%571TeWTNClwbS^wYVry$PjFmd*o*7^$y9)Jr3tnE?4OO=2*Pz=^ zVB@)NSZ|a=$YaOVBGDPtbzVc$-ZS8_xp29ISVwhXzE}#iJYyj^;R|CEH6NS45(4hB zgm&-a*JeR@rqFbV(>XRw9 zHR!j8inSFjng0GSX27fQjKRilp3O`v?_pkT&gBgUnl-Ra={_V9ZL66r+3$zE-5 z`VUlWd!)sT#ZPHzNr_fH;F>&nQnRKd&Ca1dsG^rhZ@w-NpKq90d5_f}aEJo~7(0C$ z@$WiBT}lZo;>+uF9L`GOO9P2-*%0Ci ziUBLK!^~gOlJDw-rNq96obC+^lnLPq}9M2Qk^+j+~{- zP_(uI+|ff+9SuiF*n#a7IApJ@C&FW`P!b7XLX@-LuhAu0j+J3$!t6{Hzod$;kxs^eV53GWzC{RTah9Uzj8kvb` zHbT;TWtB@wNk|S~hiU3qvbGWVi|;m!r6nmUCM#Xrc7$(M`9~hRK*-y^ni{LEqy&bh zXMu*QXQ3SP)Kv}A%nS>t!so9*VUf=;>l%`r$6J-ZX><5rZ8K-T@Yrp!k~fOhH}i10 zSeEI3GF4&d8dR2@nwH@3dQnj5GvM_m>`f0<`(E0XMOFiCpS4%SwSWm zhaySPWf@vJ4QiMWoDP`7gHhMYRV&Lc_DtQne*rMGd1IN{*Y{IFZLL+2Rkt`5VOb`j zu`KmW2BvPp;t&++&q38mX(RhedjA(Ve)xk*V>a69^0+h-nJkEfhL9Q^V?YUXPE$<- z)eTr|0*GBuW_x;cj?#7Ob^N*jIQGd$HPEz9S3!Ydi_dyvJ-wK{dJXAF1g56laAw}r zq;nTo?GET1Q6_pW8=$nQ)wlu80>j6S*1^JcxEC*09HyBsUj7Y}-Q7rqnbrnnakLbr zG|y(Yf$)45N>vpCE1Y8L^4P^o90&Sf8-tSmS9dpAJf3fT0l$*(c01+1KQMa!8zk9r z?TdWSL6g1h9lXlgxMF#^kjo$(gU;zWcX#_&K#IlX@Y%B#&7@7FyQVto3izFYty=|& z={42Wg~YXfcvn|~5f%0;z$LG!J$>-&xu)Yqysw(syKdw%l z`+9_&BB(Jr@0lyU`& z79n?e8H$^mk%%XZSa>uQJ$JS&tKl&QWk>4vv-FEstgw-yVsYZa1;J5T`ds~)FHhXs z3HyOvY}4MA6%}OF#x{u45kt;#rik5MR=sb3^k$X!0W};Uoq@{LH2M1#!M&{H=|_jJ zpSj(D-3#pIfw%5mQ%j|u-lV&}u54XrS9C!iGRL|c;CwEy;d!9zPQQS6fjzl|?8u=s f@GKjZ^Xq>DHM>kjcMRe#00000NkvXXu0mjfEu3U^ literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/4.png b/CycloBranch/images/icons/4.png new file mode 100644 index 0000000000000000000000000000000000000000..4b015b336664fd3514df3eeeb04d3cc0ce033549 GIT binary patch literal 911 zcmV;A191F_P)`tpc&=Ma#1KkFN7Sc_lDBob0O-g)N;yXQ<6%7Z$lhxNN}FS>RE+fQM<5 z+)Wi9WOZZc*!sYp1%dBhPITJ^{=oWBjk>zQAvo=T$OAe7@&$r|ZUF+1`+1&Rji$BC zi^AT)uKEjQf$t8*2b$gThV5&g-2YfDIA_YBiC#gj?*0+@fcKxUo zKYPn(3slQ!_waBsU-Y?wyVE8t3OH>Xmbhj3s(~q1)9J^ z^D2@@;qZ*TcXUd}3uCU9Ep7pe{dT;@&ZAE({rl@N?dKh#@)@o?`Om=Smf8*5UaxCV zWFF%w0*7dTusX^t+EXiI8B3e};`mr5e(JB}@Qq!q4zbLyUdbCMPFn^u2%dw3qL4$=*0N*0;j%+_L-4faH$ zJ4?`BFGFFpXcoqy+i~sYqs-8sJYpcR~9!l_6IpVg4d7clmDd*#5T`|r@DY5*}U363jm91m6XAsS6W`?{lYVDOt; zG|=cpkagm5&Sbfkj3OCJA+di|<-ocxf1#cwej2Q?afvLOZ0^4b(5JB!H~qu9%7LCQ zMyL{Wp~<7*;dJh$KbJ`3e*xw2Phmk6Pk5Sxb8ltw)6oQoX?#=|+&Ne=uw=q}kuVGU lmK{|ljcFe_y=$;s{J-B6P$bac0>1zN002ovPDHLkV1f>G!=C^E literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/48.png b/CycloBranch/images/icons/48.png new file mode 100644 index 0000000000000000000000000000000000000000..8cdcbeb097bb441746890b44c2987dac9d24e29f GIT binary patch literal 937 zcmV;a16KTrP)+qvF96~o z+^Arghf^eIA*oyKESSFaH+=1LXWw5tt{tUUd=o@V1gAG>qPEY95rM}`VEmtg5T5gI zIXn}%M9}2b^vea6R{OaghAluDS6kC`iHc_ijUs}i2e6Na@zEeOuw>xda7e;9D3{{f zHoMQ<(l;OJ%3Dfy&Qlf5h?RiLJ7``IjPUSL{wvcI!23=ols)e#MOl|VzCNs1r-+FO zzTmGzG!i95oKeJWIB5LTh_cST`*JF8Mgr>%iHdhLe10%m99HL?C(ACZdf$qc9(#G_ zNUnBAyn^;SJ4D0fGOUktyuH^A`)|HIi{>1v&)k5WY2bS)KhPut?lokN|a(JNlMw9WewJX=(m9*ZWB=YqzXWk0)mjJnZ0Ha^yf61v-3z{0WG=EHUHq{pRmwCR@(uvaE(+&Xaf6q_0a) zJiSGyNm0sapb&prxcS@>BrkGF07VV#hJJ>H>z0;x=Z&@<*0VW}2AyS2vFooTESjk* zAmHswv~e=Igoa271){*+04@S%JlMaPf7qRH;NlC$(%7!;s@%{FVc8g@v4*Sa*-6Uf z3FD+0(?WP82htHPgcpOnF&g``>YiTPS#iS)ojiWH*a)WaEgX8!lr^XDVm~9 zX^>xHhR01E2Isx4xBd@E6k{lVTD&oBzFZ=J-6t${e;AL!{a_dSUqJo7JK9Nc(uVjb zk+9PI;fk%zz70R!;|d=)DxlhMA?jy0QzWJ-A>(4p9S;j%jx_c!LN{KM6S0W#00000 LNkvXXu0mjfS{cEM literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/52.png b/CycloBranch/images/icons/52.png new file mode 100644 index 0000000000000000000000000000000000000000..8ec886f1eddfb6031c9779a217e7eef5439cd83a GIT binary patch literal 738 zcmV<80v-K{P)Y^y4i|ArdAQ6i$ zx|4xYVKl-T{b__PQd$`k+d>^%o11KBZ|CfMXXj@MQ5_B+-~01D-}^k@`y%}354A?( zHEsf+lj6237a{P7>%9^ueEKWE)H}G%S)2BmDvz#_Y~kmF>1=Z18Q%(L{}@oLilkB$ z?BcaOan9CkldNpQA5TqQwaLXUU6B+MS>ymP`Vy$L`HmXVrXq8YA#BL~0+8AJX2x#Tz^J*9wa=r`|Avrq=$?!1qvzYjkke2Lu z(TL;JAV*b>6NRF%N)^_zX&)r##-U{OUMSnpU7%%r$^)^0JBDBTIjY;zsYWEK$mpYt zJ@@@BB%>iHUv~(~8V;*EXz0g+PvVh@`#~Ik$Wg<#9l0oho~q;teepvo5r@j=BT!ni zTaN2Qm5m>xuF(99e+0+e92M~<5YmFok1&rZrE+4K_1ljFU(v)=XAq=UDB!(5n^}mu zaHNkTiv^*^(NXxMBG|I!wNS*{WFSJuk{BZu^y8zONuq2!zH*t!QjE~jer)Nk#ljG1 z$3a})54f|U$BHj*nTWTVq2<6q&|PWh97PS|ZPFT>jlgH0Z((P*z@ztuiApPqz|pp~ zV7|1^qbI7+6#+$A0w2CXcrqN?b55wnp=%~uRc(ch&RYF+pjv^pFXbH85$yd&yg^7r zQ*ZY72u^%_*-Z6~Jgm3dj4xv74Az)Br)&=o&Oka%cRMZ#r*Pn+ne44*sH)@g`FSZx zZyWDX%%}YeQU{#wypridPmfvG&jgxD$+={ma^uYz@RW1eoYmOXn+Yt|5dZZ329lN) U`JIV{ivR!s07*qoM6N<$f=+2>S^xk5 literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/54.png b/CycloBranch/images/icons/54.png new file mode 100644 index 0000000000000000000000000000000000000000..5953e5dd6602efde6201198d889c5d32f39c6523 GIT binary patch literal 718 zcmV;<0x|uGP)zSF(cqt0oayo~@!06(sMPmgx-Zuoz0}fpD z3#1BX))dk?5%qvF1^$mh(V#$2A&ZH=_^QH~FNH;Gmi1N3ELGS`&v04t3;bz$c0H7+ zfZS5XAJ9v=s)R!#wQ8BAz=?hVst5EF$`9ar%CrwBqY22bPH(t3Kk%OD*40qUWgLW* zzS7t%om2e@Wc>gS-_#fnw&#Q5C~C~3(nBh&VLG}yyZ*d!BF7Qok%qkPwIF$m;s0lmBK_}lvs+~XvbQ+ zHnX(+QdYhkax^28s9Er6YsVjRRa{){XpNO8# zo;BV?p8cu*ufP>(_}!HN@7&g8sabn@sw-dZcar3YBy=}m^#A|>07*qoM6N<$f`z72 A1poj5 literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/57.png b/CycloBranch/images/icons/57.png new file mode 100644 index 0000000000000000000000000000000000000000..f87b6b33563ab7b2a8cd25481254b1468310129f GIT binary patch literal 657 zcmV;C0&e|@P)a zN{T3Ww1P#fk3%gYB37Yk)5L5Zn{1P^yP5f%-6m-xinI;5upt|X|7N4G#9Rs=k7Lq_DlqOx&TzPUTNY4FrN8Jp`}@btC9Gb%fixYZck z6d1T2#*_Y9c=tUAQy&#Br?gATaO?dNxU=^&Hq^O+(tl%FjYG%&YVftxz}Ex=MbTm6 zeS(K$xoerxgLf^^dv%(1wtJ~05x}yP%@SI%l^TI%gTs*~7wp>VfG<%4+)f)rlNvmm z4D-22wlDjjZJ2m_-m=Sqz0_%^fQTiiNSm=Ds^t+5?{R`tvcac_4i1roUEFe7hv39K z&M&0yDNnUjr<6ci)ghJRV0YNe(SQ(Y#nprg;cp8|q$cp3H6CiE zv;dZ-xE3zNiRg%V2844{7w-@Y%*2xroek+6v71zNj@Hq4XF00000NkvXXu0mjfH;glj literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/61.png b/CycloBranch/images/icons/61.png new file mode 100644 index 0000000000000000000000000000000000000000..4d87cf0166f6c33167b975820733d60734ed2996 GIT binary patch literal 973 zcmV;;12X)HP)MjY_H%qCS{b2&4&KASeoLh}ty8(A*xY)wHx&0$G!EySp=cncF#jGc{1PjSu8mj`!mcWAUAYF8kw>S!pfWrkC zlb}jKnIUKxSGo2)8sXC?&rlJR{O@(kBR>JEl190F~4Gx801Vs zfNpB!PLm{PbXFwq0TfyC&oUFBR-jB}xIeBUYgl;e;OsTFsrS3D-)XODVH;vN`$wLf z2@>4`(2txEK=%IsPOzFxx^*WUVAw!TXMSDAu`ho)!&plqUVUHWaBE}L?(U`sakJ!= zZ6oWIYztVffS?x2Bn}cNLgj{4=2xLnrkv&Chq(m|Caxq+z0}G4$?P1DhC=E<{Uenf zBL`|xB9P04?~E#g=>i4~qeML|Qi7EN#}f59#~G5Re#g1rZcG^ILYH%*d5NuVjofxJ zCMohj%>%JLAMf9a3<+$`{h=(A>vWNWOhczprwM3MqVrSpn7^K#a167@`DRDTH;3Co zYMYEoj2(JtW3=60R@m<4(csvPX9;uQL7t^quaS z4AI^VRmK9H@9wYj2V_v677Z5}8d!|5>`1bR`{^o4kN zZ-c)&i4Uex__l3L&Hn?R`b=!!_ayBlFmZGWh3{WkA28hTiFl#!8QMo6IdmHN>5laQ zBXu8%=ihwR|A0-tpM){ny*^;{@uQ-yz1~014$nZp(7R6HV?%?%^3ZFZ#bUO2*tqy= v-@1UYn!!fy@_z4=L+^Tj?o!{`weJ4~*{G!Eyj<$J00000NkvXXu0mjf^vc{5 literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/62.png b/CycloBranch/images/icons/62.png new file mode 100644 index 0000000000000000000000000000000000000000..9dbc5c3a5008788ae3b31311056a39184ddc4e62 GIT binary patch literal 922 zcmV;L17-Y)P)1B zzI~5(UVr*E62m~Q`ZHqlf)#Is>k0`HW8kiH&lqMMdB$-1)lY`E-~KdU7|2t5D*j-G z)@&mwq`<=g)}4CB5Zim~%eQ}wzuCFj1zCAHuVNS|RCBWbe6c}+v;Z5!KVa-KF+u{G zkr6Y%ou^;@c<97^XSRR;o-qsaCjbBY?=OadnyshTZ_CmTkl2Cddp>z=h*1>=onllD{lR%RGF3UjkCF#LzO3~VUWl^~jpnStTlqc8v6C!KS8 z+iQOSuYr~wCl4=7Gqw@nVrKXc^fEIO!a$fyIe>O;x%m1|(!y&3?0~vgm=cNbhP0aGsf*8aAbs;n&Kn4SY zkAa(mfuU^fh5L7&f7U+OVD}xXfof@+R35(gylFzYtEQ!nD8t`BPy>*|4{9hc(7?pb zLnp33`rzco`Ns+NubN3Uh!B1Gy0FI+)j?idleue)sVwLu$q9uE&qxRWKaS z|BuznMwuI>pFDok6cTLaWn!!-At%kv@b@P9=d7%=c~GlGL)@7|jXv!-m{`1RYb7>0}GUx+pk40KyLIJh}1WaLCU wJ-kiy9zA@;uyfmmH9x=o%w)KPX&49q0B2S>-xfhPYybcN07*qoM6N<$f=%?nM*si- literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/64.png b/CycloBranch/images/icons/64.png new file mode 100644 index 0000000000000000000000000000000000000000..4f32fe437cc0b26a5983d20f29800f1e289b4d7f GIT binary patch literal 722 zcmV;@0xkWCP)D z4ErOo{_Vk!#6}BTBrNrmlH#y9{>9Rv4&)5G?4jDgd~k(m#2p61GVII|4ccz21O9a;}sM*UD7Co`%0 z7E;*cY{y zda7L*2~3a0+SCG-qBTr(U3$@UjMl0LkYHVU!AvMIiyH6cMGLE8E~OuC8=0s1vtB;M zH&#*s#ol^;Lf>dn9axlp7G=IvNm0SE!tNa_0#+yI=zYx3kFs<49q6q_%$?Scmi2>( zwXq#C*3V7I{JCZEtT+!URrTrySK_lN6t-Y6AAe10KTr7*EFbDtC&dN6yTb!NqU~@ z)XN}!%mGx+NB1a{($+f(xcbOF%A}80w1exO72>8t%7N$v;Hu8s^yEsH*0dEm!HV3EV58Scn9AIAmvhyR06 zcnO&59W&s{&rM}Vz%$tkgdpUJ0}PXzlNLzFvWpPMbHI}|S0FgkpHpqUbuBy@dBF=* z+BawA1HM-vozN3L1uWZg2)vV@wd%+UAf46|J_anWXaH~2 z&o|RYQZdOWlyO-61@c)Pq0pHg9X%2!%a&}vv>vsbRE%kPnWOs(22YR?oOfn;bfv*u5_e;^B zqSwt-AZntS=5j{`baj20M?%6mgpQlwrug<6SG~bE-UD1BH;qQ5g-kI*VrVLw9G|sk zw|ouUU?7(*PV3^Wt6h1%Q7=6}(z8Lxz8XG!geh@ioA5Y z%@T*mJLW4YMl-|j6w^k8R={%y+|VZndB#8Df%wE+d^#LA({Q$64R=ln%GeL{J$XsYCFq&ECj8+n3Al=pzHUsY2 zz6}Bq55Is>F`?uxNbS&}-h4BiEkJu=vBkh%HjDvhv|E8Q*2we~u`ouSfgGrF@ zX9ER_+q)x;Q+OkPz!9MdaNn+K2n=>{UkwH6d>-gbPjU4-HJp}-P@L4MCv434`_jCt o%uRlzBWzT+na`P1)TPJ$2AM}fr)xP~?f?J)07*qoM6N<$g2LKv)c^nh literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/73.png b/CycloBranch/images/icons/73.png new file mode 100644 index 0000000000000000000000000000000000000000..47fff47dca6458855cafda15d1505768d3519b94 GIT binary patch literal 859 zcmV-h1El zLes3Qh`_SeJfO5gP4i55a$R@Fnc3ah*_l>BA-cx?U*Crxyblk8QC!XokwB_?I3NZO z4)}z4MGng(LoQKdrLoYKpbln`R&4)so{$yQPRQYHyadqGC%{-tDyDRF=G~o>1H(DZ zVD=L(msZ3128M!)W^XVK3ltGFm0e^@kcKlW^6PL-psm=A2!z_=$1;g57lQWA-lql~ zv9@HdMIFv8I9-VaMd^elaLcVOWMnX9deQ`Nd=OxakF6!c()#DQv)IA+`KO!&=k}d* zcY6!9Cfz^?K#4RbBOG*+ z2qrQJ?Op|H%ija7%18bQuFS8q;uKRb#xzNE` zVVY*r5qcf?+#EO`Iwd(2I?#FDdhKt&`URYK(zzja(zv4Z*=7=G23#x;6{T-vKPT?{ zX5W0{U!DI1rXPR3-kdPLWbPa@4p9trcSo>CRZ8D?Pd4k=c2mnDM!>XVFV`lTV;`(u zltf@g8oqQ0P+nREJ)ONacj1oPTCfptMqc@bsg}6HHA^iNZKR+vf;}s#fsU^|S^dSC zcCFYDn3h*=O-_k(WGu5VhH(_UYZamFel@fxS`sXcajCX~rj2bA(vT*SrXO1TP;LES zo0Yx^}U?;-aY5t-#zEtbMGbi zziZuBX8L@I$_grZRMH+;2B>sVxlH93wCovuyes){gWYhL@H}76FzimfM#;OqfxHEo zb6t)Zx0a`NoknTDaqAzIN-pl2a(D>Gao-Z~HIXy#@J|56CAB7Se1%FOD@;pCFr*tK zbGNQth}<+S0&XvC4nI^z9nM|1;6VKq81(94i*dAqRt}%En_rd1)OXggGab zinF%An#azS^Tu_HlVQ*)g~7%roWk3bpcdXgcUn+?;SNm6#<7;R8}R#sy)?2SZ{rSL z0ID}P?2<{vm5VYGO{?ZYU_R1qF;wdC}fGjwN}i07G!Bwg1wE&Y?l_T;;{?4>#qC zv*xHX^%8=kt+!FSJQeW@Q4Dyd!y-^#DKN)$Gc@FeU+#{6$Fqfg9a>H>8QPOtQ?Vn;)OPi;AKY z7z9s=;ON(F7DNkd&#EMzusQ+G8Iit7-NQ%wiNgBY~L$zUi7>%jLOh zSluCXj8Pf!K^n)vsAQc3j)=`4#{RRL3`YcD@kvK?D>^4*N!FG{@`y7SG28t-c4x~$ zCmx?%bqm0%WlABJNB;IfLu*zoW=0!&e5@~wUWOq>O(hyWR$V1cE)!U$LM0}JtIc#n za77kpC&XcWiU`#mJ^@r!AjjF^Ai5{QNLIyNZ?lBq^5ZY)C1u&?~KM>bGZwmCt!XI|?4dY}V^Df|C=NSt|)y(TRMYXATM07*qoM6N<$f~V38 A(*OVf literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/81.png b/CycloBranch/images/icons/81.png new file mode 100644 index 0000000000000000000000000000000000000000..a00a329acbf09029b7b489a0c5c980fa880daf88 GIT binary patch literal 788 zcmV+v1MB>WP)&EiSt`^lx5 zS&kA`Z2ae27!cTCz}0D2K{ z8BpgkBES;p$b%6T%;L+NPe^_p=OKx|U^Ml@WbKB<4w}t|va&N~r=up3F&I|BFePLu zA)$Vn9-9t)g1~tKqZv%m(w(rkuB?n%UFj)pfm{K~c$mmmVQX z=x4Q(6H3WhN+=PWRnHW%Oz92knvh#tt5wr>e^>)s2;A)}SVRdOT0&~dc$7ebm6yN} zXv?3ox|UnndRzRgG0Tt8|5~!4{oTc)t43AA;T#dH2?cQoo*_BgvCD5)V)Ve%1 zuYkEcNQu@YR7!qOP_nD85)!}gGZ9ZabE0U2n1VhdBwbEsX>-U|6=f^H3#&j*14|{e zG9ps4d4!&NA*H+3t0yFz>B=25%EfKLKsE%;wBDk_B4jBOATa!Unn?C{Cn z6u%LuqeeB+U)xO>Ogmw=u=%U!h{0+fg2mQ}XM10(!0n(*uFNFX2mf*Whu|My8i4B+ S4+{Cn@E zIyDouI3S)@DNuOm%; zqx^4U?whbLrf7QLvG(i$mf4bTRJgO|$QE*qgnkH(cXJCZZXIem@Tec#zq^a!(CnhA zfrs1l5+A1EV2V<(YyOM`22IRECZ{A5Gnce{Y09bVbJ3OVh9mJ7@4y2sc}9)zs#6(3 z3u2^vAOyiAZBiI<&Irg)f5W-_Xf-$IEyx*MZxkF9sfF-y5 z^$1)uPO;_9^?At}^#+qpq2(DE;IRNY0pA0aj4{6r*mbq7;n~|EGnA%IaVQ(=^!`#& z(b}*uwK_%|$cx1wlpqiR_LvZj*M)8b_0RgB7gTh}+)h`%t87K7cOa+C+U)QE`5u!h zNT$}Xfy_({K1vE?84x%KH3Tg$?bh0-pTaQ@J9@iqK7uonJZ>VvxdCQ`QIm+p=lxWHI+;=qI)4H+b?t-nCL}rTta2teCqO)>c&tC&M@m7}2Vi;T{kB*Fp)hfUc%)sd@ja|g$TI#&NvG=cm zoS5VrbLrvS3y7Z`zI?tK=BhB{9(&M3x4-wFfSmB+t4Rpqa)n`Ds6NWyWr`LtIR`5n z{u$_rm;O=;g%&E8CF+K{dOwc#bies8pa&X%E|V5J$#_N-{s8lb4v0=3P?`V$002ov JPDHLkV1mv7swDsb literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/83.png b/CycloBranch/images/icons/83.png new file mode 100644 index 0000000000000000000000000000000000000000..113ec8783490e5c953672d3f6abcbc3cc6f6ad85 GIT binary patch literal 917 zcmV;G18V$Y~x)0$S!nYuJ*(=0c$54~bS1rgMj%HE(pq-7Q@do}5W!cuyp z1gXe~NDCpGNYHZTa#>lHDVe1%4K!tLyPbOnQZSS1e>vw|p7TFH&NA0xZ~1`@57d! zQT~rH&vht>EuS2CxHUJFrZyBAWS)()By-pxLq3GO)9gks+XgL#kH2Eai03lwk1L-T zc%VfW;76U?w?Hn~o*bM+A#Yfi_lz@)l+59PZ1_s^fF-ZC$4z#+0}g7fzJZ0!CW9() z$?=@00g^>Uvq|vJz5X~ ziFpvzHGX}5uBuJqak-1!m5Z+V2C`aJlN%K(-Dy;WOOz@)jGBhQPmV!IQy_3Mq#9E&4`x1qD*xB9L=f^ON(OJ2)$v2Qy&i!0zplDNqTqcf|28lxh1QLoyOrL9{_eEFV zH+x4v9h0Dp7{#WW*MnD_QDgqMF;ExGs4Isr17aB zMVLk+mx3mQf$G}Ueo_f(&Rf~-zJZg7pL2T#rf{`XHC4?*4dhi^xoPe3xS3Sf-IZN` z4P?bzTsf1X@I7hFjOp=e8R#P@D8A6p!MNS?T@TiF|22>mm3cLhB>|hC^-n-nIK3;eKUm1m@C20OYx rk9Kvw`!65|)t+2MhHZ@ZMU?&oW^5gZg!r;P00000NkvXXu0mjfF8ius literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/84.png b/CycloBranch/images/icons/84.png new file mode 100644 index 0000000000000000000000000000000000000000..21a14262f4cf48f74a4f7b2fd07e700326700271 GIT binary patch literal 984 zcmV;}11J26P)b}eaXVHA{>A{J#73p#D_Eh?Bv)HpQR{(;qqi7pY6O{a|MHZ{&= z_yX}QYJ#sgbyf|&m6#cUB9-dmJ1YreS~}SVN=n94lgK*3VFjSLM8w&7hHa$Ujq(k(m#)zi6&#>nv?k?dSa#tROhkKWST!eXGLxYv#A#wyFA&1byS-4p<1#q5FXi`Ixb`^g{CGAjG^zP$`uc@98t-{vVJ16Tg& z-<)q`71Ko$t&D*mu6SYJ$(H{(*%#$PBo=`bFmDnxT$h9qTx)%HyQblRJRA&FhwA4Zihi({T(GCcE7sUFiE^!u zO<=}i5UDAUWk4Jt)DX1a^?NR~{F;gdIMD6&i3lOKKz(6bWFV*F^L9mC%tt1*N~Twg zk;TV~gNGj&#u7A9#hRBpP|MYq59jewl+)Y^Q6@G+I;on*6K8M38InTqvin%)@5 z$IJZP3<}+)o}Opy>+Jqzu*>`Ce*t-D*7hZ|C?~@wV%J|N$~uTfK*s9;0000yA5jasy{FrmI42rv1`I`lgRO2zuil1peOXU?MUWT~v#hle4xwSidmHN+u2+7U2f zK#+?w@o4Wr?^o@#N(G!hhiKqqK(Q|Awhfeu;v0nF)nVmA6iqLaI8J4bs!mG&LpbH*#_SuNP=-h2WbH7(PXGTLPuxl>D@g@r6=WCRO6Juq5R>J*N-_P+ubwcKW6N~W4vtw4M{z11*| z4h+yXlrS07luAGl5b5v7`m!gO=o7Vn1cpx>XnOa2rZKak0?=pxe}GN_q_2-=BFD&ATAdJ+H8=&7=;4R=^%`c zV{Pd}Fm)rO{RQZ^9B!U=zHT^DSxHNxu;8X#E(no*lp&%BM5DB)B0#K#;^HttZ#}!j zd`&y#zWWpKjgp8d*=B`4KOgw)qZ=a(#MAN=^hxN9((FWfNHEBtYBg5I#;~?LAIb`d z{CA+wl6%MPoVZ$0TT8Q}Wk$km$w0e8#e;Nou#)TQ7&I7QmPFX04w~h$lH4nMh9>UG zz!x;Ozz0FJL6JC^VVX~y^_sT)!R~Z?0VC2QB=m!zTL1t607*qoM6N<$f-XvYxc~qF literal 0 HcmV?d00001 diff --git a/CycloBranch/images/icons/93.png b/CycloBranch/images/icons/93.png new file mode 100644 index 0000000000000000000000000000000000000000..c3bd133fbe59a6f1c743de47588ba9f7bd93107b GIT binary patch literal 980 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

    b{_l$KI9h%w$zeZ0vL!|FAs5X-ZDl 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 literal 0 HcmV?d00001 diff --git a/CycloBranch/licence.txt b/CycloBranch/licence.txt new file mode 100644 index 0000000..818433e --- /dev/null +++ b/CycloBranch/licence.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/CycloBranch/main.cpp b/CycloBranch/main.cpp index cbfb6ab..e4c75dc 100644 --- a/CycloBranch/main.cpp +++ b/CycloBranch/main.cpp @@ -1,7 +1,11 @@ #include #include #include +#include +#include +#include +#include "core/utilities.h" #include "gui/cMainWindow.h" @@ -12,9 +16,14 @@ \retval int 0 when the application finished successfully */ int main(int argc, char** argv) { - + QApplication app(argc, argv); - qRegisterMetaType("cTheoreticalSpectrum"); + Q_INIT_RESOURCE(images); + + #if OS_TYPE == UNX + setlocale(LC_NUMERIC,"C"); + chdir(linuxinstalldir.toStdString().c_str()); + #endif qRegisterMetaType("cParameters"); qRegisterMetaType >("vector"); qRegisterMetaType("peptideType"); @@ -22,9 +31,25 @@ int main(int argc, char** argv) { qRegisterMetaType("string"); qRegisterMetaType("cFragmentIons"); + QPixmap pixmap(":/images/splash.png"); + QSplashScreen splash(pixmap); + if(!pixmap.isNull()) { + splash.show(); + splash.showMessage(QObject::tr(QString(appname + " " + appversion + " is starting ...").toStdString().c_str()), Qt::AlignLeft | Qt::AlignBottom, Qt::black); + for (int i = 0; i < 50; i++) { + if (!splash.isVisible()) { + break; + } + QThread::msleep(100); + app.processEvents(); + } + } + cMainWindow mwin; mwin.show(); + splash.finish(&mwin); + return app.exec(); } diff --git a/CycloBranch/parallel/cGraphReaderThread.cpp b/CycloBranch/parallel/cGraphReaderThread.cpp index 17f4316..8c9e5da 100644 --- a/CycloBranch/parallel/cGraphReaderThread.cpp +++ b/CycloBranch/parallel/cGraphReaderThread.cpp @@ -3,7 +3,7 @@ #include "gui/cMainThread.h" -int cGraphReaderThread::getTheoreticalSpectraIter(bool cterminalstartingnode, cCandidateSet* candidates, int nodeid, vector& composition, double precursormass, int startmodifID, int endmodifID, int middlemodifID, int middlepos, vector& perspectivepath, double cummass, bool* terminatecomputation) { +int cGraphReaderThread::getCandidatesIter(bool cterminalstartingnode, cCandidateSet* candidates, int nodeid, vector& composition, double precursormass, int startmodifID, int endmodifID, int middlemodifID, int middlepos, vector& perspectivepath, double cummass, bool* terminatecomputation) { nodeEdge ne; int tmpmiddlemodifID = 0; int finish; @@ -18,10 +18,19 @@ int cGraphReaderThread::getTheoreticalSpectraIter(bool cterminalstartingnode, cC return 0; } + if ((parameters->peptidetype == lasso) && (startmodifID > 0) && (middlemodifID > 0)) { + return 0; + } + if ((*graph)[nodeid].size() > 0) { for (int i = 0; i < (int)(*graph)[nodeid].size(); i++) { + // target charge of an edge must be equal to the source charge of a following edge + if ((perspectivepath.size() > 0) && ((*graph)[nodeid][i].sourcecharge != (*graph)[perspectivepath.back().nodeid][perspectivepath.back().edgeid].targetcharge)) { + continue; + } + // accumulation of middle modifications is not allowed if (((parameters->peptidetype == branched) || (parameters->peptidetype == lasso)) && (middlemodifID != 0) && ((*graph)[nodeid][i].middlemodifID != 0)) { continue; @@ -39,7 +48,7 @@ int cGraphReaderThread::getTheoreticalSpectraIter(bool cterminalstartingnode, cC if (cycle) { continue; } - + ne.nodeid = nodeid; ne.edgeid = i; perspectivepath.push_back(ne); @@ -52,7 +61,7 @@ int cGraphReaderThread::getTheoreticalSpectraIter(bool cterminalstartingnode, cC } composition.push_back((*graph)[nodeid][i].composition); - finish = getTheoreticalSpectraIter(cterminalstartingnode, candidates, (*graph)[nodeid][i].targetnode, composition, precursormass, startmodifID, (*graph)[nodeid][i].endmodifID, tmpmiddlemodifID, middlepos, perspectivepath, cummass + (*graph)[nodeid][i].massdifference, terminatecomputation); + finish = getCandidatesIter(cterminalstartingnode, candidates, (*graph)[nodeid][i].targetnode, composition, precursormass, startmodifID, (*graph)[nodeid][i].endmodifID, tmpmiddlemodifID, middlepos, perspectivepath, cummass + (*graph)[nodeid][i].massdifference, terminatecomputation); composition.pop_back(); perspectivepath.pop_back(); @@ -77,7 +86,7 @@ int cGraphReaderThread::getTheoreticalSpectraIter(bool cterminalstartingnode, cC if ((parameters->peptidetype == branched) || (parameters->peptidetype == lasso)) { result.getSet().clear(); - candidate.prepareBranchedCandidate(result, parameters->peptidetype, terminatecomputation); + candidate.prepareBranchedCandidates(result, parameters->peptidetype, terminatecomputation); if (scanmode == 0) { candidates->lock(); for (auto i = result.getSet().begin(); i != result.getSet().end(); ++i) { @@ -132,18 +141,6 @@ int cGraphReaderThread::getTheoreticalSpectraIter(bool cterminalstartingnode, cC } -int cGraphReaderThread::reverseCTerminalCandidates(int nodeid, cCandidateSet* candidates, double precursormass, int startmodifID, bool* terminatecomputation) { - vector composition; - vector perspectivepath; - - if (getTheoreticalSpectraIter((*graph)[nodeid].checkIonAnnotation(y_ion), candidates, nodeid, composition, precursormass, startmodifID, 0, 0, -1, perspectivepath, (*graph)[nodeid].getMZRatio(), terminatecomputation) == -1) { - return -1; - } - - return 0; -} - - cGraphReaderThread::cGraphReaderThread() { graph = 0; bricksdatabasewithcombinations = 0; @@ -177,12 +174,12 @@ void cGraphReaderThread::run() { vector composition; vector perspectivepath; int startmodifID = 0; - double unchargedprecursormass = uncharge(parameters->precursormass, parameters->precursorcharge); + double unchargedprecursormass = charge(uncharge(parameters->precursormass, parameters->precursorcharge), (parameters->precursorcharge > 0)?1:-1); switch (parameters->peptidetype) { case cyclic: - if (getTheoreticalSpectraIter(false, candidates, 0, composition, unchargedprecursormass, 0, 0, 0, -1, perspectivepath, (*graph)[0].getMZRatio(), terminatecomputation) == -1) { + if (getCandidatesIter(false, candidates, 0, composition, unchargedprecursormass, 0, 0, 0, -1, perspectivepath, (*graph)[0].getMZRatio(), terminatecomputation) == -1) { // terminated return; } @@ -193,7 +190,7 @@ void cGraphReaderThread::run() { if (i - 2 > 0) { startmodifID = i - 2; } - if (reverseCTerminalCandidates(i, candidates, unchargedprecursormass, startmodifID, terminatecomputation) == -1) { + if (getCandidatesIter((*graph)[i].checkIonAnnotation(y_ion), candidates, i, composition, unchargedprecursormass, startmodifID, 0, 0, -1, perspectivepath, (*graph)[i].getMZRatio(), terminatecomputation) == -1) { // terminated return; } @@ -204,9 +201,11 @@ void cGraphReaderThread::run() { if (i - 1/*2*/ > 0) { startmodifID = i - 1/*2*/; } - if (reverseCTerminalCandidates(i, candidates, unchargedprecursormass, startmodifID, terminatecomputation) == -1) { - // terminated - return; + if (parameters->searchedmodifications[startmodifID].nterminal) { + if (getCandidatesIter((*graph)[i].checkIonAnnotation(y_ion), candidates, i, composition, unchargedprecursormass, startmodifID, 0, 0, -1, perspectivepath, (*graph)[i].getMZRatio(), terminatecomputation) == -1) { + // terminated + return; + } } } break; @@ -215,7 +214,7 @@ void cGraphReaderThread::run() { if (i - 1 > 0) { startmodifID = i - 1; } - if (reverseCTerminalCandidates(i, candidates, unchargedprecursormass, startmodifID, terminatecomputation) == -1) { + if (getCandidatesIter((*graph)[i].checkIonAnnotation(y_ion), candidates, i, composition, unchargedprecursormass, startmodifID, 0, 0, -1, perspectivepath, (*graph)[i].getMZRatio(), terminatecomputation) == -1) { // terminated return; } diff --git a/CycloBranch/parallel/cGraphReaderThread.h b/CycloBranch/parallel/cGraphReaderThread.h index fbaa489..81457e8 100644 --- a/CycloBranch/parallel/cGraphReaderThread.h +++ b/CycloBranch/parallel/cGraphReaderThread.h @@ -44,9 +44,7 @@ class cGraphReaderThread : public QThread { int scanmode; bool* terminatecomputation; - int getTheoreticalSpectraIter(bool cterminalstartingnode, cCandidateSet* candidates, int nodeid, vector& composition, double precursormass, int startmodifID, int endmodifID, int middlemodifID, int middlepos, vector& perspectivepath, double cummass, bool* terminatecomputation); - - int reverseCTerminalCandidates(int nodeid, cCandidateSet* candidates, double precursormass, int startmodifID, bool* terminatecomputation); + int getCandidatesIter(bool cterminalstartingnode, cCandidateSet* candidates, int nodeid, vector& composition, double precursormass, int startmodifID, int endmodifID, int middlemodifID, int middlepos, vector& perspectivepath, double cummass, bool* terminatecomputation); public: diff --git a/CycloBranch/parallel/cSpectrumComparatorThread.cpp b/CycloBranch/parallel/cSpectrumComparatorThread.cpp index f519934..0a9b202 100644 --- a/CycloBranch/parallel/cSpectrumComparatorThread.cpp +++ b/CycloBranch/parallel/cSpectrumComparatorThread.cpp @@ -3,7 +3,7 @@ #include "core/cTheoreticalSpectrumList.h" -bool compareBandAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b) { +bool compareBandAllIonsDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b) { if (a.getNumberOfMatchedPeaks(b_ion) > b.getNumberOfMatchedPeaks(b_ion)) { return true; } @@ -17,11 +17,11 @@ bool compareBandAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b) { } -bool compareBBwaterLossAndAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b) { - if (a.getNumberOfMatchedPeaks(b_ion) + a.getNumberOfMatchedPeaks(b_ion_water_loss) > b.getNumberOfMatchedPeaks(b_ion) + b.getNumberOfMatchedPeaks(b_ion_water_loss)) { +bool compareBBwaterLossAndAllIonsDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b) { + if (a.getNumberOfMatchedPeaks(b_ion) + a.getNumberOfMatchedPeaks(b_ion_dehydrated) > b.getNumberOfMatchedPeaks(b_ion) + b.getNumberOfMatchedPeaks(b_ion_dehydrated)) { return true; } - if (a.getNumberOfMatchedPeaks(b_ion) + a.getNumberOfMatchedPeaks(b_ion_water_loss) < b.getNumberOfMatchedPeaks(b_ion) + b.getNumberOfMatchedPeaks(b_ion_water_loss)) { + if (a.getNumberOfMatchedPeaks(b_ion) + a.getNumberOfMatchedPeaks(b_ion_dehydrated) < b.getNumberOfMatchedPeaks(b_ion) + b.getNumberOfMatchedPeaks(b_ion_dehydrated)) { return false; } if (a.getNumberOfMatchedPeaks() > b.getNumberOfMatchedPeaks()) { @@ -31,11 +31,11 @@ bool compareBBwaterLossAndAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpect } -bool compareBBammoniaLossAndAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b) { - if (a.getNumberOfMatchedPeaks(b_ion) + a.getNumberOfMatchedPeaks(b_ion_ammonia_loss) > b.getNumberOfMatchedPeaks(b_ion) + b.getNumberOfMatchedPeaks(b_ion_ammonia_loss)) { +bool compareBBammoniaLossAndAllIonsDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b) { + if (a.getNumberOfMatchedPeaks(b_ion) + a.getNumberOfMatchedPeaks(b_ion_deamidated) > b.getNumberOfMatchedPeaks(b_ion) + b.getNumberOfMatchedPeaks(b_ion_deamidated)) { return true; } - if (a.getNumberOfMatchedPeaks(b_ion) + a.getNumberOfMatchedPeaks(b_ion_ammonia_loss) < b.getNumberOfMatchedPeaks(b_ion) + b.getNumberOfMatchedPeaks(b_ion_ammonia_loss)) { + if (a.getNumberOfMatchedPeaks(b_ion) + a.getNumberOfMatchedPeaks(b_ion_deamidated) < b.getNumberOfMatchedPeaks(b_ion) + b.getNumberOfMatchedPeaks(b_ion_deamidated)) { return false; } if (a.getNumberOfMatchedPeaks() > b.getNumberOfMatchedPeaks()) { @@ -45,7 +45,7 @@ bool compareBBammoniaLossAndAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpe } -bool compareYBandAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b) { +bool compareYBandAllIonsDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b) { if (a.getNumberOfMatchedPeaksYB() > b.getNumberOfMatchedPeaksYB()) { return true; } @@ -59,7 +59,7 @@ bool compareYBandAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b) { } -bool compareYandAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b) { +bool compareYandAllIonsDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b) { if (a.getNumberOfMatchedPeaks(y_ion) > b.getNumberOfMatchedPeaks(y_ion)) { return true; } @@ -73,17 +73,17 @@ bool compareYandAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b) { } -bool compareWeightedIntensityDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b) { +bool compareWeightedIntensityDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b) { return (a.getWeightedIntensityScore() > b.getWeightedIntensityScore()); } -bool compareNumberOfMatchedPeaksDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b) { +bool compareNumberOfMatchedPeaksDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b) { return (a.getNumberOfMatchedPeaks() > b.getNumberOfMatchedPeaks()); } -bool compareNumberOfMatchedBricksDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b) { +bool compareNumberOfMatchedBricksDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b) { return (a.getNumberOfMatchedBricks() > b.getNumberOfMatchedBricks()); } @@ -161,11 +161,11 @@ void cSpectrumComparatorThread::run() { case b_ions: score = tsp.getNumberOfMatchedPeaks(b_ion); break; - case b_ions_and_b_water_loss_ions: - score = tsp.getNumberOfMatchedPeaks(b_ion) + tsp.getNumberOfMatchedPeaks(b_ion_water_loss); + case b_ions_and_b_dehydrated_ions: + score = tsp.getNumberOfMatchedPeaks(b_ion) + tsp.getNumberOfMatchedPeaks(b_ion_dehydrated); break; - case b_ions_and_b_ammonia_loss_ions: - score = tsp.getNumberOfMatchedPeaks(b_ion) + tsp.getNumberOfMatchedPeaks(b_ion_ammonia_loss); + case b_ions_and_b_deamidated_ions: + score = tsp.getNumberOfMatchedPeaks(b_ion) + tsp.getNumberOfMatchedPeaks(b_ion_deamidated); break; case y_ions_and_b_ions: score = tsp.getNumberOfMatchedPeaksYB(); diff --git a/CycloBranch/parallel/cSpectrumComparatorThread.h b/CycloBranch/parallel/cSpectrumComparatorThread.h index 5431536..c7c7a23 100644 --- a/CycloBranch/parallel/cSpectrumComparatorThread.h +++ b/CycloBranch/parallel/cSpectrumComparatorThread.h @@ -22,7 +22,7 @@ class cTheoreticalSpectrumList; \param b second theoretical spectrum \retval bool true if the score of \a a is greater than the score of \a b */ -bool compareBandAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b); +bool compareBandAllIonsDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b); /** @@ -31,7 +31,7 @@ bool compareBandAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b); \param b second theoretical spectrum \retval bool true if the score of \a a is greater than the score of \a b */ -bool compareBBwaterLossAndAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b); +bool compareBBwaterLossAndAllIonsDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b); /** @@ -40,7 +40,7 @@ bool compareBBwaterLossAndAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpect \param b second theoretical spectrum \retval bool true if the score of \a a is greater than the score of \a b */ -bool compareBBammoniaLossAndAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b); +bool compareBBammoniaLossAndAllIonsDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b); /** @@ -49,7 +49,7 @@ bool compareBBammoniaLossAndAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpe \param b second theoretical spectrum \retval bool true if the score of \a a is greater than the score of \a b */ -bool compareYBandAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b); +bool compareYBandAllIonsDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b); /** @@ -58,7 +58,7 @@ bool compareYBandAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b); \param b second theoretical spectrum \retval bool true if the score of \a a is greater than the score of \a b */ -bool compareYandAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b); +bool compareYandAllIonsDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b); /** @@ -67,7 +67,7 @@ bool compareYandAllIonsDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b); \param b second theoretical spectrum \retval bool true if the score of \a a is greater than the score of \a b */ -bool compareWeightedIntensityDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b); +bool compareWeightedIntensityDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b); /** @@ -76,7 +76,7 @@ bool compareWeightedIntensityDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& \param b second theoretical spectrum \retval bool true if the score of \a a is greater than the score of \a b */ -bool compareNumberOfMatchedPeaksDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b); +bool compareNumberOfMatchedPeaksDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b); /** @@ -85,7 +85,7 @@ bool compareNumberOfMatchedPeaksDesc(cTheoreticalSpectrum& a, cTheoreticalSpectr \param b second theoretical spectrum \retval bool true if the score of \a a is greater than the score of \a b */ -bool compareNumberOfMatchedBricksDesc(cTheoreticalSpectrum& a, cTheoreticalSpectrum& b); +bool compareNumberOfMatchedBricksDesc(const cTheoreticalSpectrum& a, const cTheoreticalSpectrum& b); /** diff --git a/CycloBranch/readme-linux-compile.txt b/CycloBranch/readme-linux-compile.txt new file mode 100644 index 0000000..d47dbc1 --- /dev/null +++ b/CycloBranch/readme-linux-compile.txt @@ -0,0 +1,12 @@ +1) Required packages: +g++ +libboost-all-dev +qt5-default +libqt5svg5* + +2) Execute the following commands in the directory where CycloBranch is unpacked: +mkdir build +mkdir moc +qmake +make + diff --git a/readme.txt b/readme.txt index 571ce70..43fa1a7 100644 --- a/readme.txt +++ b/readme.txt @@ -1,3 +1,3 @@ CycloBranch.sln - project for MS Visual Studio 2012 -- requires Qt 5.1.1 installed +- requires Qt 5.2.1 and Boost 1.57 installed